diff options
author | Imre Kaloz <kaloz@openwrt.org> | 2013-11-08 12:44:38 +0000 |
---|---|---|
committer | Imre Kaloz <kaloz@openwrt.org> | 2013-11-08 12:44:38 +0000 |
commit | 06d0fda4d1220ea54c2886df594320f19622a98c (patch) | |
tree | 70520b668371ddd7d0e5386867763fc4895a37df /target | |
parent | 1381fa6c5c4d1d3bb6d69f6d5869722af28e3e39 (diff) | |
download | mtk-20170518-06d0fda4d1220ea54c2886df594320f19622a98c.zip mtk-20170518-06d0fda4d1220ea54c2886df594320f19622a98c.tar.gz mtk-20170518-06d0fda4d1220ea54c2886df594320f19622a98c.tar.bz2 |
switch to 3.12, enable support for AM33xx/OMAP3
Signed-off-by: Imre Kaloz <kaloz@openwrt.org>
SVN-Revision: 38692
Diffstat (limited to 'target')
-rw-r--r-- | target/linux/omap/Makefile | 4 | ||||
-rw-r--r-- | target/linux/omap/base-files/etc/inittab | 1 | ||||
-rw-r--r-- | target/linux/omap/config-default | 465 | ||||
-rw-r--r-- | target/linux/omap/image/Makefile | 8 | ||||
-rw-r--r-- | target/linux/omap/image/boot.script | 4 | ||||
-rw-r--r-- | target/linux/omap/patches-3.12/001-ti_git.patch | 82370 |
6 files changed, 82731 insertions, 121 deletions
diff --git a/target/linux/omap/Makefile b/target/linux/omap/Makefile index 3a62911..78361fc 100644 --- a/target/linux/omap/Makefile +++ b/target/linux/omap/Makefile @@ -13,11 +13,11 @@ FEATURES:=usb targz audio display CPU_TYPE:=cortex-a9 CPU_SUBTYPE:=vfpv3 -LINUX_VERSION:=3.3.8 +LINUX_VERSION:=3.12 MAINTAINER:=Imre Kaloz <kaloz@openwrt.org> -KERNELNAME:="uImage" +KERNELNAME:="zImage dtbs" DEFAULT_PACKAGES += uboot-omap-am335x_evm uboot-omap-omap3_beagle uboot-omap-omap3_overo uboot-omap-omap4_panda diff --git a/target/linux/omap/base-files/etc/inittab b/target/linux/omap/base-files/etc/inittab index cc6c31a..502c6f8 100644 --- a/target/linux/omap/base-files/etc/inittab +++ b/target/linux/omap/base-files/etc/inittab @@ -1,4 +1,5 @@ ::sysinit:/etc/init.d/rcS S boot ::shutdown:/etc/init.d/rcS K shutdown +ttyO0::askfirst:/bin/ash --login ttyO2::askfirst:/bin/ash --login tty1::askfirst:/bin/ash --login diff --git a/target/linux/omap/config-default b/target/linux/omap/config-default index d51ebc4..a0cc53e 100644 --- a/target/linux/omap/config-default +++ b/target/linux/omap/config-default @@ -1,39 +1,67 @@ CONFIG_ALIGNMENT_TRAP=y +CONFIG_AM335X_CONTROL_USB=y +CONFIG_AM335X_PHY_USB=y # CONFIG_APM_EMULATION is not set CONFIG_ARCH_BINFMT_ELF_RANDOMIZE_PIE=y +CONFIG_ARCH_HAS_ATOMIC64_DEC_IF_POSITIVE=y +CONFIG_ARCH_HAS_BANDGAP=y CONFIG_ARCH_HAS_BARRIERS=y CONFIG_ARCH_HAS_CPUFREQ=y -CONFIG_ARCH_HAS_CPU_IDLE_WAIT=y CONFIG_ARCH_HAS_HOLES_MEMORYMODEL=y CONFIG_ARCH_HAS_OPP=y -CONFIG_ARCH_NR_GPIO=0 +CONFIG_ARCH_HAS_RESET_CONTROLLER=y +CONFIG_ARCH_HAS_TICK_BROADCAST=y +CONFIG_ARCH_HAVE_CUSTOM_GPIO_H=y +# CONFIG_ARCH_MULTI_CPU_AUTO is not set +CONFIG_ARCH_MULTI_V6_V7=y +CONFIG_ARCH_MULTI_V7=y +CONFIG_ARCH_NEEDS_CPU_IDLE_COUPLED=y +CONFIG_ARCH_NR_GPIO=192 CONFIG_ARCH_OMAP=y -# CONFIG_ARCH_OMAP1 is not set -# CONFIG_ARCH_OMAP2 is not set CONFIG_ARCH_OMAP2PLUS=y CONFIG_ARCH_OMAP2PLUS_TYPICAL=y -# CONFIG_ARCH_OMAP3 is not set +CONFIG_ARCH_OMAP3=y CONFIG_ARCH_OMAP4=y CONFIG_ARCH_REQUIRE_GPIOLIB=y # CONFIG_ARCH_SELECT_MEMORY_MODEL is not set # CONFIG_ARCH_SPARSEMEM_DEFAULT is not set CONFIG_ARCH_SUSPEND_POSSIBLE=y -# CONFIG_ARCH_USES_GETTIMEOFFSET is not set +CONFIG_ARCH_WANT_GENERAL_HUGETLB=y +CONFIG_ARCH_WANT_IPC_PARSE_VERSION=y CONFIG_ARM=y +# CONFIG_ARM_BIG_LITTLE_CPUFREQ is not set CONFIG_ARM_CPU_SUSPEND=y CONFIG_ARM_ERRATA_720789=y +CONFIG_ARM_ERRATA_754322=y +CONFIG_ARM_ERRATA_775420=y CONFIG_ARM_GIC=y +# CONFIG_ARM_KIRKWOOD_CPUFREQ is not set CONFIG_ARM_L1_CACHE_SHIFT=6 CONFIG_ARM_L1_CACHE_SHIFT_6=y # CONFIG_ARM_LPAE is not set CONFIG_ARM_NR_BANKS=8 +CONFIG_ARM_OMAP2PLUS_CPUFREQ=y CONFIG_ARM_PATCH_PHYS_VIRT=y CONFIG_ARM_THUMB=y # CONFIG_ARM_THUMBEE is not set -# CONFIG_ATH_COMMON is not set -# CONFIG_ATMEL_PWM is not set +CONFIG_ARM_VIRT_EXT=y +CONFIG_AT803X_PHY=y +# CONFIG_ATH_CARDS is not set +CONFIG_AUTO_ZRELADDR=y CONFIG_AVERAGE=y -CONFIG_BCMA_POSSIBLE=y +# CONFIG_BACKLIGHT_ADP8860 is not set +# CONFIG_BACKLIGHT_ADP8870 is not set +# CONFIG_BACKLIGHT_BD6107 is not set +CONFIG_BACKLIGHT_CLASS_DEVICE=y +# CONFIG_BACKLIGHT_GENERIC is not set +# CONFIG_BACKLIGHT_GPIO is not set +CONFIG_BACKLIGHT_LCD_SUPPORT=y +# CONFIG_BACKLIGHT_LV5207LP is not set +# CONFIG_BACKLIGHT_PANDORA is not set +CONFIG_BACKLIGHT_PWM=y +# CONFIG_BACKLIGHT_TPS65217 is not set +CONFIG_BCH=y +CONFIG_BCH_CONST_M=13 CONFIG_BOUNCE=y CONFIG_CACHE_L2X0=y CONFIG_CACHE_PL310=y @@ -46,6 +74,11 @@ CONFIG_CFG80211_DEFAULT_PS=y CONFIG_CFG80211_WEXT=y CONFIG_CLKDEV_LOOKUP=y CONFIG_CLKSRC_MMIO=y +CONFIG_CLKSRC_OF=y +# CONFIG_CLK_TWL6040 is not set +CONFIG_CLONE_BACKWARDS=y +CONFIG_CMDLINE="console=ttyO0,115200n8" +CONFIG_COMMON_CLK=y CONFIG_CONSOLE_TRANSLATIONS=y CONFIG_CPU_32v6K=y CONFIG_CPU_32v7=y @@ -56,110 +89,196 @@ CONFIG_CPU_CACHE_VIPT=y CONFIG_CPU_COPY_V6=y CONFIG_CPU_CP15=y CONFIG_CPU_CP15_MMU=y +CONFIG_CPU_FREQ=y +# CONFIG_CPU_FREQ_DEFAULT_GOV_CONSERVATIVE is not set +CONFIG_CPU_FREQ_DEFAULT_GOV_ONDEMAND=y +# CONFIG_CPU_FREQ_DEFAULT_GOV_PERFORMANCE is not set +# CONFIG_CPU_FREQ_DEFAULT_GOV_POWERSAVE is not set +# CONFIG_CPU_FREQ_DEFAULT_GOV_USERSPACE is not set +CONFIG_CPU_FREQ_GOV_COMMON=y +# CONFIG_CPU_FREQ_GOV_CONSERVATIVE is not set +CONFIG_CPU_FREQ_GOV_ONDEMAND=y +CONFIG_CPU_FREQ_GOV_PERFORMANCE=y +# CONFIG_CPU_FREQ_GOV_POWERSAVE is not set +# CONFIG_CPU_FREQ_GOV_USERSPACE is not set +CONFIG_CPU_FREQ_STAT=y +# CONFIG_CPU_FREQ_STAT_DETAILS is not set +CONFIG_CPU_FREQ_TABLE=y CONFIG_CPU_HAS_ASID=y -CONFIG_CPU_HAS_PMU=y # CONFIG_CPU_ICACHE_DISABLE is not set +CONFIG_CPU_IDLE=y +CONFIG_CPU_IDLE_GOV_LADDER=y +CONFIG_CPU_IDLE_GOV_MENU=y CONFIG_CPU_PABRT_V7=y +CONFIG_CPU_PM=y CONFIG_CPU_RMAP=y CONFIG_CPU_TLB_V7=y CONFIG_CPU_V7=y CONFIG_CRC16=y -CONFIG_CRYPTO_AES=m -CONFIG_CRYPTO_ALGAPI=m -CONFIG_CRYPTO_ALGAPI2=m +# CONFIG_CROSSBAR is not set CONFIG_CRYPTO_ARC4=m -# CONFIG_DEBUG_HIGHMEM is not set +CONFIG_CRYPTO_BLKCIPHER=m +CONFIG_CRYPTO_BLKCIPHER2=m +CONFIG_CRYPTO_CRC32C=y +CONFIG_CRYPTO_HASH=y +CONFIG_CRYPTO_HASH2=y +CONFIG_CRYPTO_RNG2=m +CONFIG_CRYPTO_WORKQUEUE=m +CONFIG_DCACHE_WORD_ACCESS=y +CONFIG_DDR=y +CONFIG_DEBUG_LL_INCLUDE="mach/debug-macro.S" +# CONFIG_DEBUG_UART_8250 is not set +# CONFIG_DEBUG_UART_PL01X is not set # CONFIG_DEBUG_USER is not set -CONFIG_DECOMPRESS_LZMA=y +# CONFIG_DISPLAY_DRA_EVM_ENCODER_TPD12S015 is not set +# CONFIG_DISPLAY_ENCODER_SIL9022 is not set +CONFIG_DISPLAY_PANEL_DPI=y +CONFIG_DISPLAY_PANEL_DSI_CM=y +# CONFIG_DISPLAY_PANEL_NEC_NL8048HL11 is not set +CONFIG_DISPLAY_PANEL_SHARP_LS037V7DW01=y +# CONFIG_DISPLAY_PANEL_SONY_ACX565AKM is not set +# CONFIG_DISPLAY_PANEL_TFCS9700 is not set +CONFIG_DMADEVICES=y +CONFIG_DMA_ENGINE=y +CONFIG_DMA_OF=y +CONFIG_DMA_OMAP=y +CONFIG_DMA_VIRTUAL_CHANNELS=y +CONFIG_DTC=y CONFIG_DUMMY_CONSOLE=y -# CONFIG_DW_WATCHDOG is not set +# CONFIG_DW_DMAC_CORE is not set +CONFIG_EEPROM_AT24=y CONFIG_EXT4_FS=y CONFIG_FB=y CONFIG_FB_CFB_COPYAREA=y CONFIG_FB_CFB_FILLRECT=y CONFIG_FB_CFB_IMAGEBLIT=y +CONFIG_FB_CFB_REV_PIXELS_IN_BYTE=y +CONFIG_FB_DA8XX=y +# CONFIG_FB_DA8XX_TDA998X is not set CONFIG_FB_MODE_HELPERS=y CONFIG_FB_OMAP2=y CONFIG_FB_OMAP2_DEBUG_SUPPORT=y CONFIG_FB_OMAP2_NUM_FBS=3 -# CONFIG_FB_OMAP_BOOTLOADER_INIT is not set -# CONFIG_FB_SM7XX is not set -CONFIG_FB_TILEBLITTING=y -# CONFIG_FB_WMT_GE_ROPS is not set CONFIG_FIRMWARE_EDID=y # CONFIG_FONTS is not set CONFIG_FONT_8x16=y CONFIG_FONT_8x8=y +CONFIG_FONT_SUPPORT=y +CONFIG_FORCE_MAX_ZONEORDER=12 CONFIG_FRAMEBUFFER_CONSOLE=y CONFIG_FRAMEBUFFER_CONSOLE_DETECT_PRIMARY=y # CONFIG_FRAMEBUFFER_CONSOLE_ROTATION is not set CONFIG_FRAME_POINTER=y +CONFIG_FREEZER=y CONFIG_FS_MBCACHE=y CONFIG_GENERIC_BUG=y CONFIG_GENERIC_CLOCKEVENTS=y CONFIG_GENERIC_CLOCKEVENTS_BROADCAST=y CONFIG_GENERIC_CLOCKEVENTS_BUILD=y -CONFIG_GENERIC_GPIO=y +# CONFIG_GENERIC_CPUFREQ_CPU0 is not set +CONFIG_GENERIC_IDLE_POLL_SETUP=y +CONFIG_GENERIC_IO=y CONFIG_GENERIC_IRQ_CHIP=y CONFIG_GENERIC_IRQ_SHOW=y +CONFIG_GENERIC_NET_UTILS=y CONFIG_GENERIC_PCI_IOMAP=y +CONFIG_GENERIC_PHY=y +CONFIG_GENERIC_PINCONF=y +CONFIG_GENERIC_SCHED_CLOCK=y +CONFIG_GENERIC_SMP_IDLE_THREAD=y +CONFIG_GENERIC_STRNCPY_FROM_USER=y +CONFIG_GENERIC_STRNLEN_USER=y CONFIG_GPIOLIB=y +CONFIG_GPIO_DEVRES=y +CONFIG_GPIO_TPS65910=y CONFIG_GPIO_TWL4030=y +# CONFIG_GPIO_TWL6040 is not set CONFIG_HARDIRQS_SW_RESEND=y CONFIG_HAS_DMA=y CONFIG_HAS_IOMEM=y CONFIG_HAS_IOPORT=y -CONFIG_HAVE_AOUT=y +# CONFIG_HAVE_64BIT_ALIGNED_ACCESS is not set +CONFIG_HAVE_ARCH_JUMP_LABEL=y CONFIG_HAVE_ARCH_KGDB=y CONFIG_HAVE_ARCH_PFN_VALID=y +CONFIG_HAVE_ARCH_SECCOMP_FILTER=y +CONFIG_HAVE_ARCH_TRACEHOOK=y CONFIG_HAVE_ARM_SCU=y CONFIG_HAVE_ARM_TWD=y +# CONFIG_HAVE_BOOTMEM_INFO_NODE is not set +CONFIG_HAVE_BPF_JIT=y CONFIG_HAVE_CLK=y +CONFIG_HAVE_CLK_PREPARE=y +CONFIG_HAVE_CONTEXT_TRACKING=y CONFIG_HAVE_C_RECORDMCOUNT=y +CONFIG_HAVE_DEBUG_KMEMLEAK=y CONFIG_HAVE_DMA_API_DEBUG=y +CONFIG_HAVE_DMA_ATTRS=y +CONFIG_HAVE_DMA_CONTIGUOUS=y CONFIG_HAVE_DYNAMIC_FTRACE=y CONFIG_HAVE_FTRACE_MCOUNT_RECORD=y CONFIG_HAVE_FUNCTION_GRAPH_TRACER=y CONFIG_HAVE_FUNCTION_TRACER=y CONFIG_HAVE_GENERIC_DMA_COHERENT=y -CONFIG_HAVE_GENERIC_HARDIRQS=y -CONFIG_HAVE_IRQ_WORK=y +CONFIG_HAVE_IRQ_TIME_ACCOUNTING=y CONFIG_HAVE_KERNEL_GZIP=y +CONFIG_HAVE_KERNEL_LZ4=y CONFIG_HAVE_KERNEL_LZMA=y CONFIG_HAVE_KERNEL_LZO=y CONFIG_HAVE_KERNEL_XZ=y CONFIG_HAVE_MEMBLOCK=y +CONFIG_HAVE_NET_DSA=y CONFIG_HAVE_OPROFILE=y CONFIG_HAVE_PERF_EVENTS=y CONFIG_HAVE_PROC_CPU=y CONFIG_HAVE_REGS_AND_STACK_ACCESS_API=y -CONFIG_HAVE_SCHED_CLOCK=y CONFIG_HAVE_SMP=y -CONFIG_HAVE_SPARSE_IRQ=y +CONFIG_HAVE_SYSCALL_TRACEPOINTS=y +CONFIG_HAVE_UID16=y CONFIG_HIGHMEM=y # CONFIG_HIGHPTE is not set +CONFIG_HOTPLUG_CPU=y +CONFIG_HWMON=y CONFIG_HW_CONSOLE=y -CONFIG_HZ=128 +CONFIG_HZ_FIXED=0 CONFIG_I2C=y CONFIG_I2C_BOARDINFO=y +CONFIG_I2C_CHARDEV=y +CONFIG_I2C_HELPER_AUTO=y CONFIG_I2C_OMAP=y CONFIG_INITRAMFS_SOURCE="" CONFIG_INPUT=y CONFIG_INPUT_KEYBOARD=y +CONFIG_INPUT_MATRIXKMAP=y +CONFIG_INPUT_TOUCHSCREEN=y CONFIG_INPUT_TWL4030_PWRBUTTON=y # CONFIG_INPUT_TWL4030_VIBRA is not set # CONFIG_INPUT_TWL6040_VIBRA is not set +CONFIG_IRQCHIP=y CONFIG_IRQ_DOMAIN=y -# CONFIG_IWM is not set +CONFIG_IRQ_FORCED_THREADING=y +CONFIG_IRQ_WORK=y CONFIG_JBD2=y # CONFIG_KEYBOARD_GPIO is not set -# CONFIG_KEYBOARD_OMAP4 is not set CONFIG_KEYBOARD_TWL4030=y CONFIG_KTIME_SCALAR=y -# CONFIG_LEDS is not set +# CONFIG_LCD_AMS369FG06 is not set +CONFIG_LCD_CLASS_DEVICE=y +# CONFIG_LCD_L4F00242T03 is not set +# CONFIG_LCD_LD9040 is not set +# CONFIG_LCD_LMS283GF05 is not set +# CONFIG_LCD_LTV350QV is not set +# CONFIG_LCD_PLATFORM is not set +# CONFIG_LCD_S6E63M0 is not set +# CONFIG_LCD_TDO24M is not set +# CONFIG_LCD_VGG2432A4 is not set CONFIG_LEDS_GPIO=y +# CONFIG_LEDS_PWM is not set # CONFIG_LEDS_REGULATOR is not set -CONFIG_LOCAL_TIMERS=y +CONFIG_LOGO=y +CONFIG_LOGO_LINUX_CLUT224=y +CONFIG_LOGO_LINUX_MONO=y +CONFIG_LOGO_LINUX_VGA16=y CONFIG_LZO_COMPRESS=y CONFIG_LZO_DECOMPRESS=y CONFIG_MAC80211=m @@ -174,191 +293,307 @@ CONFIG_MAC80211_RC_DEFAULT_MINSTREL=y CONFIG_MAC80211_RC_MINSTREL=y CONFIG_MAC80211_RC_MINSTREL_HT=y # CONFIG_MAC80211_RC_PID is not set -CONFIG_MACH_OMAP4_PANDA=y -# CONFIG_MACH_OMAP_4430SDP is not set -# CONFIG_MACH_OMAP_GENERIC is not set +# CONFIG_MACH_CM_T35 is not set +# CONFIG_MACH_CM_T3517 is not set +# CONFIG_MACH_CRANEBOARD is not set +# CONFIG_MACH_DEVKIT8000 is not set +# CONFIG_MACH_IGEP0020 is not set +# CONFIG_MACH_IGEP0030 is not set +# CONFIG_MACH_NOKIA_RM680 is not set +# CONFIG_MACH_NOKIA_RX51 is not set +# CONFIG_MACH_OMAP3517EVM is not set +# CONFIG_MACH_OMAP3530_LV_SOM is not set +# CONFIG_MACH_OMAP3EVM is not set +CONFIG_MACH_OMAP3_BEAGLE=y +# CONFIG_MACH_OMAP3_PANDORA is not set +# CONFIG_MACH_OMAP3_TORPEDO is not set +# CONFIG_MACH_OMAP_3430SDP is not set +# CONFIG_MACH_OMAP_3630SDP is not set +CONFIG_MACH_OMAP_GENERIC=y +# CONFIG_MACH_OMAP_LDP is not set +# CONFIG_MACH_OMAP_ZOOM2 is not set +# CONFIG_MACH_OMAP_ZOOM3 is not set +CONFIG_MACH_OVERO=y +# CONFIG_MACH_SBC3530 is not set +# CONFIG_MACH_TOUCHBOOK is not set +CONFIG_MAILBOX=y CONFIG_MDIO_BOARDINFO=y +CONFIG_MEMORY=y +CONFIG_MFD_CORE=y CONFIG_MFD_OMAP_USB_HOST=y -# CONFIG_MFD_T7L66XB is not set -# CONFIG_MFD_TWL4030_AUDIO is not set +CONFIG_MFD_TI_AM335X_TSCADC=y +CONFIG_MFD_TPS65217=y +# CONFIG_MFD_TPS65218 is not set +CONFIG_MFD_TPS65910=y +CONFIG_MFD_TWL4030_AUDIO=y +CONFIG_MIGHT_HAVE_CACHE_L2X0=y CONFIG_MMC=y CONFIG_MMC_BLOCK=y -CONFIG_MMC_OMAP=y +# CONFIG_MMC_OMAP is not set CONFIG_MMC_OMAP_HS=y CONFIG_MMC_UNSAFE_RESUME=y -# CONFIG_MPCORE_WATCHDOG is not set +CONFIG_MODULES_USE_ELF_REL=y # CONFIG_MTD_CFI_INTELEXT is not set CONFIG_MTD_CMDLINE_PARTS=y # CONFIG_MTD_COMPLEX_MAPPINGS is not set CONFIG_MTD_DATAFLASH=y # CONFIG_MTD_DATAFLASH_OTP is not set # CONFIG_MTD_DATAFLASH_WRITE_VERIFY is not set +CONFIG_MTD_NAND=y +CONFIG_MTD_NAND_BCH=y +CONFIG_MTD_NAND_ECC=y +CONFIG_MTD_NAND_ECC_BCH=y +CONFIG_MTD_NAND_OMAP2=y +CONFIG_MTD_NAND_OMAP_BCH=y CONFIG_MTD_PHYSMAP=y +# CONFIG_MTD_PHYSMAP_OF is not set +# CONFIG_MTD_SM_COMMON is not set CONFIG_MULTI_IRQ_HANDLER=y CONFIG_MUTEX_SPIN_ON_OWNER=y # CONFIG_MWIFIEX is not set CONFIG_NEED_DMA_MAP_STATE=y CONFIG_NEON=y +# CONFIG_NET_DMA is not set +CONFIG_NET_FLOW_LIMIT=y +CONFIG_NET_RX_BUSY_POLL=y # CONFIG_NET_VENDOR_I825XX is not set # CONFIG_NL80211_TESTMODE is not set CONFIG_NLS=y +CONFIG_NOP_USB_XCEIV=y CONFIG_NO_HZ=y -CONFIG_NR_CPUS=2 +CONFIG_NO_HZ_COMMON=y +CONFIG_NO_HZ_IDLE=y +CONFIG_NR_CPUS=4 +CONFIG_OF=y +CONFIG_OF_ADDRESS=y +CONFIG_OF_EARLY_FLATTREE=y +CONFIG_OF_FLATTREE=y +CONFIG_OF_GPIO=y +CONFIG_OF_IRQ=y +CONFIG_OF_MDIO=y +CONFIG_OF_MTD=y +CONFIG_OF_NET=y +CONFIG_OLD_SIGACTION=y +CONFIG_OLD_SIGSUSPEND3=y +CONFIG_OMAP2PLUS_MBOX=y CONFIG_OMAP2_DSS=y -# CONFIG_OMAP2_DSS_COLLECT_IRQ_STATS is not set -CONFIG_OMAP2_DSS_DEBUG_SUPPORT=y CONFIG_OMAP2_DSS_DPI=y +CONFIG_OMAP2_DSS_DRA7XX_DPI=y CONFIG_OMAP2_DSS_DSI=y -# CONFIG_OMAP2_DSS_FAKE_VSYNC is not set CONFIG_OMAP2_DSS_MIN_FCK_PER_PCK=0 -# CONFIG_OMAP2_DSS_RFBI is not set +CONFIG_OMAP2_DSS_SDI=y CONFIG_OMAP2_DSS_SLEEP_AFTER_VENC_RESET=y # CONFIG_OMAP2_DSS_VENC is not set -CONFIG_OMAP2_VRAM=y -CONFIG_OMAP2_VRAM_SIZE=32 +CONFIG_OMAP2_VRFB=y +# CONFIG_OMAP3_EMU is not set +# CONFIG_OMAP3_L2_AUX_SECURE_SAVE_RESTORE is not set +# CONFIG_OMAP3_SDRC_AC_TIMING is not set CONFIG_OMAP4_DSS_HDMI=y +CONFIG_OMAP4_DSS_HDMI_AUDIO=y CONFIG_OMAP4_ERRATA_I688=y +CONFIG_OMAP5_DSS_HDMI=y CONFIG_OMAP_32K_TIMER=y -CONFIG_OMAP_32K_TIMER_HZ=128 +CONFIG_OMAP_CONTROL_PHY=y CONFIG_OMAP_DM_TIMER=y -# CONFIG_OMAP_MBOX_FWK is not set -CONFIG_OMAP_MCBSP=y +CONFIG_OMAP_INTERCONNECT=y +CONFIG_OMAP_MBOX=y +CONFIG_OMAP_MBOX_KFIFO_SIZE=256 CONFIG_OMAP_MUX=y # CONFIG_OMAP_MUX_DEBUG is not set CONFIG_OMAP_MUX_WARNINGS=y -CONFIG_OMAP_PACKAGE_CBL=y -CONFIG_OMAP_PACKAGE_CBS=y +CONFIG_OMAP_OCP2SCP=y +CONFIG_OMAP_PACKAGE_CBB=y +# CONFIG_OMAP_PIPE3 is not set CONFIG_OMAP_PM_NOOP=y CONFIG_OMAP_RESET_CLOCKS=y -# CONFIG_OMAP_SMARTREFLEX is not set -# CONFIG_OMAP_WATCHDOG is not set +CONFIG_OMAP_USB2=y +CONFIG_OMAP_WATCHDOG=y CONFIG_OUTER_CACHE=y CONFIG_OUTER_CACHE_SYNC=y CONFIG_PAGEFLAGS_EXTENDED=y CONFIG_PAGE_OFFSET=0xC0000000 -CONFIG_PANEL_DVI=y -CONFIG_PANEL_GENERIC_DPI=y -# CONFIG_PANEL_LGPHILIPS_LB035Q02 is not set -# CONFIG_PANEL_PICODLP is not set -# CONFIG_PANEL_TPO_TD043MTEA1 is not set # CONFIG_PCI_SYSCALL is not set CONFIG_PERF_USE_VMALLOC=y CONFIG_PHYLIB=y +CONFIG_PINCTRL=y CONFIG_PL310_ERRATA_588369=y CONFIG_PL310_ERRATA_727915=y # CONFIG_PL310_ERRATA_753970 is not set -CONFIG_PL310_ERRATA_769419=y +# CONFIG_PL310_ERRATA_769419 is not set CONFIG_PM=y CONFIG_PM_CLK=y # CONFIG_PM_DEBUG is not set CONFIG_PM_OPP=y CONFIG_PM_RUNTIME=y +CONFIG_PM_SLEEP=y +CONFIG_PM_SLEEP_SMP=y +CONFIG_POWER_AVS=y +# CONFIG_POWER_AVS_OMAP is not set +CONFIG_PPS=y # CONFIG_PREEMPT_RCU is not set +CONFIG_PROC_DEVICETREE=y +CONFIG_PTP_1588_CLOCK=y +CONFIG_PWM=y +# CONFIG_PWM_PCA9685 is not set +CONFIG_PWM_SYSFS=y +CONFIG_PWM_TIECAP=y +CONFIG_PWM_TIEHRPWM=y +CONFIG_PWM_TIPWMSS=y +# CONFIG_PWM_TWL is not set +# CONFIG_PWM_TWL_LED is not set +CONFIG_RCU_STALL_COMMON=y CONFIG_REGMAP=y CONFIG_REGMAP_I2C=y +CONFIG_REGMAP_IRQ=y +CONFIG_REGMAP_MMIO=y +CONFIG_REGMAP_SPI=y CONFIG_REGULATOR=y -# CONFIG_REGULATOR_AD5398 is not set # CONFIG_REGULATOR_DEBUG is not set -# CONFIG_REGULATOR_DUMMY is not set +CONFIG_REGULATOR_DUMMY=y CONFIG_REGULATOR_FIXED_VOLTAGE=y -# CONFIG_REGULATOR_ISL6271A is not set -# CONFIG_REGULATOR_LP3971 is not set -# CONFIG_REGULATOR_LP3972 is not set -# CONFIG_REGULATOR_MAX1586 is not set -# CONFIG_REGULATOR_MAX8649 is not set -# CONFIG_REGULATOR_MAX8660 is not set -# CONFIG_REGULATOR_MAX8952 is not set +CONFIG_REGULATOR_GPIO=y +CONFIG_REGULATOR_TIAVSCLASS0=y CONFIG_REGULATOR_TPS65023=y CONFIG_REGULATOR_TPS6507X=y -# CONFIG_REGULATOR_TPS6524X is not set +CONFIG_REGULATOR_TPS65217=y +CONFIG_REGULATOR_TPS65910=y CONFIG_REGULATOR_TWL4030=y # CONFIG_REGULATOR_USERSPACE_CONSUMER is not set +CONFIG_RESET_CONTROLLER=y +CONFIG_RESET_TI=y # CONFIG_RFKILL_REGULATOR is not set CONFIG_RFS_ACCEL=y CONFIG_RPS=y CONFIG_RTC_CLASS=y -# CONFIG_RTC_DRV_PT7C4338 is not set +CONFIG_RTC_DRV_OMAP=y +CONFIG_RTC_DRV_TPS65910=y CONFIG_RTC_DRV_TWL4030=y -# CONFIG_RTL8192CU is not set +CONFIG_SCHED_HRTICK=y # CONFIG_SCSI_DMA is not set -# CONFIG_SERIAL_8250 is not set +# CONFIG_SENSORS_G762 is not set +# CONFIG_SENSORS_HTU21 is not set +CONFIG_SENSORS_LM75=y +CONFIG_SERIAL_8250_EXTENDED=y +CONFIG_SERIAL_8250_SHARE_IRQ=y +CONFIG_SERIAL_OF_PLATFORM=y CONFIG_SERIAL_OMAP=y CONFIG_SERIAL_OMAP_CONSOLE=y CONFIG_SMP=y CONFIG_SMP_ON_UP=y +CONFIG_SMSC911X=y +# CONFIG_SMSC911X_ARCH_HOOKS is not set +CONFIG_SND=y +CONFIG_SND_AM33XX_SOC_EVM=y +CONFIG_SND_ARM=y +CONFIG_SND_COMPRESS_OFFLOAD=y +CONFIG_SND_DAVINCI_SOC=y +CONFIG_SND_DAVINCI_SOC_MCASP=y +CONFIG_SND_DMAENGINE_PCM=y +# CONFIG_SND_EMU10K1_SEQ is not set +CONFIG_SND_JACK=y +CONFIG_SND_OMAP_SOC=y +CONFIG_SND_OMAP_SOC_DMIC=y +CONFIG_SND_OMAP_SOC_HDMI=y +CONFIG_SND_OMAP_SOC_MCBSP=y +CONFIG_SND_OMAP_SOC_MCPDM=y +CONFIG_SND_OMAP_SOC_OMAP_ABE_TWL6040=y +CONFIG_SND_OMAP_SOC_OMAP_HDMI=y +CONFIG_SND_OMAP_SOC_OMAP_TWL4030=y +# CONFIG_SND_OPL3_LIB_SEQ is not set +# CONFIG_SND_OPL4_LIB_SEQ is not set +CONFIG_SND_PCM=y +CONFIG_SND_PCM_OSS=y +# CONFIG_SND_RAWMIDI_SEQ is not set +# CONFIG_SND_SBAWE_SEQ is not set +CONFIG_SND_SOC=y +CONFIG_SND_SOC_DMIC=y +CONFIG_SND_SOC_HDMI_CODEC=y +CONFIG_SND_SOC_I2C_AND_SPI=y +CONFIG_SND_SOC_TLV320AIC3X=y +CONFIG_SND_SOC_TWL4030=y +CONFIG_SND_SOC_TWL6040=y +CONFIG_SND_TIMER=y +# CONFIG_SND_USB_HIFACE is not set +CONFIG_SOC_AM33XX=y +CONFIG_SOC_AM43XX=y +CONFIG_SOC_BUS=y +CONFIG_SOC_HAS_OMAP2_SDRC=y +# CONFIG_SOC_OMAP3430 is not set +# CONFIG_SOC_TI81XX is not set +CONFIG_SOUND=y +CONFIG_SOUND_OSS_CORE=y +CONFIG_SOUND_OSS_CORE_PRECLAIM=y +CONFIG_SPARSE_IRQ=y CONFIG_SPI=y CONFIG_SPI_MASTER=y # CONFIG_SPI_OMAP24XX is not set CONFIG_STOP_MACHINE=y +CONFIG_SUSPEND=y +CONFIG_SUSPEND_FREEZER=y CONFIG_SWP_EMULATE=y CONFIG_SYS_SUPPORTS_APM_EMULATION=y # CONFIG_THUMB2_KERNEL is not set +CONFIG_TICK_CPU_ACCOUNTING=y +# CONFIG_TIDSPBRIDGE is not set +CONFIG_TI_CPPI41=y +CONFIG_TI_CPSW=y +CONFIG_TI_CPSW_PHY_SEL=y +CONFIG_TI_CPTS=y +CONFIG_TI_DAVINCI_CPDMA=y +# CONFIG_TI_DAVINCI_EMAC is not set +CONFIG_TI_DAVINCI_MDIO=y +CONFIG_TI_EDMA=y +CONFIG_TI_EMIF=y +CONFIG_TI_PRIV_EDMA=y +# CONFIG_TOUCHSCREEN_ATMEL_MXT is not set +# CONFIG_TOUCHSCREEN_AUO_PIXCIR is not set +# CONFIG_TOUCHSCREEN_BU21013 is not set +# CONFIG_TOUCHSCREEN_CYTTSP4_CORE is not set +# CONFIG_TOUCHSCREEN_DYNAPRO is not set +# CONFIG_TOUCHSCREEN_EGALAX is not set +# CONFIG_TOUCHSCREEN_HAMPSHIRE is not set +# CONFIG_TOUCHSCREEN_MAX11801 is not set +# CONFIG_TOUCHSCREEN_PIXCIR is not set +# CONFIG_TOUCHSCREEN_ST1232 is not set +CONFIG_TOUCHSCREEN_TI_AM335X_TSC=y +# CONFIG_TOUCHSCREEN_TSC2005 is not set +# CONFIG_TOUCHSCREEN_TSC_SERIO is not set CONFIG_TREE_RCU=y CONFIG_TWL4030_CORE=y # CONFIG_TWL4030_MADC is not set CONFIG_TWL4030_POWER=y -CONFIG_TWL4030_USB=y CONFIG_TWL4030_WATCHDOG=y -# CONFIG_TWL6030_PWM is not set -CONFIG_TWL6030_USB=y -# CONFIG_TWL6040_CORE is not set +CONFIG_TWL6040_CORE=y CONFIG_UID16=y +CONFIG_UNCOMPRESS_INCLUDE="debug/uncompress.h" CONFIG_USB=y -# CONFIG_USB_ARCH_HAS_XHCI is not set -# CONFIG_USB_CDC_COMPOSITE is not set +CONFIG_USB_ANNOUNCE_NEW_DEVICES=y CONFIG_USB_COMMON=y -# CONFIG_USB_DUMMY_HCD is not set -CONFIG_USB_EHCI_HCD=y -CONFIG_USB_EHCI_HCD_OMAP=y +CONFIG_USB_EHCI_HCD=m +CONFIG_USB_EHCI_HCD_OMAP=m # CONFIG_USB_EHCI_HCD_PLATFORM is not set -CONFIG_USB_EHCI_TT_NEWSCHED=y -# CONFIG_USB_ETH is not set -# CONFIG_USB_FILE_STORAGE is not set -# CONFIG_USB_FUNCTIONFS is not set -# CONFIG_USB_FUSB300 is not set -CONFIG_USB_GADGET=y -# CONFIG_USB_GADGETFS 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_G_DBGP is not set -# CONFIG_USB_G_HID is not set -# CONFIG_USB_G_NCM is not set -# CONFIG_USB_G_PRINTER is not set -# CONFIG_USB_G_SERIAL is not set -# CONFIG_USB_M66592 is not set -# CONFIG_USB_MV_UDC is not set -# CONFIG_USB_NET2272 is not set CONFIG_USB_NET_SMSC95XX=y -# CONFIG_USB_OHCI_BIG_ENDIAN_DESC is not set -# CONFIG_USB_OHCI_BIG_ENDIAN_MMIO is not set -CONFIG_USB_OHCI_HCD=y -CONFIG_USB_OHCI_HCD_OMAP3=y -# CONFIG_USB_OHCI_HCD_PLATFORM is not set -CONFIG_USB_OMAP=y -CONFIG_USB_OTG_UTILS=y -# CONFIG_USB_R8A66597 is not set +CONFIG_USB_OTG=y +CONFIG_USB_PHY=y CONFIG_USB_SUPPORT=y CONFIG_USB_USBNET=y -# CONFIG_USB_ZERO is not set CONFIG_USE_GENERIC_SMP_HELPERS=y +CONFIG_USE_OF=y CONFIG_VECTORS_BASE=0xffff0000 CONFIG_VFP=y CONFIG_VFPv3=y +CONFIG_VIDEOMODE_HELPERS=y CONFIG_VT=y CONFIG_VT_CONSOLE=y -# CONFIG_VT_HW_CONSOLE_BINDING is not set +CONFIG_VT_CONSOLE_SLEEP=y +CONFIG_VT_HW_CONSOLE_BINDING=y # CONFIG_W35UND is not set -# CONFIG_WL1251 is not set -CONFIG_WL12XX=m -CONFIG_WL12XX_MENU=m -CONFIG_WL12XX_PLATFORM_DATA=y -CONFIG_WL12XX_SDIO=m -# CONFIG_WL12XX_SPI is not set +CONFIG_WATCHDOG_CORE=y +# CONFIG_XEN is not set CONFIG_XPS=y -CONFIG_XZ_DEC=y CONFIG_XZ_DEC_ARM=y CONFIG_XZ_DEC_BCJ=y CONFIG_ZBOOT_ROM_BSS=0 CONFIG_ZBOOT_ROM_TEXT=0 +# CONFIG_ZBUD is not set CONFIG_ZONE_DMA_FLAG=0 diff --git a/target/linux/omap/image/Makefile b/target/linux/omap/image/Makefile index e118122..afd8398 100644 --- a/target/linux/omap/image/Makefile +++ b/target/linux/omap/image/Makefile @@ -1,5 +1,5 @@ # -# Copyright (C) 2012 OpenWrt.org +# Copyright (C) 2012-2013 OpenWrt.org # # This is free software, licensed under the GNU General Public License v2. # See /LICENSE for more information. @@ -9,7 +9,11 @@ include $(INCLUDE_DIR)/image.mk define Image/BuildKernel mkimage -A arm -O linux -T script -C none -a 0 -e 0 -n 'Boot Image' -d boot.script $(BIN_DIR)/boot.scr - cp $(KDIR)/uImage $(BIN_DIR)/openwrt-$(BOARD)-uImage + cp $(KDIR)/zImage $(BIN_DIR)/openwrt-$(BOARD)-zImage + -mkdir $(BIN_DIR)/dtbs + $(CP) $(LINUX_DIR)/arch/arm/boot/dts/am335x*.dtb $(BIN_DIR)/dtbs/ + $(CP) $(LINUX_DIR)/arch/arm/boot/dts/omap3*.dtb $(BIN_DIR)/dtbs/ + $(CP) $(LINUX_DIR)/arch/arm/boot/dts/omap4*.dtb $(BIN_DIR)/dtbs/ endef define Image/Build diff --git a/target/linux/omap/image/boot.script b/target/linux/omap/image/boot.script index d884a70..ecdacfc 100644 --- a/target/linux/omap/image/boot.script +++ b/target/linux/omap/image/boot.script @@ -1,3 +1,3 @@ -fatload mmc 0:1 0x80000000 openwrt-omap-uImage +fatload mmc 0:1 0x80000000 openwrt-omap-zImage setenv bootargs vram=32M fixrtc mem=1G@0x80000000 root=/dev/mmcblk0p2 rootfstype=ext4 console=ttyO2,115200n8 rootwait -bootm 0x80000000 +bootz 0x80000000 diff --git a/target/linux/omap/patches-3.12/001-ti_git.patch b/target/linux/omap/patches-3.12/001-ti_git.patch new file mode 100644 index 0000000..9a1b6c2 --- /dev/null +++ b/target/linux/omap/patches-3.12/001-ti_git.patch @@ -0,0 +1,82370 @@ +--- a/arch/arm/boot/dts/am335x-boneblack.dts ++++ b/arch/arm/boot/dts/am335x-boneblack.dts +@@ -15,3 +15,80 @@ + regulator-max-microvolt = <1800000>; + regulator-always-on; + }; ++ ++&mmc1 { ++ vmmc-supply = <&vmmcsd_fixed>; ++}; ++ ++&mmc2 { ++ vmmc-supply = <&vmmcsd_fixed>; ++ pinctrl-names = "default"; ++ pinctrl-0 = <&emmc_pins>; ++ bus-width = <8>; ++ ti,non-removable; ++ status = "okay"; ++}; ++ ++&am33xx_pinmux { ++ nxp_hdmi_bonelt_pins: nxp_hdmi_bonelt_pins { ++ pinctrl-single,pins = < ++ 0x1b0 0x03 /* xdma_event_intr0, OMAP_MUX_MODE3 | AM33XX_PIN_OUTPUT */ ++ 0xa0 0x08 /* lcd_data0.lcd_data0, OMAP_MUX_MODE0 | AM33XX_PIN_OUTPUT | AM33XX_PULL_DISA */ ++ 0xa4 0x08 /* lcd_data1.lcd_data1, OMAP_MUX_MODE0 | AM33XX_PIN_OUTPUT | AM33XX_PULL_DISA */ ++ 0xa8 0x08 /* lcd_data2.lcd_data2, OMAP_MUX_MODE0 | AM33XX_PIN_OUTPUT | AM33XX_PULL_DISA */ ++ 0xac 0x08 /* lcd_data3.lcd_data3, OMAP_MUX_MODE0 | AM33XX_PIN_OUTPUT | AM33XX_PULL_DISA */ ++ 0xb0 0x08 /* lcd_data4.lcd_data4, OMAP_MUX_MODE0 | AM33XX_PIN_OUTPUT | AM33XX_PULL_DISA */ ++ 0xb4 0x08 /* lcd_data5.lcd_data5, OMAP_MUX_MODE0 | AM33XX_PIN_OUTPUT | AM33XX_PULL_DISA */ ++ 0xb8 0x08 /* lcd_data6.lcd_data6, OMAP_MUX_MODE0 | AM33XX_PIN_OUTPUT | AM33XX_PULL_DISA */ ++ 0xbc 0x08 /* lcd_data7.lcd_data7, OMAP_MUX_MODE0 | AM33XX_PIN_OUTPUT | AM33XX_PULL_DISA */ ++ 0xc0 0x08 /* lcd_data8.lcd_data8, OMAP_MUX_MODE0 | AM33XX_PIN_OUTPUT | AM33XX_PULL_DISA */ ++ 0xc4 0x08 /* lcd_data9.lcd_data9, OMAP_MUX_MODE0 | AM33XX_PIN_OUTPUT | AM33XX_PULL_DISA */ ++ 0xc8 0x08 /* lcd_data10.lcd_data10, OMAP_MUX_MODE0 | AM33XX_PIN_OUTPUT | AM33XX_PULL_DISA */ ++ 0xcc 0x08 /* lcd_data11.lcd_data11, OMAP_MUX_MODE0 | AM33XX_PIN_OUTPUT | AM33XX_PULL_DISA */ ++ 0xd0 0x08 /* lcd_data12.lcd_data12, OMAP_MUX_MODE0 | AM33XX_PIN_OUTPUT | AM33XX_PULL_DISA */ ++ 0xd4 0x08 /* lcd_data13.lcd_data13, OMAP_MUX_MODE0 | AM33XX_PIN_OUTPUT | AM33XX_PULL_DISA */ ++ 0xd8 0x08 /* lcd_data14.lcd_data14, OMAP_MUX_MODE0 | AM33XX_PIN_OUTPUT | AM33XX_PULL_DISA */ ++ 0xdc 0x08 /* lcd_data15.lcd_data15, OMAP_MUX_MODE0 | AM33XX_PIN_OUTPUT | AM33XX_PULL_DISA */ ++ 0xe0 0x00 /* lcd_vsync.lcd_vsync, OMAP_MUX_MODE0 | AM33XX_PIN_OUTPUT */ ++ 0xe4 0x00 /* lcd_hsync.lcd_hsync, OMAP_MUX_MODE0 | AM33XX_PIN_OUTPUT */ ++ 0xe8 0x00 /* lcd_pclk.lcd_pclk, OMAP_MUX_MODE0 | AM33XX_PIN_OUTPUT */ ++ 0xec 0x00 /* lcd_ac_bias_en.lcd_ac_bias_en, OMAP_MUX_MODE0 | AM33XX_PIN_OUTPUT */ ++ >; ++ }; ++ nxp_hdmi_bonelt_off_pins: nxp_hdmi_bonelt_off_pins { ++ pinctrl-single,pins = < ++ 0x1b0 0x03 /* xdma_event_intr0, OMAP_MUX_MODE3 | AM33XX_PIN_OUTPUT */ ++ >; ++ }; ++}; ++ ++&i2c0 { ++ hdmi1: hdmi@70 { ++ compatible = "nxp,tda998x"; ++ reg = <0x70>; ++ }; ++}; ++ ++&lcdc { ++ pinctrl-names = "default", "off"; ++ pinctrl-0 = <&nxp_hdmi_bonelt_pins>; ++ pinctrl-1 = <&nxp_hdmi_bonelt_off_pins>; ++ status = "okay"; ++ hdmi = <&hdmi1>; ++ display-timings { ++ 640x480P60 { ++ clock-frequency = <25200000>; ++ hactive = <640>; ++ vactive = <480>; ++ hfront-porch = <16>; ++ hback-porch = <48>; ++ hsync-len = <96>; ++ vback-porch = <31>; ++ vfront-porch = <11>; ++ vsync-len = <2>; ++ hsync-active = <0>; ++ vsync-active = <0>; ++ }; ++ }; ++}; ++ +--- a/arch/arm/boot/dts/am335x-bone-common.dtsi ++++ b/arch/arm/boot/dts/am335x-bone-common.dtsi +@@ -107,6 +107,27 @@ + 0x14c (PIN_INPUT_PULLDOWN | MUX_MODE7) + >; + }; ++ ++ mmc1_pins: pinmux_mmc1_pins { ++ pinctrl-single,pins = < ++ 0x160 (PIN_INPUT | MUX_MODE7) /* GPIO0_6 */ ++ >; ++ }; ++ ++ emmc_pins: pinmux_emmc_pins { ++ pinctrl-single,pins = < ++ 0x80 (PIN_INPUT_PULLUP | MUX_MODE2) /* gpmc_csn1.mmc1_clk */ ++ 0x84 (PIN_INPUT_PULLUP | MUX_MODE2) /* gpmc_csn2.mmc1_cmd */ ++ 0x00 (PIN_INPUT_PULLUP | MUX_MODE1) /* gpmc_ad0.mmc1_dat0 */ ++ 0x04 (PIN_INPUT_PULLUP | MUX_MODE1) /* gpmc_ad1.mmc1_dat1 */ ++ 0x08 (PIN_INPUT_PULLUP | MUX_MODE1) /* gpmc_ad2.mmc1_dat2 */ ++ 0x0c (PIN_INPUT_PULLUP | MUX_MODE1) /* gpmc_ad3.mmc1_dat3 */ ++ 0x10 (PIN_INPUT_PULLUP | MUX_MODE1) /* gpmc_ad4.mmc1_dat4 */ ++ 0x14 (PIN_INPUT_PULLUP | MUX_MODE1) /* gpmc_ad5.mmc1_dat5 */ ++ 0x18 (PIN_INPUT_PULLUP | MUX_MODE1) /* gpmc_ad6.mmc1_dat6 */ ++ 0x1c (PIN_INPUT_PULLUP | MUX_MODE1) /* gpmc_ad7.mmc1_dat7 */ ++ >; ++ }; + }; + + ocp { +@@ -183,15 +204,24 @@ + led@4 { + label = "beaglebone:green:usr2"; + gpios = <&gpio1 23 GPIO_ACTIVE_HIGH>; ++ linux,default-trigger = "cpu0"; + default-state = "off"; + }; + + led@5 { + label = "beaglebone:green:usr3"; + gpios = <&gpio1 24 GPIO_ACTIVE_HIGH>; ++ linux,default-trigger = "mmc1"; + default-state = "off"; + }; + }; ++ ++ vmmcsd_fixed: fixedregulator@0 { ++ compatible = "regulator-fixed"; ++ regulator-name = "vmmcsd_fixed"; ++ regulator-min-microvolt = <3300000>; ++ regulator-max-microvolt = <3300000>; ++ }; + }; + + /include/ "tps65217.dtsi" +@@ -260,3 +290,12 @@ + pinctrl-0 = <&davinci_mdio_default>; + pinctrl-1 = <&davinci_mdio_sleep>; + }; ++ ++&mmc1 { ++ status = "okay"; ++ bus-width = <0x4>; ++ pinctrl-names = "default"; ++ pinctrl-0 = <&mmc1_pins>; ++ cd-gpios = <&gpio0 6 GPIO_ACTIVE_HIGH>; ++ cd-inverted; ++}; +--- a/arch/arm/boot/dts/am335x-bone.dts ++++ b/arch/arm/boot/dts/am335x-bone.dts +@@ -9,3 +9,13 @@ + + #include "am33xx.dtsi" + #include "am335x-bone-common.dtsi" ++ ++&ldo3_reg { ++ regulator-min-microvolt = <1800000>; ++ regulator-max-microvolt = <3300000>; ++ regulator-always-on; ++}; ++ ++&mmc1 { ++ vmmc-supply = <&ldo3_reg>; ++}; +--- a/arch/arm/boot/dts/am335x-evm.dts ++++ b/arch/arm/boot/dts/am335x-evm.dts +@@ -149,6 +149,54 @@ + 0x14c (PIN_INPUT_PULLDOWN | MUX_MODE7) + >; + }; ++ ++ mmc1_pins: pinmux_mmc1_pins { ++ pinctrl-single,pins = < ++ 0x160 (PIN_INPUT | MUX_MODE7) /* spi0_cs1.gpio0_6 */ ++ >; ++ }; ++ ++ lcd_pins_s0: lcd_pins_s0 { ++ pinctrl-single,pins = < ++ 0x20 0x01 /* gpmc_ad8.lcd_data16, OUTPUT | MODE1 */ ++ 0x24 0x01 /* gpmc_ad9.lcd_data17, OUTPUT | MODE1 */ ++ 0x28 0x01 /* gpmc_ad10.lcd_data18, OUTPUT | MODE1 */ ++ 0x2c 0x01 /* gpmc_ad11.lcd_data19, OUTPUT | MODE1 */ ++ 0x30 0x01 /* gpmc_ad12.lcd_data20, OUTPUT | MODE1 */ ++ 0x34 0x01 /* gpmc_ad13.lcd_data21, OUTPUT | MODE1 */ ++ 0x38 0x01 /* gpmc_ad14.lcd_data22, OUTPUT | MODE1 */ ++ 0x3c 0x01 /* gpmc_ad15.lcd_data23, OUTPUT | MODE1 */ ++ 0xa0 0x00 /* lcd_data0.lcd_data0, OUTPUT | MODE0 */ ++ 0xa4 0x00 /* lcd_data1.lcd_data1, OUTPUT | MODE0 */ ++ 0xa8 0x00 /* lcd_data2.lcd_data2, OUTPUT | MODE0 */ ++ 0xac 0x00 /* lcd_data3.lcd_data3, OUTPUT | MODE0 */ ++ 0xb0 0x00 /* lcd_data4.lcd_data4, OUTPUT | MODE0 */ ++ 0xb4 0x00 /* lcd_data5.lcd_data5, OUTPUT | MODE0 */ ++ 0xb8 0x00 /* lcd_data6.lcd_data6, OUTPUT | MODE0 */ ++ 0xbc 0x00 /* lcd_data7.lcd_data7, OUTPUT | MODE0 */ ++ 0xc0 0x00 /* lcd_data8.lcd_data8, OUTPUT | MODE0 */ ++ 0xc4 0x00 /* lcd_data9.lcd_data9, OUTPUT | MODE0 */ ++ 0xc8 0x00 /* lcd_data10.lcd_data10, OUTPUT | MODE0 */ ++ 0xcc 0x00 /* lcd_data11.lcd_data11, OUTPUT | MODE0 */ ++ 0xd0 0x00 /* lcd_data12.lcd_data12, OUTPUT | MODE0 */ ++ 0xd4 0x00 /* lcd_data13.lcd_data13, OUTPUT | MODE0 */ ++ 0xd8 0x00 /* lcd_data14.lcd_data14, OUTPUT | MODE0 */ ++ 0xdc 0x00 /* lcd_data15.lcd_data15, OUTPUT | MODE0 */ ++ 0xe0 0x00 /* lcd_vsync.lcd_vsync, OUTPUT | MODE0 */ ++ 0xe4 0x00 /* lcd_hsync.lcd_hsync, OUTPUT | MODE0 */ ++ 0xe8 0x00 /* lcd_pclk.lcd_pclk, OUTPUT | MODE0 */ ++ 0xec 0x00 /* lcd_ac_bias_en.lcd_ac_bias_en, OUTPUT | MODE0 */ ++ >; ++ }; ++ ++ am335x_evm_audio_pins: am335x_evm_audio_pins { ++ pinctrl-single,pins = < ++ 0x10c (PIN_INPUT_PULLDOWN | MUX_MODE4) /* mii1_rx_dv.mcasp1_aclkx */ ++ 0x110 (PIN_INPUT_PULLDOWN | MUX_MODE4) /* mii1_txd3.mcasp1_fsx */ ++ 0x108 (PIN_OUTPUT_PULLDOWN | MUX_MODE4) /* mii1_col.mcasp1_axr2 */ ++ 0x144 (PIN_INPUT_PULLDOWN | MUX_MODE4) /* rmii1_ref_clk.mcasp1_axr3 */ ++ >; ++ }; + }; + + ocp { +@@ -244,6 +292,18 @@ + compatible = "ti,tmp275"; + reg = <0x48>; + }; ++ ++ tlv320aic3106: tlv320aic3106@1b { ++ compatible = "ti,tlv320aic3106"; ++ reg = <0x1b>; ++ status = "okay"; ++ ++ /* Regulators */ ++ AVDD-supply = <&vaux2_reg>; ++ IOVDD-supply = <&vaux2_reg>; ++ DRVDD-supply = <&vaux2_reg>; ++ DVDD-supply = <&vbat>; ++ }; + }; + + elm: elm@48080000 { +@@ -268,8 +328,7 @@ + nand@0,0 { + reg = <0 0 0>; /* CS0, offset 0 */ + nand-bus-width = <8>; +- ti,nand-ecc-opt = "bch8"; +- gpmc,device-nand = "true"; ++ ti,nand-ecc-opt= "bch8"; + gpmc,device-width = <1>; + gpmc,sync-clk-ps = <0>; + gpmc,cs-on-ns = <0>; +@@ -293,53 +352,78 @@ + gpmc,wait-monitoring-ns = <0>; + gpmc,wr-access-ns = <40>; + gpmc,wr-data-mux-bus-ns = <0>; +- + #address-cells = <1>; + #size-cells = <1>; +- elm_id = <&elm>; +- ++ ti,elm-id = <&elm>; + /* MTD partition table */ + partition@0 { + label = "SPL1"; + reg = <0x00000000 0x000020000>; + }; +- + partition@1 { + label = "SPL2"; + reg = <0x00020000 0x00020000>; + }; +- + partition@2 { + label = "SPL3"; + reg = <0x00040000 0x00020000>; + }; +- + partition@3 { + label = "SPL4"; + reg = <0x00060000 0x00020000>; + }; +- + partition@4 { + label = "U-boot"; + reg = <0x00080000 0x001e0000>; + }; +- + partition@5 { + label = "environment"; + reg = <0x00260000 0x00020000>; + }; +- + partition@6 { + label = "Kernel"; + reg = <0x00280000 0x00500000>; + }; +- + partition@7 { + label = "File-System"; + reg = <0x00780000 0x0F880000>; + }; + }; + }; ++ ++ lcdc: lcdc@0x4830e000 { ++ pinctrl-names = "default"; ++ pinctrl-0 = <&lcd_pins_s0>; ++ status = "okay"; ++ display-timings { ++ 800x480p62 { ++ clock-frequency = <30000000>; ++ hactive = <800>; ++ vactive = <480>; ++ hfront-porch = <39>; ++ hback-porch = <39>; ++ hsync-len = <47>; ++ vback-porch = <29>; ++ vfront-porch = <13>; ++ vsync-len = <2>; ++ hsync-active = <1>; ++ vsync-active = <1>; ++ }; ++ }; ++ }; ++ ++ sound { ++ compatible = "ti,da830-evm-audio"; ++ ti,model = "AM335x-EVM"; ++ ti,audio-codec = <&tlv320aic3106>; ++ ti,mcasp-controller = <&mcasp1>; ++ ti,codec-clock-rate = <12000000>; ++ ti,audio-routing = ++ "Headphone Jack", "HPLOUT", ++ "Headphone Jack", "HPROUT", ++ "LINE1L", "Line In", ++ "LINE1R", "Line In"; ++ }; + }; + + vbat: fixedregulator@0 { +@@ -403,10 +487,63 @@ + brightness-levels = <0 51 53 56 62 75 101 152 255>; + default-brightness-level = <8>; + }; ++ ++ panel { ++ compatible = "ti,tilcdc,panel"; ++ status = "okay"; ++ pinctrl-names = "default"; ++ pinctrl-0 = <&lcd_pins_s0>; ++ panel-info { ++ ac-bias = <255>; ++ ac-bias-intrpt = <0>; ++ dma-burst-sz = <16>; ++ bpp = <32>; ++ fdd = <0x80>; ++ sync-edge = <0>; ++ sync-ctrl = <1>; ++ raster-order = <0>; ++ fifo-th = <0>; ++ }; ++ ++ display-timings { ++ 800x480p62 { ++ clock-frequency = <30000000>; ++ hactive = <800>; ++ vactive = <480>; ++ hfront-porch = <39>; ++ hback-porch = <39>; ++ hsync-len = <47>; ++ vback-porch = <29>; ++ vfront-porch = <13>; ++ vsync-len = <2>; ++ hsync-active = <1>; ++ vsync-active = <1>; ++ }; ++ }; ++ }; + }; + + #include "tps65910.dtsi" + ++&mcasp1 { ++ pinctrl-names = "default"; ++ pinctrl-0 = <&am335x_evm_audio_pins>; ++ ++ status = "okay"; ++ ++ op-mode = <0>; /* MCASP_IIS_MODE */ ++ tdm-slots = <2>; ++ /* 16 serializer */ ++ serial-dir = < /* 0: INACTIVE, 1: TX, 2: RX */ ++ 0 0 1 2 ++ 0 0 0 0 ++ 0 0 0 0 ++ 0 0 0 0 ++ >; ++ tx-num-evt = <1>; ++ rx-num-evt = <1>; ++}; ++ + &tps { + vcc1-supply = <&vbat>; + vcc2-supply = <&vbat>; +@@ -477,6 +614,8 @@ + }; + + vmmc_reg: regulator@12 { ++ regulator-min-microvolt = <1800000>; ++ regulator-max-microvolt = <3300000>; + regulator-always-on; + }; + }; +@@ -509,7 +648,7 @@ + tsc { + ti,wires = <4>; + ti,x-plate-resistance = <200>; +- ti,coordiante-readouts = <5>; ++ ti,coordinate-readouts = <5>; + ti,wire-config = <0x00 0x11 0x22 0x33>; + }; + +@@ -517,3 +656,12 @@ + ti,adc-channels = <4 5 6 7>; + }; + }; ++ ++&mmc1 { ++ status = "okay"; ++ vmmc-supply = <&vmmc_reg>; ++ bus-width = <4>; ++ pinctrl-names = "default"; ++ pinctrl-0 = <&mmc1_pins>; ++ cd-gpios = <&gpio0 6 GPIO_ACTIVE_HIGH>; ++}; +--- /dev/null ++++ b/arch/arm/boot/dts/am335x-evm-profile2.dts +@@ -0,0 +1,296 @@ ++/* ++ * Copyright (C) 2012 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 version 2 as ++ * published by the Free Software Foundation. ++ */ ++/dts-v1/; ++ ++#include "am33xx.dtsi" ++ ++/ { ++ model = "TI AM335x EVM"; ++ compatible = "ti,am335x-evm", "ti,am33xx"; ++ ++ cpus { ++ cpu@0 { ++ cpu0-supply = <&vdd1_reg>; ++ }; ++ }; ++ ++ memory { ++ device_type = "memory"; ++ reg = <0x80000000 0x10000000>; /* 256 MB */ ++ }; ++ ++ am33xx_pinmux: pinmux@44e10800 { ++ pinctrl-names = "default"; ++ pinctrl-0 = <&matrix_keypad_s0 &clkout2_pin>; ++ ++ matrix_keypad_s0: matrix_keypad_s0 { ++ pinctrl-single,pins = < ++ 0x54 (PIN_OUTPUT_PULLDOWN | MUX_MODE7) /* gpmc_a5.gpio1_21 */ ++ 0x58 (PIN_OUTPUT_PULLDOWN | MUX_MODE7) /* gpmc_a6.gpio1_22 */ ++ 0x64 (PIN_INPUT_PULLDOWN | MUX_MODE7) /* gpmc_a9.gpio1_25 */ ++ 0x68 (PIN_INPUT_PULLDOWN | MUX_MODE7) /* gpmc_a10.gpio1_26 */ ++ 0x6c (PIN_INPUT_PULLDOWN | MUX_MODE7) /* gpmc_a11.gpio1_27 */ ++ >; ++ }; ++ ++ i2c0_pins: pinmux_i2c0_pins { ++ pinctrl-single,pins = < ++ 0x188 (PIN_INPUT_PULLUP | MUX_MODE0) /* i2c0_sda.i2c0_sda */ ++ 0x18c (PIN_INPUT_PULLUP | MUX_MODE0) /* i2c0_scl.i2c0_scl */ ++ >; ++ }; ++ ++ spi0_pins: pinmux_spi0_pins { ++ pinctrl-single,pins = < ++ 0x150 (PIN_INPUT_PULLUP | MUX_MODE0) /* spi0_clk.spi0_clk */ ++ 0x154 (PIN_INPUT_PULLUP | MUX_MODE0) /* spi0_d0.spi0_d0 */ ++ 0x158 (PIN_INPUT_PULLUP | MUX_MODE0) /* spi0_d1.spi0_d1 */ ++ 0x15c (PIN_INPUT_PULLUP | MUX_MODE0) /* spi0_cs0.spi0_cs0 */ ++ >; ++ }; ++ ++ uart0_pins: pinmux_uart0_pins { ++ pinctrl-single,pins = < ++ 0x170 (PIN_INPUT_PULLUP | MUX_MODE0) /* uart0_rxd.uart0_rxd */ ++ 0x174 (PIN_OUTPUT_PULLDOWN | MUX_MODE0) /* uart0_txd.uart0_txd */ ++ >; ++ }; ++ ++ clkout2_pin: pinmux_clkout2_pin { ++ pinctrl-single,pins = < ++ 0x1b4 (PIN_OUTPUT_PULLDOWN | MUX_MODE3) /* xdma_event_intr1.clkout2 */ ++ >; ++ }; ++ ++ cpsw_default: cpsw_default { ++ pinctrl-single,pins = < ++ /* Slave 1 */ ++ 0x114 (PIN_OUTPUT_PULLDOWN | MUX_MODE2) /* mii1_txen.rgmii1_tctl */ ++ 0x118 (PIN_INPUT_PULLDOWN | MUX_MODE2) /* mii1_rxdv.rgmii1_rctl */ ++ 0x11c (PIN_OUTPUT_PULLDOWN | MUX_MODE2) /* mii1_txd3.rgmii1_td3 */ ++ 0x120 (PIN_OUTPUT_PULLDOWN | MUX_MODE2) /* mii1_txd2.rgmii1_td2 */ ++ 0x124 (PIN_OUTPUT_PULLDOWN | MUX_MODE2) /* mii1_txd1.rgmii1_td1 */ ++ 0x128 (PIN_OUTPUT_PULLDOWN | MUX_MODE2) /* mii1_txd0.rgmii1_td0 */ ++ 0x12c (PIN_OUTPUT_PULLDOWN | MUX_MODE2) /* mii1_txclk.rgmii1_tclk */ ++ 0x130 (PIN_INPUT_PULLDOWN | MUX_MODE2) /* mii1_rxclk.rgmii1_rclk */ ++ 0x134 (PIN_INPUT_PULLDOWN | MUX_MODE2) /* mii1_rxd3.rgmii1_rd3 */ ++ 0x138 (PIN_INPUT_PULLDOWN | MUX_MODE2) /* mii1_rxd2.rgmii1_rd2 */ ++ 0x13c (PIN_INPUT_PULLDOWN | MUX_MODE2) /* mii1_rxd1.rgmii1_rd1 */ ++ 0x140 (PIN_INPUT_PULLDOWN | MUX_MODE2) /* mii1_rxd0.rgmii1_rd0 */ ++ >; ++ }; ++ ++ cpsw_sleep: cpsw_sleep { ++ pinctrl-single,pins = < ++ /* Slave 1 reset value */ ++ 0x114 (PIN_INPUT_PULLDOWN | MUX_MODE7) ++ 0x118 (PIN_INPUT_PULLDOWN | MUX_MODE7) ++ 0x11c (PIN_INPUT_PULLDOWN | MUX_MODE7) ++ 0x120 (PIN_INPUT_PULLDOWN | MUX_MODE7) ++ 0x124 (PIN_INPUT_PULLDOWN | MUX_MODE7) ++ 0x128 (PIN_INPUT_PULLDOWN | MUX_MODE7) ++ 0x12c (PIN_INPUT_PULLDOWN | MUX_MODE7) ++ 0x130 (PIN_INPUT_PULLDOWN | MUX_MODE7) ++ 0x134 (PIN_INPUT_PULLDOWN | MUX_MODE7) ++ 0x138 (PIN_INPUT_PULLDOWN | MUX_MODE7) ++ 0x13c (PIN_INPUT_PULLDOWN | MUX_MODE7) ++ 0x140 (PIN_INPUT_PULLDOWN | MUX_MODE7) ++ >; ++ }; ++ ++ davinci_mdio_default: davinci_mdio_default { ++ pinctrl-single,pins = < ++ /* MDIO */ ++ 0x148 (PIN_INPUT_PULLUP | SLEWCTRL_FAST | MUX_MODE0) /* mdio_data.mdio_data */ ++ 0x14c (PIN_OUTPUT_PULLUP | MUX_MODE0) /* mdio_clk.mdio_clk */ ++ >; ++ }; ++ ++ davinci_mdio_sleep: davinci_mdio_sleep { ++ pinctrl-single,pins = < ++ /* MDIO reset value */ ++ 0x148 (PIN_INPUT_PULLDOWN | MUX_MODE7) ++ 0x14c (PIN_INPUT_PULLDOWN | MUX_MODE7) ++ >; ++ }; ++ }; ++ ++ ocp { ++ uart0: serial@44e09000 { ++ pinctrl-names = "default"; ++ pinctrl-0 = <&uart0_pins>; ++ ++ status = "okay"; ++ }; ++ ++ i2c0: i2c@44e0b000 { ++ pinctrl-names = "default"; ++ pinctrl-0 = <&i2c0_pins>; ++ ++ status = "okay"; ++ clock-frequency = <400000>; ++ ++ tps: tps@2d { ++ reg = <0x2d>; ++ }; ++ }; ++ ++ spi0: spi@48030000 { ++ pinctrl-names = "default"; ++ pinctrl-0 = <&spi0_pins>; ++ ++ status = "okay"; ++ m25p80@0 { ++ compatible = "w25q64"; ++ spi-max-frequency = <24000000>; ++ reg = <0x0>; ++ }; ++ }; ++ }; ++ ++ vbat: fixedregulator@0 { ++ compatible = "regulator-fixed"; ++ regulator-name = "vbat"; ++ regulator-min-microvolt = <5000000>; ++ regulator-max-microvolt = <5000000>; ++ regulator-boot-on; ++ }; ++ ++ lis3_reg: fixedregulator@1 { ++ compatible = "regulator-fixed"; ++ regulator-name = "lis3_reg"; ++ regulator-boot-on; ++ }; ++ ++ matrix_keypad: matrix_keypad@0 { ++ compatible = "gpio-matrix-keypad"; ++ debounce-delay-ms = <5>; ++ col-scan-delay-us = <2>; ++ ++ row-gpios = <&gpio1 25 GPIO_ACTIVE_HIGH /* Bank1, pin25 */ ++ &gpio1 26 GPIO_ACTIVE_HIGH /* Bank1, pin26 */ ++ &gpio1 27 GPIO_ACTIVE_HIGH>; /* Bank1, pin27 */ ++ ++ col-gpios = <&gpio1 21 GPIO_ACTIVE_HIGH /* Bank1, pin21 */ ++ &gpio1 22 GPIO_ACTIVE_HIGH>; /* Bank1, pin22 */ ++ ++ linux,keymap = <0x0000008b /* MENU */ ++ 0x0100009e /* BACK */ ++ 0x02000069 /* LEFT */ ++ 0x0001006a /* RIGHT */ ++ 0x0101001c /* ENTER */ ++ 0x0201006c>; /* DOWN */ ++ }; ++}; ++ ++#include "tps65910.dtsi" ++ ++&tps { ++ vcc1-supply = <&vbat>; ++ vcc2-supply = <&vbat>; ++ vcc3-supply = <&vbat>; ++ vcc4-supply = <&vbat>; ++ vcc5-supply = <&vbat>; ++ vcc6-supply = <&vbat>; ++ vcc7-supply = <&vbat>; ++ vccio-supply = <&vbat>; ++ ++ regulators { ++ vrtc_reg: regulator@0 { ++ regulator-always-on; ++ }; ++ ++ vio_reg: regulator@1 { ++ regulator-always-on; ++ }; ++ ++ vdd1_reg: regulator@2 { ++ /* VDD_MPU voltage limits 0.95V - 1.26V with +/-4% tolerance */ ++ regulator-name = "vdd_mpu"; ++ regulator-min-microvolt = <912500>; ++ regulator-max-microvolt = <1312500>; ++ regulator-boot-on; ++ regulator-always-on; ++ }; ++ ++ vdd2_reg: regulator@3 { ++ /* VDD_CORE voltage limits 0.95V - 1.1V with +/-4% tolerance */ ++ regulator-name = "vdd_core"; ++ regulator-min-microvolt = <912500>; ++ regulator-max-microvolt = <1150000>; ++ regulator-boot-on; ++ regulator-always-on; ++ }; ++ ++ vdd3_reg: regulator@4 { ++ regulator-always-on; ++ }; ++ ++ vdig1_reg: regulator@5 { ++ regulator-always-on; ++ }; ++ ++ vdig2_reg: regulator@6 { ++ regulator-always-on; ++ }; ++ ++ vpll_reg: regulator@7 { ++ regulator-always-on; ++ }; ++ ++ vdac_reg: regulator@8 { ++ regulator-always-on; ++ }; ++ ++ vaux1_reg: regulator@9 { ++ regulator-always-on; ++ }; ++ ++ vaux2_reg: regulator@10 { ++ regulator-always-on; ++ }; ++ ++ vaux33_reg: regulator@11 { ++ regulator-always-on; ++ }; ++ ++ vmmc_reg: regulator@12 { ++ regulator-min-microvolt = <1800000>; ++ regulator-max-microvolt = <3300000>; ++ regulator-always-on; ++ }; ++ }; ++}; ++ ++&mac { ++ pinctrl-names = "default", "sleep"; ++ pinctrl-0 = <&cpsw_default>; ++ pinctrl-1 = <&cpsw_sleep>; ++}; ++ ++&davinci_mdio { ++ pinctrl-names = "default", "sleep"; ++ pinctrl-0 = <&davinci_mdio_default>; ++ pinctrl-1 = <&davinci_mdio_sleep>; ++}; ++ ++&cpsw_emac0 { ++ phy_id = <&davinci_mdio>, <0>; ++ phy-mode = "rgmii-txid"; ++}; ++ ++&cpsw_emac1 { ++ phy_id = <&davinci_mdio>, <1>; ++ phy-mode = "rgmii-txid"; ++}; ++ ++&mmc1 { ++ status = "okay"; ++ vmmc-supply = <&vmmc_reg>; ++ bus-width = <4>; ++}; +--- a/arch/arm/boot/dts/am335x-evmsk.dts ++++ b/arch/arm/boot/dts/am335x-evmsk.dts +@@ -35,6 +35,39 @@ + pinctrl-names = "default"; + pinctrl-0 = <&gpio_keys_s0 &clkout2_pin>; + ++ lcd_pins_s0: lcd_pins_s0 { ++ pinctrl-single,pins = < ++ 0x20 0x01 /* gpmc_ad8.lcd_data16, OUTPUT | MODE1 */ ++ 0x24 0x01 /* gpmc_ad9.lcd_data17, OUTPUT | MODE1 */ ++ 0x28 0x01 /* gpmc_ad10.lcd_data18, OUTPUT | MODE1 */ ++ 0x2c 0x01 /* gpmc_ad11.lcd_data19, OUTPUT | MODE1 */ ++ 0x30 0x01 /* gpmc_ad12.lcd_data20, OUTPUT | MODE1 */ ++ 0x34 0x01 /* gpmc_ad13.lcd_data21, OUTPUT | MODE1 */ ++ 0x38 0x01 /* gpmc_ad14.lcd_data22, OUTPUT | MODE1 */ ++ 0x3c 0x01 /* gpmc_ad15.lcd_data23, OUTPUT | MODE1 */ ++ 0xa0 0x00 /* lcd_data0.lcd_data0, OUTPUT | MODE0 */ ++ 0xa4 0x00 /* lcd_data1.lcd_data1, OUTPUT | MODE0 */ ++ 0xa8 0x00 /* lcd_data2.lcd_data2, OUTPUT | MODE0 */ ++ 0xac 0x00 /* lcd_data3.lcd_data3, OUTPUT | MODE0 */ ++ 0xb0 0x00 /* lcd_data4.lcd_data4, OUTPUT | MODE0 */ ++ 0xb4 0x00 /* lcd_data5.lcd_data5, OUTPUT | MODE0 */ ++ 0xb8 0x00 /* lcd_data6.lcd_data6, OUTPUT | MODE0 */ ++ 0xbc 0x00 /* lcd_data7.lcd_data7, OUTPUT | MODE0 */ ++ 0xc0 0x00 /* lcd_data8.lcd_data8, OUTPUT | MODE0 */ ++ 0xc4 0x00 /* lcd_data9.lcd_data9, OUTPUT | MODE0 */ ++ 0xc8 0x00 /* lcd_data10.lcd_data10, OUTPUT | MODE0 */ ++ 0xcc 0x00 /* lcd_data11.lcd_data11, OUTPUT | MODE0 */ ++ 0xd0 0x00 /* lcd_data12.lcd_data12, OUTPUT | MODE0 */ ++ 0xd4 0x00 /* lcd_data13.lcd_data13, OUTPUT | MODE0 */ ++ 0xd8 0x00 /* lcd_data14.lcd_data14, OUTPUT | MODE0 */ ++ 0xdc 0x00 /* lcd_data15.lcd_data15, OUTPUT | MODE0 */ ++ 0xe0 0x00 /* lcd_vsync.lcd_vsync, OUTPUT | MODE0 */ ++ 0xe4 0x00 /* lcd_hsync.lcd_hsync, OUTPUT | MODE0 */ ++ 0xe8 0x00 /* lcd_pclk.lcd_pclk, OUTPUT | MODE0 */ ++ 0xec 0x00 /* lcd_ac_bias_en.lcd_ac_bias_en, OUTPUT | MODE0 */ ++ >; ++ }; ++ + user_leds_s0: user_leds_s0 { + pinctrl-single,pins = < + 0x10 (PIN_OUTPUT_PULLDOWN | MUX_MODE7) /* gpmc_ad4.gpio1_4 */ +@@ -158,6 +191,21 @@ + 0x14c (PIN_INPUT_PULLDOWN | MUX_MODE7) + >; + }; ++ ++ mmc1_pins: pinmux_mmc1_pins { ++ pinctrl-single,pins = < ++ 0x160 (PIN_INPUT | MUX_MODE7) /* spi0_cs1.gpio0_6 */ ++ >; ++ }; ++ ++ mcasp1_pins: mcasp1_pins { ++ pinctrl-single,pins = < ++ 0x10c (PIN_INPUT_PULLDOWN | MUX_MODE4) /* mii1_crs.mcasp1_aclkx */ ++ 0x110 (PIN_INPUT_PULLDOWN | MUX_MODE4) /* mii1_rxerr.mcasp1_fsx */ ++ 0x108 (PIN_OUTPUT_PULLDOWN | MUX_MODE4) /* mii1_col.mcasp1_axr2 */ ++ 0x144 (PIN_INPUT_PULLDOWN | MUX_MODE4) /* rmii1_ref_clk.mcasp1_axr3 */ ++ >; ++ }; + }; + + ocp { +@@ -206,6 +254,18 @@ + st,max-limit-y = <550>; + st,max-limit-z = <750>; + }; ++ ++ tlv320aic3106: tlv320aic3106@1b { ++ compatible = "ti,tlv320aic3106"; ++ reg = <0x1b>; ++ status = "okay"; ++ ++ /* Regulators */ ++ AVDD-supply = <&vaux2_reg>; ++ IOVDD-supply = <&vaux2_reg>; ++ DRVDD-supply = <&vaux2_reg>; ++ DVDD-supply = <&vbat>; ++ }; + }; + + musb: usb@47400000 { +@@ -219,9 +279,22 @@ + status = "okay"; + }; + ++ usb-phy@47401b00 { ++ status = "okay"; ++ }; ++ + usb@47401000 { + status = "okay"; + }; ++ ++ usb@47401800 { ++ status = "okay"; ++ dr_mode = "host"; ++ }; ++ ++ dma-controller@07402000 { ++ status = "okay"; ++ }; + }; + + epwmss2: epwmss@48304000 { +@@ -233,6 +306,38 @@ + pinctrl-0 = <&ecap2_pins>; + }; + }; ++ ++ lcdc: lcdc@0x4830e000 { ++ pinctrl-names = "default"; ++ pinctrl-0 = <&lcd_pins_s0>; ++ status = "okay"; ++ display-timings { ++ 480x272 { ++ hactive = <480>; ++ vactive = <272>; ++ hback-porch = <43>; ++ hfront-porch = <8>; ++ hsync-len = <4>; ++ vback-porch = <12>; ++ vfront-porch = <4>; ++ vsync-len = <10>; ++ clock-frequency = <9000000>; ++ hsync-active = <0>; ++ vsync-active = <0>; ++ }; ++ }; ++ }; ++ ++ sound { ++ compatible = "ti,da830-evm-audio"; ++ ti,model = "AM335x-EVMSK"; ++ ti,audio-codec = <&tlv320aic3106>; ++ ti,mcasp-controller = <&mcasp1>; ++ ti,codec-clock-rate = <24576000>; ++ ti,audio-routing = ++ "Headphone Jack", "HPLOUT", ++ "Headphone Jack", "HPROUT"; ++ }; + }; + + vbat: fixedregulator@0 { +@@ -393,6 +498,8 @@ + }; + + vmmc_reg: regulator@12 { ++ regulator-min-microvolt = <1800000>; ++ regulator-max-microvolt = <3300000>; + regulator-always-on; + }; + }; +@@ -419,3 +526,45 @@ + phy_id = <&davinci_mdio>, <1>; + phy-mode = "rgmii-txid"; + }; ++ ++&tscadc { ++ status = "okay"; ++ tsc { ++ ti,wires = <4>; ++ ti,x-plate-resistance = <200>; ++ ti,coordinate-readouts = <5>; ++ ti,wire-config = <0x00 0x11 0x22 0x33>; ++ }; ++}; ++ ++&gpio0 { ++ ti,no-reset; ++}; ++ ++&mmc1 { ++ status = "okay"; ++ vmmc-supply = <&vmmc_reg>; ++ bus-width = <4>; ++ pinctrl-names = "default"; ++ pinctrl-0 = <&mmc1_pins>; ++ cd-gpios = <&gpio0 6 GPIO_ACTIVE_HIGH>; ++}; ++ ++&mcasp1 { ++ pinctrl-names = "default"; ++ pinctrl-0 = <&mcasp1_pins>; ++ ++ status = "okay"; ++ ++ op-mode = <0>; /* MCASP_IIS_MODE */ ++ tdm-slots = <2>; ++ /* 16 serializer */ ++ serial-dir = < /* 0: INACTIVE, 1: TX, 2: RX */ ++ 0 0 1 2 ++ 0 0 0 0 ++ 0 0 0 0 ++ 0 0 0 0 ++ >; ++ tx-num-evt = <1>; ++ rx-num-evt = <1>; ++}; +--- /dev/null ++++ b/arch/arm/boot/dts/am33xx-clocks.dtsi +@@ -0,0 +1,661 @@ ++/* ++ * Device Tree Source for AM33xx clock data ++ * ++ * Copyright (C) 2013 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. ++ */ ++ ++clk_32768_ck: clk_32768_ck { ++ #clock-cells = <0>; ++ compatible = "fixed-clock"; ++ clock-frequency = <32768>; ++}; ++ ++clk_rc32k_ck: clk_rc32k_ck { ++ #clock-cells = <0>; ++ compatible = "fixed-clock"; ++ clock-frequency = <32000>; ++}; ++ ++virt_19200000_ck: virt_19200000_ck { ++ #clock-cells = <0>; ++ compatible = "fixed-clock"; ++ clock-frequency = <19200000>; ++}; ++ ++virt_24000000_ck: virt_24000000_ck { ++ #clock-cells = <0>; ++ compatible = "fixed-clock"; ++ clock-frequency = <24000000>; ++}; ++ ++virt_25000000_ck: virt_25000000_ck { ++ #clock-cells = <0>; ++ compatible = "fixed-clock"; ++ clock-frequency = <25000000>; ++}; ++ ++virt_26000000_ck: virt_26000000_ck { ++ #clock-cells = <0>; ++ compatible = "fixed-clock"; ++ clock-frequency = <26000000>; ++}; ++ ++sys_clkin_ck: sys_clkin_ck@44e10040 { ++ #clock-cells = <0>; ++ compatible = "mux-clock"; ++ clocks = <&virt_19200000_ck>, <&virt_24000000_ck>, <&virt_25000000_ck>, <&virt_26000000_ck>; ++ bit-shift = <22>; ++ reg = <0x44e10040 0x4>; ++ bit-mask = <0x3>; ++}; ++ ++tclkin_ck: tclkin_ck { ++ #clock-cells = <0>; ++ compatible = "fixed-clock"; ++ clock-frequency = <12000000>; ++}; ++ ++dpll_core_ck: dpll_core_ck@44e00490 { ++ #clock-cells = <0>; ++ compatible = "ti,omap4-dpll-core-clock"; ++ clocks = <&sys_clkin_ck>, <&sys_clkin_ck>; ++ reg = <0x44e00490 0x4>, <0x44e0045c 0x4>, <0x44e00468 0x4>; ++ reg-names = "control", "idlest", "mult-div1"; ++}; ++ ++dpll_core_x2_ck: dpll_core_x2_ck { ++ #clock-cells = <0>; ++ compatible = "ti,omap4-dpll-x2-clock"; ++ clocks = <&dpll_core_ck>; ++}; ++ ++dpll_core_m4_ck: dpll_core_m4_ck@44e00480 { ++ #clock-cells = <0>; ++ compatible = "divider-clock"; ++ clocks = <&dpll_core_x2_ck>; ++ reg = <0x44e00480 0x4>; ++ bit-mask = <0x1f>; ++ index-starts-at-one; ++}; ++ ++dpll_core_m5_ck: dpll_core_m5_ck@44e00484 { ++ #clock-cells = <0>; ++ compatible = "divider-clock"; ++ clocks = <&dpll_core_x2_ck>; ++ reg = <0x44e00484 0x4>; ++ bit-mask = <0x1f>; ++ index-starts-at-one; ++}; ++ ++dpll_core_m6_ck: dpll_core_m6_ck@44e004d8 { ++ #clock-cells = <0>; ++ compatible = "divider-clock"; ++ clocks = <&dpll_core_x2_ck>; ++ reg = <0x44e004d8 0x4>; ++ bit-mask = <0x1f>; ++ index-starts-at-one; ++}; ++ ++dpll_mpu_ck: dpll_mpu_ck@44e00488 { ++ #clock-cells = <0>; ++ compatible = "ti,omap4-dpll-clock"; ++ clocks = <&sys_clkin_ck>, <&sys_clkin_ck>; ++ reg = <0x44e00488 0x4>, <0x44e00420 0x4>, <0x44e0042c 0x4>; ++ reg-names = "control", "idlest", "mult-div1"; ++}; ++ ++dpll_mpu_m2_ck: dpll_mpu_m2_ck@44e004a8 { ++ #clock-cells = <0>; ++ compatible = "divider-clock"; ++ clocks = <&dpll_mpu_ck>; ++ reg = <0x44e004a8 0x4>; ++ bit-mask = <0x1f>; ++ index-starts-at-one; ++}; ++ ++dpll_ddr_ck: dpll_ddr_ck@44e00494 { ++ #clock-cells = <0>; ++ compatible = "ti,omap4-dpll-no-gate-clock"; ++ clocks = <&sys_clkin_ck>, <&sys_clkin_ck>; ++ reg = <0x44e00494 0x4>, <0x44e00434 0x4>, <0x44e00440 0x4>; ++ reg-names = "control", "idlest", "mult-div1"; ++}; ++ ++dpll_ddr_m2_ck: dpll_ddr_m2_ck@44e004a0 { ++ #clock-cells = <0>; ++ compatible = "divider-clock"; ++ clocks = <&dpll_ddr_ck>; ++ reg = <0x44e004a0 0x4>; ++ bit-mask = <0x1f>; ++ index-starts-at-one; ++}; ++ ++dpll_ddr_m2_div2_ck: dpll_ddr_m2_div2_ck { ++ #clock-cells = <0>; ++ compatible = "fixed-factor-clock"; ++ clocks = <&dpll_ddr_m2_ck>; ++ clock-mult = <1>; ++ clock-div = <2>; ++}; ++ ++dpll_disp_ck: dpll_disp_ck@44e00498 { ++ #clock-cells = <0>; ++ compatible = "ti,omap4-dpll-no-gate-clock"; ++ clocks = <&sys_clkin_ck>, <&sys_clkin_ck>; ++ reg = <0x44e00498 0x4>, <0x44e00448 0x4>, <0x44e00454 0x4>; ++ reg-names = "control", "idlest", "mult-div1"; ++}; ++ ++dpll_disp_m2_ck: dpll_disp_m2_ck@44e004a4 { ++ #clock-cells = <0>; ++ compatible = "divider-clock"; ++ clocks = <&dpll_disp_ck>; ++ reg = <0x44e004a4 0x4>; ++ bit-mask = <0x1f>; ++ index-starts-at-one; ++ set-rate-parent; ++}; ++ ++dpll_per_ck: dpll_per_ck@44e0048c { ++ #clock-cells = <0>; ++ compatible = "ti,omap4-dpll-no-gate-j-type-clock"; ++ clocks = <&sys_clkin_ck>, <&sys_clkin_ck>; ++ reg = <0x44e0048c 0x4>, <0x44e00470 0x4>, <0x44e0049c 0x4>; ++ reg-names = "control", "idlest", "mult-div1"; ++}; ++ ++dpll_per_m2_ck: dpll_per_m2_ck@44e004ac { ++ #clock-cells = <0>; ++ compatible = "divider-clock"; ++ clocks = <&dpll_per_ck>; ++ reg = <0x44e004ac 0x4>; ++ bit-mask = <0x1f>; ++ index-starts-at-one; ++}; ++ ++dpll_per_m2_div4_wkupdm_ck: dpll_per_m2_div4_wkupdm_ck { ++ #clock-cells = <0>; ++ compatible = "fixed-factor-clock"; ++ clocks = <&dpll_per_m2_ck>; ++ clock-mult = <1>; ++ clock-div = <4>; ++}; ++ ++dpll_per_m2_div4_ck: dpll_per_m2_div4_ck { ++ #clock-cells = <0>; ++ compatible = "fixed-factor-clock"; ++ clocks = <&dpll_per_m2_ck>; ++ clock-mult = <1>; ++ clock-div = <4>; ++}; ++ ++adc_tsc_fck: adc_tsc_fck { ++ #clock-cells = <0>; ++ compatible = "fixed-factor-clock"; ++ clocks = <&sys_clkin_ck>; ++ clock-mult = <1>; ++ clock-div = <1>; ++}; ++ ++cefuse_fck: cefuse_fck@44e00a20 { ++ #clock-cells = <0>; ++ compatible = "gate-clock"; ++ clocks = <&sys_clkin_ck>; ++ bit-shift = <1>; ++ reg = <0x44e00a20 0x4>; ++}; ++ ++clk_24mhz: clk_24mhz { ++ #clock-cells = <0>; ++ compatible = "fixed-factor-clock"; ++ clocks = <&dpll_per_m2_ck>; ++ clock-mult = <1>; ++ clock-div = <8>; ++}; ++ ++clkdiv32k_ck: clkdiv32k_ck { ++ #clock-cells = <0>; ++ compatible = "fixed-factor-clock"; ++ clocks = <&clk_24mhz>; ++ clock-mult = <1>; ++ clock-div = <732>; ++}; ++ ++clkdiv32k_ick: clkdiv32k_ick@44e0014c { ++ #clock-cells = <0>; ++ compatible = "ti,gate-clock"; ++ clocks = <&clkdiv32k_ck>; ++ reg = <0x44e0014c 0x4>; ++ bit-shift = <1>; ++}; ++ ++dcan0_fck: dcan0_fck { ++ #clock-cells = <0>; ++ compatible = "fixed-factor-clock"; ++ clocks = <&sys_clkin_ck>; ++ clock-mult = <1>; ++ clock-div = <1>; ++}; ++ ++dcan1_fck: dcan1_fck { ++ #clock-cells = <0>; ++ compatible = "fixed-factor-clock"; ++ clocks = <&sys_clkin_ck>; ++ clock-mult = <1>; ++ clock-div = <1>; ++}; ++ ++l3_gclk: l3_gclk { ++ #clock-cells = <0>; ++ compatible = "fixed-factor-clock"; ++ clocks = <&dpll_core_m4_ck>; ++ clock-mult = <1>; ++ clock-div = <1>; ++}; ++ ++pruss_ocp_gclk: pruss_ocp_gclk@44e00530 { ++ #clock-cells = <0>; ++ compatible = "mux-clock"; ++ clocks = <&l3_gclk>, <&dpll_disp_m2_ck>; ++ reg = <0x44e00530 0x4>; ++ bit-mask = <0x1>; ++}; ++ ++mcasp0_fck: mcasp0_fck { ++ #clock-cells = <0>; ++ compatible = "fixed-factor-clock"; ++ clocks = <&sys_clkin_ck>; ++ clock-mult = <1>; ++ clock-div = <1>; ++}; ++ ++mcasp1_fck: mcasp1_fck { ++ #clock-cells = <0>; ++ compatible = "fixed-factor-clock"; ++ clocks = <&sys_clkin_ck>; ++ clock-mult = <1>; ++ clock-div = <1>; ++}; ++ ++mmu_fck: mmu_fck@44e00914 { ++ #clock-cells = <0>; ++ compatible = "gate-clock"; ++ clocks = <&dpll_core_m4_ck>; ++ bit-shift = <1>; ++ reg = <0x44e00914 0x4>; ++}; ++ ++smartreflex0_fck: smartreflex0_fck { ++ #clock-cells = <0>; ++ compatible = "fixed-factor-clock"; ++ clocks = <&sys_clkin_ck>; ++ clock-mult = <1>; ++ clock-div = <1>; ++}; ++ ++smartreflex1_fck: smartreflex1_fck { ++ #clock-cells = <0>; ++ compatible = "fixed-factor-clock"; ++ clocks = <&sys_clkin_ck>; ++ clock-mult = <1>; ++ clock-div = <1>; ++}; ++ ++sha0_fck: sha0_fck { ++ #clock-cells = <0>; ++ compatible = "fixed-factor-clock"; ++ clocks = <&sys_clkin_ck>; ++ clock-mult = <1>; ++ clock-div = <1>; ++}; ++ ++rng_fck: rng_fck { ++ #clock-cells = <0>; ++ compatible = "fixed-factor-clock"; ++ clocks = <&sys_clkin_ck>; ++ clock-mult = <1>; ++ clock-div = <1>; ++}; ++ ++aes0_fck: aes0_fck { ++ #clock-cells = <0>; ++ compatible = "fixed-factor-clock"; ++ clocks = <&sys_clkin_ck>; ++ clock-mult = <1>; ++ clock-div = <1>; ++}; ++ ++timer1_fck: timer1_fck@44e00528 { ++ #clock-cells = <0>; ++ compatible = "mux-clock"; ++ clocks = <&sys_clkin_ck>, <&clkdiv32k_ick>, <&tclkin_ck>, <&clk_rc32k_ck>, <&clk_32768_ck>; ++ reg = <0x44e00528 0x4>; ++ bit-mask = <0x7>; ++}; ++ ++timer2_fck: timer2_fck@44e00508 { ++ #clock-cells = <0>; ++ compatible = "mux-clock"; ++ clocks = <&tclkin_ck>, <&sys_clkin_ck>, <&clkdiv32k_ick>; ++ reg = <0x44e00508 0x4>; ++ bit-mask = <0x3>; ++}; ++ ++timer3_fck: timer3_fck@44e0050c { ++ #clock-cells = <0>; ++ compatible = "mux-clock"; ++ clocks = <&tclkin_ck>, <&sys_clkin_ck>, <&clkdiv32k_ick>; ++ reg = <0x44e0050c 0x4>; ++ bit-mask = <0x3>; ++}; ++ ++timer4_fck: timer4_fck@44e00510 { ++ #clock-cells = <0>; ++ compatible = "mux-clock"; ++ clocks = <&tclkin_ck>, <&sys_clkin_ck>, <&clkdiv32k_ick>; ++ reg = <0x44e00510 0x4>; ++ bit-mask = <0x3>; ++}; ++ ++timer5_fck: timer5_fck@44e00518 { ++ #clock-cells = <0>; ++ compatible = "mux-clock"; ++ clocks = <&tclkin_ck>, <&sys_clkin_ck>, <&clkdiv32k_ick>; ++ reg = <0x44e00518 0x4>; ++ bit-mask = <0x3>; ++}; ++ ++timer6_fck: timer6_fck@44e0051c { ++ #clock-cells = <0>; ++ compatible = "mux-clock"; ++ clocks = <&tclkin_ck>, <&sys_clkin_ck>, <&clkdiv32k_ick>; ++ reg = <0x44e0051c 0x4>; ++ bit-mask = <0x3>; ++}; ++ ++timer7_fck: timer7_fck@44e00504 { ++ #clock-cells = <0>; ++ compatible = "mux-clock"; ++ clocks = <&tclkin_ck>, <&sys_clkin_ck>, <&clkdiv32k_ick>; ++ reg = <0x44e00504 0x4>; ++ bit-mask = <0x3>; ++}; ++ ++usbotg_fck: usbotg_fck@44e0047c { ++ #clock-cells = <0>; ++ compatible = "gate-clock"; ++ clocks = <&dpll_per_ck>; ++ bit-shift = <8>; ++ reg = <0x44e0047c 0x4>; ++}; ++ ++dpll_core_m4_div2_ck: dpll_core_m4_div2_ck { ++ #clock-cells = <0>; ++ compatible = "fixed-factor-clock"; ++ clocks = <&dpll_core_m4_ck>; ++ clock-mult = <1>; ++ clock-div = <2>; ++}; ++ ++ieee5000_fck: ieee5000_fck@44e000e4 { ++ #clock-cells = <0>; ++ compatible = "gate-clock"; ++ clocks = <&dpll_core_m4_div2_ck>; ++ bit-shift = <1>; ++ reg = <0x44e000e4 0x4>; ++}; ++ ++wdt1_fck: wdt1_fck@44e00538 { ++ #clock-cells = <0>; ++ compatible = "mux-clock"; ++ clocks = <&clk_rc32k_ck>, <&clkdiv32k_ick>; ++ reg = <0x44e00538 0x4>; ++ bit-mask = <0x3>; ++}; ++ ++l4_rtc_gclk: l4_rtc_gclk { ++ #clock-cells = <0>; ++ compatible = "fixed-factor-clock"; ++ clocks = <&dpll_core_m4_ck>; ++ clock-mult = <1>; ++ clock-div = <2>; ++}; ++ ++l4hs_gclk: l4hs_gclk { ++ #clock-cells = <0>; ++ compatible = "fixed-factor-clock"; ++ clocks = <&dpll_core_m4_ck>; ++ clock-mult = <1>; ++ clock-div = <1>; ++}; ++ ++l3s_gclk: l3s_gclk { ++ #clock-cells = <0>; ++ compatible = "fixed-factor-clock"; ++ clocks = <&dpll_core_m4_div2_ck>; ++ clock-mult = <1>; ++ clock-div = <1>; ++}; ++ ++l4fw_gclk: l4fw_gclk { ++ #clock-cells = <0>; ++ compatible = "fixed-factor-clock"; ++ clocks = <&dpll_core_m4_div2_ck>; ++ clock-mult = <1>; ++ clock-div = <1>; ++}; ++ ++l4ls_gclk: l4ls_gclk { ++ #clock-cells = <0>; ++ compatible = "fixed-factor-clock"; ++ clocks = <&dpll_core_m4_div2_ck>; ++ clock-mult = <1>; ++ clock-div = <1>; ++}; ++ ++sysclk_div_ck: sysclk_div_ck { ++ #clock-cells = <0>; ++ compatible = "fixed-factor-clock"; ++ clocks = <&dpll_core_m4_ck>; ++ clock-mult = <1>; ++ clock-div = <1>; ++}; ++ ++cpsw_125mhz_gclk: cpsw_125mhz_gclk { ++ #clock-cells = <0>; ++ compatible = "fixed-factor-clock"; ++ clocks = <&dpll_core_m5_ck>; ++ clock-mult = <1>; ++ clock-div = <2>; ++}; ++ ++cpsw_cpts_rft_clk: cpsw_cpts_rft_clk@44e00520 { ++ #clock-cells = <0>; ++ compatible = "mux-clock"; ++ clocks = <&dpll_core_m5_ck>, <&dpll_core_m4_ck>; ++ reg = <0x44e00520 0x4>; ++ bit-mask = <0x1>; ++}; ++ ++gpio0_dbclk_mux_ck: gpio0_dbclk_mux_ck@44e0053c { ++ #clock-cells = <0>; ++ compatible = "mux-clock"; ++ clocks = <&clk_rc32k_ck>, <&clk_32768_ck>, <&clkdiv32k_ick>; ++ reg = <0x44e0053c 0x4>; ++ bit-mask = <0x3>; ++}; ++ ++gpio0_dbclk: gpio0_dbclk@44e00408 { ++ #clock-cells = <0>; ++ compatible = "gate-clock"; ++ clocks = <&gpio0_dbclk_mux_ck>; ++ bit-shift = <18>; ++ reg = <0x44e00408 0x4>; ++}; ++ ++gpio1_dbclk: gpio1_dbclk@44e000ac { ++ #clock-cells = <0>; ++ compatible = "gate-clock"; ++ clocks = <&clkdiv32k_ick>; ++ bit-shift = <18>; ++ reg = <0x44e000ac 0x4>; ++}; ++ ++gpio2_dbclk: gpio2_dbclk@44e000b0 { ++ #clock-cells = <0>; ++ compatible = "gate-clock"; ++ clocks = <&clkdiv32k_ick>; ++ bit-shift = <18>; ++ reg = <0x44e000b0 0x4>; ++}; ++ ++gpio3_dbclk: gpio3_dbclk@44e000b4 { ++ #clock-cells = <0>; ++ compatible = "gate-clock"; ++ clocks = <&clkdiv32k_ick>; ++ bit-shift = <18>; ++ reg = <0x44e000b4 0x4>; ++}; ++ ++lcd_gclk: lcd_gclk@44e00534 { ++ #clock-cells = <0>; ++ compatible = "mux-clock"; ++ clocks = <&dpll_disp_m2_ck>, <&dpll_core_m5_ck>, <&dpll_per_m2_ck>; ++ reg = <0x44e00534 0x4>; ++ bit-mask = <0x3>; ++ set-rate-parent; ++}; ++ ++mmc_clk: mmc_clk { ++ #clock-cells = <0>; ++ compatible = "fixed-factor-clock"; ++ clocks = <&dpll_per_m2_ck>; ++ clock-mult = <1>; ++ clock-div = <2>; ++}; ++ ++gfx_fclk_clksel_ck: gfx_fclk_clksel_ck@44e0052c { ++ #clock-cells = <0>; ++ compatible = "mux-clock"; ++ clocks = <&dpll_core_m4_ck>, <&dpll_per_m2_ck>; ++ bit-shift = <1>; ++ reg = <0x44e0052c 0x4>; ++ bit-mask = <0x1>; ++}; ++ ++gfx_fck_div_ck: gfx_fck_div_ck@44e0052c { ++ #clock-cells = <0>; ++ compatible = "divider-clock"; ++ clocks = <&gfx_fclk_clksel_ck>; ++ reg = <0x44e0052c 0x4>; ++ table = < 1 0 >, < 2 1 >; ++ bit-mask = <0x1>; ++}; ++ ++sysclkout_pre_ck: sysclkout_pre_ck@44e00700 { ++ #clock-cells = <0>; ++ compatible = "mux-clock"; ++ clocks = <&clk_32768_ck>, <&l3_gclk>, <&dpll_ddr_m2_ck>, <&dpll_per_m2_ck>, <&lcd_gclk>; ++ reg = <0x44e00700 0x4>; ++ bit-mask = <0x7>; ++}; ++ ++clkout2_div_ck: clkout2_div_ck@44e00700 { ++ #clock-cells = <0>; ++ compatible = "divider-clock"; ++ clocks = <&sysclkout_pre_ck>; ++ bit-shift = <3>; ++ reg = <0x44e00700 0x4>; ++ table = < 1 0 >, < 2 1 >, < 3 2 >, < 4 3 >, < 5 4 >, < 6 5 >, < 7 6 >, < 8 7 >; ++ bit-mask = <0x7>; ++}; ++ ++dbg_sysclk_ck: dbg_sysclk_ck@44e00414 { ++ #clock-cells = <0>; ++ compatible = "gate-clock"; ++ clocks = <&sys_clkin_ck>; ++ bit-shift = <19>; ++ reg = <0x44e00414 0x4>; ++}; ++ ++dbg_clka_ck: dbg_clka_ck@44e00414 { ++ #clock-cells = <0>; ++ compatible = "gate-clock"; ++ clocks = <&dpll_core_m4_ck>; ++ bit-shift = <30>; ++ reg = <0x44e00414 0x4>; ++}; ++ ++stm_pmd_clock_mux_ck: stm_pmd_clock_mux_ck@44e00414 { ++ #clock-cells = <0>; ++ compatible = "mux-clock"; ++ clocks = <&dbg_sysclk_ck>, <&dbg_clka_ck>; ++ bit-shift = <22>; ++ reg = <0x44e00414 0x4>; ++ bit-mask = <0x3>; ++}; ++ ++trace_pmd_clk_mux_ck: trace_pmd_clk_mux_ck@44e00414 { ++ #clock-cells = <0>; ++ compatible = "mux-clock"; ++ clocks = <&dbg_sysclk_ck>, <&dbg_clka_ck>; ++ bit-shift = <20>; ++ reg = <0x44e00414 0x4>; ++ bit-mask = <0x3>; ++}; ++ ++stm_clk_div_ck: stm_clk_div_ck@44e00414 { ++ #clock-cells = <0>; ++ compatible = "divider-clock"; ++ clocks = <&stm_pmd_clock_mux_ck>; ++ bit-shift = <27>; ++ reg = <0x44e00414 0x4>; ++ bit-mask = <0x7>; ++ index-power-of-two; ++}; ++ ++trace_clk_div_ck: trace_clk_div_ck@44e00414 { ++ #clock-cells = <0>; ++ compatible = "divider-clock"; ++ clocks = <&trace_pmd_clk_mux_ck>; ++ bit-shift = <24>; ++ reg = <0x44e00414 0x4>; ++ bit-mask = <0x7>; ++ index-power-of-two; ++}; ++ ++clkout2_ck: clkout2_ck@44e00700 { ++ #clock-cells = <0>; ++ compatible = "gate-clock"; ++ clocks = <&clkout2_div_ck>; ++ bit-shift = <7>; ++ reg = <0x44e00700 0x4>; ++}; ++ ++ehrpwm0_tbclk: ehrpwm0_tbclk@44e10664 { ++ #clock-cells = <0>; ++ compatible = "gate-clock"; ++ clocks = <&dpll_per_m2_ck>; ++ bit-shift = <0>; ++ reg = <0x44e10664 0x4>; ++}; ++ ++ehrpwm1_tbclk: ehrpwm1_tbclk@44e10664 { ++ #clock-cells = <0>; ++ compatible = "gate-clock"; ++ clocks = <&dpll_per_m2_ck>; ++ bit-shift = <1>; ++ reg = <0x44e10664 0x4>; ++}; ++ ++ehrpwm2_tbclk: ehrpwm2_tbclk@44e10664 { ++ #clock-cells = <0>; ++ compatible = "gate-clock"; ++ clocks = <&dpll_per_m2_ck>; ++ bit-shift = <2>; ++ reg = <0x44e10664 0x4>; ++}; +--- a/arch/arm/boot/dts/am33xx.dtsi ++++ b/arch/arm/boot/dts/am33xx.dtsi +@@ -18,6 +18,9 @@ + interrupt-parent = <&intc>; + + aliases { ++ i2c0 = &i2c0; ++ i2c1 = &i2c1; ++ i2c2 = &i2c2; + serial0 = &uart0; + serial1 = &uart1; + serial2 = &uart2; +@@ -30,6 +33,8 @@ + usb1 = &usb1; + phy0 = &usb0_phy; + phy1 = &usb1_phy; ++ ethernet0 = &cpsw_emac0; ++ ethernet1 = &cpsw_emac1; + }; + + cpus { +@@ -53,6 +58,10 @@ + 275000 1125000 + >; + voltage-tolerance = <2>; /* 2 percentage */ ++ ++ clocks = <&dpll_mpu_ck>; ++ clock-names = "cpu"; ++ + clock-latency = <300000>; /* From omap-cpufreq driver */ + }; + }; +@@ -91,6 +100,8 @@ + #size-cells = <1>; + ranges; + ti,hwmods = "l3_main"; ++ clocks = <&l3_gclk>; ++ clock-names = "fck"; + + intc: interrupt-controller@48200000 { + compatible = "ti,omap2-intc"; +@@ -100,9 +111,23 @@ + reg = <0x48200000 0x1000>; + }; + ++ edma: edma@49000000 { ++ compatible = "ti,edma3"; ++ ti,hwmods = "tpcc", "tptc0", "tptc1", "tptc2"; ++ reg = <0x49000000 0x10000>, ++ <0x44e10f90 0x10>; ++ interrupts = <12 13 14>; ++ #dma-cells = <1>; ++ dma-channels = <64>; ++ ti,edma-regions = <4>; ++ ti,edma-slots = <256>; ++ }; ++ + gpio0: gpio@44e07000 { + compatible = "ti,omap4-gpio"; + ti,hwmods = "gpio1"; ++ clocks = <&dpll_core_m4_div2_ck>, <&gpio0_dbclk>; ++ clock-names = "fck", "dbclk"; + gpio-controller; + #gpio-cells = <2>; + interrupt-controller; +@@ -114,6 +139,8 @@ + gpio1: gpio@4804c000 { + compatible = "ti,omap4-gpio"; + ti,hwmods = "gpio2"; ++ clocks = <&l4ls_gclk>, <&gpio1_dbclk>; ++ clock-names = "fck", "dbclk"; + gpio-controller; + #gpio-cells = <2>; + interrupt-controller; +@@ -125,6 +152,8 @@ + gpio2: gpio@481ac000 { + compatible = "ti,omap4-gpio"; + ti,hwmods = "gpio3"; ++ clocks = <&l4ls_gclk>, <&gpio2_dbclk>; ++ clock-names = "fck", "dbclk"; + gpio-controller; + #gpio-cells = <2>; + interrupt-controller; +@@ -136,6 +165,8 @@ + gpio3: gpio@481ae000 { + compatible = "ti,omap4-gpio"; + ti,hwmods = "gpio4"; ++ clocks = <&l4ls_gclk>, <&gpio3_dbclk>; ++ clock-names = "fck", "dbclk"; + gpio-controller; + #gpio-cells = <2>; + interrupt-controller; +@@ -147,6 +178,8 @@ + uart0: serial@44e09000 { + compatible = "ti,omap3-uart"; + ti,hwmods = "uart1"; ++ clocks = <&dpll_per_m2_div4_wkupdm_ck>; ++ clock-names = "fck"; + clock-frequency = <48000000>; + reg = <0x44e09000 0x2000>; + interrupts = <72>; +@@ -156,6 +189,8 @@ + uart1: serial@48022000 { + compatible = "ti,omap3-uart"; + ti,hwmods = "uart2"; ++ clocks = <&dpll_per_m2_div4_ck>; ++ clock-names = "fck"; + clock-frequency = <48000000>; + reg = <0x48022000 0x2000>; + interrupts = <73>; +@@ -165,6 +200,8 @@ + uart2: serial@48024000 { + compatible = "ti,omap3-uart"; + ti,hwmods = "uart3"; ++ clocks = <&dpll_per_m2_div4_ck>; ++ clock-names = "fck"; + clock-frequency = <48000000>; + reg = <0x48024000 0x2000>; + interrupts = <74>; +@@ -174,6 +211,8 @@ + uart3: serial@481a6000 { + compatible = "ti,omap3-uart"; + ti,hwmods = "uart4"; ++ clocks = <&dpll_per_m2_div4_ck>; ++ clock-names = "fck"; + clock-frequency = <48000000>; + reg = <0x481a6000 0x2000>; + interrupts = <44>; +@@ -183,6 +222,8 @@ + uart4: serial@481a8000 { + compatible = "ti,omap3-uart"; + ti,hwmods = "uart5"; ++ clocks = <&dpll_per_m2_div4_ck>; ++ clock-names = "fck"; + clock-frequency = <48000000>; + reg = <0x481a8000 0x2000>; + interrupts = <45>; +@@ -192,6 +233,8 @@ + uart5: serial@481aa000 { + compatible = "ti,omap3-uart"; + ti,hwmods = "uart6"; ++ clocks = <&dpll_per_m2_div4_ck>; ++ clock-names = "fck"; + clock-frequency = <48000000>; + reg = <0x481aa000 0x2000>; + interrupts = <46>; +@@ -203,6 +246,8 @@ + #address-cells = <1>; + #size-cells = <0>; + ti,hwmods = "i2c1"; ++ clocks = <&dpll_per_m2_div4_wkupdm_ck>; ++ clock-names = "fck"; + reg = <0x44e0b000 0x1000>; + interrupts = <70>; + status = "disabled"; +@@ -213,6 +258,8 @@ + #address-cells = <1>; + #size-cells = <0>; + ti,hwmods = "i2c2"; ++ clocks = <&dpll_per_m2_div4_ck>; ++ clock-names = "fck"; + reg = <0x4802a000 0x1000>; + interrupts = <71>; + status = "disabled"; +@@ -223,14 +270,62 @@ + #address-cells = <1>; + #size-cells = <0>; + ti,hwmods = "i2c3"; ++ clocks = <&dpll_per_m2_div4_ck>; ++ clock-names = "fck"; + reg = <0x4819c000 0x1000>; + interrupts = <30>; + status = "disabled"; + }; + ++ mmc1: mmc@48060000 { ++ compatible = "ti,omap4-hsmmc"; ++ ti,hwmods = "mmc1"; ++ clocks = <&mmc_clk>, <&clkdiv32k_ick>; ++ clock-names = "fck", "mmchsdb_fck"; ++ ti,dual-volt; ++ ti,needs-special-reset; ++ ti,needs-special-hs-handling; ++ dmas = <&edma 24 ++ &edma 25>; ++ dma-names = "tx", "rx"; ++ interrupts = <64>; ++ interrupt-parent = <&intc>; ++ reg = <0x48060000 0x1000>; ++ status = "disabled"; ++ }; ++ ++ mmc2: mmc@481d8000 { ++ compatible = "ti,omap4-hsmmc"; ++ ti,hwmods = "mmc2"; ++ clocks = <&mmc_clk>, <&clkdiv32k_ick>; ++ clock-names = "fck", "mmchsdb_fck"; ++ ti,needs-special-reset; ++ dmas = <&edma 2 ++ &edma 3>; ++ dma-names = "tx", "rx"; ++ interrupts = <28>; ++ interrupt-parent = <&intc>; ++ reg = <0x481d8000 0x1000>; ++ status = "disabled"; ++ }; ++ ++ mmc3: mmc@47810000 { ++ compatible = "ti,omap4-hsmmc"; ++ ti,hwmods = "mmc3"; ++ clocks = <&mmc_clk>, <&clkdiv32k_ick>; ++ clock-names = "fck", "mmchsdb_fck"; ++ ti,needs-special-reset; ++ interrupts = <29>; ++ interrupt-parent = <&intc>; ++ reg = <0x47810000 0x1000>; ++ status = "disabled"; ++ }; ++ + wdt2: wdt@44e35000 { + compatible = "ti,omap3-wdt"; + ti,hwmods = "wd_timer2"; ++ clocks = <&wdt1_fck>; ++ clock-names = "fck"; + reg = <0x44e35000 0x1000>; + interrupts = <91>; + }; +@@ -238,6 +333,8 @@ + dcan0: d_can@481cc000 { + compatible = "bosch,d_can"; + ti,hwmods = "d_can0"; ++ clocks = <&dcan0_fck>; ++ clock-names = "fck"; + reg = <0x481cc000 0x2000 + 0x44e10644 0x4>; + interrupts = <52>; +@@ -247,17 +344,32 @@ + dcan1: d_can@481d0000 { + compatible = "bosch,d_can"; + ti,hwmods = "d_can1"; ++ clocks = <&dcan1_fck>; ++ clock-names = "fck"; + reg = <0x481d0000 0x2000 + 0x44e10644 0x4>; + interrupts = <55>; + status = "disabled"; + }; + ++ mailbox: mailbox@480C8000 { ++ compatible = "ti,omap4-mailbox"; ++ reg = <0x480C8000 0x200>; ++ interrupts = <77>; ++ ti,hwmods = "mailbox"; ++ ti,mbox-num-users = <4>; ++ ti,mbox-num-fifos = <8>; ++ ti,mbox-names = "wkup_m3"; ++ ti,mbox-data = <0 0 0 0>; ++ }; ++ + timer1: timer@44e31000 { + compatible = "ti,am335x-timer-1ms"; + reg = <0x44e31000 0x400>; + interrupts = <67>; + ti,hwmods = "timer1"; ++ clocks = <&timer1_fck>; ++ clock-names = "fck"; + ti,timer-alwon; + }; + +@@ -266,6 +378,8 @@ + reg = <0x48040000 0x400>; + interrupts = <68>; + ti,hwmods = "timer2"; ++ clocks = <&timer2_fck>; ++ clock-names = "fck"; + }; + + timer3: timer@48042000 { +@@ -273,6 +387,8 @@ + reg = <0x48042000 0x400>; + interrupts = <69>; + ti,hwmods = "timer3"; ++ clocks = <&timer3_fck>; ++ clock-names = "fck"; + }; + + timer4: timer@48044000 { +@@ -280,6 +396,8 @@ + reg = <0x48044000 0x400>; + interrupts = <92>; + ti,hwmods = "timer4"; ++ clocks = <&timer4_fck>; ++ clock-names = "fck"; + ti,timer-pwm; + }; + +@@ -288,6 +406,8 @@ + reg = <0x48046000 0x400>; + interrupts = <93>; + ti,hwmods = "timer5"; ++ clocks = <&timer5_fck>; ++ clock-names = "fck"; + ti,timer-pwm; + }; + +@@ -296,6 +416,8 @@ + reg = <0x48048000 0x400>; + interrupts = <94>; + ti,hwmods = "timer6"; ++ clocks = <&timer6_fck>; ++ clock-names = "fck"; + ti,timer-pwm; + }; + +@@ -304,6 +426,8 @@ + reg = <0x4804a000 0x400>; + interrupts = <95>; + ti,hwmods = "timer7"; ++ clocks = <&timer7_fck>; ++ clock-names = "fck"; + ti,timer-pwm; + }; + +@@ -313,6 +437,8 @@ + interrupts = <75 + 76>; + ti,hwmods = "rtc"; ++ clocks = <&clk_32768_ck>; ++ clock-names = "fck"; + }; + + spi0: spi@48030000 { +@@ -323,6 +449,13 @@ + interrupts = <65>; + ti,spi-num-cs = <2>; + ti,hwmods = "spi0"; ++ clocks = <&dpll_per_m2_div4_ck>; ++ clock-names = "fck"; ++ dmas = <&edma 16 ++ &edma 17 ++ &edma 18 ++ &edma 19>; ++ dma-names = "tx0", "rx0", "tx1", "rx1"; + status = "disabled"; + }; + +@@ -334,6 +467,13 @@ + interrupts = <125>; + ti,spi-num-cs = <2>; + ti,hwmods = "spi1"; ++ clocks = <&dpll_per_m2_div4_ck>; ++ clock-names = "fck"; ++ dmas = <&edma 42 ++ &edma 43 ++ &edma 44 ++ &edma 45>; ++ dma-names = "tx0", "rx0", "tx1", "rx1"; + status = "disabled"; + }; + +@@ -345,6 +485,8 @@ + #size-cells = <1>; + ti,hwmods = "usb_otg_hs"; + status = "disabled"; ++ clocks = <&usbotg_fck>; ++ clock-names = "fck"; + + ctrl_mod: control@44e10000 { + compatible = "ti,am335x-usb-ctrl-module"; +@@ -469,6 +611,8 @@ + compatible = "ti,am33xx-pwmss"; + reg = <0x48300000 0x10>; + ti,hwmods = "epwmss0"; ++ clocks = <&l4ls_gclk>; ++ clock-names = "fck"; + #address-cells = <1>; + #size-cells = <1>; + status = "disabled"; +@@ -481,6 +625,8 @@ + #pwm-cells = <3>; + reg = <0x48300100 0x80>; + ti,hwmods = "ecap0"; ++ clocks = <&l4ls_gclk>; ++ clock-names = "fck"; + status = "disabled"; + }; + +@@ -489,6 +635,8 @@ + #pwm-cells = <3>; + reg = <0x48300200 0x80>; + ti,hwmods = "ehrpwm0"; ++ clocks = <&l4ls_gclk>; ++ clock-names = "fck"; + status = "disabled"; + }; + }; +@@ -497,6 +645,8 @@ + compatible = "ti,am33xx-pwmss"; + reg = <0x48302000 0x10>; + ti,hwmods = "epwmss1"; ++ clocks = <&l4ls_gclk>; ++ clock-names = "fck"; + #address-cells = <1>; + #size-cells = <1>; + status = "disabled"; +@@ -509,6 +659,8 @@ + #pwm-cells = <3>; + reg = <0x48302100 0x80>; + ti,hwmods = "ecap1"; ++ clocks = <&l4ls_gclk>; ++ clock-names = "fck"; + status = "disabled"; + }; + +@@ -517,6 +669,8 @@ + #pwm-cells = <3>; + reg = <0x48302200 0x80>; + ti,hwmods = "ehrpwm1"; ++ clocks = <&l4ls_gclk>; ++ clock-names = "fck"; + status = "disabled"; + }; + }; +@@ -525,6 +679,8 @@ + compatible = "ti,am33xx-pwmss"; + reg = <0x48304000 0x10>; + ti,hwmods = "epwmss2"; ++ clocks = <&l4ls_gclk>; ++ clock-names = "fck"; + #address-cells = <1>; + #size-cells = <1>; + status = "disabled"; +@@ -537,6 +693,8 @@ + #pwm-cells = <3>; + reg = <0x48304100 0x80>; + ti,hwmods = "ecap2"; ++ clocks = <&l4ls_gclk>; ++ clock-names = "fck"; + status = "disabled"; + }; + +@@ -545,6 +703,8 @@ + #pwm-cells = <3>; + reg = <0x48304200 0x80>; + ti,hwmods = "ehrpwm2"; ++ clocks = <&l4ls_gclk>; ++ clock-names = "fck"; + status = "disabled"; + }; + }; +@@ -552,6 +712,8 @@ + mac: ethernet@4a100000 { + compatible = "ti,cpsw"; + ti,hwmods = "cpgmac0"; ++ clocks = <&cpsw_125mhz_gclk>; ++ clock-names = "fck"; + cpdma_channels = <8>; + ale_entries = <1024>; + bd_ram_size = <0x2000>; +@@ -581,6 +743,8 @@ + #address-cells = <1>; + #size-cells = <0>; + ti,hwmods = "davinci_mdio"; ++ clocks = <&cpsw_125mhz_gclk>; ++ clock-names = "fck"; + bus_freq = <1000000>; + reg = <0x4a101000 0x100>; + }; +@@ -594,19 +758,33 @@ + /* Filled in by U-Boot */ + mac-address = [ 00 00 00 00 00 00 ]; + }; ++ ++ phy_sel: cpsw-phy-sel@44e10650 { ++ compatible = "ti,am3352-cpsw-phy-sel"; ++ reg= <0x44e10650 0x4>; ++ reg-names = "gmii-sel"; ++ }; + }; + + ocmcram: ocmcram@40300000 { + compatible = "ti,am3352-ocmcram"; + reg = <0x40300000 0x10000>; + ti,hwmods = "ocmcram"; ++ clocks = <&l3_gclk>; ++ clock-names = "fck"; + }; + + wkup_m3: wkup_m3@44d00000 { + compatible = "ti,am3353-wkup-m3"; +- reg = <0x44d00000 0x4000 /* M3 UMEM */ +- 0x44d80000 0x2000>; /* M3 DMEM */ ++ reg = <0x44d00000 0x4000 ++ 0x44d80000 0x2000 ++ 0x44e11324 0x0024>; ++ reg-names = "m3_umem", "m3_dmem", "ipc_regs"; ++ interrupts = <78>; + ti,hwmods = "wkup_m3"; ++ ti,no-reset; ++ clocks = <&dpll_core_m4_div2_ck>; ++ clock-names = "fck"; + }; + + elm: elm@48080000 { +@@ -614,6 +792,8 @@ + reg = <0x48080000 0x2000>; + interrupts = <4>; + ti,hwmods = "elm"; ++ clocks = <&l4ls_gclk>; ++ clock-names = "fck"; + status = "disabled"; + }; + +@@ -623,6 +803,8 @@ + interrupt-parent = <&intc>; + interrupts = <16>; + ti,hwmods = "adc_tsc"; ++ clocks = <&adc_tsc_fck>; ++ clock-names = "fck"; + status = "disabled"; + + tsc { +@@ -637,6 +819,9 @@ + gpmc: gpmc@50000000 { + compatible = "ti,am3352-gpmc"; + ti,hwmods = "gpmc"; ++ ti,no-idle; ++ clocks = <&l3s_gclk>; ++ clock-names = "fck"; + reg = <0x50000000 0x2000>; + interrupts = <100>; + gpmc,num-cs = <7>; +@@ -645,5 +830,102 @@ + #size-cells = <1>; + status = "disabled"; + }; ++ ++ prcm: prcm@44e00000 { ++ compatible = "ti,am3352-prcm"; ++ reg = <0x44e00000 0x1300>; ++ #reset-cells = <1>; ++ }; ++ ++ sham: sham@53100000 { ++ compatible = "ti,omap4-sham"; ++ ti,hwmods = "sham"; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <0x53100000 0x200>; ++ interrupt-parent = <&intc>; ++ interrupts = <109>; ++ dmas = <&edma 36>; ++ dma-names = "rx"; ++ clocks = <&l3_gclk>; ++ clock-names = "fck"; ++ }; ++ ++ aes: aes@53500000 { ++ compatible = "ti,omap4-aes"; ++ ti,hwmods = "aes"; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <0x53500000 0xa0>; ++ interrupt-parent = <&intc>; ++ interrupts = <103>; ++ dmas = <&edma 6 ++ &edma 5>; ++ dma-names = "tx", "rx"; ++ clocks = <&aes0_fck>; ++ clock-names = "fck"; ++ }; ++ ++ rng: rng@48310000 { ++ compatible = "ti,omap4-rng"; ++ ti,hwmods = "rng"; ++ reg = <0x48310000 0x2000>; ++ interrupts = <111>; ++ clocks = <&rng_fck>; ++ clock-names = "fck"; ++ }; ++ ++ lcdc: lcdc@0x4830e000 { ++ compatible = "ti,am33xx-tilcdc"; ++ reg = <0x4830e000 0x1000>; ++ interrupt-parent = <&intc>; ++ interrupts = <36>; ++ clocks = <&lcd_gclk>; ++ clock-names = "fck"; ++ ti,hwmods = "lcdc"; ++ status = "disabled"; ++ }; ++ ++ mcasp0: mcasp@48038000 { ++ compatible = "ti,omap2-mcasp-audio"; ++ ti,hwmods = "mcasp0"; ++ reg = <0x48038000 0x2000>, ++ <0x46400000 0x400000>; ++ reg-names = "mpu", "dma"; ++ interrupts = <80 81>; ++ interrupts-names = "tx", "rx"; ++ status = "disabled"; ++ dmas = <&edma 8 ++ &edma 9>; ++ dma-names = "tx", "rx"; ++ }; ++ ++ mcasp1: mcasp@4803C000 { ++ compatible = "ti,omap2-mcasp-audio"; ++ ti,hwmods = "mcasp1"; ++ reg = <0x4803C000 0x2000>, ++ <0x46400000 0x400000>; ++ reg-names = "mpu", "dma"; ++ interrupts = <82 83>; ++ interrupts-names = "tx", "rx"; ++ status = "disabled"; ++ dmas = <&edma 10 ++ &edma 11>; ++ dma-names = "tx", "rx"; ++ }; ++ }; ++ ++ clocks { ++ #address-cells = <1>; ++ #size-cells = <1>; ++ ranges; ++ /include/ "am33xx-clocks.dtsi" + }; ++ ++ clockdomains { ++ clk_24mhz_clkdm: clk_24mhz_clkdm { ++ compatible = "ti,clockdomain"; ++ clocks = <&clkdiv32k_ick>; ++ }; ++ }; + }; +--- /dev/null ++++ b/arch/arm/boot/dts/am3517.dtsi +@@ -0,0 +1,116 @@ ++/* ++ * Device Tree Source for AM3517 SoC ++ * ++ * Copyright (C) 2013 Texas Instruments Incorporated - http://www.ti.com/ ++ * ++ * This file is licensed under the terms of the GNU General Public License ++ * version 2. This program is licensed "as is" without any warranty of any ++ * kind, whether express or implied. ++ */ ++ ++#include "omap3.dtsi" ++ ++/ { ++ cpus { ++ cpu@0 { ++ /* OMAP343x/OMAP35xx variants OPP1-5 */ ++ operating-points = < ++ /* kHz uV */ ++ 125000 975000 ++ 250000 1075000 ++ 500000 1200000 ++ 550000 1270000 ++ 600000 1350000 ++ >; ++ clock-latency = <300000>; /* From legacy driver */ ++ }; ++ }; ++ ++ clocks { ++ #address-cells = <1>; ++ #size-cells = <1>; ++ ranges; ++ /include/ "am35xx-clocks.dtsi" ++ /include/ "omap36xx-am35xx-omap3430es2plus-clocks.dtsi" ++ }; ++ ++ clockdomains { ++ dss_clkdm: dss_clkdm { ++ compatible = "ti,clockdomain"; ++ clocks = <&dss1_alwon_fck_3430es2>, <&dss_ick_3430es2>; ++ }; ++ ++ usbhost_clkdm: usbhost_clkdm { ++ compatible = "ti,clockdomain"; ++ clocks = <&usbhost_48m_fck>, <&usbhost_ick>; ++ }; ++ ++ core_l4_clkdm: core_l4_clkdm { ++ compatible = "ti,clockdomain"; ++ clocks = <&mmchs1_ick>, <&mmchs2_ick>, <&hdq_fck>, ++ <&uart1_ick>, <&mcspi4_fck>, <&i2c3_fck>, ++ <&mcspi2_ick>, <&uart2_ick>, <&mcspi3_ick>, ++ <&i2c1_fck>, <&hdq_ick>, <&sha12_ick>, ++ <&mcbsp5_ick>, <&mcspi3_fck>, <&aes2_ick>, ++ <&mcspi1_ick>, <&uart2_fck>, <&mmchs2_fck>, ++ <&mmchs1_fck>, <&i2c3_ick>, <&mcspi1_fck>, ++ <&mcspi4_ick>, <&omapctrl_ick>, <&mcbsp1_ick>, ++ <&mcspi2_fck>, <&gpt10_ick>, <&i2c2_fck>, ++ <&i2c2_ick>, <&gpt11_ick>, <&i2c1_ick>, ++ <&uart1_fck>; ++ }; ++ ++ wkup_clkdm: wkup_clkdm { ++ compatible = "ti,clockdomain"; ++ clocks = <&wdt1_ick>, <&gpt12_ick>, <&gpio1_ick>, ++ <&gpt1_ick>, <&omap_32ksync_ick>, <&wdt2_ick>, ++ <&wdt2_fck>; ++ }; ++ ++ dpll4_clkdm: dpll4_clkdm { ++ compatible = "ti,clockdomain"; ++ clocks = <&dpll4_ck>; ++ }; ++ ++ core_l3_clkdm: core_l3_clkdm { ++ compatible = "ti,clockdomain"; ++ clocks = <&sdrc_ick>; ++ }; ++ ++ per_clkdm: per_clkdm { ++ compatible = "ti,clockdomain"; ++ clocks = <&gpt2_ick>, <&uart3_fck>, <&gpio3_ick>, ++ <&mcbsp2_ick>, <&gpt6_ick>, <&mcbsp4_ick>, ++ <&gpt4_ick>, <&mcbsp3_ick>, <&gpt8_ick>, ++ <&uart3_ick>, <&gpt5_ick>, <&gpt7_ick>, ++ <&gpio2_ick>, <&gpio6_ick>, <&gpt9_ick>, ++ <&gpt3_ick>, <&gpio5_ick>, <&wdt3_ick>, ++ <&gpio4_ick>, <&wdt3_fck>, <&uart4_ick>; ++ }; ++ ++ emu_clkdm: emu_clkdm { ++ compatible = "ti,clockdomain"; ++ clocks = <&emu_src_ck>; ++ }; ++ ++ sgx_clkdm: sgx_clkdm { ++ compatible = "ti,clockdomain"; ++ clocks = <&sgx_ick>; ++ }; ++ ++ dpll3_clkdm: dpll3_clkdm { ++ compatible = "ti,clockdomain"; ++ clocks = <&dpll3_ck>; ++ }; ++ ++ dpll5_clkdm: dpll5_clkdm { ++ compatible = "ti,clockdomain"; ++ clocks = <&dpll5_ck>; ++ }; ++ ++ dpll1_clkdm: dpll1_clkdm { ++ compatible = "ti,clockdomain"; ++ clocks = <&dpll1_ck>; ++ }; ++ }; ++}; +--- a/arch/arm/boot/dts/am3517-evm.dts ++++ b/arch/arm/boot/dts/am3517-evm.dts +@@ -7,7 +7,7 @@ + */ + /dts-v1/; + +-#include "omap34xx.dtsi" ++#include "am3517.dtsi" + + / { + model = "TI AM3517 EVM (AM3517/05)"; +--- a/arch/arm/boot/dts/am3517_mt_ventoux.dts ++++ b/arch/arm/boot/dts/am3517_mt_ventoux.dts +@@ -7,7 +7,7 @@ + */ + /dts-v1/; + +-#include "omap34xx.dtsi" ++#include "am3517.dtsi" + + / { + model = "TeeJet Mt.Ventoux"; +--- /dev/null ++++ b/arch/arm/boot/dts/am35xx-clocks.dtsi +@@ -0,0 +1,101 @@ ++/* ++ * Device Tree Source for AM35xx clock data ++ * ++ * Copyright (C) 2013 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. ++ */ ++ ++ipss_ick: ipss_ick@48004a10 { ++ #clock-cells = <0>; ++ compatible = "ti,am35xx-interface-clock"; ++ clocks = <&core_l3_ick>; ++ reg = <0x48004a10 0x4>; ++ ti,enable-bit = <4>; ++}; ++ ++rmii_ck: rmii_ck { ++ #clock-cells = <0>; ++ compatible = "fixed-clock"; ++ clock-frequency = <50000000>; ++}; ++ ++pclk_ck: pclk_ck { ++ #clock-cells = <0>; ++ compatible = "fixed-clock"; ++ clock-frequency = <27000000>; ++}; ++ ++emac_ick: emac_ick@4800259c { ++ #clock-cells = <0>; ++ compatible = "ti,am35xx-gate-clock"; ++ clocks = <&ipss_ick>; ++ reg = <0x4800259c 0x4>; ++ ti,enable-bit = <1>; ++}; ++ ++emac_fck: emac_fck@4800259c { ++ #clock-cells = <0>; ++ compatible = "gate-clock"; ++ clocks = <&rmii_ck>; ++ reg = <0x4800259c 0x4>; ++ bit-shift = <9>; ++}; ++ ++vpfe_ick: vpfe_ick@4800259c { ++ #clock-cells = <0>; ++ compatible = "ti,am35xx-gate-clock"; ++ clocks = <&ipss_ick>; ++ reg = <0x4800259c 0x4>; ++ ti,enable-bit = <2>; ++}; ++ ++vpfe_fck: vpfe_fck@4800259c { ++ #clock-cells = <0>; ++ compatible = "gate-clock"; ++ clocks = <&pclk_ck>; ++ reg = <0x4800259c 0x4>; ++ bit-shift = <10>; ++}; ++ ++hsotgusb_ick: hsotgusb_ick@4800259c { ++ #clock-cells = <0>; ++ compatible = "ti,am35xx-gate-clock"; ++ clocks = <&ipss_ick>; ++ reg = <0x4800259c 0x4>; ++ ti,enable-bit = <0>; ++}; ++ ++hsotgusb_fck_am35xx: hsotgusb_fck_am35xx@4800259c { ++ #clock-cells = <0>; ++ compatible = "gate-clock"; ++ clocks = <&sys_ck>; ++ reg = <0x4800259c 0x4>; ++ bit-shift = <8>; ++}; ++ ++hecc_ck: hecc_ck@4800259c { ++ #clock-cells = <0>; ++ compatible = "ti,am35xx-gate-clock"; ++ clocks = <&sys_ck>; ++ reg = <0x4800259c 0x4>; ++ ti,enable-bit = <3>; ++}; ++ ++uart4_ick_am35xx: uart4_ick_am35xx@48004a10 { ++ #clock-cells = <0>; ++ compatible = "ti,omap3-interface-clock"; ++ clocks = <&core_l4_ick>; ++ reg = <0x48004a10 0x4>; ++ ti,enable-bit = <23>; ++}; ++ ++uart4_fck_am35xx: uart4_fck_am35xx@48004a00 { ++ #clock-cells = <0>; ++ compatible = "ti,gate-clock"; ++ clocks = <&core_48m_fck>; ++ reg = <0x48004a00 0x4>; ++ ti,enable-bit = <23>; ++}; +--- a/arch/arm/boot/dts/am4372.dtsi ++++ b/arch/arm/boot/dts/am4372.dtsi +@@ -8,6 +8,7 @@ + * kind, whether express or implied. + */ + ++#include <dt-bindings/gpio/gpio.h> + #include <dt-bindings/interrupt-controller/arm-gic.h> + + #include "skeleton.dtsi" +@@ -18,12 +19,21 @@ + + + aliases { ++ i2c0 = &i2c0; ++ i2c1 = &i2c1; ++ i2c2 = &i2c2; + serial0 = &uart0; ++ ethernet0 = &cpsw_emac0; ++ ethernet1 = &cpsw_emac1; + }; + + cpus { ++ #address-cells = <1>; ++ #size-cells = <0>; + cpu@0 { + compatible = "arm,cortex-a9"; ++ device_type = "cpu"; ++ reg = <0>; + }; + }; + +@@ -35,16 +45,124 @@ + <0x48240100 0x0100>; + }; + ++ l2-cache-controller@48242000 { ++ compatible = "arm,pl310-cache"; ++ reg = <0x48242000 0x1000>; ++ cache-unified; ++ cache-level = <2>; ++ }; ++ ++ am43xx_pinmux: pinmux@44e10800 { ++ compatible = "pinctrl-single"; ++ reg = <0x44e10800 0x31c>; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ pinctrl-single,register-width = <32>; ++ pinctrl-single,function-mask = <0xffffffff>; ++ }; ++ + ocp { + compatible = "simple-bus"; + #address-cells = <1>; + #size-cells = <1>; + ranges; ++ ti,hwmods = "l3_main"; ++ clocks = <&l3_gclk>; ++ clock-names = "fck"; ++ ++ edma: edma@49000000 { ++ compatible = "ti,edma3"; ++ ti,hwmods = "tpcc", "tptc0", "tptc1", "tptc2"; ++ reg = <0x49000000 0x10000>, ++ <0x44e10f90 0x10>; ++ interrupts = <GIC_SPI 12 IRQ_TYPE_LEVEL_HIGH>, ++ <GIC_SPI 13 IRQ_TYPE_LEVEL_HIGH>, ++ <GIC_SPI 14 IRQ_TYPE_LEVEL_HIGH>; ++ #dma-cells = <1>; ++ dma-channels = <64>; ++ ti,edma-regions = <4>; ++ ti,edma-slots = <256>; ++ }; + + uart0: serial@44e09000 { + compatible = "ti,am4372-uart","ti,omap2-uart"; + reg = <0x44e09000 0x2000>; + interrupts = <GIC_SPI 72 IRQ_TYPE_LEVEL_HIGH>; ++ ti,hwmods = "uart1"; ++ clocks = <&dpll_per_m2_div4_wkupdm_ck>; ++ clock-names = "fck"; ++ }; ++ ++ uart1: serial@48022000 { ++ compatible = "ti,am4372-uart","ti,omap2-uart"; ++ reg = <0x48022000 0x2000>; ++ interrupts = <GIC_SPI 73 IRQ_TYPE_LEVEL_HIGH>; ++ ti,hwmods = "uart2"; ++ clocks = <&dpll_per_m2_div4_ck>; ++ clock-names = "fck"; ++ status = "disabled"; ++ }; ++ ++ uart2: serial@48024000 { ++ compatible = "ti,am4372-uart","ti,omap2-uart"; ++ reg = <0x48024000 0x2000>; ++ interrupts = <GIC_SPI 74 IRQ_TYPE_LEVEL_HIGH>; ++ ti,hwmods = "uart3"; ++ clocks = <&dpll_per_m2_div4_ck>; ++ clock-names = "fck"; ++ status = "disabled"; ++ }; ++ ++ uart3: serial@481a6000 { ++ compatible = "ti,am4372-uart","ti,omap2-uart"; ++ reg = <0x481a6000 0x2000>; ++ interrupts = <GIC_SPI 44 IRQ_TYPE_LEVEL_HIGH>; ++ ti,hwmods = "uart4"; ++ clocks = <&dpll_per_m2_div4_ck>; ++ clock-names = "fck"; ++ status = "disabled"; ++ }; ++ ++ uart4: serial@481a8000 { ++ compatible = "ti,am4372-uart","ti,omap2-uart"; ++ reg = <0x481a8000 0x2000>; ++ interrupts = <GIC_SPI 45 IRQ_TYPE_LEVEL_HIGH>; ++ ti,hwmods = "uart5"; ++ clocks = <&dpll_per_m2_div4_ck>; ++ clock-names = "fck"; ++ status = "disabled"; ++ }; ++ ++ uart5: serial@481aa000 { ++ compatible = "ti,am4372-uart","ti,omap2-uart"; ++ reg = <0x481aa000 0x2000>; ++ interrupts = <GIC_SPI 46 IRQ_TYPE_LEVEL_HIGH>; ++ ti,hwmods = "uart6"; ++ clocks = <&dpll_per_m2_div4_ck>; ++ clock-names = "fck"; ++ status = "disabled"; ++ }; ++ ++ mailbox: mailbox@480C8000 { ++ compatible = "ti,omap4-mailbox"; ++ reg = <0x480C8000 0x200>; ++ interrupts = <GIC_SPI 77 IRQ_TYPE_LEVEL_HIGH>; ++ ti,hwmods = "mailbox"; ++ ti,mbox-num-users = <4>; ++ ti,mbox-num-fifos = <8>; ++ ti,mbox-names = "wkup_m3"; ++ ti,mbox-data = <0 0 0 0>; ++ }; ++ ++ qspi: qspi@47900000 { ++ compatible = "ti,am4372-qspi"; ++ reg = <0x47900000 0x100>; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ti,hwmods = "qspi"; ++ interrupts = <0 138 0x4>; ++ num-cs = <4>; ++ mmap_read; + }; + + timer1: timer@44e31000 { +@@ -52,17 +170,818 @@ + reg = <0x44e31000 0x400>; + interrupts = <GIC_SPI 67 IRQ_TYPE_LEVEL_HIGH>; + ti,timer-alwon; ++ ti,hwmods = "timer1"; ++ clocks = <&timer1_fck>; ++ clock-names = "fck"; + }; + + timer2: timer@48040000 { + compatible = "ti,am4372-timer","ti,am335x-timer"; + reg = <0x48040000 0x400>; + interrupts = <GIC_SPI 68 IRQ_TYPE_LEVEL_HIGH>; ++ ti,hwmods = "timer2"; ++ clocks = <&timer2_fck>; ++ clock-names = "fck"; ++ }; ++ ++ timer3: timer@48042000 { ++ compatible = "ti,am4372-timer","ti,am335x-timer"; ++ reg = <0x48042000 0x400>; ++ interrupts = <GIC_SPI 69 IRQ_TYPE_LEVEL_HIGH>; ++ ti,hwmods = "timer3"; ++ clocks = <&timer3_fck>; ++ clock-names = "fck"; ++ status = "disabled"; ++ }; ++ ++ timer4: timer@48044000 { ++ compatible = "ti,am4372-timer","ti,am335x-timer"; ++ reg = <0x48044000 0x400>; ++ interrupts = <GIC_SPI 92 IRQ_TYPE_LEVEL_HIGH>; ++ ti,timer-pwm; ++ ti,hwmods = "timer4"; ++ clocks = <&timer4_fck>; ++ clock-names = "fck"; ++ status = "disabled"; ++ }; ++ ++ timer5: timer@48046000 { ++ compatible = "ti,am4372-timer","ti,am335x-timer"; ++ reg = <0x48046000 0x400>; ++ interrupts = <GIC_SPI 93 IRQ_TYPE_LEVEL_HIGH>; ++ ti,timer-pwm; ++ ti,hwmods = "timer5"; ++ clocks = <&timer5_fck>; ++ clock-names = "fck"; ++ status = "disabled"; ++ }; ++ ++ timer6: timer@48048000 { ++ compatible = "ti,am4372-timer","ti,am335x-timer"; ++ reg = <0x48048000 0x400>; ++ interrupts = <GIC_SPI 94 IRQ_TYPE_LEVEL_HIGH>; ++ ti,timer-pwm; ++ ti,hwmods = "timer6"; ++ clocks = <&timer6_fck>; ++ clock-names = "fck"; ++ status = "disabled"; ++ }; ++ ++ timer7: timer@4804a000 { ++ compatible = "ti,am4372-timer","ti,am335x-timer"; ++ reg = <0x4804a000 0x400>; ++ interrupts = <GIC_SPI 95 IRQ_TYPE_LEVEL_HIGH>; ++ ti,timer-pwm; ++ ti,hwmods = "timer7"; ++ clocks = <&timer7_fck>; ++ clock-names = "fck"; ++ status = "disabled"; ++ }; ++ ++ timer8: timer@481c1000 { ++ compatible = "ti,am4372-timer","ti,am335x-timer"; ++ reg = <0x481c1000 0x400>; ++ interrupts = <GIC_SPI 131 IRQ_TYPE_LEVEL_HIGH>; ++ ti,hwmods = "timer8"; ++ clocks = <&timer8_fck>; ++ clock-names = "fck"; ++ status = "disabled"; ++ }; ++ ++ timer9: timer@4833d000 { ++ compatible = "ti,am4372-timer","ti,am335x-timer"; ++ reg = <0x4833d000 0x400>; ++ interrupts = <GIC_SPI 132 IRQ_TYPE_LEVEL_HIGH>; ++ ti,hwmods = "timer9"; ++ clocks = <&timer9_fck>; ++ clock-names = "fck"; ++ status = "disabled"; ++ }; ++ ++ timer10: timer@4833f000 { ++ compatible = "ti,am4372-timer","ti,am335x-timer"; ++ reg = <0x4833f000 0x400>; ++ interrupts = <GIC_SPI 133 IRQ_TYPE_LEVEL_HIGH>; ++ ti,hwmods = "timer10"; ++ clocks = <&timer10_fck>; ++ clock-names = "fck"; ++ status = "disabled"; ++ }; ++ ++ timer11: timer@48341000 { ++ compatible = "ti,am4372-timer","ti,am335x-timer"; ++ reg = <0x48341000 0x400>; ++ interrupts = <GIC_SPI 134 IRQ_TYPE_LEVEL_HIGH>; ++ ti,hwmods = "timer11"; ++ clocks = <&timer11_fck>; ++ clock-names = "fck"; ++ status = "disabled"; + }; + + counter32k: counter@44e86000 { + compatible = "ti,am4372-counter32k","ti,omap-counter32k"; + reg = <0x44e86000 0x40>; ++ ti,hwmods = "counter_32k"; ++ clocks = <&synctimer_32kclk>; ++ clock-names = "fck"; ++ }; ++ ++ rtc: rtc@44e3e000 { ++ compatible = "ti,am4372-rtc","ti,da830-rtc"; ++ reg = <0x44e3e000 0x1000>; ++ interrupts = <GIC_SPI 75 IRQ_TYPE_LEVEL_HIGH ++ GIC_SPI 76 IRQ_TYPE_LEVEL_HIGH>; ++ ti,hwmods = "rtc"; ++ clocks = <&clk_32768_ck>; ++ clock-names = "fck"; ++ status = "disabled"; ++ }; ++ ++ wdt@44e35000 { ++ compatible = "ti,am4372-wdt","ti,omap3-wdt"; ++ reg = <0x44e35000 0x1000>; ++ interrupts = <GIC_SPI 91 IRQ_TYPE_LEVEL_HIGH>; ++ ti,hwmods = "wd_timer2"; ++ clocks = <&wdt1_fck>; ++ clock-names = "fck"; ++ }; ++ ++ gpio0: gpio@44e07000 { ++ compatible = "ti,am4372-gpio","ti,omap4-gpio"; ++ reg = <0x44e07000 0x1000>; ++ interrupts = <GIC_SPI 96 IRQ_TYPE_LEVEL_HIGH>; ++ gpio-controller; ++ #gpio-cells = <2>; ++ interrupt-controller; ++ #interrupt-cells = <2>; ++ ti,hwmods = "gpio1"; ++ clocks = <&sys_clkin_ck>, <&gpio0_dbclk>; ++ clock-names = "fck", "dbclk"; ++ status = "disabled"; ++ }; ++ ++ gpio1: gpio@4804c000 { ++ compatible = "ti,am4372-gpio","ti,omap4-gpio"; ++ reg = <0x4804c000 0x1000>; ++ interrupts = <GIC_SPI 98 IRQ_TYPE_LEVEL_HIGH>; ++ gpio-controller; ++ #gpio-cells = <2>; ++ interrupt-controller; ++ #interrupt-cells = <2>; ++ ti,hwmods = "gpio2"; ++ clocks = <&l4ls_gclk>, <&gpio1_dbclk>; ++ clock-names = "fck", "dbclk"; ++ status = "disabled"; ++ }; ++ ++ gpio2: gpio@481ac000 { ++ compatible = "ti,am4372-gpio","ti,omap4-gpio"; ++ reg = <0x481ac000 0x1000>; ++ interrupts = <GIC_SPI 32 IRQ_TYPE_LEVEL_HIGH>; ++ gpio-controller; ++ #gpio-cells = <2>; ++ interrupt-controller; ++ #interrupt-cells = <2>; ++ ti,hwmods = "gpio3"; ++ clocks = <&l4ls_gclk>, <&gpio2_dbclk>; ++ clock-names = "fck", "dbclk"; ++ status = "disabled"; ++ }; ++ ++ gpio3: gpio@481ae000 { ++ compatible = "ti,am4372-gpio","ti,omap4-gpio"; ++ reg = <0x481ae000 0x1000>; ++ interrupts = <GIC_SPI 62 IRQ_TYPE_LEVEL_HIGH>; ++ gpio-controller; ++ #gpio-cells = <2>; ++ interrupt-controller; ++ #interrupt-cells = <2>; ++ ti,hwmods = "gpio4"; ++ clocks = <&l4ls_gclk>, <&gpio3_dbclk>; ++ clock-names = "fck", "dbclk"; ++ status = "disabled"; ++ }; ++ ++ gpio4: gpio@48320000 { ++ compatible = "ti,am4372-gpio","ti,omap4-gpio"; ++ reg = <0x48320000 0x1000>; ++ interrupts = <GIC_SPI 106 IRQ_TYPE_LEVEL_HIGH>; ++ gpio-controller; ++ #gpio-cells = <2>; ++ interrupt-controller; ++ #interrupt-cells = <2>; ++ ti,hwmods = "gpio5"; ++ clocks = <&l4ls_gclk>, <&gpio4_dbclk>; ++ clock-names = "fck", "dbclk"; ++ status = "disabled"; ++ }; ++ ++ gpio5: gpio@48322000 { ++ compatible = "ti,am4372-gpio","ti,omap4-gpio"; ++ reg = <0x48322000 0x1000>; ++ interrupts = <GIC_SPI 148 IRQ_TYPE_LEVEL_HIGH>; ++ gpio-controller; ++ #gpio-cells = <2>; ++ interrupt-controller; ++ #interrupt-cells = <2>; ++ ti,hwmods = "gpio6"; ++ clocks = <&l4ls_gclk>, <&gpio5_dbclk>; ++ clock-names = "fck", "dbclk"; ++ status = "disabled"; ++ }; ++ ++ i2c0: i2c@44e0b000 { ++ compatible = "ti,am4372-i2c","ti,omap4-i2c"; ++ reg = <0x44e0b000 0x1000>; ++ interrupts = <GIC_SPI 70 IRQ_TYPE_LEVEL_HIGH>; ++ ti,hwmods = "i2c1"; ++ clocks = <&dpll_per_m2_div4_wkupdm_ck>; ++ clock-names = "fck"; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ status = "disabled"; ++ ++ tps: tps@24 { ++ reg = <0x24>; ++ }; ++ }; ++ ++ i2c1: i2c@4802a000 { ++ compatible = "ti,am4372-i2c","ti,omap4-i2c"; ++ reg = <0x4802a000 0x1000>; ++ interrupts = <GIC_SPI 71 IRQ_TYPE_LEVEL_HIGH>; ++ ti,hwmods = "i2c2"; ++ clocks = <&dpll_per_m2_div4_ck>; ++ clock-names = "fck"; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ status = "disabled"; ++ }; ++ ++ i2c2: i2c@4819c000 { ++ compatible = "ti,am4372-i2c","ti,omap4-i2c"; ++ reg = <0x4819c000 0x1000>; ++ interrupts = <GIC_SPI 30 IRQ_TYPE_LEVEL_HIGH>; ++ ti,hwmods = "i2c3"; ++ clocks = <&dpll_per_m2_div4_ck>; ++ clock-names = "fck"; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ status = "disabled"; ++ }; ++ ++ spi0: spi@48030000 { ++ compatible = "ti,am4372-mcspi","ti,omap4-mcspi"; ++ reg = <0x48030000 0x400>; ++ interrupts = <GIC_SPI 65 IRQ_TYPE_LEVEL_HIGH>; ++ ti,hwmods = "spi0"; ++ clocks = <&dpll_per_m2_div4_ck>; ++ clock-names = "fck"; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ status = "disabled"; + }; ++ ++ mmc1: mmc@48060000 { ++ compatible = "ti,omap4-hsmmc"; ++ reg = <0x48060000 0x1000>; ++ ti,hwmods = "mmc1"; ++ clocks = <&mmc_clk>, <&clkdiv32k_ick>; ++ clock-names = "fck", "mmchsdb_fck"; ++ ti,dual-volt; ++ ti,needs-special-reset; ++ dmas = <&edma 24 ++ &edma 25>; ++ dma-names = "tx", "rx"; ++ interrupts = <GIC_SPI 64 IRQ_TYPE_LEVEL_HIGH>; ++ status = "disabled"; ++ }; ++ ++ mmc2: mmc@481d8000 { ++ compatible = "ti,omap4-hsmmc"; ++ reg = <0x481d8000 0x1000>; ++ ti,hwmods = "mmc2"; ++ clocks = <&mmc_clk>, <&clkdiv32k_ick>; ++ clock-names = "fck", "mmchsdb_fck"; ++ ti,needs-special-reset; ++ dmas = <&edma 2 ++ &edma 3>; ++ dma-names = "tx", "rx"; ++ interrupts = <GIC_SPI 28 IRQ_TYPE_LEVEL_HIGH>; ++ status = "disabled"; ++ }; ++ ++ mmc3: mmc@47810000 { ++ compatible = "ti,omap4-hsmmc"; ++ reg = <0x47810000 0x1000>; ++ ti,hwmods = "mmc3"; ++ clocks = <&mmc_clk>, <&clkdiv32k_ick>; ++ clock-names = "fck", "mmchsdb_fck"; ++ ti,needs-special-reset; ++ interrupts = <GIC_SPI 29 IRQ_TYPE_LEVEL_HIGH>; ++ status = "disabled"; ++ }; ++ ++ spi1: spi@481a0000 { ++ compatible = "ti,am4372-mcspi","ti,omap4-mcspi"; ++ reg = <0x481a0000 0x400>; ++ interrupts = <GIC_SPI 125 IRQ_TYPE_LEVEL_HIGH>; ++ ti,hwmods = "spi1"; ++ clocks = <&dpll_per_m2_div4_ck>; ++ clock-names = "fck"; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ status = "disabled"; ++ }; ++ ++ spi2: spi@481a2000 { ++ compatible = "ti,am4372-mcspi","ti,omap4-mcspi"; ++ reg = <0x481a2000 0x400>; ++ interrupts = <GIC_SPI 126 IRQ_TYPE_LEVEL_HIGH>; ++ ti,hwmods = "spi2"; ++ clocks = <&dpll_per_m2_div4_ck>; ++ clock-names = "fck"; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ status = "disabled"; ++ }; ++ ++ spi3: spi@481a4000 { ++ compatible = "ti,am4372-mcspi","ti,omap4-mcspi"; ++ reg = <0x481a4000 0x400>; ++ interrupts = <GIC_SPI 136 IRQ_TYPE_LEVEL_HIGH>; ++ ti,hwmods = "spi3"; ++ clocks = <&dpll_per_m2_div4_ck>; ++ clock-names = "fck"; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ status = "disabled"; ++ }; ++ ++ spi4: spi@48345000 { ++ compatible = "ti,am4372-mcspi","ti,omap4-mcspi"; ++ reg = <0x48345000 0x400>; ++ interrupts = <GIC_SPI 137 IRQ_TYPE_LEVEL_HIGH>; ++ ti,hwmods = "spi4"; ++ clocks = <&dpll_per_m2_div4_ck>; ++ clock-names = "fck"; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ status = "disabled"; ++ }; ++ ++ mac: ethernet@4a100000 { ++ compatible = "ti,am4372-cpsw","ti,cpsw"; ++ reg = <0x4a100000 0x800 ++ 0x4a101200 0x100>; ++ interrupts = <GIC_SPI 40 IRQ_TYPE_LEVEL_HIGH ++ GIC_SPI 41 IRQ_TYPE_LEVEL_HIGH ++ GIC_SPI 42 IRQ_TYPE_LEVEL_HIGH ++ GIC_SPI 43 IRQ_TYPE_LEVEL_HIGH>; ++ #address-cells = <1>; ++ #size-cells = <1>; ++ ti,hwmods = "cpgmac0"; ++ clocks = <&cpsw_125mhz_gclk>; ++ clock-names = "fck"; ++ cpdma_channels = <8>; ++ ale_entries = <1024>; ++ bd_ram_size = <0x2000>; ++ no_bd_ram = <0>; ++ rx_descs = <64>; ++ mac_control = <0x20>; ++ slaves = <2>; ++ active_slave = <0>; ++ cpts_clock_mult = <0x80000000>; ++ cpts_clock_shift = <29>; ++ ranges; ++ status = "disabled"; ++ ++ davinci_mdio: mdio@4a101000 { ++ compatible = "ti,am4372-mdio","ti,davinci_mdio"; ++ reg = <0x4a101000 0x100>; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ti,hwmods = "davinci_mdio"; ++ clocks = <&cpsw_125mhz_gclk>; ++ clock-names = "fck"; ++ bus_freq = <1000000>; ++ status = "disabled"; ++ }; ++ ++ cpsw_emac0: slave@4a100200 { ++ /* Filled in by U-Boot */ ++ mac-address = [ 00 00 00 00 00 00 ]; ++ }; ++ ++ cpsw_emac1: slave@4a100300 { ++ /* Filled in by U-Boot */ ++ mac-address = [ 00 00 00 00 00 00 ]; ++ }; ++ ++ phy_sel: cpsw-phy-sel@44e10650 { ++ compatible = "ti,am3352-cpsw-phy-sel"; ++ reg= <0x44e10650 0x4>; ++ reg-names = "gmii-sel"; ++ }; ++ }; ++ ++ epwmss0: epwmss@48300000 { ++ compatible = "ti,am4372-pwmss","ti,am33xx-pwmss"; ++ reg = <0x48300000 0x10>; ++ #address-cells = <1>; ++ #size-cells = <1>; ++ ranges; ++ ti,hwmods = "epwmss0"; ++ clocks = <&l4ls_gclk>; ++ clock-names = "fck"; ++ status = "disabled"; ++ ++ ecap0: ecap@48300100 { ++ compatible = "ti,am4372-ecap","ti,am33xx-ecap"; ++ reg = <0x48300100 0x80>; ++ ti,hwmods = "ecap0"; ++ clocks = <&l4ls_gclk>; ++ clock-names = "fck"; ++ status = "disabled"; ++ }; ++ ++ ehrpwm0: ehrpwm@48300200 { ++ compatible = "ti,am4372-ehrpwm","ti,am33xx-ehrpwm"; ++ reg = <0x48300200 0x80>; ++ ti,hwmods = "ehrpwm0"; ++ clocks = <&l4ls_gclk>; ++ clock-names = "fck"; ++ status = "disabled"; ++ }; ++ }; ++ ++ epwmss1: epwmss@48302000 { ++ compatible = "ti,am4372-pwmss","ti,am33xx-pwmss"; ++ reg = <0x48302000 0x10>; ++ #address-cells = <1>; ++ #size-cells = <1>; ++ ranges; ++ ti,hwmods = "epwmss1"; ++ clocks = <&l4ls_gclk>; ++ clock-names = "fck"; ++ status = "disabled"; ++ ++ ecap1: ecap@48302100 { ++ compatible = "ti,am4372-ecap","ti,am33xx-ecap"; ++ reg = <0x48302100 0x80>; ++ ti,hwmods = "ecap1"; ++ clocks = <&l4ls_gclk>; ++ clock-names = "fck"; ++ status = "disabled"; ++ }; ++ ++ ehrpwm1: ehrpwm@48302200 { ++ compatible = "ti,am4372-ehrpwm","ti,am33xx-ehrpwm"; ++ reg = <0x48302200 0x80>; ++ ti,hwmods = "ehrpwm1"; ++ clocks = <&l4ls_gclk>; ++ clock-names = "fck"; ++ status = "disabled"; ++ }; ++ }; ++ ++ epwmss2: epwmss@48304000 { ++ compatible = "ti,am4372-pwmss","ti,am33xx-pwmss"; ++ reg = <0x48304000 0x10>; ++ #address-cells = <1>; ++ #size-cells = <1>; ++ ranges; ++ ti,hwmods = "epwmss2"; ++ clocks = <&l4ls_gclk>; ++ clock-names = "fck"; ++ status = "disabled"; ++ ++ ecap2: ecap@48304100 { ++ compatible = "ti,am4372-ecap","ti,am33xx-ecap"; ++ reg = <0x48304100 0x80>; ++ ti,hwmods = "ecap2"; ++ clocks = <&l4ls_gclk>; ++ clock-names = "fck"; ++ status = "disabled"; ++ }; ++ ++ ehrpwm2: ehrpwm@48304200 { ++ compatible = "ti,am4372-ehrpwm","ti,am33xx-ehrpwm"; ++ reg = <0x48304200 0x80>; ++ ti,hwmods = "ehrpwm2"; ++ clocks = <&l4ls_gclk>; ++ clock-names = "fck"; ++ status = "disabled"; ++ }; ++ }; ++ ++ epwmss3: epwmss@48306000 { ++ compatible = "ti,am4372-pwmss","ti,am33xx-pwmss"; ++ reg = <0x48306000 0x10>; ++ #address-cells = <1>; ++ #size-cells = <1>; ++ ranges; ++ ti,hwmods = "epwmss3"; ++ clocks = <&l4ls_gclk>; ++ clock-names = "fck"; ++ status = "disabled"; ++ ++ ehrpwm3: ehrpwm@48306200 { ++ compatible = "ti,am4372-ehrpwm","ti,am33xx-ehrpwm"; ++ reg = <0x48306200 0x80>; ++ ti,hwmods = "ehrpwm3"; ++ clocks = <&l4ls_gclk>; ++ clock-names = "fck"; ++ status = "disabled"; ++ }; ++ }; ++ ++ epwmss4: epwmss@48308000 { ++ compatible = "ti,am4372-pwmss","ti,am33xx-pwmss"; ++ reg = <0x48308000 0x10>; ++ #address-cells = <1>; ++ #size-cells = <1>; ++ ranges; ++ ti,hwmods = "epwmss4"; ++ clocks = <&l4ls_gclk>; ++ clock-names = "fck"; ++ status = "disabled"; ++ ++ ehrpwm4: ehrpwm@48308200 { ++ compatible = "ti,am4372-ehrpwm","ti,am33xx-ehrpwm"; ++ reg = <0x48308200 0x80>; ++ ti,hwmods = "ehrpwm4"; ++ clocks = <&l4ls_gclk>; ++ clock-names = "fck"; ++ status = "disabled"; ++ }; ++ }; ++ ++ epwmss5: epwmss@4830a000 { ++ compatible = "ti,am4372-pwmss","ti,am33xx-pwmss"; ++ reg = <0x4830a000 0x10>; ++ #address-cells = <1>; ++ #size-cells = <1>; ++ ranges; ++ ti,hwmods = "epwmss5"; ++ clocks = <&l4ls_gclk>; ++ clock-names = "fck"; ++ status = "disabled"; ++ ++ ehrpwm5: ehrpwm@4830a200 { ++ compatible = "ti,am4372-ehrpwm","ti,am33xx-ehrpwm"; ++ reg = <0x4830a200 0x80>; ++ ti,hwmods = "ehrpwm5"; ++ clocks = <&l4ls_gclk>; ++ clock-names = "fck"; ++ status = "disabled"; ++ }; ++ }; ++ ++ wkup_m3: wkup_m3@44d00000 { ++ compatible = "ti,am4372-wkup-m3","ti,am3353-wkup-m3"; ++ reg = <0x44d00000 0x4000 /* M3 UMEM */ ++ 0x44d80000 0x2000>; /* M3 DMEM */ ++ ti,hwmods = "wkup_m3"; ++ clocks = <&sys_clkin_ck>; ++ clock-names = "fck"; ++ status = "disabled"; ++ }; ++ ++ tscadc: tscadc@44e0d000 { ++ compatible = "ti,am4372-tscadc","ti,am3359-tscadc"; ++ reg = <0x44e0d000 0x1000>; ++ ti,hwmods = "adc_tsc"; ++ clocks = <&adc_tsc_fck>; ++ clock-names = "fck"; ++ status = "disabled"; ++ }; ++ ++ ocmcram: ocmcram@40300000 { ++ compatible = "ti,am4372-ocmcram","ti,am3352-ocmcram"; ++ reg = <0x40300000 0x40000>; ++ ti,hwmods = "ocmcram"; ++ clocks = <&l3_gclk>; ++ clock-names = "fck"; ++ status = "disabled"; ++ }; ++ ++ dcan0: d_can@481cc000 { ++ compatible = "bosch,d_can"; ++ ti,hwmods = "d_can0"; ++ clocks = <&dcan0_fck>; ++ clock-names = "fck"; ++ reg = <0x481cc000 0x2000 ++ 0x44e10644 0x4>; ++ status = "disabled"; ++ }; ++ ++ dcan1: d_can@481d0000 { ++ compatible = "bosch,d_can"; ++ ti,hwmods = "d_can1"; ++ clocks = <&dcan1_fck>; ++ clock-names = "fck"; ++ reg = <0x481d0000 0x2000 ++ 0x44e10644 0x4>; ++ status = "disabled"; ++ }; ++ ++ elm: elm@48080000 { ++ compatible = "ti,am4372-elm","ti,am3352-elm"; ++ reg = <0x48080000 0x2000>; ++ ti,hwmods = "elm"; ++ clocks = <&l4ls_gclk>; ++ clock-names = "fck"; ++ status = "disabled"; ++ }; ++ ++ gpmc: gpmc@50000000 { ++ compatible = "ti,am4372-gpmc","ti,am3352-gpmc"; ++ ti,hwmods = "gpmc"; ++ clocks = <&l3s_gclk>; ++ clock-names = "fck"; ++ reg = <0x50000000 0x2000>; ++ status = "disabled"; ++ }; ++ ++ prcm: prcm@44df0000 { ++ compatible = "ti,am4372-prcm"; ++ reg = <0x44df0000 0xa000>; ++ #reset-cells = <1>; ++ }; ++ ++ rng: rng@48310000 { ++ compatible = "ti,omap4-rng"; ++ ti,hwmods = "rng"; ++ reg = <0x48310000 0x2000>; ++ interrupts = <GIC_SPI 111 IRQ_TYPE_LEVEL_HIGH>; ++ clocks = <&rng_fck>; ++ clock-names = "fck"; ++ }; ++ ++ sham: sham@53100000 { ++ compatible = "ti,omap5-sham"; ++ ti,hwmods = "sham"; ++ reg = <0x53100000 0x300>; ++ dmas = <&edma 36>; ++ dma-names = "rx"; ++ interrupts = <GIC_SPI 109 IRQ_TYPE_LEVEL_HIGH>; ++ clocks = <&l3_gclk>; ++ clock-names = "fck"; ++ }; ++ ++ aes: aes@53501000 { ++ compatible = "ti,omap4-aes"; ++ ti,hwmods = "aes"; ++ reg = <0x53501000 0xa0>; ++ interrupts = <GIC_SPI 103 IRQ_TYPE_LEVEL_HIGH>; ++ dmas = <&edma 6 ++ &edma 5>; ++ dma-names = "tx", "rx"; ++ clocks = <&aes0_fck>; ++ clock-names = "fck"; ++ }; ++ ++ des: des@53701000 { ++ compatible = "ti,omap4-des"; ++ ti,hwmods = "des"; ++ reg = <0x53701000 0xa0>; ++ interrupts = <GIC_SPI 130 IRQ_TYPE_LEVEL_HIGH>; ++ dmas = <&edma 34 ++ &edma 33>; ++ dma-names = "tx", "rx"; ++ clocks = <&l3_gclk>; ++ clock-names = "fck"; ++ }; ++ ++ am43xx_control_usb2phy1: control-phy@44e10620 { ++ compatible = "ti,control-phy-am437usb2"; ++ reg = <0x44e10620 0x4>; ++ reg-names = "power"; ++ }; ++ ++ am43xx_control_usb2phy2: control-phy@0x44e10628 { ++ compatible = "ti,control-phy-am437usb2"; ++ reg = <0x44e10628 0x4>; ++ reg-names = "power"; ++ }; ++ ++ ocp2scp0: ocp2scp@483a8000 { ++ compatible = "ti,omap-ocp2scp"; ++ #address-cells = <1>; ++ #size-cells = <1>; ++ ranges; ++ ti,hwmods = "ocp2scp0"; ++ ++ usb2_phy1: usb2phy1@483a8000 { ++ compatible = "ti,am437x-usb2"; ++ reg = <0x483a8000 0x8000>; ++ ctrl-module = <&am43xx_control_usb2phy1>; ++ clocks = <&clk_32768_ck>, ++ <&usb_otg_ss0_refclk960m>; ++ clock-names = "wkupclk", ++ "refclk"; ++ #phy-cells = <0>; ++ }; ++ ++ }; ++ ++ ocp2scp1: ocp2scp@483e8000 { ++ compatible = "ti,omap-ocp2scp"; ++ #address-cells = <1>; ++ #size-cells = <1>; ++ ranges; ++ ti,hwmods = "ocp2scp1"; ++ ++ usb2_phy2: usb2phy2@483e8000 { ++ compatible = "ti,am437x-usb2"; ++ reg = <0x483e8000 0x8000>; ++ ctrl-module = <&am43xx_control_usb2phy2>; ++ clocks = <&clk_32768_ck>, ++ <&usb_otg_ss1_refclk960m>; ++ clock-names = "wkupclk", ++ "refclk"; ++ #phy-cells = <0>; ++ }; ++ ++ }; ++ ++ dwc3_1: omap_dwc3_1@48380000 { ++ compatible = "ti,am437x-dwc3"; ++ ti,hwmods = "usb_otg_ss0"; ++ reg = <0x48380000 0x10000>; ++ interrupts = <GIC_SPI 172 IRQ_TYPE_LEVEL_HIGH>; ++ #address-cells = <1>; ++ #size-cells = <1>; ++ utmi-mode = <1>; ++ ranges; ++ usb1: usb@48390000 { ++ compatible = "synopsys,dwc3"; ++ reg = <0x48390000 0x17000>; ++ interrupts = <GIC_SPI 168 IRQ_TYPE_LEVEL_HIGH>; ++ phys = <&usb2_phy1>; ++ phy-names = "usb2-phy"; ++ maximum-speed = "high-speed"; ++ dr_mode = "peripheral"; ++ }; ++ }; ++ ++ dwc3_2: omap_dwc3_2@483c0000 { ++ compatible = "ti,am437x-dwc3"; ++ ti,hwmods = "usb_otg_ss1"; ++ reg = <0x483c0000 0x10000>; ++ interrupts = <GIC_SPI 178 IRQ_TYPE_LEVEL_HIGH>; ++ #address-cells = <1>; ++ #size-cells = <1>; ++ utmi-mode = <1>; ++ ranges; ++ usb2: usb@483d0000 { ++ compatible = "synopsys,dwc3"; ++ reg = <0x483d0000 0x17000>; ++ interrupts = <GIC_SPI 174 IRQ_TYPE_LEVEL_HIGH>; ++ phys = <&usb2_phy2>; ++ phy-names = "usb2-phy"; ++ maximum-speed = "high-speed"; ++ dr_mode = "host"; ++ }; ++ }; ++ ++ dss: dss@4832A000 { ++ compatible = "ti,omap3-dss", "simple-bus"; ++ reg = <0x4832A000 0x200>; ++ ti,hwmods = "dss_core"; ++ #address-cells = <1>; ++ #size-cells = <1>; ++ ranges; ++ ++ dispc@4832A400 { ++ compatible = "ti,omap3-dispc"; ++ reg = <0x4832A400 0x400>; ++ interrupts = <GIC_SPI 127 IRQ_TYPE_LEVEL_HIGH>; ++ ti,hwmods = "dss_dispc"; ++ }; ++ ++ dpi: encoder@0 { ++ compatible = "ti,omap3-dpi"; ++ }; ++ ++ rfbi: rfbi@4832A800 { ++ compatible = "ti,omap3-rfbi"; ++ reg = <0x4832A800 0x100>; ++ ti,hwmods = "dss_rfbi"; ++ }; ++ ++ }; ++ + }; ++ ++ clocks { ++ #address-cells = <1>; ++ #size-cells = <1>; ++ ranges; ++ /include/ "am43xx-clocks.dtsi" ++ }; ++ + }; ++ ++/include/ "tps65218.dtsi" +--- /dev/null ++++ b/arch/arm/boot/dts/am437x-gp-evm.dts +@@ -0,0 +1,238 @@ ++/* ++ * Copyright (C) 2013 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 version 2 as ++ * published by the Free Software Foundation. ++ */ ++ ++/* AM437x GP EVM */ ++ ++/dts-v1/; ++ ++#include "am43x-common-evm.dtsi" ++#include <dt-bindings/pinctrl/am43xx.h> ++ ++/ { ++ model = "TI AM437x gp EVM"; ++ compatible = "ti,am437x-gp-evm","ti,am4372","ti,am43"; ++ ++ vmmcsd_fixed: fixedregulator-sd { ++ compatible = "regulator-fixed"; ++ regulator-name = "vmmcsd_fixed"; ++ regulator-min-microvolt = <3300000>; ++ regulator-max-microvolt = <3300000>; ++ enable-active-high; ++ }; ++ ++ aliases { ++ display0 = &lcd0; ++ display1 = &hdmi0; ++ }; ++ ++ lcd0: display@0 { ++ compatible = "osddisplays,osd057T0559-34ts", "panel-dpi"; ++ video-source = <&dpi>; ++ data-lines = <24>; ++ gpios = <0 /* No Enable GPIO */ ++ &gpio0 7 GPIO_ACTIVE_LOW>; /* LCD backlight GPIO */ ++ activelow_backlight; /* LCD backlight is Active low */ ++ panel-timing { ++ clock-frequency = <33000000>; ++ hactive = <800>; ++ vactive = <480>; ++ hfront-porch = <210>; ++ hback-porch = <16>; ++ hsync-len = <30>; ++ vback-porch = <10>; ++ vfront-porch = <22>; ++ vsync-len = <13>; ++ hsync-active = <0>; ++ vsync-active = <0>; ++ de-active = <1>; ++ pixelclk-active = <1>; ++ }; ++ }; ++ ++ hdmi0: connector@1 { ++ compatible = "ti,hdmi_connector"; ++ video-source = <&sii9022>; ++ }; ++}; ++ ++&am43xx_pinmux { ++ pinctrl-names = "default"; ++ pinctrl-0 = <&dss_pinctrl>; ++ cpsw_default: cpsw_default { ++ pinctrl-single,pins = < ++ /* Slave 1 */ ++ 0x114 (PIN_OUTPUT_PULLDOWN | MUX_MODE2) /* mii1_txen.rgmii1_txen */ ++ 0x118 (PIN_INPUT_PULLDOWN | MUX_MODE2) /* mii1_rxdv.rgmii1_rxctl */ ++ 0x11c (PIN_OUTPUT_PULLDOWN | MUX_MODE2) /* mii1_txd1.rgmii1_txd3 */ ++ 0x120 (PIN_OUTPUT_PULLDOWN | MUX_MODE2) /* mii1_txd0.rgmii1_txd2 */ ++ 0x124 (PIN_OUTPUT_PULLDOWN | MUX_MODE2) /* mii1_txd1.rgmii1_txd1 */ ++ 0x128 (PIN_OUTPUT_PULLDOWN | MUX_MODE2) /* mii1_txd0.rgmii1_txd0 */ ++ 0x12c (PIN_OUTPUT_PULLDOWN | MUX_MODE2) /* mii1_txclk.rmii1_tclk */ ++ 0x130 (PIN_INPUT_PULLDOWN | MUX_MODE2) /* mii1_rxclk.rmii1_rclk */ ++ 0x134 (PIN_INPUT_PULLDOWN | MUX_MODE2) /* mii1_rxd1.rgmii1_rxd3 */ ++ 0x138 (PIN_INPUT_PULLDOWN | MUX_MODE2) /* mii1_rxd0.rgmii1_rxd2 */ ++ 0x13c (PIN_INPUT_PULLDOWN | MUX_MODE2) /* mii1_rxd1.rgmii1_rxd1 */ ++ 0x140 (PIN_INPUT_PULLDOWN | MUX_MODE2) /* mii1_rxd0.rgmii1_rxd0 */ ++ >; ++ }; ++ ++ cpsw_sleep: cpsw_sleep { ++ pinctrl-single,pins = < ++ /* Slave 1 reset value */ ++ 0x10c (PIN_INPUT_PULLDOWN | MUX_MODE7) ++ 0x114 (PIN_INPUT_PULLDOWN | MUX_MODE7) ++ 0x118 (PIN_INPUT_PULLDOWN | MUX_MODE7) ++ 0x11c (PIN_INPUT_PULLDOWN | MUX_MODE7) ++ 0x120 (PIN_INPUT_PULLDOWN | MUX_MODE7) ++ 0x124 (PIN_INPUT_PULLDOWN | MUX_MODE7) ++ 0x128 (PIN_INPUT_PULLDOWN | MUX_MODE7) ++ 0x12c (PIN_INPUT_PULLDOWN | MUX_MODE7) ++ 0x130 (PIN_INPUT_PULLDOWN | MUX_MODE7) ++ 0x134 (PIN_INPUT_PULLDOWN | MUX_MODE7) ++ 0x138 (PIN_INPUT_PULLDOWN | MUX_MODE7) ++ 0x13c (PIN_INPUT_PULLDOWN | MUX_MODE7) ++ 0x140 (PIN_INPUT_PULLDOWN | MUX_MODE7) ++ >; ++ }; ++ ++ davinci_mdio_default: davinci_mdio_default { ++ pinctrl-single,pins = < ++ /* MDIO */ ++ 0x148 (PIN_INPUT_PULLUP | SLEWCTRL_FAST | MUX_MODE0) /* mdio_data.mdio_data */ ++ 0x14c (PIN_OUTPUT_PULLUP | MUX_MODE0) /* mdio_clk.mdio_clk */ ++ >; ++ }; ++ ++ davinci_mdio_sleep: davinci_mdio_sleep { ++ pinctrl-single,pins = < ++ /* MDIO reset value */ ++ 0x148 (PIN_INPUT_PULLDOWN | MUX_MODE7) ++ 0x14c (PIN_INPUT_PULLDOWN | MUX_MODE7) ++ >; ++ }; ++ ++ mmc1_pins: pinmux_mmc1_pins { ++ pinctrl-single,pins = < ++ 0x160 (PIN_INPUT | MUX_MODE7) /* spi0_cs1.gpio0_6 */ ++ >; ++ }; ++ ++ i2c0_pins: pinmux_i2c0_pins { ++ pinctrl-single,pins = < ++ 0x188 (PIN_INPUT_PULLUP | SLEWCTRL_FAST | MUX_MODE0) /* i2c0_sda.i2c0_sda */ ++ 0x18c (PIN_INPUT_PULLUP | SLEWCTRL_FAST | MUX_MODE0) /* i2c0_scl.i2c0_scl */ ++ >; ++ }; ++ ++ i2c1_pins: i2c1_pins { ++ pinctrl-single,pins = < ++ 0x15c (PIN_INPUT_PULLUP | SLEWCTRL_FAST | MUX_MODE2) /* spi0_cs0.i2c1_scl */ ++ 0x158 (PIN_INPUT_PULLUP | SLEWCTRL_FAST | MUX_MODE2) /* spi0_d1.i2c1_sda */ ++ >; ++ }; ++ ++ dss_pinctrl: dss_pinctrl { ++ pinctrl-single,pins = < ++ 0x020 (PIN_OUTPUT_PULLUP | MUX_MODE1) /*gpmc ad 8 -> DSS DATA 23 */ ++ 0x024 (PIN_OUTPUT_PULLUP | MUX_MODE1) ++ 0x028 (PIN_OUTPUT_PULLUP | MUX_MODE1) ++ 0x02C (PIN_OUTPUT_PULLUP | MUX_MODE1) ++ 0x030 (PIN_OUTPUT_PULLUP | MUX_MODE1) ++ 0x034 (PIN_OUTPUT_PULLUP | MUX_MODE1) ++ 0x038 (PIN_OUTPUT_PULLUP | MUX_MODE1) ++ 0x03C (PIN_OUTPUT_PULLUP | MUX_MODE1) /*gpmc ad 15 -> DSS DATA 16 */ ++ 0x0A0 (PIN_OUTPUT_PULLUP | MUX_MODE0) /* DSS DATA 0 */ ++ 0x0A4 (PIN_OUTPUT_PULLUP | MUX_MODE0) ++ 0x0A8 (PIN_OUTPUT_PULLUP | MUX_MODE0) ++ 0x0AC (PIN_OUTPUT_PULLUP | MUX_MODE0) ++ 0x0B0 (PIN_OUTPUT_PULLUP | MUX_MODE0) ++ 0x0B4 (PIN_OUTPUT_PULLUP | MUX_MODE0) ++ 0x0B8 (PIN_OUTPUT_PULLUP | MUX_MODE0) ++ 0x0BC (PIN_OUTPUT_PULLUP | MUX_MODE0) ++ 0x0C0 (PIN_OUTPUT_PULLUP | MUX_MODE0) ++ 0x0C4 (PIN_OUTPUT_PULLUP | MUX_MODE0) ++ 0x0C8 (PIN_OUTPUT_PULLUP | MUX_MODE0) ++ 0x0CC (PIN_OUTPUT_PULLUP | MUX_MODE0) ++ 0x0D0 (PIN_OUTPUT_PULLUP | MUX_MODE0) ++ 0x0D4 (PIN_OUTPUT_PULLUP | MUX_MODE0) ++ 0x0D8 (PIN_OUTPUT_PULLUP | MUX_MODE0) ++ 0x0DC (PIN_OUTPUT_PULLUP | MUX_MODE0) /* DSS DATA 15 */ ++ 0x0E0 (PIN_OUTPUT_PULLUP | MUX_MODE0) /* DSS VSYNC */ ++ 0x0E4 (PIN_OUTPUT_PULLUP | MUX_MODE0) /* DSS HSYNC */ ++ 0x0E8 (PIN_OUTPUT_PULLUP | MUX_MODE0) /* DSS PCLK */ ++ 0x0EC (PIN_OUTPUT_PULLUP | MUX_MODE0) /* DSS AC BIAS EN */ ++ 0x238 (PIN_OUTPUT_PULLUP | MUX_MODE7) /* GPIO 5_8 to select LCD / HDMI */ ++ 0x164 (PIN_OUTPUT_PULLUP | MUX_MODE7) /* ECAP0_IN_PWM0_OUT -> GPIO 0_7 BACKLIGHT */ ++ >; ++ }; ++}; ++ ++&rtc { ++ status = "okay"; ++}; ++ ++&gpio0 { ++ status = "okay"; ++}; ++ ++&gpio5 { ++ status = "okay"; ++}; ++ ++&mac { ++ pinctrl-names = "default", "sleep"; ++ pinctrl-0 = <&cpsw_default>; ++ pinctrl-1 = <&cpsw_sleep>; ++ status = "okay"; ++}; ++ ++&davinci_mdio { ++ pinctrl-names = "default", "sleep"; ++ pinctrl-0 = <&davinci_mdio_default>; ++ pinctrl-1 = <&davinci_mdio_sleep>; ++ status = "okay"; ++}; ++ ++&cpsw_emac0 { ++ phy_id = <&davinci_mdio>, <0>; ++ phy-mode = "rgmii"; ++}; ++ ++&cpsw_emac1 { ++ phy_id = <&davinci_mdio>, <1>; ++ phy-mode = "rgmii"; ++}; ++ ++&mmc1 { ++ status = "okay"; ++ vmmc-supply = <&vmmcsd_fixed>; ++ bus-width = <4>; ++ pinctrl-names = "default"; ++ pinctrl-0 = <&mmc1_pins>; ++ cd-gpios = <&gpio0 6 GPIO_ACTIVE_HIGH>; ++}; ++ ++&i2c0 { ++ status = "okay"; ++ pinctrl-names = "default"; ++ pinctrl-0 = <&i2c0_pins>; ++}; ++ ++&i2c1 { ++ status = "okay"; ++ pinctrl-names = "default"; ++ pinctrl-0 = <&i2c1_pins>; ++ ++ sii9022: sii9022@3b { ++ compatible = "sii,sii9022"; ++ reg = <0x3b>; ++ reset-gpio = <&gpio5 8 GPIO_ACTIVE_LOW>;/* 'SelLCDorHDMI' Gpio, LOW to select HDMI */ ++ video-source = <&dpi>; ++ data-lines = <24>; ++ }; ++}; +--- /dev/null ++++ b/arch/arm/boot/dts/am43x-common-evm.dtsi +@@ -0,0 +1,9 @@ ++/* ++ * Copyright (C) 2013 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 version 2 as ++ * published by the Free Software Foundation. ++ */ ++ ++#include "am4372.dtsi" +--- a/arch/arm/boot/dts/am43x-epos-evm.dts ++++ b/arch/arm/boot/dts/am43x-epos-evm.dts +@@ -10,9 +10,289 @@ + + /dts-v1/; + +-#include "am4372.dtsi" ++#include "am43x-common-evm.dtsi" ++#include <dt-bindings/pinctrl/am43xx.h> + + / { + model = "TI AM43x EPOS EVM"; + compatible = "ti,am43x-epos-evm","ti,am4372","ti,am43"; ++ ++ vmmcsd_fixed: fixedregulator-sd { ++ compatible = "regulator-fixed"; ++ regulator-name = "vmmcsd_fixed"; ++ regulator-min-microvolt = <3300000>; ++ regulator-max-microvolt = <3300000>; ++ enable-active-high; ++ }; ++ ++ aliases { ++ display0 = &lcd0; ++ display1 = &hdmi0; ++ }; ++ ++ lcd0: display@0 { ++ compatible = "osddisplays,osd057T0559-34ts", "panel-dpi"; ++ video-source = <&dpi>; ++ data-lines = <24>; ++ gpios = <0 /* No Enable GPIO */ ++ &gpio0 7 GPIO_ACTIVE_LOW>; /* LCD backlight GPIO */ ++ panel-timing { ++ clock-frequency = <33000000>; ++ hactive = <800>; ++ vactive = <480>; ++ hfront-porch = <210>; ++ hback-porch = <16>; ++ hsync-len = <30>; ++ vback-porch = <10>; ++ vfront-porch = <22>; ++ vsync-len = <13>; ++ hsync-active = <0>; ++ vsync-active = <0>; ++ de-active = <1>; ++ pixelclk-active = <1>; ++ }; ++ }; ++ ++ hdmi0: connector@1 { ++ compatible = "ti,hdmi_connector"; ++ video-source = <&sii9022>; ++ }; ++}; ++ ++&am43xx_pinmux { ++ pinctrl-names = "default"; ++ pinctrl-0 = <&dss_pinctrl>; ++ cpsw_default: cpsw_default { ++ pinctrl-single,pins = < ++ /* Slave 1 */ ++ 0x10c (PIN_INPUT_PULLDOWN | MUX_MODE1) /* mii1_crs.rmii1_crs */ ++ 0x110 (PIN_INPUT_PULLDOWN | MUX_MODE1) /* mii1_rxerr.rmii1_rxerr */ ++ 0x114 (PIN_OUTPUT_PULLDOWN | MUX_MODE1) /* mii1_txen.rmii1_txen */ ++ 0x118 (PIN_INPUT_PULLDOWN | MUX_MODE1) /* mii1_rxdv.rmii1_rxdv */ ++ 0x124 (PIN_OUTPUT_PULLDOWN | MUX_MODE1) /* mii1_txd1.rmii1_txd1 */ ++ 0x128 (PIN_OUTPUT_PULLDOWN | MUX_MODE1) /* mii1_txd0.rmii1_txd0 */ ++ 0x13c (PIN_INPUT_PULLDOWN | MUX_MODE1) /* mii1_rxd1.rmii1_rxd1 */ ++ 0x140 (PIN_INPUT_PULLDOWN | MUX_MODE1) /* mii1_rxd0.rmii1_rxd0 */ ++ 0x144 (PIN_INPUT_PULLDOWN | MUX_MODE0) /* rmii1_refclk.rmii1_refclk */ ++ >; ++ }; ++ ++ cpsw_sleep: cpsw_sleep { ++ pinctrl-single,pins = < ++ /* Slave 1 reset value */ ++ 0x10c (PIN_INPUT_PULLDOWN | MUX_MODE7) ++ 0x110 (PIN_INPUT_PULLDOWN | MUX_MODE7) ++ 0x114 (PIN_INPUT_PULLDOWN | MUX_MODE7) ++ 0x118 (PIN_INPUT_PULLDOWN | MUX_MODE7) ++ 0x124 (PIN_INPUT_PULLDOWN | MUX_MODE7) ++ 0x128 (PIN_INPUT_PULLDOWN | MUX_MODE7) ++ 0x13c (PIN_INPUT_PULLDOWN | MUX_MODE7) ++ 0x140 (PIN_INPUT_PULLDOWN | MUX_MODE7) ++ 0x144 (PIN_INPUT_PULLDOWN | MUX_MODE7) ++ >; ++ }; ++ ++ davinci_mdio_default: davinci_mdio_default { ++ pinctrl-single,pins = < ++ /* MDIO */ ++ 0x148 (PIN_INPUT_PULLUP | SLEWCTRL_FAST | MUX_MODE0) /* mdio_data.mdio_data */ ++ 0x14c (PIN_OUTPUT_PULLUP | MUX_MODE0) /* mdio_clk.mdio_clk */ ++ >; ++ }; ++ ++ davinci_mdio_sleep: davinci_mdio_sleep { ++ pinctrl-single,pins = < ++ /* MDIO reset value */ ++ 0x148 (PIN_INPUT_PULLDOWN | MUX_MODE7) ++ 0x14c (PIN_INPUT_PULLDOWN | MUX_MODE7) ++ >; ++ }; ++ ++ mmc1_pins: pinmux_mmc1_pins { ++ pinctrl-single,pins = < ++ 0x160 (PIN_INPUT | MUX_MODE7) /* spi0_cs1.gpio0_6 */ ++ >; ++ }; ++ ++ i2c0_pins: pinmux_i2c0_pins { ++ pinctrl-single,pins = < ++ 0x188 (PIN_INPUT_PULLUP | SLEWCTRL_FAST | MUX_MODE0) /* i2c0_sda.i2c0_sda */ ++ 0x18c (PIN_INPUT_PULLUP | SLEWCTRL_FAST | MUX_MODE0) /* i2c0_scl.i2c0_scl */ ++ >; ++ }; ++ ++ i2c2_pins: pinmux_i2c2_pins { ++ pinctrl-single,pins = < ++ 0x1c0 (PIN_INPUT_PULLUP | SLEWCTRL_FAST | MUX_MODE0) /* i2c2_sda.i2c2_sda */ ++ 0x1c4 (PIN_INPUT_PULLUP | SLEWCTRL_FAST | MUX_MODE0) /* i2c2_scl.i2c2_scl */ ++ >; ++ }; ++ ++ spi0_pins: pinmux_spi0_pins { ++ pinctrl-single,pins = < ++ 0x150 (PIN_INPUT | MUX_MODE0) /* spi0_clk.spi0_clk */ ++ 0x154 (PIN_OUTPUT | MUX_MODE0) /* spi0_d0.spi0_d0 */ ++ 0x158 (PIN_INPUT | MUX_MODE0) /* spi0_d1.spi0_d1 */ ++ 0x15c (PIN_OUTPUT | MUX_MODE0) /* spi0_cs0.spi0_cs0 */ ++ >; ++ }; ++ ++ spi1_pins: pinmux_spi1_pins { ++ pinctrl-single,pins = < ++ 0x190 (PIN_INPUT | MUX_MODE3) /* mcasp0_aclkx.spi1_clk */ ++ 0x194 (PIN_OUTPUT | MUX_MODE3) /* mcasp0_fsx.spi1_d0 */ ++ 0x198 (PIN_INPUT | MUX_MODE3) /* mcasp0_axr0.spi1_d1 */ ++ 0x19c (PIN_OUTPUT | MUX_MODE3) /* mcasp0_ahclkr.spi1_cs0 */ ++ >; ++ }; ++ ++ pixcir_ts_pins: pixcir_ts_pins { ++ pinctrl-single,pins = < ++ 0x48 (PIN_INPUT_PULLUP | MUX_MODE7) /* gpmc_a1.gpio1_17 */ ++ >; ++ }; ++ ++ dss_pinctrl: dss_pinctrl { ++ pinctrl-single,pins = < ++ 0x020 (PIN_OUTPUT_PULLUP | MUX_MODE1) /*gpmc ad 8 -> DSS DATA 23 */ ++ 0x024 (PIN_OUTPUT_PULLUP | MUX_MODE1) ++ 0x028 (PIN_OUTPUT_PULLUP | MUX_MODE1) ++ 0x02C (PIN_OUTPUT_PULLUP | MUX_MODE1) ++ 0x030 (PIN_OUTPUT_PULLUP | MUX_MODE1) ++ 0x034 (PIN_OUTPUT_PULLUP | MUX_MODE1) ++ 0x038 (PIN_OUTPUT_PULLUP | MUX_MODE1) ++ 0x03C (PIN_OUTPUT_PULLUP | MUX_MODE1) /*gpmc ad 15 -> DSS DATA 16 */ ++ 0x0A0 (PIN_OUTPUT_PULLUP | MUX_MODE0) /* DSS DATA 0 */ ++ 0x0A4 (PIN_OUTPUT_PULLUP | MUX_MODE0) ++ 0x0A8 (PIN_OUTPUT_PULLUP | MUX_MODE0) ++ 0x0AC (PIN_OUTPUT_PULLUP | MUX_MODE0) ++ 0x0B0 (PIN_OUTPUT_PULLUP | MUX_MODE0) ++ 0x0B4 (PIN_OUTPUT_PULLUP | MUX_MODE0) ++ 0x0B8 (PIN_OUTPUT_PULLUP | MUX_MODE0) ++ 0x0BC (PIN_OUTPUT_PULLUP | MUX_MODE0) ++ 0x0C0 (PIN_OUTPUT_PULLUP | MUX_MODE0) ++ 0x0C4 (PIN_OUTPUT_PULLUP | MUX_MODE0) ++ 0x0C8 (PIN_OUTPUT_PULLUP | MUX_MODE0) ++ 0x0CC (PIN_OUTPUT_PULLUP | MUX_MODE0) ++ 0x0D0 (PIN_OUTPUT_PULLUP | MUX_MODE0) ++ 0x0D4 (PIN_OUTPUT_PULLUP | MUX_MODE0) ++ 0x0D8 (PIN_OUTPUT_PULLUP | MUX_MODE0) ++ 0x0DC (PIN_OUTPUT_PULLUP | MUX_MODE0) /* DSS DATA 15 */ ++ 0x0E0 (PIN_OUTPUT_PULLUP | MUX_MODE0) /* DSS VSYNC */ ++ 0x0E4 (PIN_OUTPUT_PULLUP | MUX_MODE0) /* DSS HSYNC */ ++ 0x0E8 (PIN_OUTPUT_PULLUP | MUX_MODE0) /* DSS PCLK */ ++ 0x0EC (PIN_OUTPUT_PULLUP | MUX_MODE0) /* DSS AC BIAS EN */ ++ 0x08C (PIN_OUTPUT_PULLUP | MUX_MODE7) /* GPMC CLK -> GPIO 2_1 to select LCD / HDMI */ ++ 0x164 (PIN_OUTPUT_PULLUP | MUX_MODE7) /* ECAP0_IN_PWM0_OUT -> GPIO 0_7 BACKLIGHT */ ++ >; ++ }; ++}; ++ ++&gpio0 { ++ status = "okay"; ++}; ++ ++&gpio1 { ++ status = "okay"; ++}; ++ ++&gpio2 { ++ status = "okay"; ++}; ++ ++&qspi { ++ spi-max-frequency = <48000000>; ++ m25p80@0 { ++ compatible = "mx66l51235l"; ++ spi-max-frequency = <48000000>; ++ reg = <0>; ++ spi-cpol; ++ spi-cpha; ++ tx-nbits = <1>; ++ rx-nbits = <4>; ++ }; ++}; ++ ++&mac { ++ pinctrl-names = "default", "sleep"; ++ pinctrl-0 = <&cpsw_default>; ++ pinctrl-1 = <&cpsw_sleep>; ++ status = "okay"; ++}; ++ ++&davinci_mdio { ++ pinctrl-names = "default", "sleep"; ++ pinctrl-0 = <&davinci_mdio_default>; ++ pinctrl-1 = <&davinci_mdio_sleep>; ++ status = "okay"; ++}; ++ ++&cpsw_emac0 { ++ phy_id = <&davinci_mdio>, <16>; ++ phy-mode = "rmii"; ++}; ++ ++&cpsw_emac1 { ++ phy_id = <&davinci_mdio>, <1>; ++ phy-mode = "rmii"; ++}; ++ ++&phy_sel { ++ rmii-clock-ext; ++}; ++ ++&mmc1 { ++ status = "okay"; ++ vmmc-supply = <&vmmcsd_fixed>; ++ bus-width = <4>; ++ pinctrl-names = "default"; ++ pinctrl-0 = <&mmc1_pins>; ++ cd-gpios = <&gpio0 6 GPIO_ACTIVE_HIGH>; ++}; ++ ++&i2c0 { ++ pinctrl-names = "default"; ++ pinctrl-0 = <&i2c0_pins>; ++ status = "okay"; ++ clock-frequency = <400000>; ++ ++ pixcir_ts@5c { ++ compatible = "pixcir,pixcir_tangoc"; ++ pinctrl-names = "default"; ++ pinctrl-0 = <&pixcir_ts_pins>; ++ reg = <0x5c>; ++ interrupt-parent = <&gpio1>; ++ interrupts = <17 0>; ++ ++ attb-gpio = <&gpio1 17 GPIO_ACTIVE_HIGH>; ++ ++ x-size = <1024>; ++ y-size = <600>; ++ }; ++}; ++ ++&i2c2 { ++ pinctrl-names = "default"; ++ pinctrl-0 = <&i2c2_pins>; ++ status = "okay"; ++ ++ sii9022: sii9022@3b { ++ compatible = "sii,sii9022"; ++ reg = <0x3b>; ++ reset-gpio = <&gpio2 1 GPIO_ACTIVE_LOW>;/* 65'SelLCDorHDMI' Gpio, LOW to select HDMI */ ++ video-source = <&dpi>; ++ data-lines = <24>; ++ }; ++}; ++ ++&spi0 { ++ pinctrl-names = "default"; ++ pinctrl-0 = <&spi0_pins>; ++ status = "okay"; ++}; ++ ++&spi1 { ++ pinctrl-names = "default"; ++ pinctrl-0 = <&spi1_pins>; ++ status = "okay"; + }; +--- /dev/null ++++ b/arch/arm/boot/dts/am43xx-clocks.dtsi +@@ -0,0 +1,735 @@ ++/* ++ * Device Tree Source for AM43xx clock data ++ * ++ * Copyright (C) 2013 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. ++ */ ++ ++clk_32768_ck: clk_32768_ck { ++ #clock-cells = <0>; ++ compatible = "fixed-clock"; ++ clock-frequency = <32768>; ++}; ++ ++clk_rc32k_ck: clk_rc32k_ck { ++ #clock-cells = <0>; ++ compatible = "fixed-clock"; ++ clock-frequency = <32768>; ++}; ++ ++virt_19200000_ck: virt_19200000_ck { ++ #clock-cells = <0>; ++ compatible = "fixed-clock"; ++ clock-frequency = <19200000>; ++}; ++ ++virt_24000000_ck: virt_24000000_ck { ++ #clock-cells = <0>; ++ compatible = "fixed-clock"; ++ clock-frequency = <24000000>; ++}; ++ ++virt_25000000_ck: virt_25000000_ck { ++ #clock-cells = <0>; ++ compatible = "fixed-clock"; ++ clock-frequency = <25000000>; ++}; ++ ++virt_26000000_ck: virt_26000000_ck { ++ #clock-cells = <0>; ++ compatible = "fixed-clock"; ++ clock-frequency = <26000000>; ++}; ++ ++crystal_freq_sel_ck: crystal_freq_sel_ck@44e10040 { ++ #clock-cells = <0>; ++ compatible = "mux-clock"; ++ clocks = <&virt_19200000_ck>, <&virt_24000000_ck>, <&virt_25000000_ck>, <&virt_26000000_ck>; ++ bit-shift = <29>; ++ reg = <0x44e10040 0x4>; ++ bit-mask = <0x3>; ++}; ++ ++sysboot_freq_sel_ck: sysboot_freq_sel_ck@44e10040 { ++ #clock-cells = <0>; ++ compatible = "mux-clock"; ++ clocks = <&virt_19200000_ck>, <&virt_24000000_ck>, <&virt_25000000_ck>, <&virt_26000000_ck>; ++ bit-shift = <22>; ++ reg = <0x44e10040 0x4>; ++ bit-mask = <0x3>; ++}; ++ ++sys_clkin_ck: sys_clkin_ck@44e10040 { ++ #clock-cells = <0>; ++ compatible = "mux-clock"; ++ clocks = <&sysboot_freq_sel_ck>, <&crystal_freq_sel_ck>; ++ bit-shift = <31>; ++ reg = <0x44e10040 0x4>; ++ bit-mask = <0x1>; ++}; ++ ++tclkin_ck: tclkin_ck { ++ #clock-cells = <0>; ++ compatible = "fixed-clock"; ++ clock-frequency = <26000000>; ++}; ++ ++dpll_core_ck: dpll_core_ck@44df2d20 { ++ #clock-cells = <0>; ++ compatible = "ti,omap4-dpll-core-clock"; ++ clocks = <&sys_clkin_ck>, <&sys_clkin_ck>; ++ reg = <0x44df2d20 0x4>, <0x44df2d24 0x4>, <0x44df2d2c 0x4>; ++ reg-names = "control", "idlest", "mult-div1"; ++}; ++ ++dpll_core_x2_ck: dpll_core_x2_ck { ++ #clock-cells = <0>; ++ compatible = "ti,omap4-dpll-x2-clock"; ++ clocks = <&dpll_core_ck>; ++}; ++ ++dpll_core_m4_ck: dpll_core_m4_ck@44df2d38 { ++ #clock-cells = <0>; ++ compatible = "ti,divider-clock"; ++ clocks = <&dpll_core_x2_ck>; ++ ti,autoidle-shift = <8>; ++ reg = <0x44df2d38 0x4>; ++ bit-mask = <0x1f>; ++ index-starts-at-one; ++ ti,autoidle-low; ++}; ++ ++dpll_core_m5_ck: dpll_core_m5_ck@44df2d3c { ++ #clock-cells = <0>; ++ compatible = "ti,divider-clock"; ++ clocks = <&dpll_core_x2_ck>; ++ ti,autoidle-shift = <8>; ++ reg = <0x44df2d3c 0x4>; ++ bit-mask = <0x1f>; ++ index-starts-at-one; ++ ti,autoidle-low; ++}; ++ ++dpll_core_m6_ck: dpll_core_m6_ck@44df2d40 { ++ #clock-cells = <0>; ++ compatible = "ti,divider-clock"; ++ clocks = <&dpll_core_x2_ck>; ++ ti,autoidle-shift = <8>; ++ reg = <0x44df2d40 0x4>; ++ bit-mask = <0x1f>; ++ index-starts-at-one; ++ ti,autoidle-low; ++}; ++ ++dpll_mpu_ck: dpll_mpu_ck@44df2d60 { ++ #clock-cells = <0>; ++ compatible = "ti,omap4-dpll-clock"; ++ clocks = <&sys_clkin_ck>, <&sys_clkin_ck>; ++ reg = <0x44df2d60 0x4>, <0x44df2d64 0x4>, <0x44df2d6c 0x4>; ++ reg-names = "control", "idlest", "mult-div1"; ++}; ++ ++dpll_mpu_m2_ck: dpll_mpu_m2_ck@44df2d70 { ++ #clock-cells = <0>; ++ compatible = "ti,divider-clock"; ++ clocks = <&dpll_mpu_ck>; ++ ti,autoidle-shift = <8>; ++ reg = <0x44df2d70 0x4>; ++ bit-mask = <0x1f>; ++ index-starts-at-one; ++ ti,autoidle-low; ++}; ++ ++dpll_ddr_ck: dpll_ddr_ck@44df2da0 { ++ #clock-cells = <0>; ++ compatible = "ti,omap4-dpll-clock"; ++ clocks = <&sys_clkin_ck>, <&sys_clkin_ck>; ++ reg = <0x44df2da0 0x4>, <0x44df2da4 0x4>, <0x44df2dac 0x4>; ++ reg-names = "control", "idlest", "mult-div1"; ++}; ++ ++dpll_ddr_m2_ck: dpll_ddr_m2_ck@44df2db0 { ++ #clock-cells = <0>; ++ compatible = "ti,divider-clock"; ++ clocks = <&dpll_ddr_ck>; ++ ti,autoidle-shift = <8>; ++ reg = <0x44df2db0 0x4>; ++ bit-mask = <0x1f>; ++ index-starts-at-one; ++ ti,autoidle-low; ++}; ++ ++dpll_disp_ck: dpll_disp_ck@44df2e20 { ++ #clock-cells = <0>; ++ compatible = "ti,omap4-dpll-clock"; ++ clocks = <&sys_clkin_ck>, <&sys_clkin_ck>; ++ reg = <0x44df2e20 0x4>, <0x44df2e24 0x4>, <0x44df2e2c 0x4>; ++ reg-names = "control", "idlest", "mult-div1"; ++}; ++ ++dpll_disp_m2_ck: dpll_disp_m2_ck@44df2e30 { ++ #clock-cells = <0>; ++ compatible = "ti,divider-clock"; ++ clocks = <&dpll_disp_ck>; ++ ti,autoidle-shift = <8>; ++ reg = <0x44df2e30 0x4>; ++ bit-mask = <0x1f>; ++ index-starts-at-one; ++ ti,autoidle-low; ++}; ++ ++dpll_per_ck: dpll_per_ck@44df2de0 { ++ #clock-cells = <0>; ++ compatible = "ti,omap4-dpll-j-type-clock"; ++ clocks = <&sys_clkin_ck>, <&sys_clkin_ck>; ++ reg = <0x44df2de0 0x4>, <0x44df2de4 0x4>, <0x44df2dec 0x4>; ++ reg-names = "control", "idlest", "mult-div1"; ++}; ++ ++dpll_per_m2_ck: dpll_per_m2_ck@44df2df0 { ++ #clock-cells = <0>; ++ compatible = "ti,divider-clock"; ++ clocks = <&dpll_per_ck>; ++ ti,autoidle-shift = <8>; ++ reg = <0x44df2df0 0x4>; ++ bit-mask = <0x7f>; ++ index-starts-at-one; ++ ti,autoidle-low; ++}; ++ ++dpll_per_m2_div4_wkupdm_ck: dpll_per_m2_div4_wkupdm_ck { ++ #clock-cells = <0>; ++ compatible = "fixed-factor-clock"; ++ clocks = <&dpll_per_m2_ck>; ++ clock-mult = <1>; ++ clock-div = <4>; ++}; ++ ++dpll_per_m2_div4_ck: dpll_per_m2_div4_ck { ++ #clock-cells = <0>; ++ compatible = "fixed-factor-clock"; ++ clocks = <&dpll_per_m2_ck>; ++ clock-mult = <1>; ++ clock-div = <4>; ++}; ++ ++adc_tsc_fck: adc_tsc_fck { ++ #clock-cells = <0>; ++ compatible = "fixed-factor-clock"; ++ clocks = <&sys_clkin_ck>; ++ clock-mult = <1>; ++ clock-div = <1>; ++}; ++ ++clk_24mhz: clk_24mhz { ++ #clock-cells = <0>; ++ compatible = "fixed-factor-clock"; ++ clocks = <&dpll_per_m2_ck>; ++ clock-mult = <1>; ++ clock-div = <8>; ++}; ++ ++clkdiv32k_ck: clkdiv32k_ck { ++ #clock-cells = <0>; ++ compatible = "fixed-factor-clock"; ++ clocks = <&clk_24mhz>; ++ clock-mult = <1>; ++ clock-div = <732>; ++}; ++ ++clkdiv32k_ick: clkdiv32k_ick@44df2a38 { ++ #clock-cells = <0>; ++ compatible = "gate-clock"; ++ clocks = <&clkdiv32k_ck>; ++ bit-shift = <8>; ++ reg = <0x44df2a38 0x4>; ++}; ++ ++dcan0_fck: dcan0_fck { ++ #clock-cells = <0>; ++ compatible = "fixed-factor-clock"; ++ clocks = <&sys_clkin_ck>; ++ clock-mult = <1>; ++ clock-div = <1>; ++}; ++ ++dcan1_fck: dcan1_fck { ++ #clock-cells = <0>; ++ compatible = "fixed-factor-clock"; ++ clocks = <&sys_clkin_ck>; ++ clock-mult = <1>; ++ clock-div = <1>; ++}; ++ ++sysclk_div: sysclk_div { ++ #clock-cells = <0>; ++ compatible = "fixed-factor-clock"; ++ clocks = <&dpll_core_m4_ck>; ++ clock-mult = <1>; ++ clock-div = <1>; ++}; ++ ++pruss_ocp_gclk: pruss_ocp_gclk@44df4248 { ++ #clock-cells = <0>; ++ compatible = "mux-clock"; ++ clocks = <&sysclk_div>, <&dpll_disp_m2_ck>; ++ reg = <0x44df4248 0x4>; ++ bit-mask = <0x1>; ++}; ++ ++mcasp0_fck: mcasp0_fck { ++ #clock-cells = <0>; ++ compatible = "fixed-factor-clock"; ++ clocks = <&sys_clkin_ck>; ++ clock-mult = <1>; ++ clock-div = <1>; ++}; ++ ++mcasp1_fck: mcasp1_fck { ++ #clock-cells = <0>; ++ compatible = "fixed-factor-clock"; ++ clocks = <&sys_clkin_ck>; ++ clock-mult = <1>; ++ clock-div = <1>; ++}; ++ ++smartreflex0_fck: smartreflex0_fck { ++ #clock-cells = <0>; ++ compatible = "fixed-factor-clock"; ++ clocks = <&sys_clkin_ck>; ++ clock-mult = <1>; ++ clock-div = <1>; ++}; ++ ++smartreflex1_fck: smartreflex1_fck { ++ #clock-cells = <0>; ++ compatible = "fixed-factor-clock"; ++ clocks = <&sys_clkin_ck>; ++ clock-mult = <1>; ++ clock-div = <1>; ++}; ++ ++sha0_fck: sha0_fck { ++ #clock-cells = <0>; ++ compatible = "fixed-factor-clock"; ++ clocks = <&sys_clkin_ck>; ++ clock-mult = <1>; ++ clock-div = <1>; ++}; ++ ++rng_fck: rng_fck { ++ #clock-cells = <0>; ++ compatible = "fixed-factor-clock"; ++ clocks = <&sys_clkin_ck>; ++ clock-mult = <1>; ++ clock-div = <1>; ++}; ++ ++aes0_fck: aes0_fck { ++ #clock-cells = <0>; ++ compatible = "fixed-factor-clock"; ++ clocks = <&sys_clkin_ck>; ++ clock-mult = <1>; ++ clock-div = <1>; ++}; ++ ++clk_32k_tpm_ck: clk_32k_tpm_ck { ++ #clock-cells = <0>; ++ compatible = "fixed-clock"; ++ clock-frequency = <32768>; ++}; ++ ++timer1_fck: timer1_fck@44df4200 { ++ #clock-cells = <0>; ++ compatible = "mux-clock"; ++ clocks = <&sys_clkin_ck>, <&clkdiv32k_ick>, <&tclkin_ck>, <&clk_rc32k_ck>, <&clk_32768_ck>, <&clk_32k_tpm_ck>; ++ reg = <0x44df4200 0x4>; ++ bit-mask = <0x7>; ++}; ++ ++timer2_fck: timer2_fck@44df4204 { ++ #clock-cells = <0>; ++ compatible = "mux-clock"; ++ clocks = <&tclkin_ck>, <&sys_clkin_ck>, <&clkdiv32k_ick>; ++ reg = <0x44df4204 0x4>; ++ bit-mask = <0x3>; ++}; ++ ++timer3_fck: timer3_fck@44df4208 { ++ #clock-cells = <0>; ++ compatible = "mux-clock"; ++ clocks = <&tclkin_ck>, <&sys_clkin_ck>, <&clkdiv32k_ick>; ++ reg = <0x44df4208 0x4>; ++ bit-mask = <0x3>; ++}; ++ ++timer4_fck: timer4_fck@44df420c { ++ #clock-cells = <0>; ++ compatible = "mux-clock"; ++ clocks = <&tclkin_ck>, <&sys_clkin_ck>, <&clkdiv32k_ick>; ++ reg = <0x44df420c 0x4>; ++ bit-mask = <0x3>; ++}; ++ ++timer5_fck: timer5_fck@44df4210 { ++ #clock-cells = <0>; ++ compatible = "mux-clock"; ++ clocks = <&tclkin_ck>, <&sys_clkin_ck>, <&clkdiv32k_ick>; ++ reg = <0x44df4210 0x4>; ++ bit-mask = <0x3>; ++}; ++ ++timer6_fck: timer6_fck@44df4214 { ++ #clock-cells = <0>; ++ compatible = "mux-clock"; ++ clocks = <&tclkin_ck>, <&sys_clkin_ck>, <&clkdiv32k_ick>; ++ reg = <0x44df4214 0x4>; ++ bit-mask = <0x3>; ++}; ++ ++timer7_fck: timer7_fck@44df4218 { ++ #clock-cells = <0>; ++ compatible = "mux-clock"; ++ clocks = <&tclkin_ck>, <&sys_clkin_ck>, <&clkdiv32k_ick>; ++ reg = <0x44df4218 0x4>; ++ bit-mask = <0x3>; ++}; ++ ++wdt1_fck: wdt1_fck@44df422c { ++ #clock-cells = <0>; ++ compatible = "mux-clock"; ++ clocks = <&clk_rc32k_ck>, <&clkdiv32k_ick>; ++ reg = <0x44df422c 0x4>; ++ bit-mask = <0x1>; ++}; ++ ++l3_gclk: l3_gclk { ++ #clock-cells = <0>; ++ compatible = "fixed-factor-clock"; ++ clocks = <&dpll_core_m4_ck>; ++ clock-mult = <1>; ++ clock-div = <1>; ++}; ++ ++dpll_core_m4_div2_ck: dpll_core_m4_div2_ck { ++ #clock-cells = <0>; ++ compatible = "fixed-factor-clock"; ++ clocks = <&sysclk_div>; ++ clock-mult = <1>; ++ clock-div = <2>; ++}; ++ ++l4hs_gclk: l4hs_gclk { ++ #clock-cells = <0>; ++ compatible = "fixed-factor-clock"; ++ clocks = <&dpll_core_m4_ck>; ++ clock-mult = <1>; ++ clock-div = <1>; ++}; ++ ++l3s_gclk: l3s_gclk { ++ #clock-cells = <0>; ++ compatible = "fixed-factor-clock"; ++ clocks = <&dpll_core_m4_div2_ck>; ++ clock-mult = <1>; ++ clock-div = <1>; ++}; ++ ++l4ls_gclk: l4ls_gclk { ++ #clock-cells = <0>; ++ compatible = "fixed-factor-clock"; ++ clocks = <&dpll_core_m4_div2_ck>; ++ clock-mult = <1>; ++ clock-div = <1>; ++}; ++ ++cpsw_125mhz_gclk: cpsw_125mhz_gclk { ++ #clock-cells = <0>; ++ compatible = "fixed-factor-clock"; ++ clocks = <&dpll_core_m5_ck>; ++ clock-mult = <1>; ++ clock-div = <2>; ++}; ++ ++cpsw_cpts_rft_clk: cpsw_cpts_rft_clk@44df4238 { ++ #clock-cells = <0>; ++ compatible = "mux-clock"; ++ clocks = <&sysclk_div>, <&dpll_core_m5_ck>, <&dpll_disp_m2_ck>; ++ reg = <0x44df4238 0x4>; ++ bit-mask = <0x3>; ++}; ++ ++clk_32k_mosc_ck: clk_32k_mosc_ck { ++ #clock-cells = <0>; ++ compatible = "fixed-clock"; ++ clock-frequency = <32768>; ++}; ++ ++gpio0_dbclk_mux_ck: gpio0_dbclk_mux_ck@44df4240 { ++ #clock-cells = <0>; ++ compatible = "mux-clock"; ++ clocks = <&clk_rc32k_ck>, <&clk_32768_ck>, <&clkdiv32k_ick>, <&clk_32k_mosc_ck>, <&clk_32k_tpm_ck>; ++ reg = <0x44df4240 0x4>; ++ bit-mask = <0x7>; ++}; ++ ++gpio0_dbclk: gpio0_dbclk@44df2b68 { ++ #clock-cells = <0>; ++ compatible = "gate-clock"; ++ clocks = <&gpio0_dbclk_mux_ck>; ++ bit-shift = <8>; ++ reg = <0x44df2b68 0x4>; ++}; ++ ++gpio1_dbclk: gpio1_dbclk@44df8c78 { ++ #clock-cells = <0>; ++ compatible = "gate-clock"; ++ clocks = <&clkdiv32k_ick>; ++ bit-shift = <8>; ++ reg = <0x44df8c78 0x4>; ++}; ++ ++gpio2_dbclk: gpio2_dbclk@44df8c80 { ++ #clock-cells = <0>; ++ compatible = "gate-clock"; ++ clocks = <&clkdiv32k_ick>; ++ bit-shift = <8>; ++ reg = <0x44df8c80 0x4>; ++}; ++ ++gpio3_dbclk: gpio3_dbclk@44df8c88 { ++ #clock-cells = <0>; ++ compatible = "gate-clock"; ++ clocks = <&clkdiv32k_ick>; ++ bit-shift = <8>; ++ reg = <0x44df8c88 0x4>; ++}; ++ ++gpio4_dbclk: gpio4_dbclk@44df8c90 { ++ #clock-cells = <0>; ++ compatible = "gate-clock"; ++ clocks = <&clkdiv32k_ick>; ++ bit-shift = <8>; ++ reg = <0x44df8c90 0x4>; ++}; ++ ++gpio5_dbclk: gpio5_dbclk@44df8c98 { ++ #clock-cells = <0>; ++ compatible = "gate-clock"; ++ clocks = <&clkdiv32k_ick>; ++ bit-shift = <8>; ++ reg = <0x44df8c98 0x4>; ++}; ++ ++mmc_clk: mmc_clk { ++ #clock-cells = <0>; ++ compatible = "fixed-factor-clock"; ++ clocks = <&dpll_per_m2_ck>; ++ clock-mult = <1>; ++ clock-div = <2>; ++}; ++ ++gfx_fclk_clksel_ck: gfx_fclk_clksel_ck@44df423c { ++ #clock-cells = <0>; ++ compatible = "mux-clock"; ++ clocks = <&sysclk_div>, <&dpll_per_m2_ck>; ++ bit-shift = <1>; ++ reg = <0x44df423c 0x4>; ++ bit-mask = <0x1>; ++}; ++ ++gfx_fck_div_ck: gfx_fck_div_ck@44df423c { ++ #clock-cells = <0>; ++ compatible = "divider-clock"; ++ clocks = <&gfx_fclk_clksel_ck>; ++ reg = <0x44df423c 0x4>; ++ bit-mask = <0x1>; ++}; ++ ++disp_clk: disp_clk@44df4244 { ++ #clock-cells = <0>; ++ compatible = "mux-clock"; ++ clocks = <&dpll_disp_m2_ck>, <&dpll_core_m5_ck>, <&dpll_per_m2_ck>; ++ reg = <0x44df4244 0x4>; ++ bit-mask = <0x3>; ++}; ++ ++dpll_extdev_ck: dpll_extdev_ck@44df2e60 { ++ #clock-cells = <0>; ++ compatible = "ti,omap4-dpll-clock"; ++ clocks = <&sys_clkin_ck>, <&sys_clkin_ck>; ++ reg = <0x44df2e60 0x4>, <0x44df2e64 0x4>, <0x44df2e6c 0x4>; ++ reg-names = "control", "idlest", "mult-div1"; ++}; ++ ++dpll_extdev_m2_ck: dpll_extdev_m2_ck@44df2e70 { ++ #clock-cells = <0>; ++ compatible = "ti,divider-clock"; ++ clocks = <&dpll_extdev_ck>; ++ ti,autoidle-shift = <8>; ++ reg = <0x44df2e70 0x4>; ++ bit-mask = <0x7f>; ++ index-starts-at-one; ++ ti,autoidle-low; ++}; ++ ++mux_synctimer32k_ck: mux_synctimer32k_ck@44df4230 { ++ #clock-cells = <0>; ++ compatible = "mux-clock"; ++ clocks = <&clk_32768_ck>, <&clk_32k_tpm_ck>, <&clkdiv32k_ick>; ++ reg = <0x44df4230 0x4>; ++ bit-mask = <0x3>; ++}; ++ ++synctimer_32kclk: synctimer_32kclk@44df2a30 { ++ #clock-cells = <0>; ++ compatible = "gate-clock"; ++ clocks = <&mux_synctimer32k_ck>; ++ bit-shift = <8>; ++ reg = <0x44df2a30 0x4>; ++}; ++ ++timer8_fck: timer8_fck@44df421c { ++ #clock-cells = <0>; ++ compatible = "mux-clock"; ++ clocks = <&tclkin_ck>, <&sys_clkin_ck>, <&clkdiv32k_ick>, <&clk_32k_tpm_ck>; ++ reg = <0x44df421c 0x4>; ++ bit-mask = <0x3>; ++}; ++ ++timer9_fck: timer9_fck@44df4220 { ++ #clock-cells = <0>; ++ compatible = "mux-clock"; ++ clocks = <&tclkin_ck>, <&sys_clkin_ck>, <&clkdiv32k_ick>, <&clk_32k_tpm_ck>; ++ reg = <0x44df4220 0x4>; ++ bit-mask = <0x3>; ++}; ++ ++timer10_fck: timer10_fck@44df4224 { ++ #clock-cells = <0>; ++ compatible = "mux-clock"; ++ clocks = <&tclkin_ck>, <&sys_clkin_ck>, <&clkdiv32k_ick>, <&clk_32k_tpm_ck>; ++ reg = <0x44df4224 0x4>; ++ bit-mask = <0x3>; ++}; ++ ++timer11_fck: timer11_fck@44df4228 { ++ #clock-cells = <0>; ++ compatible = "mux-clock"; ++ clocks = <&tclkin_ck>, <&sys_clkin_ck>, <&clkdiv32k_ick>, <&clk_32k_tpm_ck>; ++ reg = <0x44df4228 0x4>; ++ bit-mask = <0x3>; ++}; ++ ++cpsw_50m_clkdiv: cpsw_50m_clkdiv { ++ #clock-cells = <0>; ++ compatible = "fixed-factor-clock"; ++ clocks = <&dpll_core_m5_ck>; ++ clock-mult = <1>; ++ clock-div = <1>; ++}; ++ ++cpsw_5m_clkdiv: cpsw_5m_clkdiv { ++ #clock-cells = <0>; ++ compatible = "fixed-factor-clock"; ++ clocks = <&cpsw_50m_clkdiv>; ++ clock-mult = <1>; ++ clock-div = <10>; ++}; ++ ++dpll_ddr_x2_ck: dpll_ddr_x2_ck { ++ #clock-cells = <0>; ++ compatible = "ti,omap4-dpll-x2-clock"; ++ clocks = <&dpll_ddr_ck>; ++}; ++ ++dpll_ddr_m4_ck: dpll_ddr_m4_ck@44df2db8 { ++ #clock-cells = <0>; ++ compatible = "ti,divider-clock"; ++ clocks = <&dpll_ddr_x2_ck>; ++ ti,autoidle-shift = <8>; ++ reg = <0x44df2db8 0x4>; ++ bit-mask = <0x1f>; ++ index-starts-at-one; ++ ti,autoidle-low; ++}; ++ ++dpll_per_clkdcoldo: dpll_per_clkdcoldo { ++ #clock-cells = <0>; ++ compatible = "fixed-factor-clock"; ++ clocks = <&dpll_per_ck>; ++ clock-mult = <1>; ++ clock-div = <1>; ++}; ++ ++dll_aging_clk_div: dll_aging_clk_div@44df4250 { ++ #clock-cells = <0>; ++ compatible = "divider-clock"; ++ clocks = <&sys_clkin_ck>; ++ reg = <0x44df4250 0x4>; ++ table = < 8 0 >, < 16 1 >, < 32 2 >; ++ bit-mask = <0x3>; ++}; ++ ++div_core_25m_ck: div_core_25m_ck { ++ #clock-cells = <0>; ++ compatible = "fixed-factor-clock"; ++ clocks = <&sysclk_div>; ++ clock-mult = <1>; ++ clock-div = <8>; ++}; ++ ++func_12m_clk: func_12m_clk { ++ #clock-cells = <0>; ++ compatible = "fixed-factor-clock"; ++ clocks = <&dpll_per_m2_ck>; ++ clock-mult = <1>; ++ clock-div = <16>; ++}; ++ ++vtp_clk_div: vtp_clk_div { ++ #clock-cells = <0>; ++ compatible = "fixed-factor-clock"; ++ clocks = <&sys_clkin_ck>; ++ clock-mult = <1>; ++ clock-div = <2>; ++}; ++ ++usbphy_32khz_clkmux: usbphy_32khz_clkmux@44df4260 { ++ #clock-cells = <0>; ++ compatible = "mux-clock"; ++ clocks = <&clk_32768_ck>, <&clk_32k_tpm_ck>; ++ reg = <0x44df4260 0x4>; ++ bit-mask = <0x1>; ++}; ++ ++usb_otg_ss0_refclk960m: usb_otg_ss0_refclk960m@44df8a60 { ++ #clock-cells = <0>; ++ compatible = "gate-clock"; ++ clocks = <&dpll_per_clkdcoldo>; ++ bit-shift = <8>; ++ reg = <0x44df8a60 0x4>; ++}; ++ ++usb_otg_ss1_refclk960m: usb_otg_ss1_refclk960m@44df8a68 { ++ #clock-cells = <0>; ++ compatible = "gate-clock"; ++ clocks = <&dpll_per_clkdcoldo>; ++ bit-shift = <8>; ++ reg = <0x44df8a68 0x4>; ++}; ++ ++usb_phy1_always_on_clk32k: usb_phy1_always_on_clk32k { ++ #clock-cells = <0>; ++ compatible = "fixed-clock"; ++ clocks = <&clk_32768_ck>; ++}; ++ ++usb_phy2_always_on_clk32k: usb_phy2_always_on_clk32k { ++ #clock-cells = <0>; ++ compatible = "fixed-clock"; ++ clocks = <&clk_32768_ck>; ++}; +--- /dev/null ++++ b/arch/arm/boot/dts/dra7.dtsi +@@ -0,0 +1,1278 @@ ++/* ++ * Copyright (C) 2013 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 version 2 as ++ * published by the Free Software Foundation. ++ * Based on "omap4.dtsi" ++ */ ++ ++#include <dt-bindings/interrupt-controller/arm-gic.h> ++ ++#include "skeleton.dtsi" ++ ++/ { ++ compatible = "ti,dra7xx"; ++ interrupt-parent = <&gic>; ++ ++ aliases { ++ i2c0 = &i2c1; ++ i2c1 = &i2c2; ++ i2c2 = &i2c3; ++ i2c3 = &i2c4; ++ i2c4 = &i2c5; ++ serial0 = &uart1; ++ serial1 = &uart2; ++ serial2 = &uart3; ++ serial3 = &uart4; ++ serial4 = &uart5; ++ serial5 = &uart6; ++ ethernet0 = &cpsw_emac0; ++ ethernet1 = &cpsw_emac1; ++ }; ++ ++ cpus { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ cpu0: cpu@0 { ++ device_type = "cpu"; ++ compatible = "arm,cortex-a15"; ++ reg = <0>; ++ ++ operating-points = < ++ /* kHz uV */ ++ 1000000 1090000 ++ 1176000 1210000 ++ >; ++ ++ clocks = <&dpll_mpu_ck>; ++ clock-names = "cpu"; ++ ++ clock-latency = <300000>; /* From omap-cpufreq driver */ ++ }; ++ cpu@1 { ++ device_type = "cpu"; ++ compatible = "arm,cortex-a15"; ++ reg = <1>; ++ }; ++ }; ++ ++ timer { ++ compatible = "arm,armv7-timer"; ++ /* PPI secure/nonsecure IRQ */ ++ interrupts = <GIC_PPI 13 (GIC_CPU_MASK_RAW(3) | IRQ_TYPE_LEVEL_LOW)>, ++ <GIC_PPI 14 (GIC_CPU_MASK_RAW(3) | IRQ_TYPE_LEVEL_LOW)>, ++ <GIC_PPI 11 (GIC_CPU_MASK_RAW(3) | IRQ_TYPE_LEVEL_LOW)>, ++ <GIC_PPI 10 (GIC_CPU_MASK_RAW(3) | IRQ_TYPE_LEVEL_LOW)>; ++ clock-frequency = <6144000>; ++ }; ++ ++ gic: interrupt-controller@48211000 { ++ compatible = "arm,cortex-a15-gic"; ++ interrupt-controller; ++ #interrupt-cells = <3>; ++ reg = <0x48211000 0x1000>, ++ <0x48212000 0x1000>, ++ <0x48214000 0x2000>, ++ <0x48216000 0x2000>; ++ }; ++ ++ /* ++ * The soc node represents the soc top level view. It is uses for IPs ++ * that are not memory mapped in the MPU view or for the MPU itself. ++ */ ++ soc { ++ compatible = "ti,omap-infra"; ++ mpu { ++ compatible = "ti,omap5-mpu"; ++ ti,hwmods = "mpu"; ++ }; ++ }; ++ ++ /* ++ * XXX: Use a flat representation of the SOC interconnect. ++ * The real OMAP interconnect network is quite complex. ++ * Since that will not bring real advantage to represent that in DT for ++ * the moment, just use a fake OCP bus entry to represent the whole bus ++ * hierarchy. ++ */ ++ ocp { ++ compatible = "ti,omap4-l3-noc", "simple-bus"; ++ #address-cells = <1>; ++ #size-cells = <1>; ++ ranges; ++ ti,hwmods = "l3_main_1", "l3_main_2"; ++ ++ crossbar_mpu: mpuirq@4a002a48 { ++ compatible = "crossbar"; ++ crossbar-name = "mpu-irq"; ++ reg = <0x4a002a48 0x0130>; ++ reg-width = <16>; ++ crossbar-lines = "mpu-irq", "rtc-ss-alarm", <0x9f 0xd9 0x12e>, ++ "mpu-irq", "mcasp3-arevt", <0x9e 0x96 0x12c>, ++ "mpu-irq", "mcasp3-axevt", <0x9d 0x97 0x12a>, ++ "mpu-irq", "mailbox5", <0x88 0xfb 0x100>, ++ "mpu-irq", "mailbox6", <0x8d 0xff 0x10a>, ++ "mpu-irq", "qspi", <0x7c 0x157 0x0ec>, ++ "mpu-irq", "vpe", <0x9c 0x162 0x128>, ++ "mpu-irq", "cpsw-rx-thresh", <0x32 0x14e 0x58>, ++ "mpu-irq", "cpsw-rx", <0x33 0x14f 0x5a>, ++ "mpu-irq", "cpsw-tx", <0x34 0x150 0x5c>, ++ "mpu-irq", "cpsw-misc", <0x35 0x151 0x5e>; ++ }; ++ ++ crossbar_dma: dmareq@4a002b78 { ++ compatible = "crossbar"; ++ crossbar-name = "dma-req"; ++ reg = <0x4a002b78 0x0100>; ++ reg-width = <16>; ++ crossbar-lines = "dma-req", "mcasp3-rx", <0x7e 0x84 0xfc>, ++ "dma-req", "mcasp3-tx", <0x7d 0x85 0xfa>; ++ }; ++ ++ prcm: prcm@4ae06000 { ++ compatible = "ti,dra7-prcm"; ++ reg = <0x4ae06000 0x1f00>; ++ #reset-cells = <1>; ++ }; ++ ++ counter32k: counter@4ae04000 { ++ compatible = "ti,omap-counter32k"; ++ reg = <0x4ae04000 0x40>; ++ ti,hwmods = "counter_32k"; ++ clocks = <&wkupaon_iclk_mux>; ++ clock-names = "fck"; ++ }; ++ ++ avs_mpu: regulator-avs@0x4A003B18 { ++ compatible = "ti,avsclass0"; ++ reg = <0x4A003B18 20>; ++ efuse-settings = <1090000 8 ++ 1210000 12 ++ 1280000 16>; ++ }; ++ ++ avs_core: regulator-avs@0x4A0025EC { ++ compatible = "ti,avsclass0"; ++ reg = <0x4A0025EC 20>; ++ efuse-settings = <1030000 8>; ++ }; ++ ++ avs_gpu: regulator-avs@0x4A003B00 { ++ compatible = "ti,avsclass0"; ++ reg = <0x4A003B00 20>; ++ efuse-settings = <1090000 8 ++ 1210000 12 ++ 1280000 16>; ++ }; ++ ++ avs_dspeve: regulator-avs@0x4A0025D8 { ++ compatible = "ti,avsclass0"; ++ reg = <0x4A0025D8 20>; ++ efuse-settings = <1055000 8 ++ 1150000 12 ++ 1250000 16>; ++ }; ++ ++ avs_iva: regulator-avs@0x4A0025C4 { ++ compatible = "ti,avsclass0"; ++ reg = <0x4A0025C4 20>; ++ efuse-settings = <1055000 8 ++ 1150000 12 ++ 1250000 16>; ++ }; ++ ++ dra7_pmx_core: pinmux@4a003400 { ++ compatible = "pinctrl-single"; ++ reg = <0x4a003400 0x0464>; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ pinctrl-single,register-width = <32>; ++ pinctrl-single,function-mask = <0x3fffffff>; ++ }; ++ ++ sdma: dma-controller@4a056000 { ++ compatible = "ti,omap4430-sdma"; ++ reg = <0x4a056000 0x1000>; ++ interrupts = <0 12 0x4>, ++ <0 13 0x4>, ++ <0 14 0x4>, ++ <0 15 0x4>; ++ #dma-cells = <1>; ++ #dma-channels = <32>; ++ #dma-requests = <127>; ++ clocks = <&l3_iclk_div>; ++ clock-names = "fck"; ++ }; ++ ++ gpio1: gpio@4ae10000 { ++ compatible = "ti,omap4-gpio"; ++ reg = <0x4ae10000 0x200>; ++ interrupts = <0 29 0x4>; ++ ti,hwmods = "gpio1"; ++ clocks = <&wkupaon_iclk_mux>, <&gpio1_dbclk>; ++ clock-names = "fck", "dbclk"; ++ gpio-controller; ++ #gpio-cells = <2>; ++ interrupt-controller; ++ #interrupt-cells = <1>; ++ }; ++ ++ gpio2: gpio@48055000 { ++ compatible = "ti,omap4-gpio"; ++ reg = <0x48055000 0x200>; ++ interrupts = <0 30 0x4>; ++ ti,hwmods = "gpio2"; ++ clocks = <&l3_iclk_div>, <&gpio2_dbclk>; ++ clock-names = "fck", "dbclk"; ++ gpio-controller; ++ #gpio-cells = <2>; ++ interrupt-controller; ++ #interrupt-cells = <1>; ++ }; ++ ++ gpio3: gpio@48057000 { ++ compatible = "ti,omap4-gpio"; ++ reg = <0x48057000 0x200>; ++ interrupts = <0 31 0x4>; ++ ti,hwmods = "gpio3"; ++ clocks = <&l3_iclk_div>, <&gpio3_dbclk>; ++ clock-names = "fck", "dbclk"; ++ gpio-controller; ++ #gpio-cells = <2>; ++ interrupt-controller; ++ #interrupt-cells = <1>; ++ }; ++ ++ gpio4: gpio@48059000 { ++ compatible = "ti,omap4-gpio"; ++ reg = <0x48059000 0x200>; ++ interrupts = <0 32 0x4>; ++ ti,hwmods = "gpio4"; ++ clocks = <&l3_iclk_div>, <&gpio4_dbclk>; ++ clock-names = "fck", "dbclk"; ++ gpio-controller; ++ #gpio-cells = <2>; ++ interrupt-controller; ++ #interrupt-cells = <1>; ++ }; ++ ++ gpio5: gpio@4805b000 { ++ compatible = "ti,omap4-gpio"; ++ reg = <0x4805b000 0x200>; ++ interrupts = <0 33 0x4>; ++ ti,hwmods = "gpio5"; ++ clocks = <&l3_iclk_div>, <&gpio5_dbclk>; ++ clock-names = "fck", "dbclk"; ++ gpio-controller; ++ #gpio-cells = <2>; ++ interrupt-controller; ++ #interrupt-cells = <1>; ++ }; ++ ++ gpio6: gpio@4805d000 { ++ compatible = "ti,omap4-gpio"; ++ reg = <0x4805d000 0x200>; ++ interrupts = <0 34 0x4>; ++ ti,hwmods = "gpio6"; ++ clocks = <&l3_iclk_div>, <&gpio6_dbclk>; ++ clock-names = "fck", "dbclk"; ++ gpio-controller; ++ #gpio-cells = <2>; ++ interrupt-controller; ++ #interrupt-cells = <1>; ++ }; ++ ++ gpio7: gpio@48051000 { ++ compatible = "ti,omap4-gpio"; ++ reg = <0x48051000 0x200>; ++ interrupts = <0 35 0x4>; ++ ti,hwmods = "gpio7"; ++ clocks = <&l3_iclk_div>, <&gpio7_dbclk>; ++ clock-names = "fck", "dbclk"; ++ gpio-controller; ++ #gpio-cells = <2>; ++ interrupt-controller; ++ #interrupt-cells = <1>; ++ }; ++ ++ gpio8: gpio@48053000 { ++ compatible = "ti,omap4-gpio"; ++ reg = <0x48053000 0x200>; ++ interrupts = <0 121 0x4>; ++ ti,hwmods = "gpio8"; ++ clocks = <&l3_iclk_div>, <&gpio8_dbclk>; ++ clock-names = "fck", "dbclk"; ++ gpio-controller; ++ #gpio-cells = <2>; ++ interrupt-controller; ++ #interrupt-cells = <1>; ++ }; ++ ++ uart1: serial@4806a000 { ++ compatible = "ti,omap4-uart"; ++ reg = <0x4806a000 0x100>; ++ interrupts = <0 72 0x4>; ++ ti,hwmods = "uart1"; ++ clocks = <&uart1_gfclk_mux>; ++ clock-names = "fck"; ++ clock-frequency = <48000000>; ++ status = "disabled"; ++ }; ++ ++ uart2: serial@4806c000 { ++ compatible = "ti,omap4-uart"; ++ reg = <0x4806c000 0x100>; ++ interrupts = <0 73 0x4>; ++ ti,hwmods = "uart2"; ++ clocks = <&uart2_gfclk_mux>; ++ clock-names = "fck"; ++ clock-frequency = <48000000>; ++ status = "disabled"; ++ }; ++ ++ uart3: serial@48020000 { ++ compatible = "ti,omap4-uart"; ++ reg = <0x48020000 0x100>; ++ interrupts = <0 74 0x4>; ++ ti,hwmods = "uart3"; ++ clocks = <&uart3_gfclk_mux>; ++ clock-names = "fck"; ++ clock-frequency = <48000000>; ++ status = "disabled"; ++ }; ++ ++ uart4: serial@4806e000 { ++ compatible = "ti,omap4-uart"; ++ reg = <0x4806e000 0x100>; ++ interrupts = <0 70 0x4>; ++ ti,hwmods = "uart4"; ++ clocks = <&uart4_gfclk_mux>; ++ clock-names = "fck"; ++ clock-frequency = <48000000>; ++ status = "disabled"; ++ }; ++ ++ uart5: serial@48066000 { ++ compatible = "ti,omap4-uart"; ++ reg = <0x48066000 0x100>; ++ interrupts = <0 105 0x4>; ++ ti,hwmods = "uart5"; ++ clocks = <&uart5_gfclk_mux>; ++ clock-names = "fck"; ++ clock-frequency = <48000000>; ++ status = "disabled"; ++ }; ++ ++ uart6: serial@48068000 { ++ compatible = "ti,omap4-uart"; ++ reg = <0x48068000 0x100>; ++ interrupts = <0 106 0x4>; ++ ti,hwmods = "uart6"; ++ clocks = <&uart6_gfclk_mux>; ++ clock-names = "fck"; ++ clock-frequency = <48000000>; ++ status = "disabled"; ++ }; ++ ++ uart7: serial@48420000 { ++ compatible = "ti,omap4-uart"; ++ reg = <0x48420000 0x100>; ++ ti,hwmods = "uart7"; ++ clock-frequency = <48000000>; ++ status = "disabled"; ++ }; ++ ++ uart8: serial@48422000 { ++ compatible = "ti,omap4-uart"; ++ reg = <0x48422000 0x100>; ++ ti,hwmods = "uart8"; ++ clock-frequency = <48000000>; ++ status = "disabled"; ++ }; ++ ++ uart9: serial@48424000 { ++ compatible = "ti,omap4-uart"; ++ reg = <0x48424000 0x100>; ++ ti,hwmods = "uart9"; ++ clock-frequency = <48000000>; ++ status = "disabled"; ++ }; ++ ++ uart10: serial@4ae2b000 { ++ compatible = "ti,omap4-uart"; ++ reg = <0x4ae2b000 0x100>; ++ ti,hwmods = "uart10"; ++ clock-frequency = <48000000>; ++ status = "disabled"; ++ }; ++ ++ mailbox1: mailbox@4a0f4000 { ++ compatible = "ti,omap4-mailbox"; ++ reg = <0x4a0f4000 0x200>; ++ interrupts = <0 26 0x4>; ++ ti,hwmods = "mailbox1"; ++ ti,mbox-num-users = <3>; ++ ti,mbox-num-fifos = <8>; ++ #ti,mbox-data-cells = <4>; ++ ti,mbox-names = "mbox1-1", "mbox1-2"; ++ ti,mbox-data = <0 1 0 0>, <3 2 0 0>; ++ }; ++ ++ mailbox2: mailbox@4883a000 { ++ compatible = "ti,omap4-mailbox"; ++ reg = <0x4883a000 0x200>; ++ ti,hwmods = "mailbox2"; ++ ti,mbox-num-users = <4>; ++ ti,mbox-num-fifos = <12>; ++ #ti,mbox-data-cells = <4>; ++ status = "disabled"; ++ }; ++ ++ mailbox3: mailbox@4883c000 { ++ compatible = "ti,omap4-mailbox"; ++ reg = <0x4883c000 0x200>; ++ ti,hwmods = "mailbox3"; ++ ti,mbox-num-users = <4>; ++ ti,mbox-num-fifos = <12>; ++ #ti,mbox-data-cells = <4>; ++ status = "disabled"; ++ }; ++ ++ mailbox4: mailbox@4883e000 { ++ compatible = "ti,omap4-mailbox"; ++ reg = <0x4883e000 0x200>; ++ ti,hwmods = "mailbox4"; ++ ti,mbox-num-users = <4>; ++ ti,mbox-num-fifos = <12>; ++ #ti,mbox-data-cells = <4>; ++ status = "disabled"; ++ }; ++ ++ mailbox5: mailbox@48840000 { ++ compatible = "ti,omap4-mailbox"; ++ reg = <0x48840000 0x200>; ++ interrupts = <0 136 0x4>; ++ ti,hwmods = "mailbox5"; ++ ti,mbox-num-users = <4>; ++ ti,mbox-num-fifos = <12>; ++ #ti,mbox-data-cells = <4>; ++ ti,mbox-names = "mbox-ipu1", "mbox-dsp1"; ++ ti,mbox-data = <6 4 0 2>, <5 1 0 2>; ++ }; ++ ++ mailbox6: mailbox@48842000 { ++ compatible = "ti,omap4-mailbox"; ++ reg = <0x48842000 0x200>; ++ interrupts = <0 141 0x4>; ++ ti,hwmods = "mailbox6"; ++ ti,mbox-num-users = <4>; ++ ti,mbox-num-fifos = <12>; ++ #ti,mbox-data-cells = <4>; ++ ti,mbox-names = "mbox-ipu2", "mbox-dsp2"; ++ ti,mbox-data = <6 4 0 2>, <5 1 0 2>; ++ }; ++ ++ mailbox7: mailbox@48844000 { ++ compatible = "ti,omap4-mailbox"; ++ reg = <0x48844000 0x200>; ++ ti,hwmods = "mailbox7"; ++ ti,mbox-num-users = <4>; ++ ti,mbox-num-fifos = <12>; ++ #ti,mbox-data-cells = <4>; ++ status = "disabled"; ++ }; ++ ++ mailbox8: mailbox@48846000 { ++ compatible = "ti,omap4-mailbox"; ++ reg = <0x48846000 0x200>; ++ ti,hwmods = "mailbox8"; ++ ti,mbox-num-users = <4>; ++ ti,mbox-num-fifos = <12>; ++ #ti,mbox-data-cells = <4>; ++ status = "disabled"; ++ }; ++ ++ mailbox9: mailbox@4885e000 { ++ compatible = "ti,omap4-mailbox"; ++ reg = <0x4885e000 0x200>; ++ ti,hwmods = "mailbox9"; ++ ti,mbox-num-users = <4>; ++ ti,mbox-num-fifos = <12>; ++ #ti,mbox-data-cells = <4>; ++ status = "disabled"; ++ }; ++ ++ mailbox10: mailbox@48860000 { ++ compatible = "ti,omap4-mailbox"; ++ reg = <0x48860000 0x200>; ++ ti,hwmods = "mailbox10"; ++ ti,mbox-num-users = <4>; ++ ti,mbox-num-fifos = <12>; ++ #ti,mbox-data-cells = <4>; ++ status = "disabled"; ++ }; ++ ++ mailbox11: mailbox@48862000 { ++ compatible = "ti,omap4-mailbox"; ++ reg = <0x48862000 0x200>; ++ ti,hwmods = "mailbox11"; ++ ti,mbox-num-users = <4>; ++ ti,mbox-num-fifos = <12>; ++ #ti,mbox-data-cells = <4>; ++ status = "disabled"; ++ }; ++ ++ mailbox12: mailbox@48864000 { ++ compatible = "ti,omap4-mailbox"; ++ reg = <0x48864000 0x200>; ++ ti,hwmods = "mailbox12"; ++ ti,mbox-num-users = <4>; ++ ti,mbox-num-fifos = <12>; ++ #ti,mbox-data-cells = <4>; ++ status = "disabled"; ++ }; ++ ++ mailbox13: mailbox@48802000 { ++ compatible = "ti,omap4-mailbox"; ++ reg = <0x48802000 0x200>; ++ ti,hwmods = "mailbox13"; ++ ti,mbox-num-users = <4>; ++ ti,mbox-num-fifos = <12>; ++ #ti,mbox-data-cells = <4>; ++ status = "disabled"; ++ }; ++ ++ timer1: timer@4ae18000 { ++ compatible = "ti,omap5430-timer"; ++ reg = <0x4ae18000 0x80>; ++ interrupts = <0 37 0x4>; ++ ti,hwmods = "timer1"; ++ clocks = <&timer1_gfclk_mux>; ++ clock-names = "fck"; ++ ti,timer-alwon; ++ }; ++ ++ timer2: timer@48032000 { ++ compatible = "ti,omap5430-timer"; ++ reg = <0x48032000 0x80>; ++ interrupts = <0 38 0x4>; ++ ti,hwmods = "timer2"; ++ clocks = <&timer2_gfclk_mux>; ++ clock-names = "fck"; ++ }; ++ ++ timer3: timer@48034000 { ++ compatible = "ti,omap5430-timer"; ++ reg = <0x48034000 0x80>; ++ interrupts = <0 39 0x4>; ++ ti,hwmods = "timer3"; ++ clocks = <&timer3_gfclk_mux>; ++ clock-names = "fck"; ++ }; ++ ++ timer4: timer@48036000 { ++ compatible = "ti,omap5430-timer"; ++ reg = <0x48036000 0x80>; ++ interrupts = <0 40 0x4>; ++ ti,hwmods = "timer4"; ++ clocks = <&timer4_gfclk_mux>; ++ clock-names = "fck"; ++ }; ++ ++ timer5: timer@48820000 { ++ compatible = "ti,omap5430-timer"; ++ reg = <0x48820000 0x80>; ++ interrupts = <0 41 0x4>; ++ ti,hwmods = "timer5"; ++ clocks = <&timer5_gfclk_mux>; ++ clock-names = "fck"; ++ ti,timer-dsp; ++ }; ++ ++ timer6: timer@48822000 { ++ compatible = "ti,omap5430-timer"; ++ reg = <0x48822000 0x80>; ++ interrupts = <0 42 0x4>; ++ ti,hwmods = "timer6"; ++ clocks = <&timer6_gfclk_mux>; ++ clock-names = "fck"; ++ ti,timer-dsp; ++ ti,timer-pwm; ++ }; ++ ++ timer7: timer@48824000 { ++ compatible = "ti,omap5430-timer"; ++ reg = <0x48824000 0x80>; ++ interrupts = <0 43 0x4>; ++ ti,hwmods = "timer7"; ++ clocks = <&timer7_gfclk_mux>; ++ clock-names = "fck"; ++ ti,timer-dsp; ++ }; ++ ++ timer8: timer@48826000 { ++ compatible = "ti,omap5430-timer"; ++ reg = <0x48826000 0x80>; ++ interrupts = <0 44 0x4>; ++ ti,hwmods = "timer8"; ++ clocks = <&timer8_gfclk_mux>; ++ clock-names = "fck"; ++ ti,timer-dsp; ++ ti,timer-pwm; ++ }; ++ ++ timer9: timer@4803e000 { ++ compatible = "ti,omap5430-timer"; ++ reg = <0x4803e000 0x80>; ++ interrupts = <0 45 0x4>; ++ ti,hwmods = "timer9"; ++ clocks = <&timer9_gfclk_mux>; ++ clock-names = "fck"; ++ }; ++ ++ timer10: timer@48086000 { ++ compatible = "ti,omap5430-timer"; ++ reg = <0x48086000 0x80>; ++ interrupts = <0 46 0x4>; ++ ti,hwmods = "timer10"; ++ clocks = <&timer10_gfclk_mux>; ++ clock-names = "fck"; ++ }; ++ ++ timer11: timer@48088000 { ++ compatible = "ti,omap5430-timer"; ++ reg = <0x48088000 0x80>; ++ interrupts = <0 47 0x4>; ++ ti,hwmods = "timer11"; ++ clocks = <&timer11_gfclk_mux>; ++ clock-names = "fck"; ++ ti,timer-pwm; ++ }; ++ ++ timer13: timer@48828000 { ++ compatible = "ti,omap5430-timer"; ++ reg = <0x48828000 0x80>; ++ ti,hwmods = "timer13"; ++ status = "disabled"; ++ }; ++ ++ timer14: timer@4882a000 { ++ compatible = "ti,omap5430-timer"; ++ reg = <0x4882a000 0x80>; ++ ti,hwmods = "timer14"; ++ status = "disabled"; ++ }; ++ ++ timer15: timer@4882c000 { ++ compatible = "ti,omap5430-timer"; ++ reg = <0x4882c000 0x80>; ++ ti,hwmods = "timer15"; ++ status = "disabled"; ++ }; ++ ++ timer16: timer@4882e000 { ++ compatible = "ti,omap5430-timer"; ++ reg = <0x4882e000 0x80>; ++ ti,hwmods = "timer16"; ++ status = "disabled"; ++ }; ++ ++ wdt2: wdt@4ae14000 { ++ compatible = "ti,omap4-wdt"; ++ reg = <0x4ae14000 0x80>; ++ interrupts = <0 80 0x4>; ++ ti,hwmods = "wd_timer2"; ++ clocks = <&sys_32k_ck>; ++ clock-names = "fck"; ++ }; ++ ++ i2c1: i2c@48070000 { ++ compatible = "ti,omap4-i2c"; ++ reg = <0x48070000 0x100>; ++ interrupts = <0 56 0x4>; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ti,hwmods = "i2c1"; ++ clocks = <&func_96m_fclk>; ++ clock-names = "fck"; ++ status = "disabled"; ++ }; ++ ++ i2c2: i2c@48072000 { ++ compatible = "ti,omap4-i2c"; ++ reg = <0x48072000 0x100>; ++ interrupts = <0 57 0x4>; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ti,hwmods = "i2c2"; ++ clocks = <&func_96m_fclk>; ++ clock-names = "fck"; ++ status = "disabled"; ++ }; ++ ++ i2c3: i2c@48060000 { ++ compatible = "ti,omap4-i2c"; ++ reg = <0x48060000 0x100>; ++ interrupts = <0 61 0x4>; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ti,hwmods = "i2c3"; ++ clocks = <&func_96m_fclk>; ++ clock-names = "fck"; ++ status = "disabled"; ++ }; ++ ++ i2c4: i2c@4807a000 { ++ compatible = "ti,omap4-i2c"; ++ reg = <0x4807a000 0x100>; ++ interrupts = <0 62 0x4>; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ti,hwmods = "i2c4"; ++ clocks = <&func_96m_fclk>; ++ clock-names = "fck"; ++ status = "disabled"; ++ }; ++ ++ i2c5: i2c@4807c000 { ++ compatible = "ti,omap4-i2c"; ++ reg = <0x4807c000 0x100>; ++ interrupts = <0 60 0x4>; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ti,hwmods = "i2c5"; ++ clocks = <&func_96m_fclk>; ++ clock-names = "fck"; ++ status = "disabled"; ++ }; ++ ++ mmc1: mmc@4809c000 { ++ compatible = "ti,omap4-hsmmc"; ++ reg = <0x4809c000 0x400>; ++ interrupts = <0 83 0x4>; ++ ti,hwmods = "mmc1"; ++ clocks = <&mmc1_fclk_div>, <&mmc1_clk32k>; ++ clock-names = "fck", "clk32k"; ++ ti,dual-volt; ++ ti,needs-special-reset; ++ dmas = <&sdma 61>, <&sdma 62>; ++ dma-names = "tx", "rx"; ++ status = "disabled"; ++ }; ++ ++ mmc2: mmc@480b4000 { ++ compatible = "ti,omap4-hsmmc"; ++ reg = <0x480b4000 0x400>; ++ interrupts = <0 86 0x4>; ++ ti,hwmods = "mmc2"; ++ clocks = <&mmc2_fclk_div>, <&mmc2_clk32k>; ++ clock-names = "fck", "clk32k"; ++ ti,needs-special-reset; ++ dmas = <&sdma 47>, <&sdma 48>; ++ dma-names = "tx", "rx"; ++ status = "disabled"; ++ }; ++ ++ mmc3: mmc@480ad000 { ++ compatible = "ti,omap4-hsmmc"; ++ reg = <0x480ad000 0x400>; ++ interrupts = <0 94 0x4>; ++ ti,hwmods = "mmc3"; ++ clocks = <&mmc3_gfclk_div>, <&mmc3_clk32k>; ++ clock-names = "fck", "clk32k"; ++ ti,needs-special-reset; ++ dmas = <&sdma 77>, <&sdma 78>; ++ dma-names = "tx", "rx"; ++ status = "disabled"; ++ }; ++ ++ mmc4: mmc@480d1000 { ++ compatible = "ti,omap4-hsmmc"; ++ reg = <0x480d1000 0x400>; ++ interrupts = <0 96 0x4>; ++ ti,hwmods = "mmc4"; ++ clocks = <&mmc4_gfclk_div>, <&mmc4_clk32k>; ++ clock-names = "fck", "clk32k"; ++ ti,needs-special-reset; ++ dmas = <&sdma 57>, <&sdma 58>; ++ dma-names = "tx", "rx"; ++ status = "disabled"; ++ }; ++ ++ qspi: qspi@4b300000 { ++ compatible = "ti,dra7xxx-qspi"; ++ reg = <0x4b300000 0x100>, <0x4a002558 0x4>, ++ <0x5c000000 0x3ffffff>; ++ reg-names = "qspi_base", ++ "qspi_ctrlmod", ++ "qspi_mmap"; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ti,hwmods = "qspi"; ++ ti,spi-num-cs = <4>; ++ interrupts = <0 124 0x4>; ++ mmap_read; ++ }; ++ ++ omap_control_sata: control-phy@4a002374 { ++ compatible = "ti,control-phy-pipe3"; ++ reg = <0x4a002374 0x4>; ++ reg-names = "power"; ++ clocks = <&sys_clkin1>; ++ clock-names = "sysclk"; ++ }; ++ ++ ocp2scp@4a090000 { ++ compatible = "ti,omap-ocp2scp"; ++ #address-cells = <1>; ++ #size-cells = <1>; ++ ranges; ++ ti,hwmods = "ocp2scp3"; ++ reg = <0x4a090000 0x400>; /* ocp2scp3 */ ++ sata_phy: sata-phy@4A096000 { ++ compatible = "ti,phy-pipe3-sata"; ++ reg = <0x4A096000 0x80>, /* phy_rx */ ++ <0x4A096400 0x64>, /* phy_tx */ ++ <0x4A096800 0x40>; /* pll_ctrl */ ++ reg-names = "phy_rx", "phy_tx", "pll_ctrl"; ++ ctrl-module = <&omap_control_sata>; ++ clocks = <&sata_ref_clk>; ++ clock-names = "refclk"; ++ #phy-cells = <0>; ++ }; ++ }; ++ ++ sata@4a141100 { ++ compatible = "ti,sata"; ++ ti,hwmods = "sata"; ++ reg = <0x4a141100 0x100>; ++ #address-cells = <1>; ++ #size-cells = <1>; ++ ranges; ++ sata@4a140000 { ++ compatible = "snps,dwc-ahci"; ++ reg = <0x4a140000 0x1100>; ++ interrupts = <0 54 0x4>; ++ phys = <&sata_phy>; ++ phy-names = "sata-phy"; ++ }; ++ }; ++ ++ ++ mcspi1: spi@48098000 { ++ compatible = "ti,omap4-mcspi"; ++ reg = <0x48098000 0x200>; ++ interrupts = <0 65 0x4>; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ti,hwmods = "mcspi1"; ++ clocks = <&func_48m_fclk>; ++ clock-names = "fck"; ++ ti,spi-num-cs = <4>; ++ dmas = <&sdma 35>, ++ <&sdma 36>, ++ <&sdma 37>, ++ <&sdma 38>, ++ <&sdma 39>, ++ <&sdma 40>, ++ <&sdma 41>, ++ <&sdma 42>; ++ dma-names = "tx0", "rx0", "tx1", "rx1", ++ "tx2", "rx2", "tx3", "rx3"; ++ status = "disabled"; ++ }; ++ ++ mcspi2: spi@4809a000 { ++ compatible = "ti,omap4-mcspi"; ++ reg = <0x4809a000 0x200>; ++ interrupts = <0 66 0x4>; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ti,hwmods = "mcspi2"; ++ clocks = <&func_48m_fclk>; ++ clock-names = "fck"; ++ ti,spi-num-cs = <2>; ++ dmas = <&sdma 43>, ++ <&sdma 44>, ++ <&sdma 45>, ++ <&sdma 46>; ++ dma-names = "tx0", "rx0", "tx1", "rx1"; ++ status = "disabled"; ++ }; ++ ++ mcspi3: spi@480b8000 { ++ compatible = "ti,omap4-mcspi"; ++ reg = <0x480b8000 0x200>; ++ interrupts = <0 91 0x4>; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ti,hwmods = "mcspi3"; ++ clocks = <&func_48m_fclk>; ++ clock-names = "fck"; ++ ti,spi-num-cs = <2>; ++ dmas = <&sdma 15>, <&sdma 16>; ++ dma-names = "tx0", "rx0"; ++ status = "disabled"; ++ }; ++ ++ mcspi4: spi@480ba000 { ++ compatible = "ti,omap4-mcspi"; ++ reg = <0x480ba000 0x200>; ++ interrupts = <0 48 0x4>; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ti,hwmods = "mcspi4"; ++ clocks = <&func_48m_fclk>; ++ clock-names = "fck"; ++ ti,spi-num-cs = <1>; ++ dmas = <&sdma 70>, <&sdma 71>; ++ dma-names = "tx0", "rx0"; ++ status = "disabled"; ++ }; ++ ++ rtcss@48838000 { ++ compatible = "ti,da830-rtc"; ++ reg = <0x48838000 0x100>; ++ interrupts = <0 159 0x4>, ++ <0 159 0x4>; ++ ti,hwmods = "rtcss"; ++ clocks = <&sys_32k_ck>; ++ clock-names = "fck"; ++ }; ++ ++ omap_control_usb2phy1: control-phy@4a002300 { ++ compatible = "ti,control-phy-usb2"; ++ reg = <0x4a002300 0x4>; ++ reg-names = "power"; ++ }; ++ ++ omap_control_usb3phy1: control-phy@4a002370 { ++ compatible = "ti,control-phy-pipe3"; ++ reg = <0x4a002370 0x4>; ++ reg-names = "power"; ++ }; ++ ++ omap_control_usb2phy2: control-phy@0x4a002e74 { ++ compatible = "ti,control-phy-dra7usb2"; ++ reg = <0x4a002e74 0x4>; ++ reg-names = "power"; ++ }; ++ ++ ocp2scp@4a080000 { ++ compatible = "ti,omap-ocp2scp"; ++ #address-cells = <1>; ++ #size-cells = <1>; ++ ranges; ++ ti,hwmods = "ocp2scp1"; ++ reg = <0x4a080000 0x400>; /* ocp2scp1 */ ++ ++ usb2_phy1: usb2phy1@4a084000 { ++ compatible = "ti,omap-usb2"; ++ reg = <0x4a084000 0x400>; ++ ctrl-module = <&omap_control_usb2phy1>; ++ clocks = <&usb_phy1_always_on_clk32k>, ++ <&usb_otg_ss1_refclk960m>; ++ clock-names = "wkupclk", ++ "refclk"; ++ #phy-cells = <0>; ++ }; ++ ++ usb2_phy2: usb2phy2@4a085000 { ++ compatible = "ti,omap-usb2"; ++ reg = <0x4a085000 0x400>; ++ ctrl-module = <&omap_control_usb2phy2>; ++ clocks = <&usb_phy2_always_on_clk32k>, ++ <&usb_otg_ss2_refclk960m>; ++ clock-names = "wkupclk", ++ "refclk"; ++ #phy-cells = <0>; ++ }; ++ ++ usb3_phy1: usb3phy@4a084400 { ++ compatible = "ti,phy-pipe3-usb3"; ++ reg = <0x4a084400 0x80>, ++ <0x4a084800 0x64>, ++ <0x4a084c00 0x40>; ++ reg-names = "phy_rx", "phy_tx", "pll_ctrl"; ++ ctrl-module = <&omap_control_usb3phy1>; ++ clocks = <&usb_phy1_always_on_clk32k>, ++ <&usb_otg_ss1_refclk960m>, ++ <&dpll_core_h13x2_ck>; ++ clock-names = "wkupclk", ++ "refclk", ++ "refclk2"; ++ #phy-cells = <0>; ++ }; ++ }; ++ ++ dwc3_1: omap_dwc3_1@48880000 { ++ compatible = "ti,dwc3"; ++ ti,hwmods = "usb_otg_ss1"; ++ reg = <0x48880000 0x10000>; ++ interrupts = <0 77 4>; ++ #address-cells = <1>; ++ #size-cells = <1>; ++ utmi-mode = <2>; ++ ranges; ++ usb1: usb@48890000 { ++ compatible = "synopsys,dwc3"; ++ reg = <0x48890000 0x17000>; ++ interrupts = <0 76 4>; ++ phys = <&usb2_phy1>, <&usb3_phy1>; ++ phy-names = "usb2-phy", "usb3-phy"; ++ tx-fifo-resize; ++ maximum-speed = "super-speed"; ++ dr_mode = "otg"; ++ }; ++ }; ++ ++ dwc3_2: omap_dwc3_2@488c0000 { ++ compatible = "ti,dwc3"; ++ ti,hwmods = "usb_otg_ss2"; ++ reg = <0x488c0000 0x10000>; ++ interrupts = <0 92 4>; ++ #address-cells = <1>; ++ #size-cells = <1>; ++ utmi-mode = <2>; ++ ranges; ++ usb2: usb@488d0000 { ++ compatible = "synopsys,dwc3"; ++ reg = <0x488d0000 0x17000>; ++ interrupts = <0 78 4>; ++ phys = <&usb2_phy2>; ++ phy-names = "usb2-phy"; ++ tx-fifo-resize; ++ maximum-speed = "high-speed"; ++ dr_mode = "otg"; ++ }; ++ }; ++ ++ /* IRQ for DWC3_3 and DWC3_4 need IRQ crossbar */ ++ dwc3_3: omap_dwc3_3@48900000 { ++ compatible = "ti,dwc3"; ++ ti,hwmods = "usb_otg_ss3"; ++ reg = <0x48900000 0x10000>; ++ /* interrupts = <0 TBD 4>; */ ++ #address-cells = <1>; ++ #size-cells = <1>; ++ utmi-mode = <2>; ++ ranges; ++ status = "disabled"; ++ usb3: usb@48910000 { ++ compatible = "synopsys,dwc3"; ++ reg = <0x48910000 0x17000>; ++ /* interrupts = <0 93 4>; */ ++ tx-fifo-resize; ++ maximum-speed = "high-speed"; ++ dr_mode = "otg"; ++ }; ++ }; ++ ++ dwc3_4: omap_dwc3_4@48940000 { ++ compatible = "ti,dwc3"; ++ ti,hwmods = "usb_otg_ss4"; ++ reg = <0x48940000 0x10000>; ++ /* interrupts = <0 TBD 4>; */ ++ #address-cells = <1>; ++ #size-cells = <1>; ++ utmi-mode = <2>; ++ ranges; ++ status = "disabled"; ++ usb4: usb@48950000 { ++ compatible = "synopsys,dwc3"; ++ reg = <0x48950000 0x17000>; ++ /* interrupts = <0 TBD 4>; */ ++ tx-fifo-resize; ++ maximum-speed = "high-speed"; ++ dr_mode = "otg"; ++ }; ++ }; ++ ++ dmm: dmm@4e000000 { ++ compatible = "ti,omap5-dmm"; ++ reg = <0x4e000000 0x800>; ++ interrupts = <0 113 0x4>; ++ ti,hwmods = "dmm"; ++ }; ++ ++ dss: dss@58000000 { ++ compatible = "ti,omap4-dss", "simple-bus"; ++ reg = <0x58000000 0x80>, ++ <0x58004000 0x340>, ++ <0x58009000 0x340>; ++ ti,hwmods = "dss_core"; ++ #address-cells = <1>; ++ #size-cells = <1>; ++ ranges; ++ ++ dispc@58001000 { ++ compatible = "ti,omap4-dispc"; ++ reg = <0x58001000 0x1000>; ++ interrupts = <0 25 0x4>; ++ ti,hwmods = "dss_dispc"; ++ }; ++ ++ dpi1: encoder@0 { ++ compatible = "ti,dra7xx-dpi"; ++ id = <0>; ++ channel = <0>; ++ }; ++ ++ dpi2: encoder@1 { ++ compatible = "ti,dra7xx-dpi"; ++ id = <1>; ++ }; ++ ++ dpi3: encoder@2 { ++ compatible = "ti,dra7xx-dpi"; ++ id = <2>; ++ }; ++ ++ hdmi: encoder@58040000 { ++ compatible = "ti,omap5-hdmi"; ++ reg = <0x58040000 0x100>, ++ <0x58040200 0x40>, ++ <0x58040300 0x40>, ++ <0x58060000 0x19000>; ++ reg-names = "hdmi_wp", "hdmi_pllctrl", ++ "hdmi_txphy", "hdmi_core"; ++ interrupts = <0 101 0x4>; ++ ti,hwmods = "dss_hdmi"; ++ }; ++ }; ++ ++ vpe { ++ compatible = "ti,vpe"; ++ ti,hwmods = "vpe"; ++ reg = <0x489d0000 0x120>, ++ <0x489d0300 0x20>, ++ <0x489d0400 0x20>, ++ <0x489d0500 0x20>, ++ <0x489d0600 0x3c>, ++ <0x489d0700 0x80>, ++ <0x489d5700 0x18>, ++ <0x489dd000 0x400>; ++ reg-names = "vpe_top", ++ "vpe_chr_us0", ++ "vpe_chr_us1", ++ "vpe_chr_us2", ++ "vpe_dei", ++ "vpe_sc", ++ "vpe_csc", ++ "vpdma"; ++ interrupts = <0 0x9c 0x4>; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ }; ++ ++ mac: ethernet@4a100000 { ++ compatible = "ti,cpsw"; ++ ti,hwmods = "gmac"; ++ cpdma_channels = <8>; ++ ale_entries = <1024>; ++ bd_ram_size = <0x2000>; ++ no_bd_ram = <0>; ++ rx_descs = <64>; ++ mac_control = <0x20>; ++ slaves = <2>; ++ active_slave = <0>; ++ cpts_clock_mult = <0x80000000>; ++ cpts_clock_shift = <29>; ++ reg = <0x48484000 0x800 ++ 0x48485200 0x100>; ++ #address-cells = <1>; ++ #size-cells = <1>; ++ /* ++ * rx_thresh_pend ++ * rx_pend ++ * tx_pend ++ * misc_pend ++ */ ++ interrupts = <GIC_SPI 50 IRQ_TYPE_LEVEL_HIGH>, ++ <GIC_SPI 51 IRQ_TYPE_LEVEL_HIGH>, ++ <GIC_SPI 52 IRQ_TYPE_LEVEL_HIGH>, ++ <GIC_SPI 53 IRQ_TYPE_LEVEL_HIGH>; ++ ranges; ++ status = "disabled"; ++ ++ davinci_mdio: mdio@4a101000 { ++ compatible = "ti,davinci_mdio"; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ti,hwmods = "davinci_mdio"; ++ bus_freq = <1000000>; ++ reg = <0x48485000 0x100>; ++ }; ++ ++ cpsw_emac0: slave@4a100200 { ++ /* Filled in by U-Boot */ ++ mac-address = [ 00 00 00 00 00 00 ]; ++ }; ++ ++ cpsw_emac1: slave@4a100300 { ++ /* Filled in by U-Boot */ ++ mac-address = [ 00 00 00 00 00 00 ]; ++ }; ++ }; ++ ++ elm: elm@48078000 { ++ compatible = "ti,am3352-elm"; ++ /* compatible = "ti,elm"; */ ++ reg = <0x48078000 0x2000>; ++ interrupts = <GIC_SPI 1 IRQ_TYPE_LEVEL_HIGH>; ++ ti,hwmods = "elm"; ++ status = "disabled"; ++ }; ++ ++ gpmc: gpmc@50000000 { ++ compatible = "ti,am3352-gpmc"; ++ /* compatible = "ti,gpmc"; */ ++ ti,hwmods = "gpmc"; ++ reg = <0x50000000 0x2000>; ++ interrupts = <GIC_SPI 15 IRQ_TYPE_LEVEL_HIGH>; ++ gpmc,num-cs = <8>; ++ gpmc,num-waitpins = <2>; ++ #address-cells = <2>; ++ #size-cells = <1>; ++ status = "disabled"; ++ }; ++ ++ aes: aes@4b500000 { ++ compatible = "ti,omap4-aes"; ++ ti,hwmods = "aes"; ++ reg = <0x4b500000 0xa0>; ++ interrupts = <GIC_SPI 85 IRQ_TYPE_LEVEL_HIGH>; ++ dmas = <&sdma 111>, <&sdma 110>; ++ dma-names = "tx", "rx"; ++ clocks = <&l3_iclk_div>; ++ clock-names = "fck"; ++ }; ++ ++ des: des@480a5000 { ++ compatible = "ti,omap4-des"; ++ ti,hwmods = "des"; ++ reg = <0x480a5000 0xa0>; ++ interrupts = <GIC_SPI 82 IRQ_TYPE_LEVEL_HIGH>; ++ dmas = <&sdma 117>, <&sdma 116>; ++ dma-names = "tx", "rx"; ++ clocks = <&l3_iclk_div>; ++ clock-names = "fck"; ++ }; ++ }; ++ ++ clocks { ++ #address-cells = <1>; ++ #size-cells = <1>; ++ ranges; ++ /include/ "dra7xx-clocks.dtsi" ++ }; ++ ++ clockdomains { ++ coreaon_clkdm: coreaon_clkdm { ++ compatible = "ti,clockdomain"; ++ clocks = <&dpll_usb_ck>; ++ }; ++ }; ++}; +--- /dev/null ++++ b/arch/arm/boot/dts/dra7-evm.dts +@@ -0,0 +1,761 @@ ++/* ++ * Copyright (C) 2013 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 version 2 as ++ * published by the Free Software Foundation. ++ */ ++/dts-v1/; ++ ++#include "dra7.dtsi" ++#include <dt-bindings/pinctrl/dra7xx.h> ++ ++/ { ++ model = "TI DRA7"; ++ compatible = "ti,dra7-evm", "ti,dra752", "ti,dra7"; ++ ++ memory { ++ device_type = "memory"; ++ reg = <0x80000000 0x60000000>; /* 1536 MB */ ++ }; ++ ++ extcon1: gpio_usbvid_extcon1 { ++ compatible = "ti,gpio-usb-id"; ++ gpios = <&gpio21 1 0>; ++ }; ++ ++ extcon2: gpio_usbvid_extcon2 { ++ compatible = "ti,gpio-usb-id"; ++ gpios = <&gpio21 2 0>; ++ }; ++ ++ mmc2_3v3: fixedregulator-mmc2 { ++ compatible = "regulator-fixed"; ++ regulator-name = "mmc2_3v3"; ++ regulator-min-microvolt = <3300000>; ++ regulator-max-microvolt = <3300000>; ++ }; ++}; ++ ++&dra7_pmx_core { ++ pinctrl-names = "default"; ++ pinctrl-0 = < ++ &vout1_pins ++ &irq_pins ++ >; ++ ++ i2c1_pins: pinmux_i2c1_pins { ++ pinctrl-single,pins = < ++ 0x400 0x60000 /* i2c1_sda */ ++ 0x404 0x60000 /* i2c1_scl */ ++ >; ++ }; ++ ++ i2c2_pins: pinmux_i2c2_pins { ++ pinctrl-single,pins = < ++ 0x408 0x60000 /* i2c2_sda */ ++ 0x40c 0x60000 /* i2c2_scl */ ++ >; ++ }; ++ ++ i2c3_pins: pinmux_i2c3_pins { ++ pinctrl-single,pins = < ++ 0x410 0x60000 /* i2c3_sda */ ++ 0x414 0x60000 /* i2c3_scl */ ++ >; ++ }; ++ ++ irq_pins: pinmux_irq_pins { ++ pinctrl-single,pins = < ++ 0x420 0x1 /* Wakeup2 INPUT | MODE1 */ ++ >; ++ }; ++ ++ mmc1_pins: pinmux_mmc1_pins { ++ pinctrl-single,pins = < ++ 0x36c 0x4000e /* mmc1sdcd.gpio INPUT | MODE15 */ ++ >; ++ }; ++ ++ mcspi1_pins: pinmux_mcspi1_pins { ++ pinctrl-single,pins = < ++ 0x3a4 0x40000 /* spi2_clk */ ++ 0x3a8 0x40000 /* spi2_d1 */ ++ 0x3ac 0x40000 /* spi2_d0 */ ++ 0x3b0 0xc0000 /* spi2_cs0 */ ++ 0x3b4 0xc0000 /* spi2_cs1 */ ++ 0x3b8 0xe0006 /* spi2_cs2 */ ++ 0x3bc 0xe0006 /* spi2_cs3 */ ++ >; ++ }; ++ ++ mcspi2_pins: pinmux_mcspi2_pins { ++ pinctrl-single,pins = < ++ 0x3c0 0x40000 /* spi2_sclk */ ++ 0x3c4 0xc0000 /* spi2_d1 */ ++ 0x3c8 0xc0000 /* spi2_d1 */ ++ 0x3cc 0xe0000 /* spi2_cs0 */ ++ >; ++ }; ++ ++ uart1_pins: pinmux_uart1_pins { ++ pinctrl-single,pins = < ++ 0x3e0 0xe0000 /* uart1_rxd */ ++ 0x3e4 0xe0000 /* uart1_txd */ ++ 0x3e8 0x60003 /* uart1_ctsn */ ++ 0x3ec 0x60003 /* uart1_rtsn */ ++ >; ++ }; ++ ++ uart2_pins: pinmux_uart2_pins { ++ pinctrl-single,pins = < ++ 0x3f0 0x60000 /* uart2_rxd */ ++ 0x3f4 0x60000 /* uart2_txd */ ++ 0x3f8 0x60000 /* uart2_ctsn */ ++ 0x3fc 0x60000 /* uart2_rtsn */ ++ >; ++ }; ++ ++ uart3_pins: pinmux_uart3_pins { ++ pinctrl-single,pins = < ++ 0x248 0xc0000 /* uart3_rxd */ ++ 0x24c 0xc0000 /* uart3_txd */ ++ >; ++ }; ++ ++ qspi1_pins: pinmux_qspi1_pins { ++ pinctrl-single,pins = < ++ 0x4c 0x40001 /* gpmc_a3.qspi1_cs2 */ ++ 0x50 0x40001 /* gpmc_a4.qspi1_cs3 */ ++ 0x74 0x40001 /* gpmc_a13.qspi1_rtclk */ ++ 0x78 0x40001 /* gpmc_a14.qspi1_d3 */ ++ 0x7c 0x40001 /* gpmc_a15.qspi1_d2 */ ++ 0x80 0x40001 /* gpmc_a16.qspi1_d1 */ ++ 0x84 0x40001 /* gpmc_a17.qspi1_d0 */ ++ 0x88 0x40001 /* qpmc_a18.qspi1_sclk */ ++ 0xb8 0x60001 /* gpmc_cs2.qspi1_cs0 */ ++ 0xbc 0x60001 /* gpmc_cs3.qspi1_cs1 */ ++ >; ++ }; ++ ++ usb1_pins: pinmux_usb1_pins { ++ pinctrl-single,pins = < ++ 0x280 0xc0000 /* usb1_drvvbus, SLOW_SLEW | PULLUPEN | MODE0 */ ++ >; ++ }; ++ ++ usb2_pins: pinmux_usb2_pins { ++ pinctrl-single,pins = < ++ 0x284 0xc0000 /* usb2_drvvbus, SLOW_SLEW | PULLUPEN | MODE0 */ ++ >; ++ }; ++ ++ vout1_pins: pinmux_vout1_pins { ++ pinctrl-single,pins = < ++ 0x1C8 0x0 /* vout1_clk OUTPUT | MODE0 */ ++ 0x1CC 0x0 /* vout1_de OUTPUT | MODE0 */ ++ 0x1D0 0x0 /* vout1_fld OUTPUT | MODE0 */ ++ 0x1D4 0x0 /* vout1_hsync OUTPUT | MODE0 */ ++ 0x1D8 0x0 /* vout1_vsync OUTPUT | MODE0 */ ++ 0x1DC 0x0 /* vout1_d0 OUTPUT | MODE0 */ ++ 0x1E0 0x0 /* vout1_d1 OUTPUT | MODE0 */ ++ 0x1E4 0x0 /* vout1_d2 OUTPUT | MODE0 */ ++ 0x1E8 0x0 /* vout1_d3 OUTPUT | MODE0 */ ++ 0x1EC 0x0 /* vout1_d4 OUTPUT | MODE0 */ ++ 0x1F0 0x0 /* vout1_d5 OUTPUT | MODE0 */ ++ 0x1F4 0x0 /* vout1_d6 OUTPUT | MODE0 */ ++ 0x1F8 0x0 /* vout1_d7 OUTPUT | MODE0 */ ++ 0x1FC 0x0 /* vout1_d8 OUTPUT | MODE0 */ ++ 0x200 0x0 /* vout1_d9 OUTPUT | MODE0 */ ++ 0x204 0x0 /* vout1_d10 OUTPUT | MODE0 */ ++ 0x208 0x0 /* vout1_d11 OUTPUT | MODE0 */ ++ 0x20C 0x0 /* vout1_d12 OUTPUT | MODE0 */ ++ 0x210 0x0 /* vout1_d13 OUTPUT | MODE0 */ ++ 0x214 0x0 /* vout1_d14 OUTPUT | MODE0 */ ++ 0x218 0x0 /* vout1_d15 OUTPUT | MODE0 */ ++ 0x21C 0x0 /* vout1_d16 OUTPUT | MODE0 */ ++ 0x220 0x0 /* vout1_d17 OUTPUT | MODE0 */ ++ 0x224 0x0 /* vout1_d18 OUTPUT | MODE0 */ ++ 0x228 0x0 /* vout1_d19 OUTPUT | MODE0 */ ++ 0x22C 0x0 /* vout1_d20 OUTPUT | MODE0 */ ++ 0x230 0x0 /* vout1_d21 OUTPUT | MODE0 */ ++ 0x234 0x0 /* vout1_d22 OUTPUT | MODE0 */ ++ 0x238 0x0 /* vout1_d23 OUTPUT | MODE0 */ ++ >; ++ }; ++ ++ cpsw_default: cpsw_default { ++ pinctrl-single,pins = < ++ /* Slave 1 */ ++ 0x250 (PIN_OUTPUT | MUX_MODE0) /* rgmii1_tclk */ ++ 0x254 (PIN_OUTPUT | MUX_MODE0) /* rgmii1_tctl */ ++ 0x258 (PIN_OUTPUT | MUX_MODE0) /* rgmii1_td3 */ ++ 0x25c (PIN_OUTPUT | MUX_MODE0) /* rgmii1_td2 */ ++ 0x260 (PIN_OUTPUT | MUX_MODE0) /* rgmii1_td1 */ ++ 0x264 (PIN_OUTPUT | MUX_MODE0) /* rgmii1_td0 */ ++ 0x268 (PIN_INPUT | MUX_MODE0) /* rgmii1_rclk */ ++ 0x26c (PIN_INPUT | MUX_MODE0) /* rgmii1_rctl */ ++ 0x270 (PIN_INPUT | MUX_MODE0) /* rgmii1_rd3 */ ++ 0x274 (PIN_INPUT | MUX_MODE0) /* rgmii1_rd2 */ ++ 0x278 (PIN_INPUT | MUX_MODE0) /* rgmii1_rd1 */ ++ 0x27c (PIN_INPUT | MUX_MODE0) /* rgmii1_rd0 */ ++ ++ /* Slave 2 */ ++ 0x198 (PIN_OUTPUT | MUX_MODE3) /* rgmii2_tclk */ ++ 0x19c (PIN_OUTPUT | MUX_MODE3) /* rgmii2_tctl */ ++ 0x1a0 (PIN_OUTPUT | MUX_MODE3) /* rgmii2_td3 */ ++ 0x1a4 (PIN_OUTPUT | MUX_MODE3) /* rgmii2_td2 */ ++ 0x1a8 (PIN_OUTPUT | MUX_MODE3) /* rgmii2_td1 */ ++ 0x1ac (PIN_OUTPUT | MUX_MODE3) /* rgmii2_td0 */ ++ 0x1b0 (PIN_INPUT | MUX_MODE3) /* rgmii2_rclk */ ++ 0x1b4 (PIN_INPUT | MUX_MODE3) /* rgmii2_rctl */ ++ 0x1b8 (PIN_INPUT | MUX_MODE3) /* rgmii2_rd3 */ ++ 0x1bc (PIN_INPUT | MUX_MODE3) /* rgmii2_rd2 */ ++ 0x1c0 (PIN_INPUT | MUX_MODE3) /* rgmii2_rd1 */ ++ 0x1c4 (PIN_INPUT | MUX_MODE3) /* rgmii2_rd0 */ ++ >; ++ ++ }; ++ cpsw_sleep: cpsw_sleep { ++ pinctrl-single,pins = < ++ /* Slave 1 */ ++ 0x250 (PIN_OFF_NONE) ++ 0x254 (PIN_OFF_NONE) ++ 0x258 (PIN_OFF_NONE) ++ 0x25c (PIN_OFF_NONE) ++ 0x260 (PIN_OFF_NONE) ++ 0x264 (PIN_OFF_NONE) ++ 0x268 (PIN_OFF_NONE) ++ 0x26c (PIN_OFF_NONE) ++ 0x270 (PIN_OFF_NONE) ++ 0x274 (PIN_OFF_NONE) ++ 0x278 (PIN_OFF_NONE) ++ 0x27c (PIN_OFF_NONE) ++ ++ /* Slave 1 */ ++ 0x198 (PIN_OFF_NONE) ++ 0x19c (PIN_OFF_NONE) ++ 0x1a0 (PIN_OFF_NONE) ++ 0x1a4 (PIN_OFF_NONE) ++ 0x1a8 (PIN_OFF_NONE) ++ 0x1ac (PIN_OFF_NONE) ++ 0x1b0 (PIN_OFF_NONE) ++ 0x1b4 (PIN_OFF_NONE) ++ 0x1b8 (PIN_OFF_NONE) ++ 0x1bc (PIN_OFF_NONE) ++ 0x1c0 (PIN_OFF_NONE) ++ 0x1c4 (PIN_OFF_NONE) ++ >; ++ }; ++ ++ davinci_mdio_default: davinci_mdio_default { ++ pinctrl-single,pins = < ++ /* MDIO */ ++ 0x23c (PIN_OUTPUT_PULLUP | MUX_MODE0) /* mdio_data */ ++ 0x240 (PIN_INPUT_PULLUP | MUX_MODE0) /* mdio_clk */ ++ >; ++ }; ++ ++ davinci_mdio_sleep: davinci_mdio_sleep { ++ pinctrl-single,pins = < ++ 0x23c (PIN_OFF_NONE) ++ 0x240 (PIN_OFF_NONE) ++ >; ++ }; ++ ++ nand_flash_x16: nand_flash_x16 { ++ /* On DRA7 EVM, GPMC_WPN and NAND_BOOTn comes from DIP switch ++ * So NAND flash requires following switch settings: ++ * SW5.9 (GPMC_WPN) = LOW ++ * SW5.1 (NAND_BOOTn) = HIGH */ ++ pinctrl-single,pins = < ++ 0x0 0x70000 /* (PIN_INPUT | MUX_MODE0) gpmc_ad0 */ ++ 0x4 0x70000 /* (PIN_INPUT | MUX_MODE0) gpmc_ad1 */ ++ 0x8 0x70000 /* (PIN_INPUT | MUX_MODE0) gpmc_ad2 */ ++ 0xc 0x70000 /* (PIN_INPUT | MUX_MODE0) gpmc_ad3 */ ++ 0x10 0x70000 /* (PIN_INPUT | MUX_MODE0) gpmc_ad4 */ ++ 0x14 0x70000 /* (PIN_INPUT | MUX_MODE0) gpmc_ad5 */ ++ 0x18 0x70000 /* (PIN_INPUT | MUX_MODE0) gpmc_ad6 */ ++ 0x1c 0x70000 /* (PIN_INPUT | MUX_MODE0) gpmc_ad7 */ ++ 0x20 0x70000 /* (PIN_INPUT | MUX_MODE0) gpmc_ad8 */ ++ 0x24 0x70000 /* (PIN_INPUT | MUX_MODE0) gpmc_ad9 */ ++ 0x28 0x70000 /* (PIN_INPUT | MUX_MODE0) gpmc_ad10 */ ++ 0x2c 0x70000 /* (PIN_INPUT | MUX_MODE0) gpmc_ad11 */ ++ 0x30 0x70000 /* (PIN_INPUT | MUX_MODE0) gpmc_ad12 */ ++ 0x34 0x70000 /* (PIN_INPUT | MUX_MODE0) gpmc_ad13 */ ++ 0x38 0x70000 /* (PIN_INPUT | MUX_MODE0) gpmc_ad14 */ ++ 0x3c 0x70000 /* (PIN_INPUT | MUX_MODE0) gpmc_ad15 */ ++ 0xD8 0x70000 /* (PIN_INPUT | MUX_MODE0) gpmc_wait0 */ ++ 0xCC 0x0 /* (PIN_OUTPUT | MUX_MODE0) gpmc_wen */ ++ 0xB4 0x0 /* (PIN_OUTPUT | MUX_MODE0) gpmc_csn0 */ ++ 0xC4 0x0 /* (PIN_OUTPUT | MUX_MODE0) gpmc_advn_ale */ ++ 0xC8 0x0 /* (PIN_OUTPUT | MUX_MODE0) gpmc_oen_ren */ ++ 0xD0 0x0 /* (PIN_OUTPUT | MUX_MODE0) gpmc_be0n_cle */ ++ >; ++ }; ++}; ++ ++&i2c1 { ++ status = "okay"; ++ pinctrl-names = "default"; ++ pinctrl-0 = <&i2c1_pins>; ++ clock-frequency = <400000>; ++ ++ tps659038: tps659038@58 { ++ compatible = "ti,tps659038"; ++ reg = <0x58>; ++ ++ tps659038_pmic { ++ compatible = "ti,tps659038-pmic"; ++ ++ regulators { ++ smps123_reg: smps123 { ++ /* VDD_MPU */ ++ regulator-name = "smps123"; ++ regulator-min-microvolt = < 850000>; ++ regulator-max-microvolt = <1250000>; ++ regulator-always-on; ++ regulator-boot-on; ++ }; ++ ++ smps45_reg: smps45 { ++ /* VDD_DSPEVE */ ++ regulator-name = "smps45"; ++ regulator-min-microvolt = < 850000>; ++ regulator-max-microvolt = <1150000>; ++ regulator-boot-on; ++ }; ++ ++ smps6_reg: smps6 { ++ /* VDD_GPU - over VDD_SMPS6 */ ++ regulator-name = "smps6"; ++ regulator-min-microvolt = <850000>; ++ regulator-max-microvolt = <12500000>; ++ regulator-boot-on; ++ }; ++ ++ smps7_reg: smps7 { ++ /* CORE_VDD */ ++ regulator-name = "smps7"; ++ regulator-min-microvolt = <850000>; ++ regulator-max-microvolt = <1030000>; ++ regulator-always-on; ++ regulator-boot-on; ++ }; ++ ++ smps8_reg: smps8 { ++ /* VDD_IVAHD */ ++ regulator-name = "smps8"; ++ regulator-min-microvolt = < 850000>; ++ regulator-max-microvolt = <1250000>; ++ regulator-boot-on; ++ }; ++ ++ smps9_reg: smps9 { ++ /* VDDS1V8 */ ++ regulator-name = "smps9"; ++ regulator-min-microvolt = <1800000>; ++ regulator-max-microvolt = <1800000>; ++ regulator-always-on; ++ regulator-boot-on; ++ }; ++ ++ ldo1_reg: ldo1 { ++ /* LDO1_OUT --> SDIO */ ++ regulator-name = "ldo1"; ++ regulator-min-microvolt = <1800000>; ++ regulator-max-microvolt = <3300000>; ++ regulator-boot-on; ++ }; ++ ++ ldo2_reg: ldo2 { ++ /* VDD_RTCIO */ ++ /* LDO2 -> VDDSHV5, LDO2 also goes to CAN_PHY_3V3 */ ++ regulator-name = "ldo2"; ++ regulator-min-microvolt = <3300000>; ++ regulator-max-microvolt = <3300000>; ++ regulator-boot-on; ++ }; ++ ++ ldo3_reg: ldo3 { ++ /* VDDA_1V8_PHY */ ++ regulator-name = "ldo3"; ++ regulator-min-microvolt = <1800000>; ++ regulator-max-microvolt = <1800000>; ++ regulator-boot-on; ++ }; ++ ++ ldo9_reg: ldo9 { ++ /* VDD_RTC */ ++ regulator-name = "ldo9"; ++ regulator-min-microvolt = <1050000>; ++ regulator-max-microvolt = <1050000>; ++ regulator-boot-on; ++ }; ++ ++ ldoln_reg: ldoln { ++ /* VDDA_1V8_PLL */ ++ regulator-name = "ldoln"; ++ regulator-min-microvolt = <1800000>; ++ regulator-max-microvolt = <1800000>; ++ regulator-always-on; ++ regulator-boot-on; ++ }; ++ ++ ldousb_reg: ldousb { ++ /* VDDA_3V_USB: VDDA_USBHS33 */ ++ regulator-name = "ldousb"; ++ regulator-min-microvolt = <3300000>; ++ regulator-max-microvolt = <3300000>; ++ regulator-boot-on; ++ }; ++ ++ }; ++ }; ++ }; ++ ++ pcf_gpio_20: gpio@20 { ++ compatible = "ti,pcf8575"; ++ reg = <0x20>; ++ lines-initial-states = <0x4000>; ++ gpio-controller; ++ #gpio-cells = <2>; ++ interrupt-parent = <&gpio6>; ++ interrupts = <11 2>; ++ interrupt-controller; ++ #interrupt-cells = <2>; ++ }; ++ ++ gpio21: gpio@21 { ++ compatible = "ti,pcf8575"; ++ reg = <0x21>; ++ lines-initial-states = <0x1408>; ++ gpio-controller; ++ #gpio-cells = <2>; ++ interrupt-parent = <&pcf_gpio_20>; ++ interrupts = <14 2>; ++ interrupt-controller; ++ #interrupt-cells = <2>; ++ }; ++ ++ /* TLC chip for LCD panel power and backlight */ ++ tlc59108: tlc59108@40 { ++ compatible = "ti,tlc59108"; ++ reg = <0x40>; ++ gpios = <&pcf_gpio_20 13 0>; /* P15, CON_LCD_PWR_DN */ ++ video-source = <&dpi1>; ++ data-lines = <24>; ++ }; ++ ++ mxt244: touchscreen@4a { ++ compatible = "atmel,mXT244"; ++ status = "okay"; ++ reg = <0x4a>; ++ interrupts = <0 119 0x4>; ++ ++ atmel,config = < ++ /* MXT244_GEN_COMMAND(6) */ ++ 0x00 0x00 0x00 0x00 0x00 0x00 ++ /* MXT244_GEN_POWER(7) */ ++ 0x20 0xff 0x32 ++ /* MXT244_GEN_ACQUIRE(8) */ ++ 0x0a 0x00 0x05 0x00 0x00 0x00 0x09 0x23 ++ /* MXT244_TOUCH_MULTI(9) */ ++ 0x00 0x00 0x00 0x13 0x0b 0x00 0x00 0x00 0x02 0x00 ++ 0x00 0x01 0x01 0x0e 0x0a 0x0a 0x0a 0x0a 0x00 0x00 ++ 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 ++ 0x00 ++ /* MXT244_TOUCH_KEYARRAY(15) */ ++ 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 ++ 0x00 ++ /* MXT244_COMMSCONFIG_T18(2) */ ++ 0x00 0x00 ++ /* MXT244_SPT_GPIOPWM(19) */ ++ 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 ++ 0x00 0x00 0x00 0x00 0x00 0x00 ++ /* MXT244_PROCI_GRIPFACE(20) */ ++ 0x07 0x00 0x00 0x00 0x00 0x00 0x00 0x50 0x28 0x04 ++ 0x0f 0x0a ++ /* MXT244_PROCG_NOISE(22) */ ++ 0x05 0x00 0x00 0x00 0x00 0x00 0x00 0x03 0x23 0x00 ++ 0x00 0x05 0x0f 0x19 0x23 0x2d 0x03 ++ /* MXT244_TOUCH_PROXIMITY(23) */ ++ 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 ++ 0x00 0x00 0x00 0x00 0x00 ++ /* MXT244_PROCI_ONETOUCH(24) */ ++ 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 ++ 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 ++ /* MXT244_SPT_SELFTEST(25) */ ++ 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 ++ 0x00 0x00 0x00 0x00 ++ /* MXT244_PROCI_TWOTOUCH(27) */ ++ 0x00 0x00 0x00 0x00 0x00 0x00 0x00 ++ /* MXT244_SPT_CTECONFIG(28) */ ++ 0x00 0x00 0x02 0x08 0x10 0x00 ++ >; ++ ++ atmel,x_line = <18>; ++ atmel,y_line = <12>; ++ atmel,x_size = <800>; ++ atmel,y_size = <480>; ++ atmel,blen = <0x01>; ++ atmel,threshold = <30>; ++ atmel,voltage = <2800000>; ++ atmel,orient = <0x4>; ++ }; ++}; ++ ++&i2c2 { ++ status = "okay"; ++ pinctrl-names = "default"; ++ pinctrl-0 = <&i2c2_pins>; ++ clock-frequency = <400000>; ++ ++ pcf_hdmi: gpio@26 { ++ compatible = "nxp,pcf8575"; ++ reg = <0x26>; ++ gpio-controller; ++ #gpio-cells = <2>; ++ }; ++}; ++ ++&i2c3 { ++ status = "okay"; ++ pinctrl-names = "default"; ++ pinctrl-0 = <&i2c3_pins>; ++ clock-frequency = <3400000>; ++}; ++ ++&mcspi1 { ++ status = "okay"; ++ pinctrl-names = "default"; ++ pinctrl-0 = <&mcspi1_pins>; ++}; ++ ++&mcspi2 { ++ status = "okay"; ++ pinctrl-names = "default"; ++ pinctrl-0 = <&mcspi2_pins>; ++}; ++ ++&uart1 { ++ status = "okay"; ++ pinctrl-names = "default"; ++ pinctrl-0 = <&uart1_pins>; ++}; ++ ++&uart2 { ++ status = "okay"; ++ pinctrl-names = "default"; ++ pinctrl-0 = <&uart2_pins>; ++}; ++ ++&uart3 { ++ status = "okay"; ++ pinctrl-names = "default"; ++ pinctrl-0 = <&uart3_pins>; ++}; ++ ++&qspi { ++ status = "okay"; ++ pinctrl-names = "default"; ++ pinctrl-0 = <&qspi1_pins>; ++ ++ spi-max-frequency = <48000000>; ++ m25p80@0 { ++ compatible = "s25fl256s1"; ++ spi-max-frequency = <48000000>; ++ reg = <0>; ++ spi-tx-bus-width = <1>; ++ spi-rx-bus-width = <4>; ++ spi-cpol; ++ spi-cpha; ++ }; ++}; ++ ++&usb1 { ++ dr_mode = "peripheral"; ++ pinctrl-names = "default"; ++ pinctrl-0 = <&usb1_pins>; ++}; ++ ++&usb2 { ++ dr_mode = "host"; ++ pinctrl-names = "default"; ++ pinctrl-0 = <&usb2_pins>; ++}; ++ ++&dwc3_1 { ++ extcon = <&extcon1>; ++}; ++ ++&dwc3_2 { ++ extcon = <&extcon2>; ++}; ++ ++&mmc1 { ++ status = "okay"; ++ vmmc-supply = <&ldo1_reg>; ++ bus-width = <4>; ++ pinctrl-names = "default"; ++ pinctrl-0 = <&mmc1_pins>; ++ cd-gpios = <&gpio6 27 0>; /* gpio 187 */ ++}; ++ ++&mmc2 { ++ status = "okay"; ++ vmmc-supply = <&mmc2_3v3>; ++ bus-width = <8>; ++ ti,non-removable; ++}; ++ ++&dss { ++ vdda_video-supply = <&ldoln_reg>; ++}; ++ ++&hdmi { ++ vdda_hdmi_dac-supply = <&ldo3_reg>; ++}; ++ ++&avs_mpu { ++ avs-supply = <&smps123_reg>; ++}; ++ ++&avs_core { ++ avs-supply = <&smps7_reg>; ++}; ++ ++&avs_gpu { ++ avs-supply = <&smps6_reg>; ++}; ++ ++&avs_dspeve { ++ avs-supply = <&smps45_reg>; ++}; ++ ++&avs_iva { ++ avs-supply = <&smps8_reg>; ++}; ++ ++&cpu0 { ++ cpu0-supply = <&avs_mpu>; ++}; ++ ++/ { ++ aliases { ++ display0 = &tlc59108; ++ display1 = &hdmi0; ++ }; ++ ++ tpd12s015: encoder@0 { ++ compatible = "ti,draevm-tpd12s015"; ++ ++ video-source = <&hdmi>; ++ ++ gpios = <&pcf_hdmi 4 0>, /* P4, CT CP HPD */ ++ <&pcf_hdmi 5 0>, /* P5, LS OE */ ++ <&gpio7 12 0>; /* gpio7_12/sp1_cs2, HPD */ ++ }; ++ ++ hdmi0: connector@0 { ++ compatible = "ti,hdmi_connector"; ++ ++ video-source = <&tpd12s015>; ++ }; ++}; ++ ++&mac { ++ status = "okay"; ++ pinctrl-names = "default", "sleep"; ++ pinctrl-0 = <&cpsw_default>; ++ pinctrl-1 = <&cpsw_sleep>; ++}; ++ ++&cpsw_emac0 { ++ phy_id = <&davinci_mdio>, <2>; ++}; ++ ++&cpsw_emac1 { ++ phy_id = <&davinci_mdio>, <3>; ++}; ++ ++&davinci_mdio { ++ pinctrl-names = "default", "sleep"; ++ pinctrl-0 = <&davinci_mdio_default>; ++ pinctrl-1 = <&davinci_mdio_sleep>; ++}; ++ ++&elm { ++ status = "okay"; ++}; ++ ++&gpmc { ++ status = "okay"; ++ pinctrl-names = "default"; ++ pinctrl-0 = <&nand_flash_x16>; ++ ranges = <0 0 0x08000000 0x10000000>; ++ nand@0,0 { ++ reg = <0 0 0>; ++ nand-bus-width = <16>; ++ ti,nand-ecc-opt = "bch8"; ++ gpmc,device-width = <2>; ++ gpmc,sync-clk-ps = <0>; ++ gpmc,cs-on-ns = <0>; ++ gpmc,cs-rd-off-ns = <55>; ++ gpmc,cs-wr-off-ns = <55>; ++ gpmc,adv-on-ns = <0>; ++ gpmc,adv-rd-off-ns = <55>; ++ gpmc,adv-wr-off-ns = <55>; ++ gpmc,we-on-ns = <5>; ++ gpmc,we-off-ns = <40>; ++ gpmc,oe-on-ns = <2>; ++ gpmc,oe-off-ns = <45>; ++ gpmc,access-ns = <40>; ++ gpmc,wr-access-ns = <37>; ++ gpmc,rd-cycle-ns = <55>; ++ gpmc,wr-cycle-ns = <55>; ++ gpmc,wait-on-read = "true"; ++ gpmc,wait-on-write = "true"; ++ gpmc,bus-turnaround-ns = <0>; ++ gpmc,cycle2cycle-delay-ns = <0>; ++ gpmc,clk-activation-ns = <0>; ++ gpmc,wait-monitoring-ns = <0>; ++ gpmc,wr-data-mux-bus-ns = <0>; ++ #address-cells = <1>; ++ #size-cells = <1>; ++ ti,elm-id = <&elm>; ++ /* MTD partition table */ ++ partition@0 { ++ label = "SPL1"; ++ reg = <0x00000000 0x000020000>; ++ }; ++ partition@1 { ++ label = "SPL2"; ++ reg = <0x00020000 0x00020000>; ++ }; ++ partition@2 { ++ label = "SPL3"; ++ reg = <0x00040000 0x00020000>; ++ }; ++ partition@3 { ++ label = "SPL4"; ++ reg = <0x00060000 0x00020000>; ++ }; ++ partition@4 { ++ label = "U-boot"; ++ reg = <0x00080000 0x001e0000>; ++ }; ++ partition@5 { ++ label = "environment"; ++ reg = <0x00260000 0x00020000>; ++ }; ++ partition@6 { ++ label = "Kernel"; ++ reg = <0x00280000 0x00500000>; ++ }; ++ partition@7 { ++ label = "File-System"; ++ reg = <0x00780000 0x0F880000>; ++ }; ++ }; ++}; +--- /dev/null ++++ b/arch/arm/boot/dts/dra7xx-clocks.dtsi +@@ -0,0 +1,2103 @@ ++/* ++ * Device Tree Source for DRA7xx clock data ++ * ++ * Copyright (C) 2013 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. ++ */ ++ ++atl_clkin0_ck: atl_clkin0_ck { ++ #clock-cells = <0>; ++ compatible = "fixed-clock"; ++ clock-frequency = <0>; ++}; ++ ++atl_clkin1_ck: atl_clkin1_ck { ++ #clock-cells = <0>; ++ compatible = "fixed-clock"; ++ clock-frequency = <0>; ++}; ++ ++atl_clkin2_ck: atl_clkin2_ck { ++ #clock-cells = <0>; ++ compatible = "fixed-clock"; ++ clock-frequency = <0>; ++}; ++ ++atlclkin3_ck: atlclkin3_ck { ++ #clock-cells = <0>; ++ compatible = "fixed-clock"; ++ clock-frequency = <0>; ++}; ++ ++hdmi_clkin_ck: hdmi_clkin_ck { ++ #clock-cells = <0>; ++ compatible = "fixed-clock"; ++ clock-frequency = <0>; ++}; ++ ++mlb_clkin_ck: mlb_clkin_ck { ++ #clock-cells = <0>; ++ compatible = "fixed-clock"; ++ clock-frequency = <0>; ++}; ++ ++mlbp_clkin_ck: mlbp_clkin_ck { ++ #clock-cells = <0>; ++ compatible = "fixed-clock"; ++ clock-frequency = <0>; ++}; ++ ++pciesref_acs_clk_ck: pciesref_acs_clk_ck { ++ #clock-cells = <0>; ++ compatible = "fixed-clock"; ++ clock-frequency = <100000000>; ++}; ++ ++ref_clkin0_ck: ref_clkin0_ck { ++ #clock-cells = <0>; ++ compatible = "fixed-clock"; ++ clock-frequency = <0>; ++}; ++ ++ref_clkin1_ck: ref_clkin1_ck { ++ #clock-cells = <0>; ++ compatible = "fixed-clock"; ++ clock-frequency = <0>; ++}; ++ ++ref_clkin2_ck: ref_clkin2_ck { ++ #clock-cells = <0>; ++ compatible = "fixed-clock"; ++ clock-frequency = <0>; ++}; ++ ++ref_clkin3_ck: ref_clkin3_ck { ++ #clock-cells = <0>; ++ compatible = "fixed-clock"; ++ clock-frequency = <0>; ++}; ++ ++rmii_clk_ck: rmii_clk_ck { ++ #clock-cells = <0>; ++ compatible = "fixed-clock"; ++ clock-frequency = <0>; ++}; ++ ++sdvenc_clkin_ck: sdvenc_clkin_ck { ++ #clock-cells = <0>; ++ compatible = "fixed-clock"; ++ clock-frequency = <0>; ++}; ++ ++secure_32k_clk_src_ck: secure_32k_clk_src_ck { ++ #clock-cells = <0>; ++ compatible = "fixed-clock"; ++ clock-frequency = <32768>; ++}; ++ ++sys_32k_ck: sys_32k_ck { ++ #clock-cells = <0>; ++ compatible = "fixed-clock"; ++ clock-frequency = <32768>; ++}; ++ ++virt_12000000_ck: virt_12000000_ck { ++ #clock-cells = <0>; ++ compatible = "fixed-clock"; ++ clock-frequency = <12000000>; ++}; ++ ++virt_13000000_ck: virt_13000000_ck { ++ #clock-cells = <0>; ++ compatible = "fixed-clock"; ++ clock-frequency = <13000000>; ++}; ++ ++virt_16800000_ck: virt_16800000_ck { ++ #clock-cells = <0>; ++ compatible = "fixed-clock"; ++ clock-frequency = <16800000>; ++}; ++ ++virt_19200000_ck: virt_19200000_ck { ++ #clock-cells = <0>; ++ compatible = "fixed-clock"; ++ clock-frequency = <19200000>; ++}; ++ ++virt_20000000_ck: virt_20000000_ck { ++ #clock-cells = <0>; ++ compatible = "fixed-clock"; ++ clock-frequency = <20000000>; ++}; ++ ++virt_26000000_ck: virt_26000000_ck { ++ #clock-cells = <0>; ++ compatible = "fixed-clock"; ++ clock-frequency = <26000000>; ++}; ++ ++virt_27000000_ck: virt_27000000_ck { ++ #clock-cells = <0>; ++ compatible = "fixed-clock"; ++ clock-frequency = <27000000>; ++}; ++ ++virt_38400000_ck: virt_38400000_ck { ++ #clock-cells = <0>; ++ compatible = "fixed-clock"; ++ clock-frequency = <38400000>; ++}; ++ ++sys_clkin1: sys_clkin1@4ae06110 { ++ #clock-cells = <0>; ++ compatible = "mux-clock"; ++ clocks = <&virt_12000000_ck>, <&virt_20000000_ck>, <&virt_16800000_ck>, <&virt_19200000_ck>, <&virt_26000000_ck>, <&virt_27000000_ck>, <&virt_38400000_ck>; ++ reg = <0x4ae06110 0x4>; ++ bit-mask = <0x7>; ++ index-starts-at-one; ++}; ++ ++sys_clkin2: sys_clkin2 { ++ #clock-cells = <0>; ++ compatible = "fixed-clock"; ++ clock-frequency = <22579200>; ++}; ++ ++usb_otg_clkin_ck: usb_otg_clkin_ck { ++ #clock-cells = <0>; ++ compatible = "fixed-clock"; ++ clock-frequency = <0>; ++}; ++ ++video1_clkin_ck: video1_clkin_ck { ++ #clock-cells = <0>; ++ compatible = "fixed-clock"; ++ clock-frequency = <0>; ++}; ++ ++video1_m2_clkin_ck: video1_m2_clkin_ck { ++ #clock-cells = <0>; ++ compatible = "fixed-clock"; ++ clock-frequency = <0>; ++}; ++ ++video2_clkin_ck: video2_clkin_ck { ++ #clock-cells = <0>; ++ compatible = "fixed-clock"; ++ clock-frequency = <0>; ++}; ++ ++video2_m2_clkin_ck: video2_m2_clkin_ck { ++ #clock-cells = <0>; ++ compatible = "fixed-clock"; ++ clock-frequency = <0>; ++}; ++ ++abe_dpll_sys_clk_mux: abe_dpll_sys_clk_mux@4ae06118 { ++ #clock-cells = <0>; ++ compatible = "mux-clock"; ++ clocks = <&sys_clkin1>, <&sys_clkin2>; ++ reg = <0x4ae06118 0x4>; ++ bit-mask = <0x1>; ++}; ++ ++abe_dpll_bypass_clk_mux: abe_dpll_bypass_clk_mux@4ae06114 { ++ #clock-cells = <0>; ++ compatible = "mux-clock"; ++ clocks = <&abe_dpll_sys_clk_mux>, <&sys_32k_ck>; ++ reg = <0x4ae06114 0x4>; ++ bit-mask = <0x1>; ++}; ++ ++abe_dpll_clk_mux: abe_dpll_clk_mux@4ae0610c { ++ #clock-cells = <0>; ++ compatible = "mux-clock"; ++ clocks = <&abe_dpll_sys_clk_mux>, <&sys_32k_ck>; ++ reg = <0x4ae0610c 0x4>; ++ bit-mask = <0x1>; ++}; ++ ++dpll_abe_ck: dpll_abe_ck@4a0051e0 { ++ #clock-cells = <0>; ++ compatible = "ti,omap4-dpll-m4xen-clock"; ++ clocks = <&abe_dpll_clk_mux>, <&abe_dpll_bypass_clk_mux>; ++ reg = <0x4a0051e0 0x4>, <0x4a0051e4 0x4>, <0x4a0051e8 0x4>, <0x4a0051ec 0x4>; ++ reg-names = "control", "idlest", "autoidle", "mult-div1"; ++}; ++ ++dpll_abe_x2_ck: dpll_abe_x2_ck { ++ #clock-cells = <0>; ++ compatible = "ti,omap4-dpll-x2-clock"; ++ clocks = <&dpll_abe_ck>; ++}; ++ ++dpll_abe_m2x2_ck: dpll_abe_m2x2_ck@4a0051f0 { ++ #clock-cells = <0>; ++ compatible = "ti,divider-clock"; ++ clocks = <&dpll_abe_x2_ck>; ++ ti,autoidle-shift = <8>; ++ reg = <0x4a0051f0 0x4>; ++ bit-mask = <0x1f>; ++ index-starts-at-one; ++ ti,autoidle-low; ++}; ++ ++abe_24m_fclk: abe_24m_fclk@4ae0611c { ++ #clock-cells = <0>; ++ compatible = "divider-clock"; ++ clocks = <&dpll_abe_m2x2_ck>; ++ reg = <0x4ae0611c 0x4>; ++ table = < 8 0 >, < 16 1 >; ++ bit-mask = <0x1>; ++}; ++ ++abe_clk: abe_clk@4a005108 { ++ #clock-cells = <0>; ++ compatible = "divider-clock"; ++ clocks = <&dpll_abe_m2x2_ck>; ++ reg = <0x4a005108 0x4>; ++ bit-mask = <0x3>; ++ index-power-of-two; ++}; ++ ++aess_fclk: aess_fclk@4ae06178 { ++ #clock-cells = <0>; ++ compatible = "divider-clock"; ++ clocks = <&abe_clk>; ++ reg = <0x4ae06178 0x4>; ++ bit-mask = <0x1>; ++}; ++ ++abe_giclk_div: abe_giclk_div@4ae06174 { ++ #clock-cells = <0>; ++ compatible = "divider-clock"; ++ clocks = <&aess_fclk>; ++ reg = <0x4ae06174 0x4>; ++ bit-mask = <0x1>; ++}; ++ ++abe_lp_clk_div: abe_lp_clk_div@4ae061d8 { ++ #clock-cells = <0>; ++ compatible = "divider-clock"; ++ clocks = <&dpll_abe_m2x2_ck>; ++ reg = <0x4ae061d8 0x4>; ++ table = < 16 0 >, < 32 1 >; ++ bit-mask = <0x1>; ++}; ++ ++abe_sys_clk_div: abe_sys_clk_div@4ae06120 { ++ #clock-cells = <0>; ++ compatible = "divider-clock"; ++ clocks = <&sys_clkin1>; ++ reg = <0x4ae06120 0x4>; ++ bit-mask = <0x1>; ++}; ++ ++adc_gfclk_mux: adc_gfclk_mux@4ae061dc { ++ #clock-cells = <0>; ++ compatible = "mux-clock"; ++ clocks = <&sys_clkin1>, <&sys_clkin2>, <&sys_32k_ck>; ++ reg = <0x4ae061dc 0x4>; ++ bit-mask = <0x7>; ++}; ++ ++dpll_pcie_ref_ck: dpll_pcie_ref_ck@4a008200 { ++ #clock-cells = <0>; ++ compatible = "ti,omap4-dpll-clock"; ++ clocks = <&sys_clkin1>, <&sys_clkin1>; ++ reg = <0x4a008200 0x4>, <0x4a008204 0x4>, <0x4a008208 0x4>, <0x4a00820c 0x4>; ++ reg-names = "control", "idlest", "autoidle", "mult-div1"; ++}; ++ ++dpll_pcie_ref_m2ldo_ck: dpll_pcie_ref_m2ldo_ck@4a008210 { ++ #clock-cells = <0>; ++ compatible = "ti,divider-clock"; ++ clocks = <&dpll_pcie_ref_ck>; ++ ti,autoidle-shift = <8>; ++ reg = <0x4a008210 0x4>; ++ bit-mask = <0x1f>; ++ index-starts-at-one; ++ ti,autoidle-low; ++}; ++ ++apll_pcie_in_clk_mux: apll_pcie_in_clk_mux@4ae06118 { ++ compatible = "mux-clock"; ++ clocks = <&dpll_pcie_ref_ck>, <&pciesref_acs_clk_ck>; ++ #clock-cells = <0>; ++ reg = <0x4a00821c 0x4>; ++ bit-mask = <0x80>; ++}; ++ ++apll_pcie_ck: apll_pcie_ck@4a008200 { ++ #clock-cells = <0>; ++ compatible = "ti,dra7-apll-clock"; ++ clocks = <&apll_pcie_in_clk_mux>, <&dpll_pcie_ref_ck>; ++ reg = <0x4a00821c 0x4>, <0x4a008220 0x4>; ++ reg-names = "control", "idlest"; ++}; ++ ++apll_pcie_clkvcoldo: apll_pcie_clkvcoldo { ++ #clock-cells = <0>; ++ compatible = "fixed-factor-clock"; ++ clocks = <&apll_pcie_ck>; ++ clock-mult = <1>; ++ clock-div = <1>; ++}; ++ ++apll_pcie_clkvcoldo_div: apll_pcie_clkvcoldo_div { ++ #clock-cells = <0>; ++ compatible = "fixed-factor-clock"; ++ clocks = <&apll_pcie_ck>; ++ clock-mult = <1>; ++ clock-div = <1>; ++}; ++ ++apll_pcie_m2_ck: apll_pcie_m2_ck@4a008224 { ++ #clock-cells = <0>; ++ compatible = "fixed-factor-clock"; ++ clocks = <&apll_pcie_ck>; ++ clock-mult = <1>; ++ clock-div = <1>; ++}; ++ ++sys_clk1_dclk_div: sys_clk1_dclk_div@4ae061c8 { ++ #clock-cells = <0>; ++ compatible = "divider-clock"; ++ clocks = <&sys_clkin1>; ++ reg = <0x4ae061c8 0x4>; ++ bit-mask = <0x7>; ++ index-power-of-two; ++}; ++ ++sys_clk2_dclk_div: sys_clk2_dclk_div@4ae061cc { ++ #clock-cells = <0>; ++ compatible = "divider-clock"; ++ clocks = <&sys_clkin2>; ++ reg = <0x4ae061cc 0x4>; ++ bit-mask = <0x7>; ++ index-power-of-two; ++}; ++ ++dpll_abe_m2_ck: dpll_abe_m2_ck@4a0051f0 { ++ #clock-cells = <0>; ++ compatible = "ti,divider-clock"; ++ clocks = <&dpll_abe_ck>; ++ ti,autoidle-shift = <8>; ++ reg = <0x4a0051f0 0x4>; ++ bit-mask = <0x1f>; ++ index-starts-at-one; ++ ti,autoidle-low; ++}; ++ ++per_abe_x1_dclk_div: per_abe_x1_dclk_div@4ae061bc { ++ #clock-cells = <0>; ++ compatible = "divider-clock"; ++ clocks = <&dpll_abe_m2_ck>; ++ reg = <0x4ae061bc 0x4>; ++ bit-mask = <0x7>; ++ index-power-of-two; ++}; ++ ++dpll_abe_m3x2_ck: dpll_abe_m3x2_ck@4a0051f4 { ++ #clock-cells = <0>; ++ compatible = "ti,divider-clock"; ++ clocks = <&dpll_abe_x2_ck>; ++ ti,autoidle-shift = <8>; ++ reg = <0x4a0051f4 0x4>; ++ bit-mask = <0x1f>; ++ index-starts-at-one; ++ ti,autoidle-low; ++}; ++ ++dpll_core_ck: dpll_core_ck@4a005120 { ++ #clock-cells = <0>; ++ compatible = "ti,omap4-dpll-core-clock"; ++ clocks = <&sys_clkin1>, <&dpll_abe_m3x2_ck>; ++ reg = <0x4a005120 0x4>, <0x4a005124 0x4>, <0x4a005128 0x4>, <0x4a00512c 0x4>; ++ reg-names = "control", "idlest", "autoidle", "mult-div1"; ++}; ++ ++dpll_core_x2_ck: dpll_core_x2_ck { ++ #clock-cells = <0>; ++ compatible = "ti,omap4-dpll-x2-clock"; ++ clocks = <&dpll_core_ck>; ++}; ++ ++dpll_core_h12x2_ck: dpll_core_h12x2_ck@4a00513c { ++ #clock-cells = <0>; ++ compatible = "ti,divider-clock"; ++ clocks = <&dpll_core_x2_ck>; ++ ti,autoidle-shift = <8>; ++ reg = <0x4a00513c 0x4>; ++ bit-mask = <0x3f>; ++ index-starts-at-one; ++ ti,autoidle-low; ++}; ++ ++mpu_dpll_hs_clk_div: mpu_dpll_hs_clk_div { ++ #clock-cells = <0>; ++ compatible = "fixed-factor-clock"; ++ clocks = <&dpll_core_h12x2_ck>; ++ clock-mult = <1>; ++ clock-div = <1>; ++}; ++ ++dpll_mpu_ck: dpll_mpu_ck@4a005160 { ++ #clock-cells = <0>; ++ compatible = "ti,omap4-dpll-clock"; ++ clocks = <&sys_clkin1>, <&mpu_dpll_hs_clk_div>; ++ reg = <0x4a005160 0x4>, <0x4a005164 0x4>, <0x4a005168 0x4>, <0x4a00516c 0x4>; ++ reg-names = "control", "idlest", "autoidle", "mult-div1"; ++}; ++ ++dpll_mpu_m2_ck: dpll_mpu_m2_ck@4a005170 { ++ #clock-cells = <0>; ++ compatible = "ti,divider-clock"; ++ clocks = <&dpll_mpu_ck>; ++ ti,autoidle-shift = <8>; ++ reg = <0x4a005170 0x4>; ++ bit-mask = <0x1f>; ++ index-starts-at-one; ++ ti,autoidle-low; ++}; ++ ++mpu_dclk_div: mpu_dclk_div { ++ #clock-cells = <0>; ++ compatible = "fixed-factor-clock"; ++ clocks = <&dpll_mpu_m2_ck>; ++ clock-mult = <1>; ++ clock-div = <1>; ++}; ++ ++dsp_dpll_hs_clk_div: dsp_dpll_hs_clk_div { ++ #clock-cells = <0>; ++ compatible = "fixed-factor-clock"; ++ clocks = <&dpll_core_h12x2_ck>; ++ clock-mult = <1>; ++ clock-div = <1>; ++}; ++ ++dpll_dsp_ck: dpll_dsp_ck@4a005234 { ++ #clock-cells = <0>; ++ compatible = "ti,omap4-dpll-clock"; ++ clocks = <&sys_clkin1>, <&dsp_dpll_hs_clk_div>; ++ reg = <0x4a005234 0x4>, <0x4a005238 0x4>, <0x4a00523c 0x4>, <0x4a005240 0x4>; ++ reg-names = "control", "idlest", "autoidle", "mult-div1"; ++}; ++ ++dpll_dsp_m2_ck: dpll_dsp_m2_ck@4a005244 { ++ #clock-cells = <0>; ++ compatible = "ti,divider-clock"; ++ clocks = <&dpll_dsp_ck>; ++ ti,autoidle-shift = <8>; ++ reg = <0x4a005244 0x4>; ++ bit-mask = <0x1f>; ++ index-starts-at-one; ++ ti,autoidle-low; ++}; ++ ++dsp_gclk_div: dsp_gclk_div@4ae0618c { ++ #clock-cells = <0>; ++ compatible = "divider-clock"; ++ clocks = <&dpll_dsp_m2_ck>; ++ reg = <0x4ae0618c 0x4>; ++ bit-mask = <0x7>; ++ index-power-of-two; ++}; ++ ++iva_dpll_hs_clk_div: iva_dpll_hs_clk_div { ++ #clock-cells = <0>; ++ compatible = "fixed-factor-clock"; ++ clocks = <&dpll_core_h12x2_ck>; ++ clock-mult = <1>; ++ clock-div = <1>; ++}; ++ ++dpll_iva_ck: dpll_iva_ck@4a0051a0 { ++ #clock-cells = <0>; ++ compatible = "ti,omap4-dpll-clock"; ++ clocks = <&sys_clkin1>, <&iva_dpll_hs_clk_div>; ++ reg = <0x4a0051a0 0x4>, <0x4a0051a4 0x4>, <0x4a0051a8 0x4>, <0x4a0051ac 0x4>; ++ reg-names = "control", "idlest", "autoidle", "mult-div1"; ++}; ++ ++dpll_iva_m2_ck: dpll_iva_m2_ck@4a0051b0 { ++ #clock-cells = <0>; ++ compatible = "ti,divider-clock"; ++ clocks = <&dpll_iva_ck>; ++ ti,autoidle-shift = <8>; ++ reg = <0x4a0051b0 0x4>; ++ bit-mask = <0x1f>; ++ index-starts-at-one; ++ ti,autoidle-low; ++}; ++ ++iva_dclk: iva_dclk { ++ #clock-cells = <0>; ++ compatible = "fixed-factor-clock"; ++ clocks = <&dpll_iva_m2_ck>; ++ clock-mult = <1>; ++ clock-div = <1>; ++}; ++ ++dpll_gpu_ck: dpll_gpu_ck@4a0052d8 { ++ #clock-cells = <0>; ++ compatible = "ti,omap4-dpll-clock"; ++ clocks = <&sys_clkin1>, <&dpll_abe_m3x2_ck>; ++ reg = <0x4a0052d8 0x4>, <0x4a0052dc 0x4>, <0x4a0052e0 0x4>, <0x4a0052e4 0x4>; ++ reg-names = "control", "idlest", "autoidle", "mult-div1"; ++}; ++ ++dpll_gpu_m2_ck: dpll_gpu_m2_ck@4a0052e8 { ++ #clock-cells = <0>; ++ compatible = "ti,divider-clock"; ++ clocks = <&dpll_gpu_ck>; ++ ti,autoidle-shift = <8>; ++ reg = <0x4a0052e8 0x4>; ++ bit-mask = <0x1f>; ++ index-starts-at-one; ++ ti,autoidle-low; ++}; ++ ++gpu_dclk: gpu_dclk@4ae061a0 { ++ #clock-cells = <0>; ++ compatible = "divider-clock"; ++ clocks = <&dpll_gpu_m2_ck>; ++ reg = <0x4ae061a0 0x4>; ++ bit-mask = <0x7>; ++ index-power-of-two; ++}; ++ ++dpll_core_m2_ck: dpll_core_m2_ck@4a005130 { ++ #clock-cells = <0>; ++ compatible = "ti,divider-clock"; ++ clocks = <&dpll_core_ck>; ++ ti,autoidle-shift = <8>; ++ reg = <0x4a005130 0x4>; ++ bit-mask = <0x1f>; ++ index-starts-at-one; ++ ti,autoidle-low; ++}; ++ ++core_dpll_out_dclk_div: core_dpll_out_dclk_div { ++ #clock-cells = <0>; ++ compatible = "fixed-factor-clock"; ++ clocks = <&dpll_core_m2_ck>; ++ clock-mult = <1>; ++ clock-div = <1>; ++}; ++ ++dpll_ddr_ck: dpll_ddr_ck@4a005210 { ++ #clock-cells = <0>; ++ compatible = "ti,omap4-dpll-clock"; ++ clocks = <&sys_clkin1>, <&dpll_abe_m3x2_ck>; ++ reg = <0x4a005210 0x4>, <0x4a005214 0x4>, <0x4a005218 0x4>, <0x4a00521c 0x4>; ++ reg-names = "control", "idlest", "autoidle", "mult-div1"; ++}; ++ ++dpll_ddr_m2_ck: dpll_ddr_m2_ck@4a005220 { ++ #clock-cells = <0>; ++ compatible = "ti,divider-clock"; ++ clocks = <&dpll_ddr_ck>; ++ ti,autoidle-shift = <8>; ++ reg = <0x4a005220 0x4>; ++ bit-mask = <0x1f>; ++ index-starts-at-one; ++ ti,autoidle-low; ++}; ++ ++emif_phy_dclk_div: emif_phy_dclk_div@4ae06190 { ++ #clock-cells = <0>; ++ compatible = "divider-clock"; ++ clocks = <&dpll_ddr_m2_ck>; ++ reg = <0x4ae06190 0x4>; ++ bit-mask = <0x7>; ++ index-power-of-two; ++}; ++ ++dpll_gmac_ck: dpll_gmac_ck@4a0052a8 { ++ #clock-cells = <0>; ++ compatible = "ti,omap4-dpll-clock"; ++ clocks = <&sys_clkin1>, <&dpll_abe_m3x2_ck>; ++ reg = <0x4a0052a8 0x4>, <0x4a0052ac 0x4>, <0x4a0052b0 0x4>, <0x4a0052b4 0x4>; ++ reg-names = "control", "idlest", "autoidle", "mult-div1"; ++}; ++ ++dpll_gmac_m2_ck: dpll_gmac_m2_ck@4a0052b8 { ++ #clock-cells = <0>; ++ compatible = "ti,divider-clock"; ++ clocks = <&dpll_gmac_ck>; ++ ti,autoidle-shift = <8>; ++ reg = <0x4a0052b8 0x4>; ++ bit-mask = <0x1f>; ++ index-starts-at-one; ++ ti,autoidle-low; ++}; ++ ++gmac_250m_dclk_div: gmac_250m_dclk_div@4ae0619c { ++ #clock-cells = <0>; ++ compatible = "divider-clock"; ++ clocks = <&dpll_gmac_m2_ck>; ++ reg = <0x4ae0619c 0x4>; ++ bit-mask = <0x7>; ++ index-power-of-two; ++}; ++ ++video2_dclk_div: video2_dclk_div { ++ #clock-cells = <0>; ++ compatible = "fixed-factor-clock"; ++ clocks = <&video2_m2_clkin_ck>; ++ clock-mult = <1>; ++ clock-div = <1>; ++}; ++ ++video1_dclk_div: video1_dclk_div { ++ #clock-cells = <0>; ++ compatible = "fixed-factor-clock"; ++ clocks = <&video1_m2_clkin_ck>; ++ clock-mult = <1>; ++ clock-div = <1>; ++}; ++ ++hdmi_dclk_div: hdmi_dclk_div { ++ #clock-cells = <0>; ++ compatible = "fixed-factor-clock"; ++ clocks = <&hdmi_clkin_ck>; ++ clock-mult = <1>; ++ clock-div = <1>; ++}; ++ ++per_dpll_hs_clk_div: per_dpll_hs_clk_div { ++ #clock-cells = <0>; ++ compatible = "fixed-factor-clock"; ++ clocks = <&dpll_abe_m3x2_ck>; ++ clock-mult = <1>; ++ clock-div = <2>; ++}; ++ ++dpll_per_ck: dpll_per_ck@4a008140 { ++ #clock-cells = <0>; ++ compatible = "ti,omap4-dpll-clock"; ++ clocks = <&sys_clkin1>, <&per_dpll_hs_clk_div>; ++ reg = <0x4a008140 0x4>, <0x4a008144 0x4>, <0x4a008148 0x4>, <0x4a00814c 0x4>; ++ reg-names = "control", "idlest", "autoidle", "mult-div1"; ++}; ++ ++dpll_per_m2_ck: dpll_per_m2_ck@4a008150 { ++ #clock-cells = <0>; ++ compatible = "ti,divider-clock"; ++ clocks = <&dpll_per_ck>; ++ ti,autoidle-shift = <8>; ++ reg = <0x4a008150 0x4>; ++ bit-mask = <0x1f>; ++ index-starts-at-one; ++ ti,autoidle-low; ++}; ++ ++func_96m_aon_dclk_div: func_96m_aon_dclk_div { ++ #clock-cells = <0>; ++ compatible = "fixed-factor-clock"; ++ clocks = <&dpll_per_m2_ck>; ++ clock-mult = <1>; ++ clock-div = <1>; ++}; ++ ++usb_dpll_hs_clk_div: usb_dpll_hs_clk_div { ++ #clock-cells = <0>; ++ compatible = "fixed-factor-clock"; ++ clocks = <&dpll_abe_m3x2_ck>; ++ clock-mult = <1>; ++ clock-div = <3>; ++}; ++ ++dpll_usb_ck: dpll_usb_ck@4a008180 { ++ #clock-cells = <0>; ++ compatible = "ti,omap4-dpll-j-type-clock"; ++ clocks = <&sys_clkin1>, <&usb_dpll_hs_clk_div>; ++ reg = <0x4a008180 0x4>, <0x4a008184 0x4>, <0x4a008188 0x4>, <0x4a00818c 0x4>; ++ reg-names = "control", "idlest", "autoidle", "mult-div1"; ++}; ++ ++dpll_usb_m2_ck: dpll_usb_m2_ck@4a008190 { ++ #clock-cells = <0>; ++ compatible = "ti,divider-clock"; ++ clocks = <&dpll_usb_ck>; ++ ti,autoidle-shift = <8>; ++ reg = <0x4a008190 0x4>; ++ bit-mask = <0x7f>; ++ index-starts-at-one; ++ ti,autoidle-low; ++}; ++ ++l3init_480m_dclk_div: l3init_480m_dclk_div@4ae061ac { ++ #clock-cells = <0>; ++ compatible = "divider-clock"; ++ clocks = <&dpll_usb_m2_ck>; ++ reg = <0x4ae061ac 0x4>; ++ bit-mask = <0x7>; ++ index-power-of-two; ++}; ++ ++usb_otg_dclk_div: usb_otg_dclk_div@4ae06184 { ++ #clock-cells = <0>; ++ compatible = "divider-clock"; ++ clocks = <&usb_otg_clkin_ck>; ++ reg = <0x4ae06184 0x4>; ++ bit-mask = <0x7>; ++ index-power-of-two; ++}; ++ ++sata_dclk_div: sata_dclk_div@4ae061c0 { ++ #clock-cells = <0>; ++ compatible = "divider-clock"; ++ clocks = <&sys_clkin1>; ++ reg = <0x4ae061c0 0x4>; ++ bit-mask = <0x7>; ++ index-power-of-two; ++}; ++ ++dpll_pcie_ref_m2_ck: dpll_pcie_ref_m2_ck@4a008210 { ++ #clock-cells = <0>; ++ compatible = "ti,divider-clock"; ++ clocks = <&dpll_pcie_ref_ck>; ++ ti,autoidle-shift = <8>; ++ reg = <0x4a008210 0x4>; ++ bit-mask = <0x7f>; ++ index-starts-at-one; ++ ti,autoidle-low; ++}; ++ ++pcie2_dclk_div: pcie2_dclk_div@4ae061b8 { ++ #clock-cells = <0>; ++ compatible = "divider-clock"; ++ clocks = <&dpll_pcie_ref_m2_ck>; ++ reg = <0x4ae061b8 0x4>; ++ bit-mask = <0x7>; ++ index-power-of-two; ++}; ++ ++pcie_dclk_div: pcie_dclk_div@4ae061b4 { ++ #clock-cells = <0>; ++ compatible = "divider-clock"; ++ clocks = <&apll_pcie_m2_ck>; ++ reg = <0x4ae061b4 0x4>; ++ bit-mask = <0x7>; ++ index-power-of-two; ++}; ++ ++emu_dclk_div: emu_dclk_div@4ae06194 { ++ #clock-cells = <0>; ++ compatible = "divider-clock"; ++ clocks = <&sys_clkin1>; ++ reg = <0x4ae06194 0x4>; ++ bit-mask = <0x7>; ++ index-power-of-two; ++}; ++ ++secure_32k_dclk_div: secure_32k_dclk_div@4ae061c4 { ++ #clock-cells = <0>; ++ compatible = "divider-clock"; ++ clocks = <&secure_32k_clk_src_ck>; ++ reg = <0x4ae061c4 0x4>; ++ bit-mask = <0x7>; ++ index-power-of-two; ++}; ++ ++eve_dpll_hs_clk_div: eve_dpll_hs_clk_div { ++ #clock-cells = <0>; ++ compatible = "fixed-factor-clock"; ++ clocks = <&dpll_core_h12x2_ck>; ++ clock-mult = <1>; ++ clock-div = <1>; ++}; ++ ++dpll_eve_ck: dpll_eve_ck@4a005284 { ++ #clock-cells = <0>; ++ compatible = "ti,omap4-dpll-clock"; ++ clocks = <&sys_clkin1>, <&eve_dpll_hs_clk_div>; ++ reg = <0x4a005284 0x4>, <0x4a005288 0x4>, <0x4a00528c 0x4>, <0x4a005290 0x4>; ++ reg-names = "control", "idlest", "autoidle", "mult-div1"; ++}; ++ ++dpll_eve_m2_ck: dpll_eve_m2_ck@4a005294 { ++ #clock-cells = <0>; ++ compatible = "ti,divider-clock"; ++ clocks = <&dpll_eve_ck>; ++ ti,autoidle-shift = <8>; ++ reg = <0x4a005294 0x4>; ++ bit-mask = <0x1f>; ++ index-starts-at-one; ++ ti,autoidle-low; ++}; ++ ++eve_dclk_div: eve_dclk_div { ++ #clock-cells = <0>; ++ compatible = "fixed-factor-clock"; ++ clocks = <&dpll_eve_m2_ck>; ++ clock-mult = <1>; ++ clock-div = <1>; ++}; ++ ++clkoutmux0_clk_mux: clkoutmux0_clk_mux@4ae06158 { ++ #clock-cells = <0>; ++ compatible = "mux-clock"; ++ clocks = <&sys_clk1_dclk_div>, <&sys_clk2_dclk_div>, <&per_abe_x1_dclk_div>, <&mpu_dclk_div>, <&dsp_gclk_div>, <&iva_dclk>, <&gpu_dclk>, <&core_dpll_out_dclk_div>, <&emif_phy_dclk_div>, <&gmac_250m_dclk_div>, <&video2_dclk_div>, <&video1_dclk_div>, <&hdmi_dclk_div>, <&func_96m_aon_dclk_div>, <&l3init_480m_dclk_div>, <&usb_otg_dclk_div>, <&sata_dclk_div>, <&pcie2_dclk_div>, <&pcie_dclk_div>, <&emu_dclk_div>, <&secure_32k_dclk_div>, <&eve_dclk_div>; ++ reg = <0x4ae06158 0x4>; ++ bit-mask = <0x1f>; ++}; ++ ++clkoutmux1_clk_mux: clkoutmux1_clk_mux@4ae0615c { ++ #clock-cells = <0>; ++ compatible = "mux-clock"; ++ clocks = <&sys_clk1_dclk_div>, <&sys_clk2_dclk_div>, <&per_abe_x1_dclk_div>, <&mpu_dclk_div>, <&dsp_gclk_div>, <&iva_dclk>, <&gpu_dclk>, <&core_dpll_out_dclk_div>, <&emif_phy_dclk_div>, <&gmac_250m_dclk_div>, <&video2_dclk_div>, <&video1_dclk_div>, <&hdmi_dclk_div>, <&func_96m_aon_dclk_div>, <&l3init_480m_dclk_div>, <&usb_otg_dclk_div>, <&sata_dclk_div>, <&pcie2_dclk_div>, <&pcie_dclk_div>, <&emu_dclk_div>, <&secure_32k_dclk_div>, <&eve_dclk_div>; ++ reg = <0x4ae0615c 0x4>; ++ bit-mask = <0x1f>; ++}; ++ ++clkoutmux2_clk_mux: clkoutmux2_clk_mux@4ae06160 { ++ #clock-cells = <0>; ++ compatible = "mux-clock"; ++ clocks = <&sys_clk1_dclk_div>, <&sys_clk2_dclk_div>, <&per_abe_x1_dclk_div>, <&mpu_dclk_div>, <&dsp_gclk_div>, <&iva_dclk>, <&gpu_dclk>, <&core_dpll_out_dclk_div>, <&emif_phy_dclk_div>, <&gmac_250m_dclk_div>, <&video2_dclk_div>, <&video1_dclk_div>, <&hdmi_dclk_div>, <&func_96m_aon_dclk_div>, <&l3init_480m_dclk_div>, <&usb_otg_dclk_div>, <&sata_dclk_div>, <&pcie2_dclk_div>, <&pcie_dclk_div>, <&emu_dclk_div>, <&secure_32k_dclk_div>, <&eve_dclk_div>; ++ reg = <0x4ae06160 0x4>; ++ bit-mask = <0x1f>; ++}; ++ ++custefuse_sys_gfclk_div: custefuse_sys_gfclk_div { ++ #clock-cells = <0>; ++ compatible = "fixed-factor-clock"; ++ clocks = <&sys_clkin1>; ++ clock-mult = <1>; ++ clock-div = <2>; ++}; ++ ++dpll_core_h13x2_ck: dpll_core_h13x2_ck@4a005140 { ++ #clock-cells = <0>; ++ compatible = "ti,divider-clock"; ++ clocks = <&dpll_core_x2_ck>; ++ ti,autoidle-shift = <8>; ++ reg = <0x4a005140 0x4>; ++ bit-mask = <0x3f>; ++ index-starts-at-one; ++ ti,autoidle-low; ++}; ++ ++dpll_core_h14x2_ck: dpll_core_h14x2_ck@4a005144 { ++ #clock-cells = <0>; ++ compatible = "ti,divider-clock"; ++ clocks = <&dpll_core_x2_ck>; ++ ti,autoidle-shift = <8>; ++ reg = <0x4a005144 0x4>; ++ bit-mask = <0x3f>; ++ index-starts-at-one; ++ ti,autoidle-low; ++}; ++ ++dpll_core_h22x2_ck: dpll_core_h22x2_ck@4a005154 { ++ #clock-cells = <0>; ++ compatible = "ti,divider-clock"; ++ clocks = <&dpll_core_x2_ck>; ++ ti,autoidle-shift = <8>; ++ reg = <0x4a005154 0x4>; ++ bit-mask = <0x3f>; ++ index-starts-at-one; ++ ti,autoidle-low; ++}; ++ ++dpll_core_h23x2_ck: dpll_core_h23x2_ck@4a005158 { ++ #clock-cells = <0>; ++ compatible = "ti,divider-clock"; ++ clocks = <&dpll_core_x2_ck>; ++ ti,autoidle-shift = <8>; ++ reg = <0x4a005158 0x4>; ++ bit-mask = <0x3f>; ++ index-starts-at-one; ++ ti,autoidle-low; ++}; ++ ++dpll_core_h24x2_ck: dpll_core_h24x2_ck@4a00515c { ++ #clock-cells = <0>; ++ compatible = "ti,divider-clock"; ++ clocks = <&dpll_core_x2_ck>; ++ ti,autoidle-shift = <8>; ++ reg = <0x4a00515c 0x4>; ++ bit-mask = <0x3f>; ++ index-starts-at-one; ++ ti,autoidle-low; ++}; ++ ++dpll_ddr_x2_ck: dpll_ddr_x2_ck { ++ #clock-cells = <0>; ++ compatible = "ti,omap4-dpll-x2-clock"; ++ clocks = <&dpll_ddr_ck>; ++}; ++ ++dpll_ddr_h11x2_ck: dpll_ddr_h11x2_ck@4a005228 { ++ #clock-cells = <0>; ++ compatible = "ti,divider-clock"; ++ clocks = <&dpll_ddr_x2_ck>; ++ ti,autoidle-shift = <8>; ++ reg = <0x4a005228 0x4>; ++ bit-mask = <0x3f>; ++ index-starts-at-one; ++ ti,autoidle-low; ++}; ++ ++dpll_dsp_x2_ck: dpll_dsp_x2_ck { ++ #clock-cells = <0>; ++ compatible = "ti,omap4-dpll-x2-clock"; ++ clocks = <&dpll_dsp_ck>; ++}; ++ ++dpll_dsp_m3x2_ck: dpll_dsp_m3x2_ck@4a005248 { ++ #clock-cells = <0>; ++ compatible = "ti,divider-clock"; ++ clocks = <&dpll_dsp_x2_ck>; ++ ti,autoidle-shift = <8>; ++ reg = <0x4a005248 0x4>; ++ bit-mask = <0x1f>; ++ index-starts-at-one; ++ ti,autoidle-low; ++}; ++ ++dpll_gmac_x2_ck: dpll_gmac_x2_ck { ++ #clock-cells = <0>; ++ compatible = "ti,omap4-dpll-x2-clock"; ++ clocks = <&dpll_gmac_ck>; ++}; ++ ++dpll_gmac_h11x2_ck: dpll_gmac_h11x2_ck@4a0052c0 { ++ #clock-cells = <0>; ++ compatible = "ti,divider-clock"; ++ clocks = <&dpll_gmac_x2_ck>; ++ ti,autoidle-shift = <8>; ++ reg = <0x4a0052c0 0x4>; ++ bit-mask = <0x3f>; ++ index-starts-at-one; ++ ti,autoidle-low; ++}; ++ ++dpll_gmac_h12x2_ck: dpll_gmac_h12x2_ck@4a0052c4 { ++ #clock-cells = <0>; ++ compatible = "ti,divider-clock"; ++ clocks = <&dpll_gmac_x2_ck>; ++ ti,autoidle-shift = <8>; ++ reg = <0x4a0052c4 0x4>; ++ bit-mask = <0x3f>; ++ index-starts-at-one; ++ ti,autoidle-low; ++}; ++ ++dpll_gmac_h13x2_ck: dpll_gmac_h13x2_ck@4a0052c8 { ++ #clock-cells = <0>; ++ compatible = "ti,divider-clock"; ++ clocks = <&dpll_gmac_x2_ck>; ++ ti,autoidle-shift = <8>; ++ reg = <0x4a0052c8 0x4>; ++ bit-mask = <0x3f>; ++ index-starts-at-one; ++ ti,autoidle-low; ++}; ++ ++dpll_gmac_m3x2_ck: dpll_gmac_m3x2_ck@4a0052bc { ++ #clock-cells = <0>; ++ compatible = "ti,divider-clock"; ++ clocks = <&dpll_gmac_x2_ck>; ++ ti,autoidle-shift = <8>; ++ reg = <0x4a0052bc 0x4>; ++ bit-mask = <0x1f>; ++ index-starts-at-one; ++ ti,autoidle-low; ++}; ++ ++dpll_per_x2_ck: dpll_per_x2_ck { ++ #clock-cells = <0>; ++ compatible = "ti,omap4-dpll-x2-clock"; ++ clocks = <&dpll_per_ck>; ++}; ++ ++dpll_per_h11x2_ck: dpll_per_h11x2_ck@4a008158 { ++ #clock-cells = <0>; ++ compatible = "ti,divider-clock"; ++ clocks = <&dpll_per_x2_ck>; ++ ti,autoidle-shift = <8>; ++ reg = <0x4a008158 0x4>; ++ bit-mask = <0x3f>; ++ index-starts-at-one; ++ ti,autoidle-low; ++}; ++ ++dpll_per_h12x2_ck: dpll_per_h12x2_ck@4a00815c { ++ #clock-cells = <0>; ++ compatible = "ti,divider-clock"; ++ clocks = <&dpll_per_x2_ck>; ++ ti,autoidle-shift = <8>; ++ reg = <0x4a00815c 0x4>; ++ bit-mask = <0x3f>; ++ index-starts-at-one; ++ ti,autoidle-low; ++}; ++ ++dpll_per_h13x2_ck: dpll_per_h13x2_ck@4a008160 { ++ #clock-cells = <0>; ++ compatible = "ti,divider-clock"; ++ clocks = <&dpll_per_x2_ck>; ++ ti,autoidle-shift = <8>; ++ reg = <0x4a008160 0x4>; ++ bit-mask = <0x3f>; ++ index-starts-at-one; ++ ti,autoidle-low; ++}; ++ ++dpll_per_h14x2_ck: dpll_per_h14x2_ck@4a008164 { ++ #clock-cells = <0>; ++ compatible = "ti,divider-clock"; ++ clocks = <&dpll_per_x2_ck>; ++ ti,autoidle-shift = <8>; ++ reg = <0x4a008164 0x4>; ++ bit-mask = <0x3f>; ++ index-starts-at-one; ++ ti,autoidle-low; ++}; ++ ++dpll_per_m2x2_ck: dpll_per_m2x2_ck@4a008150 { ++ #clock-cells = <0>; ++ compatible = "ti,divider-clock"; ++ clocks = <&dpll_per_x2_ck>; ++ ti,autoidle-shift = <8>; ++ reg = <0x4a008150 0x4>; ++ bit-mask = <0x1f>; ++ index-starts-at-one; ++ ti,autoidle-low; ++}; ++ ++dpll_usb_clkdcoldo: dpll_usb_clkdcoldo { ++ #clock-cells = <0>; ++ compatible = "fixed-factor-clock"; ++ clocks = <&dpll_usb_ck>; ++ clock-mult = <1>; ++ clock-div = <1>; ++}; ++ ++eve_clk: eve_clk@4ae06180 { ++ #clock-cells = <0>; ++ compatible = "mux-clock"; ++ clocks = <&dpll_eve_m2_ck>, <&dpll_dsp_m3x2_ck>; ++ reg = <0x4ae06180 0x4>; ++ bit-mask = <0x1>; ++}; ++ ++func_128m_clk: func_128m_clk { ++ #clock-cells = <0>; ++ compatible = "fixed-factor-clock"; ++ clocks = <&dpll_per_h11x2_ck>; ++ clock-mult = <1>; ++ clock-div = <2>; ++}; ++ ++func_12m_fclk: func_12m_fclk { ++ #clock-cells = <0>; ++ compatible = "fixed-factor-clock"; ++ clocks = <&dpll_per_m2x2_ck>; ++ clock-mult = <1>; ++ clock-div = <16>; ++}; ++ ++func_24m_clk: func_24m_clk { ++ #clock-cells = <0>; ++ compatible = "fixed-factor-clock"; ++ clocks = <&dpll_per_m2_ck>; ++ clock-mult = <1>; ++ clock-div = <4>; ++}; ++ ++func_48m_fclk: func_48m_fclk { ++ #clock-cells = <0>; ++ compatible = "fixed-factor-clock"; ++ clocks = <&dpll_per_m2x2_ck>; ++ clock-mult = <1>; ++ clock-div = <4>; ++}; ++ ++func_96m_fclk: func_96m_fclk { ++ #clock-cells = <0>; ++ compatible = "fixed-factor-clock"; ++ clocks = <&dpll_per_m2x2_ck>; ++ clock-mult = <1>; ++ clock-div = <2>; ++}; ++ ++gmii_m_clk_div: gmii_m_clk_div { ++ #clock-cells = <0>; ++ compatible = "fixed-factor-clock"; ++ clocks = <&dpll_gmac_h11x2_ck>; ++ clock-mult = <1>; ++ clock-div = <2>; ++}; ++ ++hdmi_clk2_div: hdmi_clk2_div { ++ #clock-cells = <0>; ++ compatible = "fixed-factor-clock"; ++ clocks = <&hdmi_clkin_ck>; ++ clock-mult = <1>; ++ clock-div = <1>; ++}; ++ ++hdmi_div_clk: hdmi_div_clk { ++ #clock-cells = <0>; ++ compatible = "fixed-factor-clock"; ++ clocks = <&hdmi_clkin_ck>; ++ clock-mult = <1>; ++ clock-div = <1>; ++}; ++ ++hdmi_dpll_clk_mux: hdmi_dpll_clk_mux@4ae061a4 { ++ #clock-cells = <0>; ++ compatible = "mux-clock"; ++ clocks = <&sys_clkin1>, <&sys_clkin2>; ++ reg = <0x4ae061a4 0x4>; ++ bit-mask = <0x7>; ++}; ++ ++l3_iclk_div: l3_iclk_div { ++ #clock-cells = <0>; ++ compatible = "fixed-factor-clock"; ++ clocks = <&dpll_core_h12x2_ck>; ++ clock-mult = <1>; ++ clock-div = <1>; ++}; ++ ++l3init_60m_fclk: l3init_60m_fclk@4a008104 { ++ #clock-cells = <0>; ++ compatible = "divider-clock"; ++ clocks = <&dpll_usb_m2_ck>; ++ reg = <0x4a008104 0x4>; ++ table = < 1 0 >, < 8 1 >; ++ bit-mask = <0x1>; ++}; ++ ++l3init_960m_gfclk: l3init_960m_gfclk@4a0086c0 { ++ #clock-cells = <0>; ++ compatible = "gate-clock"; ++ clocks = <&dpll_usb_clkdcoldo>; ++ bit-shift = <8>; ++ reg = <0x4a0086c0 0x4>; ++}; ++ ++l4_root_clk_div: l4_root_clk_div { ++ #clock-cells = <0>; ++ compatible = "fixed-factor-clock"; ++ clocks = <&l3_iclk_div>; ++ clock-mult = <1>; ++ clock-div = <1>; ++}; ++ ++mlb_clk: mlb_clk@4ae06134 { ++ #clock-cells = <0>; ++ compatible = "divider-clock"; ++ clocks = <&mlb_clkin_ck>; ++ reg = <0x4ae06134 0x4>; ++ bit-mask = <0x7>; ++ index-power-of-two; ++}; ++ ++mlbp_clk: mlbp_clk@4ae06130 { ++ #clock-cells = <0>; ++ compatible = "divider-clock"; ++ clocks = <&mlbp_clkin_ck>; ++ reg = <0x4ae06130 0x4>; ++ bit-mask = <0x7>; ++ index-power-of-two; ++}; ++ ++per_abe_x1_gfclk2_div: per_abe_x1_gfclk2_div@4ae06138 { ++ #clock-cells = <0>; ++ compatible = "divider-clock"; ++ clocks = <&dpll_abe_m2_ck>; ++ reg = <0x4ae06138 0x4>; ++ bit-mask = <0x7>; ++ index-power-of-two; ++}; ++ ++timer_sys_clk_div: timer_sys_clk_div@4ae06144 { ++ #clock-cells = <0>; ++ compatible = "divider-clock"; ++ clocks = <&sys_clkin1>; ++ reg = <0x4ae06144 0x4>; ++ bit-mask = <0x1>; ++}; ++ ++video1_clk2_div: video1_clk2_div { ++ #clock-cells = <0>; ++ compatible = "fixed-factor-clock"; ++ clocks = <&video1_clkin_ck>; ++ clock-mult = <1>; ++ clock-div = <1>; ++}; ++ ++video1_div_clk: video1_div_clk { ++ #clock-cells = <0>; ++ compatible = "fixed-factor-clock"; ++ clocks = <&video1_clkin_ck>; ++ clock-mult = <1>; ++ clock-div = <1>; ++}; ++ ++video1_dpll_clk_mux: video1_dpll_clk_mux@4ae061d0 { ++ #clock-cells = <0>; ++ compatible = "mux-clock"; ++ clocks = <&sys_clkin1>, <&sys_clkin2>; ++ reg = <0x4ae061d0 0x4>; ++ bit-mask = <0x7>; ++}; ++ ++video2_clk2_div: video2_clk2_div { ++ #clock-cells = <0>; ++ compatible = "fixed-factor-clock"; ++ clocks = <&video2_clkin_ck>; ++ clock-mult = <1>; ++ clock-div = <1>; ++}; ++ ++video2_div_clk: video2_div_clk { ++ #clock-cells = <0>; ++ compatible = "fixed-factor-clock"; ++ clocks = <&video2_clkin_ck>; ++ clock-mult = <1>; ++ clock-div = <1>; ++}; ++ ++video2_dpll_clk_mux: video2_dpll_clk_mux@4ae061d4 { ++ #clock-cells = <0>; ++ compatible = "mux-clock"; ++ clocks = <&sys_clkin1>, <&sys_clkin2>; ++ reg = <0x4ae061d4 0x4>; ++ bit-mask = <0x7>; ++}; ++ ++wkupaon_iclk_mux: wkupaon_iclk_mux@4ae06108 { ++ #clock-cells = <0>; ++ compatible = "mux-clock"; ++ clocks = <&sys_clkin1>, <&abe_lp_clk_div>; ++ reg = <0x4ae06108 0x4>; ++ bit-mask = <0x1>; ++}; ++ ++dss_32khz_clk: dss_32khz_clk@4a009120 { ++ #clock-cells = <0>; ++ compatible = "gate-clock"; ++ clocks = <&sys_32k_ck>; ++ bit-shift = <11>; ++ reg = <0x4a009120 0x4>; ++}; ++ ++dss_48mhz_clk: dss_48mhz_clk@4a009120 { ++ #clock-cells = <0>; ++ compatible = "gate-clock"; ++ clocks = <&func_48m_fclk>; ++ bit-shift = <9>; ++ reg = <0x4a009120 0x4>; ++}; ++ ++dss_dss_clk: dss_dss_clk@4a009120 { ++ #clock-cells = <0>; ++ compatible = "gate-clock"; ++ clocks = <&dpll_per_h12x2_ck>; ++ bit-shift = <8>; ++ reg = <0x4a009120 0x4>; ++}; ++ ++dss_hdmi_clk: dss_hdmi_clk@4a009120 { ++ #clock-cells = <0>; ++ compatible = "gate-clock"; ++ clocks = <&hdmi_dpll_clk_mux>; ++ bit-shift = <10>; ++ reg = <0x4a009120 0x4>; ++}; ++ ++dss_video1_clk: dss_video1_clk@4a009120 { ++ #clock-cells = <0>; ++ compatible = "gate-clock"; ++ clocks = <&video1_dpll_clk_mux>; ++ bit-shift = <12>; ++ reg = <0x4a009120 0x4>; ++}; ++ ++dss_video2_clk: dss_video2_clk@4a009120 { ++ #clock-cells = <0>; ++ compatible = "gate-clock"; ++ clocks = <&video2_dpll_clk_mux>; ++ bit-shift = <13>; ++ reg = <0x4a009120 0x4>; ++}; ++ ++dss_deshdcp_clk: dss_deshdcp_clk@4a002558 { ++ compatible = "gate-clock"; ++ clocks = <&l3_iclk_div>; ++ #clock-cells = <0>; ++ reg = <0x4a002558 0x1>; ++ bit-shift = <0>; ++}; ++ ++gpio1_dbclk: gpio1_dbclk@4ae07838 { ++ #clock-cells = <0>; ++ compatible = "gate-clock"; ++ clocks = <&sys_32k_ck>; ++ bit-shift = <8>; ++ reg = <0x4ae07838 0x4>; ++}; ++ ++gpio2_dbclk: gpio2_dbclk@4a009760 { ++ #clock-cells = <0>; ++ compatible = "gate-clock"; ++ clocks = <&sys_32k_ck>; ++ bit-shift = <8>; ++ reg = <0x4a009760 0x4>; ++}; ++ ++gpio3_dbclk: gpio3_dbclk@4a009768 { ++ #clock-cells = <0>; ++ compatible = "gate-clock"; ++ clocks = <&sys_32k_ck>; ++ bit-shift = <8>; ++ reg = <0x4a009768 0x4>; ++}; ++ ++gpio4_dbclk: gpio4_dbclk@4a009770 { ++ #clock-cells = <0>; ++ compatible = "gate-clock"; ++ clocks = <&sys_32k_ck>; ++ bit-shift = <8>; ++ reg = <0x4a009770 0x4>; ++}; ++ ++gpio5_dbclk: gpio5_dbclk@4a009778 { ++ #clock-cells = <0>; ++ compatible = "gate-clock"; ++ clocks = <&sys_32k_ck>; ++ bit-shift = <8>; ++ reg = <0x4a009778 0x4>; ++}; ++ ++gpio6_dbclk: gpio6_dbclk@4a009780 { ++ #clock-cells = <0>; ++ compatible = "gate-clock"; ++ clocks = <&sys_32k_ck>; ++ bit-shift = <8>; ++ reg = <0x4a009780 0x4>; ++}; ++ ++gpio7_dbclk: gpio7_dbclk@4a009810 { ++ #clock-cells = <0>; ++ compatible = "gate-clock"; ++ clocks = <&sys_32k_ck>; ++ bit-shift = <8>; ++ reg = <0x4a009810 0x4>; ++}; ++ ++gpio8_dbclk: gpio8_dbclk@4a009818 { ++ #clock-cells = <0>; ++ compatible = "gate-clock"; ++ clocks = <&sys_32k_ck>; ++ bit-shift = <8>; ++ reg = <0x4a009818 0x4>; ++}; ++ ++mmc1_clk32k: mmc1_clk32k@4a009328 { ++ #clock-cells = <0>; ++ compatible = "gate-clock"; ++ clocks = <&sys_32k_ck>; ++ bit-shift = <8>; ++ reg = <0x4a009328 0x4>; ++}; ++ ++mmc2_clk32k: mmc2_clk32k@4a009330 { ++ #clock-cells = <0>; ++ compatible = "gate-clock"; ++ clocks = <&sys_32k_ck>; ++ bit-shift = <8>; ++ reg = <0x4a009330 0x4>; ++}; ++ ++mmc3_clk32k: mmc3_clk32k@4a009820 { ++ #clock-cells = <0>; ++ compatible = "gate-clock"; ++ clocks = <&sys_32k_ck>; ++ bit-shift = <8>; ++ reg = <0x4a009820 0x4>; ++}; ++ ++mmc4_clk32k: mmc4_clk32k@4a009828 { ++ #clock-cells = <0>; ++ compatible = "gate-clock"; ++ clocks = <&sys_32k_ck>; ++ bit-shift = <8>; ++ reg = <0x4a009828 0x4>; ++}; ++ ++sata_ref_clk: sata_ref_clk@4a009388 { ++ #clock-cells = <0>; ++ compatible = "gate-clock"; ++ clocks = <&sys_clkin1>; ++ bit-shift = <8>; ++ reg = <0x4a009388 0x4>; ++}; ++ ++usb_otg_ss1_refclk960m: usb_otg_ss1_refclk960m@4a0093f0 { ++ #clock-cells = <0>; ++ compatible = "gate-clock"; ++ clocks = <&l3init_960m_gfclk>; ++ bit-shift = <8>; ++ reg = <0x4a0093f0 0x4>; ++}; ++ ++usb_otg_ss2_refclk960m: usb_otg_ss2_refclk960m@4a009340 { ++ #clock-cells = <0>; ++ compatible = "gate-clock"; ++ clocks = <&l3init_960m_gfclk>; ++ bit-shift = <8>; ++ reg = <0x4a009340 0x4>; ++}; ++ ++usb_phy1_always_on_clk32k: usb_phy1_always_on_clk32k@4a008640 { ++ #clock-cells = <0>; ++ compatible = "gate-clock"; ++ clocks = <&sys_32k_ck>; ++ bit-shift = <8>; ++ reg = <0x4a008640 0x4>; ++}; ++ ++usb_phy2_always_on_clk32k: usb_phy2_always_on_clk32k@4a008688 { ++ #clock-cells = <0>; ++ compatible = "gate-clock"; ++ clocks = <&sys_32k_ck>; ++ bit-shift = <8>; ++ reg = <0x4a008688 0x4>; ++}; ++ ++usb_phy3_always_on_clk32k: usb_phy3_always_on_clk32k@4a008698 { ++ #clock-cells = <0>; ++ compatible = "gate-clock"; ++ clocks = <&sys_32k_ck>; ++ bit-shift = <8>; ++ reg = <0x4a008698 0x4>; ++}; ++ ++atl_dpll_clk_mux: atl_dpll_clk_mux@4a008c00 { ++ #clock-cells = <0>; ++ compatible = "mux-clock"; ++ clocks = <&sys_32k_ck>, <&video1_clkin_ck>, <&video2_clkin_ck>, <&hdmi_clkin_ck>; ++ bit-shift = <24>; ++ reg = <0x4a008c00 0x4>; ++ bit-mask = <0x3>; ++}; ++ ++atl_gfclk_mux: atl_gfclk_mux@4a008c00 { ++ #clock-cells = <0>; ++ compatible = "mux-clock"; ++ clocks = <&l3_iclk_div>, <&dpll_abe_m2_ck>, <&atl_dpll_clk_mux>; ++ bit-shift = <26>; ++ reg = <0x4a008c00 0x4>; ++ bit-mask = <0x3>; ++}; ++ ++dcan1_sys_clk_mux: dcan1_sys_clk_mux@4ae07888 { ++ #clock-cells = <0>; ++ compatible = "mux-clock"; ++ clocks = <&sys_clkin1>, <&sys_clkin2>; ++ bit-shift = <24>; ++ reg = <0x4ae07888 0x4>; ++ bit-mask = <0x1>; ++}; ++ ++gmac_gmii_ref_clk_div: gmac_gmii_ref_clk_div@4a0093d0 { ++ #clock-cells = <0>; ++ compatible = "divider-clock"; ++ clocks = <&dpll_gmac_m2_ck>; ++ bit-shift = <24>; ++ reg = <0x4a0093d0 0x4>; ++ table = < 2 0 >; ++ bit-mask = <0x1>; ++}; ++ ++gmac_rft_clk_mux: gmac_rft_clk_mux@4a0093d0 { ++ #clock-cells = <0>; ++ compatible = "mux-clock"; ++ clocks = <&video1_clkin_ck>, <&video2_clkin_ck>, <&dpll_abe_m2_ck>, <&hdmi_clkin_ck>, <&l3_iclk_div>; ++ bit-shift = <25>; ++ reg = <0x4a0093d0 0x4>; ++ bit-mask = <0x7>; ++}; ++ ++gpu_core_gclk_mux: gpu_core_gclk_mux@4a009220 { ++ #clock-cells = <0>; ++ compatible = "mux-clock"; ++ clocks = <&dpll_core_h14x2_ck>, <&dpll_per_h14x2_ck>, <&dpll_gpu_m2_ck>; ++ bit-shift = <24>; ++ reg = <0x4a009220 0x4>; ++ bit-mask = <0x3>; ++}; ++ ++gpu_hyd_gclk_mux: gpu_hyd_gclk_mux@4a009220 { ++ #clock-cells = <0>; ++ compatible = "mux-clock"; ++ clocks = <&dpll_core_h14x2_ck>, <&dpll_per_h14x2_ck>, <&dpll_gpu_m2_ck>; ++ bit-shift = <26>; ++ reg = <0x4a009220 0x4>; ++ bit-mask = <0x3>; ++}; ++ ++ipu1_gfclk_mux: ipu1_gfclk_mux@4a005520 { ++ #clock-cells = <0>; ++ compatible = "mux-clock"; ++ clocks = <&dpll_abe_m2x2_ck>, <&dpll_core_h22x2_ck>; ++ bit-shift = <24>; ++ reg = <0x4a005520 0x4>; ++ bit-mask = <0x1>; ++}; ++ ++l3instr_ts_gclk_div: l3instr_ts_gclk_div@4a008e50 { ++ #clock-cells = <0>; ++ compatible = "divider-clock"; ++ clocks = <&wkupaon_iclk_mux>; ++ bit-shift = <24>; ++ reg = <0x4a008e50 0x4>; ++ table = < 8 0 >, < 16 1 >, < 32 2 >; ++ bit-mask = <0x3>; ++}; ++ ++mcasp1_ahclkr_mux: mcasp1_ahclkr_mux@4a005550 { ++ #clock-cells = <0>; ++ compatible = "mux-clock"; ++ clocks = <&abe_24m_fclk>, <&abe_sys_clk_div>, <&func_24m_clk>, <&atlclkin3_ck>, <&atl_clkin2_ck>, <&atl_clkin1_ck>, <&atl_clkin0_ck>, <&sys_clkin2>, <&ref_clkin0_ck>, <&ref_clkin1_ck>, <&ref_clkin2_ck>, <&ref_clkin3_ck>, <&mlb_clk>, <&mlbp_clk>; ++ bit-shift = <28>; ++ reg = <0x4a005550 0x4>; ++ bit-mask = <0xf>; ++}; ++ ++mcasp1_ahclkx_mux: mcasp1_ahclkx_mux@4a005550 { ++ #clock-cells = <0>; ++ compatible = "mux-clock"; ++ clocks = <&abe_24m_fclk>, <&abe_sys_clk_div>, <&func_24m_clk>, <&atlclkin3_ck>, <&atl_clkin2_ck>, <&atl_clkin1_ck>, <&atl_clkin0_ck>, <&sys_clkin2>, <&ref_clkin0_ck>, <&ref_clkin1_ck>, <&ref_clkin2_ck>, <&ref_clkin3_ck>, <&mlb_clk>, <&mlbp_clk>; ++ bit-shift = <24>; ++ reg = <0x4a005550 0x4>; ++ bit-mask = <0xf>; ++}; ++ ++mcasp1_aux_gfclk_mux: mcasp1_aux_gfclk_mux@4a005550 { ++ #clock-cells = <0>; ++ compatible = "mux-clock"; ++ clocks = <&per_abe_x1_gfclk2_div>, <&video1_clk2_div>, <&video2_clk2_div>, <&hdmi_clk2_div>; ++ bit-shift = <22>; ++ reg = <0x4a005550 0x4>; ++ bit-mask = <0x3>; ++}; ++ ++mcasp2_ahclkr_mux: mcasp2_ahclkr_mux@4a009860 { ++ #clock-cells = <0>; ++ compatible = "mux-clock"; ++ clocks = <&abe_24m_fclk>, <&abe_sys_clk_div>, <&func_24m_clk>, <&atlclkin3_ck>, <&atl_clkin2_ck>, <&atl_clkin1_ck>, <&atl_clkin0_ck>, <&sys_clkin2>, <&ref_clkin0_ck>, <&ref_clkin1_ck>, <&ref_clkin2_ck>, <&ref_clkin3_ck>, <&mlb_clk>, <&mlbp_clk>; ++ bit-shift = <28>; ++ reg = <0x4a009860 0x4>; ++ bit-mask = <0xf>; ++}; ++ ++mcasp2_ahclkx_mux: mcasp2_ahclkx_mux@4a009860 { ++ #clock-cells = <0>; ++ compatible = "mux-clock"; ++ clocks = <&abe_24m_fclk>, <&abe_sys_clk_div>, <&func_24m_clk>, <&atlclkin3_ck>, <&atl_clkin2_ck>, <&atl_clkin1_ck>, <&atl_clkin0_ck>, <&sys_clkin2>, <&ref_clkin0_ck>, <&ref_clkin1_ck>, <&ref_clkin2_ck>, <&ref_clkin3_ck>, <&mlb_clk>, <&mlbp_clk>; ++ bit-shift = <28>; ++ reg = <0x4a009860 0x4>; ++ bit-mask = <0xf>; ++}; ++ ++mcasp2_aux_gfclk_mux: mcasp2_aux_gfclk_mux@4a009860 { ++ #clock-cells = <0>; ++ compatible = "mux-clock"; ++ clocks = <&per_abe_x1_gfclk2_div>, <&video1_clk2_div>, <&video2_clk2_div>, <&hdmi_clk2_div>; ++ bit-shift = <22>; ++ reg = <0x4a009860 0x4>; ++ bit-mask = <0x3>; ++}; ++ ++mcasp3_ahclkx_mux: mcasp3_ahclkx_mux@4a009868 { ++ #clock-cells = <0>; ++ compatible = "mux-clock"; ++ clocks = <&abe_24m_fclk>, <&abe_sys_clk_div>, <&func_24m_clk>, <&atlclkin3_ck>, <&atl_clkin2_ck>, <&atl_clkin1_ck>, <&atl_clkin0_ck>, <&sys_clkin2>, <&ref_clkin0_ck>, <&ref_clkin1_ck>, <&ref_clkin2_ck>, <&ref_clkin3_ck>, <&mlb_clk>, <&mlbp_clk>; ++ bit-shift = <24>; ++ reg = <0x4a009868 0x4>; ++ bit-mask = <0xf>; ++}; ++ ++mcasp3_aux_gfclk_mux: mcasp3_aux_gfclk_mux@4a009868 { ++ #clock-cells = <0>; ++ compatible = "mux-clock"; ++ clocks = <&per_abe_x1_gfclk2_div>, <&video1_clk2_div>, <&video2_clk2_div>, <&hdmi_clk2_div>; ++ bit-shift = <22>; ++ reg = <0x4a009868 0x4>; ++ bit-mask = <0x3>; ++}; ++ ++mcasp4_ahclkx_mux: mcasp4_ahclkx_mux@4a009898 { ++ #clock-cells = <0>; ++ compatible = "mux-clock"; ++ clocks = <&abe_24m_fclk>, <&abe_sys_clk_div>, <&func_24m_clk>, <&atlclkin3_ck>, <&atl_clkin2_ck>, <&atl_clkin1_ck>, <&atl_clkin0_ck>, <&sys_clkin2>, <&ref_clkin0_ck>, <&ref_clkin1_ck>, <&ref_clkin2_ck>, <&ref_clkin3_ck>, <&mlb_clk>, <&mlbp_clk>; ++ bit-shift = <24>; ++ reg = <0x4a009898 0x4>; ++ bit-mask = <0xf>; ++}; ++ ++mcasp4_aux_gfclk_mux: mcasp4_aux_gfclk_mux@4a009898 { ++ #clock-cells = <0>; ++ compatible = "mux-clock"; ++ clocks = <&per_abe_x1_gfclk2_div>, <&video1_clk2_div>, <&video2_clk2_div>, <&hdmi_clk2_div>; ++ bit-shift = <22>; ++ reg = <0x4a009898 0x4>; ++ bit-mask = <0x3>; ++}; ++ ++mcasp5_ahclkx_mux: mcasp5_ahclkx_mux@4a009878 { ++ #clock-cells = <0>; ++ compatible = "mux-clock"; ++ clocks = <&abe_24m_fclk>, <&abe_sys_clk_div>, <&func_24m_clk>, <&atlclkin3_ck>, <&atl_clkin2_ck>, <&atl_clkin1_ck>, <&atl_clkin0_ck>, <&sys_clkin2>, <&ref_clkin0_ck>, <&ref_clkin1_ck>, <&ref_clkin2_ck>, <&ref_clkin3_ck>, <&mlb_clk>, <&mlbp_clk>; ++ bit-shift = <24>; ++ reg = <0x4a009878 0x4>; ++ bit-mask = <0xf>; ++}; ++ ++mcasp5_aux_gfclk_mux: mcasp5_aux_gfclk_mux@4a009878 { ++ #clock-cells = <0>; ++ compatible = "mux-clock"; ++ clocks = <&per_abe_x1_gfclk2_div>, <&video1_clk2_div>, <&video2_clk2_div>, <&hdmi_clk2_div>; ++ bit-shift = <22>; ++ reg = <0x4a009878 0x4>; ++ bit-mask = <0x3>; ++}; ++ ++mcasp6_ahclkx_mux: mcasp6_ahclkx_mux@4a009904 { ++ #clock-cells = <0>; ++ compatible = "mux-clock"; ++ clocks = <&abe_24m_fclk>, <&abe_sys_clk_div>, <&func_24m_clk>, <&atlclkin3_ck>, <&atl_clkin2_ck>, <&atl_clkin1_ck>, <&atl_clkin0_ck>, <&sys_clkin2>, <&ref_clkin0_ck>, <&ref_clkin1_ck>, <&ref_clkin2_ck>, <&ref_clkin3_ck>, <&mlb_clk>, <&mlbp_clk>; ++ bit-shift = <24>; ++ reg = <0x4a009904 0x4>; ++ bit-mask = <0xf>; ++}; ++ ++mcasp6_aux_gfclk_mux: mcasp6_aux_gfclk_mux@4a009904 { ++ #clock-cells = <0>; ++ compatible = "mux-clock"; ++ clocks = <&per_abe_x1_gfclk2_div>, <&video1_clk2_div>, <&video2_clk2_div>, <&hdmi_clk2_div>; ++ bit-shift = <22>; ++ reg = <0x4a009904 0x4>; ++ bit-mask = <0x3>; ++}; ++ ++mcasp7_ahclkx_mux: mcasp7_ahclkx_mux@4a009908 { ++ #clock-cells = <0>; ++ compatible = "mux-clock"; ++ clocks = <&abe_24m_fclk>, <&abe_sys_clk_div>, <&func_24m_clk>, <&atlclkin3_ck>, <&atl_clkin2_ck>, <&atl_clkin1_ck>, <&atl_clkin0_ck>, <&sys_clkin2>, <&ref_clkin0_ck>, <&ref_clkin1_ck>, <&ref_clkin2_ck>, <&ref_clkin3_ck>, <&mlb_clk>, <&mlbp_clk>; ++ bit-shift = <24>; ++ reg = <0x4a009908 0x4>; ++ bit-mask = <0xf>; ++}; ++ ++mcasp7_aux_gfclk_mux: mcasp7_aux_gfclk_mux@4a009908 { ++ #clock-cells = <0>; ++ compatible = "mux-clock"; ++ clocks = <&per_abe_x1_gfclk2_div>, <&video1_clk2_div>, <&video2_clk2_div>, <&hdmi_clk2_div>; ++ bit-shift = <22>; ++ reg = <0x4a009908 0x4>; ++ bit-mask = <0x3>; ++}; ++ ++mcasp8_ahclk_mux: mcasp8_ahclk_mux@4a009890 { ++ #clock-cells = <0>; ++ compatible = "mux-clock"; ++ clocks = <&abe_24m_fclk>, <&abe_sys_clk_div>, <&func_24m_clk>, <&atlclkin3_ck>, <&atl_clkin2_ck>, <&atl_clkin1_ck>, <&atl_clkin0_ck>, <&sys_clkin2>, <&ref_clkin0_ck>, <&ref_clkin1_ck>, <&ref_clkin2_ck>, <&ref_clkin3_ck>, <&mlb_clk>, <&mlbp_clk>; ++ bit-shift = <22>; ++ reg = <0x4a009890 0x4>; ++ bit-mask = <0x3>; ++}; ++ ++mcasp8_aux_gfclk_mux: mcasp8_aux_gfclk_mux@4a009890 { ++ #clock-cells = <0>; ++ compatible = "mux-clock"; ++ clocks = <&per_abe_x1_gfclk2_div>, <&video1_clk2_div>, <&video2_clk2_div>, <&hdmi_clk2_div>; ++ bit-shift = <24>; ++ reg = <0x4a009890 0x4>; ++ bit-mask = <0xf>; ++}; ++ ++mmc1_fclk_mux: mmc1_fclk_mux@4a009328 { ++ #clock-cells = <0>; ++ compatible = "mux-clock"; ++ clocks = <&func_128m_clk>, <&dpll_per_m2x2_ck>; ++ bit-shift = <24>; ++ reg = <0x4a009328 0x4>; ++ bit-mask = <0x1>; ++}; ++ ++mmc1_fclk_div: mmc1_fclk_div@4a009328 { ++ #clock-cells = <0>; ++ compatible = "divider-clock"; ++ clocks = <&mmc1_fclk_mux>; ++ bit-shift = <25>; ++ reg = <0x4a009328 0x4>; ++ bit-mask = <0x3>; ++ index-power-of-two; ++}; ++ ++mmc2_fclk_mux: mmc2_fclk_mux@4a009330 { ++ #clock-cells = <0>; ++ compatible = "mux-clock"; ++ clocks = <&func_128m_clk>, <&dpll_per_m2x2_ck>; ++ bit-shift = <24>; ++ reg = <0x4a009330 0x4>; ++ bit-mask = <0x1>; ++}; ++ ++mmc2_fclk_div: mmc2_fclk_div@4a009330 { ++ #clock-cells = <0>; ++ compatible = "divider-clock"; ++ clocks = <&mmc2_fclk_mux>; ++ bit-shift = <25>; ++ reg = <0x4a009330 0x4>; ++ bit-mask = <0x3>; ++ index-power-of-two; ++}; ++ ++mmc3_gfclk_mux: mmc3_gfclk_mux@4a009820 { ++ #clock-cells = <0>; ++ compatible = "mux-clock"; ++ clocks = <&func_48m_fclk>, <&dpll_per_m2x2_ck>; ++ bit-shift = <24>; ++ reg = <0x4a009820 0x4>; ++ bit-mask = <0x1>; ++}; ++ ++mmc3_gfclk_div: mmc3_gfclk_div@4a009820 { ++ #clock-cells = <0>; ++ compatible = "divider-clock"; ++ clocks = <&mmc3_gfclk_mux>; ++ bit-shift = <25>; ++ reg = <0x4a009820 0x4>; ++ bit-mask = <0x3>; ++ index-power-of-two; ++}; ++ ++mmc4_gfclk_mux: mmc4_gfclk_mux@4a009828 { ++ #clock-cells = <0>; ++ compatible = "mux-clock"; ++ clocks = <&func_48m_fclk>, <&dpll_per_m2x2_ck>; ++ bit-shift = <24>; ++ reg = <0x4a009828 0x4>; ++ bit-mask = <0x1>; ++}; ++ ++mmc4_gfclk_div: mmc4_gfclk_div@4a009828 { ++ #clock-cells = <0>; ++ compatible = "divider-clock"; ++ clocks = <&mmc4_gfclk_mux>; ++ bit-shift = <25>; ++ reg = <0x4a009828 0x4>; ++ bit-mask = <0x3>; ++ index-power-of-two; ++}; ++ ++qspi_gfclk_mux: qspi_gfclk_mux@4a009838 { ++ #clock-cells = <0>; ++ compatible = "mux-clock"; ++ clocks = <&func_128m_clk>, <&dpll_per_h13x2_ck>; ++ bit-shift = <24>; ++ reg = <0x4a009838 0x4>; ++ bit-mask = <0x1>; ++}; ++ ++qspi_gfclk_div: qspi_gfclk_div@4a009838 { ++ #clock-cells = <0>; ++ compatible = "divider-clock"; ++ clocks = <&qspi_gfclk_mux>; ++ bit-shift = <25>; ++ reg = <0x4a009838 0x4>; ++ bit-mask = <0x3>; ++ index-power-of-two; ++}; ++ ++timer10_gfclk_mux: timer10_gfclk_mux@4a009728 { ++ #clock-cells = <0>; ++ compatible = "mux-clock"; ++ clocks = <&timer_sys_clk_div>, <&sys_32k_ck>, <&sys_clkin2>, <&ref_clkin0_ck>, <&ref_clkin1_ck>, <&ref_clkin2_ck>, <&ref_clkin3_ck>, <&abe_giclk_div>, <&video1_div_clk>, <&video2_div_clk>, <&hdmi_div_clk>; ++ bit-shift = <24>; ++ reg = <0x4a009728 0x4>; ++ bit-mask = <0xf>; ++}; ++ ++timer11_gfclk_mux: timer11_gfclk_mux@4a009730 { ++ #clock-cells = <0>; ++ compatible = "mux-clock"; ++ clocks = <&timer_sys_clk_div>, <&sys_32k_ck>, <&sys_clkin2>, <&ref_clkin0_ck>, <&ref_clkin1_ck>, <&ref_clkin2_ck>, <&ref_clkin3_ck>, <&abe_giclk_div>, <&video1_div_clk>, <&video2_div_clk>, <&hdmi_div_clk>; ++ bit-shift = <24>; ++ reg = <0x4a009730 0x4>; ++ bit-mask = <0xf>; ++}; ++ ++timer13_gfclk_mux: timer13_gfclk_mux@4a0097c8 { ++ #clock-cells = <0>; ++ compatible = "mux-clock"; ++ clocks = <&timer_sys_clk_div>, <&sys_32k_ck>, <&sys_clkin2>, <&ref_clkin0_ck>, <&ref_clkin1_ck>, <&ref_clkin2_ck>, <&ref_clkin3_ck>, <&abe_giclk_div>, <&video1_div_clk>, <&video2_div_clk>, <&hdmi_div_clk>; ++ bit-shift = <24>; ++ reg = <0x4a0097c8 0x4>; ++ bit-mask = <0xf>; ++}; ++ ++timer14_gfclk_mux: timer14_gfclk_mux@4a0097d0 { ++ #clock-cells = <0>; ++ compatible = "mux-clock"; ++ clocks = <&timer_sys_clk_div>, <&sys_32k_ck>, <&sys_clkin2>, <&ref_clkin0_ck>, <&ref_clkin1_ck>, <&ref_clkin2_ck>, <&ref_clkin3_ck>, <&abe_giclk_div>, <&video1_div_clk>, <&video2_div_clk>, <&hdmi_div_clk>; ++ bit-shift = <24>; ++ reg = <0x4a0097d0 0x4>; ++ bit-mask = <0xf>; ++}; ++ ++timer15_gfclk_mux: timer15_gfclk_mux@4a0097d8 { ++ #clock-cells = <0>; ++ compatible = "mux-clock"; ++ clocks = <&timer_sys_clk_div>, <&sys_32k_ck>, <&sys_clkin2>, <&ref_clkin0_ck>, <&ref_clkin1_ck>, <&ref_clkin2_ck>, <&ref_clkin3_ck>, <&abe_giclk_div>, <&video1_div_clk>, <&video2_div_clk>, <&hdmi_div_clk>; ++ bit-shift = <24>; ++ reg = <0x4a0097d8 0x4>; ++ bit-mask = <0xf>; ++}; ++ ++timer16_gfclk_mux: timer16_gfclk_mux@4a009830 { ++ #clock-cells = <0>; ++ compatible = "mux-clock"; ++ clocks = <&timer_sys_clk_div>, <&sys_32k_ck>, <&sys_clkin2>, <&ref_clkin0_ck>, <&ref_clkin1_ck>, <&ref_clkin2_ck>, <&ref_clkin3_ck>, <&abe_giclk_div>, <&video1_div_clk>, <&video2_div_clk>, <&hdmi_div_clk>; ++ bit-shift = <24>; ++ reg = <0x4a009830 0x4>; ++ bit-mask = <0xf>; ++}; ++ ++timer1_gfclk_mux: timer1_gfclk_mux@4ae07840 { ++ #clock-cells = <0>; ++ compatible = "mux-clock"; ++ clocks = <&timer_sys_clk_div>, <&sys_32k_ck>, <&sys_clkin2>, <&ref_clkin0_ck>, <&ref_clkin1_ck>, <&ref_clkin2_ck>, <&ref_clkin3_ck>, <&abe_giclk_div>, <&video1_div_clk>, <&video2_div_clk>, <&hdmi_div_clk>; ++ bit-shift = <24>; ++ reg = <0x4ae07840 0x4>; ++ bit-mask = <0xf>; ++}; ++ ++timer2_gfclk_mux: timer2_gfclk_mux@4a009738 { ++ #clock-cells = <0>; ++ compatible = "mux-clock"; ++ clocks = <&timer_sys_clk_div>, <&sys_32k_ck>, <&sys_clkin2>, <&ref_clkin0_ck>, <&ref_clkin1_ck>, <&ref_clkin2_ck>, <&ref_clkin3_ck>, <&abe_giclk_div>, <&video1_div_clk>, <&video2_div_clk>, <&hdmi_div_clk>; ++ bit-shift = <24>; ++ reg = <0x4a009738 0x4>; ++ bit-mask = <0xf>; ++}; ++ ++timer3_gfclk_mux: timer3_gfclk_mux@4a009740 { ++ #clock-cells = <0>; ++ compatible = "mux-clock"; ++ clocks = <&timer_sys_clk_div>, <&sys_32k_ck>, <&sys_clkin2>, <&ref_clkin0_ck>, <&ref_clkin1_ck>, <&ref_clkin2_ck>, <&ref_clkin3_ck>, <&abe_giclk_div>, <&video1_div_clk>, <&video2_div_clk>, <&hdmi_div_clk>; ++ bit-shift = <24>; ++ reg = <0x4a009740 0x4>; ++ bit-mask = <0xf>; ++}; ++ ++timer4_gfclk_mux: timer4_gfclk_mux@4a009748 { ++ #clock-cells = <0>; ++ compatible = "mux-clock"; ++ clocks = <&timer_sys_clk_div>, <&sys_32k_ck>, <&sys_clkin2>, <&ref_clkin0_ck>, <&ref_clkin1_ck>, <&ref_clkin2_ck>, <&ref_clkin3_ck>, <&abe_giclk_div>, <&video1_div_clk>, <&video2_div_clk>, <&hdmi_div_clk>; ++ bit-shift = <24>; ++ reg = <0x4a009748 0x4>; ++ bit-mask = <0xf>; ++}; ++ ++timer5_gfclk_mux: timer5_gfclk_mux@4a005558 { ++ #clock-cells = <0>; ++ compatible = "mux-clock"; ++ clocks = <&timer_sys_clk_div>, <&sys_32k_ck>, <&sys_clkin2>, <&ref_clkin0_ck>, <&ref_clkin1_ck>, <&ref_clkin2_ck>, <&ref_clkin3_ck>, <&abe_giclk_div>, <&video1_div_clk>, <&video2_div_clk>, <&hdmi_div_clk>, <&clkoutmux0_clk_mux>; ++ bit-shift = <24>; ++ reg = <0x4a005558 0x4>; ++ bit-mask = <0xf>; ++}; ++ ++timer6_gfclk_mux: timer6_gfclk_mux@4a005560 { ++ #clock-cells = <0>; ++ compatible = "mux-clock"; ++ clocks = <&timer_sys_clk_div>, <&sys_32k_ck>, <&sys_clkin2>, <&ref_clkin0_ck>, <&ref_clkin1_ck>, <&ref_clkin2_ck>, <&ref_clkin3_ck>, <&abe_giclk_div>, <&video1_div_clk>, <&video2_div_clk>, <&hdmi_div_clk>, <&clkoutmux0_clk_mux>; ++ bit-shift = <24>; ++ reg = <0x4a005560 0x4>; ++ bit-mask = <0xf>; ++}; ++ ++timer7_gfclk_mux: timer7_gfclk_mux@4a005568 { ++ #clock-cells = <0>; ++ compatible = "mux-clock"; ++ clocks = <&timer_sys_clk_div>, <&sys_32k_ck>, <&sys_clkin2>, <&ref_clkin0_ck>, <&ref_clkin1_ck>, <&ref_clkin2_ck>, <&ref_clkin3_ck>, <&abe_giclk_div>, <&video1_div_clk>, <&video2_div_clk>, <&hdmi_div_clk>, <&clkoutmux0_clk_mux>; ++ bit-shift = <24>; ++ reg = <0x4a005568 0x4>; ++ bit-mask = <0xf>; ++}; ++ ++timer8_gfclk_mux: timer8_gfclk_mux@4a005570 { ++ #clock-cells = <0>; ++ compatible = "mux-clock"; ++ clocks = <&timer_sys_clk_div>, <&sys_32k_ck>, <&sys_clkin2>, <&ref_clkin0_ck>, <&ref_clkin1_ck>, <&ref_clkin2_ck>, <&ref_clkin3_ck>, <&abe_giclk_div>, <&video1_div_clk>, <&video2_div_clk>, <&hdmi_div_clk>, <&clkoutmux0_clk_mux>; ++ bit-shift = <24>; ++ reg = <0x4a005570 0x4>; ++ bit-mask = <0xf>; ++}; ++ ++timer9_gfclk_mux: timer9_gfclk_mux@4a009750 { ++ #clock-cells = <0>; ++ compatible = "mux-clock"; ++ clocks = <&timer_sys_clk_div>, <&sys_32k_ck>, <&sys_clkin2>, <&ref_clkin0_ck>, <&ref_clkin1_ck>, <&ref_clkin2_ck>, <&ref_clkin3_ck>, <&abe_giclk_div>, <&video1_div_clk>, <&video2_div_clk>, <&hdmi_div_clk>; ++ bit-shift = <24>; ++ reg = <0x4a009750 0x4>; ++ bit-mask = <0xf>; ++}; ++ ++uart10_gfclk_mux: uart10_gfclk_mux@4ae07880 { ++ #clock-cells = <0>; ++ compatible = "mux-clock"; ++ clocks = <&func_48m_fclk>, <&dpll_per_m2x2_ck>; ++ bit-shift = <24>; ++ reg = <0x4ae07880 0x4>; ++ bit-mask = <0x1>; ++}; ++ ++uart1_gfclk_mux: uart1_gfclk_mux@4a009840 { ++ #clock-cells = <0>; ++ compatible = "mux-clock"; ++ clocks = <&func_48m_fclk>, <&dpll_per_m2x2_ck>; ++ bit-shift = <24>; ++ reg = <0x4a009840 0x4>; ++ bit-mask = <0x1>; ++}; ++ ++uart2_gfclk_mux: uart2_gfclk_mux@4a009848 { ++ #clock-cells = <0>; ++ compatible = "mux-clock"; ++ clocks = <&func_48m_fclk>, <&dpll_per_m2x2_ck>; ++ bit-shift = <24>; ++ reg = <0x4a009848 0x4>; ++ bit-mask = <0x1>; ++}; ++ ++uart3_gfclk_mux: uart3_gfclk_mux@4a009850 { ++ #clock-cells = <0>; ++ compatible = "mux-clock"; ++ clocks = <&func_48m_fclk>, <&dpll_per_m2x2_ck>; ++ bit-shift = <24>; ++ reg = <0x4a009850 0x4>; ++ bit-mask = <0x1>; ++}; ++ ++uart4_gfclk_mux: uart4_gfclk_mux@4a009858 { ++ #clock-cells = <0>; ++ compatible = "mux-clock"; ++ clocks = <&func_48m_fclk>, <&dpll_per_m2x2_ck>; ++ bit-shift = <24>; ++ reg = <0x4a009858 0x4>; ++ bit-mask = <0x1>; ++}; ++ ++uart5_gfclk_mux: uart5_gfclk_mux@4a009870 { ++ #clock-cells = <0>; ++ compatible = "mux-clock"; ++ clocks = <&func_48m_fclk>, <&dpll_per_m2x2_ck>; ++ bit-shift = <24>; ++ reg = <0x4a009870 0x4>; ++ bit-mask = <0x1>; ++}; ++ ++uart6_gfclk_mux: uart6_gfclk_mux@4a005580 { ++ #clock-cells = <0>; ++ compatible = "mux-clock"; ++ clocks = <&func_48m_fclk>, <&dpll_per_m2x2_ck>; ++ bit-shift = <24>; ++ reg = <0x4a005580 0x4>; ++ bit-mask = <0x1>; ++}; ++ ++uart7_gfclk_mux: uart7_gfclk_mux@4a0098d0 { ++ #clock-cells = <0>; ++ compatible = "mux-clock"; ++ clocks = <&func_48m_fclk>, <&dpll_per_m2x2_ck>; ++ bit-shift = <24>; ++ reg = <0x4a0098d0 0x4>; ++ bit-mask = <0x1>; ++}; ++ ++uart8_gfclk_mux: uart8_gfclk_mux@4a0098e0 { ++ #clock-cells = <0>; ++ compatible = "mux-clock"; ++ clocks = <&func_48m_fclk>, <&dpll_per_m2x2_ck>; ++ bit-shift = <24>; ++ reg = <0x4a0098e0 0x4>; ++ bit-mask = <0x1>; ++}; ++ ++uart9_gfclk_mux: uart9_gfclk_mux@4a0098e8 { ++ #clock-cells = <0>; ++ compatible = "mux-clock"; ++ clocks = <&func_48m_fclk>, <&dpll_per_m2x2_ck>; ++ bit-shift = <24>; ++ reg = <0x4a0098e8 0x4>; ++ bit-mask = <0x1>; ++}; ++ ++vip1_gclk_mux: vip1_gclk_mux@4a009020 { ++ #clock-cells = <0>; ++ compatible = "mux-clock"; ++ clocks = <&l3_iclk_div>, <&dpll_core_h23x2_ck>; ++ bit-shift = <24>; ++ reg = <0x4a009020 0x4>; ++ bit-mask = <0x1>; ++}; ++ ++vip2_gclk_mux: vip2_gclk_mux@4a009028 { ++ #clock-cells = <0>; ++ compatible = "mux-clock"; ++ clocks = <&l3_iclk_div>, <&dpll_core_h23x2_ck>; ++ bit-shift = <24>; ++ reg = <0x4a009028 0x4>; ++ bit-mask = <0x1>; ++}; ++ ++vip3_gclk_mux: vip3_gclk_mux@4a009030 { ++ #clock-cells = <0>; ++ compatible = "mux-clock"; ++ clocks = <&l3_iclk_div>, <&dpll_core_h23x2_ck>; ++ bit-shift = <24>; ++ reg = <0x4a009030 0x4>; ++ bit-mask = <0x1>; ++}; ++ ++optfclk_pciephy_div: optfclk_pciephy_div@4a00821c { ++ compatible = "divider-clock"; ++ clocks = <&apll_pcie_ck>; ++ #clock-cells = <0>; ++ reg = <0x4a00821c 0x4>; ++ bit-mask = <0x100>; ++}; ++ ++optfclk_pciephy_clk: optfclk_pciephy_clk@4a0093b0 { ++ compatible = "gate-clock"; ++ clocks = <&apll_pcie_ck>; ++ #clock-cells = <0>; ++ reg = <0x4a0093b0 0x4>; ++ bit-shift = <9>; ++}; ++ ++optfclk_pciephy_div_clk: optfclk_pciephy_div_clk@4a0093b0 { ++ compatible = "gate-clock"; ++ clocks = <&optfclk_pciephy_div>; ++ #clock-cells = <0>; ++ reg = <0x4a0093b0 0x4>; ++ bit-shift = <10>; ++}; +--- a/arch/arm/boot/dts/Makefile ++++ b/arch/arm/boot/dts/Makefile +@@ -186,9 +186,12 @@ dtb-$(CONFIG_ARCH_OMAP2PLUS) += omap2420 + am335x-evmsk.dtb \ + am335x-bone.dtb \ + am335x-boneblack.dtb \ ++ am335x-evm-profile2.dtb \ + am3517-evm.dtb \ + am3517_mt_ventoux.dtb \ +- am43x-epos-evm.dtb ++ am43x-epos-evm.dtb \ ++ am437x-gp-evm.dtb \ ++ dra7-evm.dtb + dtb-$(CONFIG_ARCH_ORION5X) += orion5x-lacie-ethernet-disk-mini-v2.dtb + dtb-$(CONFIG_ARCH_PRIMA2) += prima2-evb.dtb + dtb-$(CONFIG_ARCH_U8500) += ste-snowball.dtb \ +--- a/arch/arm/boot/dts/omap2420.dtsi ++++ b/arch/arm/boot/dts/omap2420.dtsi +@@ -114,6 +114,18 @@ + dma-names = "tx", "rx"; + }; + ++ mailbox: mailbox@48094000 { ++ compatible = "ti,omap2-mailbox"; ++ reg = <0x48094000 0x200>; ++ interrupts = <26>, /* DSP Interrupt */ ++ <34>; /* IVA Interrupt */ ++ ti,hwmods = "mailbox"; ++ ti,mbox-num-users = <4>; ++ ti,mbox-num-fifos = <6>; ++ ti,mbox-names = "dsp", "iva"; ++ ti,mbox-data = <0 1 0 0>, <2 3 1 3>; ++ }; ++ + timer1: timer@48028000 { + compatible = "ti,omap2420-timer"; + reg = <0x48028000 0x400>; +--- a/arch/arm/boot/dts/omap2430.dtsi ++++ b/arch/arm/boot/dts/omap2430.dtsi +@@ -175,6 +175,17 @@ + dma-names = "tx", "rx"; + }; + ++ mailbox: mailbox@48094000 { ++ compatible = "ti,omap2-mailbox"; ++ reg = <0x48094000 0x200>; ++ interrupts = <26>; ++ ti,hwmods = "mailbox"; ++ ti,mbox-num-users = <4>; ++ ti,mbox-num-fifos = <6>; ++ ti,mbox-names = "dsp"; ++ ti,mbox-data = <0 1 0 0>; ++ }; ++ + timer1: timer@49018000 { + compatible = "ti,omap2420-timer"; + reg = <0x49018000 0x400>; +--- /dev/null ++++ b/arch/arm/boot/dts/omap3430es1-clocks.dtsi +@@ -0,0 +1,158 @@ ++/* ++ * Device Tree Source for OMAP3430 ES1 clock data ++ * ++ * Copyright (C) 2013 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. ++ */ ++ ++gfx_l3_ck: gfx_l3_ck@48004b10 { ++ #clock-cells = <0>; ++ compatible = "ti,gate-clock"; ++ clocks = <&l3_ick>; ++ reg = <0x48004b10 0x4>; ++ ti,enable-bit = <0>; ++}; ++ ++gfx_l3_fck: gfx_l3_fck@48004b40 { ++ #clock-cells = <0>; ++ compatible = "divider-clock"; ++ clocks = <&l3_ick>; ++ reg = <0x48004b40 0x4>; ++ bit-mask = <0x7>; ++ index-starts-at-one; ++}; ++ ++gfx_l3_ick: gfx_l3_ick { ++ #clock-cells = <0>; ++ compatible = "fixed-factor-clock"; ++ clocks = <&gfx_l3_ck>; ++ clock-mult = <1>; ++ clock-div = <1>; ++}; ++ ++gfx_cg1_ck: gfx_cg1_ck@48004b00 { ++ #clock-cells = <0>; ++ compatible = "ti,gate-clock"; ++ clocks = <&gfx_l3_fck>; ++ reg = <0x48004b00 0x4>; ++ ti,enable-bit = <1>; ++}; ++ ++gfx_cg2_ck: gfx_cg2_ck@48004b00 { ++ #clock-cells = <0>; ++ compatible = "ti,gate-clock"; ++ clocks = <&gfx_l3_fck>; ++ reg = <0x48004b00 0x4>; ++ ti,enable-bit = <2>; ++}; ++ ++d2d_26m_fck: d2d_26m_fck@48004a00 { ++ #clock-cells = <0>; ++ compatible = "ti,gate-clock"; ++ clocks = <&sys_ck>; ++ reg = <0x48004a00 0x4>; ++ ti,enable-bit = <3>; ++}; ++ ++fshostusb_fck: fshostusb_fck@48004a00 { ++ #clock-cells = <0>; ++ compatible = "ti,gate-clock"; ++ clocks = <&core_48m_fck>; ++ reg = <0x48004a00 0x4>; ++ ti,enable-bit = <5>; ++}; ++ ++ssi_ssr_div_fck_3430es1: ssi_ssr_div_fck_3430es1@48004a40 { ++ #clock-cells = <0>; ++ compatible = "divider-clock"; ++ clocks = <&corex2_fck>; ++ bit-shift = <8>; ++ reg = <0x48004a40 0x4>; ++ table = < 1 1 >, < 2 2 >, < 3 3 >, < 4 4 >, < 6 6 >, < 8 8 >; ++ bit-mask = <0xf>; ++}; ++ ++ssi_ssr_fck_3430es1: ssi_ssr_fck_3430es1@48004a00 { ++ #clock-cells = <0>; ++ compatible = "gate-clock"; ++ clocks = <&ssi_ssr_div_fck_3430es1>; ++ bit-shift = <0>; ++ reg = <0x48004a00 0x4>; ++}; ++ ++ssi_sst_fck_3430es1: ssi_sst_fck_3430es1 { ++ #clock-cells = <0>; ++ compatible = "fixed-factor-clock"; ++ clocks = <&ssi_ssr_fck_3430es1>; ++ clock-mult = <1>; ++ clock-div = <2>; ++}; ++ ++hsotgusb_ick: hsotgusb_ick@48004a10 { ++ #clock-cells = <0>; ++ compatible = "ti,omap3-no-wait-interface-clock"; ++ clocks = <&core_l3_ick>; ++ reg = <0x48004a10 0x4>; ++ ti,enable-bit = <4>; ++}; ++ ++fac_ick: fac_ick@48004a10 { ++ #clock-cells = <0>; ++ compatible = "ti,omap3-interface-clock"; ++ clocks = <&core_l4_ick>; ++ reg = <0x48004a10 0x4>; ++ ti,enable-bit = <8>; ++}; ++ ++ssi_l4_ick: ssi_l4_ick { ++ #clock-cells = <0>; ++ compatible = "fixed-factor-clock"; ++ clocks = <&l4_ick>; ++ clock-mult = <1>; ++ clock-div = <1>; ++}; ++ ++ssi_ick_3430es1: ssi_ick_3430es1@48004a10 { ++ #clock-cells = <0>; ++ compatible = "ti,omap3-no-wait-interface-clock"; ++ clocks = <&ssi_l4_ick>; ++ reg = <0x48004a10 0x4>; ++ ti,enable-bit = <0>; ++}; ++ ++usb_l4_div_ick: usb_l4_div_ick@48004a40 { ++ #clock-cells = <0>; ++ compatible = "divider-clock"; ++ clocks = <&l4_ick>; ++ bit-shift = <4>; ++ reg = <0x48004a40 0x4>; ++ bit-mask = <0x3>; ++ index-starts-at-one; ++}; ++ ++usb_l4_ick: usb_l4_ick@48004a10 { ++ #clock-cells = <0>; ++ compatible = "gate-clock"; ++ clocks = <&usb_l4_div_ick>; ++ bit-shift = <5>; ++ reg = <0x48004a10 0x4>; ++}; ++ ++dss1_alwon_fck_3430es1: dss1_alwon_fck_3430es1@48004e00 { ++ #clock-cells = <0>; ++ compatible = "gate-clock"; ++ clocks = <&dpll4_m4x2_ck>; ++ reg = <0x48004e00 0x4>; ++ bit-shift = <0>; ++}; ++ ++dss_ick_3430es1: dss_ick_3430es1@48004e10 { ++ #clock-cells = <0>; ++ compatible = "ti,omap3-no-wait-interface-clock"; ++ clocks = <&l4_ick>; ++ reg = <0x48004e10 0x4>; ++ ti,enable-bit = <0>; ++}; +--- a/arch/arm/boot/dts/omap34xx.dtsi ++++ b/arch/arm/boot/dts/omap34xx.dtsi +@@ -25,4 +25,113 @@ + clock-latency = <300000>; /* From legacy driver */ + }; + }; +-}; ++ ++ clocks { ++ #address-cells = <1>; ++ #size-cells = <1>; ++ ranges; ++ /include/ "omap34xx-omap36xx-clocks.dtsi" ++ /include/ "omap36xx-omap3430es2plus-clocks.dtsi" ++ /include/ "omap36xx-am35xx-omap3430es2plus-clocks.dtsi" ++ }; ++ ++ clockdomains { ++ usbhost_clkdm: usbhost_clkdm { ++ compatible = "ti,clockdomain"; ++ clocks = <&usbhost_48m_fck>, <&usbhost_ick>; ++ }; ++ ++ wkup_clkdm: wkup_clkdm { ++ compatible = "ti,clockdomain"; ++ clocks = <&wdt1_ick>, <&gpt12_ick>, <&gpio1_ick>, ++ <&gpt1_ick>, <&omap_32ksync_ick>, <&wdt2_ick>, ++ <&wdt2_fck>; ++ }; ++ ++ cam_clkdm: cam_clkdm { ++ compatible = "ti,clockdomain"; ++ clocks = <&cam_ick>; ++ }; ++ ++ dpll4_clkdm: dpll4_clkdm { ++ compatible = "ti,clockdomain"; ++ clocks = <&dpll4_ck>; ++ }; ++ ++ sgx_clkdm: sgx_clkdm { ++ compatible = "ti,clockdomain"; ++ clocks = <&sgx_ick>; ++ }; ++ ++ dpll3_clkdm: dpll3_clkdm { ++ compatible = "ti,clockdomain"; ++ clocks = <&dpll3_ck>; ++ }; ++ ++ iva2_clkdm: iva2_clkdm { ++ compatible = "ti,clockdomain"; ++ clocks = <&iva2_ck>; ++ }; ++ ++ dpll1_clkdm: dpll1_clkdm { ++ compatible = "ti,clockdomain"; ++ clocks = <&dpll1_ck>; ++ }; ++ ++ dpll2_clkdm: dpll2_clkdm { ++ compatible = "ti,clockdomain"; ++ clocks = <&dpll2_ck>; ++ }; ++ ++ dpll5_clkdm: dpll5_clkdm { ++ compatible = "ti,clockdomain"; ++ clocks = <&dpll5_ck>; ++ }; ++ ++ dss_clkdm: dss_clkdm { ++ compatible = "ti,clockdomain"; ++ clocks = <&dss1_alwon_fck_3430es2>, <&dss_ick_3430es2>; ++ }; ++ ++ core_l4_clkdm: core_l4_clkdm { ++ compatible = "ti,clockdomain"; ++ clocks = <&mmchs1_ick>, <&mmchs2_ick>, <&hdq_fck>, ++ <&uart1_ick>, <&mcspi4_fck>, <&i2c3_fck>, ++ <&mcspi2_ick>, <&uart2_ick>, <&mcspi3_ick>, ++ <&i2c1_fck>, <&hdq_ick>, <&sha12_ick>, ++ <&mcbsp5_ick>, <&mcspi3_fck>, <&aes2_ick>, ++ <&mcspi1_ick>, <&uart2_fck>, <&mmchs2_fck>, ++ <&mmchs1_fck>, <&i2c3_ick>, <&mcspi1_fck>, ++ <&mcspi4_ick>, <&omapctrl_ick>, <&mcbsp1_ick>, ++ <&mcspi2_fck>, <&gpt10_ick>, <&i2c2_fck>, ++ <&i2c2_ick>, <&gpt11_ick>, <&i2c1_ick>, ++ <&uart1_fck>; ++ }; ++ ++ core_l3_clkdm: core_l3_clkdm { ++ compatible = "ti,clockdomain"; ++ clocks = <&sdrc_ick>; ++ }; ++ ++ per_clkdm: per_clkdm { ++ compatible = "ti,clockdomain"; ++ clocks = <&gpt2_ick>, <&uart3_fck>, <&gpio3_ick>, ++ <&mcbsp2_ick>, <&gpt6_ick>, <&mcbsp4_ick>, ++ <&gpt4_ick>, <&mcbsp3_ick>, <&gpt8_ick>, ++ <&uart3_ick>, <&gpt5_ick>, <&gpt7_ick>, ++ <&gpio2_ick>, <&gpio6_ick>, <&gpt9_ick>, ++ <&gpt3_ick>, <&gpio5_ick>, <&wdt3_ick>, ++ <&gpio4_ick>, <&wdt3_fck>, <&uart4_ick>; ++ }; ++ ++ emu_clkdm: emu_clkdm { ++ compatible = "ti,clockdomain"; ++ clocks = <&emu_src_ck>; ++ }; ++ ++ d2d_clkdm: d2d_clkdm { ++ compatible = "ti,clockdomain"; ++ clocks = <&mad2d_ick>, <&sad2d_ick>, <&modem_fck>; ++ }; ++ }; ++}; +\ No newline at end of file +--- /dev/null ++++ b/arch/arm/boot/dts/omap34xx-omap36xx-clocks.dtsi +@@ -0,0 +1,222 @@ ++/* ++ * Device Tree Source for OMAP34xx/OMAP36xx clock data ++ * ++ * Copyright (C) 2013 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. ++ */ ++ ++security_l4_ick2: security_l4_ick2 { ++ #clock-cells = <0>; ++ compatible = "fixed-factor-clock"; ++ clocks = <&l4_ick>; ++ clock-mult = <1>; ++ clock-div = <1>; ++}; ++ ++aes1_ick: aes1_ick@48004a14 { ++ #clock-cells = <0>; ++ compatible = "ti,omap3-interface-clock"; ++ clocks = <&security_l4_ick2>; ++ reg = <0x48004a14 0x4>; ++ ti,enable-bit = <3>; ++}; ++ ++rng_ick: rng_ick@48004a14 { ++ #clock-cells = <0>; ++ compatible = "ti,omap3-interface-clock"; ++ clocks = <&security_l4_ick2>; ++ reg = <0x48004a14 0x4>; ++ ti,enable-bit = <2>; ++}; ++ ++sha11_ick: sha11_ick@48004a14 { ++ #clock-cells = <0>; ++ compatible = "ti,omap3-interface-clock"; ++ clocks = <&security_l4_ick2>; ++ reg = <0x48004a14 0x4>; ++ ti,enable-bit = <1>; ++}; ++ ++des1_ick: des1_ick@48004a14 { ++ #clock-cells = <0>; ++ compatible = "ti,omap3-interface-clock"; ++ clocks = <&security_l4_ick2>; ++ reg = <0x48004a14 0x4>; ++ ti,enable-bit = <0>; ++}; ++ ++cam_mclk: cam_mclk@48004f00 { ++ #clock-cells = <0>; ++ compatible = "gate-clock"; ++ clocks = <&dpll4_m5x2_ck>; ++ bit-shift = <0>; ++ reg = <0x48004f00 0x4>; ++ set-rate-parent; ++}; ++ ++cam_ick: cam_ick@48004f10 { ++ #clock-cells = <0>; ++ compatible = "ti,omap3-no-wait-interface-clock"; ++ clocks = <&l4_ick>; ++ reg = <0x48004f10 0x4>; ++ ti,enable-bit = <0>; ++}; ++ ++csi2_96m_fck: csi2_96m_fck@48004f00 { ++ #clock-cells = <0>; ++ compatible = "gate-clock"; ++ clocks = <&core_96m_fck>; ++ reg = <0x48004f00 0x4>; ++ bit-shift = <1>; ++}; ++ ++security_l3_ick: security_l3_ick { ++ #clock-cells = <0>; ++ compatible = "fixed-factor-clock"; ++ clocks = <&l3_ick>; ++ clock-mult = <1>; ++ clock-div = <1>; ++}; ++ ++pka_ick: pka_ick@48004a14 { ++ #clock-cells = <0>; ++ compatible = "ti,omap3-interface-clock"; ++ clocks = <&security_l3_ick>; ++ reg = <0x48004a14 0x4>; ++ ti,enable-bit = <4>; ++}; ++ ++icr_ick: icr_ick@48004a10 { ++ #clock-cells = <0>; ++ compatible = "ti,omap3-interface-clock"; ++ clocks = <&core_l4_ick>; ++ reg = <0x48004a10 0x4>; ++ ti,enable-bit = <29>; ++}; ++ ++des2_ick: des2_ick@48004a10 { ++ #clock-cells = <0>; ++ compatible = "ti,omap3-interface-clock"; ++ clocks = <&core_l4_ick>; ++ reg = <0x48004a10 0x4>; ++ ti,enable-bit = <26>; ++}; ++ ++mspro_ick: mspro_ick@48004a10 { ++ #clock-cells = <0>; ++ compatible = "ti,omap3-interface-clock"; ++ clocks = <&core_l4_ick>; ++ reg = <0x48004a10 0x4>; ++ ti,enable-bit = <23>; ++}; ++ ++mailboxes_ick: mailboxes_ick@48004a10 { ++ #clock-cells = <0>; ++ compatible = "ti,omap3-interface-clock"; ++ clocks = <&core_l4_ick>; ++ reg = <0x48004a10 0x4>; ++ ti,enable-bit = <7>; ++}; ++ ++ssi_l4_ick: ssi_l4_ick { ++ #clock-cells = <0>; ++ compatible = "fixed-factor-clock"; ++ clocks = <&l4_ick>; ++ clock-mult = <1>; ++ clock-div = <1>; ++}; ++ ++sr1_fck: sr1_fck@48004c00 { ++ #clock-cells = <0>; ++ compatible = "ti,gate-clock"; ++ clocks = <&sys_ck>; ++ reg = <0x48004c00 0x4>; ++ ti,enable-bit = <6>; ++}; ++ ++sr2_fck: sr2_fck@48004c00 { ++ #clock-cells = <0>; ++ compatible = "ti,gate-clock"; ++ clocks = <&sys_ck>; ++ reg = <0x48004c00 0x4>; ++ ti,enable-bit = <7>; ++}; ++ ++sr_l4_ick: sr_l4_ick { ++ #clock-cells = <0>; ++ compatible = "fixed-factor-clock"; ++ clocks = <&l4_ick>; ++ clock-mult = <1>; ++ clock-div = <1>; ++}; ++ ++dpll2_fck: dpll2_fck@48004040 { ++ #clock-cells = <0>; ++ compatible = "divider-clock"; ++ clocks = <&core_ck>; ++ bit-shift = <19>; ++ reg = <0x48004040 0x4>; ++ bit-mask = <0x7>; ++ index-starts-at-one; ++}; ++ ++dpll2_ck: dpll2_ck@48004004 { ++ #clock-cells = <0>; ++ compatible = "ti,omap3-dpll-clock"; ++ clocks = <&sys_ck>, <&dpll2_fck>; ++ ti,modes = <0xa2>; ++ reg-names = "control", "idlest", "autoidle", "mult-div1"; ++ reg = <0x48004004 0x4>, <0x48004024 0x4>, <0x48004034 0x4>, <0x48004040 0x4>; ++}; ++ ++dpll2_m2_ck: dpll2_m2_ck@48004044 { ++ #clock-cells = <0>; ++ compatible = "divider-clock"; ++ clocks = <&dpll2_ck>; ++ reg = <0x48004044 0x4>; ++ bit-mask = <0x1f>; ++ index-starts-at-one; ++}; ++ ++iva2_ck: iva2_ck@48004000 { ++ #clock-cells = <0>; ++ compatible = "ti,gate-clock"; ++ clocks = <&dpll2_m2_ck>; ++ reg = <0x48004000 0x4>; ++ ti,enable-bit = <0>; ++}; ++ ++modem_fck: modem_fck@48004a00 { ++ #clock-cells = <0>; ++ compatible = "ti,omap3-interface-clock"; ++ clocks = <&sys_ck>; ++ reg = <0x48004a00 0x4>; ++ ti,enable-bit = <31>; ++}; ++ ++sad2d_ick: sad2d_ick@48004a10 { ++ #clock-cells = <0>; ++ compatible = "ti,omap3-interface-clock"; ++ clocks = <&l3_ick>; ++ reg = <0x48004a10 0x4>; ++ ti,enable-bit = <3>; ++}; ++ ++mad2d_ick: mad2d_ick@48004a18 { ++ #clock-cells = <0>; ++ compatible = "ti,omap3-interface-clock"; ++ clocks = <&l3_ick>; ++ reg = <0x48004a18 0x4>; ++ ti,enable-bit = <3>; ++}; ++ ++mspro_fck: mspro_fck@48004a00 { ++ #clock-cells = <0>; ++ compatible = "ti,gate-clock"; ++ clocks = <&core_96m_fck>; ++ reg = <0x48004a00 0x4>; ++ ti,enable-bit = <23>; ++}; +--- /dev/null ++++ b/arch/arm/boot/dts/omap36xx-am35xx-omap3430es2plus-clocks.dtsi +@@ -0,0 +1,196 @@ ++/* ++ * Device Tree Source for OMAP36xx/AM35xx/OMAP34xx clock data ++ * ++ * Copyright (C) 2013 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. ++ */ ++ ++dpll5_ck: dpll5_ck@48004d04 { ++ #clock-cells = <0>; ++ compatible = "ti,omap3-dpll-clock"; ++ clocks = <&sys_ck>, <&sys_ck>; ++ ti,modes = <0x82>; ++ reg-names = "control", "idlest", "autoidle", "mult-div1"; ++ reg = <0x48004d04 0x4>, <0x48004d24 0x4>, <0x48004d34 0x4>, <0x48004d4c 0x4>; ++}; ++ ++dpll5_m2_ck: dpll5_m2_ck@48004d50 { ++ #clock-cells = <0>; ++ compatible = "divider-clock"; ++ clocks = <&dpll5_ck>; ++ reg = <0x48004d50 0x4>; ++ bit-mask = <0x1f>; ++ index-starts-at-one; ++}; ++ ++core_d3_ck: core_d3_ck { ++ #clock-cells = <0>; ++ compatible = "fixed-factor-clock"; ++ clocks = <&core_ck>; ++ clock-mult = <1>; ++ clock-div = <3>; ++}; ++ ++core_d4_ck: core_d4_ck { ++ #clock-cells = <0>; ++ compatible = "fixed-factor-clock"; ++ clocks = <&core_ck>; ++ clock-mult = <1>; ++ clock-div = <4>; ++}; ++ ++core_d6_ck: core_d6_ck { ++ #clock-cells = <0>; ++ compatible = "fixed-factor-clock"; ++ clocks = <&core_ck>; ++ clock-mult = <1>; ++ clock-div = <6>; ++}; ++ ++omap_192m_alwon_fck: omap_192m_alwon_fck { ++ #clock-cells = <0>; ++ compatible = "fixed-factor-clock"; ++ clocks = <&dpll4_m2x2_ck>; ++ clock-mult = <1>; ++ clock-div = <1>; ++}; ++ ++core_d2_ck: core_d2_ck { ++ #clock-cells = <0>; ++ compatible = "fixed-factor-clock"; ++ clocks = <&core_ck>; ++ clock-mult = <1>; ++ clock-div = <2>; ++}; ++ ++corex2_d3_fck: corex2_d3_fck { ++ #clock-cells = <0>; ++ compatible = "fixed-factor-clock"; ++ clocks = <&corex2_fck>; ++ clock-mult = <1>; ++ clock-div = <3>; ++}; ++ ++corex2_d5_fck: corex2_d5_fck { ++ #clock-cells = <0>; ++ compatible = "fixed-factor-clock"; ++ clocks = <&corex2_fck>; ++ clock-mult = <1>; ++ clock-div = <5>; ++}; ++ ++sgx_mux_fck: sgx_mux_fck@48004b40 { ++ #clock-cells = <0>; ++ compatible = "mux-clock"; ++ clocks = <&core_d3_ck>, <&core_d4_ck>, <&core_d6_ck>, <&cm_96m_fck>, <&omap_192m_alwon_fck>, <&core_d2_ck>, <&corex2_d3_fck>, <&corex2_d5_fck>; ++ reg = <0x48004b40 0x4>; ++ table = <&core_d3_ck 0>, <&core_d4_ck 1>, <&core_d6_ck 2>, <&cm_96m_fck 3>, <&omap_192m_alwon_fck 4>, <&core_d2_ck 5>, <&corex2_d3_fck 6>, <&corex2_d5_fck 7>; ++ bit-mask = <0x7>; ++}; ++ ++sgx_fck: sgx_fck@48004b00 { ++ #clock-cells = <0>; ++ compatible = "gate-clock"; ++ clocks = <&sgx_mux_fck>; ++ bit-shift = <1>; ++ reg = <0x48004b00 0x4>; ++}; ++ ++sgx_ick: sgx_ick@48004b10 { ++ #clock-cells = <0>; ++ compatible = "ti,gate-clock"; ++ clocks = <&l3_ick>; ++ reg = <0x48004b10 0x4>; ++ ti,enable-bit = <0>; ++}; ++ ++cpefuse_fck: cpefuse_fck@48004a08 { ++ #clock-cells = <0>; ++ compatible = "gate-clock"; ++ clocks = <&sys_ck>; ++ reg = <0x48004a08 0x4>; ++ bit-shift = <0>; ++}; ++ ++ts_fck: ts_fck@48004a08 { ++ #clock-cells = <0>; ++ compatible = "gate-clock"; ++ clocks = <&omap_32k_fck>; ++ reg = <0x48004a08 0x4>; ++ bit-shift = <1>; ++}; ++ ++usbtll_fck: usbtll_fck@48004a08 { ++ #clock-cells = <0>; ++ compatible = "ti,gate-clock"; ++ clocks = <&dpll5_m2_ck>; ++ reg = <0x48004a08 0x4>; ++ ti,enable-bit = <2>; ++}; ++ ++usbtll_ick: usbtll_ick@48004a18 { ++ #clock-cells = <0>; ++ compatible = "ti,omap3-interface-clock"; ++ clocks = <&core_l4_ick>; ++ reg = <0x48004a18 0x4>; ++ ti,enable-bit = <2>; ++}; ++ ++mmchs3_ick: mmchs3_ick@48004a10 { ++ #clock-cells = <0>; ++ compatible = "ti,omap3-interface-clock"; ++ clocks = <&core_l4_ick>; ++ reg = <0x48004a10 0x4>; ++ ti,enable-bit = <30>; ++}; ++ ++mmchs3_fck: mmchs3_fck@48004a00 { ++ #clock-cells = <0>; ++ compatible = "ti,gate-clock"; ++ clocks = <&core_96m_fck>; ++ reg = <0x48004a00 0x4>; ++ ti,enable-bit = <30>; ++}; ++ ++dss1_alwon_fck_3430es2: dss1_alwon_fck_3430es2@48004e00 { ++ #clock-cells = <0>; ++ compatible = "ti,dss-gate-clock"; ++ clocks = <&dpll4_m4x2_ck>; ++ reg = <0x48004e00 0x4>; ++ ti,enable-bit = <0>; ++}; ++ ++dss_ick_3430es2: dss_ick_3430es2@48004e10 { ++ #clock-cells = <0>; ++ compatible = "ti,omap3-dss-interface-clock"; ++ clocks = <&l4_ick>; ++ reg = <0x48004e10 0x4>; ++ ti,enable-bit = <0>; ++}; ++ ++usbhost_120m_fck: usbhost_120m_fck@48005400 { ++ #clock-cells = <0>; ++ compatible = "gate-clock"; ++ clocks = <&dpll5_m2_ck>; ++ reg = <0x48005400 0x4>; ++ bit-shift = <1>; ++}; ++ ++usbhost_48m_fck: usbhost_48m_fck@48005400 { ++ #clock-cells = <0>; ++ compatible = "ti,dss-gate-clock"; ++ clocks = <&omap_48m_fck>; ++ reg = <0x48005400 0x4>; ++ ti,enable-bit = <0>; ++}; ++ ++usbhost_ick: usbhost_ick@48005410 { ++ #clock-cells = <0>; ++ compatible = "ti,omap3-dss-interface-clock"; ++ clocks = <&l4_ick>; ++ reg = <0x48005410 0x4>; ++ ti,enable-bit = <0>; ++}; +--- /dev/null ++++ b/arch/arm/boot/dts/omap36xx-clocks.dtsi +@@ -0,0 +1,80 @@ ++/* ++ * Device Tree Source for OMAP36xx clock data ++ * ++ * Copyright (C) 2013 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. ++ */ ++ ++dpll4_ck: dpll4_ck@48004d00 { ++ #clock-cells = <0>; ++ compatible = "ti,omap3-dpll-per-j-type-clock"; ++ clocks = <&sys_ck>, <&sys_ck>; ++ ti,modes = <0x82>; ++ reg-names = "control", "idlest", "autoidle", "mult-div1"; ++ reg = <0x48004d00 0x4>, <0x48004d20 0x4>, <0x48004d30 0x4>, <0x48004d44 0x4>; ++}; ++ ++dpll4_m2x2_ck: dpll4_m2x2_ck@48004d00 { ++ #clock-cells = <0>; ++ compatible = "ti,hsdiv-gate-clock"; ++ clocks = <&dpll4_m2x2_mul_ck>; ++ reg = <0x48004d00 0x4>; ++ ti,enable-bit = <0x1b>; ++ ti,set-bit-to-disable; ++}; ++ ++dpll3_m3x2_ck: dpll3_m3x2_ck@48004d00 { ++ #clock-cells = <0>; ++ compatible = "ti,hsdiv-gate-clock"; ++ clocks = <&dpll3_m3x2_mul_ck>; ++ reg = <0x48004d00 0x4>; ++ ti,enable-bit = <0xc>; ++ ti,set-bit-to-disable; ++}; ++ ++dpll4_m3x2_ck: dpll4_m3x2_ck@48004d00 { ++ #clock-cells = <0>; ++ compatible = "ti,hsdiv-gate-clock"; ++ clocks = <&dpll4_m3x2_mul_ck>; ++ reg = <0x48004d00 0x4>; ++ ti,enable-bit = <0x1c>; ++ ti,set-bit-to-disable; ++}; ++ ++dpll4_m5x2_ck: dpll4_m5x2_ck@48004d00 { ++ #clock-cells = <0>; ++ compatible = "ti,hsdiv-gate-clock"; ++ clocks = <&dpll4_m5x2_mul_ck>; ++ reg = <0x48004d00 0x4>; ++ ti,enable-bit = <0x1e>; ++ ti,set-rate-parent; ++ ti,set-bit-to-disable; ++}; ++ ++dpll4_m6x2_ck: dpll4_m6x2_ck@48004d00 { ++ #clock-cells = <0>; ++ compatible = "ti,hsdiv-gate-clock"; ++ clocks = <&dpll4_m6x2_mul_ck>; ++ reg = <0x48004d00 0x4>; ++ ti,enable-bit = <0x1f>; ++ ti,set-bit-to-disable; ++}; ++ ++omap_192m_alwon_fck: omap_192m_alwon_fck { ++ #clock-cells = <0>; ++ compatible = "fixed-factor-clock"; ++ clocks = <&dpll4_m2x2_ck>; ++ clock-mult = <1>; ++ clock-div = <1>; ++}; ++ ++uart4_fck: uart4_fck@48005000 { ++ #clock-cells = <0>; ++ compatible = "ti,gate-clock"; ++ clocks = <&per_48m_fck>; ++ reg = <0x48005000 0x4>; ++ ti,enable-bit = <18>; ++}; +--- a/arch/arm/boot/dts/omap36xx.dtsi ++++ b/arch/arm/boot/dts/omap36xx.dtsi +@@ -35,4 +35,114 @@ + clock-frequency = <48000000>; + }; + }; +-}; ++ ++ clocks { ++ #address-cells = <1>; ++ #size-cells = <1>; ++ ranges; ++ /include/ "omap36xx-clocks.dtsi" ++ /include/ "omap34xx-omap36xx-clocks.dtsi" ++ /include/ "omap36xx-omap3430es2plus-clocks.dtsi" ++ /include/ "omap36xx-am35xx-omap3430es2plus-clocks.dtsi" ++ }; ++ ++ clockdomains { ++ usbhost_clkdm: usbhost_clkdm { ++ compatible = "ti,clockdomain"; ++ clocks = <&usbhost_48m_fck>, <&usbhost_ick>; ++ }; ++ ++ wkup_clkdm: wkup_clkdm { ++ compatible = "ti,clockdomain"; ++ clocks = <&wdt1_ick>, <&gpt12_ick>, <&gpio1_ick>, ++ <&gpt1_ick>, <&omap_32ksync_ick>, <&wdt2_ick>, ++ <&wdt2_fck>; ++ }; ++ ++ cam_clkdm: cam_clkdm { ++ compatible = "ti,clockdomain"; ++ clocks = <&cam_ick>; ++ }; ++ ++ dpll4_clkdm: dpll4_clkdm { ++ compatible = "ti,clockdomain"; ++ clocks = <&dpll4_ck>; ++ }; ++ ++ sgx_clkdm: sgx_clkdm { ++ compatible = "ti,clockdomain"; ++ clocks = <&sgx_ick>; ++ }; ++ ++ dpll3_clkdm: dpll3_clkdm { ++ compatible = "ti,clockdomain"; ++ clocks = <&dpll3_ck>; ++ }; ++ ++ iva2_clkdm: iva2_clkdm { ++ compatible = "ti,clockdomain"; ++ clocks = <&iva2_ck>; ++ }; ++ ++ dpll1_clkdm: dpll1_clkdm { ++ compatible = "ti,clockdomain"; ++ clocks = <&dpll1_ck>; ++ }; ++ ++ dpll5_clkdm: dpll5_clkdm { ++ compatible = "ti,clockdomain"; ++ clocks = <&dpll5_ck>; ++ }; ++ ++ dpll2_clkdm: dpll2_clkdm { ++ compatible = "ti,clockdomain"; ++ clocks = <&dpll2_ck>; ++ }; ++ ++ dss_clkdm: dss_clkdm { ++ compatible = "ti,clockdomain"; ++ clocks = <&dss1_alwon_fck_3430es2>, <&dss_ick_3430es2>; ++ }; ++ ++ core_l4_clkdm: core_l4_clkdm { ++ compatible = "ti,clockdomain"; ++ clocks = <&mmchs1_ick>, <&mmchs2_ick>, <&hdq_fck>, ++ <&uart1_ick>, <&mcspi4_fck>, <&i2c3_fck>, ++ <&mcspi2_ick>, <&uart2_ick>, <&mcspi3_ick>, ++ <&i2c1_fck>, <&hdq_ick>, <&sha12_ick>, ++ <&mcbsp5_ick>, <&mcspi3_fck>, <&aes2_ick>, ++ <&mcspi1_ick>, <&uart2_fck>, <&mmchs2_fck>, ++ <&mmchs1_fck>, <&i2c3_ick>, <&mcspi1_fck>, ++ <&mcspi4_ick>, <&omapctrl_ick>, <&mcbsp1_ick>, ++ <&mcspi2_fck>, <&gpt10_ick>, <&i2c2_fck>, ++ <&i2c2_ick>, <&gpt11_ick>, <&i2c1_ick>, ++ <&uart1_fck>; ++ }; ++ ++ core_l3_clkdm: core_l3_clkdm { ++ compatible = "ti,clockdomain"; ++ clocks = <&sdrc_ick>; ++ }; ++ ++ per_clkdm: per_clkdm { ++ compatible = "ti,clockdomain"; ++ clocks = <&gpt2_ick>, <&uart3_fck>, <&gpio3_ick>, ++ <&mcbsp2_ick>, <&gpt6_ick>, <&mcbsp4_ick>, ++ <&gpt4_ick>, <&mcbsp3_ick>, <&gpt8_ick>, ++ <&uart3_ick>, <&gpt5_ick>, <&gpt7_ick>, ++ <&gpio2_ick>, <&gpio6_ick>, <&gpt9_ick>, ++ <&gpt3_ick>, <&gpio5_ick>, <&wdt3_ick>, ++ <&gpio4_ick>, <&wdt3_fck>, <&uart4_ick>; ++ }; ++ ++ emu_clkdm: emu_clkdm { ++ compatible = "ti,clockdomain"; ++ clocks = <&emu_src_ck>; ++ }; ++ ++ d2d_clkdm: d2d_clkdm { ++ compatible = "ti,clockdomain"; ++ clocks = <&mad2d_ick>, <&sad2d_ick>, <&modem_fck>; ++ }; ++ }; ++}; +\ No newline at end of file +--- /dev/null ++++ b/arch/arm/boot/dts/omap36xx-omap3430es2plus-clocks.dtsi +@@ -0,0 +1,175 @@ ++/* ++ * Device Tree Source for OMAP34xx/OMAP36xx clock data ++ * ++ * Copyright (C) 2013 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. ++ */ ++ ++ssi_ssr_div_fck_3430es2: ssi_ssr_div_fck_3430es2@48004a40 { ++ #clock-cells = <0>; ++ compatible = "divider-clock"; ++ clocks = <&corex2_fck>; ++ bit-shift = <8>; ++ reg = <0x48004a40 0x4>; ++ table = < 1 1 >, < 2 2 >, < 3 3 >, < 4 4 >, < 6 6 >, < 8 8 >; ++ bit-mask = <0xf>; ++}; ++ ++ssi_ssr_fck_3430es2: ssi_ssr_fck_3430es2@48004a00 { ++ #clock-cells = <0>; ++ compatible = "gate-clock"; ++ clocks = <&ssi_ssr_div_fck_3430es2>; ++ bit-shift = <0>; ++ reg = <0x48004a00 0x4>; ++}; ++ ++ssi_sst_fck_3430es2: ssi_sst_fck_3430es2 { ++ #clock-cells = <0>; ++ compatible = "fixed-factor-clock"; ++ clocks = <&ssi_ssr_fck_3430es2>; ++ clock-mult = <1>; ++ clock-div = <2>; ++}; ++ ++hsotgusb_ick: hsotgusb_ick@48004a10 { ++ #clock-cells = <0>; ++ compatible = "ti,omap3-hsotgusb-interface-clock"; ++ clocks = <&core_l3_ick>; ++ reg = <0x48004a10 0x4>; ++ ti,enable-bit = <4>; ++}; ++ ++ssi_l4_ick: ssi_l4_ick { ++ #clock-cells = <0>; ++ compatible = "fixed-factor-clock"; ++ clocks = <&l4_ick>; ++ clock-mult = <1>; ++ clock-div = <1>; ++}; ++ ++ssi_ick_3430es2: ssi_ick_3430es2@48004a10 { ++ #clock-cells = <0>; ++ compatible = "ti,omap3-ssi-interface-clock"; ++ clocks = <&ssi_l4_ick>; ++ reg = <0x48004a10 0x4>; ++ ti,enable-bit = <0>; ++}; ++ ++dpll5_ck: dpll5_ck@48004d04 { ++ #clock-cells = <0>; ++ compatible = "ti,omap3-dpll-clock"; ++ clocks = <&sys_ck>, <&sys_ck>; ++ ti,modes = <0x82>; ++ reg-names = "control", "idlest", "autoidle", "mult-div1"; ++ reg = <0x48004d04 0x4>, <0x48004d24 0x4>, <0x48004d34 0x4>, <0x48004d4c 0x4>; ++}; ++ ++dpll5_m2_ck: dpll5_m2_ck@48004d50 { ++ #clock-cells = <0>; ++ compatible = "divider-clock"; ++ clocks = <&dpll5_ck>; ++ reg = <0x48004d50 0x4>; ++ bit-mask = <0x1f>; ++ index-starts-at-one; ++}; ++ ++dpll5_m2_d20_ck: dpll5_m2_d20_ck { ++ #clock-cells = <0>; ++ compatible = "fixed-factor-clock"; ++ clocks = <&dpll5_m2_ck>; ++ clock-mult = <1>; ++ clock-div = <20>; ++}; ++ ++sys_d2_ck: sys_d2_ck { ++ #clock-cells = <0>; ++ compatible = "fixed-factor-clock"; ++ clocks = <&sys_ck>; ++ clock-mult = <1>; ++ clock-div = <2>; ++}; ++ ++omap_96m_d2_fck: omap_96m_d2_fck { ++ #clock-cells = <0>; ++ compatible = "fixed-factor-clock"; ++ clocks = <&omap_96m_fck>; ++ clock-mult = <1>; ++ clock-div = <2>; ++}; ++ ++omap_96m_d4_fck: omap_96m_d4_fck { ++ #clock-cells = <0>; ++ compatible = "fixed-factor-clock"; ++ clocks = <&omap_96m_fck>; ++ clock-mult = <1>; ++ clock-div = <4>; ++}; ++ ++omap_96m_d8_fck: omap_96m_d8_fck { ++ #clock-cells = <0>; ++ compatible = "fixed-factor-clock"; ++ clocks = <&omap_96m_fck>; ++ clock-mult = <1>; ++ clock-div = <8>; ++}; ++ ++omap_96m_d10_fck: omap_96m_d10_fck { ++ #clock-cells = <0>; ++ compatible = "fixed-factor-clock"; ++ clocks = <&omap_96m_fck>; ++ clock-mult = <1>; ++ clock-div = <10>; ++}; ++ ++dpll5_m2_d4_ck: dpll5_m2_d4_ck { ++ #clock-cells = <0>; ++ compatible = "fixed-factor-clock"; ++ clocks = <&dpll5_m2_ck>; ++ clock-mult = <1>; ++ clock-div = <4>; ++}; ++ ++dpll5_m2_d8_ck: dpll5_m2_d8_ck { ++ #clock-cells = <0>; ++ compatible = "fixed-factor-clock"; ++ clocks = <&dpll5_m2_ck>; ++ clock-mult = <1>; ++ clock-div = <8>; ++}; ++ ++dpll5_m2_d16_ck: dpll5_m2_d16_ck { ++ #clock-cells = <0>; ++ compatible = "fixed-factor-clock"; ++ clocks = <&dpll5_m2_ck>; ++ clock-mult = <1>; ++ clock-div = <16>; ++}; ++ ++usim_mux_fck: usim_mux_fck@48004c40 { ++ #clock-cells = <0>; ++ compatible = "mux-clock"; ++ clocks = <&sys_ck>, <&dpll5_m2_d20_ck>, <&sys_d2_ck>, <&omap_96m_d2_fck>, <&omap_96m_d4_fck>, <&omap_96m_d8_fck>, <&omap_96m_d10_fck>, <&dpll5_m2_d4_ck>, <&dpll5_m2_d8_ck>, <&dpll5_m2_d16_ck>; ++ bit-shift = <3>; ++ reg = <0x48004c40 0x4>; ++ table = <&sys_ck 1>, <&dpll5_m2_d20_ck 10>, <&sys_d2_ck 2>, <&omap_96m_d2_fck 3>, <&omap_96m_d4_fck 4>, <&omap_96m_d8_fck 5>, <&omap_96m_d10_fck 6>, <&dpll5_m2_d4_ck 7>, <&dpll5_m2_d8_ck 8>, <&dpll5_m2_d16_ck 9>; ++ bit-mask = <0xf>; ++}; ++ ++usim_fck: usim_fck@48004c00 { ++ #clock-cells = <0>; ++ compatible = "gate-clock"; ++ clocks = <&usim_mux_fck>; ++ bit-shift = <9>; ++ reg = <0x48004c00 0x4>; ++}; ++ ++usim_ick: usim_ick@48004c10 { ++ #clock-cells = <0>; ++ compatible = "ti,omap3-interface-clock"; ++ clocks = <&wkup_l4_ick>; ++ reg = <0x48004c10 0x4>; ++ ti,enable-bit = <9>; ++}; +--- a/arch/arm/boot/dts/omap3-beagle.dts ++++ b/arch/arm/boot/dts/omap3-beagle.dts +@@ -44,17 +44,6 @@ + }; + }; + +- /* HS USB Port 2 RESET */ +- hsusb2_reset: hsusb2_reset_reg { +- compatible = "regulator-fixed"; +- regulator-name = "hsusb2_reset"; +- regulator-min-microvolt = <3300000>; +- regulator-max-microvolt = <3300000>; +- gpio = <&gpio5 19 0>; /* gpio_147 */ +- startup-delay-us = <70000>; +- enable-active-high; +- }; +- + /* HS USB Port 2 Power */ + hsusb2_power: hsusb2_power_reg { + compatible = "regulator-fixed"; +@@ -68,7 +57,7 @@ + /* HS USB Host PHY on PORT 2 */ + hsusb2_phy: hsusb2_phy { + compatible = "usb-nop-xceiv"; +- reset-supply = <&hsusb2_reset>; ++ reset-gpios = <&gpio5 19 GPIO_ACTIVE_LOW>; /* gpio_147 */ + vcc-supply = <&hsusb2_power>; + }; + +@@ -101,18 +90,18 @@ + + hsusbb2_pins: pinmux_hsusbb2_pins { + pinctrl-single,pins = < +- 0x5c0 (PIN_OUTPUT | MUX_MODE3) /* usbb2_ulpitll_clk.usbb1_ulpiphy_clk */ +- 0x5c2 (PIN_OUTPUT | MUX_MODE3) /* usbb2_ulpitll_clk.usbb1_ulpiphy_stp */ +- 0x5c4 (PIN_INPUT_PULLDOWN | MUX_MODE3) /* usbb2_ulpitll_clk.usbb1_ulpiphy_dir */ +- 0x5c6 (PIN_INPUT_PULLDOWN | MUX_MODE3) /* usbb2_ulpitll_clk.usbb1_ulpiphy_nxt */ +- 0x5c8 (PIN_INPUT_PULLDOWN | MUX_MODE3) /* usbb2_ulpitll_clk.usbb1_ulpiphy_dat0 */ +- 0x5cA (PIN_INPUT_PULLDOWN | MUX_MODE3) /* usbb2_ulpitll_clk.usbb1_ulpiphy_dat1 */ +- 0x1a4 (PIN_INPUT_PULLDOWN | MUX_MODE3) /* usbb2_ulpitll_clk.usbb1_ulpiphy_dat2 */ +- 0x1a6 (PIN_INPUT_PULLDOWN | MUX_MODE3) /* usbb2_ulpitll_clk.usbb1_ulpiphy_dat3 */ +- 0x1a8 (PIN_INPUT_PULLDOWN | MUX_MODE3) /* usbb2_ulpitll_clk.usbb1_ulpiphy_dat4 */ +- 0x1aa (PIN_INPUT_PULLDOWN | MUX_MODE3) /* usbb2_ulpitll_clk.usbb1_ulpiphy_dat5 */ +- 0x1ac (PIN_INPUT_PULLDOWN | MUX_MODE3) /* usbb2_ulpitll_clk.usbb1_ulpiphy_dat6 */ +- 0x1ae (PIN_INPUT_PULLDOWN | MUX_MODE3) /* usbb2_ulpitll_clk.usbb1_ulpiphy_dat7 */ ++ 0x5c0 (PIN_OUTPUT | MUX_MODE3) /* etk_d10.hsusb2_clk */ ++ 0x5c2 (PIN_OUTPUT | MUX_MODE3) /* etk_d11.hsusb2_stp */ ++ 0x5c4 (PIN_INPUT_PULLDOWN | MUX_MODE3) /* etk_d12.hsusb2_dir */ ++ 0x5c6 (PIN_INPUT_PULLDOWN | MUX_MODE3) /* etk_d13.hsusb2_nxt */ ++ 0x5c8 (PIN_INPUT_PULLDOWN | MUX_MODE3) /* etk_d14.hsusb2_data0 */ ++ 0x5cA (PIN_INPUT_PULLDOWN | MUX_MODE3) /* etk_d15.hsusb2_data1 */ ++ 0x1a4 (PIN_INPUT_PULLDOWN | MUX_MODE3) /* mcspi1_cs3.hsusb2_data2 */ ++ 0x1a6 (PIN_INPUT_PULLDOWN | MUX_MODE3) /* mcspi2_clk.hsusb2_data7 */ ++ 0x1a8 (PIN_INPUT_PULLDOWN | MUX_MODE3) /* mcspi2_simo.hsusb2_data4 */ ++ 0x1aa (PIN_INPUT_PULLDOWN | MUX_MODE3) /* mcspi2_somi.hsusb2_data5 */ ++ 0x1ac (PIN_INPUT_PULLDOWN | MUX_MODE3) /* mcspi2_cs0.hsusb2_data6 */ ++ 0x1ae (PIN_INPUT_PULLDOWN | MUX_MODE3) /* mcspi2_cs1.hsusb2_data3 */ + >; + }; + +@@ -180,3 +169,39 @@ + pinctrl-names = "default"; + pinctrl-0 = <&gpio1_pins>; + }; ++ ++&usb_otg_hs { ++ interface-type = <0>; ++ usb-phy = <&usb2_phy>; ++ mode = <3>; ++ power = <50>; ++}; ++ ++&dpi { ++ vdds_dsi-supply = <&vpll2>; ++}; ++ ++/ { ++ aliases { ++ display0 = &dvi0; ++ display1 = &tv0; ++ }; ++ ++ tfp410: encoder@0 { ++ compatible = "ti,tfp410"; ++ video-source = <&dpi>; ++ data-lines = <24>; ++ gpios = <&gpio5 10 0>; /* 170, power-down */ ++ }; ++ ++ dvi0: connector@0 { ++ compatible = "ti,dvi_connector"; ++ video-source = <&tfp410>; ++ i2c-bus = <&i2c3>; ++ }; ++ ++ tv0: connector@1 { ++ compatible = "ti,svideo_connector"; ++ video-source = <&venc>; ++ }; ++}; +--- a/arch/arm/boot/dts/omap3-beagle-xm.dts ++++ b/arch/arm/boot/dts/omap3-beagle-xm.dts +@@ -69,6 +69,23 @@ + }; + + }; ++ ++ /* HS USB Port 2 Power */ ++ hsusb2_power: hsusb2_power_reg { ++ compatible = "regulator-fixed"; ++ regulator-name = "hsusb2_vbus"; ++ regulator-min-microvolt = <3300000>; ++ regulator-max-microvolt = <3300000>; ++ gpio = <&twl_gpio 18 0>; /* GPIO LEDA */ ++ startup-delay-us = <70000>; ++ }; ++ ++ /* HS USB Host PHY on PORT 2 */ ++ hsusb2_phy: hsusb2_phy { ++ compatible = "usb-nop-xceiv"; ++ reset-gpios = <&gpio5 19 GPIO_ACTIVE_LOW>; /* gpio_147 */ ++ vcc-supply = <&hsusb2_power>; ++ }; + }; + + &omap3_pmx_wkup { +@@ -79,6 +96,37 @@ + }; + }; + ++&omap3_pmx_core { ++ pinctrl-names = "default"; ++ pinctrl-0 = < ++ &hsusbb2_pins ++ >; ++ ++ uart3_pins: pinmux_uart3_pins { ++ pinctrl-single,pins = < ++ 0x16e (PIN_INPUT | PIN_OFF_WAKEUPENABLE | MUX_MODE0) /* uart3_rx_irrx.uart3_rx_irrx */ ++ 0x170 (PIN_OUTPUT | MUX_MODE0) /* uart3_tx_irtx.uart3_tx_irtx OUTPUT | MODE0 */ ++ >; ++ }; ++ ++ hsusbb2_pins: pinmux_hsusbb2_pins { ++ pinctrl-single,pins = < ++ 0x5c0 (PIN_OUTPUT | MUX_MODE3) /* etk_d10.hsusb2_clk */ ++ 0x5c2 (PIN_OUTPUT | MUX_MODE3) /* etk_d11.hsusb2_stp */ ++ 0x5c4 (PIN_INPUT_PULLDOWN | MUX_MODE3) /* etk_d12.hsusb2_dir */ ++ 0x5c6 (PIN_INPUT_PULLDOWN | MUX_MODE3) /* etk_d13.hsusb2_nxt */ ++ 0x5c8 (PIN_INPUT_PULLDOWN | MUX_MODE3) /* etk_d14.hsusb2_data0 */ ++ 0x5cA (PIN_INPUT_PULLDOWN | MUX_MODE3) /* etk_d15.hsusb2_data1 */ ++ 0x1a4 (PIN_INPUT_PULLDOWN | MUX_MODE3) /* mcspi1_cs3.hsusb2_data2 */ ++ 0x1a6 (PIN_INPUT_PULLDOWN | MUX_MODE3) /* mcspi2_clk.hsusb2_data7 */ ++ 0x1a8 (PIN_INPUT_PULLDOWN | MUX_MODE3) /* mcspi2_simo.hsusb2_data4 */ ++ 0x1aa (PIN_INPUT_PULLDOWN | MUX_MODE3) /* mcspi2_somi.hsusb2_data5 */ ++ 0x1ac (PIN_INPUT_PULLDOWN | MUX_MODE3) /* mcspi2_cs0.hsusb2_data6 */ ++ 0x1ae (PIN_INPUT_PULLDOWN | MUX_MODE3) /* mcspi2_cs1.hsusb2_data3 */ ++ >; ++ }; ++}; ++ + &i2c1 { + clock-frequency = <2600000>; + +@@ -144,19 +192,12 @@ + &usb_otg_hs { + interface-type = <0>; + usb-phy = <&usb2_phy>; ++ phys = <&usb2_phy>; ++ phy-names = "usb2-phy"; + mode = <3>; + power = <50>; + }; + +-&omap3_pmx_core { +- uart3_pins: pinmux_uart3_pins { +- pinctrl-single,pins = < +- 0x16e (PIN_INPUT | PIN_OFF_WAKEUPENABLE | MUX_MODE0) /* uart3_rx_irrx.uart3_rx_irrx */ +- 0x170 (PIN_OUTPUT | MUX_MODE0) /* uart3_tx_irtx.uart3_tx_irtx OUTPUT | MODE0 */ +- >; +- }; +-}; +- + &uart3 { + pinctrl-names = "default"; + pinctrl-0 = <&uart3_pins>; +@@ -166,3 +207,11 @@ + pinctrl-names = "default"; + pinctrl-0 = <&gpio1_pins>; + }; ++ ++&usbhshost { ++ port2-mode = "ehci-phy"; ++}; ++ ++&usbhsehci { ++ phys = <0 &hsusb2_phy>; ++}; +--- a/arch/arm/boot/dts/omap3.dtsi ++++ b/arch/arm/boot/dts/omap3.dtsi +@@ -19,6 +19,9 @@ + interrupt-parent = <&intc>; + + aliases { ++ i2c0 = &i2c1; ++ i2c1 = &i2c2; ++ i2c2 = &i2c3; + serial0 = &uart1; + serial1 = &uart2; + serial2 = &uart3; +@@ -32,6 +35,11 @@ + compatible = "arm,cortex-a8"; + device_type = "cpu"; + reg = <0x0>; ++ ++ clocks = <&dpll1_ck>; ++ clock-names = "cpu"; ++ ++ clock-latency = <300000>; /* From omap-cpufreq driver */ + }; + }; + +@@ -80,6 +88,8 @@ + compatible = "ti,omap-counter32k"; + reg = <0x48320000 0x20>; + ti,hwmods = "counter_32k"; ++ clocks = <&wkup_32k_fck>; ++ clock-names = "fck"; + }; + + intc: interrupt-controller@48200000 { +@@ -100,6 +110,8 @@ + #dma-cells = <1>; + #dma-channels = <32>; + #dma-requests = <96>; ++ clocks = <&core_l3_ick>; ++ clock-names = "fck"; + }; + + omap3_pmx_core: pinmux@48002030 { +@@ -125,6 +137,8 @@ + reg = <0x48310000 0x200>; + interrupts = <29>; + ti,hwmods = "gpio1"; ++ clocks = <&gpio1_ick>, <&gpio1_dbck>; ++ clock-names = "fck", "dbclk"; + ti,gpio-always-on; + gpio-controller; + #gpio-cells = <2>; +@@ -137,6 +151,8 @@ + reg = <0x49050000 0x200>; + interrupts = <30>; + ti,hwmods = "gpio2"; ++ clocks = <&gpio2_ick>, <&gpio2_dbck>; ++ clock-names = "fck", "dbclk"; + gpio-controller; + #gpio-cells = <2>; + interrupt-controller; +@@ -148,6 +164,8 @@ + reg = <0x49052000 0x200>; + interrupts = <31>; + ti,hwmods = "gpio3"; ++ clocks = <&gpio3_ick>, <&gpio3_dbck>; ++ clock-names = "fck", "dbclk"; + gpio-controller; + #gpio-cells = <2>; + interrupt-controller; +@@ -159,6 +177,8 @@ + reg = <0x49054000 0x200>; + interrupts = <32>; + ti,hwmods = "gpio4"; ++ clocks = <&gpio4_ick>, <&gpio4_dbck>; ++ clock-names = "fck", "dbclk"; + gpio-controller; + #gpio-cells = <2>; + interrupt-controller; +@@ -170,6 +190,8 @@ + reg = <0x49056000 0x200>; + interrupts = <33>; + ti,hwmods = "gpio5"; ++ clocks = <&gpio5_ick>, <&gpio5_dbck>; ++ clock-names = "fck", "dbclk"; + gpio-controller; + #gpio-cells = <2>; + interrupt-controller; +@@ -181,6 +203,8 @@ + reg = <0x49058000 0x200>; + interrupts = <34>; + ti,hwmods = "gpio6"; ++ clocks = <&gpio6_ick>, <&gpio6_dbck>; ++ clock-names = "fck", "dbclk"; + gpio-controller; + #gpio-cells = <2>; + interrupt-controller; +@@ -190,18 +214,24 @@ + uart1: serial@4806a000 { + compatible = "ti,omap3-uart"; + ti,hwmods = "uart1"; ++ clocks = <&uart1_fck>; ++ clock-names = "fck"; + clock-frequency = <48000000>; + }; + + uart2: serial@4806c000 { + compatible = "ti,omap3-uart"; + ti,hwmods = "uart2"; ++ clocks = <&uart2_fck>; ++ clock-names = "fck"; + clock-frequency = <48000000>; + }; + + uart3: serial@49020000 { + compatible = "ti,omap3-uart"; + ti,hwmods = "uart3"; ++ clocks = <&uart3_fck>; ++ clock-names = "fck"; + clock-frequency = <48000000>; + }; + +@@ -210,6 +240,8 @@ + #address-cells = <1>; + #size-cells = <0>; + ti,hwmods = "i2c1"; ++ clocks = <&i2c1_fck>; ++ clock-names = "fck"; + }; + + i2c2: i2c@48072000 { +@@ -217,6 +249,8 @@ + #address-cells = <1>; + #size-cells = <0>; + ti,hwmods = "i2c2"; ++ clocks = <&i2c2_fck>; ++ clock-names = "fck"; + }; + + i2c3: i2c@48060000 { +@@ -224,6 +258,8 @@ + #address-cells = <1>; + #size-cells = <0>; + ti,hwmods = "i2c3"; ++ clocks = <&i2c3_fck>; ++ clock-names = "fck"; + }; + + mcspi1: spi@48098000 { +@@ -231,6 +267,8 @@ + #address-cells = <1>; + #size-cells = <0>; + ti,hwmods = "mcspi1"; ++ clocks = <&mcspi1_fck>; ++ clock-names = "fck"; + ti,spi-num-cs = <4>; + dmas = <&sdma 35>, + <&sdma 36>, +@@ -249,6 +287,8 @@ + #address-cells = <1>; + #size-cells = <0>; + ti,hwmods = "mcspi2"; ++ clocks = <&mcspi2_fck>; ++ clock-names = "fck"; + ti,spi-num-cs = <2>; + dmas = <&sdma 43>, + <&sdma 44>, +@@ -262,6 +302,8 @@ + #address-cells = <1>; + #size-cells = <0>; + ti,hwmods = "mcspi3"; ++ clocks = <&mcspi3_fck>; ++ clock-names = "fck"; + ti,spi-num-cs = <2>; + dmas = <&sdma 15>, + <&sdma 16>, +@@ -275,6 +317,8 @@ + #address-cells = <1>; + #size-cells = <0>; + ti,hwmods = "mcspi4"; ++ clocks = <&mcspi4_fck>; ++ clock-names = "fck"; + ti,spi-num-cs = <1>; + dmas = <&sdma 70>, <&sdma 71>; + dma-names = "tx0", "rx0"; +@@ -283,6 +327,8 @@ + mmc1: mmc@4809c000 { + compatible = "ti,omap3-hsmmc"; + ti,hwmods = "mmc1"; ++ clocks = <&mmchs1_fck>, <&omap_32k_fck>; ++ clock-names = "fck", "dbck"; + ti,dual-volt; + dmas = <&sdma 61>, <&sdma 62>; + dma-names = "tx", "rx"; +@@ -291,6 +337,8 @@ + mmc2: mmc@480b4000 { + compatible = "ti,omap3-hsmmc"; + ti,hwmods = "mmc2"; ++ clocks = <&mmchs2_fck>, <&omap_32k_fck>; ++ clock-names = "fck", "dbck"; + dmas = <&sdma 47>, <&sdma 48>; + dma-names = "tx", "rx"; + }; +@@ -298,6 +346,8 @@ + mmc3: mmc@480ad000 { + compatible = "ti,omap3-hsmmc"; + ti,hwmods = "mmc3"; ++ clocks = <&mmchs3_fck>, <&omap_32k_fck>; ++ clock-names = "fck", "dbck"; + dmas = <&sdma 77>, <&sdma 78>; + dma-names = "tx", "rx"; + }; +@@ -305,6 +355,8 @@ + wdt2: wdt@48314000 { + compatible = "ti,omap3-wdt"; + ti,hwmods = "wd_timer2"; ++ clocks = <&wdt2_fck>; ++ clock-names = "fck"; + }; + + mcbsp1: mcbsp@48074000 { +@@ -317,6 +369,8 @@ + interrupt-names = "common", "tx", "rx"; + ti,buffer-size = <128>; + ti,hwmods = "mcbsp1"; ++ clocks = <&mcbsp1_fck>, <&mcbsp_clks>, <&core_96m_fck>; ++ clock-names = "fck", "pad_fck", "prcm_fck"; + dmas = <&sdma 31>, + <&sdma 32>; + dma-names = "tx", "rx"; +@@ -366,6 +420,8 @@ + interrupt-names = "common", "tx", "rx"; + ti,buffer-size = <128>; + ti,hwmods = "mcbsp4"; ++ clocks = <&mcbsp4_fck>, <&mcbsp_clks>, <&per_96m_fck>; ++ clock-names = "fck", "pad_fck", "prcm_fck"; + dmas = <&sdma 19>, + <&sdma 20>; + dma-names = "tx", "rx"; +@@ -381,16 +437,31 @@ + interrupt-names = "common", "tx", "rx"; + ti,buffer-size = <128>; + ti,hwmods = "mcbsp5"; ++ clocks = <&mcbsp5_fck>, <&mcbsp_clks>, <&core_96m_fck>; ++ clock-names = "fck", "pad_fck", "prcm_fck"; + dmas = <&sdma 21>, + <&sdma 22>; + dma-names = "tx", "rx"; + }; + ++ mailbox: mailbox@48094000 { ++ compatible = "ti,omap2-mailbox"; ++ reg = <0x48094000 0x200>; ++ interrupts = <26>; ++ ti,hwmods = "mailbox"; ++ ti,mbox-num-users = <2>; ++ ti,mbox-num-fifos = <2>; ++ ti,mbox-names = "dsp"; ++ ti,mbox-data = <0 1 0 0>; ++ }; ++ + timer1: timer@48318000 { + compatible = "ti,omap3430-timer"; + reg = <0x48318000 0x400>; + interrupts = <37>; + ti,hwmods = "timer1"; ++ clocks = <&gpt1_fck>; ++ clock-names = "fck"; + ti,timer-alwon; + }; + +@@ -399,6 +470,8 @@ + reg = <0x49032000 0x400>; + interrupts = <38>; + ti,hwmods = "timer2"; ++ clocks = <&gpt2_fck>; ++ clock-names = "fck"; + }; + + timer3: timer@49034000 { +@@ -406,6 +479,8 @@ + reg = <0x49034000 0x400>; + interrupts = <39>; + ti,hwmods = "timer3"; ++ clocks = <&gpt3_fck>; ++ clock-names = "fck"; + }; + + timer4: timer@49036000 { +@@ -413,6 +488,8 @@ + reg = <0x49036000 0x400>; + interrupts = <40>; + ti,hwmods = "timer4"; ++ clocks = <&gpt4_fck>; ++ clock-names = "fck"; + }; + + timer5: timer@49038000 { +@@ -420,6 +497,8 @@ + reg = <0x49038000 0x400>; + interrupts = <41>; + ti,hwmods = "timer5"; ++ clocks = <&gpt5_fck>; ++ clock-names = "fck"; + ti,timer-dsp; + }; + +@@ -428,6 +507,8 @@ + reg = <0x4903a000 0x400>; + interrupts = <42>; + ti,hwmods = "timer6"; ++ clocks = <&gpt6_fck>; ++ clock-names = "fck"; + ti,timer-dsp; + }; + +@@ -436,6 +517,8 @@ + reg = <0x4903c000 0x400>; + interrupts = <43>; + ti,hwmods = "timer7"; ++ clocks = <&gpt7_fck>; ++ clock-names = "fck"; + ti,timer-dsp; + }; + +@@ -444,6 +527,8 @@ + reg = <0x4903e000 0x400>; + interrupts = <44>; + ti,hwmods = "timer8"; ++ clocks = <&gpt8_fck>; ++ clock-names = "fck"; + ti,timer-pwm; + ti,timer-dsp; + }; +@@ -453,6 +538,8 @@ + reg = <0x49040000 0x400>; + interrupts = <45>; + ti,hwmods = "timer9"; ++ clocks = <&gpt9_fck>; ++ clock-names = "fck"; + ti,timer-pwm; + }; + +@@ -461,6 +548,8 @@ + reg = <0x48086000 0x400>; + interrupts = <46>; + ti,hwmods = "timer10"; ++ clocks = <&gpt10_fck>; ++ clock-names = "fck"; + ti,timer-pwm; + }; + +@@ -469,6 +558,8 @@ + reg = <0x48088000 0x400>; + interrupts = <47>; + ti,hwmods = "timer11"; ++ clocks = <&gpt11_fck>; ++ clock-names = "fck"; + ti,timer-pwm; + }; + +@@ -477,6 +568,8 @@ + reg = <0x48304000 0x400>; + interrupts = <95>; + ti,hwmods = "timer12"; ++ clocks = <&gpt12_fck>; ++ clock-names = "fck"; + ti,timer-alwon; + ti,timer-secure; + }; +@@ -486,12 +579,16 @@ + reg = <0x48062000 0x1000>; + interrupts = <78>; + ti,hwmods = "usb_tll_hs"; ++ clocks = <&usbtll_fck>; ++ clock-names = "fck"; + }; + + usbhshost: usbhshost@48064000 { + compatible = "ti,usbhs-host"; + reg = <0x48064000 0x400>; + ti,hwmods = "usb_host_hs"; ++ clocks = <&usbhost_48m_fck>, <&usbhost_120m_fck>; ++ clock-names = "fck", "ehci_logic_fck"; + #address-cells = <1>; + #size-cells = <1>; + ranges; +@@ -514,6 +611,8 @@ + gpmc: gpmc@6e000000 { + compatible = "ti,omap3430-gpmc"; + ti,hwmods = "gpmc"; ++ clocks = <&gpmc_fck>; ++ clock-names = "fck"; + reg = <0x6e000000 0x02d0>; + interrupts = <20>; + gpmc,num-cs = <8>; +@@ -528,9 +627,61 @@ + interrupts = <92>, <93>; + interrupt-names = "mc", "dma"; + ti,hwmods = "usb_otg_hs"; ++ clocks = <&hsotgusb_ick>; ++ clock-names = "fck"; + multipoint = <1>; + num-eps = <16>; + ram-bits = <12>; + }; ++ ++ dss@48050000 { ++ compatible = "ti,omap3-dss", "simple-bus"; ++ reg = <0x48050000 0x200>; ++ ti,hwmods = "dss_core"; ++ #address-cells = <1>; ++ #size-cells = <1>; ++ ranges; ++ ++ dispc@48050400 { ++ compatible = "ti,omap3-dispc"; ++ reg = <0x48050400 0x400>; ++ interrupts = <25>; ++ ti,hwmods = "dss_dispc"; ++ }; ++ ++ dpi: encoder@0 { ++ compatible = "ti,omap3-dpi"; ++ }; ++ ++ sdi: encoder@1 { ++ compatible = "ti,omap3-sdi"; ++ }; ++ ++ dsi: encoder@4804fc00 { ++ compatible = "ti,omap3-dsi"; ++ reg = <0x4804fc00 0x400>; ++ interrupts = <25>; ++ ti,hwmods = "dss_dsi1"; ++ }; ++ ++ rfbi: encoder@48050800 { ++ compatible = "ti,omap3-rfbi"; ++ reg = <0x48050800 0x100>; ++ ti,hwmods = "dss_rfbi"; ++ }; ++ ++ venc: encoder@48050c00 { ++ compatible = "ti,omap3-venc"; ++ reg = <0x48050c00 0x100>; ++ ti,hwmods = "dss_venc"; ++ }; ++ }; ++ }; ++ ++ clocks { ++ #address-cells = <1>; ++ #size-cells = <1>; ++ ranges; ++ /include/ "omap3xxx-clocks.dtsi" + }; + }; +--- a/arch/arm/boot/dts/omap3-evm.dts ++++ b/arch/arm/boot/dts/omap3-evm.dts +@@ -70,6 +70,8 @@ + &usb_otg_hs { + interface-type = <0>; + usb-phy = <&usb2_phy>; ++ phys = <&usb2_phy>; ++ phy-names = "usb2-phy"; + mode = <3>; + power = <50>; + }; +--- a/arch/arm/boot/dts/omap3-overo.dtsi ++++ b/arch/arm/boot/dts/omap3-overo.dtsi +@@ -76,6 +76,8 @@ + &usb_otg_hs { + interface-type = <0>; + usb-phy = <&usb2_phy>; ++ phys = <&usb2_phy>; ++ phy-names = "usb2-phy"; + mode = <3>; + power = <50>; + }; +--- a/arch/arm/boot/dts/omap3-tobi.dts ++++ b/arch/arm/boot/dts/omap3-tobi.dts +@@ -81,3 +81,36 @@ + &mmc3 { + status = "disabled"; + }; ++ ++&dpi { ++ vdds_dsi-supply = <&vpll2>; ++}; ++ ++/ { ++ aliases { ++ display0 = &lcd0; ++ }; ++ ++ lcd0: display@0 { ++ compatible = "samsung,lte430wq-f0c", "panel-dpi"; ++ video-source = <&dpi>; ++ data-lines = <24>; ++ ++ panel-timing { ++ clock-frequency = <9200000>; ++ hactive = <480>; ++ vactive = <272>; ++ hfront-porch = <8>; ++ hback-porch = <4>; ++ hsync-len = <41>; ++ vback-porch = <2>; ++ vfront-porch = <4>; ++ vsync-len = <10>; ++ ++ hsync-active = <0>; ++ vsync-active = <0>; ++ de-active = <1>; ++ pixelclk-active = <1>; ++ }; ++ }; ++}; +--- /dev/null ++++ b/arch/arm/boot/dts/omap3xxx-clocks.dtsi +@@ -0,0 +1,1513 @@ ++/* ++ * Device Tree Source for OMAP3 clock data ++ * ++ * Copyright (C) 2013 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. ++ */ ++ ++dummy_apb_pclk: dummy_apb_pclk { ++ #clock-cells = <0>; ++ compatible = "fixed-clock"; ++ clock-frequency = <0x0>; ++}; ++ ++omap_32k_fck: omap_32k_fck { ++ #clock-cells = <0>; ++ compatible = "fixed-clock"; ++ clock-frequency = <32768>; ++}; ++ ++virt_12m_ck: virt_12m_ck { ++ #clock-cells = <0>; ++ compatible = "fixed-clock"; ++ clock-frequency = <12000000>; ++}; ++ ++virt_13m_ck: virt_13m_ck { ++ #clock-cells = <0>; ++ compatible = "fixed-clock"; ++ clock-frequency = <13000000>; ++}; ++ ++virt_19200000_ck: virt_19200000_ck { ++ #clock-cells = <0>; ++ compatible = "fixed-clock"; ++ clock-frequency = <19200000>; ++}; ++ ++virt_26000000_ck: virt_26000000_ck { ++ #clock-cells = <0>; ++ compatible = "fixed-clock"; ++ clock-frequency = <26000000>; ++}; ++ ++virt_38_4m_ck: virt_38_4m_ck { ++ #clock-cells = <0>; ++ compatible = "fixed-clock"; ++ clock-frequency = <38400000>; ++}; ++ ++virt_16_8m_ck: virt_16_8m_ck { ++ #clock-cells = <0>; ++ compatible = "fixed-clock"; ++ clock-frequency = <16800000>; ++}; ++ ++osc_sys_ck: osc_sys_ck@48306d40 { ++ #clock-cells = <0>; ++ compatible = "mux-clock"; ++ clocks = <&virt_12m_ck>, <&virt_13m_ck>, <&virt_19200000_ck>, <&virt_26000000_ck>, <&virt_38_4m_ck>, <&virt_16_8m_ck>; ++ reg = <0x48306d40 0x4>; ++ bit-mask = <0x7>; ++}; ++ ++sys_ck: sys_ck@48307270 { ++ #clock-cells = <0>; ++ compatible = "divider-clock"; ++ clocks = <&osc_sys_ck>; ++ bit-shift = <6>; ++ reg = <0x48307270 0x4>; ++ bit-mask = <0x3>; ++ index-starts-at-one; ++}; ++ ++dpll4_ck: dpll4_ck@48004d00 { ++ #clock-cells = <0>; ++ compatible = "ti,omap3-dpll-per-clock"; ++ clocks = <&sys_ck>, <&sys_ck>; ++ ti,modes = <0x82>; ++ reg-names = "control", "idlest", "autoidle", "mult-div1"; ++ reg = <0x48004d00 0x4>, <0x48004d20 0x4>, <0x48004d30 0x4>, <0x48004d44 0x4>; ++}; ++ ++dpll4_m2_ck: dpll4_m2_ck@48004d48 { ++ #clock-cells = <0>; ++ compatible = "divider-clock"; ++ clocks = <&dpll4_ck>; ++ reg = <0x48004d48 0x4>; ++ bit-mask = <0x3f>; ++ index-starts-at-one; ++}; ++ ++dpll4_m2x2_mul_ck: dpll4_m2x2_mul_ck { ++ #clock-cells = <0>; ++ compatible = "fixed-factor-clock"; ++ clocks = <&dpll4_m2_ck>; ++ clock-mult = <2>; ++ clock-div = <1>; ++}; ++ ++dpll4_m2x2_ck: dpll4_m2x2_ck@48004d00 { ++ #clock-cells = <0>; ++ compatible = "gate-clock"; ++ clocks = <&dpll4_m2x2_mul_ck>; ++ bit-shift = <0x1b>; ++ reg = <0x48004d00 0x4>; ++ set-bit-to-disable; ++}; ++ ++omap_96m_alwon_fck: omap_96m_alwon_fck { ++ #clock-cells = <0>; ++ compatible = "fixed-factor-clock"; ++ clocks = <&dpll4_m2x2_ck>; ++ clock-mult = <1>; ++ clock-div = <1>; ++}; ++ ++dpll3_ck: dpll3_ck@48004d00 { ++ #clock-cells = <0>; ++ compatible = "ti,omap3-dpll-core-clock"; ++ clocks = <&sys_ck>, <&sys_ck>; ++ reg-names = "control", "idlest", "autoidle", "mult-div1"; ++ reg = <0x48004d00 0x4>, <0x48004d20 0x4>, <0x48004d30 0x4>, <0x48004d40 0x4>; ++}; ++ ++dpll3_m3_ck: dpll3_m3_ck@48005140 { ++ #clock-cells = <0>; ++ compatible = "divider-clock"; ++ clocks = <&dpll3_ck>; ++ bit-shift = <16>; ++ reg = <0x48005140 0x4>; ++ bit-mask = <0x1f>; ++ index-starts-at-one; ++}; ++ ++dpll3_m3x2_mul_ck: dpll3_m3x2_mul_ck { ++ #clock-cells = <0>; ++ compatible = "fixed-factor-clock"; ++ clocks = <&dpll3_m3_ck>; ++ clock-mult = <2>; ++ clock-div = <1>; ++}; ++ ++dpll3_m3x2_ck: dpll3_m3x2_ck@48004d00 { ++ #clock-cells = <0>; ++ compatible = "gate-clock"; ++ clocks = <&dpll3_m3x2_mul_ck>; ++ bit-shift = <0xc>; ++ reg = <0x48004d00 0x4>; ++ set-bit-to-disable; ++}; ++ ++emu_core_alwon_ck: emu_core_alwon_ck { ++ #clock-cells = <0>; ++ compatible = "fixed-factor-clock"; ++ clocks = <&dpll3_m3x2_ck>; ++ clock-mult = <1>; ++ clock-div = <1>; ++}; ++ ++sys_altclk: sys_altclk { ++ #clock-cells = <0>; ++ compatible = "fixed-clock"; ++ clock-frequency = <0x0>; ++}; ++ ++mcbsp_clks: mcbsp_clks { ++ #clock-cells = <0>; ++ compatible = "fixed-clock"; ++ clock-frequency = <0x0>; ++}; ++ ++sys_clkout1: sys_clkout1@48306d70 { ++ #clock-cells = <0>; ++ compatible = "gate-clock"; ++ clocks = <&osc_sys_ck>; ++ reg = <0x48306d70 0x4>; ++ bit-shift = <7>; ++}; ++ ++dpll3_m2_ck: dpll3_m2_ck@48004d40 { ++ #clock-cells = <0>; ++ compatible = "divider-clock"; ++ clocks = <&dpll3_ck>; ++ bit-shift = <27>; ++ reg = <0x48004d40 0x4>; ++ bit-mask = <0x1f>; ++ index-starts-at-one; ++}; ++ ++core_ck: core_ck { ++ #clock-cells = <0>; ++ compatible = "fixed-factor-clock"; ++ clocks = <&dpll3_m2_ck>; ++ clock-mult = <1>; ++ clock-div = <1>; ++}; ++ ++dpll1_fck: dpll1_fck@48004940 { ++ #clock-cells = <0>; ++ compatible = "divider-clock"; ++ clocks = <&core_ck>; ++ bit-shift = <19>; ++ reg = <0x48004940 0x4>; ++ bit-mask = <0x7>; ++ index-starts-at-one; ++}; ++ ++dpll1_ck: dpll1_ck@48004904 { ++ #clock-cells = <0>; ++ compatible = "ti,omap3-dpll-clock"; ++ clocks = <&sys_ck>, <&dpll1_fck>; ++ reg-names = "control", "idlest", "autoidle", "mult-div1"; ++ reg = <0x48004904 0x4>, <0x48004924 0x4>, <0x48004934 0x4>, <0x48004940 0x4>; ++}; ++ ++dpll1_x2_ck: dpll1_x2_ck { ++ #clock-cells = <0>; ++ compatible = "fixed-factor-clock"; ++ clocks = <&dpll1_ck>; ++ clock-mult = <2>; ++ clock-div = <1>; ++}; ++ ++dpll1_x2m2_ck: dpll1_x2m2_ck@48004944 { ++ #clock-cells = <0>; ++ compatible = "divider-clock"; ++ clocks = <&dpll1_x2_ck>; ++ reg = <0x48004944 0x4>; ++ bit-mask = <0x1f>; ++ index-starts-at-one; ++}; ++ ++dpll3_x2_ck: dpll3_x2_ck { ++ #clock-cells = <0>; ++ compatible = "fixed-factor-clock"; ++ clocks = <&dpll3_ck>; ++ clock-mult = <2>; ++ clock-div = <1>; ++}; ++ ++dpll3_m2x2_ck: dpll3_m2x2_ck { ++ #clock-cells = <0>; ++ compatible = "fixed-factor-clock"; ++ clocks = <&dpll3_m2_ck>; ++ clock-mult = <2>; ++ clock-div = <1>; ++}; ++ ++dpll4_x2_ck: dpll4_x2_ck { ++ #clock-cells = <0>; ++ compatible = "fixed-factor-clock"; ++ clocks = <&dpll4_ck>; ++ clock-mult = <2>; ++ clock-div = <1>; ++}; ++ ++cm_96m_fck: cm_96m_fck { ++ #clock-cells = <0>; ++ compatible = "fixed-factor-clock"; ++ clocks = <&omap_96m_alwon_fck>; ++ clock-mult = <1>; ++ clock-div = <1>; ++}; ++ ++omap_96m_fck: omap_96m_fck@48004d40 { ++ #clock-cells = <0>; ++ compatible = "mux-clock"; ++ clocks = <&cm_96m_fck>, <&sys_ck>; ++ bit-shift = <6>; ++ reg = <0x48004d40 0x4>; ++ bit-mask = <0x1>; ++}; ++ ++dpll4_m3_ck: dpll4_m3_ck@48004e40 { ++ #clock-cells = <0>; ++ compatible = "divider-clock"; ++ clocks = <&dpll4_ck>; ++ bit-shift = <8>; ++ reg = <0x48004e40 0x4>; ++ bit-mask = <0x3f>; ++ index-starts-at-one; ++}; ++ ++dpll4_m3x2_mul_ck: dpll4_m3x2_mul_ck { ++ #clock-cells = <0>; ++ compatible = "fixed-factor-clock"; ++ clocks = <&dpll4_m3_ck>; ++ clock-mult = <2>; ++ clock-div = <1>; ++}; ++ ++dpll4_m3x2_ck: dpll4_m3x2_ck@48004d00 { ++ #clock-cells = <0>; ++ compatible = "gate-clock"; ++ clocks = <&dpll4_m3x2_mul_ck>; ++ bit-shift = <0x1c>; ++ reg = <0x48004d00 0x4>; ++ set-bit-to-disable; ++}; ++ ++omap_54m_fck: omap_54m_fck@48004d40 { ++ #clock-cells = <0>; ++ compatible = "mux-clock"; ++ clocks = <&dpll4_m3x2_ck>, <&sys_altclk>; ++ bit-shift = <5>; ++ reg = <0x48004d40 0x4>; ++ bit-mask = <0x1>; ++}; ++ ++cm_96m_d2_fck: cm_96m_d2_fck { ++ #clock-cells = <0>; ++ compatible = "fixed-factor-clock"; ++ clocks = <&cm_96m_fck>; ++ clock-mult = <1>; ++ clock-div = <2>; ++}; ++ ++omap_48m_fck: omap_48m_fck@48004d40 { ++ #clock-cells = <0>; ++ compatible = "mux-clock"; ++ clocks = <&cm_96m_d2_fck>, <&sys_altclk>; ++ bit-shift = <3>; ++ reg = <0x48004d40 0x4>; ++ table = <&cm_96m_d2_fck 0>, <&sys_altclk 1>; ++ bit-mask = <0x1>; ++}; ++ ++omap_12m_fck: omap_12m_fck { ++ #clock-cells = <0>; ++ compatible = "fixed-factor-clock"; ++ clocks = <&omap_48m_fck>; ++ clock-mult = <1>; ++ clock-div = <4>; ++}; ++ ++dpll4_m4_ck: dpll4_m4_ck@48004e40 { ++ #clock-cells = <0>; ++ compatible = "divider-clock"; ++ clocks = <&dpll4_ck>; ++ reg = <0x48004e40 0x4>; ++ bit-mask = <0x3f>; ++ index-starts-at-one; ++}; ++ ++dpll4_m4x2_mul_ck: dpll4_m4x2_mul_ck { ++ #clock-cells = <0>; ++ compatible = "fixed-factor-clock"; ++ clocks = <&dpll4_m4_ck>; ++ clock-mult = <2>; ++ clock-div = <1>; ++}; ++ ++dpll4_m4x2_ck: dpll4_m4x2_ck@48004d00 { ++ #clock-cells = <0>; ++ compatible = "gate-clock"; ++ clocks = <&dpll4_m4x2_mul_ck>; ++ bit-shift = <0x1d>; ++ reg = <0x48004d00 0x4>; ++ set-bit-to-disable; ++}; ++ ++dpll4_m5_ck: dpll4_m5_ck@48004f40 { ++ #clock-cells = <0>; ++ compatible = "divider-clock"; ++ clocks = <&dpll4_ck>; ++ reg = <0x48004f40 0x4>; ++ bit-mask = <0x3f>; ++ index-starts-at-one; ++}; ++ ++dpll4_m5x2_mul_ck: dpll4_m5x2_mul_ck { ++ #clock-cells = <0>; ++ compatible = "fixed-factor-clock"; ++ clocks = <&dpll4_m5_ck>; ++ clock-mult = <2>; ++ clock-div = <1>; ++}; ++ ++dpll4_m5x2_ck: dpll4_m5x2_ck@48004d00 { ++ #clock-cells = <0>; ++ compatible = "gate-clock"; ++ clocks = <&dpll4_m5x2_mul_ck>; ++ bit-shift = <0x1e>; ++ reg = <0x48004d00 0x4>; ++ set-bit-to-disable; ++}; ++ ++dpll4_m6_ck: dpll4_m6_ck@48005140 { ++ #clock-cells = <0>; ++ compatible = "divider-clock"; ++ clocks = <&dpll4_ck>; ++ bit-shift = <24>; ++ reg = <0x48005140 0x4>; ++ bit-mask = <0x3f>; ++ index-starts-at-one; ++}; ++ ++dpll4_m6x2_mul_ck: dpll4_m6x2_mul_ck { ++ #clock-cells = <0>; ++ compatible = "fixed-factor-clock"; ++ clocks = <&dpll4_m6_ck>; ++ clock-mult = <2>; ++ clock-div = <1>; ++}; ++ ++dpll4_m6x2_ck: dpll4_m6x2_ck@48004d00 { ++ #clock-cells = <0>; ++ compatible = "gate-clock"; ++ clocks = <&dpll4_m6x2_mul_ck>; ++ bit-shift = <0x1f>; ++ reg = <0x48004d00 0x4>; ++ set-bit-to-disable; ++}; ++ ++emu_per_alwon_ck: emu_per_alwon_ck { ++ #clock-cells = <0>; ++ compatible = "fixed-factor-clock"; ++ clocks = <&dpll4_m6x2_ck>; ++ clock-mult = <1>; ++ clock-div = <1>; ++}; ++ ++clkout2_src_mux_ck: clkout2_src_mux_ck@48004d70 { ++ #clock-cells = <0>; ++ compatible = "mux-clock"; ++ clocks = <&core_ck>, <&sys_ck>, <&cm_96m_fck>, <&omap_54m_fck>; ++ reg = <0x48004d70 0x4>; ++ bit-mask = <0x3>; ++}; ++ ++clkout2_src_ck: clkout2_src_ck@48004d70 { ++ #clock-cells = <0>; ++ compatible = "gate-clock"; ++ clocks = <&clkout2_src_mux_ck>; ++ bit-shift = <7>; ++ reg = <0x48004d70 0x4>; ++}; ++ ++sys_clkout2: sys_clkout2@48004d70 { ++ #clock-cells = <0>; ++ compatible = "divider-clock"; ++ clocks = <&clkout2_src_ck>; ++ bit-shift = <3>; ++ reg = <0x48004d70 0x4>; ++ bit-mask = <0x7>; ++ index-power-of-two; ++}; ++ ++corex2_fck: corex2_fck { ++ #clock-cells = <0>; ++ compatible = "fixed-factor-clock"; ++ clocks = <&dpll3_m2x2_ck>; ++ clock-mult = <1>; ++ clock-div = <1>; ++}; ++ ++mpu_ck: mpu_ck { ++ #clock-cells = <0>; ++ compatible = "fixed-factor-clock"; ++ clocks = <&dpll1_x2m2_ck>; ++ clock-mult = <1>; ++ clock-div = <1>; ++}; ++ ++arm_fck: arm_fck@48004924 { ++ #clock-cells = <0>; ++ compatible = "divider-clock"; ++ clocks = <&mpu_ck>; ++ reg = <0x48004924 0x4>; ++ bit-mask = <0x1>; ++}; ++ ++emu_mpu_alwon_ck: emu_mpu_alwon_ck { ++ #clock-cells = <0>; ++ compatible = "fixed-factor-clock"; ++ clocks = <&mpu_ck>; ++ clock-mult = <1>; ++ clock-div = <1>; ++}; ++ ++l3_ick: l3_ick@48004a40 { ++ #clock-cells = <0>; ++ compatible = "divider-clock"; ++ clocks = <&core_ck>; ++ reg = <0x48004a40 0x4>; ++ bit-mask = <0x3>; ++ index-starts-at-one; ++}; ++ ++l4_ick: l4_ick@48004a40 { ++ #clock-cells = <0>; ++ compatible = "divider-clock"; ++ clocks = <&l3_ick>; ++ bit-shift = <2>; ++ reg = <0x48004a40 0x4>; ++ bit-mask = <0x3>; ++ index-starts-at-one; ++}; ++ ++rm_ick: rm_ick@48004c40 { ++ #clock-cells = <0>; ++ compatible = "divider-clock"; ++ clocks = <&l4_ick>; ++ bit-shift = <1>; ++ reg = <0x48004c40 0x4>; ++ bit-mask = <0x3>; ++ index-starts-at-one; ++}; ++ ++gpt10_mux_fck: gpt10_mux_fck@48004a40 { ++ #clock-cells = <0>; ++ compatible = "mux-clock"; ++ clocks = <&omap_32k_fck>, <&sys_ck>; ++ bit-shift = <6>; ++ reg = <0x48004a40 0x4>; ++ bit-mask = <0x1>; ++}; ++ ++gpt10_fck: gpt10_fck@48004a00 { ++ #clock-cells = <0>; ++ compatible = "gate-clock"; ++ clocks = <&gpt10_mux_fck>; ++ bit-shift = <11>; ++ reg = <0x48004a00 0x4>; ++}; ++ ++gpt11_mux_fck: gpt11_mux_fck@48004a40 { ++ #clock-cells = <0>; ++ compatible = "mux-clock"; ++ clocks = <&omap_32k_fck>, <&sys_ck>; ++ bit-shift = <7>; ++ reg = <0x48004a40 0x4>; ++ bit-mask = <0x1>; ++}; ++ ++gpt11_fck: gpt11_fck@48004a00 { ++ #clock-cells = <0>; ++ compatible = "gate-clock"; ++ clocks = <&gpt11_mux_fck>; ++ bit-shift = <12>; ++ reg = <0x48004a00 0x4>; ++}; ++ ++core_96m_fck: core_96m_fck { ++ #clock-cells = <0>; ++ compatible = "fixed-factor-clock"; ++ clocks = <&omap_96m_fck>; ++ clock-mult = <1>; ++ clock-div = <1>; ++}; ++ ++mmchs2_fck: mmchs2_fck@48004a00 { ++ #clock-cells = <0>; ++ compatible = "ti,gate-clock"; ++ clocks = <&core_96m_fck>; ++ reg = <0x48004a00 0x4>; ++ ti,enable-bit = <25>; ++}; ++ ++mmchs1_fck: mmchs1_fck@48004a00 { ++ #clock-cells = <0>; ++ compatible = "ti,gate-clock"; ++ clocks = <&core_96m_fck>; ++ reg = <0x48004a00 0x4>; ++ ti,enable-bit = <24>; ++}; ++ ++i2c3_fck: i2c3_fck@48004a00 { ++ #clock-cells = <0>; ++ compatible = "ti,gate-clock"; ++ clocks = <&core_96m_fck>; ++ reg = <0x48004a00 0x4>; ++ ti,enable-bit = <17>; ++}; ++ ++i2c2_fck: i2c2_fck@48004a00 { ++ #clock-cells = <0>; ++ compatible = "ti,gate-clock"; ++ clocks = <&core_96m_fck>; ++ reg = <0x48004a00 0x4>; ++ ti,enable-bit = <16>; ++}; ++ ++i2c1_fck: i2c1_fck@48004a00 { ++ #clock-cells = <0>; ++ compatible = "ti,gate-clock"; ++ clocks = <&core_96m_fck>; ++ reg = <0x48004a00 0x4>; ++ ti,enable-bit = <15>; ++}; ++ ++mcbsp5_mux_fck: mcbsp5_mux_fck@480022d8 { ++ #clock-cells = <0>; ++ compatible = "mux-clock"; ++ clocks = <&core_96m_fck>, <&mcbsp_clks>; ++ bit-shift = <4>; ++ reg = <0x480022d8 0x4>; ++ bit-mask = <0x1>; ++}; ++ ++mcbsp5_fck: mcbsp5_fck@48004a00 { ++ #clock-cells = <0>; ++ compatible = "gate-clock"; ++ clocks = <&mcbsp5_mux_fck>; ++ bit-shift = <10>; ++ reg = <0x48004a00 0x4>; ++}; ++ ++mcbsp1_mux_fck: mcbsp1_mux_fck@48002274 { ++ #clock-cells = <0>; ++ compatible = "mux-clock"; ++ clocks = <&core_96m_fck>, <&mcbsp_clks>; ++ bit-shift = <2>; ++ reg = <0x48002274 0x4>; ++ bit-mask = <0x1>; ++}; ++ ++mcbsp1_fck: mcbsp1_fck@48004a00 { ++ #clock-cells = <0>; ++ compatible = "gate-clock"; ++ clocks = <&mcbsp1_mux_fck>; ++ bit-shift = <9>; ++ reg = <0x48004a00 0x4>; ++}; ++ ++core_48m_fck: core_48m_fck { ++ #clock-cells = <0>; ++ compatible = "fixed-factor-clock"; ++ clocks = <&omap_48m_fck>; ++ clock-mult = <1>; ++ clock-div = <1>; ++}; ++ ++mcspi4_fck: mcspi4_fck@48004a00 { ++ #clock-cells = <0>; ++ compatible = "ti,gate-clock"; ++ clocks = <&core_48m_fck>; ++ reg = <0x48004a00 0x4>; ++ ti,enable-bit = <21>; ++}; ++ ++mcspi3_fck: mcspi3_fck@48004a00 { ++ #clock-cells = <0>; ++ compatible = "ti,gate-clock"; ++ clocks = <&core_48m_fck>; ++ reg = <0x48004a00 0x4>; ++ ti,enable-bit = <20>; ++}; ++ ++mcspi2_fck: mcspi2_fck@48004a00 { ++ #clock-cells = <0>; ++ compatible = "ti,gate-clock"; ++ clocks = <&core_48m_fck>; ++ reg = <0x48004a00 0x4>; ++ ti,enable-bit = <19>; ++}; ++ ++mcspi1_fck: mcspi1_fck@48004a00 { ++ #clock-cells = <0>; ++ compatible = "ti,gate-clock"; ++ clocks = <&core_48m_fck>; ++ reg = <0x48004a00 0x4>; ++ ti,enable-bit = <18>; ++}; ++ ++uart2_fck: uart2_fck@48004a00 { ++ #clock-cells = <0>; ++ compatible = "ti,gate-clock"; ++ clocks = <&core_48m_fck>; ++ reg = <0x48004a00 0x4>; ++ ti,enable-bit = <14>; ++}; ++ ++uart1_fck: uart1_fck@48004a00 { ++ #clock-cells = <0>; ++ compatible = "ti,gate-clock"; ++ clocks = <&core_48m_fck>; ++ reg = <0x48004a00 0x4>; ++ ti,enable-bit = <13>; ++}; ++ ++core_12m_fck: core_12m_fck { ++ #clock-cells = <0>; ++ compatible = "fixed-factor-clock"; ++ clocks = <&omap_12m_fck>; ++ clock-mult = <1>; ++ clock-div = <1>; ++}; ++ ++hdq_fck: hdq_fck@48004a00 { ++ #clock-cells = <0>; ++ compatible = "ti,gate-clock"; ++ clocks = <&core_12m_fck>; ++ reg = <0x48004a00 0x4>; ++ ti,enable-bit = <22>; ++}; ++ ++core_l3_ick: core_l3_ick { ++ #clock-cells = <0>; ++ compatible = "fixed-factor-clock"; ++ clocks = <&l3_ick>; ++ clock-mult = <1>; ++ clock-div = <1>; ++}; ++ ++sdrc_ick: sdrc_ick@48004a10 { ++ #clock-cells = <0>; ++ compatible = "ti,gate-clock"; ++ clocks = <&core_l3_ick>; ++ reg = <0x48004a10 0x4>; ++ ti,enable-bit = <1>; ++}; ++ ++gpmc_fck: gpmc_fck { ++ #clock-cells = <0>; ++ compatible = "fixed-factor-clock"; ++ clocks = <&core_l3_ick>; ++ clock-mult = <1>; ++ clock-div = <1>; ++}; ++ ++core_l4_ick: core_l4_ick { ++ #clock-cells = <0>; ++ compatible = "fixed-factor-clock"; ++ clocks = <&l4_ick>; ++ clock-mult = <1>; ++ clock-div = <1>; ++}; ++ ++mmchs2_ick: mmchs2_ick@48004a10 { ++ #clock-cells = <0>; ++ compatible = "ti,omap3-interface-clock"; ++ clocks = <&core_l4_ick>; ++ reg = <0x48004a10 0x4>; ++ ti,enable-bit = <25>; ++}; ++ ++mmchs1_ick: mmchs1_ick@48004a10 { ++ #clock-cells = <0>; ++ compatible = "ti,omap3-interface-clock"; ++ clocks = <&core_l4_ick>; ++ reg = <0x48004a10 0x4>; ++ ti,enable-bit = <24>; ++}; ++ ++hdq_ick: hdq_ick@48004a10 { ++ #clock-cells = <0>; ++ compatible = "ti,omap3-interface-clock"; ++ clocks = <&core_l4_ick>; ++ reg = <0x48004a10 0x4>; ++ ti,enable-bit = <22>; ++}; ++ ++mcspi4_ick: mcspi4_ick@48004a10 { ++ #clock-cells = <0>; ++ compatible = "ti,omap3-interface-clock"; ++ clocks = <&core_l4_ick>; ++ reg = <0x48004a10 0x4>; ++ ti,enable-bit = <21>; ++}; ++ ++mcspi3_ick: mcspi3_ick@48004a10 { ++ #clock-cells = <0>; ++ compatible = "ti,omap3-interface-clock"; ++ clocks = <&core_l4_ick>; ++ reg = <0x48004a10 0x4>; ++ ti,enable-bit = <20>; ++}; ++ ++mcspi2_ick: mcspi2_ick@48004a10 { ++ #clock-cells = <0>; ++ compatible = "ti,omap3-interface-clock"; ++ clocks = <&core_l4_ick>; ++ reg = <0x48004a10 0x4>; ++ ti,enable-bit = <19>; ++}; ++ ++mcspi1_ick: mcspi1_ick@48004a10 { ++ #clock-cells = <0>; ++ compatible = "ti,omap3-interface-clock"; ++ clocks = <&core_l4_ick>; ++ reg = <0x48004a10 0x4>; ++ ti,enable-bit = <18>; ++}; ++ ++i2c3_ick: i2c3_ick@48004a10 { ++ #clock-cells = <0>; ++ compatible = "ti,omap3-interface-clock"; ++ clocks = <&core_l4_ick>; ++ reg = <0x48004a10 0x4>; ++ ti,enable-bit = <17>; ++}; ++ ++i2c2_ick: i2c2_ick@48004a10 { ++ #clock-cells = <0>; ++ compatible = "ti,omap3-interface-clock"; ++ clocks = <&core_l4_ick>; ++ reg = <0x48004a10 0x4>; ++ ti,enable-bit = <16>; ++}; ++ ++i2c1_ick: i2c1_ick@48004a10 { ++ #clock-cells = <0>; ++ compatible = "ti,omap3-interface-clock"; ++ clocks = <&core_l4_ick>; ++ reg = <0x48004a10 0x4>; ++ ti,enable-bit = <15>; ++}; ++ ++uart2_ick: uart2_ick@48004a10 { ++ #clock-cells = <0>; ++ compatible = "ti,omap3-interface-clock"; ++ clocks = <&core_l4_ick>; ++ reg = <0x48004a10 0x4>; ++ ti,enable-bit = <14>; ++}; ++ ++uart1_ick: uart1_ick@48004a10 { ++ #clock-cells = <0>; ++ compatible = "ti,omap3-interface-clock"; ++ clocks = <&core_l4_ick>; ++ reg = <0x48004a10 0x4>; ++ ti,enable-bit = <13>; ++}; ++ ++gpt11_ick: gpt11_ick@48004a10 { ++ #clock-cells = <0>; ++ compatible = "ti,omap3-interface-clock"; ++ clocks = <&core_l4_ick>; ++ reg = <0x48004a10 0x4>; ++ ti,enable-bit = <12>; ++}; ++ ++gpt10_ick: gpt10_ick@48004a10 { ++ #clock-cells = <0>; ++ compatible = "ti,omap3-interface-clock"; ++ clocks = <&core_l4_ick>; ++ reg = <0x48004a10 0x4>; ++ ti,enable-bit = <11>; ++}; ++ ++mcbsp5_ick: mcbsp5_ick@48004a10 { ++ #clock-cells = <0>; ++ compatible = "ti,omap3-interface-clock"; ++ clocks = <&core_l4_ick>; ++ reg = <0x48004a10 0x4>; ++ ti,enable-bit = <10>; ++}; ++ ++mcbsp1_ick: mcbsp1_ick@48004a10 { ++ #clock-cells = <0>; ++ compatible = "ti,omap3-interface-clock"; ++ clocks = <&core_l4_ick>; ++ reg = <0x48004a10 0x4>; ++ ti,enable-bit = <9>; ++}; ++ ++omapctrl_ick: omapctrl_ick@48004a10 { ++ #clock-cells = <0>; ++ compatible = "ti,omap3-interface-clock"; ++ clocks = <&core_l4_ick>; ++ reg = <0x48004a10 0x4>; ++ ti,enable-bit = <6>; ++}; ++ ++dss_tv_fck: dss_tv_fck@48004e00 { ++ #clock-cells = <0>; ++ compatible = "gate-clock"; ++ clocks = <&omap_54m_fck>; ++ reg = <0x48004e00 0x4>; ++ bit-shift = <2>; ++}; ++ ++dss_96m_fck: dss_96m_fck@48004e00 { ++ #clock-cells = <0>; ++ compatible = "gate-clock"; ++ clocks = <&omap_96m_fck>; ++ reg = <0x48004e00 0x4>; ++ bit-shift = <2>; ++}; ++ ++dss2_alwon_fck: dss2_alwon_fck@48004e00 { ++ #clock-cells = <0>; ++ compatible = "gate-clock"; ++ clocks = <&sys_ck>; ++ reg = <0x48004e00 0x4>; ++ bit-shift = <1>; ++}; ++ ++gpt1_mux_fck: gpt1_mux_fck@48004c40 { ++ #clock-cells = <0>; ++ compatible = "mux-clock"; ++ clocks = <&omap_32k_fck>, <&sys_ck>; ++ reg = <0x48004c40 0x4>; ++ bit-mask = <0x1>; ++}; ++ ++gpt1_fck: gpt1_fck@48004c00 { ++ #clock-cells = <0>; ++ compatible = "gate-clock"; ++ clocks = <&gpt1_mux_fck>; ++ bit-shift = <0>; ++ reg = <0x48004c00 0x4>; ++}; ++ ++aes2_ick: aes2_ick@48004a10 { ++ #clock-cells = <0>; ++ compatible = "ti,omap3-interface-clock"; ++ clocks = <&core_l4_ick>; ++ reg = <0x48004a10 0x4>; ++ ti,enable-bit = <28>; ++}; ++ ++wkup_32k_fck: wkup_32k_fck { ++ #clock-cells = <0>; ++ compatible = "fixed-factor-clock"; ++ clocks = <&omap_32k_fck>; ++ clock-mult = <1>; ++ clock-div = <1>; ++}; ++ ++gpio1_dbck: gpio1_dbck@48004c00 { ++ #clock-cells = <0>; ++ compatible = "gate-clock"; ++ clocks = <&wkup_32k_fck>; ++ reg = <0x48004c00 0x4>; ++ bit-shift = <3>; ++}; ++ ++sha12_ick: sha12_ick@48004a10 { ++ #clock-cells = <0>; ++ compatible = "ti,omap3-interface-clock"; ++ clocks = <&core_l4_ick>; ++ reg = <0x48004a10 0x4>; ++ ti,enable-bit = <27>; ++}; ++ ++wdt2_fck: wdt2_fck@48004c00 { ++ #clock-cells = <0>; ++ compatible = "ti,gate-clock"; ++ clocks = <&wkup_32k_fck>; ++ reg = <0x48004c00 0x4>; ++ ti,enable-bit = <5>; ++}; ++ ++wkup_l4_ick: wkup_l4_ick { ++ #clock-cells = <0>; ++ compatible = "fixed-factor-clock"; ++ clocks = <&sys_ck>; ++ clock-mult = <1>; ++ clock-div = <1>; ++}; ++ ++wdt2_ick: wdt2_ick@48004c10 { ++ #clock-cells = <0>; ++ compatible = "ti,omap3-interface-clock"; ++ clocks = <&wkup_l4_ick>; ++ reg = <0x48004c10 0x4>; ++ ti,enable-bit = <5>; ++}; ++ ++wdt1_ick: wdt1_ick@48004c10 { ++ #clock-cells = <0>; ++ compatible = "ti,omap3-interface-clock"; ++ clocks = <&wkup_l4_ick>; ++ reg = <0x48004c10 0x4>; ++ ti,enable-bit = <4>; ++}; ++ ++gpio1_ick: gpio1_ick@48004c10 { ++ #clock-cells = <0>; ++ compatible = "ti,omap3-interface-clock"; ++ clocks = <&wkup_l4_ick>; ++ reg = <0x48004c10 0x4>; ++ ti,enable-bit = <3>; ++}; ++ ++omap_32ksync_ick: omap_32ksync_ick@48004c10 { ++ #clock-cells = <0>; ++ compatible = "ti,omap3-interface-clock"; ++ clocks = <&wkup_l4_ick>; ++ reg = <0x48004c10 0x4>; ++ ti,enable-bit = <2>; ++}; ++ ++gpt12_ick: gpt12_ick@48004c10 { ++ #clock-cells = <0>; ++ compatible = "ti,omap3-interface-clock"; ++ clocks = <&wkup_l4_ick>; ++ reg = <0x48004c10 0x4>; ++ ti,enable-bit = <1>; ++}; ++ ++gpt1_ick: gpt1_ick@48004c10 { ++ #clock-cells = <0>; ++ compatible = "ti,omap3-interface-clock"; ++ clocks = <&wkup_l4_ick>; ++ reg = <0x48004c10 0x4>; ++ ti,enable-bit = <0>; ++}; ++ ++per_96m_fck: per_96m_fck { ++ #clock-cells = <0>; ++ compatible = "fixed-factor-clock"; ++ clocks = <&omap_96m_alwon_fck>; ++ clock-mult = <1>; ++ clock-div = <1>; ++}; ++ ++per_48m_fck: per_48m_fck { ++ #clock-cells = <0>; ++ compatible = "fixed-factor-clock"; ++ clocks = <&omap_48m_fck>; ++ clock-mult = <1>; ++ clock-div = <1>; ++}; ++ ++uart3_fck: uart3_fck@48005000 { ++ #clock-cells = <0>; ++ compatible = "ti,gate-clock"; ++ clocks = <&per_48m_fck>; ++ reg = <0x48005000 0x4>; ++ ti,enable-bit = <11>; ++}; ++ ++gpt2_mux_fck: gpt2_mux_fck@48005040 { ++ #clock-cells = <0>; ++ compatible = "mux-clock"; ++ clocks = <&omap_32k_fck>, <&sys_ck>; ++ reg = <0x48005040 0x4>; ++ bit-mask = <0x1>; ++}; ++ ++gpt2_fck: gpt2_fck@48005000 { ++ #clock-cells = <0>; ++ compatible = "gate-clock"; ++ clocks = <&gpt2_mux_fck>; ++ bit-shift = <3>; ++ reg = <0x48005000 0x4>; ++}; ++ ++gpt3_mux_fck: gpt3_mux_fck@48005040 { ++ #clock-cells = <0>; ++ compatible = "mux-clock"; ++ clocks = <&omap_32k_fck>, <&sys_ck>; ++ bit-shift = <1>; ++ reg = <0x48005040 0x4>; ++ bit-mask = <0x1>; ++}; ++ ++gpt3_fck: gpt3_fck@48005000 { ++ #clock-cells = <0>; ++ compatible = "gate-clock"; ++ clocks = <&gpt3_mux_fck>; ++ bit-shift = <4>; ++ reg = <0x48005000 0x4>; ++}; ++ ++gpt4_mux_fck: gpt4_mux_fck@48005040 { ++ #clock-cells = <0>; ++ compatible = "mux-clock"; ++ clocks = <&omap_32k_fck>, <&sys_ck>; ++ bit-shift = <2>; ++ reg = <0x48005040 0x4>; ++ bit-mask = <0x1>; ++}; ++ ++gpt4_fck: gpt4_fck@48005000 { ++ #clock-cells = <0>; ++ compatible = "gate-clock"; ++ clocks = <&gpt4_mux_fck>; ++ bit-shift = <5>; ++ reg = <0x48005000 0x4>; ++}; ++ ++gpt5_mux_fck: gpt5_mux_fck@48005040 { ++ #clock-cells = <0>; ++ compatible = "mux-clock"; ++ clocks = <&omap_32k_fck>, <&sys_ck>; ++ bit-shift = <3>; ++ reg = <0x48005040 0x4>; ++ bit-mask = <0x1>; ++}; ++ ++gpt5_fck: gpt5_fck@48005000 { ++ #clock-cells = <0>; ++ compatible = "gate-clock"; ++ clocks = <&gpt5_mux_fck>; ++ bit-shift = <6>; ++ reg = <0x48005000 0x4>; ++}; ++ ++gpt6_mux_fck: gpt6_mux_fck@48005040 { ++ #clock-cells = <0>; ++ compatible = "mux-clock"; ++ clocks = <&omap_32k_fck>, <&sys_ck>; ++ bit-shift = <4>; ++ reg = <0x48005040 0x4>; ++ bit-mask = <0x1>; ++}; ++ ++gpt6_fck: gpt6_fck@48005000 { ++ #clock-cells = <0>; ++ compatible = "gate-clock"; ++ clocks = <&gpt6_mux_fck>; ++ bit-shift = <7>; ++ reg = <0x48005000 0x4>; ++}; ++ ++gpt7_mux_fck: gpt7_mux_fck@48005040 { ++ #clock-cells = <0>; ++ compatible = "mux-clock"; ++ clocks = <&omap_32k_fck>, <&sys_ck>; ++ bit-shift = <5>; ++ reg = <0x48005040 0x4>; ++ bit-mask = <0x1>; ++}; ++ ++gpt7_fck: gpt7_fck@48005000 { ++ #clock-cells = <0>; ++ compatible = "gate-clock"; ++ clocks = <&gpt7_mux_fck>; ++ bit-shift = <8>; ++ reg = <0x48005000 0x4>; ++}; ++ ++gpt8_mux_fck: gpt8_mux_fck@48005040 { ++ #clock-cells = <0>; ++ compatible = "mux-clock"; ++ clocks = <&omap_32k_fck>, <&sys_ck>; ++ bit-shift = <6>; ++ reg = <0x48005040 0x4>; ++ bit-mask = <0x1>; ++}; ++ ++gpt8_fck: gpt8_fck@48005000 { ++ #clock-cells = <0>; ++ compatible = "gate-clock"; ++ clocks = <&gpt8_mux_fck>; ++ bit-shift = <9>; ++ reg = <0x48005000 0x4>; ++}; ++ ++gpt9_mux_fck: gpt9_mux_fck@48005040 { ++ #clock-cells = <0>; ++ compatible = "mux-clock"; ++ clocks = <&omap_32k_fck>, <&sys_ck>; ++ bit-shift = <7>; ++ reg = <0x48005040 0x4>; ++ bit-mask = <0x1>; ++}; ++ ++gpt9_fck: gpt9_fck@48005000 { ++ #clock-cells = <0>; ++ compatible = "gate-clock"; ++ clocks = <&gpt9_mux_fck>; ++ bit-shift = <10>; ++ reg = <0x48005000 0x4>; ++}; ++ ++per_32k_alwon_fck: per_32k_alwon_fck { ++ #clock-cells = <0>; ++ compatible = "fixed-factor-clock"; ++ clocks = <&omap_32k_fck>; ++ clock-mult = <1>; ++ clock-div = <1>; ++}; ++ ++gpio6_dbck: gpio6_dbck@48005000 { ++ #clock-cells = <0>; ++ compatible = "gate-clock"; ++ clocks = <&per_32k_alwon_fck>; ++ reg = <0x48005000 0x4>; ++ bit-shift = <17>; ++}; ++ ++gpio5_dbck: gpio5_dbck@48005000 { ++ #clock-cells = <0>; ++ compatible = "gate-clock"; ++ clocks = <&per_32k_alwon_fck>; ++ reg = <0x48005000 0x4>; ++ bit-shift = <16>; ++}; ++ ++gpio4_dbck: gpio4_dbck@48005000 { ++ #clock-cells = <0>; ++ compatible = "gate-clock"; ++ clocks = <&per_32k_alwon_fck>; ++ reg = <0x48005000 0x4>; ++ bit-shift = <15>; ++}; ++ ++gpio3_dbck: gpio3_dbck@48005000 { ++ #clock-cells = <0>; ++ compatible = "gate-clock"; ++ clocks = <&per_32k_alwon_fck>; ++ reg = <0x48005000 0x4>; ++ bit-shift = <14>; ++}; ++ ++gpio2_dbck: gpio2_dbck@48005000 { ++ #clock-cells = <0>; ++ compatible = "gate-clock"; ++ clocks = <&per_32k_alwon_fck>; ++ reg = <0x48005000 0x4>; ++ bit-shift = <13>; ++}; ++ ++wdt3_fck: wdt3_fck@48005000 { ++ #clock-cells = <0>; ++ compatible = "ti,gate-clock"; ++ clocks = <&per_32k_alwon_fck>; ++ reg = <0x48005000 0x4>; ++ ti,enable-bit = <12>; ++}; ++ ++per_l4_ick: per_l4_ick { ++ #clock-cells = <0>; ++ compatible = "fixed-factor-clock"; ++ clocks = <&l4_ick>; ++ clock-mult = <1>; ++ clock-div = <1>; ++}; ++ ++gpio6_ick: gpio6_ick@48005010 { ++ #clock-cells = <0>; ++ compatible = "ti,omap3-interface-clock"; ++ clocks = <&per_l4_ick>; ++ reg = <0x48005010 0x4>; ++ ti,enable-bit = <17>; ++}; ++ ++gpio5_ick: gpio5_ick@48005010 { ++ #clock-cells = <0>; ++ compatible = "ti,omap3-interface-clock"; ++ clocks = <&per_l4_ick>; ++ reg = <0x48005010 0x4>; ++ ti,enable-bit = <16>; ++}; ++ ++gpio4_ick: gpio4_ick@48005010 { ++ #clock-cells = <0>; ++ compatible = "ti,omap3-interface-clock"; ++ clocks = <&per_l4_ick>; ++ reg = <0x48005010 0x4>; ++ ti,enable-bit = <15>; ++}; ++ ++gpio3_ick: gpio3_ick@48005010 { ++ #clock-cells = <0>; ++ compatible = "ti,omap3-interface-clock"; ++ clocks = <&per_l4_ick>; ++ reg = <0x48005010 0x4>; ++ ti,enable-bit = <14>; ++}; ++ ++gpio2_ick: gpio2_ick@48005010 { ++ #clock-cells = <0>; ++ compatible = "ti,omap3-interface-clock"; ++ clocks = <&per_l4_ick>; ++ reg = <0x48005010 0x4>; ++ ti,enable-bit = <13>; ++}; ++ ++wdt3_ick: wdt3_ick@48005010 { ++ #clock-cells = <0>; ++ compatible = "ti,omap3-interface-clock"; ++ clocks = <&per_l4_ick>; ++ reg = <0x48005010 0x4>; ++ ti,enable-bit = <12>; ++}; ++ ++uart3_ick: uart3_ick@48005010 { ++ #clock-cells = <0>; ++ compatible = "ti,omap3-interface-clock"; ++ clocks = <&per_l4_ick>; ++ reg = <0x48005010 0x4>; ++ ti,enable-bit = <11>; ++}; ++ ++uart4_ick: uart4_ick@48005010 { ++ #clock-cells = <0>; ++ compatible = "ti,omap3-interface-clock"; ++ clocks = <&per_l4_ick>; ++ reg = <0x48005010 0x4>; ++ ti,enable-bit = <18>; ++}; ++ ++gpt9_ick: gpt9_ick@48005010 { ++ #clock-cells = <0>; ++ compatible = "ti,omap3-interface-clock"; ++ clocks = <&per_l4_ick>; ++ reg = <0x48005010 0x4>; ++ ti,enable-bit = <10>; ++}; ++ ++gpt8_ick: gpt8_ick@48005010 { ++ #clock-cells = <0>; ++ compatible = "ti,omap3-interface-clock"; ++ clocks = <&per_l4_ick>; ++ reg = <0x48005010 0x4>; ++ ti,enable-bit = <9>; ++}; ++ ++gpt7_ick: gpt7_ick@48005010 { ++ #clock-cells = <0>; ++ compatible = "ti,omap3-interface-clock"; ++ clocks = <&per_l4_ick>; ++ reg = <0x48005010 0x4>; ++ ti,enable-bit = <8>; ++}; ++ ++gpt6_ick: gpt6_ick@48005010 { ++ #clock-cells = <0>; ++ compatible = "ti,omap3-interface-clock"; ++ clocks = <&per_l4_ick>; ++ reg = <0x48005010 0x4>; ++ ti,enable-bit = <7>; ++}; ++ ++gpt5_ick: gpt5_ick@48005010 { ++ #clock-cells = <0>; ++ compatible = "ti,omap3-interface-clock"; ++ clocks = <&per_l4_ick>; ++ reg = <0x48005010 0x4>; ++ ti,enable-bit = <6>; ++}; ++ ++gpt4_ick: gpt4_ick@48005010 { ++ #clock-cells = <0>; ++ compatible = "ti,omap3-interface-clock"; ++ clocks = <&per_l4_ick>; ++ reg = <0x48005010 0x4>; ++ ti,enable-bit = <5>; ++}; ++ ++gpt3_ick: gpt3_ick@48005010 { ++ #clock-cells = <0>; ++ compatible = "ti,omap3-interface-clock"; ++ clocks = <&per_l4_ick>; ++ reg = <0x48005010 0x4>; ++ ti,enable-bit = <4>; ++}; ++ ++gpt2_ick: gpt2_ick@48005010 { ++ #clock-cells = <0>; ++ compatible = "ti,omap3-interface-clock"; ++ clocks = <&per_l4_ick>; ++ reg = <0x48005010 0x4>; ++ ti,enable-bit = <3>; ++}; ++ ++mcbsp2_ick: mcbsp2_ick@48005010 { ++ #clock-cells = <0>; ++ compatible = "ti,omap3-interface-clock"; ++ clocks = <&per_l4_ick>; ++ reg = <0x48005010 0x4>; ++ ti,enable-bit = <0>; ++}; ++ ++mcbsp3_ick: mcbsp3_ick@48005010 { ++ #clock-cells = <0>; ++ compatible = "ti,omap3-interface-clock"; ++ clocks = <&per_l4_ick>; ++ reg = <0x48005010 0x4>; ++ ti,enable-bit = <1>; ++}; ++ ++mcbsp4_ick: mcbsp4_ick@48005010 { ++ #clock-cells = <0>; ++ compatible = "ti,omap3-interface-clock"; ++ clocks = <&per_l4_ick>; ++ reg = <0x48005010 0x4>; ++ ti,enable-bit = <2>; ++}; ++ ++mcbsp2_mux_fck: mcbsp2_mux_fck@48002274 { ++ #clock-cells = <0>; ++ compatible = "mux-clock"; ++ clocks = <&per_96m_fck>, <&mcbsp_clks>; ++ bit-shift = <6>; ++ reg = <0x48002274 0x4>; ++ bit-mask = <0x1>; ++}; ++ ++mcbsp2_fck: mcbsp2_fck@48005000 { ++ #clock-cells = <0>; ++ compatible = "gate-clock"; ++ clocks = <&mcbsp2_mux_fck>; ++ bit-shift = <0>; ++ reg = <0x48005000 0x4>; ++}; ++ ++mcbsp3_mux_fck: mcbsp3_mux_fck@480022d8 { ++ #clock-cells = <0>; ++ compatible = "mux-clock"; ++ clocks = <&per_96m_fck>, <&mcbsp_clks>; ++ reg = <0x480022d8 0x4>; ++ bit-mask = <0x1>; ++}; ++ ++mcbsp3_fck: mcbsp3_fck@48005000 { ++ #clock-cells = <0>; ++ compatible = "gate-clock"; ++ clocks = <&mcbsp3_mux_fck>; ++ bit-shift = <1>; ++ reg = <0x48005000 0x4>; ++}; ++ ++mcbsp4_mux_fck: mcbsp4_mux_fck@480022d8 { ++ #clock-cells = <0>; ++ compatible = "mux-clock"; ++ clocks = <&per_96m_fck>, <&mcbsp_clks>; ++ bit-shift = <2>; ++ reg = <0x480022d8 0x4>; ++ bit-mask = <0x1>; ++}; ++ ++mcbsp4_fck: mcbsp4_fck@48005000 { ++ #clock-cells = <0>; ++ compatible = "gate-clock"; ++ clocks = <&mcbsp4_mux_fck>; ++ bit-shift = <2>; ++ reg = <0x48005000 0x4>; ++}; ++ ++emu_src_mux_ck: emu_src_mux_ck@48005140 { ++ #clock-cells = <0>; ++ compatible = "mux-clock"; ++ clocks = <&sys_ck>, <&emu_core_alwon_ck>, <&emu_per_alwon_ck>, <&emu_mpu_alwon_ck>; ++ reg = <0x48005140 0x4>; ++ bit-mask = <0x3>; ++}; ++ ++emu_src_ck: emu_src_ck { ++ #clock-cells = <0>; ++ compatible = "ti,clkdm-gate-clock"; ++ clocks = <&emu_src_mux_ck>; ++}; ++ ++pclk_fck: pclk_fck@48005140 { ++ #clock-cells = <0>; ++ compatible = "divider-clock"; ++ clocks = <&emu_src_ck>; ++ bit-shift = <8>; ++ reg = <0x48005140 0x4>; ++ bit-mask = <0x7>; ++ index-starts-at-one; ++}; ++ ++pclkx2_fck: pclkx2_fck@48005140 { ++ #clock-cells = <0>; ++ compatible = "divider-clock"; ++ clocks = <&emu_src_ck>; ++ bit-shift = <6>; ++ reg = <0x48005140 0x4>; ++ bit-mask = <0x3>; ++ index-starts-at-one; ++}; ++ ++atclk_fck: atclk_fck@48005140 { ++ #clock-cells = <0>; ++ compatible = "divider-clock"; ++ clocks = <&emu_src_ck>; ++ bit-shift = <4>; ++ reg = <0x48005140 0x4>; ++ bit-mask = <0x3>; ++ index-starts-at-one; ++}; ++ ++traceclk_src_fck: traceclk_src_fck@48005140 { ++ #clock-cells = <0>; ++ compatible = "mux-clock"; ++ clocks = <&sys_ck>, <&emu_core_alwon_ck>, <&emu_per_alwon_ck>, <&emu_mpu_alwon_ck>; ++ bit-shift = <2>; ++ reg = <0x48005140 0x4>; ++ bit-mask = <0x3>; ++}; ++ ++traceclk_fck: traceclk_fck@48005140 { ++ #clock-cells = <0>; ++ compatible = "divider-clock"; ++ clocks = <&traceclk_src_fck>; ++ bit-shift = <11>; ++ reg = <0x48005140 0x4>; ++ bit-mask = <0x7>; ++ index-starts-at-one; ++}; ++ ++secure_32k_fck: secure_32k_fck { ++ #clock-cells = <0>; ++ compatible = "fixed-clock"; ++ clock-frequency = <32768>; ++}; ++ ++gpt12_fck: gpt12_fck { ++ #clock-cells = <0>; ++ compatible = "fixed-factor-clock"; ++ clocks = <&secure_32k_fck>; ++ clock-mult = <1>; ++ clock-div = <1>; ++}; ++ ++wdt1_fck: wdt1_fck { ++ #clock-cells = <0>; ++ compatible = "fixed-factor-clock"; ++ clocks = <&secure_32k_fck>; ++ clock-mult = <1>; ++ clock-div = <1>; ++}; +--- /dev/null ++++ b/arch/arm/boot/dts/omap443x-clocks.dtsi +@@ -0,0 +1,17 @@ ++/* ++ * Device Tree Source for OMAP443x clock data ++ * ++ * Copyright (C) 2013 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. ++ */ ++ ++bandgap_fclk: bandgap_fclk@4a307888 { ++ #clock-cells = <0>; ++ compatible = "gate-clock"; ++ clocks = <&sys_32k_ck>; ++ bit-shift = <8>; ++ reg = <0x4a307888 0x4>; ++}; +--- a/arch/arm/boot/dts/omap443x.dtsi ++++ b/arch/arm/boot/dts/omap443x.dtsi +@@ -30,4 +30,24 @@ + 0x4a00232C 0x4>; + compatible = "ti,omap4430-bandgap"; + }; ++ ++ clocks { ++ #address-cells = <1>; ++ #size-cells = <1>; ++ ranges; ++ /include/ "omap44xx-clocks.dtsi" ++ /include/ "omap443x-clocks.dtsi" ++ }; ++ ++ clockdomains { ++ l3_init_clkdm: l3_init_clkdm { ++ compatible = "ti,clockdomain"; ++ clocks = <&dpll_usb_ck>; ++ }; ++ ++ emu_sys_clkdm: emu_sys_clkdm { ++ compatible = "ti,clockdomain"; ++ clocks = <&trace_clk_div_ck>; ++ }; ++ }; + }; +--- a/arch/arm/boot/dts/omap4460.dtsi ++++ b/arch/arm/boot/dts/omap4460.dtsi +@@ -38,4 +38,24 @@ + interrupts = <0 126 IRQ_TYPE_LEVEL_HIGH>; /* talert */ + gpios = <&gpio3 22 0>; /* tshut */ + }; ++ ++ clocks { ++ #address-cells = <1>; ++ #size-cells = <1>; ++ ranges; ++ /include/ "omap44xx-clocks.dtsi" ++ /include/ "omap446x-clocks.dtsi" ++ }; ++ ++ clockdomains { ++ l3_init_clkdm: l3_init_clkdm { ++ compatible = "ti,clockdomain"; ++ clocks = <&dpll_usb_ck>; ++ }; ++ ++ emu_sys_clkdm: emu_sys_clkdm { ++ compatible = "ti,clockdomain"; ++ clocks = <&trace_clk_div_ck>; ++ }; ++ }; + }; +--- /dev/null ++++ b/arch/arm/boot/dts/omap446x-clocks.dtsi +@@ -0,0 +1,27 @@ ++/* ++ * Device Tree Source for OMAP446x clock data ++ * ++ * Copyright (C) 2013 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. ++ */ ++ ++div_ts_ck: div_ts_ck@4a307888 { ++ #clock-cells = <0>; ++ compatible = "divider-clock"; ++ clocks = <&l4_wkup_clk_mux_ck>; ++ bit-shift = <24>; ++ reg = <0x4a307888 0x4>; ++ table = < 8 0 >, < 16 1 >, < 32 2 >; ++ bit-mask = <0x3>; ++}; ++ ++bandgap_ts_fclk: bandgap_ts_fclk@4a307888 { ++ #clock-cells = <0>; ++ compatible = "gate-clock"; ++ clocks = <&div_ts_ck>; ++ bit-shift = <8>; ++ reg = <0x4a307888 0x4>; ++}; +--- /dev/null ++++ b/arch/arm/boot/dts/omap44xx-clocks.dtsi +@@ -0,0 +1,1639 @@ ++/* ++ * Device Tree Source for OMAP4 clock data ++ * ++ * Copyright (C) 2013 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. ++ */ ++ ++extalt_clkin_ck: extalt_clkin_ck { ++ #clock-cells = <0>; ++ compatible = "fixed-clock"; ++ clock-frequency = <59000000>; ++}; ++ ++pad_clks_src_ck: pad_clks_src_ck { ++ #clock-cells = <0>; ++ compatible = "fixed-clock"; ++ clock-frequency = <12000000>; ++}; ++ ++pad_clks_ck: pad_clks_ck@4a004108 { ++ #clock-cells = <0>; ++ compatible = "gate-clock"; ++ clocks = <&pad_clks_src_ck>; ++ bit-shift = <8>; ++ reg = <0x4a004108 0x4>; ++}; ++ ++pad_slimbus_core_clks_ck: pad_slimbus_core_clks_ck { ++ #clock-cells = <0>; ++ compatible = "fixed-clock"; ++ clock-frequency = <12000000>; ++}; ++ ++secure_32k_clk_src_ck: secure_32k_clk_src_ck { ++ #clock-cells = <0>; ++ compatible = "fixed-clock"; ++ clock-frequency = <32768>; ++}; ++ ++slimbus_src_clk: slimbus_src_clk { ++ #clock-cells = <0>; ++ compatible = "fixed-clock"; ++ clock-frequency = <12000000>; ++}; ++ ++slimbus_clk: slimbus_clk@4a004108 { ++ #clock-cells = <0>; ++ compatible = "gate-clock"; ++ clocks = <&slimbus_src_clk>; ++ bit-shift = <10>; ++ reg = <0x4a004108 0x4>; ++}; ++ ++sys_32k_ck: sys_32k_ck { ++ #clock-cells = <0>; ++ compatible = "fixed-clock"; ++ clock-frequency = <32768>; ++}; ++ ++virt_12000000_ck: virt_12000000_ck { ++ #clock-cells = <0>; ++ compatible = "fixed-clock"; ++ clock-frequency = <12000000>; ++}; ++ ++virt_13000000_ck: virt_13000000_ck { ++ #clock-cells = <0>; ++ compatible = "fixed-clock"; ++ clock-frequency = <13000000>; ++}; ++ ++virt_16800000_ck: virt_16800000_ck { ++ #clock-cells = <0>; ++ compatible = "fixed-clock"; ++ clock-frequency = <16800000>; ++}; ++ ++virt_19200000_ck: virt_19200000_ck { ++ #clock-cells = <0>; ++ compatible = "fixed-clock"; ++ clock-frequency = <19200000>; ++}; ++ ++virt_26000000_ck: virt_26000000_ck { ++ #clock-cells = <0>; ++ compatible = "fixed-clock"; ++ clock-frequency = <26000000>; ++}; ++ ++virt_27000000_ck: virt_27000000_ck { ++ #clock-cells = <0>; ++ compatible = "fixed-clock"; ++ clock-frequency = <27000000>; ++}; ++ ++virt_38400000_ck: virt_38400000_ck { ++ #clock-cells = <0>; ++ compatible = "fixed-clock"; ++ clock-frequency = <38400000>; ++}; ++ ++sys_clkin_ck: sys_clkin_ck@4a306110 { ++ #clock-cells = <0>; ++ compatible = "mux-clock"; ++ clocks = <&virt_12000000_ck>, <&virt_13000000_ck>, <&virt_16800000_ck>, <&virt_19200000_ck>, <&virt_26000000_ck>, <&virt_27000000_ck>, <&virt_38400000_ck>; ++ reg = <0x4a306110 0x4>; ++ bit-mask = <0x7>; ++ index-starts-at-one; ++}; ++ ++tie_low_clock_ck: tie_low_clock_ck { ++ #clock-cells = <0>; ++ compatible = "fixed-clock"; ++ clock-frequency = <0>; ++}; ++ ++utmi_phy_clkout_ck: utmi_phy_clkout_ck { ++ #clock-cells = <0>; ++ compatible = "fixed-clock"; ++ clock-frequency = <60000000>; ++}; ++ ++xclk60mhsp1_ck: xclk60mhsp1_ck { ++ #clock-cells = <0>; ++ compatible = "fixed-clock"; ++ clock-frequency = <60000000>; ++}; ++ ++xclk60mhsp2_ck: xclk60mhsp2_ck { ++ #clock-cells = <0>; ++ compatible = "fixed-clock"; ++ clock-frequency = <60000000>; ++}; ++ ++xclk60motg_ck: xclk60motg_ck { ++ #clock-cells = <0>; ++ compatible = "fixed-clock"; ++ clock-frequency = <60000000>; ++}; ++ ++abe_dpll_bypass_clk_mux_ck: abe_dpll_bypass_clk_mux_ck@4a306108 { ++ #clock-cells = <0>; ++ compatible = "mux-clock"; ++ clocks = <&sys_clkin_ck>, <&sys_32k_ck>; ++ bit-shift = <24>; ++ reg = <0x4a306108 0x4>; ++ bit-mask = <0x1>; ++}; ++ ++abe_dpll_refclk_mux_ck: abe_dpll_refclk_mux_ck@4a30610c { ++ #clock-cells = <0>; ++ compatible = "mux-clock"; ++ clocks = <&sys_clkin_ck>, <&sys_32k_ck>; ++ reg = <0x4a30610c 0x4>; ++ bit-mask = <0x1>; ++}; ++ ++dpll_abe_ck: dpll_abe_ck@4a0041e0 { ++ #clock-cells = <0>; ++ compatible = "ti,omap4-dpll-m4xen-clock"; ++ clocks = <&abe_dpll_refclk_mux_ck>, <&abe_dpll_bypass_clk_mux_ck>; ++ reg = <0x4a0041e0 0x4>, <0x4a0041e4 0x4>, <0x4a0041e8 0x4>, <0x4a0041ec 0x4>; ++ reg-names = "control", "idlest", "autoidle", "mult-div1"; ++}; ++ ++dpll_abe_x2_ck: dpll_abe_x2_ck@4a0041f0 { ++ #clock-cells = <0>; ++ compatible = "ti,omap4-dpll-x2-clock"; ++ clocks = <&dpll_abe_ck>; ++ reg = <0x4a0041f0 0x4>; ++}; ++ ++dpll_abe_m2x2_ck: dpll_abe_m2x2_ck@4a0041f0 { ++ #clock-cells = <0>; ++ compatible = "ti,divider-clock"; ++ clocks = <&dpll_abe_x2_ck>; ++ ti,autoidle-shift = <8>; ++ reg = <0x4a0041f0 0x4>; ++ bit-mask = <0x1f>; ++ index-starts-at-one; ++ ti,autoidle-low; ++}; ++ ++abe_24m_fclk: abe_24m_fclk { ++ #clock-cells = <0>; ++ compatible = "fixed-factor-clock"; ++ clocks = <&dpll_abe_m2x2_ck>; ++ clock-mult = <1>; ++ clock-div = <8>; ++}; ++ ++abe_clk: abe_clk@4a004108 { ++ #clock-cells = <0>; ++ compatible = "divider-clock"; ++ clocks = <&dpll_abe_m2x2_ck>; ++ reg = <0x4a004108 0x4>; ++ bit-mask = <0x3>; ++ index-power-of-two; ++}; ++ ++aess_fclk: aess_fclk@4a004528 { ++ #clock-cells = <0>; ++ compatible = "divider-clock"; ++ clocks = <&abe_clk>; ++ bit-shift = <24>; ++ reg = <0x4a004528 0x4>; ++ bit-mask = <0x1>; ++}; ++ ++dpll_abe_m3x2_ck: dpll_abe_m3x2_ck@4a0041f4 { ++ #clock-cells = <0>; ++ compatible = "ti,divider-clock"; ++ clocks = <&dpll_abe_x2_ck>; ++ ti,autoidle-shift = <8>; ++ reg = <0x4a0041f4 0x4>; ++ bit-mask = <0x1f>; ++ index-starts-at-one; ++ ti,autoidle-low; ++}; ++ ++core_hsd_byp_clk_mux_ck: core_hsd_byp_clk_mux_ck@4a00412c { ++ #clock-cells = <0>; ++ compatible = "mux-clock"; ++ clocks = <&sys_clkin_ck>, <&dpll_abe_m3x2_ck>; ++ bit-shift = <23>; ++ reg = <0x4a00412c 0x4>; ++ bit-mask = <0x1>; ++}; ++ ++dpll_core_ck: dpll_core_ck@4a004120 { ++ #clock-cells = <0>; ++ compatible = "ti,omap4-dpll-core-clock"; ++ clocks = <&sys_clkin_ck>, <&core_hsd_byp_clk_mux_ck>; ++ reg = <0x4a004120 0x4>, <0x4a004124 0x4>, <0x4a004128 0x4>, <0x4a00412c 0x4>; ++ reg-names = "control", "idlest", "autoidle", "mult-div1"; ++}; ++ ++dpll_core_x2_ck: dpll_core_x2_ck { ++ #clock-cells = <0>; ++ compatible = "ti,omap4-dpll-x2-clock"; ++ clocks = <&dpll_core_ck>; ++}; ++ ++dpll_core_m6x2_ck: dpll_core_m6x2_ck@4a004140 { ++ #clock-cells = <0>; ++ compatible = "ti,divider-clock"; ++ clocks = <&dpll_core_x2_ck>; ++ ti,autoidle-shift = <8>; ++ reg = <0x4a004140 0x4>; ++ bit-mask = <0x1f>; ++ index-starts-at-one; ++ ti,autoidle-low; ++}; ++ ++dbgclk_mux_ck: dbgclk_mux_ck { ++ #clock-cells = <0>; ++ compatible = "fixed-factor-clock"; ++ clocks = <&sys_clkin_ck>; ++ clock-mult = <1>; ++ clock-div = <1>; ++}; ++ ++dpll_core_m2_ck: dpll_core_m2_ck@4a004130 { ++ #clock-cells = <0>; ++ compatible = "ti,divider-clock"; ++ clocks = <&dpll_core_ck>; ++ ti,autoidle-shift = <8>; ++ reg = <0x4a004130 0x4>; ++ bit-mask = <0x1f>; ++ index-starts-at-one; ++ ti,autoidle-low; ++}; ++ ++ddrphy_ck: ddrphy_ck { ++ #clock-cells = <0>; ++ compatible = "fixed-factor-clock"; ++ clocks = <&dpll_core_m2_ck>; ++ clock-mult = <1>; ++ clock-div = <2>; ++}; ++ ++dpll_core_m5x2_ck: dpll_core_m5x2_ck@4a00413c { ++ #clock-cells = <0>; ++ compatible = "ti,divider-clock"; ++ clocks = <&dpll_core_x2_ck>; ++ ti,autoidle-shift = <8>; ++ reg = <0x4a00413c 0x4>; ++ bit-mask = <0x1f>; ++ index-starts-at-one; ++ ti,autoidle-low; ++}; ++ ++div_core_ck: div_core_ck@4a004100 { ++ #clock-cells = <0>; ++ compatible = "divider-clock"; ++ clocks = <&dpll_core_m5x2_ck>; ++ reg = <0x4a004100 0x4>; ++ bit-mask = <0x1>; ++}; ++ ++div_iva_hs_clk: div_iva_hs_clk@4a0041dc { ++ #clock-cells = <0>; ++ compatible = "divider-clock"; ++ clocks = <&dpll_core_m5x2_ck>; ++ reg = <0x4a0041dc 0x4>; ++ bit-mask = <0x3>; ++ index-power-of-two; ++}; ++ ++div_mpu_hs_clk: div_mpu_hs_clk@4a00419c { ++ #clock-cells = <0>; ++ compatible = "divider-clock"; ++ clocks = <&dpll_core_m5x2_ck>; ++ reg = <0x4a00419c 0x4>; ++ bit-mask = <0x3>; ++ index-power-of-two; ++}; ++ ++dpll_core_m4x2_ck: dpll_core_m4x2_ck@4a004138 { ++ #clock-cells = <0>; ++ compatible = "ti,divider-clock"; ++ clocks = <&dpll_core_x2_ck>; ++ ti,autoidle-shift = <8>; ++ reg = <0x4a004138 0x4>; ++ bit-mask = <0x1f>; ++ index-starts-at-one; ++ ti,autoidle-low; ++}; ++ ++dll_clk_div_ck: dll_clk_div_ck { ++ #clock-cells = <0>; ++ compatible = "fixed-factor-clock"; ++ clocks = <&dpll_core_m4x2_ck>; ++ clock-mult = <1>; ++ clock-div = <2>; ++}; ++ ++dpll_abe_m2_ck: dpll_abe_m2_ck@4a0041f0 { ++ #clock-cells = <0>; ++ compatible = "divider-clock"; ++ clocks = <&dpll_abe_ck>; ++ reg = <0x4a0041f0 0x4>; ++ bit-mask = <0x1f>; ++ index-starts-at-one; ++}; ++ ++dpll_core_m3x2_div_ck: dpll_core_m3x2_div_ck@4a004134 { ++ #clock-cells = <0>; ++ compatible = "divider-clock"; ++ clocks = <&dpll_core_x2_ck>; ++ reg = <0x4a004134 0x4>; ++ bit-mask = <0x1f>; ++ index-starts-at-one; ++}; ++ ++dpll_core_m3x2_ck: dpll_core_m3x2_ck@4a004134 { ++ #clock-cells = <0>; ++ compatible = "gate-clock"; ++ clocks = <&dpll_core_m3x2_div_ck>; ++ bit-shift = <8>; ++ reg = <0x4a004134 0x4>; ++}; ++ ++dpll_core_m7x2_ck: dpll_core_m7x2_ck@4a004144 { ++ #clock-cells = <0>; ++ compatible = "ti,divider-clock"; ++ clocks = <&dpll_core_x2_ck>; ++ ti,autoidle-shift = <8>; ++ reg = <0x4a004144 0x4>; ++ bit-mask = <0x1f>; ++ index-starts-at-one; ++ ti,autoidle-low; ++}; ++ ++iva_hsd_byp_clk_mux_ck: iva_hsd_byp_clk_mux_ck@4a0041ac { ++ #clock-cells = <0>; ++ compatible = "mux-clock"; ++ clocks = <&sys_clkin_ck>, <&div_iva_hs_clk>; ++ bit-shift = <23>; ++ reg = <0x4a0041ac 0x4>; ++ bit-mask = <0x1>; ++}; ++ ++dpll_iva_ck: dpll_iva_ck@4a0041a0 { ++ #clock-cells = <0>; ++ compatible = "ti,omap4-dpll-clock"; ++ clocks = <&sys_clkin_ck>, <&iva_hsd_byp_clk_mux_ck>; ++ reg = <0x4a0041a0 0x4>, <0x4a0041a4 0x4>, <0x4a0041a8 0x4>, <0x4a0041ac 0x4>; ++ reg-names = "control", "idlest", "autoidle", "mult-div1"; ++}; ++ ++dpll_iva_x2_ck: dpll_iva_x2_ck { ++ #clock-cells = <0>; ++ compatible = "ti,omap4-dpll-x2-clock"; ++ clocks = <&dpll_iva_ck>; ++}; ++ ++dpll_iva_m4x2_ck: dpll_iva_m4x2_ck@4a0041b8 { ++ #clock-cells = <0>; ++ compatible = "ti,divider-clock"; ++ clocks = <&dpll_iva_x2_ck>; ++ ti,autoidle-shift = <8>; ++ reg = <0x4a0041b8 0x4>; ++ bit-mask = <0x1f>; ++ index-starts-at-one; ++ ti,autoidle-low; ++}; ++ ++dpll_iva_m5x2_ck: dpll_iva_m5x2_ck@4a0041bc { ++ #clock-cells = <0>; ++ compatible = "ti,divider-clock"; ++ clocks = <&dpll_iva_x2_ck>; ++ ti,autoidle-shift = <8>; ++ reg = <0x4a0041bc 0x4>; ++ bit-mask = <0x1f>; ++ index-starts-at-one; ++ ti,autoidle-low; ++}; ++ ++dpll_mpu_ck: dpll_mpu_ck@4a004160 { ++ #clock-cells = <0>; ++ compatible = "ti,omap4-dpll-clock"; ++ clocks = <&sys_clkin_ck>, <&div_mpu_hs_clk>; ++ reg = <0x4a004160 0x4>, <0x4a004164 0x4>, <0x4a004168 0x4>, <0x4a00416c 0x4>; ++ reg-names = "control", "idlest", "autoidle", "mult-div1"; ++}; ++ ++dpll_mpu_m2_ck: dpll_mpu_m2_ck@4a004170 { ++ #clock-cells = <0>; ++ compatible = "ti,divider-clock"; ++ clocks = <&dpll_mpu_ck>; ++ ti,autoidle-shift = <8>; ++ reg = <0x4a004170 0x4>; ++ bit-mask = <0x1f>; ++ index-starts-at-one; ++ ti,autoidle-low; ++}; ++ ++per_hs_clk_div_ck: per_hs_clk_div_ck { ++ #clock-cells = <0>; ++ compatible = "fixed-factor-clock"; ++ clocks = <&dpll_abe_m3x2_ck>; ++ clock-mult = <1>; ++ clock-div = <2>; ++}; ++ ++per_hsd_byp_clk_mux_ck: per_hsd_byp_clk_mux_ck@4a00814c { ++ #clock-cells = <0>; ++ compatible = "mux-clock"; ++ clocks = <&sys_clkin_ck>, <&per_hs_clk_div_ck>; ++ bit-shift = <23>; ++ reg = <0x4a00814c 0x4>; ++ bit-mask = <0x1>; ++}; ++ ++dpll_per_ck: dpll_per_ck@4a008140 { ++ #clock-cells = <0>; ++ compatible = "ti,omap4-dpll-clock"; ++ clocks = <&sys_clkin_ck>, <&per_hsd_byp_clk_mux_ck>; ++ reg = <0x4a008140 0x4>, <0x4a008144 0x4>, <0x4a008148 0x4>, <0x4a00814c 0x4>; ++ reg-names = "control", "idlest", "autoidle", "mult-div1"; ++}; ++ ++dpll_per_m2_ck: dpll_per_m2_ck@4a008150 { ++ #clock-cells = <0>; ++ compatible = "divider-clock"; ++ clocks = <&dpll_per_ck>; ++ reg = <0x4a008150 0x4>; ++ bit-mask = <0x1f>; ++ index-starts-at-one; ++}; ++ ++dpll_per_x2_ck: dpll_per_x2_ck@4a008150 { ++ #clock-cells = <0>; ++ compatible = "ti,omap4-dpll-x2-clock"; ++ clocks = <&dpll_per_ck>; ++ reg = <0x4a008150 0x4>; ++}; ++ ++dpll_per_m2x2_ck: dpll_per_m2x2_ck@4a008150 { ++ #clock-cells = <0>; ++ compatible = "ti,divider-clock"; ++ clocks = <&dpll_per_x2_ck>; ++ ti,autoidle-shift = <8>; ++ reg = <0x4a008150 0x4>; ++ bit-mask = <0x1f>; ++ index-starts-at-one; ++ ti,autoidle-low; ++}; ++ ++dpll_per_m3x2_div_ck: dpll_per_m3x2_div_ck@4a008154 { ++ #clock-cells = <0>; ++ compatible = "divider-clock"; ++ clocks = <&dpll_per_x2_ck>; ++ reg = <0x4a008154 0x4>; ++ bit-mask = <0x1f>; ++ index-starts-at-one; ++}; ++ ++dpll_per_m3x2_ck: dpll_per_m3x2_ck@4a008154 { ++ #clock-cells = <0>; ++ compatible = "gate-clock"; ++ clocks = <&dpll_per_m3x2_div_ck>; ++ bit-shift = <8>; ++ reg = <0x4a008154 0x4>; ++}; ++ ++dpll_per_m4x2_ck: dpll_per_m4x2_ck@4a008158 { ++ #clock-cells = <0>; ++ compatible = "ti,divider-clock"; ++ clocks = <&dpll_per_x2_ck>; ++ ti,autoidle-shift = <8>; ++ reg = <0x4a008158 0x4>; ++ bit-mask = <0x1f>; ++ index-starts-at-one; ++ ti,autoidle-low; ++}; ++ ++dpll_per_m5x2_ck: dpll_per_m5x2_ck@4a00815c { ++ #clock-cells = <0>; ++ compatible = "ti,divider-clock"; ++ clocks = <&dpll_per_x2_ck>; ++ ti,autoidle-shift = <8>; ++ reg = <0x4a00815c 0x4>; ++ bit-mask = <0x1f>; ++ index-starts-at-one; ++ ti,autoidle-low; ++}; ++ ++dpll_per_m6x2_ck: dpll_per_m6x2_ck@4a008160 { ++ #clock-cells = <0>; ++ compatible = "ti,divider-clock"; ++ clocks = <&dpll_per_x2_ck>; ++ ti,autoidle-shift = <8>; ++ reg = <0x4a008160 0x4>; ++ bit-mask = <0x1f>; ++ index-starts-at-one; ++ ti,autoidle-low; ++}; ++ ++dpll_per_m7x2_ck: dpll_per_m7x2_ck@4a008164 { ++ #clock-cells = <0>; ++ compatible = "ti,divider-clock"; ++ clocks = <&dpll_per_x2_ck>; ++ ti,autoidle-shift = <8>; ++ reg = <0x4a008164 0x4>; ++ bit-mask = <0x1f>; ++ index-starts-at-one; ++ ti,autoidle-low; ++}; ++ ++usb_hs_clk_div_ck: usb_hs_clk_div_ck { ++ #clock-cells = <0>; ++ compatible = "fixed-factor-clock"; ++ clocks = <&dpll_abe_m3x2_ck>; ++ clock-mult = <1>; ++ clock-div = <3>; ++}; ++ ++dpll_usb_ck: dpll_usb_ck@4a008180 { ++ #clock-cells = <0>; ++ compatible = "ti,omap4-dpll-j-type-clock"; ++ clocks = <&sys_clkin_ck>, <&usb_hs_clk_div_ck>; ++ reg = <0x4a008180 0x4>, <0x4a008184 0x4>, <0x4a008188 0x4>, <0x4a00818c 0x4>; ++ reg-names = "control", "idlest", "autoidle", "mult-div1"; ++}; ++ ++dpll_usb_clkdcoldo_ck: dpll_usb_clkdcoldo_ck@4a0081b4 { ++ #clock-cells = <0>; ++ compatible = "ti,fixed-factor-clock"; ++ clocks = <&dpll_usb_ck>; ++ ti,autoidle-shift = <8>; ++ clock-div = <1>; ++ reg = <0x4a0081b4 0x4>; ++ clock-mult = <1>; ++ ti,autoidle-low; ++}; ++ ++dpll_usb_m2_ck: dpll_usb_m2_ck@4a008190 { ++ #clock-cells = <0>; ++ compatible = "ti,divider-clock"; ++ clocks = <&dpll_usb_ck>; ++ ti,autoidle-shift = <8>; ++ reg = <0x4a008190 0x4>; ++ bit-mask = <0x7f>; ++ index-starts-at-one; ++ ti,autoidle-low; ++}; ++ ++ducati_clk_mux_ck: ducati_clk_mux_ck@4a008100 { ++ #clock-cells = <0>; ++ compatible = "mux-clock"; ++ clocks = <&div_core_ck>, <&dpll_per_m6x2_ck>; ++ reg = <0x4a008100 0x4>; ++ bit-mask = <0x1>; ++}; ++ ++func_12m_fclk: func_12m_fclk { ++ #clock-cells = <0>; ++ compatible = "fixed-factor-clock"; ++ clocks = <&dpll_per_m2x2_ck>; ++ clock-mult = <1>; ++ clock-div = <16>; ++}; ++ ++func_24m_clk: func_24m_clk { ++ #clock-cells = <0>; ++ compatible = "fixed-factor-clock"; ++ clocks = <&dpll_per_m2_ck>; ++ clock-mult = <1>; ++ clock-div = <4>; ++}; ++ ++func_24mc_fclk: func_24mc_fclk { ++ #clock-cells = <0>; ++ compatible = "fixed-factor-clock"; ++ clocks = <&dpll_per_m2x2_ck>; ++ clock-mult = <1>; ++ clock-div = <8>; ++}; ++ ++func_48m_fclk: func_48m_fclk@4a008108 { ++ #clock-cells = <0>; ++ compatible = "divider-clock"; ++ clocks = <&dpll_per_m2x2_ck>; ++ reg = <0x4a008108 0x4>; ++ table = < 4 0 >, < 8 1 >; ++ bit-mask = <0x1>; ++}; ++ ++func_48mc_fclk: func_48mc_fclk { ++ #clock-cells = <0>; ++ compatible = "fixed-factor-clock"; ++ clocks = <&dpll_per_m2x2_ck>; ++ clock-mult = <1>; ++ clock-div = <4>; ++}; ++ ++func_64m_fclk: func_64m_fclk@4a008108 { ++ #clock-cells = <0>; ++ compatible = "divider-clock"; ++ clocks = <&dpll_per_m4x2_ck>; ++ reg = <0x4a008108 0x4>; ++ table = < 2 0 >, < 4 1 >; ++ bit-mask = <0x1>; ++}; ++ ++func_96m_fclk: func_96m_fclk@4a008108 { ++ #clock-cells = <0>; ++ compatible = "divider-clock"; ++ clocks = <&dpll_per_m2x2_ck>; ++ reg = <0x4a008108 0x4>; ++ table = < 2 0 >, < 4 1 >; ++ bit-mask = <0x1>; ++}; ++ ++init_60m_fclk: init_60m_fclk@4a008104 { ++ #clock-cells = <0>; ++ compatible = "divider-clock"; ++ clocks = <&dpll_usb_m2_ck>; ++ reg = <0x4a008104 0x4>; ++ table = < 1 0 >, < 8 1 >; ++ bit-mask = <0x1>; ++}; ++ ++l3_div_ck: l3_div_ck@4a004100 { ++ #clock-cells = <0>; ++ compatible = "divider-clock"; ++ clocks = <&div_core_ck>; ++ bit-shift = <4>; ++ reg = <0x4a004100 0x4>; ++ bit-mask = <0x1>; ++}; ++ ++l4_div_ck: l4_div_ck@4a004100 { ++ #clock-cells = <0>; ++ compatible = "divider-clock"; ++ clocks = <&l3_div_ck>; ++ bit-shift = <8>; ++ reg = <0x4a004100 0x4>; ++ bit-mask = <0x1>; ++}; ++ ++lp_clk_div_ck: lp_clk_div_ck { ++ #clock-cells = <0>; ++ compatible = "fixed-factor-clock"; ++ clocks = <&dpll_abe_m2x2_ck>; ++ clock-mult = <1>; ++ clock-div = <16>; ++}; ++ ++l4_wkup_clk_mux_ck: l4_wkup_clk_mux_ck@4a306108 { ++ #clock-cells = <0>; ++ compatible = "mux-clock"; ++ clocks = <&sys_clkin_ck>, <&lp_clk_div_ck>; ++ reg = <0x4a306108 0x4>; ++ bit-mask = <0x1>; ++}; ++ ++mpu_periphclk: mpu_periphclk { ++ #clock-cells = <0>; ++ compatible = "fixed-factor-clock"; ++ clocks = <&dpll_mpu_ck>; ++ clock-mult = <1>; ++ clock-div = <2>; ++}; ++ ++ocp_abe_iclk: ocp_abe_iclk@4a004528 { ++ #clock-cells = <0>; ++ compatible = "divider-clock"; ++ clocks = <&aess_fclk>; ++ bit-shift = <24>; ++ reg = <0x4a004528 0x4>; ++ table = < 2 0 >, < 1 1 >; ++ bit-mask = <0x1>; ++}; ++ ++per_abe_24m_fclk: per_abe_24m_fclk { ++ #clock-cells = <0>; ++ compatible = "fixed-factor-clock"; ++ clocks = <&dpll_abe_m2_ck>; ++ clock-mult = <1>; ++ clock-div = <4>; ++}; ++ ++per_abe_nc_fclk: per_abe_nc_fclk@4a008108 { ++ #clock-cells = <0>; ++ compatible = "divider-clock"; ++ clocks = <&dpll_abe_m2_ck>; ++ reg = <0x4a008108 0x4>; ++ bit-mask = <0x1>; ++}; ++ ++syc_clk_div_ck: syc_clk_div_ck@4a306100 { ++ #clock-cells = <0>; ++ compatible = "divider-clock"; ++ clocks = <&sys_clkin_ck>; ++ reg = <0x4a306100 0x4>; ++ bit-mask = <0x1>; ++}; ++ ++aes1_fck: aes1_fck@4a0095a0 { ++ #clock-cells = <0>; ++ compatible = "gate-clock"; ++ clocks = <&l3_div_ck>; ++ bit-shift = <1>; ++ reg = <0x4a0095a0 0x4>; ++}; ++ ++aes2_fck: aes2_fck@4a0095a8 { ++ #clock-cells = <0>; ++ compatible = "gate-clock"; ++ clocks = <&l3_div_ck>; ++ bit-shift = <1>; ++ reg = <0x4a0095a8 0x4>; ++}; ++ ++dmic_sync_mux_ck: dmic_sync_mux_ck@4a004538 { ++ #clock-cells = <0>; ++ compatible = "mux-clock"; ++ clocks = <&abe_24m_fclk>, <&syc_clk_div_ck>, <&func_24m_clk>; ++ bit-shift = <25>; ++ reg = <0x4a004538 0x4>; ++ bit-mask = <0x1>; ++}; ++ ++func_dmic_abe_gfclk: func_dmic_abe_gfclk@4a004538 { ++ #clock-cells = <0>; ++ compatible = "mux-clock"; ++ clocks = <&dmic_sync_mux_ck>, <&pad_clks_ck>, <&slimbus_clk>; ++ bit-shift = <24>; ++ reg = <0x4a004538 0x4>; ++ bit-mask = <0x3>; ++}; ++ ++dss_sys_clk: dss_sys_clk@4a009120 { ++ #clock-cells = <0>; ++ compatible = "gate-clock"; ++ clocks = <&syc_clk_div_ck>; ++ bit-shift = <10>; ++ reg = <0x4a009120 0x4>; ++}; ++ ++dss_tv_clk: dss_tv_clk@4a009120 { ++ #clock-cells = <0>; ++ compatible = "gate-clock"; ++ clocks = <&extalt_clkin_ck>; ++ bit-shift = <11>; ++ reg = <0x4a009120 0x4>; ++}; ++ ++dss_dss_clk: dss_dss_clk@4a009120 { ++ #clock-cells = <0>; ++ compatible = "gate-clock"; ++ clocks = <&dpll_per_m5x2_ck>; ++ bit-shift = <8>; ++ reg = <0x4a009120 0x4>; ++}; ++ ++dss_48mhz_clk: dss_48mhz_clk@4a009120 { ++ #clock-cells = <0>; ++ compatible = "gate-clock"; ++ clocks = <&func_48mc_fclk>; ++ bit-shift = <9>; ++ reg = <0x4a009120 0x4>; ++}; ++ ++dss_fck: dss_fck@4a009120 { ++ #clock-cells = <0>; ++ compatible = "gate-clock"; ++ clocks = <&l3_div_ck>; ++ bit-shift = <1>; ++ reg = <0x4a009120 0x4>; ++}; ++ ++fdif_fck: fdif_fck@4a009028 { ++ #clock-cells = <0>; ++ compatible = "divider-clock"; ++ clocks = <&dpll_per_m4x2_ck>; ++ bit-shift = <24>; ++ reg = <0x4a009028 0x4>; ++ bit-mask = <0x3>; ++ index-power-of-two; ++}; ++ ++gpio1_dbclk: gpio1_dbclk@4a307838 { ++ #clock-cells = <0>; ++ compatible = "gate-clock"; ++ clocks = <&sys_32k_ck>; ++ bit-shift = <8>; ++ reg = <0x4a307838 0x4>; ++}; ++ ++gpio2_dbclk: gpio2_dbclk@4a009460 { ++ #clock-cells = <0>; ++ compatible = "gate-clock"; ++ clocks = <&sys_32k_ck>; ++ bit-shift = <8>; ++ reg = <0x4a009460 0x4>; ++}; ++ ++gpio3_dbclk: gpio3_dbclk@4a009468 { ++ #clock-cells = <0>; ++ compatible = "gate-clock"; ++ clocks = <&sys_32k_ck>; ++ bit-shift = <8>; ++ reg = <0x4a009468 0x4>; ++}; ++ ++gpio4_dbclk: gpio4_dbclk@4a009470 { ++ #clock-cells = <0>; ++ compatible = "gate-clock"; ++ clocks = <&sys_32k_ck>; ++ bit-shift = <8>; ++ reg = <0x4a009470 0x4>; ++}; ++ ++gpio5_dbclk: gpio5_dbclk@4a009478 { ++ #clock-cells = <0>; ++ compatible = "gate-clock"; ++ clocks = <&sys_32k_ck>; ++ bit-shift = <8>; ++ reg = <0x4a009478 0x4>; ++}; ++ ++gpio6_dbclk: gpio6_dbclk@4a009480 { ++ #clock-cells = <0>; ++ compatible = "gate-clock"; ++ clocks = <&sys_32k_ck>; ++ bit-shift = <8>; ++ reg = <0x4a009480 0x4>; ++}; ++ ++sgx_clk_mux: sgx_clk_mux@4a009220 { ++ #clock-cells = <0>; ++ compatible = "mux-clock"; ++ clocks = <&dpll_core_m7x2_ck>, <&dpll_per_m7x2_ck>; ++ bit-shift = <24>; ++ reg = <0x4a009220 0x4>; ++ bit-mask = <0x1>; ++}; ++ ++hsi_fck: hsi_fck@4a009338 { ++ #clock-cells = <0>; ++ compatible = "divider-clock"; ++ clocks = <&dpll_per_m2x2_ck>; ++ bit-shift = <24>; ++ reg = <0x4a009338 0x4>; ++ bit-mask = <0x3>; ++ index-power-of-two; ++}; ++ ++iss_ctrlclk: iss_ctrlclk@4a009020 { ++ #clock-cells = <0>; ++ compatible = "gate-clock"; ++ clocks = <&func_96m_fclk>; ++ bit-shift = <8>; ++ reg = <0x4a009020 0x4>; ++}; ++ ++mcasp_sync_mux_ck: mcasp_sync_mux_ck@4a004540 { ++ #clock-cells = <0>; ++ compatible = "mux-clock"; ++ clocks = <&abe_24m_fclk>, <&syc_clk_div_ck>, <&func_24m_clk>; ++ bit-shift = <25>; ++ reg = <0x4a004540 0x4>; ++ bit-mask = <0x1>; ++}; ++ ++func_mcasp_abe_gfclk: func_mcasp_abe_gfclk@4a004540 { ++ #clock-cells = <0>; ++ compatible = "mux-clock"; ++ clocks = <&mcasp_sync_mux_ck>, <&pad_clks_ck>, <&slimbus_clk>; ++ bit-shift = <24>; ++ reg = <0x4a004540 0x4>; ++ bit-mask = <0x3>; ++}; ++ ++mcbsp1_sync_mux_ck: mcbsp1_sync_mux_ck@4a004548 { ++ #clock-cells = <0>; ++ compatible = "mux-clock"; ++ clocks = <&abe_24m_fclk>, <&syc_clk_div_ck>, <&func_24m_clk>; ++ bit-shift = <25>; ++ reg = <0x4a004548 0x4>; ++ bit-mask = <0x1>; ++}; ++ ++func_mcbsp1_gfclk: func_mcbsp1_gfclk@4a004548 { ++ #clock-cells = <0>; ++ compatible = "mux-clock"; ++ clocks = <&mcbsp1_sync_mux_ck>, <&pad_clks_ck>, <&slimbus_clk>; ++ bit-shift = <24>; ++ reg = <0x4a004548 0x4>; ++ bit-mask = <0x3>; ++}; ++ ++mcbsp2_sync_mux_ck: mcbsp2_sync_mux_ck@4a004550 { ++ #clock-cells = <0>; ++ compatible = "mux-clock"; ++ clocks = <&abe_24m_fclk>, <&syc_clk_div_ck>, <&func_24m_clk>; ++ bit-shift = <25>; ++ reg = <0x4a004550 0x4>; ++ bit-mask = <0x1>; ++}; ++ ++func_mcbsp2_gfclk: func_mcbsp2_gfclk@4a004550 { ++ #clock-cells = <0>; ++ compatible = "mux-clock"; ++ clocks = <&mcbsp2_sync_mux_ck>, <&pad_clks_ck>, <&slimbus_clk>; ++ bit-shift = <24>; ++ reg = <0x4a004550 0x4>; ++ bit-mask = <0x3>; ++}; ++ ++mcbsp3_sync_mux_ck: mcbsp3_sync_mux_ck@4a004558 { ++ #clock-cells = <0>; ++ compatible = "mux-clock"; ++ clocks = <&abe_24m_fclk>, <&syc_clk_div_ck>, <&func_24m_clk>; ++ bit-shift = <25>; ++ reg = <0x4a004558 0x4>; ++ bit-mask = <0x1>; ++}; ++ ++func_mcbsp3_gfclk: func_mcbsp3_gfclk@4a004558 { ++ #clock-cells = <0>; ++ compatible = "mux-clock"; ++ clocks = <&mcbsp3_sync_mux_ck>, <&pad_clks_ck>, <&slimbus_clk>; ++ bit-shift = <24>; ++ reg = <0x4a004558 0x4>; ++ bit-mask = <0x3>; ++}; ++ ++mcbsp4_sync_mux_ck: mcbsp4_sync_mux_ck@4a0094e0 { ++ #clock-cells = <0>; ++ compatible = "mux-clock"; ++ clocks = <&func_96m_fclk>, <&per_abe_nc_fclk>; ++ bit-shift = <25>; ++ reg = <0x4a0094e0 0x4>; ++ bit-mask = <0x1>; ++}; ++ ++per_mcbsp4_gfclk: per_mcbsp4_gfclk@4a0094e0 { ++ #clock-cells = <0>; ++ compatible = "mux-clock"; ++ clocks = <&mcbsp4_sync_mux_ck>, <&pad_clks_ck>; ++ bit-shift = <24>; ++ reg = <0x4a0094e0 0x4>; ++ bit-mask = <0x1>; ++}; ++ ++hsmmc1_fclk: hsmmc1_fclk@4a009328 { ++ #clock-cells = <0>; ++ compatible = "mux-clock"; ++ clocks = <&func_64m_fclk>, <&func_96m_fclk>; ++ bit-shift = <24>; ++ reg = <0x4a009328 0x4>; ++ bit-mask = <0x1>; ++}; ++ ++hsmmc2_fclk: hsmmc2_fclk@4a009330 { ++ #clock-cells = <0>; ++ compatible = "mux-clock"; ++ clocks = <&func_64m_fclk>, <&func_96m_fclk>; ++ bit-shift = <24>; ++ reg = <0x4a009330 0x4>; ++ bit-mask = <0x1>; ++}; ++ ++ocp2scp_usb_phy_phy_48m: ocp2scp_usb_phy_phy_48m@4a0093e0 { ++ #clock-cells = <0>; ++ compatible = "gate-clock"; ++ clocks = <&func_48m_fclk>; ++ bit-shift = <8>; ++ reg = <0x4a0093e0 0x4>; ++}; ++ ++sha2md5_fck: sha2md5_fck@4a0095c8 { ++ #clock-cells = <0>; ++ compatible = "gate-clock"; ++ clocks = <&l3_div_ck>; ++ bit-shift = <1>; ++ reg = <0x4a0095c8 0x4>; ++}; ++ ++slimbus1_fclk_1: slimbus1_fclk_1@4a004560 { ++ #clock-cells = <0>; ++ compatible = "gate-clock"; ++ clocks = <&func_24m_clk>; ++ bit-shift = <9>; ++ reg = <0x4a004560 0x4>; ++}; ++ ++slimbus1_fclk_0: slimbus1_fclk_0@4a004560 { ++ #clock-cells = <0>; ++ compatible = "gate-clock"; ++ clocks = <&abe_24m_fclk>; ++ bit-shift = <8>; ++ reg = <0x4a004560 0x4>; ++}; ++ ++slimbus1_fclk_2: slimbus1_fclk_2@4a004560 { ++ #clock-cells = <0>; ++ compatible = "gate-clock"; ++ clocks = <&pad_clks_ck>; ++ bit-shift = <10>; ++ reg = <0x4a004560 0x4>; ++}; ++ ++slimbus1_slimbus_clk: slimbus1_slimbus_clk@4a004560 { ++ #clock-cells = <0>; ++ compatible = "gate-clock"; ++ clocks = <&slimbus_clk>; ++ bit-shift = <11>; ++ reg = <0x4a004560 0x4>; ++}; ++ ++slimbus2_fclk_1: slimbus2_fclk_1@4a009538 { ++ #clock-cells = <0>; ++ compatible = "gate-clock"; ++ clocks = <&per_abe_24m_fclk>; ++ bit-shift = <9>; ++ reg = <0x4a009538 0x4>; ++}; ++ ++slimbus2_fclk_0: slimbus2_fclk_0@4a009538 { ++ #clock-cells = <0>; ++ compatible = "gate-clock"; ++ clocks = <&func_24mc_fclk>; ++ bit-shift = <8>; ++ reg = <0x4a009538 0x4>; ++}; ++ ++slimbus2_slimbus_clk: slimbus2_slimbus_clk@4a009538 { ++ #clock-cells = <0>; ++ compatible = "gate-clock"; ++ clocks = <&pad_slimbus_core_clks_ck>; ++ bit-shift = <10>; ++ reg = <0x4a009538 0x4>; ++}; ++ ++smartreflex_core_fck: smartreflex_core_fck@4a008638 { ++ #clock-cells = <0>; ++ compatible = "gate-clock"; ++ clocks = <&l4_wkup_clk_mux_ck>; ++ bit-shift = <1>; ++ reg = <0x4a008638 0x4>; ++}; ++ ++smartreflex_iva_fck: smartreflex_iva_fck@4a008630 { ++ #clock-cells = <0>; ++ compatible = "gate-clock"; ++ clocks = <&l4_wkup_clk_mux_ck>; ++ bit-shift = <1>; ++ reg = <0x4a008630 0x4>; ++}; ++ ++smartreflex_mpu_fck: smartreflex_mpu_fck@4a008628 { ++ #clock-cells = <0>; ++ compatible = "gate-clock"; ++ clocks = <&l4_wkup_clk_mux_ck>; ++ bit-shift = <1>; ++ reg = <0x4a008628 0x4>; ++}; ++ ++dmt1_clk_mux: dmt1_clk_mux@4a307840 { ++ #clock-cells = <0>; ++ compatible = "mux-clock"; ++ clocks = <&sys_clkin_ck>, <&sys_32k_ck>; ++ bit-shift = <24>; ++ reg = <0x4a307840 0x4>; ++ bit-mask = <0x1>; ++}; ++ ++cm2_dm10_mux: cm2_dm10_mux@4a009428 { ++ #clock-cells = <0>; ++ compatible = "mux-clock"; ++ clocks = <&sys_clkin_ck>, <&sys_32k_ck>; ++ bit-shift = <24>; ++ reg = <0x4a009428 0x4>; ++ bit-mask = <0x1>; ++}; ++ ++cm2_dm11_mux: cm2_dm11_mux@4a009430 { ++ #clock-cells = <0>; ++ compatible = "mux-clock"; ++ clocks = <&sys_clkin_ck>, <&sys_32k_ck>; ++ bit-shift = <24>; ++ reg = <0x4a009430 0x4>; ++ bit-mask = <0x1>; ++}; ++ ++cm2_dm2_mux: cm2_dm2_mux@4a009438 { ++ #clock-cells = <0>; ++ compatible = "mux-clock"; ++ clocks = <&sys_clkin_ck>, <&sys_32k_ck>; ++ bit-shift = <24>; ++ reg = <0x4a009438 0x4>; ++ bit-mask = <0x1>; ++}; ++ ++cm2_dm3_mux: cm2_dm3_mux@4a009440 { ++ #clock-cells = <0>; ++ compatible = "mux-clock"; ++ clocks = <&sys_clkin_ck>, <&sys_32k_ck>; ++ bit-shift = <24>; ++ reg = <0x4a009440 0x4>; ++ bit-mask = <0x1>; ++}; ++ ++cm2_dm4_mux: cm2_dm4_mux@4a009448 { ++ #clock-cells = <0>; ++ compatible = "mux-clock"; ++ clocks = <&sys_clkin_ck>, <&sys_32k_ck>; ++ bit-shift = <24>; ++ reg = <0x4a009448 0x4>; ++ bit-mask = <0x1>; ++}; ++ ++timer5_sync_mux: timer5_sync_mux@4a004568 { ++ #clock-cells = <0>; ++ compatible = "mux-clock"; ++ clocks = <&syc_clk_div_ck>, <&sys_32k_ck>; ++ bit-shift = <24>; ++ reg = <0x4a004568 0x4>; ++ bit-mask = <0x1>; ++}; ++ ++timer6_sync_mux: timer6_sync_mux@4a004570 { ++ #clock-cells = <0>; ++ compatible = "mux-clock"; ++ clocks = <&syc_clk_div_ck>, <&sys_32k_ck>; ++ bit-shift = <24>; ++ reg = <0x4a004570 0x4>; ++ bit-mask = <0x1>; ++}; ++ ++timer7_sync_mux: timer7_sync_mux@4a004578 { ++ #clock-cells = <0>; ++ compatible = "mux-clock"; ++ clocks = <&syc_clk_div_ck>, <&sys_32k_ck>; ++ bit-shift = <24>; ++ reg = <0x4a004578 0x4>; ++ bit-mask = <0x1>; ++}; ++ ++timer8_sync_mux: timer8_sync_mux@4a004580 { ++ #clock-cells = <0>; ++ compatible = "mux-clock"; ++ clocks = <&syc_clk_div_ck>, <&sys_32k_ck>; ++ bit-shift = <24>; ++ reg = <0x4a004580 0x4>; ++ bit-mask = <0x1>; ++}; ++ ++cm2_dm9_mux: cm2_dm9_mux@4a009450 { ++ #clock-cells = <0>; ++ compatible = "mux-clock"; ++ clocks = <&sys_clkin_ck>, <&sys_32k_ck>; ++ bit-shift = <24>; ++ reg = <0x4a009450 0x4>; ++ bit-mask = <0x1>; ++}; ++ ++usb_host_fs_fck: usb_host_fs_fck@4a0093d0 { ++ #clock-cells = <0>; ++ compatible = "gate-clock"; ++ clocks = <&func_48mc_fclk>; ++ reg = <0x4a0093d0 0x4>; ++ bit-shift = <1>; ++}; ++ ++utmi_p1_gfclk: utmi_p1_gfclk@4a009358 { ++ #clock-cells = <0>; ++ compatible = "mux-clock"; ++ clocks = <&init_60m_fclk>, <&xclk60mhsp1_ck>; ++ bit-shift = <24>; ++ reg = <0x4a009358 0x4>; ++ bit-mask = <0x1>; ++}; ++ ++usb_host_hs_utmi_p1_clk: usb_host_hs_utmi_p1_clk@4a009358 { ++ #clock-cells = <0>; ++ compatible = "gate-clock"; ++ clocks = <&utmi_p1_gfclk>; ++ bit-shift = <8>; ++ reg = <0x4a009358 0x4>; ++}; ++ ++utmi_p2_gfclk: utmi_p2_gfclk@4a009358 { ++ #clock-cells = <0>; ++ compatible = "mux-clock"; ++ clocks = <&init_60m_fclk>, <&xclk60mhsp2_ck>; ++ bit-shift = <25>; ++ reg = <0x4a009358 0x4>; ++ bit-mask = <0x1>; ++}; ++ ++usb_host_hs_utmi_p2_clk: usb_host_hs_utmi_p2_clk@4a009358 { ++ #clock-cells = <0>; ++ compatible = "gate-clock"; ++ clocks = <&utmi_p2_gfclk>; ++ bit-shift = <9>; ++ reg = <0x4a009358 0x4>; ++}; ++ ++usb_host_hs_utmi_p3_clk: usb_host_hs_utmi_p3_clk@4a009358 { ++ #clock-cells = <0>; ++ compatible = "gate-clock"; ++ clocks = <&init_60m_fclk>; ++ bit-shift = <10>; ++ reg = <0x4a009358 0x4>; ++}; ++ ++usb_host_hs_hsic480m_p1_clk: usb_host_hs_hsic480m_p1_clk@4a009358 { ++ #clock-cells = <0>; ++ compatible = "gate-clock"; ++ clocks = <&dpll_usb_m2_ck>; ++ bit-shift = <13>; ++ reg = <0x4a009358 0x4>; ++}; ++ ++usb_host_hs_hsic60m_p1_clk: usb_host_hs_hsic60m_p1_clk@4a009358 { ++ #clock-cells = <0>; ++ compatible = "gate-clock"; ++ clocks = <&init_60m_fclk>; ++ bit-shift = <11>; ++ reg = <0x4a009358 0x4>; ++}; ++ ++usb_host_hs_hsic60m_p2_clk: usb_host_hs_hsic60m_p2_clk@4a009358 { ++ #clock-cells = <0>; ++ compatible = "gate-clock"; ++ clocks = <&init_60m_fclk>; ++ bit-shift = <12>; ++ reg = <0x4a009358 0x4>; ++}; ++ ++usb_host_hs_hsic480m_p2_clk: usb_host_hs_hsic480m_p2_clk@4a009358 { ++ #clock-cells = <0>; ++ compatible = "gate-clock"; ++ clocks = <&dpll_usb_m2_ck>; ++ bit-shift = <14>; ++ reg = <0x4a009358 0x4>; ++}; ++ ++usb_host_hs_func48mclk: usb_host_hs_func48mclk@4a009358 { ++ #clock-cells = <0>; ++ compatible = "gate-clock"; ++ clocks = <&func_48mc_fclk>; ++ bit-shift = <15>; ++ reg = <0x4a009358 0x4>; ++}; ++ ++usb_host_hs_fck: usb_host_hs_fck@4a009358 { ++ #clock-cells = <0>; ++ compatible = "gate-clock"; ++ clocks = <&init_60m_fclk>; ++ bit-shift = <1>; ++ reg = <0x4a009358 0x4>; ++}; ++ ++otg_60m_gfclk: otg_60m_gfclk@4a009360 { ++ #clock-cells = <0>; ++ compatible = "mux-clock"; ++ clocks = <&utmi_phy_clkout_ck>, <&xclk60motg_ck>; ++ bit-shift = <24>; ++ reg = <0x4a009360 0x4>; ++ bit-mask = <0x1>; ++}; ++ ++usb_otg_hs_xclk: usb_otg_hs_xclk@4a009360 { ++ #clock-cells = <0>; ++ compatible = "gate-clock"; ++ clocks = <&otg_60m_gfclk>; ++ bit-shift = <8>; ++ reg = <0x4a009360 0x4>; ++}; ++ ++usb_otg_hs_ick: usb_otg_hs_ick@4a009360 { ++ #clock-cells = <0>; ++ compatible = "gate-clock"; ++ clocks = <&l3_div_ck>; ++ bit-shift = <0>; ++ reg = <0x4a009360 0x4>; ++}; ++ ++usb_phy_cm_clk32k: usb_phy_cm_clk32k@4a008640 { ++ #clock-cells = <0>; ++ compatible = "gate-clock"; ++ clocks = <&sys_32k_ck>; ++ bit-shift = <8>; ++ reg = <0x4a008640 0x4>; ++}; ++ ++usb_tll_hs_usb_ch2_clk: usb_tll_hs_usb_ch2_clk@4a009368 { ++ #clock-cells = <0>; ++ compatible = "gate-clock"; ++ clocks = <&init_60m_fclk>; ++ bit-shift = <10>; ++ reg = <0x4a009368 0x4>; ++}; ++ ++usb_tll_hs_usb_ch0_clk: usb_tll_hs_usb_ch0_clk@4a009368 { ++ #clock-cells = <0>; ++ compatible = "gate-clock"; ++ clocks = <&init_60m_fclk>; ++ bit-shift = <8>; ++ reg = <0x4a009368 0x4>; ++}; ++ ++usb_tll_hs_usb_ch1_clk: usb_tll_hs_usb_ch1_clk@4a009368 { ++ #clock-cells = <0>; ++ compatible = "gate-clock"; ++ clocks = <&init_60m_fclk>; ++ bit-shift = <9>; ++ reg = <0x4a009368 0x4>; ++}; ++ ++usb_tll_hs_ick: usb_tll_hs_ick@4a009368 { ++ #clock-cells = <0>; ++ compatible = "gate-clock"; ++ clocks = <&l4_div_ck>; ++ bit-shift = <0>; ++ reg = <0x4a009368 0x4>; ++}; ++ ++usim_ck: usim_ck@4a307858 { ++ #clock-cells = <0>; ++ compatible = "divider-clock"; ++ clocks = <&dpll_per_m4x2_ck>; ++ bit-shift = <24>; ++ reg = <0x4a307858 0x4>; ++ table = < 14 0 >, < 18 1 >; ++ bit-mask = <0x1>; ++}; ++ ++usim_fclk: usim_fclk@4a307858 { ++ #clock-cells = <0>; ++ compatible = "gate-clock"; ++ clocks = <&usim_ck>; ++ bit-shift = <8>; ++ reg = <0x4a307858 0x4>; ++}; ++ ++pmd_stm_clock_mux_ck: pmd_stm_clock_mux_ck@4a307a20 { ++ #clock-cells = <0>; ++ compatible = "mux-clock"; ++ clocks = <&sys_clkin_ck>, <&dpll_core_m6x2_ck>, <&tie_low_clock_ck>; ++ bit-shift = <20>; ++ reg = <0x4a307a20 0x4>; ++ bit-mask = <0x3>; ++}; ++ ++pmd_trace_clk_mux_ck: pmd_trace_clk_mux_ck@4a307a20 { ++ #clock-cells = <0>; ++ compatible = "mux-clock"; ++ clocks = <&sys_clkin_ck>, <&dpll_core_m6x2_ck>, <&tie_low_clock_ck>; ++ bit-shift = <22>; ++ reg = <0x4a307a20 0x4>; ++ bit-mask = <0x3>; ++}; ++ ++stm_clk_div_ck: stm_clk_div_ck@4a307a20 { ++ #clock-cells = <0>; ++ compatible = "divider-clock"; ++ clocks = <&pmd_stm_clock_mux_ck>; ++ bit-shift = <27>; ++ reg = <0x4a307a20 0x4>; ++ bit-mask = <0x7>; ++ index-power-of-two; ++}; ++ ++trace_clk_div_div_ck: trace_clk_div_div_ck@4a307a20 { ++ #clock-cells = <0>; ++ compatible = "divider-clock"; ++ bit-shift = <24>; ++ reg = <0x4a307a20 0x4>; ++ bit-mask = <0x7>; ++ index-power-of-two; ++}; ++ ++trace_clk_div_ck: trace_clk_div_ck { ++ #clock-cells = <0>; ++ compatible = "ti,clkdm-gate-clock"; ++ clocks = <&trace_clk_div_div_ck>; ++}; ++ ++auxclk0_src_mux_ck: auxclk0_src_mux_ck@4a30a310 { ++ #clock-cells = <0>; ++ compatible = "mux-clock"; ++ clocks = <&sys_clkin_ck>, <&dpll_core_m3x2_ck>, <&dpll_per_m3x2_ck>; ++ bit-shift = <1>; ++ reg = <0x4a30a310 0x4>; ++ bit-mask = <0x3>; ++}; ++ ++auxclk0_src_ck: auxclk0_src_ck@4a30a310 { ++ #clock-cells = <0>; ++ compatible = "gate-clock"; ++ clocks = <&auxclk0_src_mux_ck>; ++ bit-shift = <8>; ++ reg = <0x4a30a310 0x4>; ++}; ++ ++auxclk0_ck: auxclk0_ck@4a30a310 { ++ #clock-cells = <0>; ++ compatible = "divider-clock"; ++ clocks = <&auxclk0_src_ck>; ++ bit-shift = <16>; ++ reg = <0x4a30a310 0x4>; ++ bit-mask = <0xf>; ++}; ++ ++auxclk1_src_mux_ck: auxclk1_src_mux_ck@4a30a314 { ++ #clock-cells = <0>; ++ compatible = "mux-clock"; ++ clocks = <&sys_clkin_ck>, <&dpll_core_m3x2_ck>, <&dpll_per_m3x2_ck>; ++ bit-shift = <1>; ++ reg = <0x4a30a314 0x4>; ++ bit-mask = <0x3>; ++}; ++ ++auxclk1_src_ck: auxclk1_src_ck@4a30a314 { ++ #clock-cells = <0>; ++ compatible = "gate-clock"; ++ clocks = <&auxclk1_src_mux_ck>; ++ bit-shift = <8>; ++ reg = <0x4a30a314 0x4>; ++}; ++ ++auxclk1_ck: auxclk1_ck@4a30a314 { ++ #clock-cells = <0>; ++ compatible = "divider-clock"; ++ clocks = <&auxclk1_src_ck>; ++ bit-shift = <16>; ++ reg = <0x4a30a314 0x4>; ++ bit-mask = <0xf>; ++}; ++ ++auxclk2_src_mux_ck: auxclk2_src_mux_ck@4a30a318 { ++ #clock-cells = <0>; ++ compatible = "mux-clock"; ++ clocks = <&sys_clkin_ck>, <&dpll_core_m3x2_ck>, <&dpll_per_m3x2_ck>; ++ bit-shift = <1>; ++ reg = <0x4a30a318 0x4>; ++ bit-mask = <0x3>; ++}; ++ ++auxclk2_src_ck: auxclk2_src_ck@4a30a318 { ++ #clock-cells = <0>; ++ compatible = "gate-clock"; ++ clocks = <&auxclk2_src_mux_ck>; ++ bit-shift = <8>; ++ reg = <0x4a30a318 0x4>; ++}; ++ ++auxclk2_ck: auxclk2_ck@4a30a318 { ++ #clock-cells = <0>; ++ compatible = "divider-clock"; ++ clocks = <&auxclk2_src_ck>; ++ bit-shift = <16>; ++ reg = <0x4a30a318 0x4>; ++ bit-mask = <0xf>; ++}; ++ ++auxclk3_src_mux_ck: auxclk3_src_mux_ck@4a30a31c { ++ #clock-cells = <0>; ++ compatible = "mux-clock"; ++ clocks = <&sys_clkin_ck>, <&dpll_core_m3x2_ck>, <&dpll_per_m3x2_ck>; ++ bit-shift = <1>; ++ reg = <0x4a30a31c 0x4>; ++ bit-mask = <0x3>; ++}; ++ ++auxclk3_src_ck: auxclk3_src_ck@4a30a31c { ++ #clock-cells = <0>; ++ compatible = "gate-clock"; ++ clocks = <&auxclk3_src_mux_ck>; ++ bit-shift = <8>; ++ reg = <0x4a30a31c 0x4>; ++}; ++ ++auxclk3_ck: auxclk3_ck@4a30a31c { ++ #clock-cells = <0>; ++ compatible = "divider-clock"; ++ clocks = <&auxclk3_src_ck>; ++ bit-shift = <16>; ++ reg = <0x4a30a31c 0x4>; ++ bit-mask = <0xf>; ++}; ++ ++auxclk4_src_mux_ck: auxclk4_src_mux_ck@4a30a320 { ++ #clock-cells = <0>; ++ compatible = "mux-clock"; ++ clocks = <&sys_clkin_ck>, <&dpll_core_m3x2_ck>, <&dpll_per_m3x2_ck>; ++ bit-shift = <1>; ++ reg = <0x4a30a320 0x4>; ++ bit-mask = <0x3>; ++}; ++ ++auxclk4_src_ck: auxclk4_src_ck@4a30a320 { ++ #clock-cells = <0>; ++ compatible = "gate-clock"; ++ clocks = <&auxclk4_src_mux_ck>; ++ bit-shift = <8>; ++ reg = <0x4a30a320 0x4>; ++}; ++ ++auxclk4_ck: auxclk4_ck@4a30a320 { ++ #clock-cells = <0>; ++ compatible = "divider-clock"; ++ clocks = <&auxclk4_src_ck>; ++ bit-shift = <16>; ++ reg = <0x4a30a320 0x4>; ++ bit-mask = <0xf>; ++}; ++ ++auxclk5_src_mux_ck: auxclk5_src_mux_ck@4a30a324 { ++ #clock-cells = <0>; ++ compatible = "mux-clock"; ++ clocks = <&sys_clkin_ck>, <&dpll_core_m3x2_ck>, <&dpll_per_m3x2_ck>; ++ bit-shift = <1>; ++ reg = <0x4a30a324 0x4>; ++ bit-mask = <0x3>; ++}; ++ ++auxclk5_src_ck: auxclk5_src_ck@4a30a324 { ++ #clock-cells = <0>; ++ compatible = "gate-clock"; ++ clocks = <&auxclk5_src_mux_ck>; ++ bit-shift = <8>; ++ reg = <0x4a30a324 0x4>; ++}; ++ ++auxclk5_ck: auxclk5_ck@4a30a324 { ++ #clock-cells = <0>; ++ compatible = "divider-clock"; ++ clocks = <&auxclk5_src_ck>; ++ bit-shift = <16>; ++ reg = <0x4a30a324 0x4>; ++ bit-mask = <0xf>; ++}; ++ ++auxclkreq0_ck: auxclkreq0_ck@4a30a210 { ++ #clock-cells = <0>; ++ compatible = "mux-clock"; ++ clocks = <&auxclk0_ck>, <&auxclk1_ck>, <&auxclk2_ck>, <&auxclk3_ck>, <&auxclk4_ck>, <&auxclk5_ck>; ++ bit-shift = <2>; ++ reg = <0x4a30a210 0x4>; ++ bit-mask = <0x7>; ++}; ++ ++auxclkreq1_ck: auxclkreq1_ck@4a30a214 { ++ #clock-cells = <0>; ++ compatible = "mux-clock"; ++ clocks = <&auxclk0_ck>, <&auxclk1_ck>, <&auxclk2_ck>, <&auxclk3_ck>, <&auxclk4_ck>, <&auxclk5_ck>; ++ bit-shift = <2>; ++ reg = <0x4a30a214 0x4>; ++ bit-mask = <0x7>; ++}; ++ ++auxclkreq2_ck: auxclkreq2_ck@4a30a218 { ++ #clock-cells = <0>; ++ compatible = "mux-clock"; ++ clocks = <&auxclk0_ck>, <&auxclk1_ck>, <&auxclk2_ck>, <&auxclk3_ck>, <&auxclk4_ck>, <&auxclk5_ck>; ++ bit-shift = <2>; ++ reg = <0x4a30a218 0x4>; ++ bit-mask = <0x7>; ++}; ++ ++auxclkreq3_ck: auxclkreq3_ck@4a30a21c { ++ #clock-cells = <0>; ++ compatible = "mux-clock"; ++ clocks = <&auxclk0_ck>, <&auxclk1_ck>, <&auxclk2_ck>, <&auxclk3_ck>, <&auxclk4_ck>, <&auxclk5_ck>; ++ bit-shift = <2>; ++ reg = <0x4a30a21c 0x4>; ++ bit-mask = <0x7>; ++}; ++ ++auxclkreq4_ck: auxclkreq4_ck@4a30a220 { ++ #clock-cells = <0>; ++ compatible = "mux-clock"; ++ clocks = <&auxclk0_ck>, <&auxclk1_ck>, <&auxclk2_ck>, <&auxclk3_ck>, <&auxclk4_ck>, <&auxclk5_ck>; ++ bit-shift = <2>; ++ reg = <0x4a30a220 0x4>; ++ bit-mask = <0x7>; ++}; ++ ++auxclkreq5_ck: auxclkreq5_ck@4a30a224 { ++ #clock-cells = <0>; ++ compatible = "mux-clock"; ++ clocks = <&auxclk0_ck>, <&auxclk1_ck>, <&auxclk2_ck>, <&auxclk3_ck>, <&auxclk4_ck>, <&auxclk5_ck>; ++ bit-shift = <2>; ++ reg = <0x4a30a224 0x4>; ++ bit-mask = <0x7>; ++}; +--- a/arch/arm/boot/dts/omap4.dtsi ++++ b/arch/arm/boot/dts/omap4.dtsi +@@ -17,6 +17,10 @@ + interrupt-parent = <&gic>; + + aliases { ++ i2c0 = &i2c1; ++ i2c1 = &i2c2; ++ i2c2 = &i2c3; ++ i2c3 = &i2c4; + serial0 = &uart1; + serial1 = &uart2; + serial2 = &uart3; +@@ -32,6 +36,11 @@ + device_type = "cpu"; + next-level-cache = <&L2>; + reg = <0x0>; ++ ++ clocks = <&dpll_mpu_ck>; ++ clock-names = "cpu"; ++ ++ clock-latency = <300000>; /* From omap-cpufreq driver */ + }; + cpu@1 { + compatible = "arm,cortex-a9"; +@@ -107,6 +116,8 @@ + compatible = "ti,omap-counter32k"; + reg = <0x4a304000 0x20>; + ti,hwmods = "counter_32k"; ++ clocks = <&sys_32k_ck>; ++ clock-names = "fck"; + }; + + omap4_pmx_core: pinmux@4a100040 { +@@ -136,6 +147,8 @@ + #dma-cells = <1>; + #dma-channels = <32>; + #dma-requests = <127>; ++ clocks = <&l3_div_ck>; ++ clock-names = "fck"; + }; + + gpio1: gpio@4a310000 { +@@ -143,6 +156,8 @@ + reg = <0x4a310000 0x200>; + interrupts = <GIC_SPI 29 IRQ_TYPE_LEVEL_HIGH>; + ti,hwmods = "gpio1"; ++ clocks = <&l4_wkup_clk_mux_ck>, <&gpio1_dbclk>; ++ clock-names = "fck", "dbclk"; + ti,gpio-always-on; + gpio-controller; + #gpio-cells = <2>; +@@ -155,6 +170,8 @@ + reg = <0x48055000 0x200>; + interrupts = <GIC_SPI 30 IRQ_TYPE_LEVEL_HIGH>; + ti,hwmods = "gpio2"; ++ clocks = <&l4_div_ck>, <&gpio2_dbclk>; ++ clock-names = "fck", "dbclk"; + gpio-controller; + #gpio-cells = <2>; + interrupt-controller; +@@ -166,6 +183,8 @@ + reg = <0x48057000 0x200>; + interrupts = <GIC_SPI 31 IRQ_TYPE_LEVEL_HIGH>; + ti,hwmods = "gpio3"; ++ clocks = <&l4_div_ck>, <&gpio3_dbclk>; ++ clock-names = "fck", "dbclk"; + gpio-controller; + #gpio-cells = <2>; + interrupt-controller; +@@ -177,6 +196,8 @@ + reg = <0x48059000 0x200>; + interrupts = <GIC_SPI 32 IRQ_TYPE_LEVEL_HIGH>; + ti,hwmods = "gpio4"; ++ clocks = <&l4_div_ck>, <&gpio4_dbclk>; ++ clock-names = "fck", "dbclk"; + gpio-controller; + #gpio-cells = <2>; + interrupt-controller; +@@ -188,6 +209,8 @@ + reg = <0x4805b000 0x200>; + interrupts = <GIC_SPI 33 IRQ_TYPE_LEVEL_HIGH>; + ti,hwmods = "gpio5"; ++ clocks = <&l4_div_ck>, <&gpio5_dbclk>; ++ clock-names = "fck", "dbclk"; + gpio-controller; + #gpio-cells = <2>; + interrupt-controller; +@@ -199,6 +222,8 @@ + reg = <0x4805d000 0x200>; + interrupts = <GIC_SPI 34 IRQ_TYPE_LEVEL_HIGH>; + ti,hwmods = "gpio6"; ++ clocks = <&l4_div_ck>, <&gpio6_dbclk>; ++ clock-names = "fck", "dbclk"; + gpio-controller; + #gpio-cells = <2>; + interrupt-controller; +@@ -214,6 +239,7 @@ + gpmc,num-cs = <8>; + gpmc,num-waitpins = <4>; + ti,hwmods = "gpmc"; ++ ti,no-idle; + }; + + uart1: serial@4806a000 { +@@ -221,6 +247,8 @@ + reg = <0x4806a000 0x100>; + interrupts = <GIC_SPI 72 IRQ_TYPE_LEVEL_HIGH>; + ti,hwmods = "uart1"; ++ clocks = <&func_48m_fclk>; ++ clock-names = "fck"; + clock-frequency = <48000000>; + }; + +@@ -229,6 +257,8 @@ + reg = <0x4806c000 0x100>; + interrupts = <GIC_SPI 73 IRQ_TYPE_LEVEL_HIGH>; + ti,hwmods = "uart2"; ++ clocks = <&func_48m_fclk>; ++ clock-names = "fck"; + clock-frequency = <48000000>; + }; + +@@ -237,6 +267,8 @@ + reg = <0x48020000 0x100>; + interrupts = <GIC_SPI 74 IRQ_TYPE_LEVEL_HIGH>; + ti,hwmods = "uart3"; ++ clocks = <&func_48m_fclk>; ++ clock-names = "fck"; + clock-frequency = <48000000>; + }; + +@@ -245,6 +277,8 @@ + reg = <0x4806e000 0x100>; + interrupts = <GIC_SPI 70 IRQ_TYPE_LEVEL_HIGH>; + ti,hwmods = "uart4"; ++ clocks = <&func_48m_fclk>; ++ clock-names = "fck"; + clock-frequency = <48000000>; + }; + +@@ -255,6 +289,8 @@ + #address-cells = <1>; + #size-cells = <0>; + ti,hwmods = "i2c1"; ++ clocks = <&func_96m_fclk>; ++ clock-names = "fck"; + }; + + i2c2: i2c@48072000 { +@@ -264,6 +300,8 @@ + #address-cells = <1>; + #size-cells = <0>; + ti,hwmods = "i2c2"; ++ clocks = <&func_96m_fclk>; ++ clock-names = "fck"; + }; + + i2c3: i2c@48060000 { +@@ -273,6 +311,8 @@ + #address-cells = <1>; + #size-cells = <0>; + ti,hwmods = "i2c3"; ++ clocks = <&func_96m_fclk>; ++ clock-names = "fck"; + }; + + i2c4: i2c@48350000 { +@@ -282,6 +322,8 @@ + #address-cells = <1>; + #size-cells = <0>; + ti,hwmods = "i2c4"; ++ clocks = <&func_96m_fclk>; ++ clock-names = "fck"; + }; + + mcspi1: spi@48098000 { +@@ -291,6 +333,8 @@ + #address-cells = <1>; + #size-cells = <0>; + ti,hwmods = "mcspi1"; ++ clocks = <&func_48m_fclk>; ++ clock-names = "fck"; + ti,spi-num-cs = <4>; + dmas = <&sdma 35>, + <&sdma 36>, +@@ -311,6 +355,8 @@ + #address-cells = <1>; + #size-cells = <0>; + ti,hwmods = "mcspi2"; ++ clocks = <&func_48m_fclk>; ++ clock-names = "fck"; + ti,spi-num-cs = <2>; + dmas = <&sdma 43>, + <&sdma 44>, +@@ -326,6 +372,8 @@ + #address-cells = <1>; + #size-cells = <0>; + ti,hwmods = "mcspi3"; ++ clocks = <&func_48m_fclk>; ++ clock-names = "fck"; + ti,spi-num-cs = <2>; + dmas = <&sdma 15>, <&sdma 16>; + dma-names = "tx0", "rx0"; +@@ -338,6 +386,8 @@ + #address-cells = <1>; + #size-cells = <0>; + ti,hwmods = "mcspi4"; ++ clocks = <&func_48m_fclk>; ++ clock-names = "fck"; + ti,spi-num-cs = <1>; + dmas = <&sdma 70>, <&sdma 71>; + dma-names = "tx0", "rx0"; +@@ -348,6 +398,8 @@ + reg = <0x4809c000 0x400>; + interrupts = <GIC_SPI 83 IRQ_TYPE_LEVEL_HIGH>; + ti,hwmods = "mmc1"; ++ clocks = <&hsmmc1_fclk>; ++ clock-names = "fck"; + ti,dual-volt; + ti,needs-special-reset; + dmas = <&sdma 61>, <&sdma 62>; +@@ -359,6 +411,8 @@ + reg = <0x480b4000 0x400>; + interrupts = <GIC_SPI 86 IRQ_TYPE_LEVEL_HIGH>; + ti,hwmods = "mmc2"; ++ clocks = <&hsmmc2_fclk>; ++ clock-names = "fck"; + ti,needs-special-reset; + dmas = <&sdma 47>, <&sdma 48>; + dma-names = "tx", "rx"; +@@ -369,6 +423,8 @@ + reg = <0x480ad000 0x400>; + interrupts = <GIC_SPI 94 IRQ_TYPE_LEVEL_HIGH>; + ti,hwmods = "mmc3"; ++ clocks = <&func_48m_fclk>; ++ clock-names = "fck"; + ti,needs-special-reset; + dmas = <&sdma 77>, <&sdma 78>; + dma-names = "tx", "rx"; +@@ -379,6 +435,8 @@ + reg = <0x480d1000 0x400>; + interrupts = <GIC_SPI 96 IRQ_TYPE_LEVEL_HIGH>; + ti,hwmods = "mmc4"; ++ clocks = <&func_48m_fclk>; ++ clock-names = "fck"; + ti,needs-special-reset; + dmas = <&sdma 57>, <&sdma 58>; + dma-names = "tx", "rx"; +@@ -389,16 +447,20 @@ + reg = <0x480d5000 0x400>; + interrupts = <GIC_SPI 59 IRQ_TYPE_LEVEL_HIGH>; + ti,hwmods = "mmc5"; ++ clocks = <&func_48m_fclk>; ++ clock-names = "fck"; + ti,needs-special-reset; + dmas = <&sdma 59>, <&sdma 60>; + dma-names = "tx", "rx"; + }; + + wdt2: wdt@4a314000 { +- compatible = "ti,omap4-wdt", "ti,omap3-wdt"; ++ compatible = "ti,omap4-wdt"; + reg = <0x4a314000 0x80>; + interrupts = <GIC_SPI 80 IRQ_TYPE_LEVEL_HIGH>; + ti,hwmods = "wd_timer2"; ++ clocks = <&sys_32k_ck>; ++ clock-names = "fck"; + }; + + mcpdm: mcpdm@40132000 { +@@ -408,6 +470,8 @@ + reg-names = "mpu", "dma"; + interrupts = <GIC_SPI 112 IRQ_TYPE_LEVEL_HIGH>; + ti,hwmods = "mcpdm"; ++ clocks = <&pad_clks_ck>; ++ clock-names = "fck"; + dmas = <&sdma 65>, + <&sdma 66>; + dma-names = "up_link", "dn_link"; +@@ -420,6 +484,8 @@ + reg-names = "mpu", "dma"; + interrupts = <GIC_SPI 114 IRQ_TYPE_LEVEL_HIGH>; + ti,hwmods = "dmic"; ++ clocks = <&func_dmic_abe_gfclk>; ++ clock-names = "fck"; + dmas = <&sdma 67>; + dma-names = "up_link"; + }; +@@ -433,6 +499,8 @@ + interrupt-names = "common"; + ti,buffer-size = <128>; + ti,hwmods = "mcbsp1"; ++ clocks = <&func_mcbsp1_gfclk>, <&pad_clks_ck>, <&mcbsp1_sync_mux_ck>; ++ clock-names = "fck", "pad_fck", "prcm_fck"; + dmas = <&sdma 33>, + <&sdma 34>; + dma-names = "tx", "rx"; +@@ -447,6 +515,8 @@ + interrupt-names = "common"; + ti,buffer-size = <128>; + ti,hwmods = "mcbsp2"; ++ clocks = <&func_mcbsp2_gfclk>, <&pad_clks_ck>, <&mcbsp2_sync_mux_ck>; ++ clock-names = "fck", "pad_fck", "prcm_fck"; + dmas = <&sdma 17>, + <&sdma 18>; + dma-names = "tx", "rx"; +@@ -461,6 +531,8 @@ + interrupt-names = "common"; + ti,buffer-size = <128>; + ti,hwmods = "mcbsp3"; ++ clocks = <&func_mcbsp3_gfclk>, <&pad_clks_ck>, <&mcbsp3_sync_mux_ck>; ++ clock-names = "fck", "pad_fck", "prcm_fck"; + dmas = <&sdma 19>, + <&sdma 20>; + dma-names = "tx", "rx"; +@@ -474,6 +546,8 @@ + interrupt-names = "common"; + ti,buffer-size = <128>; + ti,hwmods = "mcbsp4"; ++ clocks = <&per_mcbsp4_gfclk>, <&pad_clks_ck>, <&mcbsp4_sync_mux_ck>; ++ clock-names = "fck", "pad_fck", "prcm_fck"; + dmas = <&sdma 31>, + <&sdma 32>; + dma-names = "tx", "rx"; +@@ -485,6 +559,15 @@ + interrupts = <GIC_SPI 120 IRQ_TYPE_LEVEL_HIGH>; + reg-names = "mpu"; + ti,hwmods = "kbd"; ++ clocks = <&sys_32k_ck>; ++ clock-names = "fck"; ++ }; ++ ++ dmm: dmm@4e000000 { ++ compatible = "ti,omap4-dmm"; ++ reg = <0x4e000000 0x800>; ++ interrupts = <0 113 0x4>; ++ ti,hwmods = "dmm"; + }; + + emif1: emif@4c000000 { +@@ -492,6 +575,9 @@ + reg = <0x4c000000 0x100>; + interrupts = <GIC_SPI 110 IRQ_TYPE_LEVEL_HIGH>; + ti,hwmods = "emif1"; ++ ti,no-idle; ++ clocks = <&ddrphy_ck>; ++ clock-names = "fck"; + phy-type = <1>; + hw-caps-read-idle-ctrl; + hw-caps-ll-interface; +@@ -503,6 +589,9 @@ + reg = <0x4d000000 0x100>; + interrupts = <GIC_SPI 111 IRQ_TYPE_LEVEL_HIGH>; + ti,hwmods = "emif2"; ++ ti,no-idle; ++ clocks = <&ddrphy_ck>; ++ clock-names = "fck"; + phy-type = <1>; + hw-caps-read-idle-ctrl; + hw-caps-ll-interface; +@@ -516,18 +605,36 @@ + #size-cells = <1>; + ranges; + ti,hwmods = "ocp2scp_usb_phy"; ++ clocks = <&ocp2scp_usb_phy_phy_48m>; ++ clock-names = "fck"; + usb2_phy: usb2phy@4a0ad080 { + compatible = "ti,omap-usb2"; + reg = <0x4a0ad080 0x58>; +- ctrl-module = <&omap_control_usb>; ++ ctrl-module = <&omap_control_usb2phy>; ++ clocks = <&usb_phy_cm_clk32k>, <&ocp2scp_usb_phy_phy_48m>; ++ clock-names = "wkupclk", "refclk"; ++ #phy-cells = <0>; + }; + }; + ++ mailbox: mailbox@4a0f4000 { ++ compatible = "ti,omap4-mailbox"; ++ reg = <0x4a0f4000 0x200>; ++ interrupts = <GIC_SPI 26 IRQ_TYPE_LEVEL_HIGH>; ++ ti,hwmods = "mailbox"; ++ ti,mbox-num-users = <3>; ++ ti,mbox-num-fifos = <8>; ++ ti,mbox-names = "mbox-ipu", "mbox-dsp"; ++ ti,mbox-data = <0 1 0 0>, <3 2 0 0>; ++ }; ++ + timer1: timer@4a318000 { + compatible = "ti,omap3430-timer"; + reg = <0x4a318000 0x80>; + interrupts = <GIC_SPI 37 IRQ_TYPE_LEVEL_HIGH>; + ti,hwmods = "timer1"; ++ clocks = <&dmt1_clk_mux>; ++ clock-names = "fck"; + ti,timer-alwon; + }; + +@@ -536,6 +643,8 @@ + reg = <0x48032000 0x80>; + interrupts = <GIC_SPI 38 IRQ_TYPE_LEVEL_HIGH>; + ti,hwmods = "timer2"; ++ clocks = <&cm2_dm2_mux>; ++ clock-names = "fck"; + }; + + timer3: timer@48034000 { +@@ -543,6 +652,8 @@ + reg = <0x48034000 0x80>; + interrupts = <GIC_SPI 39 IRQ_TYPE_LEVEL_HIGH>; + ti,hwmods = "timer3"; ++ clocks = <&cm2_dm3_mux>; ++ clock-names = "fck"; + }; + + timer4: timer@48036000 { +@@ -550,6 +661,8 @@ + reg = <0x48036000 0x80>; + interrupts = <GIC_SPI 40 IRQ_TYPE_LEVEL_HIGH>; + ti,hwmods = "timer4"; ++ clocks = <&cm2_dm4_mux>; ++ clock-names = "fck"; + }; + + timer5: timer@40138000 { +@@ -558,6 +671,8 @@ + <0x49038000 0x80>; + interrupts = <GIC_SPI 41 IRQ_TYPE_LEVEL_HIGH>; + ti,hwmods = "timer5"; ++ clocks = <&timer5_sync_mux>; ++ clock-names = "fck"; + ti,timer-dsp; + }; + +@@ -567,6 +682,8 @@ + <0x4903a000 0x80>; + interrupts = <GIC_SPI 42 IRQ_TYPE_LEVEL_HIGH>; + ti,hwmods = "timer6"; ++ clocks = <&timer6_sync_mux>; ++ clock-names = "fck"; + ti,timer-dsp; + }; + +@@ -576,6 +693,8 @@ + <0x4903c000 0x80>; + interrupts = <GIC_SPI 43 IRQ_TYPE_LEVEL_HIGH>; + ti,hwmods = "timer7"; ++ clocks = <&timer7_sync_mux>; ++ clock-names = "fck"; + ti,timer-dsp; + }; + +@@ -585,6 +704,8 @@ + <0x4903e000 0x80>; + interrupts = <GIC_SPI 44 IRQ_TYPE_LEVEL_HIGH>; + ti,hwmods = "timer8"; ++ clocks = <&timer8_sync_mux>; ++ clock-names = "fck"; + ti,timer-pwm; + ti,timer-dsp; + }; +@@ -594,6 +715,8 @@ + reg = <0x4803e000 0x80>; + interrupts = <GIC_SPI 45 IRQ_TYPE_LEVEL_HIGH>; + ti,hwmods = "timer9"; ++ clocks = <&cm2_dm9_mux>; ++ clock-names = "fck"; + ti,timer-pwm; + }; + +@@ -602,6 +725,8 @@ + reg = <0x48086000 0x80>; + interrupts = <GIC_SPI 46 IRQ_TYPE_LEVEL_HIGH>; + ti,hwmods = "timer10"; ++ clocks = <&cm2_dm10_mux>; ++ clock-names = "fck"; + ti,timer-pwm; + }; + +@@ -610,6 +735,8 @@ + reg = <0x48088000 0x80>; + interrupts = <GIC_SPI 47 IRQ_TYPE_LEVEL_HIGH>; + ti,hwmods = "timer11"; ++ clocks = <&cm2_dm11_mux>; ++ clock-names = "fck"; + ti,timer-pwm; + }; + +@@ -618,12 +745,16 @@ + reg = <0x4a062000 0x1000>; + interrupts = <GIC_SPI 78 IRQ_TYPE_LEVEL_HIGH>; + ti,hwmods = "usb_tll_hs"; ++ clocks = <&usb_tll_hs_ick>; ++ clock-names = "fck"; + }; + + usbhshost: usbhshost@4a064000 { + compatible = "ti,usbhs-host"; + reg = <0x4a064000 0x800>; + ti,hwmods = "usb_host_hs"; ++ clocks = <&usb_host_hs_fck>; ++ clock-names = "fck"; + #address-cells = <1>; + #size-cells = <1>; + ranges; +@@ -643,12 +774,16 @@ + }; + }; + +- omap_control_usb: omap-control-usb@4a002300 { +- compatible = "ti,omap-control-usb"; +- reg = <0x4a002300 0x4>, +- <0x4a00233c 0x4>; +- reg-names = "control_dev_conf", "otghs_control"; +- ti,type = <1>; ++ omap_control_usb2phy: control-phy@4a002300 { ++ compatible = "ti,control-phy-usb2"; ++ reg = <0x4a002300 0x4>; ++ reg-names = "power"; ++ }; ++ ++ omap_control_usbotg: control-phy@4a00233c { ++ compatible = "ti,control-phy-otghs"; ++ reg = <0x4a00233c 0x4>; ++ reg-names = "otghs_control"; + }; + + usb_otg_hs: usb_otg_hs@4a0ab000 { +@@ -657,11 +792,98 @@ + interrupts = <GIC_SPI 92 IRQ_TYPE_LEVEL_HIGH>, <GIC_SPI 93 IRQ_TYPE_LEVEL_HIGH>; + interrupt-names = "mc", "dma"; + ti,hwmods = "usb_otg_hs"; ++ clocks = <&usb_otg_hs_ick>, <&usb_otg_hs_xclk>; ++ clock-names = "fck", "xclk"; + usb-phy = <&usb2_phy>; ++ phys = <&usb2_phy>; ++ phy-names = "usb2-phy"; + multipoint = <1>; + num-eps = <16>; + ram-bits = <12>; +- ti,has-mailbox; ++ ctrl-module = <&omap_control_usbotg>; ++ dr_mode = "peripheral"; ++ }; ++ ++ dss@58000000 { ++ compatible = "ti,omap4-dss", "simple-bus"; ++ reg = <0x58000000 0x80>; ++ ti,hwmods = "dss_core"; ++ #address-cells = <1>; ++ #size-cells = <1>; ++ ranges; ++ ++ dispc@58001000 { ++ compatible = "ti,omap4-dispc"; ++ reg = <0x58001000 0x1000>; ++ interrupts = <0 25 0x4>; ++ ti,hwmods = "dss_dispc"; ++ }; ++ ++ dpi: encoder@0 { ++ compatible = "ti,omap4-dpi"; ++ }; ++ ++ rfbi: encoder@58002000 { ++ compatible = "ti,omap4-rfbi"; ++ reg = <0x58002000 0x1000>; ++ ti,hwmods = "dss_rfbi"; ++ }; ++ ++ /* ++ * Accessing venc registers cause a crash on omap4, so ++ * this is disabled for now. ++ */ ++ /* ++ venc: encoder@58003000 { ++ compatible = "ti,omap4-venc"; ++ reg = <0x58003000 0x1000>; ++ ti,hwmods = "dss_venc"; ++ }; ++ */ ++ ++ dsi1: encoder@58004000 { ++ compatible = "ti,omap4-dsi"; ++ reg = <0x58004000 0x200>; ++ interrupts = <0 53 0x4>; ++ ti,hwmods = "dss_dsi1"; ++ }; ++ ++ dsi2: encoder@58005000 { ++ compatible = "ti,omap4-dsi"; ++ reg = <0x58005000 0x200>; ++ interrupts = <0 84 0x4>; ++ ti,hwmods = "dss_dsi2"; ++ }; ++ ++ hdmi: encoder@58006000 { ++ compatible = "ti,omap4-hdmi"; ++ reg = <0x58006000 0x200>, ++ <0x58006200 0x100>, ++ <0x58006300 0x100>, ++ <0x58006400 0x1000>; ++ reg-names = "hdmi_wp", "hdmi_pllctrl", ++ "hdmi_txphy", "hdmi_core"; ++ interrupts = <0 101 0x4>; ++ ti,hwmods = "dss_hdmi"; ++ }; ++ }; ++ ++ aes: aes@4b501000 { ++ compatible = "ti,omap4-aes"; ++ ti,hwmods = "aes"; ++ reg = <0x4b501000 0xa0>; ++ interrupts = <GIC_SPI 85 IRQ_TYPE_LEVEL_HIGH>; ++ dmas = <&sdma 111>, <&sdma 110>; ++ dma-names = "tx", "rx"; ++ }; ++ ++ des: des@480a5000 { ++ compatible = "ti,omap4-des"; ++ ti,hwmods = "des"; ++ reg = <0x480a5000 0xa0>; ++ interrupts = <GIC_SPI 82 IRQ_TYPE_LEVEL_HIGH>; ++ dmas = <&sdma 117>, <&sdma 116>; ++ dma-names = "tx", "rx"; + }; + }; + }; +--- a/arch/arm/boot/dts/omap4-panda-common.dtsi ++++ b/arch/arm/boot/dts/omap4-panda-common.dtsi +@@ -60,22 +60,6 @@ + "AFMR", "Line In"; + }; + +- /* +- * Temp hack: Need to be replaced with the proper gpio-controlled +- * reset driver as soon it will be merged. +- * http://thread.gmane.org/gmane.linux.drivers.devicetree/36830 +- */ +- /* HS USB Port 1 RESET */ +- hsusb1_reset: hsusb1_reset_reg { +- compatible = "regulator-fixed"; +- regulator-name = "hsusb1_reset"; +- regulator-min-microvolt = <3300000>; +- regulator-max-microvolt = <3300000>; +- gpio = <&gpio2 30 0>; /* gpio_62 */ +- startup-delay-us = <70000>; +- enable-active-high; +- }; +- + /* HS USB Port 1 Power */ + hsusb1_power: hsusb1_power_reg { + compatible = "regulator-fixed"; +@@ -97,14 +81,10 @@ + /* HS USB Host PHY on PORT 1 */ + hsusb1_phy: hsusb1_phy { + compatible = "usb-nop-xceiv"; +- reset-supply = <&hsusb1_reset>; ++ reset-gpios = <&gpio2 30 GPIO_ACTIVE_LOW>; /* gpio_62 */ + vcc-supply = <&hsusb1_power>; +- /** +- * FIXME: +- * put the right clock phandle here when available +- * clocks = <&auxclk3>; +- * clock-names = "main_clk"; +- */ ++ clocks = <&auxclk3_ck>; ++ clock-names = "main_clk"; + clock-frequency = <19200000>; + }; + +@@ -401,3 +381,51 @@ + &usbhsehci { + phys = <&hsusb1_phy>; + }; ++ ++&dsi1 { ++ vdds_dsi-supply = <&vcxio>; ++}; ++ ++&dsi2 { ++ vdds_dsi-supply = <&vcxio>; ++}; ++ ++&hdmi { ++ vdda_hdmi_dac-supply = <&vdac>; ++}; ++ ++/ { ++ aliases { ++ display0 = &dvi0; ++ display1 = &hdmi0; ++ }; ++ ++ tfp410: encoder@0 { ++ compatible = "ti,tfp410"; ++ video-source = <&dpi>; ++ data-lines = <24>; ++ gpios = <&gpio1 0 0>; /* 0, power-down */ ++ }; ++ ++ dvi0: connector@0 { ++ compatible = "ti,dvi_connector"; ++ video-source = <&tfp410>; ++ i2c-bus = <&i2c3>; ++ }; ++ ++ tpd12s015: encoder@1 { ++ compatible = "ti,tpd12s015"; ++ ++ video-source = <&hdmi>; ++ ++ gpios = <&gpio2 28 0>, /* 60, CT CP HPD */ ++ <&gpio2 9 0>, /* 41, LS OE */ ++ <&gpio2 31 0>; /* 63, HPD */ ++ }; ++ ++ hdmi0: connector@1 { ++ compatible = "ti,hdmi_connector"; ++ ++ video-source = <&tpd12s015>; ++ }; ++}; +--- a/arch/arm/boot/dts/omap4-sdp.dts ++++ b/arch/arm/boot/dts/omap4-sdp.dts +@@ -569,3 +569,73 @@ + mode = <3>; + power = <50>; + }; ++ ++&dsi1 { ++ vdds_dsi-supply = <&vcxio>; ++}; ++ ++&dsi2 { ++ vdds_dsi-supply = <&vcxio>; ++}; ++ ++&hdmi { ++ vdda_hdmi_dac-supply = <&vdac>; ++}; ++ ++/ { ++ aliases { ++ display0 = &lcd0; ++ display1 = &lcd1; ++ display2 = &hdmi0; ++ }; ++ ++ lcd0: display@0 { ++ compatible = "tpo,taal", "panel-dsi-cm"; ++ ++ video-source = <&dsi1>; ++ ++ lanes = < ++ 0 /* clk + */ ++ 1 /* clk - */ ++ 2 /* data1 + */ ++ 3 /* data1 - */ ++ 4 /* data2 + */ ++ 5 /* data2 - */ ++ >; ++ ++ gpios = <&gpio4 6 0>; /* 102, reset */ ++ }; ++ ++ lcd1: display@1 { ++ compatible = "tpo,taal", "panel-dsi-cm"; ++ ++ video-source = <&dsi2>; ++ ++ lanes = < ++ 0 /* clk + */ ++ 1 /* clk - */ ++ 2 /* data1 + */ ++ 3 /* data1 - */ ++ 4 /* data2 + */ ++ 5 /* data2 - */ ++ >; ++ ++ gpios = <&gpio4 8 0>; /* 104, reset */ ++ }; ++ ++ tpd12s015: encoder@0 { ++ compatible = "ti,tpd12s015"; ++ ++ video-source = <&hdmi>; ++ ++ gpios = <&gpio2 28 0>, /* 60, CT CP HPD */ ++ <&gpio2 9 0>, /* 41, LS OE */ ++ <&gpio2 31 0>; /* 63, HPD */ ++ }; ++ ++ hdmi0: connector@0 { ++ compatible = "ti,hdmi_connector"; ++ ++ video-source = <&tpd12s015>; ++ }; ++}; +--- /dev/null ++++ b/arch/arm/boot/dts/omap54xx-clocks.dtsi +@@ -0,0 +1,1400 @@ ++/* ++ * Device Tree Source for OMAP5 clock data ++ * ++ * Copyright (C) 2013 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. ++ */ ++ ++pad_clks_src_ck: pad_clks_src_ck { ++ #clock-cells = <0>; ++ compatible = "fixed-clock"; ++ clock-frequency = <12000000>; ++}; ++ ++pad_clks_ck: pad_clks_ck@4a004108 { ++ #clock-cells = <0>; ++ compatible = "gate-clock"; ++ clocks = <&pad_clks_src_ck>; ++ bit-shift = <8>; ++ reg = <0x4a004108 0x4>; ++}; ++ ++secure_32k_clk_src_ck: secure_32k_clk_src_ck { ++ #clock-cells = <0>; ++ compatible = "fixed-clock"; ++ clock-frequency = <32768>; ++}; ++ ++slimbus_src_clk: slimbus_src_clk { ++ #clock-cells = <0>; ++ compatible = "fixed-clock"; ++ clock-frequency = <12000000>; ++}; ++ ++slimbus_clk: slimbus_clk@4a004108 { ++ #clock-cells = <0>; ++ compatible = "gate-clock"; ++ clocks = <&slimbus_src_clk>; ++ bit-shift = <10>; ++ reg = <0x4a004108 0x4>; ++}; ++ ++sys_32k_ck: sys_32k_ck { ++ #clock-cells = <0>; ++ compatible = "fixed-clock"; ++ clock-frequency = <32768>; ++}; ++ ++virt_12000000_ck: virt_12000000_ck { ++ #clock-cells = <0>; ++ compatible = "fixed-clock"; ++ clock-frequency = <12000000>; ++}; ++ ++virt_13000000_ck: virt_13000000_ck { ++ #clock-cells = <0>; ++ compatible = "fixed-clock"; ++ clock-frequency = <13000000>; ++}; ++ ++virt_16800000_ck: virt_16800000_ck { ++ #clock-cells = <0>; ++ compatible = "fixed-clock"; ++ clock-frequency = <16800000>; ++}; ++ ++virt_19200000_ck: virt_19200000_ck { ++ #clock-cells = <0>; ++ compatible = "fixed-clock"; ++ clock-frequency = <19200000>; ++}; ++ ++virt_26000000_ck: virt_26000000_ck { ++ #clock-cells = <0>; ++ compatible = "fixed-clock"; ++ clock-frequency = <26000000>; ++}; ++ ++virt_27000000_ck: virt_27000000_ck { ++ #clock-cells = <0>; ++ compatible = "fixed-clock"; ++ clock-frequency = <27000000>; ++}; ++ ++virt_38400000_ck: virt_38400000_ck { ++ #clock-cells = <0>; ++ compatible = "fixed-clock"; ++ clock-frequency = <38400000>; ++}; ++ ++sys_clkin: sys_clkin@4ae06110 { ++ #clock-cells = <0>; ++ compatible = "mux-clock"; ++ clocks = <&virt_12000000_ck>, <&virt_13000000_ck>, <&virt_16800000_ck>, <&virt_19200000_ck>, <&virt_26000000_ck>, <&virt_27000000_ck>, <&virt_38400000_ck>; ++ reg = <0x4ae06110 0x4>; ++ bit-mask = <0x7>; ++ index-starts-at-one; ++}; ++ ++xclk60mhsp1_ck: xclk60mhsp1_ck { ++ #clock-cells = <0>; ++ compatible = "fixed-clock"; ++ clock-frequency = <60000000>; ++}; ++ ++xclk60mhsp2_ck: xclk60mhsp2_ck { ++ #clock-cells = <0>; ++ compatible = "fixed-clock"; ++ clock-frequency = <60000000>; ++}; ++ ++abe_dpll_bypass_clk_mux: abe_dpll_bypass_clk_mux@4ae06108 { ++ #clock-cells = <0>; ++ compatible = "mux-clock"; ++ clocks = <&sys_clkin>, <&sys_32k_ck>; ++ reg = <0x4ae06108 0x4>; ++ bit-mask = <0x1>; ++}; ++ ++abe_dpll_clk_mux: abe_dpll_clk_mux@4ae0610c { ++ #clock-cells = <0>; ++ compatible = "mux-clock"; ++ clocks = <&sys_clkin>, <&sys_32k_ck>; ++ reg = <0x4ae0610c 0x4>; ++ bit-mask = <0x1>; ++}; ++ ++dpll_abe_ck: dpll_abe_ck@4a0041e0 { ++ #clock-cells = <0>; ++ compatible = "ti,omap4-dpll-m4xen-clock"; ++ clocks = <&abe_dpll_clk_mux>, <&abe_dpll_bypass_clk_mux>; ++ reg = <0x4a0041e0 0x4>, <0x4a0041e4 0x4>, <0x4a0041e8 0x4>, <0x4a0041ec 0x4>; ++ reg-names = "control", "idlest", "autoidle", "mult-div1"; ++}; ++ ++dpll_abe_x2_ck: dpll_abe_x2_ck { ++ #clock-cells = <0>; ++ compatible = "ti,omap4-dpll-x2-clock"; ++ clocks = <&dpll_abe_ck>; ++}; ++ ++dpll_abe_m2x2_ck: dpll_abe_m2x2_ck@4a0041f0 { ++ #clock-cells = <0>; ++ compatible = "ti,divider-clock"; ++ clocks = <&dpll_abe_x2_ck>; ++ ti,autoidle-shift = <8>; ++ reg = <0x4a0041f0 0x4>; ++ bit-mask = <0x1f>; ++ index-starts-at-one; ++ ti,autoidle-low; ++}; ++ ++abe_24m_fclk: abe_24m_fclk { ++ #clock-cells = <0>; ++ compatible = "fixed-factor-clock"; ++ clocks = <&dpll_abe_m2x2_ck>; ++ clock-mult = <1>; ++ clock-div = <8>; ++}; ++ ++abe_clk: abe_clk@4a004108 { ++ #clock-cells = <0>; ++ compatible = "divider-clock"; ++ clocks = <&dpll_abe_m2x2_ck>; ++ reg = <0x4a004108 0x4>; ++ bit-mask = <0x3>; ++ index-power-of-two; ++}; ++ ++abe_iclk: abe_iclk { ++ #clock-cells = <0>; ++ compatible = "fixed-factor-clock"; ++ clocks = <&abe_clk>; ++ clock-mult = <1>; ++ clock-div = <2>; ++}; ++ ++abe_lp_clk_div: abe_lp_clk_div { ++ #clock-cells = <0>; ++ compatible = "fixed-factor-clock"; ++ clocks = <&dpll_abe_m2x2_ck>; ++ clock-mult = <1>; ++ clock-div = <16>; ++}; ++ ++dpll_abe_m3x2_ck: dpll_abe_m3x2_ck@4a0041f4 { ++ #clock-cells = <0>; ++ compatible = "ti,divider-clock"; ++ clocks = <&dpll_abe_x2_ck>; ++ ti,autoidle-shift = <8>; ++ reg = <0x4a0041f4 0x4>; ++ bit-mask = <0x1f>; ++ index-starts-at-one; ++ ti,autoidle-low; ++}; ++ ++dpll_core_ck: dpll_core_ck@4a004120 { ++ #clock-cells = <0>; ++ compatible = "ti,omap4-dpll-core-clock"; ++ clocks = <&sys_clkin>, <&dpll_abe_m3x2_ck>; ++ reg = <0x4a004120 0x4>, <0x4a004124 0x4>, <0x4a004128 0x4>, <0x4a00412c 0x4>; ++ reg-names = "control", "idlest", "autoidle", "mult-div1"; ++}; ++ ++dpll_core_x2_ck: dpll_core_x2_ck { ++ #clock-cells = <0>; ++ compatible = "ti,omap4-dpll-x2-clock"; ++ clocks = <&dpll_core_ck>; ++}; ++ ++dpll_core_h21x2_ck: dpll_core_h21x2_ck@4a004150 { ++ #clock-cells = <0>; ++ compatible = "ti,divider-clock"; ++ clocks = <&dpll_core_x2_ck>; ++ ti,autoidle-shift = <8>; ++ reg = <0x4a004150 0x4>; ++ bit-mask = <0x3f>; ++ index-starts-at-one; ++ ti,autoidle-low; ++}; ++ ++c2c_fclk: c2c_fclk { ++ #clock-cells = <0>; ++ compatible = "fixed-factor-clock"; ++ clocks = <&dpll_core_h21x2_ck>; ++ clock-mult = <1>; ++ clock-div = <1>; ++}; ++ ++c2c_iclk: c2c_iclk { ++ #clock-cells = <0>; ++ compatible = "fixed-factor-clock"; ++ clocks = <&c2c_fclk>; ++ clock-mult = <1>; ++ clock-div = <2>; ++}; ++ ++custefuse_sys_gfclk_div: custefuse_sys_gfclk_div { ++ #clock-cells = <0>; ++ compatible = "fixed-factor-clock"; ++ clocks = <&sys_clkin>; ++ clock-mult = <1>; ++ clock-div = <2>; ++}; ++ ++dpll_core_h11x2_ck: dpll_core_h11x2_ck@4a004138 { ++ #clock-cells = <0>; ++ compatible = "ti,divider-clock"; ++ clocks = <&dpll_core_x2_ck>; ++ ti,autoidle-shift = <8>; ++ reg = <0x4a004138 0x4>; ++ bit-mask = <0x3f>; ++ index-starts-at-one; ++ ti,autoidle-low; ++}; ++ ++dpll_core_h12x2_ck: dpll_core_h12x2_ck@4a00413c { ++ #clock-cells = <0>; ++ compatible = "ti,divider-clock"; ++ clocks = <&dpll_core_x2_ck>; ++ ti,autoidle-shift = <8>; ++ reg = <0x4a00413c 0x4>; ++ bit-mask = <0x3f>; ++ index-starts-at-one; ++ ti,autoidle-low; ++}; ++ ++dpll_core_h13x2_ck: dpll_core_h13x2_ck@4a004140 { ++ #clock-cells = <0>; ++ compatible = "ti,divider-clock"; ++ clocks = <&dpll_core_x2_ck>; ++ ti,autoidle-shift = <8>; ++ reg = <0x4a004140 0x4>; ++ bit-mask = <0x3f>; ++ index-starts-at-one; ++ ti,autoidle-low; ++}; ++ ++dpll_core_h14x2_ck: dpll_core_h14x2_ck@4a004144 { ++ #clock-cells = <0>; ++ compatible = "ti,divider-clock"; ++ clocks = <&dpll_core_x2_ck>; ++ ti,autoidle-shift = <8>; ++ reg = <0x4a004144 0x4>; ++ bit-mask = <0x3f>; ++ index-starts-at-one; ++ ti,autoidle-low; ++}; ++ ++dpll_core_h22x2_ck: dpll_core_h22x2_ck@4a004154 { ++ #clock-cells = <0>; ++ compatible = "ti,divider-clock"; ++ clocks = <&dpll_core_x2_ck>; ++ ti,autoidle-shift = <8>; ++ reg = <0x4a004154 0x4>; ++ bit-mask = <0x3f>; ++ index-starts-at-one; ++ ti,autoidle-low; ++}; ++ ++dpll_core_h23x2_ck: dpll_core_h23x2_ck@4a004158 { ++ #clock-cells = <0>; ++ compatible = "ti,divider-clock"; ++ clocks = <&dpll_core_x2_ck>; ++ ti,autoidle-shift = <8>; ++ reg = <0x4a004158 0x4>; ++ bit-mask = <0x3f>; ++ index-starts-at-one; ++ ti,autoidle-low; ++}; ++ ++dpll_core_h24x2_ck: dpll_core_h24x2_ck@4a00415c { ++ #clock-cells = <0>; ++ compatible = "ti,divider-clock"; ++ clocks = <&dpll_core_x2_ck>; ++ ti,autoidle-shift = <8>; ++ reg = <0x4a00415c 0x4>; ++ bit-mask = <0x3f>; ++ index-starts-at-one; ++ ti,autoidle-low; ++}; ++ ++dpll_core_m2_ck: dpll_core_m2_ck@4a004130 { ++ #clock-cells = <0>; ++ compatible = "ti,divider-clock"; ++ clocks = <&dpll_core_ck>; ++ ti,autoidle-shift = <8>; ++ reg = <0x4a004130 0x4>; ++ bit-mask = <0x1f>; ++ index-starts-at-one; ++ ti,autoidle-low; ++}; ++ ++dpll_core_m3x2_ck: dpll_core_m3x2_ck@4a004134 { ++ #clock-cells = <0>; ++ compatible = "ti,divider-clock"; ++ clocks = <&dpll_core_x2_ck>; ++ ti,autoidle-shift = <8>; ++ reg = <0x4a004134 0x4>; ++ bit-mask = <0x1f>; ++ index-starts-at-one; ++ ti,autoidle-low; ++}; ++ ++iva_dpll_hs_clk_div: iva_dpll_hs_clk_div { ++ #clock-cells = <0>; ++ compatible = "fixed-factor-clock"; ++ clocks = <&dpll_core_h12x2_ck>; ++ clock-mult = <1>; ++ clock-div = <1>; ++}; ++ ++dpll_iva_ck: dpll_iva_ck@4a0041a0 { ++ #clock-cells = <0>; ++ compatible = "ti,omap4-dpll-clock"; ++ clocks = <&sys_clkin>, <&iva_dpll_hs_clk_div>; ++ reg = <0x4a0041a0 0x4>, <0x4a0041a4 0x4>, <0x4a0041a8 0x4>, <0x4a0041ac 0x4>; ++ reg-names = "control", "idlest", "autoidle", "mult-div1"; ++}; ++ ++dpll_iva_x2_ck: dpll_iva_x2_ck { ++ #clock-cells = <0>; ++ compatible = "ti,omap4-dpll-x2-clock"; ++ clocks = <&dpll_iva_ck>; ++}; ++ ++dpll_iva_h11x2_ck: dpll_iva_h11x2_ck@4a0041b8 { ++ #clock-cells = <0>; ++ compatible = "ti,divider-clock"; ++ clocks = <&dpll_iva_x2_ck>; ++ ti,autoidle-shift = <8>; ++ reg = <0x4a0041b8 0x4>; ++ bit-mask = <0x3f>; ++ index-starts-at-one; ++ ti,autoidle-low; ++}; ++ ++dpll_iva_h12x2_ck: dpll_iva_h12x2_ck@4a0041bc { ++ #clock-cells = <0>; ++ compatible = "ti,divider-clock"; ++ clocks = <&dpll_iva_x2_ck>; ++ ti,autoidle-shift = <8>; ++ reg = <0x4a0041bc 0x4>; ++ bit-mask = <0x3f>; ++ index-starts-at-one; ++ ti,autoidle-low; ++}; ++ ++mpu_dpll_hs_clk_div: mpu_dpll_hs_clk_div { ++ #clock-cells = <0>; ++ compatible = "fixed-factor-clock"; ++ clocks = <&dpll_core_h12x2_ck>; ++ clock-mult = <1>; ++ clock-div = <1>; ++}; ++ ++dpll_mpu_ck: dpll_mpu_ck@4a004160 { ++ #clock-cells = <0>; ++ compatible = "ti,omap4-dpll-clock"; ++ clocks = <&sys_clkin>, <&mpu_dpll_hs_clk_div>; ++ reg = <0x4a004160 0x4>, <0x4a004164 0x4>, <0x4a004168 0x4>, <0x4a00416c 0x4>; ++ reg-names = "control", "idlest", "autoidle", "mult-div1"; ++}; ++ ++dpll_mpu_m2_ck: dpll_mpu_m2_ck@4a004170 { ++ #clock-cells = <0>; ++ compatible = "ti,divider-clock"; ++ clocks = <&dpll_mpu_ck>; ++ ti,autoidle-shift = <8>; ++ reg = <0x4a004170 0x4>; ++ bit-mask = <0x1f>; ++ index-starts-at-one; ++ ti,autoidle-low; ++}; ++ ++per_dpll_hs_clk_div: per_dpll_hs_clk_div { ++ #clock-cells = <0>; ++ compatible = "fixed-factor-clock"; ++ clocks = <&dpll_abe_m3x2_ck>; ++ clock-mult = <1>; ++ clock-div = <2>; ++}; ++ ++dpll_per_ck: dpll_per_ck@4a008140 { ++ #clock-cells = <0>; ++ compatible = "ti,omap4-dpll-clock"; ++ clocks = <&sys_clkin>, <&per_dpll_hs_clk_div>; ++ reg = <0x4a008140 0x4>, <0x4a008144 0x4>, <0x4a008148 0x4>, <0x4a00814c 0x4>; ++ reg-names = "control", "idlest", "autoidle", "mult-div1"; ++}; ++ ++dpll_per_x2_ck: dpll_per_x2_ck { ++ #clock-cells = <0>; ++ compatible = "ti,omap4-dpll-x2-clock"; ++ clocks = <&dpll_per_ck>; ++}; ++ ++dpll_per_h11x2_ck: dpll_per_h11x2_ck@4a008158 { ++ #clock-cells = <0>; ++ compatible = "ti,divider-clock"; ++ clocks = <&dpll_per_x2_ck>; ++ ti,autoidle-shift = <8>; ++ reg = <0x4a008158 0x4>; ++ bit-mask = <0x3f>; ++ index-starts-at-one; ++ ti,autoidle-low; ++}; ++ ++dpll_per_h12x2_ck: dpll_per_h12x2_ck@4a00815c { ++ #clock-cells = <0>; ++ compatible = "ti,divider-clock"; ++ clocks = <&dpll_per_x2_ck>; ++ ti,autoidle-shift = <8>; ++ reg = <0x4a00815c 0x4>; ++ bit-mask = <0x3f>; ++ index-starts-at-one; ++ ti,autoidle-low; ++}; ++ ++dpll_per_h14x2_ck: dpll_per_h14x2_ck@4a008164 { ++ #clock-cells = <0>; ++ compatible = "ti,divider-clock"; ++ clocks = <&dpll_per_x2_ck>; ++ ti,autoidle-shift = <8>; ++ reg = <0x4a008164 0x4>; ++ bit-mask = <0x3f>; ++ index-starts-at-one; ++ ti,autoidle-low; ++}; ++ ++dpll_per_m2_ck: dpll_per_m2_ck@4a008150 { ++ #clock-cells = <0>; ++ compatible = "ti,divider-clock"; ++ clocks = <&dpll_per_ck>; ++ ti,autoidle-shift = <8>; ++ reg = <0x4a008150 0x4>; ++ bit-mask = <0x1f>; ++ index-starts-at-one; ++ ti,autoidle-low; ++}; ++ ++dpll_per_m2x2_ck: dpll_per_m2x2_ck@4a008150 { ++ #clock-cells = <0>; ++ compatible = "ti,divider-clock"; ++ clocks = <&dpll_per_x2_ck>; ++ ti,autoidle-shift = <8>; ++ reg = <0x4a008150 0x4>; ++ bit-mask = <0x1f>; ++ index-starts-at-one; ++ ti,autoidle-low; ++}; ++ ++dpll_per_m3x2_ck: dpll_per_m3x2_ck@4a008154 { ++ #clock-cells = <0>; ++ compatible = "ti,divider-clock"; ++ clocks = <&dpll_per_x2_ck>; ++ ti,autoidle-shift = <8>; ++ reg = <0x4a008154 0x4>; ++ bit-mask = <0x1f>; ++ index-starts-at-one; ++ ti,autoidle-low; ++}; ++ ++dpll_unipro1_ck: dpll_unipro1_ck@4a008200 { ++ #clock-cells = <0>; ++ compatible = "ti,omap4-dpll-clock"; ++ clocks = <&sys_clkin>, <&sys_clkin>; ++ reg = <0x4a008200 0x4>, <0x4a008204 0x4>, <0x4a008208 0x4>, <0x4a00820c 0x4>; ++ reg-names = "control", "idlest", "autoidle", "mult-div1"; ++}; ++ ++dpll_unipro1_clkdcoldo: dpll_unipro1_clkdcoldo { ++ #clock-cells = <0>; ++ compatible = "fixed-factor-clock"; ++ clocks = <&dpll_unipro1_ck>; ++ clock-mult = <1>; ++ clock-div = <1>; ++}; ++ ++dpll_unipro1_m2_ck: dpll_unipro1_m2_ck@4a008210 { ++ #clock-cells = <0>; ++ compatible = "ti,divider-clock"; ++ clocks = <&dpll_unipro1_ck>; ++ ti,autoidle-shift = <8>; ++ reg = <0x4a008210 0x4>; ++ bit-mask = <0x7f>; ++ index-starts-at-one; ++ ti,autoidle-low; ++}; ++ ++dpll_unipro2_ck: dpll_unipro2_ck@4a0081c0 { ++ #clock-cells = <0>; ++ compatible = "ti,omap4-dpll-clock"; ++ clocks = <&sys_clkin>, <&sys_clkin>; ++ reg = <0x4a0081c0 0x4>, <0x4a0081c4 0x4>, <0x4a0081c8 0x4>, <0x4a0081cc 0x4>; ++ reg-names = "control", "idlest", "autoidle", "mult-div1"; ++}; ++ ++dpll_unipro2_clkdcoldo: dpll_unipro2_clkdcoldo { ++ #clock-cells = <0>; ++ compatible = "fixed-factor-clock"; ++ clocks = <&dpll_unipro2_ck>; ++ clock-mult = <1>; ++ clock-div = <1>; ++}; ++ ++dpll_unipro2_m2_ck: dpll_unipro2_m2_ck@4a0081d0 { ++ #clock-cells = <0>; ++ compatible = "ti,divider-clock"; ++ clocks = <&dpll_unipro2_ck>; ++ ti,autoidle-shift = <8>; ++ reg = <0x4a0081d0 0x4>; ++ bit-mask = <0x7f>; ++ index-starts-at-one; ++ ti,autoidle-low; ++}; ++ ++usb_dpll_hs_clk_div: usb_dpll_hs_clk_div { ++ #clock-cells = <0>; ++ compatible = "fixed-factor-clock"; ++ clocks = <&dpll_abe_m3x2_ck>; ++ clock-mult = <1>; ++ clock-div = <3>; ++}; ++ ++dpll_usb_ck: dpll_usb_ck@4a008180 { ++ #clock-cells = <0>; ++ compatible = "ti,omap4-dpll-j-type-clock"; ++ clocks = <&sys_clkin>, <&usb_dpll_hs_clk_div>; ++ reg = <0x4a008180 0x4>, <0x4a008184 0x4>, <0x4a008188 0x4>, <0x4a00818c 0x4>; ++ reg-names = "control", "idlest", "autoidle", "mult-div1"; ++}; ++ ++dpll_usb_clkdcoldo: dpll_usb_clkdcoldo { ++ #clock-cells = <0>; ++ compatible = "fixed-factor-clock"; ++ clocks = <&dpll_usb_ck>; ++ clock-mult = <1>; ++ clock-div = <1>; ++}; ++ ++dpll_usb_m2_ck: dpll_usb_m2_ck@4a008190 { ++ #clock-cells = <0>; ++ compatible = "ti,divider-clock"; ++ clocks = <&dpll_usb_ck>; ++ ti,autoidle-shift = <8>; ++ reg = <0x4a008190 0x4>; ++ bit-mask = <0x7f>; ++ index-starts-at-one; ++ ti,autoidle-low; ++}; ++ ++dss_syc_gfclk_div: dss_syc_gfclk_div { ++ #clock-cells = <0>; ++ compatible = "fixed-factor-clock"; ++ clocks = <&sys_clkin>; ++ clock-mult = <1>; ++ clock-div = <1>; ++}; ++ ++func_128m_clk: func_128m_clk { ++ #clock-cells = <0>; ++ compatible = "fixed-factor-clock"; ++ clocks = <&dpll_per_h11x2_ck>; ++ clock-mult = <1>; ++ clock-div = <2>; ++}; ++ ++func_12m_fclk: func_12m_fclk { ++ #clock-cells = <0>; ++ compatible = "fixed-factor-clock"; ++ clocks = <&dpll_per_m2x2_ck>; ++ clock-mult = <1>; ++ clock-div = <16>; ++}; ++ ++func_24m_clk: func_24m_clk { ++ #clock-cells = <0>; ++ compatible = "fixed-factor-clock"; ++ clocks = <&dpll_per_m2_ck>; ++ clock-mult = <1>; ++ clock-div = <4>; ++}; ++ ++func_48m_fclk: func_48m_fclk { ++ #clock-cells = <0>; ++ compatible = "fixed-factor-clock"; ++ clocks = <&dpll_per_m2x2_ck>; ++ clock-mult = <1>; ++ clock-div = <4>; ++}; ++ ++func_96m_fclk: func_96m_fclk { ++ #clock-cells = <0>; ++ compatible = "fixed-factor-clock"; ++ clocks = <&dpll_per_m2x2_ck>; ++ clock-mult = <1>; ++ clock-div = <2>; ++}; ++ ++l3_iclk_div: l3_iclk_div { ++ #clock-cells = <0>; ++ compatible = "fixed-factor-clock"; ++ clocks = <&dpll_core_h12x2_ck>; ++ clock-mult = <1>; ++ clock-div = <1>; ++}; ++ ++gpu_l3_iclk: gpu_l3_iclk { ++ #clock-cells = <0>; ++ compatible = "fixed-factor-clock"; ++ clocks = <&l3_iclk_div>; ++ clock-mult = <1>; ++ clock-div = <1>; ++}; ++ ++l3init_60m_fclk: l3init_60m_fclk@4a008104 { ++ #clock-cells = <0>; ++ compatible = "divider-clock"; ++ clocks = <&dpll_usb_m2_ck>; ++ reg = <0x4a008104 0x4>; ++ table = < 1 0 >, < 8 1 >; ++ bit-mask = <0x1>; ++}; ++ ++wkupaon_iclk_mux: wkupaon_iclk_mux@4ae06108 { ++ #clock-cells = <0>; ++ compatible = "mux-clock"; ++ clocks = <&sys_clkin>, <&abe_lp_clk_div>; ++ reg = <0x4ae06108 0x4>; ++ bit-mask = <0x1>; ++}; ++ ++l3instr_ts_gclk_div: l3instr_ts_gclk_div { ++ #clock-cells = <0>; ++ compatible = "fixed-factor-clock"; ++ clocks = <&wkupaon_iclk_mux>; ++ clock-mult = <1>; ++ clock-div = <1>; ++}; ++ ++l4_root_clk_div: l4_root_clk_div { ++ #clock-cells = <0>; ++ compatible = "fixed-factor-clock"; ++ clocks = <&l3_iclk_div>; ++ clock-mult = <1>; ++ clock-div = <1>; ++}; ++ ++dss_32khz_clk: dss_32khz_clk@4a009420 { ++ #clock-cells = <0>; ++ compatible = "gate-clock"; ++ clocks = <&sys_32k_ck>; ++ bit-shift = <11>; ++ reg = <0x4a009420 0x4>; ++}; ++ ++dss_48mhz_clk: dss_48mhz_clk@4a009420 { ++ #clock-cells = <0>; ++ compatible = "gate-clock"; ++ clocks = <&func_48m_fclk>; ++ bit-shift = <9>; ++ reg = <0x4a009420 0x4>; ++}; ++ ++dss_dss_clk: dss_dss_clk@4a009420 { ++ #clock-cells = <0>; ++ compatible = "gate-clock"; ++ clocks = <&dpll_per_h12x2_ck>; ++ bit-shift = <8>; ++ reg = <0x4a009420 0x4>; ++}; ++ ++dss_sys_clk: dss_sys_clk@4a009420 { ++ #clock-cells = <0>; ++ compatible = "gate-clock"; ++ clocks = <&dss_syc_gfclk_div>; ++ bit-shift = <10>; ++ reg = <0x4a009420 0x4>; ++}; ++ ++gpio1_dbclk: gpio1_dbclk@4ae07938 { ++ #clock-cells = <0>; ++ compatible = "gate-clock"; ++ clocks = <&sys_32k_ck>; ++ bit-shift = <8>; ++ reg = <0x4ae07938 0x4>; ++}; ++ ++gpio2_dbclk: gpio2_dbclk@4a009060 { ++ #clock-cells = <0>; ++ compatible = "gate-clock"; ++ clocks = <&sys_32k_ck>; ++ bit-shift = <8>; ++ reg = <0x4a009060 0x4>; ++}; ++ ++gpio3_dbclk: gpio3_dbclk@4a009068 { ++ #clock-cells = <0>; ++ compatible = "gate-clock"; ++ clocks = <&sys_32k_ck>; ++ bit-shift = <8>; ++ reg = <0x4a009068 0x4>; ++}; ++ ++gpio4_dbclk: gpio4_dbclk@4a009070 { ++ #clock-cells = <0>; ++ compatible = "gate-clock"; ++ clocks = <&sys_32k_ck>; ++ bit-shift = <8>; ++ reg = <0x4a009070 0x4>; ++}; ++ ++gpio5_dbclk: gpio5_dbclk@4a009078 { ++ #clock-cells = <0>; ++ compatible = "gate-clock"; ++ clocks = <&sys_32k_ck>; ++ bit-shift = <8>; ++ reg = <0x4a009078 0x4>; ++}; ++ ++gpio6_dbclk: gpio6_dbclk@4a009080 { ++ #clock-cells = <0>; ++ compatible = "gate-clock"; ++ clocks = <&sys_32k_ck>; ++ bit-shift = <8>; ++ reg = <0x4a009080 0x4>; ++}; ++ ++gpio7_dbclk: gpio7_dbclk@4a009110 { ++ #clock-cells = <0>; ++ compatible = "gate-clock"; ++ clocks = <&sys_32k_ck>; ++ bit-shift = <8>; ++ reg = <0x4a009110 0x4>; ++}; ++ ++gpio8_dbclk: gpio8_dbclk@4a009118 { ++ #clock-cells = <0>; ++ compatible = "gate-clock"; ++ clocks = <&sys_32k_ck>; ++ bit-shift = <8>; ++ reg = <0x4a009118 0x4>; ++}; ++ ++iss_ctrlclk: iss_ctrlclk@4a009320 { ++ #clock-cells = <0>; ++ compatible = "gate-clock"; ++ clocks = <&func_96m_fclk>; ++ bit-shift = <8>; ++ reg = <0x4a009320 0x4>; ++}; ++ ++lli_txphy_clk: lli_txphy_clk@4a008f20 { ++ #clock-cells = <0>; ++ compatible = "gate-clock"; ++ clocks = <&dpll_unipro1_clkdcoldo>; ++ bit-shift = <8>; ++ reg = <0x4a008f20 0x4>; ++}; ++ ++lli_txphy_ls_clk: lli_txphy_ls_clk@4a008f20 { ++ #clock-cells = <0>; ++ compatible = "gate-clock"; ++ clocks = <&dpll_unipro1_m2_ck>; ++ bit-shift = <9>; ++ reg = <0x4a008f20 0x4>; ++}; ++ ++mmc1_32khz_clk: mmc1_32khz_clk@4a009628 { ++ #clock-cells = <0>; ++ compatible = "gate-clock"; ++ clocks = <&sys_32k_ck>; ++ bit-shift = <8>; ++ reg = <0x4a009628 0x4>; ++}; ++ ++sata_ref_clk: sata_ref_clk@4a009688 { ++ #clock-cells = <0>; ++ compatible = "gate-clock"; ++ clocks = <&sys_clkin>; ++ bit-shift = <8>; ++ reg = <0x4a009688 0x4>; ++}; ++ ++slimbus1_slimbus_clk: slimbus1_slimbus_clk@4a004560 { ++ #clock-cells = <0>; ++ compatible = "gate-clock"; ++ clocks = <&slimbus_clk>; ++ bit-shift = <11>; ++ reg = <0x4a004560 0x4>; ++}; ++ ++usb_host_hs_hsic480m_p1_clk: usb_host_hs_hsic480m_p1_clk@4a009658 { ++ #clock-cells = <0>; ++ compatible = "gate-clock"; ++ clocks = <&dpll_usb_m2_ck>; ++ bit-shift = <13>; ++ reg = <0x4a009658 0x4>; ++}; ++ ++usb_host_hs_hsic480m_p2_clk: usb_host_hs_hsic480m_p2_clk@4a009658 { ++ #clock-cells = <0>; ++ compatible = "gate-clock"; ++ clocks = <&dpll_usb_m2_ck>; ++ bit-shift = <14>; ++ reg = <0x4a009658 0x4>; ++}; ++ ++usb_host_hs_hsic480m_p3_clk: usb_host_hs_hsic480m_p3_clk@4a009658 { ++ #clock-cells = <0>; ++ compatible = "gate-clock"; ++ clocks = <&dpll_usb_m2_ck>; ++ bit-shift = <7>; ++ reg = <0x4a009658 0x4>; ++}; ++ ++usb_host_hs_hsic60m_p1_clk: usb_host_hs_hsic60m_p1_clk@4a009658 { ++ #clock-cells = <0>; ++ compatible = "gate-clock"; ++ clocks = <&l3init_60m_fclk>; ++ bit-shift = <11>; ++ reg = <0x4a009658 0x4>; ++}; ++ ++usb_host_hs_hsic60m_p2_clk: usb_host_hs_hsic60m_p2_clk@4a009658 { ++ #clock-cells = <0>; ++ compatible = "gate-clock"; ++ clocks = <&l3init_60m_fclk>; ++ bit-shift = <12>; ++ reg = <0x4a009658 0x4>; ++}; ++ ++usb_host_hs_hsic60m_p3_clk: usb_host_hs_hsic60m_p3_clk@4a009658 { ++ #clock-cells = <0>; ++ compatible = "gate-clock"; ++ clocks = <&l3init_60m_fclk>; ++ bit-shift = <6>; ++ reg = <0x4a009658 0x4>; ++}; ++ ++utmi_p1_gfclk: utmi_p1_gfclk@4a009658 { ++ #clock-cells = <0>; ++ compatible = "mux-clock"; ++ clocks = <&l3init_60m_fclk>, <&xclk60mhsp1_ck>; ++ bit-shift = <24>; ++ reg = <0x4a009658 0x4>; ++ bit-mask = <0x1>; ++}; ++ ++usb_host_hs_utmi_p1_clk: usb_host_hs_utmi_p1_clk@4a009658 { ++ #clock-cells = <0>; ++ compatible = "gate-clock"; ++ clocks = <&utmi_p1_gfclk>; ++ bit-shift = <8>; ++ reg = <0x4a009658 0x4>; ++}; ++ ++utmi_p2_gfclk: utmi_p2_gfclk@4a009658 { ++ #clock-cells = <0>; ++ compatible = "mux-clock"; ++ clocks = <&l3init_60m_fclk>, <&xclk60mhsp2_ck>; ++ bit-shift = <25>; ++ reg = <0x4a009658 0x4>; ++ bit-mask = <0x1>; ++}; ++ ++usb_host_hs_utmi_p2_clk: usb_host_hs_utmi_p2_clk@4a009658 { ++ #clock-cells = <0>; ++ compatible = "gate-clock"; ++ clocks = <&utmi_p2_gfclk>; ++ bit-shift = <9>; ++ reg = <0x4a009658 0x4>; ++}; ++ ++usb_host_hs_utmi_p3_clk: usb_host_hs_utmi_p3_clk@4a009658 { ++ #clock-cells = <0>; ++ compatible = "gate-clock"; ++ clocks = <&l3init_60m_fclk>; ++ bit-shift = <10>; ++ reg = <0x4a009658 0x4>; ++}; ++ ++usb_otg_ss_refclk960m: usb_otg_ss_refclk960m@4a0096f0 { ++ #clock-cells = <0>; ++ compatible = "gate-clock"; ++ clocks = <&dpll_usb_clkdcoldo>; ++ bit-shift = <8>; ++ reg = <0x4a0096f0 0x4>; ++}; ++ ++usb_phy_cm_clk32k: usb_phy_cm_clk32k@4a008640 { ++ #clock-cells = <0>; ++ compatible = "gate-clock"; ++ clocks = <&sys_32k_ck>; ++ bit-shift = <8>; ++ reg = <0x4a008640 0x4>; ++}; ++ ++usb_tll_hs_usb_ch0_clk: usb_tll_hs_usb_ch0_clk@4a009668 { ++ #clock-cells = <0>; ++ compatible = "gate-clock"; ++ clocks = <&l3init_60m_fclk>; ++ bit-shift = <8>; ++ reg = <0x4a009668 0x4>; ++}; ++ ++usb_tll_hs_usb_ch1_clk: usb_tll_hs_usb_ch1_clk@4a009668 { ++ #clock-cells = <0>; ++ compatible = "gate-clock"; ++ clocks = <&l3init_60m_fclk>; ++ bit-shift = <9>; ++ reg = <0x4a009668 0x4>; ++}; ++ ++usb_tll_hs_usb_ch2_clk: usb_tll_hs_usb_ch2_clk@4a009668 { ++ #clock-cells = <0>; ++ compatible = "gate-clock"; ++ clocks = <&l3init_60m_fclk>; ++ bit-shift = <10>; ++ reg = <0x4a009668 0x4>; ++}; ++ ++aess_fclk: aess_fclk@4a004528 { ++ #clock-cells = <0>; ++ compatible = "divider-clock"; ++ clocks = <&abe_clk>; ++ bit-shift = <24>; ++ reg = <0x4a004528 0x4>; ++ bit-mask = <0x1>; ++}; ++ ++dmic_sync_mux_ck: dmic_sync_mux_ck@4a004538 { ++ #clock-cells = <0>; ++ compatible = "mux-clock"; ++ clocks = <&abe_24m_fclk>, <&dss_syc_gfclk_div>, <&func_24m_clk>; ++ bit-shift = <26>; ++ reg = <0x4a004538 0x4>; ++ bit-mask = <0x3>; ++}; ++ ++dmic_gfclk: dmic_gfclk@4a004538 { ++ #clock-cells = <0>; ++ compatible = "mux-clock"; ++ clocks = <&dmic_sync_mux_ck>, <&pad_clks_ck>, <&slimbus_clk>; ++ bit-shift = <24>; ++ reg = <0x4a004538 0x4>; ++ bit-mask = <0x3>; ++}; ++ ++fdif_fclk: fdif_fclk@4a009328 { ++ #clock-cells = <0>; ++ compatible = "divider-clock"; ++ clocks = <&dpll_per_h11x2_ck>; ++ bit-shift = <24>; ++ reg = <0x4a009328 0x4>; ++ bit-mask = <0x1>; ++}; ++ ++gpu_core_gclk_mux: gpu_core_gclk_mux@4a009520 { ++ #clock-cells = <0>; ++ compatible = "mux-clock"; ++ clocks = <&dpll_core_h14x2_ck>, <&dpll_per_h14x2_ck>; ++ bit-shift = <24>; ++ reg = <0x4a009520 0x4>; ++ bit-mask = <0x1>; ++}; ++ ++gpu_hyd_gclk_mux: gpu_hyd_gclk_mux@4a009520 { ++ #clock-cells = <0>; ++ compatible = "mux-clock"; ++ clocks = <&dpll_core_h14x2_ck>, <&dpll_per_h14x2_ck>; ++ bit-shift = <25>; ++ reg = <0x4a009520 0x4>; ++ bit-mask = <0x1>; ++}; ++ ++hsi_fclk: hsi_fclk@4a009638 { ++ #clock-cells = <0>; ++ compatible = "divider-clock"; ++ clocks = <&dpll_per_m2x2_ck>; ++ bit-shift = <24>; ++ reg = <0x4a009638 0x4>; ++ bit-mask = <0x1>; ++}; ++ ++mcasp_sync_mux_ck: mcasp_sync_mux_ck@4a004540 { ++ #clock-cells = <0>; ++ compatible = "mux-clock"; ++ clocks = <&abe_24m_fclk>, <&dss_syc_gfclk_div>, <&func_24m_clk>; ++ bit-shift = <26>; ++ reg = <0x4a004540 0x4>; ++ bit-mask = <0x3>; ++}; ++ ++mcasp_gfclk: mcasp_gfclk@4a004540 { ++ #clock-cells = <0>; ++ compatible = "mux-clock"; ++ clocks = <&mcasp_sync_mux_ck>, <&pad_clks_ck>, <&slimbus_clk>; ++ bit-shift = <24>; ++ reg = <0x4a004540 0x4>; ++ bit-mask = <0x3>; ++}; ++ ++mcbsp1_sync_mux_ck: mcbsp1_sync_mux_ck@4a004548 { ++ #clock-cells = <0>; ++ compatible = "mux-clock"; ++ clocks = <&abe_24m_fclk>, <&dss_syc_gfclk_div>, <&func_24m_clk>; ++ bit-shift = <26>; ++ reg = <0x4a004548 0x4>; ++ bit-mask = <0x3>; ++}; ++ ++mcbsp1_gfclk: mcbsp1_gfclk@4a004548 { ++ #clock-cells = <0>; ++ compatible = "mux-clock"; ++ clocks = <&mcbsp1_sync_mux_ck>, <&pad_clks_ck>, <&slimbus_clk>; ++ bit-shift = <24>; ++ reg = <0x4a004548 0x4>; ++ bit-mask = <0x3>; ++}; ++ ++mcbsp2_sync_mux_ck: mcbsp2_sync_mux_ck@4a004550 { ++ #clock-cells = <0>; ++ compatible = "mux-clock"; ++ clocks = <&abe_24m_fclk>, <&dss_syc_gfclk_div>, <&func_24m_clk>; ++ bit-shift = <26>; ++ reg = <0x4a004550 0x4>; ++ bit-mask = <0x3>; ++}; ++ ++mcbsp2_gfclk: mcbsp2_gfclk@4a004550 { ++ #clock-cells = <0>; ++ compatible = "mux-clock"; ++ clocks = <&mcbsp2_sync_mux_ck>, <&pad_clks_ck>, <&slimbus_clk>; ++ bit-shift = <24>; ++ reg = <0x4a004550 0x4>; ++ bit-mask = <0x3>; ++}; ++ ++mcbsp3_sync_mux_ck: mcbsp3_sync_mux_ck@4a004558 { ++ #clock-cells = <0>; ++ compatible = "mux-clock"; ++ clocks = <&abe_24m_fclk>, <&dss_syc_gfclk_div>, <&func_24m_clk>; ++ bit-shift = <26>; ++ reg = <0x4a004558 0x4>; ++ bit-mask = <0x3>; ++}; ++ ++mcbsp3_gfclk: mcbsp3_gfclk@4a004558 { ++ #clock-cells = <0>; ++ compatible = "mux-clock"; ++ clocks = <&mcbsp3_sync_mux_ck>, <&pad_clks_ck>, <&slimbus_clk>; ++ bit-shift = <24>; ++ reg = <0x4a004558 0x4>; ++ bit-mask = <0x3>; ++}; ++ ++mmc1_fclk_mux: mmc1_fclk_mux@4a009628 { ++ #clock-cells = <0>; ++ compatible = "mux-clock"; ++ clocks = <&func_128m_clk>, <&dpll_per_m2x2_ck>; ++ bit-shift = <24>; ++ reg = <0x4a009628 0x4>; ++ bit-mask = <0x1>; ++}; ++ ++mmc1_fclk: mmc1_fclk@4a009628 { ++ #clock-cells = <0>; ++ compatible = "divider-clock"; ++ clocks = <&mmc1_fclk_mux>; ++ bit-shift = <25>; ++ reg = <0x4a009628 0x4>; ++ bit-mask = <0x1>; ++}; ++ ++mmc2_fclk_mux: mmc2_fclk_mux@4a009630 { ++ #clock-cells = <0>; ++ compatible = "mux-clock"; ++ clocks = <&func_128m_clk>, <&dpll_per_m2x2_ck>; ++ bit-shift = <24>; ++ reg = <0x4a009630 0x4>; ++ bit-mask = <0x1>; ++}; ++ ++mmc2_fclk: mmc2_fclk@4a009630 { ++ #clock-cells = <0>; ++ compatible = "divider-clock"; ++ clocks = <&mmc2_fclk_mux>; ++ bit-shift = <25>; ++ reg = <0x4a009630 0x4>; ++ bit-mask = <0x1>; ++}; ++ ++timer10_gfclk_mux: timer10_gfclk_mux@4a009028 { ++ #clock-cells = <0>; ++ compatible = "mux-clock"; ++ clocks = <&sys_clkin>, <&sys_32k_ck>; ++ bit-shift = <24>; ++ reg = <0x4a009028 0x4>; ++ bit-mask = <0x1>; ++}; ++ ++timer11_gfclk_mux: timer11_gfclk_mux@4a009030 { ++ #clock-cells = <0>; ++ compatible = "mux-clock"; ++ clocks = <&sys_clkin>, <&sys_32k_ck>; ++ bit-shift = <24>; ++ reg = <0x4a009030 0x4>; ++ bit-mask = <0x1>; ++}; ++ ++timer1_gfclk_mux: timer1_gfclk_mux@4ae07940 { ++ #clock-cells = <0>; ++ compatible = "mux-clock"; ++ clocks = <&sys_clkin>, <&sys_32k_ck>; ++ bit-shift = <24>; ++ reg = <0x4ae07940 0x4>; ++ bit-mask = <0x1>; ++}; ++ ++timer2_gfclk_mux: timer2_gfclk_mux@4a009038 { ++ #clock-cells = <0>; ++ compatible = "mux-clock"; ++ clocks = <&sys_clkin>, <&sys_32k_ck>; ++ bit-shift = <24>; ++ reg = <0x4a009038 0x4>; ++ bit-mask = <0x1>; ++}; ++ ++timer3_gfclk_mux: timer3_gfclk_mux@4a009040 { ++ #clock-cells = <0>; ++ compatible = "mux-clock"; ++ clocks = <&sys_clkin>, <&sys_32k_ck>; ++ bit-shift = <24>; ++ reg = <0x4a009040 0x4>; ++ bit-mask = <0x1>; ++}; ++ ++timer4_gfclk_mux: timer4_gfclk_mux@4a009048 { ++ #clock-cells = <0>; ++ compatible = "mux-clock"; ++ clocks = <&sys_clkin>, <&sys_32k_ck>; ++ bit-shift = <24>; ++ reg = <0x4a009048 0x4>; ++ bit-mask = <0x1>; ++}; ++ ++timer5_gfclk_mux: timer5_gfclk_mux@4a004568 { ++ #clock-cells = <0>; ++ compatible = "mux-clock"; ++ clocks = <&dss_syc_gfclk_div>, <&sys_32k_ck>; ++ bit-shift = <24>; ++ reg = <0x4a004568 0x4>; ++ bit-mask = <0x1>; ++}; ++ ++timer6_gfclk_mux: timer6_gfclk_mux@4a004570 { ++ #clock-cells = <0>; ++ compatible = "mux-clock"; ++ clocks = <&dss_syc_gfclk_div>, <&sys_32k_ck>; ++ bit-shift = <24>; ++ reg = <0x4a004570 0x4>; ++ bit-mask = <0x1>; ++}; ++ ++timer7_gfclk_mux: timer7_gfclk_mux@4a004578 { ++ #clock-cells = <0>; ++ compatible = "mux-clock"; ++ clocks = <&dss_syc_gfclk_div>, <&sys_32k_ck>; ++ bit-shift = <24>; ++ reg = <0x4a004578 0x4>; ++ bit-mask = <0x1>; ++}; ++ ++timer8_gfclk_mux: timer8_gfclk_mux@4a004580 { ++ #clock-cells = <0>; ++ compatible = "mux-clock"; ++ clocks = <&dss_syc_gfclk_div>, <&sys_32k_ck>; ++ bit-shift = <24>; ++ reg = <0x4a004580 0x4>; ++ bit-mask = <0x1>; ++}; ++ ++timer9_gfclk_mux: timer9_gfclk_mux@4a009050 { ++ #clock-cells = <0>; ++ compatible = "mux-clock"; ++ clocks = <&sys_clkin>, <&sys_32k_ck>; ++ bit-shift = <24>; ++ reg = <0x4a009050 0x4>; ++ bit-mask = <0x1>; ++}; ++ ++auxclk0_src_mux_ck: auxclk0_src_mux_ck@4ae0a310 { ++ #clock-cells = <0>; ++ compatible = "mux-clock"; ++ clocks = <&sys_clkin>, <&dpll_core_m3x2_ck>, <&dpll_per_m3x2_ck>; ++ bit-shift = <1>; ++ reg = <0x4ae0a310 0x4>; ++ bit-mask = <0x3>; ++}; ++ ++auxclk0_src_ck: auxclk0_src_ck@4ae0a310 { ++ #clock-cells = <0>; ++ compatible = "gate-clock"; ++ clocks = <&auxclk0_src_mux_ck>; ++ bit-shift = <8>; ++ reg = <0x4ae0a310 0x4>; ++}; ++ ++auxclk0_ck: auxclk0_ck@4ae0a310 { ++ #clock-cells = <0>; ++ compatible = "divider-clock"; ++ clocks = <&auxclk0_src_ck>; ++ bit-shift = <16>; ++ reg = <0x4ae0a310 0x4>; ++ bit-mask = <0xf>; ++}; ++ ++auxclk1_src_mux_ck: auxclk1_src_mux_ck@4ae0a314 { ++ #clock-cells = <0>; ++ compatible = "mux-clock"; ++ clocks = <&sys_clkin>, <&dpll_core_m3x2_ck>, <&dpll_per_m3x2_ck>; ++ bit-shift = <1>; ++ reg = <0x4ae0a314 0x4>; ++ bit-mask = <0x3>; ++}; ++ ++auxclk1_src_ck: auxclk1_src_ck@4ae0a314 { ++ #clock-cells = <0>; ++ compatible = "gate-clock"; ++ clocks = <&auxclk1_src_mux_ck>; ++ bit-shift = <8>; ++ reg = <0x4ae0a314 0x4>; ++}; ++ ++auxclk1_ck: auxclk1_ck@4ae0a314 { ++ #clock-cells = <0>; ++ compatible = "divider-clock"; ++ clocks = <&auxclk1_src_ck>; ++ bit-shift = <16>; ++ reg = <0x4ae0a314 0x4>; ++ bit-mask = <0xf>; ++}; ++ ++auxclk2_src_mux_ck: auxclk2_src_mux_ck@4ae0a318 { ++ #clock-cells = <0>; ++ compatible = "mux-clock"; ++ clocks = <&sys_clkin>, <&dpll_core_m3x2_ck>, <&dpll_per_m3x2_ck>; ++ bit-shift = <1>; ++ reg = <0x4ae0a318 0x4>; ++ bit-mask = <0x3>; ++}; ++ ++auxclk2_src_ck: auxclk2_src_ck@4ae0a318 { ++ #clock-cells = <0>; ++ compatible = "gate-clock"; ++ clocks = <&auxclk2_src_mux_ck>; ++ bit-shift = <8>; ++ reg = <0x4ae0a318 0x4>; ++}; ++ ++auxclk2_ck: auxclk2_ck@4ae0a318 { ++ #clock-cells = <0>; ++ compatible = "divider-clock"; ++ clocks = <&auxclk2_src_ck>; ++ bit-shift = <16>; ++ reg = <0x4ae0a318 0x4>; ++ bit-mask = <0xf>; ++}; ++ ++auxclk3_src_mux_ck: auxclk3_src_mux_ck@4ae0a31c { ++ #clock-cells = <0>; ++ compatible = "mux-clock"; ++ clocks = <&sys_clkin>, <&dpll_core_m3x2_ck>, <&dpll_per_m3x2_ck>; ++ bit-shift = <1>; ++ reg = <0x4ae0a31c 0x4>; ++ bit-mask = <0x3>; ++}; ++ ++auxclk3_src_ck: auxclk3_src_ck@4ae0a31c { ++ #clock-cells = <0>; ++ compatible = "gate-clock"; ++ clocks = <&auxclk3_src_mux_ck>; ++ bit-shift = <8>; ++ reg = <0x4ae0a31c 0x4>; ++}; ++ ++auxclk3_ck: auxclk3_ck@4ae0a31c { ++ #clock-cells = <0>; ++ compatible = "divider-clock"; ++ clocks = <&auxclk3_src_ck>; ++ bit-shift = <16>; ++ reg = <0x4ae0a31c 0x4>; ++ bit-mask = <0xf>; ++}; ++ ++auxclk4_src_mux_ck: auxclk4_src_mux_ck@4ae0a320 { ++ #clock-cells = <0>; ++ compatible = "mux-clock"; ++ clocks = <&sys_clkin>, <&dpll_core_m3x2_ck>, <&dpll_per_m3x2_ck>; ++ bit-shift = <1>; ++ reg = <0x4ae0a320 0x4>; ++ bit-mask = <0x3>; ++}; ++ ++auxclk4_src_ck: auxclk4_src_ck@4ae0a320 { ++ #clock-cells = <0>; ++ compatible = "gate-clock"; ++ clocks = <&auxclk4_src_mux_ck>; ++ bit-shift = <8>; ++ reg = <0x4ae0a320 0x4>; ++}; ++ ++auxclk4_ck: auxclk4_ck@4ae0a320 { ++ #clock-cells = <0>; ++ compatible = "divider-clock"; ++ clocks = <&auxclk4_src_ck>; ++ bit-shift = <16>; ++ reg = <0x4ae0a320 0x4>; ++ bit-mask = <0xf>; ++}; ++ ++auxclkreq0_ck: auxclkreq0_ck@4ae0a210 { ++ #clock-cells = <0>; ++ compatible = "mux-clock"; ++ clocks = <&auxclk0_ck>, <&auxclk1_ck>, <&auxclk2_ck>, <&auxclk3_ck>, <&auxclk4_ck>; ++ bit-shift = <2>; ++ reg = <0x4ae0a210 0x4>; ++ bit-mask = <0x7>; ++}; ++ ++auxclkreq1_ck: auxclkreq1_ck@4ae0a214 { ++ #clock-cells = <0>; ++ compatible = "mux-clock"; ++ clocks = <&auxclk0_ck>, <&auxclk1_ck>, <&auxclk2_ck>, <&auxclk3_ck>, <&auxclk4_ck>; ++ bit-shift = <2>; ++ reg = <0x4ae0a214 0x4>; ++ bit-mask = <0x7>; ++}; ++ ++auxclkreq2_ck: auxclkreq2_ck@4ae0a218 { ++ #clock-cells = <0>; ++ compatible = "mux-clock"; ++ clocks = <&auxclk0_ck>, <&auxclk1_ck>, <&auxclk2_ck>, <&auxclk3_ck>, <&auxclk4_ck>; ++ bit-shift = <2>; ++ reg = <0x4ae0a218 0x4>; ++ bit-mask = <0x7>; ++}; ++ ++auxclkreq3_ck: auxclkreq3_ck@4ae0a21c { ++ #clock-cells = <0>; ++ compatible = "mux-clock"; ++ clocks = <&auxclk0_ck>, <&auxclk1_ck>, <&auxclk2_ck>, <&auxclk3_ck>, <&auxclk4_ck>; ++ bit-shift = <2>; ++ reg = <0x4ae0a21c 0x4>; ++ bit-mask = <0x7>; ++}; +--- a/arch/arm/boot/dts/omap5.dtsi ++++ b/arch/arm/boot/dts/omap5.dtsi +@@ -21,6 +21,11 @@ + interrupt-parent = <&gic>; + + aliases { ++ i2c0 = &i2c1; ++ i2c1 = &i2c2; ++ i2c2 = &i2c3; ++ i2c3 = &i2c4; ++ i2c4 = &i2c5; + serial0 = &uart1; + serial1 = &uart2; + serial2 = &uart3; +@@ -33,10 +38,23 @@ + #address-cells = <1>; + #size-cells = <0>; + +- cpu@0 { ++ cpu0: cpu@0 { + device_type = "cpu"; + compatible = "arm,cortex-a15"; + reg = <0x0>; ++ ++ operating-points = < ++ /* kHz uV */ ++ 500000 880000 ++ 1000000 1060000 ++ 1500000 1250000 ++ >; ++ ++ clocks = <&dpll_mpu_ck>; ++ clock-names = "cpu"; ++ ++ clock-latency = <300000>; /* From omap-cpufreq driver */ ++ + }; + cpu@1 { + device_type = "cpu"; +@@ -52,7 +70,6 @@ + <GIC_PPI 14 (GIC_CPU_MASK_RAW(3) | IRQ_TYPE_LEVEL_LOW)>, + <GIC_PPI 11 (GIC_CPU_MASK_RAW(3) | IRQ_TYPE_LEVEL_LOW)>, + <GIC_PPI 10 (GIC_CPU_MASK_RAW(3) | IRQ_TYPE_LEVEL_LOW)>; +- clock-frequency = <6144000>; + }; + + gic: interrupt-controller@48211000 { +@@ -100,6 +117,8 @@ + compatible = "ti,omap-counter32k"; + reg = <0x4ae04000 0x40>; + ti,hwmods = "counter_32k"; ++ clocks = <&wkupaon_iclk_mux>; ++ clock-names = "fck"; + }; + + omap5_pmx_core: pinmux@4a002840 { +@@ -129,6 +148,8 @@ + #dma-cells = <1>; + #dma-channels = <32>; + #dma-requests = <127>; ++ clocks = <&l3_iclk_div>; ++ clock-names = "fck"; + }; + + gpio1: gpio@4ae10000 { +@@ -136,6 +157,8 @@ + reg = <0x4ae10000 0x200>; + interrupts = <GIC_SPI 29 IRQ_TYPE_LEVEL_HIGH>; + ti,hwmods = "gpio1"; ++ clocks = <&wkupaon_iclk_mux>, <&gpio1_dbclk>; ++ clock-names = "fck", "dbclk"; + ti,gpio-always-on; + gpio-controller; + #gpio-cells = <2>; +@@ -148,6 +171,8 @@ + reg = <0x48055000 0x200>; + interrupts = <GIC_SPI 30 IRQ_TYPE_LEVEL_HIGH>; + ti,hwmods = "gpio2"; ++ clocks = <&l4_root_clk_div>, <&gpio2_dbclk>; ++ clock-names = "fck", "dbclk"; + gpio-controller; + #gpio-cells = <2>; + interrupt-controller; +@@ -159,6 +184,8 @@ + reg = <0x48057000 0x200>; + interrupts = <GIC_SPI 31 IRQ_TYPE_LEVEL_HIGH>; + ti,hwmods = "gpio3"; ++ clocks = <&l4_root_clk_div>, <&gpio3_dbclk>; ++ clock-names = "fck", "dbclk"; + gpio-controller; + #gpio-cells = <2>; + interrupt-controller; +@@ -170,6 +197,8 @@ + reg = <0x48059000 0x200>; + interrupts = <GIC_SPI 32 IRQ_TYPE_LEVEL_HIGH>; + ti,hwmods = "gpio4"; ++ clocks = <&l4_root_clk_div>, <&gpio4_dbclk>; ++ clock-names = "fck", "dbclk"; + gpio-controller; + #gpio-cells = <2>; + interrupt-controller; +@@ -181,6 +210,8 @@ + reg = <0x4805b000 0x200>; + interrupts = <GIC_SPI 33 IRQ_TYPE_LEVEL_HIGH>; + ti,hwmods = "gpio5"; ++ clocks = <&l4_root_clk_div>, <&gpio5_dbclk>; ++ clock-names = "fck", "dbclk"; + gpio-controller; + #gpio-cells = <2>; + interrupt-controller; +@@ -192,6 +223,8 @@ + reg = <0x4805d000 0x200>; + interrupts = <GIC_SPI 34 IRQ_TYPE_LEVEL_HIGH>; + ti,hwmods = "gpio6"; ++ clocks = <&l4_root_clk_div>, <&gpio6_dbclk>; ++ clock-names = "fck", "dbclk"; + gpio-controller; + #gpio-cells = <2>; + interrupt-controller; +@@ -203,6 +236,8 @@ + reg = <0x48051000 0x200>; + interrupts = <GIC_SPI 35 IRQ_TYPE_LEVEL_HIGH>; + ti,hwmods = "gpio7"; ++ clocks = <&l4_root_clk_div>, <&gpio7_dbclk>; ++ clock-names = "fck", "dbclk"; + gpio-controller; + #gpio-cells = <2>; + interrupt-controller; +@@ -214,6 +249,8 @@ + reg = <0x48053000 0x200>; + interrupts = <GIC_SPI 121 IRQ_TYPE_LEVEL_HIGH>; + ti,hwmods = "gpio8"; ++ clocks = <&l4_root_clk_div>, <&gpio8_dbclk>; ++ clock-names = "fck", "dbclk"; + gpio-controller; + #gpio-cells = <2>; + interrupt-controller; +@@ -238,6 +275,9 @@ + #address-cells = <1>; + #size-cells = <0>; + ti,hwmods = "i2c1"; ++ clocks = <&func_96m_fclk>; ++ clock-names = "fck"; ++ status = "disabled"; + }; + + i2c2: i2c@48072000 { +@@ -247,6 +287,9 @@ + #address-cells = <1>; + #size-cells = <0>; + ti,hwmods = "i2c2"; ++ clocks = <&func_96m_fclk>; ++ clock-names = "fck"; ++ status = "disabled"; + }; + + i2c3: i2c@48060000 { +@@ -256,6 +299,9 @@ + #address-cells = <1>; + #size-cells = <0>; + ti,hwmods = "i2c3"; ++ clocks = <&func_96m_fclk>; ++ clock-names = "fck"; ++ status = "disabled"; + }; + + i2c4: i2c@4807a000 { +@@ -265,6 +311,9 @@ + #address-cells = <1>; + #size-cells = <0>; + ti,hwmods = "i2c4"; ++ clocks = <&func_96m_fclk>; ++ clock-names = "fck"; ++ status = "disabled"; + }; + + i2c5: i2c@4807c000 { +@@ -274,6 +323,9 @@ + #address-cells = <1>; + #size-cells = <0>; + ti,hwmods = "i2c5"; ++ clocks = <&func_96m_fclk>; ++ clock-names = "fck"; ++ status = "disabled"; + }; + + mcspi1: spi@48098000 { +@@ -283,6 +335,8 @@ + #address-cells = <1>; + #size-cells = <0>; + ti,hwmods = "mcspi1"; ++ clocks = <&func_48m_fclk>; ++ clock-names = "fck"; + ti,spi-num-cs = <4>; + dmas = <&sdma 35>, + <&sdma 36>, +@@ -294,6 +348,7 @@ + <&sdma 42>; + dma-names = "tx0", "rx0", "tx1", "rx1", + "tx2", "rx2", "tx3", "rx3"; ++ status = "disabled"; + }; + + mcspi2: spi@4809a000 { +@@ -303,12 +358,15 @@ + #address-cells = <1>; + #size-cells = <0>; + ti,hwmods = "mcspi2"; ++ clocks = <&func_48m_fclk>; ++ clock-names = "fck"; + ti,spi-num-cs = <2>; + dmas = <&sdma 43>, + <&sdma 44>, + <&sdma 45>, + <&sdma 46>; + dma-names = "tx0", "rx0", "tx1", "rx1"; ++ status = "disabled"; + }; + + mcspi3: spi@480b8000 { +@@ -318,9 +376,12 @@ + #address-cells = <1>; + #size-cells = <0>; + ti,hwmods = "mcspi3"; ++ clocks = <&func_48m_fclk>; ++ clock-names = "fck"; + ti,spi-num-cs = <2>; + dmas = <&sdma 15>, <&sdma 16>; + dma-names = "tx0", "rx0"; ++ status = "disabled"; + }; + + mcspi4: spi@480ba000 { +@@ -330,9 +391,12 @@ + #address-cells = <1>; + #size-cells = <0>; + ti,hwmods = "mcspi4"; ++ clocks = <&func_48m_fclk>; ++ clock-names = "fck"; + ti,spi-num-cs = <1>; + dmas = <&sdma 70>, <&sdma 71>; + dma-names = "tx0", "rx0"; ++ status = "disabled"; + }; + + uart1: serial@4806a000 { +@@ -340,7 +404,10 @@ + reg = <0x4806a000 0x100>; + interrupts = <GIC_SPI 72 IRQ_TYPE_LEVEL_HIGH>; + ti,hwmods = "uart1"; ++ clocks = <&func_48m_fclk>; ++ clock-names = "fck"; + clock-frequency = <48000000>; ++ status = "disabled"; + }; + + uart2: serial@4806c000 { +@@ -348,7 +415,10 @@ + reg = <0x4806c000 0x100>; + interrupts = <GIC_SPI 73 IRQ_TYPE_LEVEL_HIGH>; + ti,hwmods = "uart2"; ++ clocks = <&func_48m_fclk>; ++ clock-names = "fck"; + clock-frequency = <48000000>; ++ status = "disabled"; + }; + + uart3: serial@48020000 { +@@ -356,7 +426,10 @@ + reg = <0x48020000 0x100>; + interrupts = <GIC_SPI 74 IRQ_TYPE_LEVEL_HIGH>; + ti,hwmods = "uart3"; ++ clocks = <&func_48m_fclk>; ++ clock-names = "fck"; + clock-frequency = <48000000>; ++ status = "disabled"; + }; + + uart4: serial@4806e000 { +@@ -364,7 +437,10 @@ + reg = <0x4806e000 0x100>; + interrupts = <GIC_SPI 70 IRQ_TYPE_LEVEL_HIGH>; + ti,hwmods = "uart4"; ++ clocks = <&func_48m_fclk>; ++ clock-names = "fck"; + clock-frequency = <48000000>; ++ status = "disabled"; + }; + + uart5: serial@48066000 { +@@ -372,7 +448,10 @@ + reg = <0x48066000 0x100>; + interrupts = <GIC_SPI 105 IRQ_TYPE_LEVEL_HIGH>; + ti,hwmods = "uart5"; ++ clocks = <&func_48m_fclk>; ++ clock-names = "fck"; + clock-frequency = <48000000>; ++ status = "disabled"; + }; + + uart6: serial@48068000 { +@@ -380,7 +459,10 @@ + reg = <0x48068000 0x100>; + interrupts = <GIC_SPI 106 IRQ_TYPE_LEVEL_HIGH>; + ti,hwmods = "uart6"; ++ clocks = <&func_48m_fclk>; ++ clock-names = "fck"; + clock-frequency = <48000000>; ++ status = "disabled"; + }; + + mmc1: mmc@4809c000 { +@@ -388,6 +470,8 @@ + reg = <0x4809c000 0x400>; + interrupts = <GIC_SPI 83 IRQ_TYPE_LEVEL_HIGH>; + ti,hwmods = "mmc1"; ++ clocks = <&mmc1_fclk>, <&mmc1_32khz_clk>; ++ clock-names = "fck", "32khz_clk"; + ti,dual-volt; + ti,needs-special-reset; + dmas = <&sdma 61>, <&sdma 62>; +@@ -399,6 +483,8 @@ + reg = <0x480b4000 0x400>; + interrupts = <GIC_SPI 86 IRQ_TYPE_LEVEL_HIGH>; + ti,hwmods = "mmc2"; ++ clocks = <&mmc2_fclk>; ++ clock-names = "fck"; + ti,needs-special-reset; + dmas = <&sdma 47>, <&sdma 48>; + dma-names = "tx", "rx"; +@@ -409,6 +495,8 @@ + reg = <0x480ad000 0x400>; + interrupts = <GIC_SPI 94 IRQ_TYPE_LEVEL_HIGH>; + ti,hwmods = "mmc3"; ++ clocks = <&func_48m_fclk>; ++ clock-names = "fck"; + ti,needs-special-reset; + dmas = <&sdma 77>, <&sdma 78>; + dma-names = "tx", "rx"; +@@ -419,6 +507,8 @@ + reg = <0x480d1000 0x400>; + interrupts = <GIC_SPI 96 IRQ_TYPE_LEVEL_HIGH>; + ti,hwmods = "mmc4"; ++ clocks = <&func_48m_fclk>; ++ clock-names = "fck"; + ti,needs-special-reset; + dmas = <&sdma 57>, <&sdma 58>; + dma-names = "tx", "rx"; +@@ -429,15 +519,63 @@ + reg = <0x480d5000 0x400>; + interrupts = <GIC_SPI 59 IRQ_TYPE_LEVEL_HIGH>; + ti,hwmods = "mmc5"; ++ clocks = <&func_96m_fclk>; ++ clock-names = "fck"; + ti,needs-special-reset; + dmas = <&sdma 59>, <&sdma 60>; + dma-names = "tx", "rx"; + }; + ++ omap_control_sata: control-phy@4a002374 { ++ compatible = "ti,control-phy-pipe3"; ++ reg = <0x4a002374 0x4>; ++ reg-names = "power"; ++ clocks = <&sys_clkin>; ++ clock-names = "sysclk"; ++ }; ++ ++ ocp2scp@4a090000 { ++ compatible = "ti,omap-ocp2scp"; ++ #address-cells = <1>; ++ #size-cells = <1>; ++ ranges; ++ ti,hwmods = "ocp2scp3"; ++ reg = <0x4a090000 0x1c>; /* ocp2scp3 */ ++ sata_phy: sata-phy@4A096000 { ++ compatible = "ti,phy-pipe3-sata"; ++ reg = <0x4A096000 0x80>, /* phy_rx */ ++ <0x4A096400 0x64>, /* phy_tx */ ++ <0x4A096800 0x40>; /* pll_ctrl */ ++ reg-names = "phy_rx", "phy_tx", "pll_ctrl"; ++ ctrl-module = <&omap_control_sata>; ++ #phy-cells = <0>; ++ clocks = <&sata_ref_clk>; ++ clock-names = "refclk"; ++ }; ++ }; ++ ++ sata@4a141100 { ++ compatible = "ti,sata"; ++ ti,hwmods = "sata"; ++ reg = <0x4a141100 0x100>; ++ #address-cells = <1>; ++ #size-cells = <1>; ++ ranges; ++ sata@4a140000 { ++ compatible = "snps,dwc-ahci"; ++ reg = <0x4a140000 0x1100>; ++ interrupts = <GIC_SPI 54 IRQ_TYPE_LEVEL_HIGH>; ++ phys = <&sata_phy>; ++ phy-names = "sata-phy"; ++ }; ++ }; ++ + keypad: keypad@4ae1c000 { + compatible = "ti,omap4-keypad"; + reg = <0x4ae1c000 0x400>; + ti,hwmods = "kbd"; ++ clocks = <&sys_32k_ck>; ++ clock-names = "fck"; + }; + + mcpdm: mcpdm@40132000 { +@@ -447,6 +585,8 @@ + reg-names = "mpu", "dma"; + interrupts = <GIC_SPI 112 IRQ_TYPE_LEVEL_HIGH>; + ti,hwmods = "mcpdm"; ++ clocks = <&pad_clks_ck>; ++ clock-names = "fck"; + dmas = <&sdma 65>, + <&sdma 66>; + dma-names = "up_link", "dn_link"; +@@ -459,6 +599,8 @@ + reg-names = "mpu", "dma"; + interrupts = <GIC_SPI 114 IRQ_TYPE_LEVEL_HIGH>; + ti,hwmods = "dmic"; ++ clocks = <&dmic_gfclk>; ++ clock-names = "fck"; + dmas = <&sdma 67>; + dma-names = "up_link"; + }; +@@ -472,6 +614,8 @@ + interrupt-names = "common"; + ti,buffer-size = <128>; + ti,hwmods = "mcbsp1"; ++ clocks = <&mcbsp1_gfclk>, <&pad_clks_ck>, <&mcbsp1_sync_mux_ck>; ++ clock-names = "fck", "pad_fck", "prcm_fck"; + dmas = <&sdma 33>, + <&sdma 34>; + dma-names = "tx", "rx"; +@@ -486,6 +630,8 @@ + interrupt-names = "common"; + ti,buffer-size = <128>; + ti,hwmods = "mcbsp2"; ++ clocks = <&mcbsp2_gfclk>, <&pad_clks_ck>, <&mcbsp2_sync_mux_ck>; ++ clock-names = "fck", "pad_fck", "prcm_fck"; + dmas = <&sdma 17>, + <&sdma 18>; + dma-names = "tx", "rx"; +@@ -500,16 +646,31 @@ + interrupt-names = "common"; + ti,buffer-size = <128>; + ti,hwmods = "mcbsp3"; ++ clocks = <&mcbsp3_gfclk>, <&pad_clks_ck>, <&mcbsp3_sync_mux_ck>; ++ clock-names = "fck", "pad_fck", "prcm_fck"; + dmas = <&sdma 19>, + <&sdma 20>; + dma-names = "tx", "rx"; + }; + ++ mailbox: mailbox@4a0f4000 { ++ compatible = "ti,omap4-mailbox"; ++ reg = <0x4a0f4000 0x200>; ++ interrupts = <GIC_SPI 26 IRQ_TYPE_LEVEL_HIGH>; ++ ti,hwmods = "mailbox"; ++ ti,mbox-num-users = <3>; ++ ti,mbox-num-fifos = <8>; ++ ti,mbox-names = "mbox-ipu", "mbox-dsp"; ++ ti,mbox-data = <0 1 0 0>, <3 2 0 0>; ++ }; ++ + timer1: timer@4ae18000 { + compatible = "ti,omap5430-timer"; + reg = <0x4ae18000 0x80>; + interrupts = <GIC_SPI 37 IRQ_TYPE_LEVEL_HIGH>; + ti,hwmods = "timer1"; ++ clocks = <&timer1_gfclk_mux>; ++ clock-names = "fck"; + ti,timer-alwon; + }; + +@@ -518,6 +679,8 @@ + reg = <0x48032000 0x80>; + interrupts = <GIC_SPI 38 IRQ_TYPE_LEVEL_HIGH>; + ti,hwmods = "timer2"; ++ clocks = <&timer2_gfclk_mux>; ++ clock-names = "fck"; + }; + + timer3: timer@48034000 { +@@ -525,6 +688,8 @@ + reg = <0x48034000 0x80>; + interrupts = <GIC_SPI 39 IRQ_TYPE_LEVEL_HIGH>; + ti,hwmods = "timer3"; ++ clocks = <&timer3_gfclk_mux>; ++ clock-names = "fck"; + }; + + timer4: timer@48036000 { +@@ -532,6 +697,8 @@ + reg = <0x48036000 0x80>; + interrupts = <GIC_SPI 40 IRQ_TYPE_LEVEL_HIGH>; + ti,hwmods = "timer4"; ++ clocks = <&timer4_gfclk_mux>; ++ clock-names = "fck"; + }; + + timer5: timer@40138000 { +@@ -540,6 +707,8 @@ + <0x49038000 0x80>; + interrupts = <GIC_SPI 41 IRQ_TYPE_LEVEL_HIGH>; + ti,hwmods = "timer5"; ++ clocks = <&timer5_gfclk_mux>; ++ clock-names = "fck"; + ti,timer-dsp; + ti,timer-pwm; + }; +@@ -550,6 +719,8 @@ + <0x4903a000 0x80>; + interrupts = <GIC_SPI 42 IRQ_TYPE_LEVEL_HIGH>; + ti,hwmods = "timer6"; ++ clocks = <&timer6_gfclk_mux>; ++ clock-names = "fck"; + ti,timer-dsp; + ti,timer-pwm; + }; +@@ -560,6 +731,8 @@ + <0x4903c000 0x80>; + interrupts = <GIC_SPI 43 IRQ_TYPE_LEVEL_HIGH>; + ti,hwmods = "timer7"; ++ clocks = <&timer7_gfclk_mux>; ++ clock-names = "fck"; + ti,timer-dsp; + }; + +@@ -569,6 +742,8 @@ + <0x4903e000 0x80>; + interrupts = <GIC_SPI 44 IRQ_TYPE_LEVEL_HIGH>; + ti,hwmods = "timer8"; ++ clocks = <&timer8_gfclk_mux>; ++ clock-names = "fck"; + ti,timer-dsp; + ti,timer-pwm; + }; +@@ -578,6 +753,8 @@ + reg = <0x4803e000 0x80>; + interrupts = <GIC_SPI 45 IRQ_TYPE_LEVEL_HIGH>; + ti,hwmods = "timer9"; ++ clocks = <&timer9_gfclk_mux>; ++ clock-names = "fck"; + ti,timer-pwm; + }; + +@@ -586,6 +763,8 @@ + reg = <0x48086000 0x80>; + interrupts = <GIC_SPI 46 IRQ_TYPE_LEVEL_HIGH>; + ti,hwmods = "timer10"; ++ clocks = <&timer10_gfclk_mux>; ++ clock-names = "fck"; + ti,timer-pwm; + }; + +@@ -594,19 +773,33 @@ + reg = <0x48088000 0x80>; + interrupts = <GIC_SPI 47 IRQ_TYPE_LEVEL_HIGH>; + ti,hwmods = "timer11"; ++ clocks = <&timer11_gfclk_mux>; ++ clock-names = "fck"; + ti,timer-pwm; + }; + + wdt2: wdt@4ae14000 { +- compatible = "ti,omap5-wdt", "ti,omap3-wdt"; ++ compatible = "ti,omap5-wdt", "ti,omap4-wdt"; + reg = <0x4ae14000 0x80>; + interrupts = <GIC_SPI 80 IRQ_TYPE_LEVEL_HIGH>; + ti,hwmods = "wd_timer2"; ++ clocks = <&sys_32k_ck>; ++ clock-names = "fck"; ++ }; ++ ++ dmm: dmm@4e000000 { ++ compatible = "ti,omap5-dmm"; ++ reg = <0x4e000000 0x800>; ++ interrupts = <0 113 0x4>; ++ ti,hwmods = "dmm"; + }; + + emif1: emif@0x4c000000 { + compatible = "ti,emif-4d5"; + ti,hwmods = "emif1"; ++ ti,no-idle; ++ clocks = <&dpll_core_h11x2_ck>; ++ clock-names = "fck"; + phy-type = <2>; /* DDR PHY type: Intelli PHY */ + reg = <0x4c000000 0x400>; + interrupts = <GIC_SPI 110 IRQ_TYPE_LEVEL_HIGH>; +@@ -618,6 +811,9 @@ + emif2: emif@0x4d000000 { + compatible = "ti,emif-4d5"; + ti,hwmods = "emif2"; ++ ti,no-idle; ++ clocks = <&dpll_core_h11x2_ck>; ++ clock-names = "fck"; + phy-type = <2>; /* DDR PHY type: Intelli PHY */ + reg = <0x4d000000 0x400>; + interrupts = <GIC_SPI 111 IRQ_TYPE_LEVEL_HIGH>; +@@ -626,18 +822,25 @@ + hw-caps-temp-alert; + }; + +- omap_control_usb: omap-control-usb@4a002300 { +- compatible = "ti,omap-control-usb"; +- reg = <0x4a002300 0x4>, +- <0x4a002370 0x4>; +- reg-names = "control_dev_conf", "phy_power_usb"; +- ti,type = <2>; ++ omap_control_usb2phy: control-phy@4a002300 { ++ compatible = "ti,control-phy-usb2"; ++ reg = <0x4a002300 0x4>; ++ reg-names = "power"; ++ }; ++ ++ omap_control_usb3phy: control-phy@4a002370 { ++ compatible = "ti,control-phy-pipe3"; ++ reg = <0x4a002370 0x4>; ++ reg-names = "power"; + }; + +- omap_dwc3@4a020000 { ++ usb3: omap_dwc3@4a020000 { + compatible = "ti,dwc3"; + ti,hwmods = "usb_otg_ss"; ++ clocks = <&dpll_core_h13x2_ck>, <&usb_otg_ss_refclk960m>; ++ clock-names = "fck", "refclk960m"; + reg = <0x4a020000 0x10000>; ++ + interrupts = <GIC_SPI 93 IRQ_TYPE_LEVEL_HIGH>; + #address-cells = <1>; + #size-cells = <1>; +@@ -647,7 +850,10 @@ + compatible = "snps,dwc3"; + reg = <0x4a030000 0x10000>; + interrupts = <GIC_SPI 92 IRQ_TYPE_LEVEL_HIGH>; +- usb-phy = <&usb2_phy>, <&usb3_phy>; ++ phys = <&usb2_phy>, <&usb3_phy>; ++ phy-names = "usb2-phy", "usb3-phy"; ++ maximum-speed = "super-speed"; ++ dr_mode = "peripheral"; + tx-fifo-resize; + }; + }; +@@ -662,16 +868,26 @@ + usb2_phy: usb2phy@4a084000 { + compatible = "ti,omap-usb2"; + reg = <0x4a084000 0x7c>; +- ctrl-module = <&omap_control_usb>; ++ ctrl-module = <&omap_control_usb2phy>; ++ clocks = <&usb_phy_cm_clk32k>, <&usb_otg_ss_refclk960m>; ++ clock-names = "wkupclk", "refclk"; ++ #phy-cells = <0>; + }; + + usb3_phy: usb3phy@4a084400 { +- compatible = "ti,omap-usb3"; ++ compatible = "ti,phy-pipe3-usb3"; + reg = <0x4a084400 0x80>, + <0x4a084800 0x64>, + <0x4a084c00 0x40>; + reg-names = "phy_rx", "phy_tx", "pll_ctrl"; +- ctrl-module = <&omap_control_usb>; ++ ctrl-module = <&omap_control_usb3phy>; ++ clocks = <&usb_phy_cm_clk32k>, ++ <&usb_otg_ss_refclk960m>, ++ <&dpll_core_h13x2_ck>; ++ clock-names = "wkupclk", ++ "refclk", ++ "refclk2"; ++ #phy-cells = <0>; + }; + }; + +@@ -689,6 +905,8 @@ + #address-cells = <1>; + #size-cells = <1>; + ranges; ++ clocks = <&l3init_60m_fclk>; ++ clock-names = "init_60m_fclk"; + + usbhsohci: ohci@4a064800 { + compatible = "ti,ohci-omap3", "usb-ohci"; +@@ -713,5 +931,71 @@ + interrupts = <GIC_SPI 126 IRQ_TYPE_LEVEL_HIGH>; + compatible = "ti,omap5430-bandgap"; + }; ++ ++ dss@58000000 { ++ compatible = "ti,omap4-dss", "simple-bus"; ++ reg = <0x58000000 0x80>; ++ ti,hwmods = "dss_core"; ++ #address-cells = <1>; ++ #size-cells = <1>; ++ ranges; ++ ++ dispc@58001000 { ++ compatible = "ti,omap4-dispc"; ++ reg = <0x58001000 0x1000>; ++ interrupts = <0 25 0x4>; ++ ti,hwmods = "dss_dispc"; ++ }; ++ ++ dpi: encoder@0 { ++ compatible = "ti,omap4-dpi"; ++ }; ++ ++ rfbi: encoder@58002000 { ++ compatible = "ti,omap4-rfbi"; ++ reg = <0x58002000 0x1000>; ++ ti,hwmods = "dss_rfbi"; ++ }; ++ ++ dsi1: encoder@58004000 { ++ compatible = "ti,omap4-dsi"; ++ reg = <0x58004000 0x200>; ++ interrupts = <0 53 0x4>; ++ ti,hwmods = "dss_dsi1"; ++ }; ++ ++ dsi2: encoder@58005000 { ++ compatible = "ti,omap4-dsi"; ++ reg = <0x58005000 0x200>; ++ interrupts = <0 84 0x4>; ++ ti,hwmods = "dss_dsi2"; ++ }; ++ ++ hdmi: encoder@58060000 { ++ compatible = "ti,omap5-hdmi"; ++ reg = <0x58040000 0x200>, ++ <0x58040200 0x100>, ++ <0x58040300 0x100>, ++ <0x58060000 0x19000>; ++ reg-names = "hdmi_wp", "hdmi_pllctrl", ++ "hdmi_txphy", "hdmi_core"; ++ interrupts = <0 101 0x4>; ++ ti,hwmods = "dss_hdmi"; ++ }; ++ }; ++ }; ++ ++ clocks { ++ #address-cells = <1>; ++ #size-cells = <1>; ++ ranges; ++ /include/ "omap54xx-clocks.dtsi" ++ }; ++ ++ clockdomains { ++ l3init_clkdm: l3init_clkdm { ++ compatible = "ti,clockdomain"; ++ clocks = <&dpll_usb_ck>; ++ }; + }; + }; +--- a/arch/arm/boot/dts/omap5-uevm.dts ++++ b/arch/arm/boot/dts/omap5-uevm.dts +@@ -27,45 +27,19 @@ + regulator-max-microvolt = <3000000>; + }; + +- /* HS USB Port 2 RESET */ +- hsusb2_reset: hsusb2_reset_reg { +- compatible = "regulator-fixed"; +- regulator-name = "hsusb2_reset"; +- regulator-min-microvolt = <3300000>; +- regulator-max-microvolt = <3300000>; +- gpio = <&gpio3 16 GPIO_ACTIVE_HIGH>; /* gpio3_80 HUB_NRESET */ +- startup-delay-us = <70000>; +- enable-active-high; +- }; +- + /* HS USB Host PHY on PORT 2 */ + hsusb2_phy: hsusb2_phy { + compatible = "usb-nop-xceiv"; +- reset-supply = <&hsusb2_reset>; +- /** +- * FIXME +- * Put the right clock phandle here when available +- * clocks = <&auxclk1>; +- * clock-names = "main_clk"; +- */ ++ reset-gpios = <&gpio3 16 GPIO_ACTIVE_LOW>; /* gpio3_80 HUB_NRESET */ ++ clocks = <&auxclk1_ck>; ++ clock-names = "main_clk"; + clock-frequency = <19200000>; + }; + +- /* HS USB Port 3 RESET */ +- hsusb3_reset: hsusb3_reset_reg { +- compatible = "regulator-fixed"; +- regulator-name = "hsusb3_reset"; +- regulator-min-microvolt = <3300000>; +- regulator-max-microvolt = <3300000>; +- gpio = <&gpio3 15 GPIO_ACTIVE_HIGH>; /* gpio3_79 ETH_NRESET */ +- startup-delay-us = <70000>; +- enable-active-high; +- }; +- + /* HS USB Host PHY on PORT 3 */ + hsusb3_phy: hsusb3_phy { + compatible = "usb-nop-xceiv"; +- reset-supply = <&hsusb3_reset>; ++ reset-gpios = <&gpio3 15 GPIO_ACTIVE_LOW>; /* gpio3_79 ETH_NRESET */ + }; + + leds { +@@ -77,6 +51,28 @@ + default-state = "off"; + }; + }; ++ ++ sound: sound { ++ compatible = "ti,abe-twl6040"; ++ ti,model = "omap5-uevm"; ++ ++ ti,mclk-freq = <19200000>; ++ ++ ti,mcpdm = <&mcpdm>; ++ ++ ti,twl6040 = <&twl6040>; ++ ++ /* Audio routing */ ++ ti,audio-routing = ++ "Headset Stereophone", "HSOL", ++ "Headset Stereophone", "HSOR", ++ "Line Out", "AUXL", ++ "Line Out", "AUXR", ++ "HSMIC", "Headset Mic", ++ "Headset Mic", "Headset Mic Bias", ++ "AFML", "Line In", ++ "AFMR", "Line In"; ++ }; + }; + + &omap5_pmx_core { +@@ -84,16 +80,18 @@ + pinctrl-0 = < + &twl6040_pins + &mcpdm_pins +- &dmic_pins + &mcbsp1_pins + &mcbsp2_pins + &usbhost_pins + &led_gpio_pins ++ &dss_hdmi_pins ++ &tpd12s015_pins ++ &palmas_pins + >; + + twl6040_pins: pinmux_twl6040_pins { + pinctrl-single,pins = < +- 0x18a (PIN_OUTPUT | MUX_MODE6) /* perslimbus2_clock.gpio5_145 */ ++ 0x17e (PIN_OUTPUT | MUX_MODE6) /* mcspi1_somi.gpio5_141 */ + >; + }; + +@@ -107,15 +105,6 @@ + >; + }; + +- dmic_pins: pinmux_dmic_pins { +- pinctrl-single,pins = < +- 0x144 (PIN_INPUT | MUX_MODE0) /* abedmic_din1.abedmic_din1 */ +- 0x146 (PIN_INPUT | MUX_MODE0) /* abedmic_din2.abedmic_din2 */ +- 0x148 (PIN_INPUT | MUX_MODE0) /* abedmic_din3.abedmic_din3 */ +- 0x14a (PIN_OUTPUT | MUX_MODE0) /* abedmic_clk1.abedmic_clk1 */ +- >; +- }; +- + mcbsp1_pins: pinmux_mcbsp1_pins { + pinctrl-single,pins = < + 0x14c (PIN_INPUT | MUX_MODE1) /* abedmic_clk2.abemcbsp1_fsx */ +@@ -143,8 +132,14 @@ + + i2c5_pins: pinmux_i2c5_pins { + pinctrl-single,pins = < +- 0x184 (PIN_INPUT | MUX_MODE0) /* i2c5_scl */ +- 0x186 (PIN_INPUT | MUX_MODE0) /* i2c5_sda */ ++ 0x186 (PIN_INPUT | MUX_MODE0) /* i2c5_scl */ ++ 0x188 (PIN_INPUT | MUX_MODE0) /* i2c5_sda */ ++ >; ++ }; ++ ++ mmc1_pins: pinmux_mmc1_pins { ++ pinctrl-single,pins = < ++ 0x194 (PIN_INPUT | MUX_MODE6) /* gpio5_152 */ + >; + }; + +@@ -153,25 +148,25 @@ + 0xbc (PIN_INPUT | MUX_MODE0) /* mcspi2_clk */ + 0xbe (PIN_INPUT | MUX_MODE0) /* mcspi2_simo */ + 0xc0 (PIN_INPUT_PULLUP | MUX_MODE0) /* mcspi2_somi */ +- 0xc2 (PIN_OUTPUT | MUX_MODE0) /* mcspi2_cs */ ++ 0xc2 (PIN_OUTPUT | MUX_MODE0) /* mcspi2_cs0 */ + >; + }; + + mcspi3_pins: pinmux_mcspi3_pins { + pinctrl-single,pins = < +- 0x78 (PIN_INPUT | MUX_MODE1) /* mcspi2_somi */ +- 0x7a (PIN_INPUT | MUX_MODE1) /* mcspi2_cs */ +- 0x7c (PIN_INPUT | MUX_MODE1) /* mcspi2_simo */ +- 0x7e (PIN_INPUT | MUX_MODE1) /* mcspi2_clk */ ++ 0x78 (PIN_INPUT | MUX_MODE1) /* mcspi3_somi */ ++ 0x7a (PIN_INPUT | MUX_MODE1) /* mcspi3_cs0 */ ++ 0x7c (PIN_INPUT | MUX_MODE1) /* mcspi3_simo */ ++ 0x7e (PIN_INPUT | MUX_MODE1) /* mcspi3_clk */ + >; + }; + + mcspi4_pins: pinmux_mcspi4_pins { + pinctrl-single,pins = < +- 0x164 (PIN_INPUT | MUX_MODE1) /* mcspi2_clk */ +- 0x168 (PIN_INPUT | MUX_MODE1) /* mcspi2_simo */ +- 0x16a (PIN_INPUT | MUX_MODE1) /* mcspi2_somi */ +- 0x16c (PIN_INPUT | MUX_MODE1) /* mcspi2_cs */ ++ 0x164 (PIN_INPUT | MUX_MODE1) /* mcspi4_clk */ ++ 0x168 (PIN_INPUT | MUX_MODE1) /* mcspi4_simo */ ++ 0x16a (PIN_INPUT | MUX_MODE1) /* mcspi4_somi */ ++ 0x16c (PIN_INPUT | MUX_MODE1) /* mcspi4_cs0 */ + >; + }; + +@@ -219,6 +214,25 @@ + >; + }; + ++ dss_hdmi_pins: pinmux_dss_hdmi_pins { ++ pinctrl-single,pins = < ++ 0x0fc (PIN_INPUT_PULLUP | MUX_MODE0) /* hdmi_cec.hdmi_cec */ ++ 0x100 (PIN_INPUT | MUX_MODE0) /* DDC-SCL */ ++ 0x102 (PIN_INPUT | MUX_MODE0) /* DDC-SDA */ ++ >; ++ }; ++ ++ tpd12s015_pins: pinmux_tpd12s015_pins { ++ pinctrl-single,pins = < ++ 0x0fe (PIN_INPUT_PULLDOWN | MUX_MODE6) /* hdmi_hpd.gpio7_193 */ ++ >; ++ }; ++ ++ palmas_pins: pinmux_palmas_pins { ++ pinctrl-single,pins = < ++ 0x140 (PIN_INPUT_PULLUP | MUX_MODE1) /* MSECURE */ ++ >; ++ }; + }; + + &omap5_pmx_wkup { +@@ -235,8 +249,11 @@ + }; + + &mmc1 { ++ pinctrl-names = "default"; ++ pinctrl-0 = <&mmc1_pins>; + vmmc-supply = <&ldo9_reg>; + bus-width = <4>; ++ cd-gpios = <&gpio5 24 0>; /* gpio 152 */ + }; + + &mmc2 { +@@ -259,6 +276,7 @@ + }; + + &i2c1 { ++ status = "okay"; + pinctrl-names = "default"; + pinctrl-0 = <&i2c1_pins>; + +@@ -272,6 +290,30 @@ + interrupt-controller; + #interrupt-cells = <2>; + ++ extcon_usb3: palmas_usb { ++ compatible = "ti,palmas-usb-vid"; ++ ti,enable-vbus-detection; ++ ti,enable-id-detection; ++ ti,wakeup; ++ }; ++ ++ palmas_rtc: rtc { ++ compatible = "ti,palmas-rtc"; ++ interrupt-parent = <&palmas>; ++ interrupts = <8 IRQ_TYPE_NONE>; ++ ti,backup-battery-chargeable; ++ }; ++ ++ clk32kg: palmas_clk32k@0 { ++ compatible = "ti,palmas-clk32kg"; ++ #clock-cells = <0>; ++ }; ++ ++ clk32kgaudio: palmas_clk32k@1 { ++ compatible = "ti,palmas-clk32kgaudio"; ++ #clock-cells = <0>; ++ }; ++ + palmas_pmic { + compatible = "ti,palmas-pmic"; + interrupt-parent = <&palmas>; +@@ -334,15 +376,22 @@ + ti,smps-range = <0x80>; + }; + +- smps10_reg: smps10 { ++ smps10_out2_reg: smps10_out2 { + /* VBUS_5V_OTG */ +- regulator-name = "smps10"; ++ regulator-name = "smps10_out2"; + regulator-min-microvolt = <5000000>; + regulator-max-microvolt = <5000000>; + regulator-always-on; + regulator-boot-on; + }; + ++ smps10_out1_reg: smps10_out1 { ++ /* VBUS_5V_OTG */ ++ regulator-name = "smps10_out1"; ++ regulator-min-microvolt = <5000000>; ++ regulator-max-microvolt = <5000000>; ++ }; ++ + ldo1_reg: ldo1 { + /* VDDAPHY_CAM: vdda_csiport */ + regulator-name = "ldo1"; +@@ -448,13 +497,37 @@ + }; + }; + }; ++ ++ twl6040: twl@4b { ++ compatible = "ti,twl6040"; ++ reg = <0x4b>; ++ ++ interrupts = <GIC_SPI 119 IRQ_TYPE_NONE>; /* IRQ_SYS_2N cascaded to gic */ ++ interrupt-parent = <&gic>; ++ ti,audpwron-gpio = <&gpio5 13 0>; /* gpio line 141 */ ++ ++ vio-supply = <&smps7_reg>; ++ v2v1-supply = <&smps9_reg>; ++ enable-active-high; ++ ++ clocks = <&clk32kgaudio>; ++ clock-names = "clk32k"; ++ }; + }; + + &i2c5 { ++ status = "okay"; + pinctrl-names = "default"; + pinctrl-0 = <&i2c5_pins>; + + clock-frequency = <400000>; ++ ++ tca6424a: tca6424a@22 { ++ compatible = "ti,tca6424"; ++ reg = <0x22>; ++ gpio-controller; ++ #gpio-cells = <2>; ++ }; + }; + + &mcbsp3 { +@@ -470,36 +543,91 @@ + phys = <0 &hsusb2_phy &hsusb3_phy>; + }; + +-&mcspi1 { ++&usb3 { ++ extcon = <&extcon_usb3>; ++ vbus-supply = <&smps10_out1_reg>; ++}; + ++&mcspi1 { ++ status = "okay"; + }; + + &mcspi2 { ++ status = "okay"; + pinctrl-names = "default"; + pinctrl-0 = <&mcspi2_pins>; + }; + + &mcspi3 { ++ status = "okay"; + pinctrl-names = "default"; + pinctrl-0 = <&mcspi3_pins>; + }; + + &mcspi4 { ++ status = "okay"; + pinctrl-names = "default"; + pinctrl-0 = <&mcspi4_pins>; + }; + + &uart1 { ++ status = "okay"; + pinctrl-names = "default"; + pinctrl-0 = <&uart1_pins>; + }; + + &uart3 { ++ status = "okay"; + pinctrl-names = "default"; + pinctrl-0 = <&uart3_pins>; + }; + + &uart5 { ++ status = "okay"; + pinctrl-names = "default"; + pinctrl-0 = <&uart5_pins>; + }; ++ ++&hdmi { ++ vdda_hdmi_dac-supply = <&ldo4_reg>; ++}; ++ ++&dsi1 { ++ vdds_dsi-supply = <&ldo4_reg>; ++}; ++ ++&dsi2 { ++ vdds_dsi-supply = <&ldo4_reg>; ++}; ++ ++&cpu0 { ++ cpu0-supply = <&smps123_reg>; ++}; ++ ++/ { ++ aliases { ++ display0 = &hdmi0; ++ ethernet0 = &smsc0; ++ }; ++ ++ tpd12s015: encoder@0 { ++ compatible = "ti,tpd12s015"; ++ ++ video-source = <&hdmi>; ++ ++ gpios = <&tca6424a 0 0>, /* TCA6424A P01, CT CP HPD */ ++ <&tca6424a 1 0>, /* TCA6424A P00, LS OE */ ++ <&gpio7 1 0>; /* GPIO 193, HPD */ ++ }; ++ ++ hdmi0: connector@0 { ++ compatible = "ti,hdmi_connector"; ++ ++ video-source = <&tpd12s015>; ++ }; ++ ++ smsc0: smsc95xx@0 { ++ /* Filled in by U-Boot */ ++ mac-address = [ 00 00 00 00 00 00 ]; ++ }; ++}; +--- /dev/null ++++ b/arch/arm/boot/dts/tps65218.dtsi +@@ -0,0 +1,41 @@ ++/* ++ * Copyright (C) 2013 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 version 2 as ++ * published by the Free Software Foundation. ++ */ ++ ++&tps { ++ compatible = "ti,tps65218"; ++ interrupt-controller; ++ #interrupt-cells = <2>; ++ ++ dcdc1: regulator-dcdc1 { ++ compatible = "ti,tps65218-dcdc1"; ++ }; ++ ++ dcdc2: regulator-dcdc2 { ++ compatible = "ti,tps65218-dcdc2"; ++ }; ++ ++ dcdc3: regulator-dcdc3 { ++ compatible = "ti,tps65218-dcdc3"; ++ }; ++ ++ dcdc4: regulator-dcdc4 { ++ compatible = "ti,tps65218-dcdc4"; ++ }; ++ ++ dcdc5: regulator-dcdc5 { ++ compatible = "ti,tps65218-dcdc5"; ++ }; ++ ++ dcdc6: regulator-dcdc6 { ++ compatible = "ti,tps65218-dcdc6"; ++ }; ++ ++ ldo1: regulator-ldo1 { ++ compatible = "ti,tps65218-ldo1"; ++ }; ++}; +--- a/arch/arm/boot/dts/twl4030.dtsi ++++ b/arch/arm/boot/dts/twl4030.dtsi +@@ -86,6 +86,7 @@ + usb1v8-supply = <&vusb1v8>; + usb3v1-supply = <&vusb3v1>; + usb_mode = <1>; ++ #phy-cells = <0>; + }; + + twl_pwm: pwm { +--- a/arch/arm/boot/Makefile ++++ b/arch/arm/boot/Makefile +@@ -55,6 +55,9 @@ $(obj)/zImage: $(obj)/compressed/vmlinux + $(call if_changed,objcopy) + @$(kecho) ' Kernel: $@ is ready' + ++$(obj)/zImage-dtb.%: $(obj)/dts/%.dtb $(obj)/zImage ++ cat $(obj)/zImage $< > $@ ++ + endif + + ifneq ($(LOADADDR),) +@@ -80,6 +83,10 @@ $(obj)/uImage: $(obj)/zImage FORCE + $(call if_changed,uimage) + @$(kecho) ' Image $@ is ready' + ++$(obj)/uImage.%: $(obj)/zImage-dtb.% FORCE ++ $(call if_changed,uimage) ++ @echo ' Image $@ is ready' ++ + $(obj)/bootp/bootp: $(obj)/zImage initrd FORCE + $(Q)$(MAKE) $(build)=$(obj)/bootp $@ + @: +--- a/arch/arm/configs/omap2plus_defconfig ++++ b/arch/arm/configs/omap2plus_defconfig +@@ -26,11 +26,13 @@ CONFIG_ARCH_OMAP2=y + CONFIG_ARCH_OMAP3=y + CONFIG_ARCH_OMAP4=y + CONFIG_SOC_AM33XX=y ++CONFIG_SOC_AM43XX=y + CONFIG_OMAP_RESET_CLOCKS=y + CONFIG_OMAP_MUX_DEBUG=y + CONFIG_ARCH_VEXPRESS_CA9X4=y + CONFIG_ARM_THUMBEE=y + CONFIG_ARM_ERRATA_411920=y ++CONFIG_OMAP4_ERRATA_I688=y + CONFIG_NO_HZ=y + CONFIG_HIGH_RES_TIMERS=y + CONFIG_SMP=y +@@ -42,6 +44,14 @@ CONFIG_ARM_APPENDED_DTB=y + CONFIG_ARM_ATAG_DTB_COMPAT=y + CONFIG_CMDLINE="root=/dev/mmcblk0p2 rootwait console=ttyO2,115200" + CONFIG_KEXEC=y ++CONFIG_CPU_FREQ=y ++CONFIG_CPU_FREQ_STAT_DETAILS=y ++CONFIG_CPU_FREQ_DEFAULT_GOV_ONDEMAND=y ++CONFIG_CPU_FREQ_GOV_POWERSAVE=y ++CONFIG_CPU_FREQ_GOV_USERSPACE=y ++CONFIG_CPU_FREQ_GOV_CONSERVATIVE=y ++CONFIG_GENERIC_CPUFREQ_CPU0=y ++# CONFIG_ARM_OMAP2PLUS_CPUFREQ is not set + CONFIG_FPE_NWFPE=y + CONFIG_BINFMT_MISC=y + CONFIG_PM_DEBUG=y +@@ -60,6 +70,7 @@ CONFIG_IP_PNP_RARP=y + # CONFIG_INET_LRO is not set + # CONFIG_IPV6 is not set + CONFIG_NETFILTER=y ++CONFIG_VLAN_8021Q=y + CONFIG_CAN=m + CONFIG_CAN_RAW=m + CONFIG_CAN_BCM=m +@@ -82,6 +93,7 @@ CONFIG_DMA_CMA=y + CONFIG_CONNECTOR=y + CONFIG_DEVTMPFS=y + CONFIG_DEVTMPFS_MOUNT=y ++CONFIG_OMAP_OCP2SCP=y + CONFIG_MTD=y + CONFIG_MTD_CMDLINE_PARTS=y + CONFIG_MTD_CHAR=y +@@ -89,8 +101,11 @@ CONFIG_MTD_BLOCK=y + CONFIG_MTD_OOPS=y + CONFIG_MTD_CFI=y + CONFIG_MTD_CFI_INTELEXT=y ++CONFIG_MTD_M25P80=y ++# CONFIG_M25PXX_USE_FAST_READ is not set + CONFIG_MTD_NAND=y + CONFIG_MTD_NAND_OMAP2=y ++CONFIG_MTD_NAND_OMAP_BCH=y + CONFIG_MTD_ONENAND=y + CONFIG_MTD_ONENAND_VERIFY_WRITE=y + CONFIG_MTD_ONENAND_OMAP2=y +@@ -106,6 +121,9 @@ CONFIG_SCSI=y + CONFIG_BLK_DEV_SD=y + CONFIG_SCSI_MULTI_LUN=y + CONFIG_SCSI_SCAN_ASYNC=y ++CONFIG_ATA=y ++CONFIG_SATA_AHCI_PLATFORM=y ++CONFIG_SATA_TI=y + CONFIG_MD=y + CONFIG_NETDEVICES=y + CONFIG_SMSC_PHY=y +@@ -131,6 +149,9 @@ CONFIG_KEYBOARD_MATRIX=m + CONFIG_KEYBOARD_TWL4030=y + CONFIG_INPUT_TOUCHSCREEN=y + CONFIG_TOUCHSCREEN_ADS7846=y ++CONFIG_TOUCHSCREEN_ATMEL_MXT=y ++CONFIG_TOUCHSCREEN_TI_AM335X_TSC=y ++CONFIG_TOUCHSCREEN_PIXCIR=m + CONFIG_INPUT_MISC=y + CONFIG_INPUT_TWL4030_PWRBUTTON=y + CONFIG_VT_HW_CONSOLE_BINDING=y +@@ -151,10 +172,14 @@ CONFIG_HW_RANDOM=y + CONFIG_I2C_CHARDEV=y + CONFIG_SPI=y + CONFIG_SPI_OMAP24XX=y ++CONFIG_SPI_TI_QSPI=y + CONFIG_PINCTRL_SINGLE=y + CONFIG_DEBUG_GPIO=y + CONFIG_GPIO_SYSFS=y + CONFIG_GPIO_TWL4030=y ++CONFIG_GPIOLIB=y ++CONFIG_I2C=y ++CONFIG_GPIO_PCF857X=y + CONFIG_W1=y + CONFIG_POWER_SUPPLY=y + CONFIG_SENSORS_LM75=m +@@ -168,31 +193,52 @@ CONFIG_THERMAL_GOV_USER_SPACE=y + CONFIG_CPU_THERMAL=y + CONFIG_OMAP_WATCHDOG=y + CONFIG_TWL4030_WATCHDOG=y ++CONFIG_MFD_TI_AM335X_TSCADC=y ++CONFIG_MFD_PALMAS=y + CONFIG_MFD_TPS65217=y + CONFIG_MFD_TPS65910=y + CONFIG_TWL6040_CORE=y + CONFIG_REGULATOR_TWL4030=y ++CONFIG_REGULATOR_TIAVSCLASS0=y + CONFIG_REGULATOR_TPS65023=y + CONFIG_REGULATOR_TPS6507X=y + CONFIG_REGULATOR_TPS65217=y + CONFIG_REGULATOR_TPS65910=y ++CONFIG_REGULATOR_PALMAS=y ++CONFIG_MEDIA_SUPPORT=m ++CONFIG_MEDIA_CAMERA_SUPPORT=y ++CONFIG_VIDEO_DEV=m ++CONFIG_VIDEO_V4L2=m ++CONFIG_VIDEOBUF2_CORE=m ++CONFIG_VIDEOBUF2_MEMOPS=m ++CONFIG_VIDEOBUF2_VMALLOC=m ++CONFIG_MEDIA_USB_SUPPORT=y ++CONFIG_USB_VIDEO_CLASS=m ++CONFIG_USB_VIDEO_CLASS_INPUT_EVDEV=y ++CONFIG_USB_GSPCA=m + CONFIG_FB=y + CONFIG_FIRMWARE_EDID=y + CONFIG_FB_MODE_HELPERS=y + CONFIG_FB_TILEBLITTING=y + CONFIG_FB_OMAP_LCD_VGA=y +-CONFIG_OMAP2_DSS=m ++CONFIG_FB_DA8XX=y ++CONFIG_FB_DA8XX_TDA998X=y ++CONFIG_OMAP2_DSS=y + CONFIG_OMAP2_DSS_RFBI=y + CONFIG_OMAP2_DSS_SDI=y + CONFIG_OMAP2_DSS_DSI=y +-CONFIG_FB_OMAP2=m +-CONFIG_DISPLAY_ENCODER_TFP410=m +-CONFIG_DISPLAY_ENCODER_TPD12S015=m +-CONFIG_DISPLAY_CONNECTOR_DVI=m +-CONFIG_DISPLAY_CONNECTOR_HDMI=m +-CONFIG_DISPLAY_PANEL_DPI=m ++CONFIG_FB_OMAP2=y ++CONFIG_DISPLAY_ENCODER_TFP410=y ++CONFIG_DISPLAY_ENCODER_TPD12S015=y ++CONFIG_DISPLAY_DRA_EVM_ENCODER_TPD12S015=y ++CONFIG_DISPLAY_CONNECTOR_DVI=y ++CONFIG_DISPLAY_CONNECTOR_HDMI=y ++CONFIG_DISPLAY_PANEL_DPI=y ++CONFIG_DISPLAY_PANEL_TFCS9700=y + CONFIG_BACKLIGHT_LCD_SUPPORT=y + CONFIG_LCD_CLASS_DEVICE=y ++CONFIG_BACKLIGHT_CLASS_DEVICE=y ++CONFIG_BACKLIGHT_PWM=y + CONFIG_LCD_PLATFORM=y + CONFIG_DISPLAY_SUPPORT=y + CONFIG_FRAMEBUFFER_CONSOLE=y +@@ -210,25 +256,57 @@ CONFIG_SND_DEBUG=y + CONFIG_SND_USB_AUDIO=m + CONFIG_SND_SOC=m + CONFIG_SND_OMAP_SOC=m ++CONFIG_SND_AM33XX_SOC_EVM=m ++CONFIG_SND_DAVINCI_SOC=m + CONFIG_SND_OMAP_SOC_OMAP_TWL4030=m + CONFIG_SND_OMAP_SOC_OMAP_ABE_TWL6040=m + CONFIG_SND_OMAP_SOC_OMAP3_PANDORA=m + CONFIG_USB=y +-CONFIG_USB_DEBUG=y + CONFIG_USB_ANNOUNCE_NEW_DEVICES=y + CONFIG_USB_DEVICEFS=y + CONFIG_USB_MON=y ++CONFIG_USB_XHCI_HCD=y ++CONFIG_USB_XHCI_PLATFORM=y ++CONFIG_USB_EHCI_HCD=y ++CONFIG_USB_MUSB_HDRC=y ++CONFIG_USB_MUSB_OMAP2PLUS=m ++CONFIG_USB_MUSB_DSPS=m + CONFIG_USB_WDM=y + CONFIG_USB_STORAGE=y + CONFIG_USB_LIBUSUAL=y + CONFIG_USB_TEST=y ++CONFIG_AM335X_PHY_USB=y ++CONFIG_TWL6030_USB=y + CONFIG_USB_PHY=y + CONFIG_NOP_USB_XCEIV=y ++ ++CONFIG_USB_DWC3=y ++CONFIG_USB_DWC3_OMAP=y ++ + CONFIG_USB_GADGET=y + CONFIG_USB_GADGET_DEBUG=y + CONFIG_USB_GADGET_DEBUG_FILES=y + CONFIG_USB_GADGET_DEBUG_FS=y + CONFIG_USB_ZERO=m ++CONFIG_USB_AUDIO=m ++CONFIG_USB_ETH=m ++CONFIG_USB_G_NCM=m ++CONFIG_USB_GADGETFS=m ++CONFIG_USB_FUNCTIONFS=m ++CONFIG_USB_FUNCTIONFS_ETH=y ++CONFIG_USB_FUNCTIONFS_RNDIS=y ++CONFIG_USB_FUNCTIONFS_GENERIC=y ++CONFIG_USB_MASS_STORAGE=m ++CONFIG_USB_G_SERIAL=m ++CONFIG_USB_MIDI_GADGET=m ++CONFIG_USB_G_PRINTER=m ++CONFIG_USB_CDC_COMPOSITE=m ++CONFIG_USB_G_ACM_MS=m ++CONFIG_USB_G_MULTI=m ++CONFIG_USB_G_MULTI_CDC=y ++CONFIG_USB_G_HID=m ++CONFIG_USB_G_DBGP=m ++CONFIG_USB_G_WEBCAM=m + CONFIG_MMC=y + CONFIG_MMC_UNSAFE_RESUME=y + CONFIG_SDIO_UART=y +@@ -249,14 +327,35 @@ CONFIG_RTC_CLASS=y + CONFIG_RTC_DRV_TWL92330=y + CONFIG_RTC_DRV_TWL4030=y + CONFIG_RTC_DRV_OMAP=y ++CONFIG_RTC_DRV_PALMAS=y + CONFIG_DMADEVICES=y + CONFIG_TI_EDMA=y + CONFIG_DMA_OMAP=y ++CONFIG_PWM=y ++CONFIG_COMMON_CLK_DEBUG=y ++CONFIG_PWM_TIECAP=m ++CONFIG_PWM_TIEHRPWM=m + CONFIG_TI_SOC_THERMAL=y + CONFIG_TI_THERMAL=y + CONFIG_OMAP4_THERMAL=y + CONFIG_OMAP5_THERMAL=y + CONFIG_DRA752_THERMAL=y ++ ++CONFIG_EXTCON=y ++CONFIG_EXTCON_PALMAS=y ++CONFIG_EXTCON_GPIO_USBVID=y ++ ++CONFIG_GENERIC_PHY=y ++CONFIG_OMAP_CONTROL_PHY=y ++CONFIG_IIO=m ++CONFIG_IIO_BUFFER=y ++CONFIG_IIO_BUFFER_CB=y ++CONFIG_IIO_KFIFO_BUF=m ++CONFIG_TI_AM335X_ADC=m ++CONFIG_OMAP_USB2=y ++CONFIG_OMAP_PIPE3=y ++CONFIG_TWL4030_USB=y ++ + CONFIG_EXT2_FS=y + CONFIG_EXT3_FS=y + # CONFIG_EXT3_FS_XATTR is not set +@@ -295,6 +394,10 @@ CONFIG_DEBUG_INFO=y + CONFIG_SECURITY=y + CONFIG_CRYPTO_MICHAEL_MIC=y + # CONFIG_CRYPTO_ANSI_CPRNG is not set ++CONFIG_CRYPTO_DEV_OMAP_SHAM=y ++CONFIG_CRYPTO_DEV_OMAP_AES=y ++CONFIG_CRYPTO_DEV_OMAP_DES=y ++CONFIG_CRYPTO_TEST=m + CONFIG_CRC_CCITT=y + CONFIG_CRC_T10DIF=y + CONFIG_CRC_ITU_T=y +@@ -306,3 +409,4 @@ CONFIG_TI_DAVINCI_CPDMA=y + CONFIG_TI_CPSW=y + CONFIG_AT803X_PHY=y + CONFIG_SOC_DRA7XX=y ++CONFIG_GPIO_PCA953X=y +--- a/arch/arm/Kconfig ++++ b/arch/arm/Kconfig +@@ -873,10 +873,33 @@ config ARCH_OMAP1 + help + Support for older TI OMAP1 (omap7xx, omap15xx or omap16xx) + ++config ARCH_OMAP2PLUS ++ bool "TI OMAP2+" ++ depends on MMU ++ select ARCH_HAS_BANDGAP ++ select ARCH_HAS_CPUFREQ ++ select ARCH_HAS_HOLES_MEMORYMODEL ++ select ARCH_OMAP ++ select ARCH_REQUIRE_GPIOLIB ++ select CLKDEV_LOOKUP ++ select CLKSRC_MMIO ++ select GENERIC_CLOCKEVENTS ++ select GENERIC_IRQ_CHIP ++ select HAVE_CLK ++ select OMAP_DM_TIMER ++ select PINCTRL ++ select PROC_DEVICETREE if PROC_FS ++ select SOC_BUS ++ select SPARSE_IRQ ++ select TI_PRIV_EDMA ++ select USE_OF ++ select AUTO_ZRELADDR ++ help ++ SUpport for OMAP2, OMAP3, OMAP4 and OMAP5 ++ + endchoice + + menu "Multiple platform selection" +- depends on ARCH_MULTIPLATFORM + + comment "CPU Core family selection" + +@@ -1606,6 +1629,7 @@ config ARCH_NR_GPIO + default 352 if ARCH_VT8500 + default 288 if ARCH_SUNXI + default 264 if MACH_H4700 ++ default 192 if SOC_AM43XX + default 0 + help + Maximum number of GPIOs in the system. +--- a/arch/arm/Kconfig.debug ++++ b/arch/arm/Kconfig.debug +@@ -1077,7 +1077,7 @@ config DEBUG_UNCOMPRESS + + config UNCOMPRESS_INCLUDE + string +- default "debug/uncompress.h" if ARCH_MULTIPLATFORM || ARCH_MSM ++ default "debug/uncompress.h" if ARCH_MULTIPLATFORM || ARCH_MSM || ARCH_OMAP + default "mach/uncompress.h" + + config EARLY_PRINTK +--- a/arch/arm/kernel/head.S ++++ b/arch/arm/kernel/head.S +@@ -534,7 +534,8 @@ smp_on_up: + __do_fixup_smp_on_up: + cmp r4, r5 + movhs pc, lr +- ldmia r4!, {r0, r6} ++ ldmia r4!, {r0} ++ ldmia r4!, {r6} + ARM( str r6, [r0, r3] ) + THUMB( add r0, r0, r3 ) + #ifdef __ARMEB__ +--- a/arch/arm/mach-omap2/am33xx-restart.c ++++ b/arch/arm/mach-omap2/am33xx-restart.c +@@ -9,6 +9,7 @@ + #include <linux/reboot.h> + + #include "common.h" ++#include "prcm43xx.h" + #include "prm-regbits-33xx.h" + #include "prm33xx.h" + +@@ -33,3 +34,25 @@ void am33xx_restart(enum reboot_mode mod + (void)am33xx_prm_read_reg(AM33XX_PRM_DEVICE_MOD, + AM33XX_PRM_RSTCTRL_OFFSET); + } ++ ++/** ++ * am43xx_restart - trigger a software restart of the SoC ++ * @mode: the "reboot mode", see arch/arm/kernel/{setup,process}.c ++ * @cmd: passed fr-om the userspace program rebooting the system (if provided) ++ * ++ * Resets the SoC. For @cmd, see the 'reboot' syscall in ++ * kernel/sys.c. No return value. ++ */ ++void am43xx_restart(enum reboot_mode mode, const char *cmd) ++{ ++ /* TODO: Handle mode and cmd if necessary */ ++ ++ am33xx_prm_rmw_reg_bits(AM33XX_RST_GLOBAL_WARM_SW_MASK, ++ AM33XX_RST_GLOBAL_WARM_SW_MASK, ++ AM43XX_PRM_DEVICE_INST, ++ AM33XX_PRM_RSTCTRL_OFFSET); ++ ++ /* OCP barrier */ ++ (void)am33xx_prm_read_reg(AM43XX_PRM_DEVICE_INST, ++ AM33XX_PRM_RSTCTRL_OFFSET); ++} +--- a/arch/arm/mach-omap2/board-2430sdp.c ++++ b/arch/arm/mach-omap2/board-2430sdp.c +@@ -246,7 +246,7 @@ static void __init omap_2430sdp_init(voi + omap_hsmmc_init(mmc); + + omap_mux_init_signal("usb0hs_stp", OMAP_PULL_ENA | OMAP_PULL_UP); +- usb_bind_phy("musb-hdrc.0.auto", 0, "twl4030_usb"); ++ usb_bind_phy("musb-hdrc.0", 0, "twl4030_usb"); + usb_musb_init(NULL); + + board_smc91x_init(); +--- a/arch/arm/mach-omap2/board-3430sdp.c ++++ b/arch/arm/mach-omap2/board-3430sdp.c +@@ -607,7 +607,7 @@ static void __init omap_3430sdp_init(voi + omap_ads7846_init(1, gpio_pendown, 310, NULL); + omap_serial_init(); + omap_sdrc_init(hyb18m512160af6_sdrc_params, NULL); +- usb_bind_phy("musb-hdrc.0.auto", 0, "twl4030_usb"); ++ usb_bind_phy("musb-hdrc.0", 0, "twl4030_usb"); + usb_musb_init(NULL); + board_smc91x_init(); + board_flash_init(sdp_flash_partitions, chip_sel_3430, 0); +--- a/arch/arm/mach-omap2/board-cm-t35.c ++++ b/arch/arm/mach-omap2/board-cm-t35.c +@@ -725,7 +725,7 @@ static void __init cm_t3x_common_init(vo + cm_t35_init_display(); + omap_twl4030_audio_init("cm-t3x", NULL); + +- usb_bind_phy("musb-hdrc.0.auto", 0, "twl4030_usb"); ++ usb_bind_phy("musb-hdrc.0", 0, "twl4030_usb"); + usb_musb_init(NULL); + cm_t35_init_usbh(); + cm_t35_init_camera(); +--- a/arch/arm/mach-omap2/board-devkit8000.c ++++ b/arch/arm/mach-omap2/board-devkit8000.c +@@ -628,7 +628,7 @@ static void __init devkit8000_init(void) + + omap_ads7846_init(2, OMAP3_DEVKIT_TS_GPIO, 0, NULL); + +- usb_bind_phy("musb-hdrc.0.auto", 0, "twl4030_usb"); ++ usb_bind_phy("musb-hdrc.0", 0, "twl4030_usb"); + usb_musb_init(NULL); + usbhs_init(&usbhs_bdata); + board_nand_init(devkit8000_nand_partitions, +--- a/arch/arm/mach-omap2/board-flash.c ++++ b/arch/arm/mach-omap2/board-flash.c +@@ -142,7 +142,7 @@ __init board_nand_init(struct mtd_partit + board_nand_data.nr_parts = nr_parts; + board_nand_data.devsize = nand_type; + +- board_nand_data.ecc_opt = OMAP_ECC_HAMMING_CODE_DEFAULT; ++ board_nand_data.ecc_opt = OMAP_ECC_BCH8_CODE_HW; + gpmc_nand_init(&board_nand_data, gpmc_t); + } + #endif /* CONFIG_MTD_NAND_OMAP2 || CONFIG_MTD_NAND_OMAP2_MODULE */ +--- a/arch/arm/mach-omap2/board-generic.c ++++ b/arch/arm/mach-omap2/board-generic.c +@@ -15,13 +15,11 @@ + #include <linux/of_irq.h> + #include <linux/of_platform.h> + #include <linux/irqdomain.h> +-#include <linux/clk.h> + + #include <asm/mach/arch.h> + + #include "common.h" + #include "common-board-devices.h" +-#include "dss-common.h" + + #if !(defined(CONFIG_ARCH_OMAP2) || defined(CONFIG_ARCH_OMAP3)) + #define intc_of_init NULL +@@ -36,40 +34,13 @@ static struct of_device_id omap_dt_match + { } + }; + +-/* +- * Create alias for USB host PHY clock. +- * Remove this when clock phandle can be provided via DT +- */ +-static void __init legacy_init_ehci_clk(char *clkname) +-{ +- int ret; +- +- ret = clk_add_alias("main_clk", NULL, clkname, NULL); +- if (ret) { +- pr_err("%s:Failed to add main_clk alias to %s :%d\n", +- __func__, clkname, ret); +- } +-} +- + static void __init omap_generic_init(void) + { + omap_sdrc_init(NULL, NULL); + + of_platform_populate(NULL, omap_dt_match_table, NULL, NULL); + +- /* +- * HACK: call display setup code for selected boards to enable omapdss. +- * This will be removed when omapdss supports DT. +- */ +- if (of_machine_is_compatible("ti,omap4-panda")) { +- omap4_panda_display_init_of(); +- legacy_init_ehci_clk("auxclk3_ck"); +- +- } +- else if (of_machine_is_compatible("ti,omap4-sdp")) +- omap_4430sdp_display_init_of(); +- else if (of_machine_is_compatible("ti,omap5-uevm")) +- legacy_init_ehci_clk("auxclk1_ck"); ++ omapdss_init_of(); + } + + #ifdef CONFIG_SOC_OMAP2420 +@@ -165,6 +136,24 @@ DT_MACHINE_START(OMAP3_GP_DT, "Generic O + .dt_compat = omap3_gp_boards_compat, + .restart = omap3xxx_restart, + MACHINE_END ++ ++static const char *omap3630_gp_boards_compat[] __initdata = { ++ "ti,omap3-beagle-xm", ++ NULL, ++}; ++ ++DT_MACHINE_START(OMAP3630_GP_DT, "Generic OMAP3630-GP (Flattened Device Tree)") ++ .reserve = omap_reserve, ++ .map_io = omap3_map_io, ++ .init_early = omap3630_init_early, ++ .init_irq = omap_intc_of_init, ++ .handle_irq = omap3_intc_handle_irq, ++ .init_machine = omap_generic_init, ++ .init_late = omap3_init_late, ++ .init_time = omap3_secure_sync32k_timer_init, ++ .dt_compat = omap3630_gp_boards_compat, ++ .restart = omap3xxx_restart, ++MACHINE_END + #endif + + #ifdef CONFIG_SOC_AM33XX +@@ -174,12 +163,14 @@ static const char *am33xx_boards_compat[ + }; + + DT_MACHINE_START(AM33XX_DT, "Generic AM33XX (Flattened Device Tree)") +- .reserve = omap_reserve, ++ .reserve = am33xx_reserve, + .map_io = am33xx_map_io, + .init_early = am33xx_init_early, ++ .init_late = am33xx_init_late, + .init_irq = omap_intc_of_init, + .handle_irq = omap3_intc_handle_irq, + .init_machine = omap_generic_init, ++ .init_late = am33xx_init_late, + .init_time = omap3_gptimer_timer_init, + .dt_compat = am33xx_boards_compat, + .restart = am33xx_restart, +@@ -219,6 +210,7 @@ DT_MACHINE_START(OMAP5_DT, "Generic OMAP + .init_early = omap5_init_early, + .init_irq = omap_gic_of_init, + .init_machine = omap_generic_init, ++ .init_late = omap5_init_late, + .init_time = omap5_realtime_timer_init, + .dt_compat = omap5_boards_compat, + .restart = omap44xx_restart, +@@ -232,12 +224,14 @@ static const char *am43_boards_compat[] + }; + + DT_MACHINE_START(AM43_DT, "Generic AM43 (Flattened Device Tree)") ++ .reserve = am33xx_reserve, + .map_io = am33xx_map_io, + .init_early = am43xx_init_early, + .init_irq = omap_gic_of_init, + .init_machine = omap_generic_init, + .init_time = omap3_sync32k_timer_init, + .dt_compat = am43_boards_compat, ++ .restart = am43xx_restart, + MACHINE_END + #endif + +@@ -254,6 +248,7 @@ DT_MACHINE_START(DRA7XX_DT, "Generic DRA + .init_early = dra7xx_init_early, + .init_irq = omap_gic_of_init, + .init_machine = omap_generic_init, ++ .init_late = dra7xx_init_late, + .init_time = omap5_realtime_timer_init, + .dt_compat = dra7xx_boards_compat, + .restart = omap44xx_restart, +--- a/arch/arm/mach-omap2/board-igep0020.c ++++ b/arch/arm/mach-omap2/board-igep0020.c +@@ -667,7 +667,7 @@ static void __init igep_init(void) + omap_serial_init(); + omap_sdrc_init(m65kxxxxam_sdrc_params, + m65kxxxxam_sdrc_params); +- usb_bind_phy("musb-hdrc.0.auto", 0, "twl4030_usb"); ++ usb_bind_phy("musb-hdrc.0", 0, "twl4030_usb"); + usb_musb_init(NULL); + + igep_flash_init(); +--- a/arch/arm/mach-omap2/board-ldp.c ++++ b/arch/arm/mach-omap2/board-ldp.c +@@ -403,7 +403,7 @@ static void __init omap_ldp_init(void) + omap_ads7846_init(1, 54, 310, NULL); + omap_serial_init(); + omap_sdrc_init(NULL, NULL); +- usb_bind_phy("musb-hdrc.0.auto", 0, "twl4030_usb"); ++ usb_bind_phy("musb-hdrc.0", 0, "twl4030_usb"); + usb_musb_init(NULL); + board_nand_init(ldp_nand_partitions, ARRAY_SIZE(ldp_nand_partitions), + ZOOM_NAND_CS, 0, nand_default_timings); +--- a/arch/arm/mach-omap2/board-omap3beagle.c ++++ b/arch/arm/mach-omap2/board-omap3beagle.c +@@ -289,18 +289,12 @@ static struct regulator_consumer_supply + + static struct gpio_led gpio_leds[]; + +-/* PHY's VCC regulator might be added later, so flag that we need it */ +-static struct usb_phy_gen_xceiv_platform_data hsusb2_phy_data = { +- .needs_vcc = true, +-}; +- + static struct usbhs_phy_data phy_data[] = { + { + .port = 2, + .reset_gpio = 147, + .vcc_gpio = -1, /* updated in beagle_twl_gpio_setup */ + .vcc_polarity = 1, /* updated in beagle_twl_gpio_setup */ +- .platform_data = &hsusb2_phy_data, + }, + }; + +@@ -567,7 +561,7 @@ static void __init omap3_beagle_init(voi + omap_sdrc_init(mt46h32m32lf6_sdrc_params, + mt46h32m32lf6_sdrc_params); + +- usb_bind_phy("musb-hdrc.0.auto", 0, "twl4030_usb"); ++ usb_bind_phy("musb-hdrc.0", 0, "twl4030_usb"); + usb_musb_init(NULL); + + usbhs_init(&usbhs_bdata); +--- a/arch/arm/mach-omap2/board-omap3evm.c ++++ b/arch/arm/mach-omap2/board-omap3evm.c +@@ -723,7 +723,7 @@ static void __init omap3_evm_init(void) + omap_mux_init_gpio(135, OMAP_PIN_OUTPUT); + phy_data[0].reset_gpio = 135; + } +- usb_bind_phy("musb-hdrc.0.auto", 0, "twl4030_usb"); ++ usb_bind_phy("musb-hdrc.0", 0, "twl4030_usb"); + usb_musb_init(&musb_board_data); + + usbhs_init_phys(phy_data, ARRAY_SIZE(phy_data)); +--- a/arch/arm/mach-omap2/board-omap3logic.c ++++ b/arch/arm/mach-omap2/board-omap3logic.c +@@ -216,7 +216,7 @@ static void __init omap3logic_init(void) + board_mmc_init(); + board_smsc911x_init(); + +- usb_bind_phy("musb-hdrc.0.auto", 0, "twl4030_usb"); ++ usb_bind_phy("musb-hdrc.0", 0, "twl4030_usb"); + usb_musb_init(NULL); + + /* Ensure SDRC pins are mux'd for self-refresh */ +--- a/arch/arm/mach-omap2/board-omap3pandora.c ++++ b/arch/arm/mach-omap2/board-omap3pandora.c +@@ -607,7 +607,7 @@ static void __init omap3pandora_init(voi + usbhs_init_phys(phy_data, ARRAY_SIZE(phy_data)); + usbhs_init(&usbhs_bdata); + +- usb_bind_phy("musb-hdrc.0.auto", 0, "twl4030_usb"); ++ usb_bind_phy("musb-hdrc.0", 0, "twl4030_usb"); + usb_musb_init(NULL); + gpmc_nand_init(&pandora_nand_data, NULL); + +--- a/arch/arm/mach-omap2/board-omap3stalker.c ++++ b/arch/arm/mach-omap2/board-omap3stalker.c +@@ -407,7 +407,7 @@ static void __init omap3_stalker_init(vo + + omap_serial_init(); + omap_sdrc_init(mt46h32m32lf6_sdrc_params, NULL); +- usb_bind_phy("musb-hdrc.0.auto", 0, "twl4030_usb"); ++ usb_bind_phy("musb-hdrc.0", 0, "twl4030_usb"); + usb_musb_init(NULL); + + usbhs_init_phys(phy_data, ARRAY_SIZE(phy_data)); +--- a/arch/arm/mach-omap2/board-omap3touchbook.c ++++ b/arch/arm/mach-omap2/board-omap3touchbook.c +@@ -367,7 +367,7 @@ static void __init omap3_touchbook_init( + + /* Touchscreen and accelerometer */ + omap_ads7846_init(4, OMAP3_TS_GPIO, 310, &ads7846_pdata); +- usb_bind_phy("musb-hdrc.0.auto", 0, "twl4030_usb"); ++ usb_bind_phy("musb-hdrc.0", 0, "twl4030_usb"); + usb_musb_init(NULL); + + usbhs_init_phys(phy_data, ARRAY_SIZE(phy_data)); +--- a/arch/arm/mach-omap2/board-overo.c ++++ b/arch/arm/mach-omap2/board-overo.c +@@ -511,7 +511,7 @@ static void __init overo_init(void) + mt46h32m32lf6_sdrc_params); + board_nand_init(overo_nand_partitions, + ARRAY_SIZE(overo_nand_partitions), NAND_CS, 0, NULL); +- usb_bind_phy("musb-hdrc.0.auto", 0, "twl4030_usb"); ++ usb_bind_phy("musb-hdrc.0", 0, "twl4030_usb"); + usb_musb_init(NULL); + + usbhs_init_phys(phy_data, ARRAY_SIZE(phy_data)); +--- a/arch/arm/mach-omap2/board-rm680.c ++++ b/arch/arm/mach-omap2/board-rm680.c +@@ -135,7 +135,7 @@ static void __init rm680_init(void) + sdrc_params = nokia_get_sdram_timings(); + omap_sdrc_init(sdrc_params, sdrc_params); + +- usb_bind_phy("musb-hdrc.0.auto", 0, "twl4030_usb"); ++ usb_bind_phy("musb-hdrc.0", 0, "twl4030_usb"); + usb_musb_init(NULL); + rm680_peripherals_init(); + } +--- a/arch/arm/mach-omap2/board-rx51.c ++++ b/arch/arm/mach-omap2/board-rx51.c +@@ -99,7 +99,7 @@ static void __init rx51_init(void) + sdrc_params = nokia_get_sdram_timings(); + omap_sdrc_init(sdrc_params, sdrc_params); + +- usb_bind_phy("musb-hdrc.0.auto", 0, "twl4030_usb"); ++ usb_bind_phy("musb-hdrc.0", 0, "twl4030_usb"); + usb_musb_init(&musb_board_data); + rx51_peripherals_init(); + +--- a/arch/arm/mach-omap2/board-zoom-peripherals.c ++++ b/arch/arm/mach-omap2/board-zoom-peripherals.c +@@ -353,7 +353,7 @@ void __init zoom_peripherals_init(void) + omap_i2c_init(); + pwm_add_table(zoom_pwm_lookup, ARRAY_SIZE(zoom_pwm_lookup)); + platform_add_devices(zoom_devices, ARRAY_SIZE(zoom_devices)); +- usb_bind_phy("musb-hdrc.0.auto", 0, "twl4030_usb"); ++ usb_bind_phy("musb-hdrc.0", 0, "twl4030_usb"); + usb_musb_init(NULL); + enable_board_wakeup_source(); + omap_serial_init(); +--- a/arch/arm/mach-omap2/cclock33xx_data.c ++++ /dev/null +@@ -1,1064 +0,0 @@ +-/* +- * AM33XX Clock data +- * +- * Copyright (C) 2012 Texas Instruments Incorporated - http://www.ti.com/ +- * Vaibhav Hiremath <hvaibhav@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/kernel.h> +-#include <linux/list.h> +-#include <linux/clk-private.h> +-#include <linux/clkdev.h> +-#include <linux/io.h> +- +-#include "am33xx.h" +-#include "soc.h" +-#include "iomap.h" +-#include "clock.h" +-#include "control.h" +-#include "cm.h" +-#include "cm33xx.h" +-#include "cm-regbits-33xx.h" +-#include "prm.h" +- +-/* Modulemode control */ +-#define AM33XX_MODULEMODE_HWCTRL_SHIFT 0 +-#define AM33XX_MODULEMODE_SWCTRL_SHIFT 1 +- +-/*LIST_HEAD(clocks);*/ +- +-/* Root clocks */ +- +-/* RTC 32k */ +-DEFINE_CLK_FIXED_RATE(clk_32768_ck, CLK_IS_ROOT, 32768, 0x0); +- +-/* On-Chip 32KHz RC OSC */ +-DEFINE_CLK_FIXED_RATE(clk_rc32k_ck, CLK_IS_ROOT, 32000, 0x0); +- +-/* Crystal input clks */ +-DEFINE_CLK_FIXED_RATE(virt_19200000_ck, CLK_IS_ROOT, 19200000, 0x0); +- +-DEFINE_CLK_FIXED_RATE(virt_24000000_ck, CLK_IS_ROOT, 24000000, 0x0); +- +-DEFINE_CLK_FIXED_RATE(virt_25000000_ck, CLK_IS_ROOT, 25000000, 0x0); +- +-DEFINE_CLK_FIXED_RATE(virt_26000000_ck, CLK_IS_ROOT, 26000000, 0x0); +- +-/* Oscillator clock */ +-/* 19.2, 24, 25 or 26 MHz */ +-static const char *sys_clkin_ck_parents[] = { +- "virt_19200000_ck", "virt_24000000_ck", "virt_25000000_ck", +- "virt_26000000_ck", +-}; +- +-/* +- * sys_clk in: input to the dpll and also used as funtional clock for, +- * adc_tsc, smartreflex0-1, timer1-7, mcasp0-1, dcan0-1, cefuse +- * +- */ +-DEFINE_CLK_MUX(sys_clkin_ck, sys_clkin_ck_parents, NULL, 0x0, +- AM33XX_CTRL_REGADDR(AM33XX_CONTROL_STATUS), +- AM33XX_CONTROL_STATUS_SYSBOOT1_SHIFT, +- AM33XX_CONTROL_STATUS_SYSBOOT1_WIDTH, +- 0, NULL); +- +-/* External clock - 12 MHz */ +-DEFINE_CLK_FIXED_RATE(tclkin_ck, CLK_IS_ROOT, 12000000, 0x0); +- +-/* Module clocks and DPLL outputs */ +- +-/* DPLL_CORE */ +-static struct dpll_data dpll_core_dd = { +- .mult_div1_reg = AM33XX_CM_CLKSEL_DPLL_CORE, +- .clk_bypass = &sys_clkin_ck, +- .clk_ref = &sys_clkin_ck, +- .control_reg = AM33XX_CM_CLKMODE_DPLL_CORE, +- .modes = (1 << DPLL_LOW_POWER_BYPASS) | (1 << DPLL_LOCKED), +- .idlest_reg = AM33XX_CM_IDLEST_DPLL_CORE, +- .mult_mask = AM33XX_DPLL_MULT_MASK, +- .div1_mask = AM33XX_DPLL_DIV_MASK, +- .enable_mask = AM33XX_DPLL_EN_MASK, +- .idlest_mask = AM33XX_ST_DPLL_CLK_MASK, +- .max_multiplier = 2047, +- .max_divider = 128, +- .min_divider = 1, +-}; +- +-/* CLKDCOLDO output */ +-static const char *dpll_core_ck_parents[] = { +- "sys_clkin_ck", +-}; +- +-static struct clk dpll_core_ck; +- +-static const struct clk_ops dpll_core_ck_ops = { +- .recalc_rate = &omap3_dpll_recalc, +- .get_parent = &omap2_init_dpll_parent, +-}; +- +-static struct clk_hw_omap dpll_core_ck_hw = { +- .hw = { +- .clk = &dpll_core_ck, +- }, +- .dpll_data = &dpll_core_dd, +- .ops = &clkhwops_omap3_dpll, +-}; +- +-DEFINE_STRUCT_CLK(dpll_core_ck, dpll_core_ck_parents, dpll_core_ck_ops); +- +-static const char *dpll_core_x2_ck_parents[] = { +- "dpll_core_ck", +-}; +- +-static struct clk dpll_core_x2_ck; +- +-static const struct clk_ops dpll_x2_ck_ops = { +- .recalc_rate = &omap3_clkoutx2_recalc, +-}; +- +-static struct clk_hw_omap dpll_core_x2_ck_hw = { +- .hw = { +- .clk = &dpll_core_x2_ck, +- }, +- .flags = CLOCK_CLKOUTX2, +-}; +- +-DEFINE_STRUCT_CLK(dpll_core_x2_ck, dpll_core_x2_ck_parents, dpll_x2_ck_ops); +- +-DEFINE_CLK_DIVIDER(dpll_core_m4_ck, "dpll_core_x2_ck", &dpll_core_x2_ck, +- 0x0, AM33XX_CM_DIV_M4_DPLL_CORE, +- AM33XX_HSDIVIDER_CLKOUT1_DIV_SHIFT, +- AM33XX_HSDIVIDER_CLKOUT1_DIV_WIDTH, CLK_DIVIDER_ONE_BASED, +- NULL); +- +-DEFINE_CLK_DIVIDER(dpll_core_m5_ck, "dpll_core_x2_ck", &dpll_core_x2_ck, +- 0x0, AM33XX_CM_DIV_M5_DPLL_CORE, +- AM33XX_HSDIVIDER_CLKOUT2_DIV_SHIFT, +- AM33XX_HSDIVIDER_CLKOUT2_DIV_WIDTH, +- CLK_DIVIDER_ONE_BASED, NULL); +- +-DEFINE_CLK_DIVIDER(dpll_core_m6_ck, "dpll_core_x2_ck", &dpll_core_x2_ck, +- 0x0, AM33XX_CM_DIV_M6_DPLL_CORE, +- AM33XX_HSDIVIDER_CLKOUT3_DIV_SHIFT, +- AM33XX_HSDIVIDER_CLKOUT3_DIV_WIDTH, +- CLK_DIVIDER_ONE_BASED, NULL); +- +- +-/* DPLL_MPU */ +-static struct dpll_data dpll_mpu_dd = { +- .mult_div1_reg = AM33XX_CM_CLKSEL_DPLL_MPU, +- .clk_bypass = &sys_clkin_ck, +- .clk_ref = &sys_clkin_ck, +- .control_reg = AM33XX_CM_CLKMODE_DPLL_MPU, +- .modes = (1 << DPLL_LOW_POWER_BYPASS) | (1 << DPLL_LOCKED), +- .idlest_reg = AM33XX_CM_IDLEST_DPLL_MPU, +- .mult_mask = AM33XX_DPLL_MULT_MASK, +- .div1_mask = AM33XX_DPLL_DIV_MASK, +- .enable_mask = AM33XX_DPLL_EN_MASK, +- .idlest_mask = AM33XX_ST_DPLL_CLK_MASK, +- .max_multiplier = 2047, +- .max_divider = 128, +- .min_divider = 1, +-}; +- +-/* CLKOUT: fdpll/M2 */ +-static struct clk dpll_mpu_ck; +- +-static const struct clk_ops dpll_mpu_ck_ops = { +- .enable = &omap3_noncore_dpll_enable, +- .disable = &omap3_noncore_dpll_disable, +- .recalc_rate = &omap3_dpll_recalc, +- .round_rate = &omap2_dpll_round_rate, +- .set_rate = &omap3_noncore_dpll_set_rate, +- .get_parent = &omap2_init_dpll_parent, +-}; +- +-static struct clk_hw_omap dpll_mpu_ck_hw = { +- .hw = { +- .clk = &dpll_mpu_ck, +- }, +- .dpll_data = &dpll_mpu_dd, +- .ops = &clkhwops_omap3_dpll, +-}; +- +-DEFINE_STRUCT_CLK(dpll_mpu_ck, dpll_core_ck_parents, dpll_mpu_ck_ops); +- +-/* +- * TODO: Add clksel here (sys_clkin, CORE_CLKOUTM6, PER_CLKOUTM2 +- * and ALT_CLK1/2) +- */ +-DEFINE_CLK_DIVIDER(dpll_mpu_m2_ck, "dpll_mpu_ck", &dpll_mpu_ck, +- 0x0, AM33XX_CM_DIV_M2_DPLL_MPU, AM33XX_DPLL_CLKOUT_DIV_SHIFT, +- AM33XX_DPLL_CLKOUT_DIV_WIDTH, CLK_DIVIDER_ONE_BASED, NULL); +- +-/* DPLL_DDR */ +-static struct dpll_data dpll_ddr_dd = { +- .mult_div1_reg = AM33XX_CM_CLKSEL_DPLL_DDR, +- .clk_bypass = &sys_clkin_ck, +- .clk_ref = &sys_clkin_ck, +- .control_reg = AM33XX_CM_CLKMODE_DPLL_DDR, +- .modes = (1 << DPLL_LOW_POWER_BYPASS) | (1 << DPLL_LOCKED), +- .idlest_reg = AM33XX_CM_IDLEST_DPLL_DDR, +- .mult_mask = AM33XX_DPLL_MULT_MASK, +- .div1_mask = AM33XX_DPLL_DIV_MASK, +- .enable_mask = AM33XX_DPLL_EN_MASK, +- .idlest_mask = AM33XX_ST_DPLL_CLK_MASK, +- .max_multiplier = 2047, +- .max_divider = 128, +- .min_divider = 1, +-}; +- +-/* CLKOUT: fdpll/M2 */ +-static struct clk dpll_ddr_ck; +- +-static const struct clk_ops dpll_ddr_ck_ops = { +- .recalc_rate = &omap3_dpll_recalc, +- .get_parent = &omap2_init_dpll_parent, +- .round_rate = &omap2_dpll_round_rate, +- .set_rate = &omap3_noncore_dpll_set_rate, +-}; +- +-static struct clk_hw_omap dpll_ddr_ck_hw = { +- .hw = { +- .clk = &dpll_ddr_ck, +- }, +- .dpll_data = &dpll_ddr_dd, +- .ops = &clkhwops_omap3_dpll, +-}; +- +-DEFINE_STRUCT_CLK(dpll_ddr_ck, dpll_core_ck_parents, dpll_ddr_ck_ops); +- +-/* +- * TODO: Add clksel here (sys_clkin, CORE_CLKOUTM6, PER_CLKOUTM2 +- * and ALT_CLK1/2) +- */ +-DEFINE_CLK_DIVIDER(dpll_ddr_m2_ck, "dpll_ddr_ck", &dpll_ddr_ck, +- 0x0, AM33XX_CM_DIV_M2_DPLL_DDR, +- AM33XX_DPLL_CLKOUT_DIV_SHIFT, AM33XX_DPLL_CLKOUT_DIV_WIDTH, +- CLK_DIVIDER_ONE_BASED, NULL); +- +-/* emif_fck functional clock */ +-DEFINE_CLK_FIXED_FACTOR(dpll_ddr_m2_div2_ck, "dpll_ddr_m2_ck", &dpll_ddr_m2_ck, +- 0x0, 1, 2); +- +-/* DPLL_DISP */ +-static struct dpll_data dpll_disp_dd = { +- .mult_div1_reg = AM33XX_CM_CLKSEL_DPLL_DISP, +- .clk_bypass = &sys_clkin_ck, +- .clk_ref = &sys_clkin_ck, +- .control_reg = AM33XX_CM_CLKMODE_DPLL_DISP, +- .modes = (1 << DPLL_LOW_POWER_BYPASS) | (1 << DPLL_LOCKED), +- .idlest_reg = AM33XX_CM_IDLEST_DPLL_DISP, +- .mult_mask = AM33XX_DPLL_MULT_MASK, +- .div1_mask = AM33XX_DPLL_DIV_MASK, +- .enable_mask = AM33XX_DPLL_EN_MASK, +- .idlest_mask = AM33XX_ST_DPLL_CLK_MASK, +- .max_multiplier = 2047, +- .max_divider = 128, +- .min_divider = 1, +-}; +- +-/* CLKOUT: fdpll/M2 */ +-static struct clk dpll_disp_ck; +- +-static struct clk_hw_omap dpll_disp_ck_hw = { +- .hw = { +- .clk = &dpll_disp_ck, +- }, +- .dpll_data = &dpll_disp_dd, +- .ops = &clkhwops_omap3_dpll, +-}; +- +-DEFINE_STRUCT_CLK(dpll_disp_ck, dpll_core_ck_parents, dpll_ddr_ck_ops); +- +-/* +- * TODO: Add clksel here (sys_clkin, CORE_CLKOUTM6, PER_CLKOUTM2 +- * and ALT_CLK1/2) +- */ +-DEFINE_CLK_DIVIDER(dpll_disp_m2_ck, "dpll_disp_ck", &dpll_disp_ck, +- CLK_SET_RATE_PARENT, AM33XX_CM_DIV_M2_DPLL_DISP, +- AM33XX_DPLL_CLKOUT_DIV_SHIFT, AM33XX_DPLL_CLKOUT_DIV_WIDTH, +- CLK_DIVIDER_ONE_BASED, NULL); +- +-/* DPLL_PER */ +-static struct dpll_data dpll_per_dd = { +- .mult_div1_reg = AM33XX_CM_CLKSEL_DPLL_PERIPH, +- .clk_bypass = &sys_clkin_ck, +- .clk_ref = &sys_clkin_ck, +- .control_reg = AM33XX_CM_CLKMODE_DPLL_PER, +- .modes = (1 << DPLL_LOW_POWER_BYPASS) | (1 << DPLL_LOCKED), +- .idlest_reg = AM33XX_CM_IDLEST_DPLL_PER, +- .mult_mask = AM33XX_DPLL_MULT_PERIPH_MASK, +- .div1_mask = AM33XX_DPLL_PER_DIV_MASK, +- .enable_mask = AM33XX_DPLL_EN_MASK, +- .idlest_mask = AM33XX_ST_DPLL_CLK_MASK, +- .max_multiplier = 2047, +- .max_divider = 128, +- .min_divider = 1, +- .flags = DPLL_J_TYPE, +-}; +- +-/* CLKDCOLDO */ +-static struct clk dpll_per_ck; +- +-static struct clk_hw_omap dpll_per_ck_hw = { +- .hw = { +- .clk = &dpll_per_ck, +- }, +- .dpll_data = &dpll_per_dd, +- .ops = &clkhwops_omap3_dpll, +-}; +- +-DEFINE_STRUCT_CLK(dpll_per_ck, dpll_core_ck_parents, dpll_ddr_ck_ops); +- +-/* CLKOUT: fdpll/M2 */ +-DEFINE_CLK_DIVIDER(dpll_per_m2_ck, "dpll_per_ck", &dpll_per_ck, 0x0, +- AM33XX_CM_DIV_M2_DPLL_PER, AM33XX_DPLL_CLKOUT_DIV_SHIFT, +- AM33XX_DPLL_CLKOUT_DIV_WIDTH, CLK_DIVIDER_ONE_BASED, +- NULL); +- +-DEFINE_CLK_FIXED_FACTOR(dpll_per_m2_div4_wkupdm_ck, "dpll_per_m2_ck", +- &dpll_per_m2_ck, 0x0, 1, 4); +- +-DEFINE_CLK_FIXED_FACTOR(dpll_per_m2_div4_ck, "dpll_per_m2_ck", +- &dpll_per_m2_ck, 0x0, 1, 4); +- +-DEFINE_CLK_FIXED_FACTOR(dpll_core_m4_div2_ck, "dpll_core_m4_ck", +- &dpll_core_m4_ck, 0x0, 1, 2); +- +-DEFINE_CLK_FIXED_FACTOR(l4_rtc_gclk, "dpll_core_m4_ck", &dpll_core_m4_ck, 0x0, +- 1, 2); +- +-DEFINE_CLK_FIXED_FACTOR(clk_24mhz, "dpll_per_m2_ck", &dpll_per_m2_ck, 0x0, 1, +- 8); +- +-/* +- * Below clock nodes describes clockdomains derived out +- * of core clock. +- */ +-static const struct clk_ops clk_ops_null = { +-}; +- +-static const char *l3_gclk_parents[] = { +- "dpll_core_m4_ck" +-}; +- +-static struct clk l3_gclk; +-DEFINE_STRUCT_CLK_HW_OMAP(l3_gclk, NULL); +-DEFINE_STRUCT_CLK(l3_gclk, l3_gclk_parents, clk_ops_null); +- +-static struct clk l4hs_gclk; +-DEFINE_STRUCT_CLK_HW_OMAP(l4hs_gclk, NULL); +-DEFINE_STRUCT_CLK(l4hs_gclk, l3_gclk_parents, clk_ops_null); +- +-static const char *l3s_gclk_parents[] = { +- "dpll_core_m4_div2_ck" +-}; +- +-static struct clk l3s_gclk; +-DEFINE_STRUCT_CLK_HW_OMAP(l3s_gclk, NULL); +-DEFINE_STRUCT_CLK(l3s_gclk, l3s_gclk_parents, clk_ops_null); +- +-static struct clk l4fw_gclk; +-DEFINE_STRUCT_CLK_HW_OMAP(l4fw_gclk, NULL); +-DEFINE_STRUCT_CLK(l4fw_gclk, l3s_gclk_parents, clk_ops_null); +- +-static struct clk l4ls_gclk; +-DEFINE_STRUCT_CLK_HW_OMAP(l4ls_gclk, NULL); +-DEFINE_STRUCT_CLK(l4ls_gclk, l3s_gclk_parents, clk_ops_null); +- +-static struct clk sysclk_div_ck; +-DEFINE_STRUCT_CLK_HW_OMAP(sysclk_div_ck, NULL); +-DEFINE_STRUCT_CLK(sysclk_div_ck, l3_gclk_parents, clk_ops_null); +- +-/* +- * In order to match the clock domain with hwmod clockdomain entry, +- * separate clock nodes is required for the modules which are +- * directly getting their funtioncal clock from sys_clkin. +- */ +-static struct clk adc_tsc_fck; +-DEFINE_STRUCT_CLK_HW_OMAP(adc_tsc_fck, NULL); +-DEFINE_STRUCT_CLK(adc_tsc_fck, dpll_core_ck_parents, clk_ops_null); +- +-static struct clk dcan0_fck; +-DEFINE_STRUCT_CLK_HW_OMAP(dcan0_fck, NULL); +-DEFINE_STRUCT_CLK(dcan0_fck, dpll_core_ck_parents, clk_ops_null); +- +-static struct clk dcan1_fck; +-DEFINE_STRUCT_CLK_HW_OMAP(dcan1_fck, NULL); +-DEFINE_STRUCT_CLK(dcan1_fck, dpll_core_ck_parents, clk_ops_null); +- +-static struct clk mcasp0_fck; +-DEFINE_STRUCT_CLK_HW_OMAP(mcasp0_fck, NULL); +-DEFINE_STRUCT_CLK(mcasp0_fck, dpll_core_ck_parents, clk_ops_null); +- +-static struct clk mcasp1_fck; +-DEFINE_STRUCT_CLK_HW_OMAP(mcasp1_fck, NULL); +-DEFINE_STRUCT_CLK(mcasp1_fck, dpll_core_ck_parents, clk_ops_null); +- +-static struct clk smartreflex0_fck; +-DEFINE_STRUCT_CLK_HW_OMAP(smartreflex0_fck, NULL); +-DEFINE_STRUCT_CLK(smartreflex0_fck, dpll_core_ck_parents, clk_ops_null); +- +-static struct clk smartreflex1_fck; +-DEFINE_STRUCT_CLK_HW_OMAP(smartreflex1_fck, NULL); +-DEFINE_STRUCT_CLK(smartreflex1_fck, dpll_core_ck_parents, clk_ops_null); +- +-static struct clk sha0_fck; +-DEFINE_STRUCT_CLK_HW_OMAP(sha0_fck, NULL); +-DEFINE_STRUCT_CLK(sha0_fck, dpll_core_ck_parents, clk_ops_null); +- +-static struct clk aes0_fck; +-DEFINE_STRUCT_CLK_HW_OMAP(aes0_fck, NULL); +-DEFINE_STRUCT_CLK(aes0_fck, dpll_core_ck_parents, clk_ops_null); +- +-static struct clk rng_fck; +-DEFINE_STRUCT_CLK_HW_OMAP(rng_fck, NULL); +-DEFINE_STRUCT_CLK(rng_fck, dpll_core_ck_parents, clk_ops_null); +- +-/* +- * Modules clock nodes +- * +- * The following clock leaf nodes are added for the moment because: +- * +- * - hwmod data is not present for these modules, either hwmod +- * control is not required or its not populated. +- * - Driver code is not yet migrated to use hwmod/runtime pm +- * - Modules outside kernel access (to disable them by default) +- * +- * - mmu (gfx domain) +- * - cefuse +- * - usbotg_fck (its additional clock and not really a modulemode) +- * - ieee5000 +- */ +- +-DEFINE_CLK_GATE(mmu_fck, "dpll_core_m4_ck", &dpll_core_m4_ck, 0x0, +- AM33XX_CM_GFX_MMUDATA_CLKCTRL, AM33XX_MODULEMODE_SWCTRL_SHIFT, +- 0x0, NULL); +- +-DEFINE_CLK_GATE(cefuse_fck, "sys_clkin_ck", &sys_clkin_ck, 0x0, +- AM33XX_CM_CEFUSE_CEFUSE_CLKCTRL, AM33XX_MODULEMODE_SWCTRL_SHIFT, +- 0x0, NULL); +- +-/* +- * clkdiv32 is generated from fixed division of 732.4219 +- */ +-DEFINE_CLK_FIXED_FACTOR(clkdiv32k_ck, "clk_24mhz", &clk_24mhz, 0x0, 1, 732); +- +-static struct clk clkdiv32k_ick; +- +-static const char *clkdiv32k_ick_parent_names[] = { +- "clkdiv32k_ck", +-}; +- +-static const struct clk_ops clkdiv32k_ick_ops = { +- .enable = &omap2_dflt_clk_enable, +- .disable = &omap2_dflt_clk_disable, +- .is_enabled = &omap2_dflt_clk_is_enabled, +- .init = &omap2_init_clk_clkdm, +-}; +- +-static struct clk_hw_omap clkdiv32k_ick_hw = { +- .hw = { +- .clk = &clkdiv32k_ick, +- }, +- .enable_reg = AM33XX_CM_PER_CLKDIV32K_CLKCTRL, +- .enable_bit = AM33XX_MODULEMODE_SWCTRL_SHIFT, +- .clkdm_name = "clk_24mhz_clkdm", +-}; +- +-DEFINE_STRUCT_CLK(clkdiv32k_ick, clkdiv32k_ick_parent_names, clkdiv32k_ick_ops); +- +-/* "usbotg_fck" is an additional clock and not really a modulemode */ +-DEFINE_CLK_GATE(usbotg_fck, "dpll_per_ck", &dpll_per_ck, 0x0, +- AM33XX_CM_CLKDCOLDO_DPLL_PER, AM33XX_ST_DPLL_CLKDCOLDO_SHIFT, +- 0x0, NULL); +- +-DEFINE_CLK_GATE(ieee5000_fck, "dpll_core_m4_div2_ck", &dpll_core_m4_div2_ck, +- 0x0, AM33XX_CM_PER_IEEE5000_CLKCTRL, +- AM33XX_MODULEMODE_SWCTRL_SHIFT, 0x0, NULL); +- +-/* Timers */ +-static const struct clksel timer1_clkmux_sel[] = { +- { .parent = &sys_clkin_ck, .rates = div_1_0_rates }, +- { .parent = &clkdiv32k_ick, .rates = div_1_1_rates }, +- { .parent = &tclkin_ck, .rates = div_1_2_rates }, +- { .parent = &clk_rc32k_ck, .rates = div_1_3_rates }, +- { .parent = &clk_32768_ck, .rates = div_1_4_rates }, +- { .parent = NULL }, +-}; +- +-static const char *timer1_ck_parents[] = { +- "sys_clkin_ck", "clkdiv32k_ick", "tclkin_ck", "clk_rc32k_ck", +- "clk_32768_ck", +-}; +- +-static struct clk timer1_fck; +- +-static const struct clk_ops timer1_fck_ops = { +- .recalc_rate = &omap2_clksel_recalc, +- .get_parent = &omap2_clksel_find_parent_index, +- .set_parent = &omap2_clksel_set_parent, +- .init = &omap2_init_clk_clkdm, +-}; +- +-static struct clk_hw_omap timer1_fck_hw = { +- .hw = { +- .clk = &timer1_fck, +- }, +- .clkdm_name = "l4ls_clkdm", +- .clksel = timer1_clkmux_sel, +- .clksel_reg = AM33XX_CLKSEL_TIMER1MS_CLK, +- .clksel_mask = AM33XX_CLKSEL_0_2_MASK, +-}; +- +-DEFINE_STRUCT_CLK(timer1_fck, timer1_ck_parents, timer1_fck_ops); +- +-static const struct clksel timer2_to_7_clk_sel[] = { +- { .parent = &tclkin_ck, .rates = div_1_0_rates }, +- { .parent = &sys_clkin_ck, .rates = div_1_1_rates }, +- { .parent = &clkdiv32k_ick, .rates = div_1_2_rates }, +- { .parent = NULL }, +-}; +- +-static const char *timer2_to_7_ck_parents[] = { +- "tclkin_ck", "sys_clkin_ck", "clkdiv32k_ick", +-}; +- +-static struct clk timer2_fck; +- +-static struct clk_hw_omap timer2_fck_hw = { +- .hw = { +- .clk = &timer2_fck, +- }, +- .clkdm_name = "l4ls_clkdm", +- .clksel = timer2_to_7_clk_sel, +- .clksel_reg = AM33XX_CLKSEL_TIMER2_CLK, +- .clksel_mask = AM33XX_CLKSEL_0_1_MASK, +-}; +- +-DEFINE_STRUCT_CLK(timer2_fck, timer2_to_7_ck_parents, timer1_fck_ops); +- +-static struct clk timer3_fck; +- +-static struct clk_hw_omap timer3_fck_hw = { +- .hw = { +- .clk = &timer3_fck, +- }, +- .clkdm_name = "l4ls_clkdm", +- .clksel = timer2_to_7_clk_sel, +- .clksel_reg = AM33XX_CLKSEL_TIMER3_CLK, +- .clksel_mask = AM33XX_CLKSEL_0_1_MASK, +-}; +- +-DEFINE_STRUCT_CLK(timer3_fck, timer2_to_7_ck_parents, timer1_fck_ops); +- +-static struct clk timer4_fck; +- +-static struct clk_hw_omap timer4_fck_hw = { +- .hw = { +- .clk = &timer4_fck, +- }, +- .clkdm_name = "l4ls_clkdm", +- .clksel = timer2_to_7_clk_sel, +- .clksel_reg = AM33XX_CLKSEL_TIMER4_CLK, +- .clksel_mask = AM33XX_CLKSEL_0_1_MASK, +-}; +- +-DEFINE_STRUCT_CLK(timer4_fck, timer2_to_7_ck_parents, timer1_fck_ops); +- +-static struct clk timer5_fck; +- +-static struct clk_hw_omap timer5_fck_hw = { +- .hw = { +- .clk = &timer5_fck, +- }, +- .clkdm_name = "l4ls_clkdm", +- .clksel = timer2_to_7_clk_sel, +- .clksel_reg = AM33XX_CLKSEL_TIMER5_CLK, +- .clksel_mask = AM33XX_CLKSEL_0_1_MASK, +-}; +- +-DEFINE_STRUCT_CLK(timer5_fck, timer2_to_7_ck_parents, timer1_fck_ops); +- +-static struct clk timer6_fck; +- +-static struct clk_hw_omap timer6_fck_hw = { +- .hw = { +- .clk = &timer6_fck, +- }, +- .clkdm_name = "l4ls_clkdm", +- .clksel = timer2_to_7_clk_sel, +- .clksel_reg = AM33XX_CLKSEL_TIMER6_CLK, +- .clksel_mask = AM33XX_CLKSEL_0_1_MASK, +-}; +- +-DEFINE_STRUCT_CLK(timer6_fck, timer2_to_7_ck_parents, timer1_fck_ops); +- +-static struct clk timer7_fck; +- +-static struct clk_hw_omap timer7_fck_hw = { +- .hw = { +- .clk = &timer7_fck, +- }, +- .clkdm_name = "l4ls_clkdm", +- .clksel = timer2_to_7_clk_sel, +- .clksel_reg = AM33XX_CLKSEL_TIMER7_CLK, +- .clksel_mask = AM33XX_CLKSEL_0_1_MASK, +-}; +- +-DEFINE_STRUCT_CLK(timer7_fck, timer2_to_7_ck_parents, timer1_fck_ops); +- +-DEFINE_CLK_FIXED_FACTOR(cpsw_125mhz_gclk, +- "dpll_core_m5_ck", +- &dpll_core_m5_ck, +- 0x0, +- 1, 2); +- +-static const struct clk_ops cpsw_fck_ops = { +- .recalc_rate = &omap2_clksel_recalc, +- .get_parent = &omap2_clksel_find_parent_index, +- .set_parent = &omap2_clksel_set_parent, +-}; +- +-static const struct clksel cpsw_cpts_rft_clkmux_sel[] = { +- { .parent = &dpll_core_m5_ck, .rates = div_1_0_rates }, +- { .parent = &dpll_core_m4_ck, .rates = div_1_1_rates }, +- { .parent = NULL }, +-}; +- +-static const char *cpsw_cpts_rft_ck_parents[] = { +- "dpll_core_m5_ck", "dpll_core_m4_ck", +-}; +- +-static struct clk cpsw_cpts_rft_clk; +- +-static struct clk_hw_omap cpsw_cpts_rft_clk_hw = { +- .hw = { +- .clk = &cpsw_cpts_rft_clk, +- }, +- .clkdm_name = "cpsw_125mhz_clkdm", +- .clksel = cpsw_cpts_rft_clkmux_sel, +- .clksel_reg = AM33XX_CM_CPTS_RFT_CLKSEL, +- .clksel_mask = AM33XX_CLKSEL_0_0_MASK, +-}; +- +-DEFINE_STRUCT_CLK(cpsw_cpts_rft_clk, cpsw_cpts_rft_ck_parents, cpsw_fck_ops); +- +- +-/* gpio */ +-static const char *gpio0_ck_parents[] = { +- "clk_rc32k_ck", "clk_32768_ck", "clkdiv32k_ick", +-}; +- +-static const struct clksel gpio0_dbclk_mux_sel[] = { +- { .parent = &clk_rc32k_ck, .rates = div_1_0_rates }, +- { .parent = &clk_32768_ck, .rates = div_1_1_rates }, +- { .parent = &clkdiv32k_ick, .rates = div_1_2_rates }, +- { .parent = NULL }, +-}; +- +-static const struct clk_ops gpio_fck_ops = { +- .recalc_rate = &omap2_clksel_recalc, +- .get_parent = &omap2_clksel_find_parent_index, +- .set_parent = &omap2_clksel_set_parent, +- .init = &omap2_init_clk_clkdm, +-}; +- +-static struct clk gpio0_dbclk_mux_ck; +- +-static struct clk_hw_omap gpio0_dbclk_mux_ck_hw = { +- .hw = { +- .clk = &gpio0_dbclk_mux_ck, +- }, +- .clkdm_name = "l4_wkup_clkdm", +- .clksel = gpio0_dbclk_mux_sel, +- .clksel_reg = AM33XX_CLKSEL_GPIO0_DBCLK, +- .clksel_mask = AM33XX_CLKSEL_0_1_MASK, +-}; +- +-DEFINE_STRUCT_CLK(gpio0_dbclk_mux_ck, gpio0_ck_parents, gpio_fck_ops); +- +-DEFINE_CLK_GATE(gpio0_dbclk, "gpio0_dbclk_mux_ck", &gpio0_dbclk_mux_ck, 0x0, +- AM33XX_CM_WKUP_GPIO0_CLKCTRL, +- AM33XX_OPTFCLKEN_GPIO0_GDBCLK_SHIFT, 0x0, NULL); +- +-DEFINE_CLK_GATE(gpio1_dbclk, "clkdiv32k_ick", &clkdiv32k_ick, 0x0, +- AM33XX_CM_PER_GPIO1_CLKCTRL, +- AM33XX_OPTFCLKEN_GPIO_1_GDBCLK_SHIFT, 0x0, NULL); +- +-DEFINE_CLK_GATE(gpio2_dbclk, "clkdiv32k_ick", &clkdiv32k_ick, 0x0, +- AM33XX_CM_PER_GPIO2_CLKCTRL, +- AM33XX_OPTFCLKEN_GPIO_2_GDBCLK_SHIFT, 0x0, NULL); +- +-DEFINE_CLK_GATE(gpio3_dbclk, "clkdiv32k_ick", &clkdiv32k_ick, 0x0, +- AM33XX_CM_PER_GPIO3_CLKCTRL, +- AM33XX_OPTFCLKEN_GPIO_3_GDBCLK_SHIFT, 0x0, NULL); +- +- +-static const char *pruss_ck_parents[] = { +- "l3_gclk", "dpll_disp_m2_ck", +-}; +- +-static const struct clksel pruss_ocp_clk_mux_sel[] = { +- { .parent = &l3_gclk, .rates = div_1_0_rates }, +- { .parent = &dpll_disp_m2_ck, .rates = div_1_1_rates }, +- { .parent = NULL }, +-}; +- +-static struct clk pruss_ocp_gclk; +- +-static struct clk_hw_omap pruss_ocp_gclk_hw = { +- .hw = { +- .clk = &pruss_ocp_gclk, +- }, +- .clkdm_name = "pruss_ocp_clkdm", +- .clksel = pruss_ocp_clk_mux_sel, +- .clksel_reg = AM33XX_CLKSEL_PRUSS_OCP_CLK, +- .clksel_mask = AM33XX_CLKSEL_0_0_MASK, +-}; +- +-DEFINE_STRUCT_CLK(pruss_ocp_gclk, pruss_ck_parents, gpio_fck_ops); +- +-static const char *lcd_ck_parents[] = { +- "dpll_disp_m2_ck", "dpll_core_m5_ck", "dpll_per_m2_ck", +-}; +- +-static const struct clksel lcd_clk_mux_sel[] = { +- { .parent = &dpll_disp_m2_ck, .rates = div_1_0_rates }, +- { .parent = &dpll_core_m5_ck, .rates = div_1_1_rates }, +- { .parent = &dpll_per_m2_ck, .rates = div_1_2_rates }, +- { .parent = NULL }, +-}; +- +-static struct clk lcd_gclk; +- +-static struct clk_hw_omap lcd_gclk_hw = { +- .hw = { +- .clk = &lcd_gclk, +- }, +- .clkdm_name = "lcdc_clkdm", +- .clksel = lcd_clk_mux_sel, +- .clksel_reg = AM33XX_CLKSEL_LCDC_PIXEL_CLK, +- .clksel_mask = AM33XX_CLKSEL_0_1_MASK, +-}; +- +-DEFINE_STRUCT_CLK_FLAGS(lcd_gclk, lcd_ck_parents, +- gpio_fck_ops, CLK_SET_RATE_PARENT); +- +-DEFINE_CLK_FIXED_FACTOR(mmc_clk, "dpll_per_m2_ck", &dpll_per_m2_ck, 0x0, 1, 2); +- +-static const char *gfx_ck_parents[] = { +- "dpll_core_m4_ck", "dpll_per_m2_ck", +-}; +- +-static const struct clksel gfx_clksel_sel[] = { +- { .parent = &dpll_core_m4_ck, .rates = div_1_0_rates }, +- { .parent = &dpll_per_m2_ck, .rates = div_1_1_rates }, +- { .parent = NULL }, +-}; +- +-static struct clk gfx_fclk_clksel_ck; +- +-static struct clk_hw_omap gfx_fclk_clksel_ck_hw = { +- .hw = { +- .clk = &gfx_fclk_clksel_ck, +- }, +- .clksel = gfx_clksel_sel, +- .clksel_reg = AM33XX_CLKSEL_GFX_FCLK, +- .clksel_mask = AM33XX_CLKSEL_GFX_FCLK_MASK, +-}; +- +-DEFINE_STRUCT_CLK(gfx_fclk_clksel_ck, gfx_ck_parents, gpio_fck_ops); +- +-static const struct clk_div_table div_1_0_2_1_rates[] = { +- { .div = 1, .val = 0, }, +- { .div = 2, .val = 1, }, +- { .div = 0 }, +-}; +- +-DEFINE_CLK_DIVIDER_TABLE(gfx_fck_div_ck, "gfx_fclk_clksel_ck", +- &gfx_fclk_clksel_ck, 0x0, AM33XX_CLKSEL_GFX_FCLK, +- AM33XX_CLKSEL_0_0_SHIFT, AM33XX_CLKSEL_0_0_WIDTH, +- 0x0, div_1_0_2_1_rates, NULL); +- +-static const char *sysclkout_ck_parents[] = { +- "clk_32768_ck", "l3_gclk", "dpll_ddr_m2_ck", "dpll_per_m2_ck", +- "lcd_gclk", +-}; +- +-static const struct clksel sysclkout_pre_sel[] = { +- { .parent = &clk_32768_ck, .rates = div_1_0_rates }, +- { .parent = &l3_gclk, .rates = div_1_1_rates }, +- { .parent = &dpll_ddr_m2_ck, .rates = div_1_2_rates }, +- { .parent = &dpll_per_m2_ck, .rates = div_1_3_rates }, +- { .parent = &lcd_gclk, .rates = div_1_4_rates }, +- { .parent = NULL }, +-}; +- +-static struct clk sysclkout_pre_ck; +- +-static struct clk_hw_omap sysclkout_pre_ck_hw = { +- .hw = { +- .clk = &sysclkout_pre_ck, +- }, +- .clksel = sysclkout_pre_sel, +- .clksel_reg = AM33XX_CM_CLKOUT_CTRL, +- .clksel_mask = AM33XX_CLKOUT2SOURCE_MASK, +-}; +- +-DEFINE_STRUCT_CLK(sysclkout_pre_ck, sysclkout_ck_parents, gpio_fck_ops); +- +-/* Divide by 8 clock rates with default clock is 1/1*/ +-static const struct clk_div_table div8_rates[] = { +- { .div = 1, .val = 0, }, +- { .div = 2, .val = 1, }, +- { .div = 3, .val = 2, }, +- { .div = 4, .val = 3, }, +- { .div = 5, .val = 4, }, +- { .div = 6, .val = 5, }, +- { .div = 7, .val = 6, }, +- { .div = 8, .val = 7, }, +- { .div = 0 }, +-}; +- +-DEFINE_CLK_DIVIDER_TABLE(clkout2_div_ck, "sysclkout_pre_ck", &sysclkout_pre_ck, +- 0x0, AM33XX_CM_CLKOUT_CTRL, AM33XX_CLKOUT2DIV_SHIFT, +- AM33XX_CLKOUT2DIV_WIDTH, 0x0, div8_rates, NULL); +- +-DEFINE_CLK_GATE(clkout2_ck, "clkout2_div_ck", &clkout2_div_ck, 0x0, +- AM33XX_CM_CLKOUT_CTRL, AM33XX_CLKOUT2EN_SHIFT, 0x0, NULL); +- +-static const char *wdt_ck_parents[] = { +- "clk_rc32k_ck", "clkdiv32k_ick", +-}; +- +-static const struct clksel wdt_clkmux_sel[] = { +- { .parent = &clk_rc32k_ck, .rates = div_1_0_rates }, +- { .parent = &clkdiv32k_ick, .rates = div_1_1_rates }, +- { .parent = NULL }, +-}; +- +-static struct clk wdt1_fck; +- +-static struct clk_hw_omap wdt1_fck_hw = { +- .hw = { +- .clk = &wdt1_fck, +- }, +- .clkdm_name = "l4_wkup_clkdm", +- .clksel = wdt_clkmux_sel, +- .clksel_reg = AM33XX_CLKSEL_WDT1_CLK, +- .clksel_mask = AM33XX_CLKSEL_0_1_MASK, +-}; +- +-DEFINE_STRUCT_CLK(wdt1_fck, wdt_ck_parents, gpio_fck_ops); +- +-static const char *pwmss_clk_parents[] = { +- "dpll_per_m2_ck", +-}; +- +-static const struct clk_ops ehrpwm_tbclk_ops = { +- .enable = &omap2_dflt_clk_enable, +- .disable = &omap2_dflt_clk_disable, +-}; +- +-DEFINE_CLK_OMAP_MUX_GATE(ehrpwm0_tbclk, "l4ls_clkdm", +- NULL, NULL, 0, +- AM33XX_CTRL_REGADDR(AM33XX_PWMSS_TBCLK_CLKCTRL), +- AM33XX_PWMSS0_TBCLKEN_SHIFT, +- NULL, pwmss_clk_parents, ehrpwm_tbclk_ops); +- +-DEFINE_CLK_OMAP_MUX_GATE(ehrpwm1_tbclk, "l4ls_clkdm", +- NULL, NULL, 0, +- AM33XX_CTRL_REGADDR(AM33XX_PWMSS_TBCLK_CLKCTRL), +- AM33XX_PWMSS1_TBCLKEN_SHIFT, +- NULL, pwmss_clk_parents, ehrpwm_tbclk_ops); +- +-DEFINE_CLK_OMAP_MUX_GATE(ehrpwm2_tbclk, "l4ls_clkdm", +- NULL, NULL, 0, +- AM33XX_CTRL_REGADDR(AM33XX_PWMSS_TBCLK_CLKCTRL), +- AM33XX_PWMSS2_TBCLKEN_SHIFT, +- NULL, pwmss_clk_parents, ehrpwm_tbclk_ops); +- +-/* +- * debugss optional clocks +- */ +-DEFINE_CLK_GATE(dbg_sysclk_ck, "sys_clkin_ck", &sys_clkin_ck, +- 0x0, AM33XX_CM_WKUP_DEBUGSS_CLKCTRL, +- AM33XX_OPTFCLKEN_DBGSYSCLK_SHIFT, 0x0, NULL); +- +-DEFINE_CLK_GATE(dbg_clka_ck, "dpll_core_m4_ck", &dpll_core_m4_ck, +- 0x0, AM33XX_CM_WKUP_DEBUGSS_CLKCTRL, +- AM33XX_OPTCLK_DEBUG_CLKA_SHIFT, 0x0, NULL); +- +-static const char *stm_pmd_clock_mux_ck_parents[] = { +- "dbg_sysclk_ck", "dbg_clka_ck", +-}; +- +-DEFINE_CLK_MUX(stm_pmd_clock_mux_ck, stm_pmd_clock_mux_ck_parents, NULL, 0x0, +- AM33XX_CM_WKUP_DEBUGSS_CLKCTRL, AM33XX_STM_PMD_CLKSEL_SHIFT, +- AM33XX_STM_PMD_CLKSEL_WIDTH, 0x0, NULL); +- +-DEFINE_CLK_MUX(trace_pmd_clk_mux_ck, stm_pmd_clock_mux_ck_parents, NULL, 0x0, +- AM33XX_CM_WKUP_DEBUGSS_CLKCTRL, +- AM33XX_TRC_PMD_CLKSEL_SHIFT, +- AM33XX_TRC_PMD_CLKSEL_WIDTH, 0x0, NULL); +- +-DEFINE_CLK_DIVIDER(stm_clk_div_ck, "stm_pmd_clock_mux_ck", +- &stm_pmd_clock_mux_ck, 0x0, AM33XX_CM_WKUP_DEBUGSS_CLKCTRL, +- AM33XX_STM_PMD_CLKDIVSEL_SHIFT, +- AM33XX_STM_PMD_CLKDIVSEL_WIDTH, CLK_DIVIDER_POWER_OF_TWO, +- NULL); +- +-DEFINE_CLK_DIVIDER(trace_clk_div_ck, "trace_pmd_clk_mux_ck", +- &trace_pmd_clk_mux_ck, 0x0, AM33XX_CM_WKUP_DEBUGSS_CLKCTRL, +- AM33XX_TRC_PMD_CLKDIVSEL_SHIFT, +- AM33XX_TRC_PMD_CLKDIVSEL_WIDTH, CLK_DIVIDER_POWER_OF_TWO, +- NULL); +- +-/* +- * clkdev +- */ +-static struct omap_clk am33xx_clks[] = { +- CLK(NULL, "clk_32768_ck", &clk_32768_ck), +- CLK(NULL, "clk_rc32k_ck", &clk_rc32k_ck), +- CLK(NULL, "virt_19200000_ck", &virt_19200000_ck), +- CLK(NULL, "virt_24000000_ck", &virt_24000000_ck), +- CLK(NULL, "virt_25000000_ck", &virt_25000000_ck), +- CLK(NULL, "virt_26000000_ck", &virt_26000000_ck), +- CLK(NULL, "sys_clkin_ck", &sys_clkin_ck), +- CLK(NULL, "tclkin_ck", &tclkin_ck), +- CLK(NULL, "dpll_core_ck", &dpll_core_ck), +- CLK(NULL, "dpll_core_x2_ck", &dpll_core_x2_ck), +- CLK(NULL, "dpll_core_m4_ck", &dpll_core_m4_ck), +- CLK(NULL, "dpll_core_m5_ck", &dpll_core_m5_ck), +- CLK(NULL, "dpll_core_m6_ck", &dpll_core_m6_ck), +- CLK(NULL, "dpll_mpu_ck", &dpll_mpu_ck), +- CLK("cpu0", NULL, &dpll_mpu_ck), +- CLK(NULL, "dpll_mpu_m2_ck", &dpll_mpu_m2_ck), +- CLK(NULL, "dpll_ddr_ck", &dpll_ddr_ck), +- CLK(NULL, "dpll_ddr_m2_ck", &dpll_ddr_m2_ck), +- CLK(NULL, "dpll_ddr_m2_div2_ck", &dpll_ddr_m2_div2_ck), +- CLK(NULL, "dpll_disp_ck", &dpll_disp_ck), +- CLK(NULL, "dpll_disp_m2_ck", &dpll_disp_m2_ck), +- CLK(NULL, "dpll_per_ck", &dpll_per_ck), +- CLK(NULL, "dpll_per_m2_ck", &dpll_per_m2_ck), +- CLK(NULL, "dpll_per_m2_div4_wkupdm_ck", &dpll_per_m2_div4_wkupdm_ck), +- CLK(NULL, "dpll_per_m2_div4_ck", &dpll_per_m2_div4_ck), +- CLK(NULL, "adc_tsc_fck", &adc_tsc_fck), +- CLK(NULL, "cefuse_fck", &cefuse_fck), +- CLK(NULL, "clkdiv32k_ck", &clkdiv32k_ck), +- CLK(NULL, "clkdiv32k_ick", &clkdiv32k_ick), +- CLK(NULL, "dcan0_fck", &dcan0_fck), +- CLK("481cc000.d_can", NULL, &dcan0_fck), +- CLK(NULL, "dcan1_fck", &dcan1_fck), +- CLK("481d0000.d_can", NULL, &dcan1_fck), +- CLK(NULL, "pruss_ocp_gclk", &pruss_ocp_gclk), +- CLK(NULL, "mcasp0_fck", &mcasp0_fck), +- CLK(NULL, "mcasp1_fck", &mcasp1_fck), +- CLK(NULL, "mmu_fck", &mmu_fck), +- CLK(NULL, "smartreflex0_fck", &smartreflex0_fck), +- CLK(NULL, "smartreflex1_fck", &smartreflex1_fck), +- CLK(NULL, "sha0_fck", &sha0_fck), +- CLK(NULL, "aes0_fck", &aes0_fck), +- CLK(NULL, "rng_fck", &rng_fck), +- CLK(NULL, "timer1_fck", &timer1_fck), +- CLK(NULL, "timer2_fck", &timer2_fck), +- CLK(NULL, "timer3_fck", &timer3_fck), +- CLK(NULL, "timer4_fck", &timer4_fck), +- CLK(NULL, "timer5_fck", &timer5_fck), +- CLK(NULL, "timer6_fck", &timer6_fck), +- CLK(NULL, "timer7_fck", &timer7_fck), +- CLK(NULL, "usbotg_fck", &usbotg_fck), +- CLK(NULL, "ieee5000_fck", &ieee5000_fck), +- CLK(NULL, "wdt1_fck", &wdt1_fck), +- CLK(NULL, "l4_rtc_gclk", &l4_rtc_gclk), +- CLK(NULL, "l3_gclk", &l3_gclk), +- CLK(NULL, "dpll_core_m4_div2_ck", &dpll_core_m4_div2_ck), +- CLK(NULL, "l4hs_gclk", &l4hs_gclk), +- CLK(NULL, "l3s_gclk", &l3s_gclk), +- CLK(NULL, "l4fw_gclk", &l4fw_gclk), +- CLK(NULL, "l4ls_gclk", &l4ls_gclk), +- CLK(NULL, "clk_24mhz", &clk_24mhz), +- CLK(NULL, "sysclk_div_ck", &sysclk_div_ck), +- CLK(NULL, "cpsw_125mhz_gclk", &cpsw_125mhz_gclk), +- CLK(NULL, "cpsw_cpts_rft_clk", &cpsw_cpts_rft_clk), +- CLK(NULL, "gpio0_dbclk_mux_ck", &gpio0_dbclk_mux_ck), +- CLK(NULL, "gpio0_dbclk", &gpio0_dbclk), +- CLK(NULL, "gpio1_dbclk", &gpio1_dbclk), +- CLK(NULL, "gpio2_dbclk", &gpio2_dbclk), +- CLK(NULL, "gpio3_dbclk", &gpio3_dbclk), +- CLK(NULL, "lcd_gclk", &lcd_gclk), +- CLK(NULL, "mmc_clk", &mmc_clk), +- CLK(NULL, "gfx_fclk_clksel_ck", &gfx_fclk_clksel_ck), +- CLK(NULL, "gfx_fck_div_ck", &gfx_fck_div_ck), +- CLK(NULL, "sysclkout_pre_ck", &sysclkout_pre_ck), +- CLK(NULL, "clkout2_div_ck", &clkout2_div_ck), +- CLK(NULL, "timer_32k_ck", &clkdiv32k_ick), +- CLK(NULL, "timer_sys_ck", &sys_clkin_ck), +- CLK(NULL, "dbg_sysclk_ck", &dbg_sysclk_ck), +- CLK(NULL, "dbg_clka_ck", &dbg_clka_ck), +- CLK(NULL, "stm_pmd_clock_mux_ck", &stm_pmd_clock_mux_ck), +- CLK(NULL, "trace_pmd_clk_mux_ck", &trace_pmd_clk_mux_ck), +- CLK(NULL, "stm_clk_div_ck", &stm_clk_div_ck), +- CLK(NULL, "trace_clk_div_ck", &trace_clk_div_ck), +- CLK(NULL, "clkout2_ck", &clkout2_ck), +- CLK("48300200.ehrpwm", "tbclk", &ehrpwm0_tbclk), +- CLK("48302200.ehrpwm", "tbclk", &ehrpwm1_tbclk), +- CLK("48304200.ehrpwm", "tbclk", &ehrpwm2_tbclk), +-}; +- +- +-static const char *enable_init_clks[] = { +- "dpll_ddr_m2_ck", +- "dpll_mpu_m2_ck", +- "l3_gclk", +- "l4hs_gclk", +- "l4fw_gclk", +- "l4ls_gclk", +- "clkout2_ck", /* Required for external peripherals like, Audio codecs */ +-}; +- +-int __init am33xx_clk_init(void) +-{ +- if (soc_is_am33xx()) +- cpu_mask = RATE_IN_AM33XX; +- +- omap_clocks_register(am33xx_clks, ARRAY_SIZE(am33xx_clks)); +- +- omap2_clk_disable_autoidle_all(); +- +- omap2_clk_enable_init_clocks(enable_init_clks, +- ARRAY_SIZE(enable_init_clks)); +- +- /* TRM ERRATA: Timer 3 & 6 default parent (TCLKIN) may not be always +- * physically present, in such a case HWMOD enabling of +- * clock would be failure with default parent. And timer +- * probe thinks clock is already enabled, this leads to +- * crash upon accessing timer 3 & 6 registers in probe. +- * Fix by setting parent of both these timers to master +- * oscillator clock. +- */ +- +- clk_set_parent(&timer3_fck, &sys_clkin_ck); +- clk_set_parent(&timer6_fck, &sys_clkin_ck); +- /* +- * The On-Chip 32K RC Osc clock is not an accurate clock-source as per +- * the design/spec, so as a result, for example, timer which supposed +- * to get expired @60Sec, but will expire somewhere ~@40Sec, which is +- * not expected by any use-case, so change WDT1 clock source to PRCM +- * 32KHz clock. +- */ +- clk_set_parent(&wdt1_fck, &clkdiv32k_ick); +- +- return 0; +-} +--- a/arch/arm/mach-omap2/clkt_dpll.c ++++ b/arch/arm/mach-omap2/clkt_dpll.c +@@ -209,7 +209,7 @@ u8 omap2_init_dpll_parent(struct clk_hw + if (v == OMAP3XXX_EN_DPLL_LPBYPASS || + v == OMAP3XXX_EN_DPLL_FRBYPASS) + return 1; +- } else if (soc_is_am33xx() || cpu_is_omap44xx()) { ++ } else if (soc_is_am33xx() || cpu_is_omap44xx() || soc_is_am43xx()) { + if (v == OMAP4XXX_EN_DPLL_LPBYPASS || + v == OMAP4XXX_EN_DPLL_FRBYPASS || + v == OMAP4XXX_EN_DPLL_MNBYPASS) +@@ -255,7 +255,7 @@ unsigned long omap2_get_dpll_rate(struct + if (v == OMAP3XXX_EN_DPLL_LPBYPASS || + v == OMAP3XXX_EN_DPLL_FRBYPASS) + return __clk_get_rate(dd->clk_bypass); +- } else if (soc_is_am33xx() || cpu_is_omap44xx()) { ++ } else if (soc_is_am33xx() || cpu_is_omap44xx() || soc_is_am43xx()) { + if (v == OMAP4XXX_EN_DPLL_LPBYPASS || + v == OMAP4XXX_EN_DPLL_FRBYPASS || + v == OMAP4XXX_EN_DPLL_MNBYPASS) +--- a/arch/arm/mach-omap2/clock3xxx.h ++++ b/arch/arm/mach-omap2/clock3xxx.h +@@ -9,11 +9,12 @@ + #define __ARCH_ARM_MACH_OMAP2_CLOCK3XXX_H + + int omap3xxx_clk_init(void); +-int omap3_dpll4_set_rate(struct clk_hw *clk, unsigned long rate, +- unsigned long parent_rate); ++int omap3430_clk_init(void); ++int omap3630_clk_init(void); ++int ti81xx_clk_init(void); ++int am35xx_clk_init(void); + int omap3_core_dpll_m2_set_rate(struct clk_hw *clk, unsigned long rate, + unsigned long parent_rate); +-void omap3_clk_lock_dpll5(void); + + extern struct clk *sdrc_ick_p; + extern struct clk *arm_fck_p; +--- a/arch/arm/mach-omap2/clock.c ++++ b/arch/arm/mach-omap2/clock.c +@@ -520,6 +520,9 @@ int omap2_clk_enable_autoidle_all(void) + list_for_each_entry(c, &clk_hw_omap_clocks, node) + if (c->ops && c->ops->allow_idle) + c->ops->allow_idle(c); ++ ++ of_omap_clk_allow_autoidle_all(); ++ + return 0; + } + +@@ -539,6 +542,9 @@ int omap2_clk_disable_autoidle_all(void) + list_for_each_entry(c, &clk_hw_omap_clocks, node) + if (c->ops && c->ops->deny_idle) + c->ops->deny_idle(c); ++ ++ of_omap_clk_deny_autoidle_all(); ++ + return 0; + } + +--- a/arch/arm/mach-omap2/clockdomain.h ++++ b/arch/arm/mach-omap2/clockdomain.h +@@ -132,7 +132,7 @@ struct clockdomain { + u8 _flags; + const u8 dep_bit; + const u8 prcm_partition; +- const s16 cm_inst; ++ const u16 cm_inst; + const u16 clkdm_offs; + struct clkdm_dep *wkdep_srcs; + struct clkdm_dep *sleepdep_srcs; +@@ -215,6 +215,7 @@ extern void __init omap242x_clockdomains + extern void __init omap243x_clockdomains_init(void); + extern void __init omap3xxx_clockdomains_init(void); + extern void __init am33xx_clockdomains_init(void); ++extern void am43xx_clockdomains_init(void); + extern void __init omap44xx_clockdomains_init(void); + extern void __init omap54xx_clockdomains_init(void); + extern void __init dra7xx_clockdomains_init(void); +@@ -226,6 +227,7 @@ extern struct clkdm_ops omap2_clkdm_oper + extern struct clkdm_ops omap3_clkdm_operations; + extern struct clkdm_ops omap4_clkdm_operations; + extern struct clkdm_ops am33xx_clkdm_operations; ++extern struct clkdm_ops am43xx_clkdm_operations; + + extern struct clkdm_dep gfx_24xx_wkdeps[]; + extern struct clkdm_dep dsp_24xx_wkdeps[]; +--- /dev/null ++++ b/arch/arm/mach-omap2/clockdomains43xx_data.c +@@ -0,0 +1,199 @@ ++/* ++ * AM43xx Clock domains framework ++ * ++ * Copyright (C) 2013 Texas Instruments, Inc. ++ * ++ * This file is made by modifying the file generated automatically ++ * from the OMAP hardware databases. ++ * ++ * 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 "clockdomain.h" ++#include "prcm44xx.h" ++#include "prcm43xx.h" ++ ++static struct clockdomain l4_cefuse_43xx_clkdm = { ++ .name = "l4_cefuse_clkdm", ++ .pwrdm = { .name = "cefuse_pwrdm" }, ++ .prcm_partition = AM43XX_CM_PARTITION, ++ .cm_inst = AM43XX_CM_CEFUSE_INST, ++ .clkdm_offs = AM43XX_CM_CEFUSE_CEFUSE_CDOFFS, ++ .flags = CLKDM_CAN_SWSUP, ++}; ++ ++static struct clockdomain mpu_43xx_clkdm = { ++ .name = "mpu_clkdm", ++ .pwrdm = { .name = "mpu_pwrdm" }, ++ .prcm_partition = AM43XX_CM_PARTITION, ++ .cm_inst = AM43XX_CM_MPU_INST, ++ .clkdm_offs = AM43XX_CM_MPU_MPU_CDOFFS, ++ .flags = CLKDM_CAN_HWSUP_SWSUP, ++}; ++ ++static struct clockdomain l4ls_43xx_clkdm = { ++ .name = "l4ls_clkdm", ++ .pwrdm = { .name = "per_pwrdm" }, ++ .prcm_partition = AM43XX_CM_PARTITION, ++ .cm_inst = AM43XX_CM_PER_INST, ++ .clkdm_offs = AM43XX_CM_PER_L4LS_CDOFFS, ++ .flags = CLKDM_CAN_SWSUP, ++}; ++ ++static struct clockdomain tamper_43xx_clkdm = { ++ .name = "tamper_clkdm", ++ .pwrdm = { .name = "tamper_pwrdm" }, ++ .prcm_partition = AM43XX_CM_PARTITION, ++ .cm_inst = AM43XX_CM_TAMPER_INST, ++ .clkdm_offs = AM43XX_CM_TAMPER_TAMPER_CDOFFS, ++ .flags = CLKDM_CAN_SWSUP, ++}; ++ ++static struct clockdomain l4_rtc_43xx_clkdm = { ++ .name = "l4_rtc_clkdm", ++ .pwrdm = { .name = "rtc_pwrdm" }, ++ .prcm_partition = AM43XX_CM_PARTITION, ++ .cm_inst = AM43XX_CM_RTC_INST, ++ .clkdm_offs = AM43XX_CM_RTC_RTC_CDOFFS, ++ .flags = CLKDM_CAN_SWSUP, ++}; ++ ++static struct clockdomain pruss_ocp_43xx_clkdm = { ++ .name = "pruss_ocp_clkdm", ++ .pwrdm = { .name = "per_pwrdm" }, ++ .prcm_partition = AM43XX_CM_PARTITION, ++ .cm_inst = AM43XX_CM_PER_INST, ++ .clkdm_offs = AM43XX_CM_PER_ICSS_CDOFFS, ++ .flags = CLKDM_CAN_SWSUP, ++}; ++ ++static struct clockdomain ocpwp_l3_43xx_clkdm = { ++ .name = "ocpwp_l3_clkdm", ++ .pwrdm = { .name = "per_pwrdm" }, ++ .prcm_partition = AM43XX_CM_PARTITION, ++ .cm_inst = AM43XX_CM_PER_INST, ++ .clkdm_offs = AM43XX_CM_PER_OCPWP_L3_CDOFFS, ++ .flags = CLKDM_CAN_SWSUP, ++}; ++ ++static struct clockdomain l3s_tsc_43xx_clkdm = { ++ .name = "l3s_tsc_clkdm", ++ .pwrdm = { .name = "wkup_pwrdm" }, ++ .prcm_partition = AM43XX_CM_PARTITION, ++ .cm_inst = AM43XX_CM_WKUP_INST, ++ .clkdm_offs = AM43XX_CM_WKUP_L3S_TSC_CDOFFS, ++ .flags = CLKDM_CAN_SWSUP, ++}; ++ ++static struct clockdomain dss_43xx_clkdm = { ++ .name = "dss_clkdm", ++ .pwrdm = { .name = "per_pwrdm" }, ++ .prcm_partition = AM43XX_CM_PARTITION, ++ .cm_inst = AM43XX_CM_PER_INST, ++ .clkdm_offs = AM43XX_CM_PER_DSS_CDOFFS, ++ .flags = CLKDM_CAN_SWSUP, ++}; ++ ++static struct clockdomain l3_aon_43xx_clkdm = { ++ .name = "l3_aon_clkdm", ++ .pwrdm = { .name = "wkup_pwrdm" }, ++ .prcm_partition = AM43XX_CM_PARTITION, ++ .cm_inst = AM43XX_CM_WKUP_INST, ++ .clkdm_offs = AM43XX_CM_WKUP_L3_AON_CDOFFS, ++ .flags = CLKDM_CAN_SWSUP, ++}; ++ ++static struct clockdomain emif_43xx_clkdm = { ++ .name = "emif_clkdm", ++ .pwrdm = { .name = "per_pwrdm" }, ++ .prcm_partition = AM43XX_CM_PARTITION, ++ .cm_inst = AM43XX_CM_PER_INST, ++ .clkdm_offs = AM43XX_CM_PER_EMIF_CDOFFS, ++ .flags = CLKDM_CAN_SWSUP, ++}; ++ ++static struct clockdomain l4_wkup_aon_43xx_clkdm = { ++ .name = "l4_wkup_aon_clkdm", ++ .pwrdm = { .name = "wkup_pwrdm" }, ++ .prcm_partition = AM43XX_CM_PARTITION, ++ .cm_inst = AM43XX_CM_WKUP_INST, ++ .clkdm_offs = AM43XX_CM_WKUP_L4_WKUP_AON_CDOFFS, ++}; ++ ++static struct clockdomain l3_43xx_clkdm = { ++ .name = "l3_clkdm", ++ .pwrdm = { .name = "per_pwrdm" }, ++ .prcm_partition = AM43XX_CM_PARTITION, ++ .cm_inst = AM43XX_CM_PER_INST, ++ .clkdm_offs = AM43XX_CM_PER_L3_CDOFFS, ++ .flags = CLKDM_CAN_SWSUP, ++}; ++ ++static struct clockdomain l4_wkup_43xx_clkdm = { ++ .name = "l4_wkup_clkdm", ++ .pwrdm = { .name = "wkup_pwrdm" }, ++ .prcm_partition = AM43XX_CM_PARTITION, ++ .cm_inst = AM43XX_CM_WKUP_INST, ++ .clkdm_offs = AM43XX_CM_WKUP_WKUP_CDOFFS, ++ .flags = CLKDM_CAN_SWSUP, ++}; ++ ++static struct clockdomain cpsw_125mhz_43xx_clkdm = { ++ .name = "cpsw_125mhz_clkdm", ++ .pwrdm = { .name = "per_pwrdm" }, ++ .prcm_partition = AM43XX_CM_PARTITION, ++ .cm_inst = AM43XX_CM_PER_INST, ++ .clkdm_offs = AM43XX_CM_PER_CPSW_CDOFFS, ++ .flags = CLKDM_CAN_SWSUP, ++}; ++ ++static struct clockdomain gfx_l3_43xx_clkdm = { ++ .name = "gfx_l3_clkdm", ++ .pwrdm = { .name = "gfx_pwrdm" }, ++ .prcm_partition = AM43XX_CM_PARTITION, ++ .cm_inst = AM43XX_CM_GFX_INST, ++ .clkdm_offs = AM43XX_CM_GFX_GFX_L3_CDOFFS, ++ .flags = CLKDM_CAN_SWSUP, ++}; ++ ++static struct clockdomain l3s_43xx_clkdm = { ++ .name = "l3s_clkdm", ++ .pwrdm = { .name = "per_pwrdm" }, ++ .prcm_partition = AM43XX_CM_PARTITION, ++ .cm_inst = AM43XX_CM_PER_INST, ++ .clkdm_offs = AM43XX_CM_PER_L3S_CDOFFS, ++ .flags = CLKDM_CAN_SWSUP, ++}; ++ ++static struct clockdomain *clockdomains_am43xx[] __initdata = { ++ &l4_cefuse_43xx_clkdm, ++ &mpu_43xx_clkdm, ++ &l4ls_43xx_clkdm, ++ &tamper_43xx_clkdm, ++ &l4_rtc_43xx_clkdm, ++ &pruss_ocp_43xx_clkdm, ++ &ocpwp_l3_43xx_clkdm, ++ &l3s_tsc_43xx_clkdm, ++ &dss_43xx_clkdm, ++ &l3_aon_43xx_clkdm, ++ &emif_43xx_clkdm, ++ &l4_wkup_aon_43xx_clkdm, ++ &l3_43xx_clkdm, ++ &l4_wkup_43xx_clkdm, ++ &cpsw_125mhz_43xx_clkdm, ++ &gfx_l3_43xx_clkdm, ++ &l3s_43xx_clkdm, ++ NULL ++}; ++ ++void __init am43xx_clockdomains_init(void) ++{ ++ clkdm_register_platform_funcs(&am43xx_clkdm_operations); ++ clkdm_register_clkdms(clockdomains_am43xx); ++ clkdm_complete_init(); ++} +--- a/arch/arm/mach-omap2/clockdomains7xx_data.c ++++ b/arch/arm/mach-omap2/clockdomains7xx_data.c +@@ -409,7 +409,7 @@ static struct clockdomain l4sec_7xx_clkd + .dep_bit = DRA7XX_L4SEC_STATDEP_SHIFT, + .wkdep_srcs = l4sec_wkup_sleep_deps, + .sleepdep_srcs = l4sec_wkup_sleep_deps, +- .flags = CLKDM_CAN_HWSUP_SWSUP, ++ .flags = CLKDM_CAN_SWSUP, + }; + + static struct clockdomain l3main1_7xx_clkdm = { +@@ -554,7 +554,7 @@ static struct clockdomain dss_7xx_clkdm + .dep_bit = DRA7XX_DSS_STATDEP_SHIFT, + .wkdep_srcs = dss_wkup_sleep_deps, + .sleepdep_srcs = dss_wkup_sleep_deps, +- .flags = CLKDM_CAN_HWSUP_SWSUP, ++ .flags = CLKDM_CAN_SWSUP, + }; + + static struct clockdomain emif_7xx_clkdm = { +--- a/arch/arm/mach-omap2/clock.h ++++ b/arch/arm/mach-omap2/clock.h +@@ -21,6 +21,7 @@ + + #include <linux/clkdev.h> + #include <linux/clk-provider.h> ++#include <linux/clk/ti.h> + + struct omap_clk { + u16 cpu; +@@ -37,7 +38,6 @@ struct omap_clk { + } + + struct clockdomain; +-#define to_clk_hw_omap(_hw) container_of(_hw, struct clk_hw_omap, hw) + + #define DEFINE_STRUCT_CLK(_name, _parent_array_name, _clkops_name) \ + static struct clk _name = { \ +@@ -178,141 +178,6 @@ struct clksel { + const struct clksel_rate *rates; + }; + +-/** +- * struct dpll_data - DPLL registers and integration data +- * @mult_div1_reg: register containing the DPLL M and N bitfields +- * @mult_mask: mask of the DPLL M bitfield in @mult_div1_reg +- * @div1_mask: mask of the DPLL N bitfield in @mult_div1_reg +- * @clk_bypass: struct clk pointer to the clock's bypass clock input +- * @clk_ref: struct clk pointer to the clock's reference clock input +- * @control_reg: register containing the DPLL mode bitfield +- * @enable_mask: mask of the DPLL mode bitfield in @control_reg +- * @last_rounded_rate: cache of the last rate result of omap2_dpll_round_rate() +- * @last_rounded_m: cache of the last M result of omap2_dpll_round_rate() +- * @last_rounded_m4xen: cache of the last M4X result of +- * omap4_dpll_regm4xen_round_rate() +- * @last_rounded_lpmode: cache of the last lpmode result of +- * omap4_dpll_lpmode_recalc() +- * @max_multiplier: maximum valid non-bypass multiplier value (actual) +- * @last_rounded_n: cache of the last N result of omap2_dpll_round_rate() +- * @min_divider: minimum valid non-bypass divider value (actual) +- * @max_divider: maximum valid non-bypass divider value (actual) +- * @modes: possible values of @enable_mask +- * @autoidle_reg: register containing the DPLL autoidle mode bitfield +- * @idlest_reg: register containing the DPLL idle status bitfield +- * @autoidle_mask: mask of the DPLL autoidle mode bitfield in @autoidle_reg +- * @freqsel_mask: mask of the DPLL jitter correction bitfield in @control_reg +- * @idlest_mask: mask of the DPLL idle status bitfield in @idlest_reg +- * @lpmode_mask: mask of the DPLL low-power mode bitfield in @control_reg +- * @m4xen_mask: mask of the DPLL M4X multiplier bitfield in @control_reg +- * @auto_recal_bit: bitshift of the driftguard enable bit in @control_reg +- * @recal_en_bit: bitshift of the PRM_IRQENABLE_* bit for recalibration IRQs +- * @recal_st_bit: bitshift of the PRM_IRQSTATUS_* bit for recalibration IRQs +- * @flags: DPLL type/features (see below) +- * +- * Possible values for @flags: +- * DPLL_J_TYPE: "J-type DPLL" (only some 36xx, 4xxx DPLLs) +- * +- * @freqsel_mask is only used on the OMAP34xx family and AM35xx. +- * +- * XXX Some DPLLs have multiple bypass inputs, so it's not technically +- * correct to only have one @clk_bypass pointer. +- * +- * XXX The runtime-variable fields (@last_rounded_rate, @last_rounded_m, +- * @last_rounded_n) should be separated from the runtime-fixed fields +- * and placed into a different structure, so that the runtime-fixed data +- * can be placed into read-only space. +- */ +-struct dpll_data { +- void __iomem *mult_div1_reg; +- u32 mult_mask; +- u32 div1_mask; +- struct clk *clk_bypass; +- struct clk *clk_ref; +- void __iomem *control_reg; +- u32 enable_mask; +- unsigned long last_rounded_rate; +- u16 last_rounded_m; +- u8 last_rounded_m4xen; +- u8 last_rounded_lpmode; +- u16 max_multiplier; +- u8 last_rounded_n; +- u8 min_divider; +- u16 max_divider; +- u8 modes; +- void __iomem *autoidle_reg; +- void __iomem *idlest_reg; +- u32 autoidle_mask; +- u32 freqsel_mask; +- u32 idlest_mask; +- u32 dco_mask; +- u32 sddiv_mask; +- u32 lpmode_mask; +- u32 m4xen_mask; +- u8 auto_recal_bit; +- u8 recal_en_bit; +- u8 recal_st_bit; +- u8 flags; +-}; +- +-/* +- * struct clk.flags possibilities +- * +- * XXX document the rest of the clock flags here +- * +- * CLOCK_CLKOUTX2: (OMAP4 only) DPLL CLKOUT and CLKOUTX2 GATE_CTRL +- * bits share the same register. This flag allows the +- * omap4_dpllmx*() code to determine which GATE_CTRL bit field +- * should be used. This is a temporary solution - a better approach +- * would be to associate clock type-specific data with the clock, +- * similar to the struct dpll_data approach. +- */ +-#define ENABLE_REG_32BIT (1 << 0) /* Use 32-bit access */ +-#define CLOCK_IDLE_CONTROL (1 << 1) +-#define CLOCK_NO_IDLE_PARENT (1 << 2) +-#define ENABLE_ON_INIT (1 << 3) /* Enable upon framework init */ +-#define INVERT_ENABLE (1 << 4) /* 0 enables, 1 disables */ +-#define CLOCK_CLKOUTX2 (1 << 5) +- +-/** +- * struct clk_hw_omap - OMAP struct clk +- * @node: list_head connecting this clock into the full clock list +- * @enable_reg: register to write to enable the clock (see @enable_bit) +- * @enable_bit: bitshift to write to enable/disable the clock (see @enable_reg) +- * @flags: see "struct clk.flags possibilities" above +- * @clksel_reg: for clksel clks, register va containing src/divisor select +- * @clksel_mask: bitmask in @clksel_reg for the src/divisor selector +- * @clksel: for clksel clks, pointer to struct clksel for this clock +- * @dpll_data: for DPLLs, pointer to struct dpll_data for this clock +- * @clkdm_name: clockdomain name that this clock is contained in +- * @clkdm: pointer to struct clockdomain, resolved from @clkdm_name at runtime +- * @rate_offset: bitshift for rate selection bitfield (OMAP1 only) +- * @src_offset: bitshift for source selection bitfield (OMAP1 only) +- * +- * XXX @rate_offset, @src_offset should probably be removed and OMAP1 +- * clock code converted to use clksel. +- * +- */ +- +-struct clk_hw_omap_ops; +- +-struct clk_hw_omap { +- struct clk_hw hw; +- struct list_head node; +- unsigned long fixed_rate; +- u8 fixed_div; +- void __iomem *enable_reg; +- u8 enable_bit; +- u8 flags; +- void __iomem *clksel_reg; +- u32 clksel_mask; +- const struct clksel *clksel; +- struct dpll_data *dpll_data; +- const char *clkdm_name; +- struct clockdomain *clkdm; +- const struct clk_hw_omap_ops *ops; +-}; +- + struct clk_hw_omap_ops { + void (*find_idlest)(struct clk_hw_omap *oclk, + void __iomem **idlest_reg, +@@ -348,36 +213,13 @@ unsigned long omap_fixed_divisor_recalc( + #define OMAP4XXX_EN_DPLL_FRBYPASS 0x6 + #define OMAP4XXX_EN_DPLL_LOCKED 0x7 + +-/* CM_CLKEN_PLL*.EN* bit values - not all are available for every DPLL */ +-#define DPLL_LOW_POWER_STOP 0x1 +-#define DPLL_LOW_POWER_BYPASS 0x5 +-#define DPLL_LOCKED 0x7 +- +-/* DPLL Type and DCO Selection Flags */ +-#define DPLL_J_TYPE 0x1 +- +-long omap2_dpll_round_rate(struct clk_hw *hw, unsigned long target_rate, +- unsigned long *parent_rate); +-unsigned long omap3_dpll_recalc(struct clk_hw *hw, unsigned long parent_rate); +-int omap3_noncore_dpll_enable(struct clk_hw *hw); +-void omap3_noncore_dpll_disable(struct clk_hw *hw); +-int omap3_noncore_dpll_set_rate(struct clk_hw *hw, unsigned long rate, +- unsigned long parent_rate); + u32 omap3_dpll_autoidle_read(struct clk_hw_omap *clk); + void omap3_dpll_allow_idle(struct clk_hw_omap *clk); + void omap3_dpll_deny_idle(struct clk_hw_omap *clk); +-unsigned long omap3_clkoutx2_recalc(struct clk_hw *hw, +- unsigned long parent_rate); + int omap4_dpllmx_gatectrl_read(struct clk_hw_omap *clk); + void omap4_dpllmx_allow_gatectrl(struct clk_hw_omap *clk); + void omap4_dpllmx_deny_gatectrl(struct clk_hw_omap *clk); +-unsigned long omap4_dpll_regm4xen_recalc(struct clk_hw *hw, +- unsigned long parent_rate); +-long omap4_dpll_regm4xen_round_rate(struct clk_hw *hw, +- unsigned long target_rate, +- unsigned long *parent_rate); + +-void omap2_init_clk_clkdm(struct clk_hw *clk); + void __init omap2_clk_disable_clkdm_control(void); + + /* clkt_clksel.c public functions */ +@@ -396,22 +238,15 @@ int omap2_clksel_set_parent(struct clk_h + extern void omap2_clkt_iclk_allow_idle(struct clk_hw_omap *clk); + extern void omap2_clkt_iclk_deny_idle(struct clk_hw_omap *clk); + +-u8 omap2_init_dpll_parent(struct clk_hw *hw); + unsigned long omap2_get_dpll_rate(struct clk_hw_omap *clk); + +-int omap2_dflt_clk_enable(struct clk_hw *hw); +-void omap2_dflt_clk_disable(struct clk_hw *hw); +-int omap2_dflt_clk_is_enabled(struct clk_hw *hw); + void omap2_clk_dflt_find_companion(struct clk_hw_omap *clk, + void __iomem **other_reg, + u8 *other_bit); + void omap2_clk_dflt_find_idlest(struct clk_hw_omap *clk, + void __iomem **idlest_reg, + u8 *idlest_bit, u8 *idlest_val); +-void omap2_init_clk_hw_omap_clocks(struct clk *clk); + int omap2_clk_enable_autoidle_all(void); +-int omap2_clk_disable_autoidle_all(void); +-void omap2_clk_enable_init_clocks(const char **clk_names, u8 num_clocks); + int omap2_clk_switch_mpurate_at_boot(const char *mpurate_ck_name); + void omap2_clk_print_new_rates(const char *hfclkin_ck_name, + const char *core_ck_name, +@@ -431,19 +266,8 @@ extern const struct clksel_rate gfx_l3_r + extern const struct clksel_rate dsp_ick_rates[]; + extern struct clk dummy_ck; + +-extern const struct clk_hw_omap_ops clkhwops_omap3_dpll; +-extern const struct clk_hw_omap_ops clkhwops_iclk_wait; +-extern const struct clk_hw_omap_ops clkhwops_wait; +-extern const struct clk_hw_omap_ops clkhwops_omap4_dpllmx; +-extern const struct clk_hw_omap_ops clkhwops_iclk; + extern const struct clk_hw_omap_ops clkhwops_omap3430es2_ssi_wait; +-extern const struct clk_hw_omap_ops clkhwops_omap3430es2_iclk_ssi_wait; +-extern const struct clk_hw_omap_ops clkhwops_omap3430es2_dss_usbhost_wait; +-extern const struct clk_hw_omap_ops clkhwops_omap3430es2_iclk_dss_usbhost_wait; +-extern const struct clk_hw_omap_ops clkhwops_omap3430es2_iclk_hsotgusb_wait; + extern const struct clk_hw_omap_ops clkhwops_omap3430es2_hsotgusb_wait; +-extern const struct clk_hw_omap_ops clkhwops_am35xx_ipss_module_wait; +-extern const struct clk_hw_omap_ops clkhwops_am35xx_ipss_wait; + extern const struct clk_hw_omap_ops clkhwops_apll54; + extern const struct clk_hw_omap_ops clkhwops_apll96; + extern const struct clk_hw_omap_ops clkhwops_omap2xxx_dpll; +@@ -460,8 +284,5 @@ extern const struct clksel_rate div31_1t + + extern int am33xx_clk_init(void); + +-extern int omap2_clkops_enable_clkdm(struct clk_hw *hw); +-extern void omap2_clkops_disable_clkdm(struct clk_hw *hw); +- + extern void omap_clocks_register(struct omap_clk *oclks, int cnt); + #endif +--- a/arch/arm/mach-omap2/cm33xx.c ++++ b/arch/arm/mach-omap2/cm33xx.c +@@ -48,13 +48,13 @@ + /* Private functions */ + + /* Read a register in a CM instance */ +-static inline u32 am33xx_cm_read_reg(s16 inst, u16 idx) ++static inline u32 am33xx_cm_read_reg(u16 inst, u16 idx) + { + return __raw_readl(cm_base + inst + idx); + } + + /* Write into a register in a CM */ +-static inline void am33xx_cm_write_reg(u32 val, s16 inst, u16 idx) ++static inline void am33xx_cm_write_reg(u32 val, u16 inst, u16 idx) + { + __raw_writel(val, cm_base + inst + idx); + } +@@ -82,7 +82,7 @@ static inline u32 am33xx_cm_clear_reg_bi + return am33xx_cm_rmw_reg_bits(bits, 0x0, inst, idx); + } + +-static inline u32 am33xx_cm_read_reg_bits(u16 inst, s16 idx, u32 mask) ++static inline u32 am33xx_cm_read_reg_bits(u16 inst, u16 idx, u32 mask) + { + u32 v; + +@@ -102,7 +102,7 @@ static inline u32 am33xx_cm_read_reg_bit + * Return the IDLEST bitfield of a CM_*_CLKCTRL register, shifted down to + * bit 0. + */ +-static u32 _clkctrl_idlest(u16 inst, s16 cdoffs, u16 clkctrl_offs) ++static u32 _clkctrl_idlest(u16 inst, u16 cdoffs, u16 clkctrl_offs) + { + u32 v = am33xx_cm_read_reg(inst, clkctrl_offs); + v &= AM33XX_IDLEST_MASK; +@@ -119,7 +119,7 @@ static u32 _clkctrl_idlest(u16 inst, s16 + * Returns true if the module's CM_*_CLKCTRL.IDLEST bitfield is either + * *FUNCTIONAL or *INTERFACE_IDLE; false otherwise. + */ +-static bool _is_module_ready(u16 inst, s16 cdoffs, u16 clkctrl_offs) ++static bool _is_module_ready(u16 inst, u16 cdoffs, u16 clkctrl_offs) + { + u32 v; + +@@ -138,7 +138,7 @@ static bool _is_module_ready(u16 inst, s + * @c must be the unshifted value for CLKTRCTRL - i.e., this function + * will handle the shift itself. + */ +-static void _clktrctrl_write(u8 c, s16 inst, u16 cdoffs) ++static void _clktrctrl_write(u8 c, u16 inst, u16 cdoffs) + { + u32 v; + +@@ -158,7 +158,7 @@ static void _clktrctrl_write(u8 c, s16 i + * Returns true if the clockdomain referred to by (@inst, @cdoffs) + * is in hardware-supervised idle mode, or 0 otherwise. + */ +-bool am33xx_cm_is_clkdm_in_hwsup(s16 inst, u16 cdoffs) ++bool am33xx_cm_is_clkdm_in_hwsup(u16 inst, u16 cdoffs) + { + u32 v; + +@@ -177,7 +177,7 @@ bool am33xx_cm_is_clkdm_in_hwsup(s16 ins + * Put a clockdomain referred to by (@inst, @cdoffs) into + * hardware-supervised idle mode. No return value. + */ +-void am33xx_cm_clkdm_enable_hwsup(s16 inst, u16 cdoffs) ++void am33xx_cm_clkdm_enable_hwsup(u16 inst, u16 cdoffs) + { + _clktrctrl_write(OMAP34XX_CLKSTCTRL_ENABLE_AUTO, inst, cdoffs); + } +@@ -191,7 +191,7 @@ void am33xx_cm_clkdm_enable_hwsup(s16 in + * software-supervised idle mode, i.e., controlled manually by the + * Linux OMAP clockdomain code. No return value. + */ +-void am33xx_cm_clkdm_disable_hwsup(s16 inst, u16 cdoffs) ++void am33xx_cm_clkdm_disable_hwsup(u16 inst, u16 cdoffs) + { + _clktrctrl_write(OMAP34XX_CLKSTCTRL_DISABLE_AUTO, inst, cdoffs); + } +@@ -204,7 +204,7 @@ void am33xx_cm_clkdm_disable_hwsup(s16 i + * Put a clockdomain referred to by (@inst, @cdoffs) into idle + * No return value. + */ +-void am33xx_cm_clkdm_force_sleep(s16 inst, u16 cdoffs) ++void am33xx_cm_clkdm_force_sleep(u16 inst, u16 cdoffs) + { + _clktrctrl_write(OMAP34XX_CLKSTCTRL_FORCE_SLEEP, inst, cdoffs); + } +@@ -217,7 +217,7 @@ void am33xx_cm_clkdm_force_sleep(s16 ins + * Take a clockdomain referred to by (@inst, @cdoffs) out of idle, + * waking it up. No return value. + */ +-void am33xx_cm_clkdm_force_wakeup(s16 inst, u16 cdoffs) ++void am33xx_cm_clkdm_force_wakeup(u16 inst, u16 cdoffs) + { + _clktrctrl_write(OMAP34XX_CLKSTCTRL_FORCE_WAKEUP, inst, cdoffs); + } +@@ -237,7 +237,7 @@ void am33xx_cm_clkdm_force_wakeup(s16 in + * sysconfig cannot be accessed and will probably lead to an "imprecise + * external abort" + */ +-int am33xx_cm_wait_module_ready(u16 inst, s16 cdoffs, u16 clkctrl_offs) ++int am33xx_cm_wait_module_ready(u16 inst, u16 cdoffs, u16 clkctrl_offs) + { + int i = 0; + +@@ -258,7 +258,7 @@ int am33xx_cm_wait_module_ready(u16 inst + * like reset assertion or parent clock de-activation must wait the + * module to be fully disabled. + */ +-int am33xx_cm_wait_module_idle(u16 inst, s16 cdoffs, u16 clkctrl_offs) ++int am33xx_cm_wait_module_idle(u16 inst, u16 cdoffs, u16 clkctrl_offs) + { + int i = 0; + +@@ -281,7 +281,7 @@ int am33xx_cm_wait_module_idle(u16 inst, + * + * No return value. + */ +-void am33xx_cm_module_enable(u8 mode, u16 inst, s16 cdoffs, u16 clkctrl_offs) ++void am33xx_cm_module_enable(u8 mode, u16 inst, u16 cdoffs, u16 clkctrl_offs) + { + u32 v; + +@@ -299,7 +299,7 @@ void am33xx_cm_module_enable(u8 mode, u1 + * + * No return value. + */ +-void am33xx_cm_module_disable(u16 inst, s16 cdoffs, u16 clkctrl_offs) ++void am33xx_cm_module_disable(u16 inst, u16 cdoffs, u16 clkctrl_offs) + { + u32 v; + +--- a/arch/arm/mach-omap2/cm33xx.h ++++ b/arch/arm/mach-omap2/cm33xx.h +@@ -377,36 +377,36 @@ + + + #ifndef __ASSEMBLER__ +-extern bool am33xx_cm_is_clkdm_in_hwsup(s16 inst, u16 cdoffs); +-extern void am33xx_cm_clkdm_enable_hwsup(s16 inst, u16 cdoffs); +-extern void am33xx_cm_clkdm_disable_hwsup(s16 inst, u16 cdoffs); +-extern void am33xx_cm_clkdm_force_sleep(s16 inst, u16 cdoffs); +-extern void am33xx_cm_clkdm_force_wakeup(s16 inst, u16 cdoffs); ++extern bool am33xx_cm_is_clkdm_in_hwsup(u16 inst, u16 cdoffs); ++extern void am33xx_cm_clkdm_enable_hwsup(u16 inst, u16 cdoffs); ++extern void am33xx_cm_clkdm_disable_hwsup(u16 inst, u16 cdoffs); ++extern void am33xx_cm_clkdm_force_sleep(u16 inst, u16 cdoffs); ++extern void am33xx_cm_clkdm_force_wakeup(u16 inst, u16 cdoffs); + +-#if defined(CONFIG_SOC_AM33XX) || defined(CONFIG_SOC_AM43XX) +-extern int am33xx_cm_wait_module_idle(u16 inst, s16 cdoffs, ++#ifdef CONFIG_SOC_AM33XX ++extern int am33xx_cm_wait_module_idle(u16 inst, u16 cdoffs, + u16 clkctrl_offs); +-extern void am33xx_cm_module_enable(u8 mode, u16 inst, s16 cdoffs, ++extern void am33xx_cm_module_enable(u8 mode, u16 inst, u16 cdoffs, + u16 clkctrl_offs); +-extern void am33xx_cm_module_disable(u16 inst, s16 cdoffs, ++extern void am33xx_cm_module_disable(u16 inst, u16 cdoffs, + u16 clkctrl_offs); +-extern int am33xx_cm_wait_module_ready(u16 inst, s16 cdoffs, ++extern int am33xx_cm_wait_module_ready(u16 inst, u16 cdoffs, + u16 clkctrl_offs); + #else +-static inline int am33xx_cm_wait_module_idle(u16 inst, s16 cdoffs, ++static inline int am33xx_cm_wait_module_idle(u16 inst, u16 cdoffs, + u16 clkctrl_offs) + { + return 0; + } +-static inline void am33xx_cm_module_enable(u8 mode, u16 inst, s16 cdoffs, ++static inline void am33xx_cm_module_enable(u8 mode, u16 inst, u16 cdoffs, + u16 clkctrl_offs) + { + } +-static inline void am33xx_cm_module_disable(u16 inst, s16 cdoffs, ++static inline void am33xx_cm_module_disable(u16 inst, u16 cdoffs, + u16 clkctrl_offs) + { + } +-static inline int am33xx_cm_wait_module_ready(u16 inst, s16 cdoffs, ++static inline int am33xx_cm_wait_module_ready(u16 inst, u16 cdoffs, + u16 clkctrl_offs) + { + return 0; +--- a/arch/arm/mach-omap2/cminst44xx.c ++++ b/arch/arm/mach-omap2/cminst44xx.c +@@ -80,7 +80,7 @@ void omap_cm_base_init(void) + * Return the IDLEST bitfield of a CM_*_CLKCTRL register, shifted down to + * bit 0. + */ +-static u32 _clkctrl_idlest(u8 part, u16 inst, s16 cdoffs, u16 clkctrl_offs) ++static u32 _clkctrl_idlest(u8 part, u16 inst, u16 cdoffs, u16 clkctrl_offs) + { + u32 v = omap4_cminst_read_inst_reg(part, inst, clkctrl_offs); + v &= OMAP4430_IDLEST_MASK; +@@ -98,7 +98,7 @@ static u32 _clkctrl_idlest(u8 part, u16 + * Returns true if the module's CM_*_CLKCTRL.IDLEST bitfield is either + * *FUNCTIONAL or *INTERFACE_IDLE; false otherwise. + */ +-static bool _is_module_ready(u8 part, u16 inst, s16 cdoffs, u16 clkctrl_offs) ++static bool _is_module_ready(u8 part, u16 inst, u16 cdoffs, u16 clkctrl_offs) + { + u32 v; + +@@ -111,7 +111,7 @@ static bool _is_module_ready(u8 part, u1 + /* Public functions */ + + /* Read a register in a CM instance */ +-u32 omap4_cminst_read_inst_reg(u8 part, s16 inst, u16 idx) ++u32 omap4_cminst_read_inst_reg(u8 part, u16 inst, u16 idx) + { + BUG_ON(part >= OMAP4_MAX_PRCM_PARTITIONS || + part == OMAP4430_INVALID_PRCM_PARTITION || +@@ -120,7 +120,7 @@ u32 omap4_cminst_read_inst_reg(u8 part, + } + + /* Write into a register in a CM instance */ +-void omap4_cminst_write_inst_reg(u32 val, u8 part, s16 inst, u16 idx) ++void omap4_cminst_write_inst_reg(u32 val, u8 part, u16 inst, u16 idx) + { + BUG_ON(part >= OMAP4_MAX_PRCM_PARTITIONS || + part == OMAP4430_INVALID_PRCM_PARTITION || +@@ -152,7 +152,7 @@ u32 omap4_cminst_clear_inst_reg_bits(u32 + return omap4_cminst_rmw_inst_reg_bits(bits, 0x0, part, inst, idx); + } + +-u32 omap4_cminst_read_inst_reg_bits(u8 part, u16 inst, s16 idx, u32 mask) ++u32 omap4_cminst_read_inst_reg_bits(u8 part, u16 inst, u16 idx, u32 mask) + { + u32 v; + +@@ -177,7 +177,7 @@ u32 omap4_cminst_read_inst_reg_bits(u8 p + * @c must be the unshifted value for CLKTRCTRL - i.e., this function + * will handle the shift itself. + */ +-static void _clktrctrl_write(u8 c, u8 part, s16 inst, u16 cdoffs) ++static void _clktrctrl_write(u8 c, u8 part, u16 inst, u16 cdoffs) + { + u32 v; + +@@ -196,7 +196,7 @@ static void _clktrctrl_write(u8 c, u8 pa + * Returns true if the clockdomain referred to by (@part, @inst, @cdoffs) + * is in hardware-supervised idle mode, or 0 otherwise. + */ +-bool omap4_cminst_is_clkdm_in_hwsup(u8 part, s16 inst, u16 cdoffs) ++bool omap4_cminst_is_clkdm_in_hwsup(u8 part, u16 inst, u16 cdoffs) + { + u32 v; + +@@ -216,7 +216,7 @@ bool omap4_cminst_is_clkdm_in_hwsup(u8 p + * Put a clockdomain referred to by (@part, @inst, @cdoffs) into + * hardware-supervised idle mode. No return value. + */ +-void omap4_cminst_clkdm_enable_hwsup(u8 part, s16 inst, u16 cdoffs) ++void omap4_cminst_clkdm_enable_hwsup(u8 part, u16 inst, u16 cdoffs) + { + _clktrctrl_write(OMAP34XX_CLKSTCTRL_ENABLE_AUTO, part, inst, cdoffs); + } +@@ -231,7 +231,7 @@ void omap4_cminst_clkdm_enable_hwsup(u8 + * software-supervised idle mode, i.e., controlled manually by the + * Linux OMAP clockdomain code. No return value. + */ +-void omap4_cminst_clkdm_disable_hwsup(u8 part, s16 inst, u16 cdoffs) ++void omap4_cminst_clkdm_disable_hwsup(u8 part, u16 inst, u16 cdoffs) + { + _clktrctrl_write(OMAP34XX_CLKSTCTRL_DISABLE_AUTO, part, inst, cdoffs); + } +@@ -245,7 +245,7 @@ void omap4_cminst_clkdm_disable_hwsup(u8 + * Take a clockdomain referred to by (@part, @inst, @cdoffs) out of idle, + * waking it up. No return value. + */ +-void omap4_cminst_clkdm_force_wakeup(u8 part, s16 inst, u16 cdoffs) ++void omap4_cminst_clkdm_force_wakeup(u8 part, u16 inst, u16 cdoffs) + { + _clktrctrl_write(OMAP34XX_CLKSTCTRL_FORCE_WAKEUP, part, inst, cdoffs); + } +@@ -266,7 +266,7 @@ void omap4_cminst_clkdm_force_wakeup(u8 + * sysconfig cannot be accessed and will probably lead to an "imprecise + * external abort" + */ +-int omap4_cminst_wait_module_ready(u8 part, u16 inst, s16 cdoffs, ++int omap4_cminst_wait_module_ready(u8 part, u16 inst, u16 cdoffs, + u16 clkctrl_offs) + { + int i = 0; +@@ -292,7 +292,8 @@ int omap4_cminst_wait_module_ready(u8 pa + * like reset assertion or parent clock de-activation must wait the + * module to be fully disabled. + */ +-int omap4_cminst_wait_module_idle(u8 part, u16 inst, s16 cdoffs, u16 clkctrl_offs) ++int omap4_cminst_wait_module_idle(u8 part, u16 inst, ++ u16 cdoffs, u16 clkctrl_offs) + { + int i = 0; + +@@ -316,7 +317,7 @@ int omap4_cminst_wait_module_idle(u8 par + * + * No return value. + */ +-void omap4_cminst_module_enable(u8 mode, u8 part, u16 inst, s16 cdoffs, ++void omap4_cminst_module_enable(u8 mode, u8 part, u16 inst, u16 cdoffs, + u16 clkctrl_offs) + { + u32 v; +@@ -336,7 +337,7 @@ void omap4_cminst_module_enable(u8 mode, + * + * No return value. + */ +-void omap4_cminst_module_disable(u8 part, u16 inst, s16 cdoffs, ++void omap4_cminst_module_disable(u8 part, u16 inst, u16 cdoffs, + u16 clkctrl_offs) + { + u32 v; +@@ -479,6 +480,15 @@ struct clkdm_ops omap4_clkdm_operations + .clkdm_sleep = omap4_clkdm_sleep, + .clkdm_wakeup = omap4_clkdm_wakeup, + .clkdm_allow_idle = omap4_clkdm_allow_idle, ++ .clkdm_deny_idle = omap4_clkdm_deny_idle, ++ .clkdm_clk_enable = omap4_clkdm_clk_enable, ++ .clkdm_clk_disable = omap4_clkdm_clk_disable, ++}; ++ ++struct clkdm_ops am43xx_clkdm_operations = { ++ .clkdm_sleep = omap4_clkdm_sleep, ++ .clkdm_wakeup = omap4_clkdm_wakeup, ++ .clkdm_allow_idle = omap4_clkdm_allow_idle, + .clkdm_deny_idle = omap4_clkdm_deny_idle, + .clkdm_clk_enable = omap4_clkdm_clk_enable, + .clkdm_clk_disable = omap4_clkdm_clk_disable, +--- a/arch/arm/mach-omap2/cminst44xx.h ++++ b/arch/arm/mach-omap2/cminst44xx.h +@@ -11,31 +11,32 @@ + #ifndef __ARCH_ASM_MACH_OMAP2_CMINST44XX_H + #define __ARCH_ASM_MACH_OMAP2_CMINST44XX_H + +-extern bool omap4_cminst_is_clkdm_in_hwsup(u8 part, s16 inst, u16 cdoffs); +-extern void omap4_cminst_clkdm_enable_hwsup(u8 part, s16 inst, u16 cdoffs); +-extern void omap4_cminst_clkdm_disable_hwsup(u8 part, s16 inst, u16 cdoffs); +-extern void omap4_cminst_clkdm_force_sleep(u8 part, s16 inst, u16 cdoffs); +-extern void omap4_cminst_clkdm_force_wakeup(u8 part, s16 inst, u16 cdoffs); +-extern int omap4_cminst_wait_module_ready(u8 part, u16 inst, s16 cdoffs, u16 clkctrl_offs); +-extern int omap4_cminst_wait_module_idle(u8 part, u16 inst, s16 cdoffs, ++extern bool omap4_cminst_is_clkdm_in_hwsup(u8 part, u16 inst, u16 cdoffs); ++extern void omap4_cminst_clkdm_enable_hwsup(u8 part, u16 inst, u16 cdoffs); ++extern void omap4_cminst_clkdm_disable_hwsup(u8 part, u16 inst, u16 cdoffs); ++extern void omap4_cminst_clkdm_force_sleep(u8 part, u16 inst, u16 cdoffs); ++extern void omap4_cminst_clkdm_force_wakeup(u8 part, u16 inst, u16 cdoffs); ++extern int omap4_cminst_wait_module_ready(u8 part, u16 inst, ++ u16 cdoffs, u16 clkctrl_offs); ++extern int omap4_cminst_wait_module_idle(u8 part, u16 inst, u16 cdoffs, + u16 clkctrl_offs); +-extern void omap4_cminst_module_enable(u8 mode, u8 part, u16 inst, s16 cdoffs, ++extern void omap4_cminst_module_enable(u8 mode, u8 part, u16 inst, u16 cdoffs, + u16 clkctrl_offs); +-extern void omap4_cminst_module_disable(u8 part, u16 inst, s16 cdoffs, ++extern void omap4_cminst_module_disable(u8 part, u16 inst, u16 cdoffs, + u16 clkctrl_offs); + /* + * In an ideal world, we would not export these low-level functions, + * but this will probably take some time to fix properly + */ +-extern u32 omap4_cminst_read_inst_reg(u8 part, s16 inst, u16 idx); +-extern void omap4_cminst_write_inst_reg(u32 val, u8 part, s16 inst, u16 idx); ++extern u32 omap4_cminst_read_inst_reg(u8 part, u16 inst, u16 idx); ++extern void omap4_cminst_write_inst_reg(u32 val, u8 part, u16 inst, u16 idx); + extern u32 omap4_cminst_rmw_inst_reg_bits(u32 mask, u32 bits, u8 part, + s16 inst, s16 idx); + extern u32 omap4_cminst_set_inst_reg_bits(u32 bits, u8 part, s16 inst, + s16 idx); + extern u32 omap4_cminst_clear_inst_reg_bits(u32 bits, u8 part, s16 inst, + s16 idx); +-extern u32 omap4_cminst_read_inst_reg_bits(u8 part, u16 inst, s16 idx, ++extern u32 omap4_cminst_read_inst_reg_bits(u8 part, u16 inst, u16 idx, + u32 mask); + + extern void omap_cm_base_init(void); +--- a/arch/arm/mach-omap2/common.c ++++ b/arch/arm/mach-omap2/common.c +@@ -15,10 +15,14 @@ + #include <linux/kernel.h> + #include <linux/init.h> + #include <linux/platform_data/dsp-omap.h> ++#include <asm/memblock.h> ++#include <asm/mach/map.h> + + #include "common.h" + #include "omap-secure.h" + ++#define AM33XX_DRAM_SYNC_VA 0xfe600000 ++ + /* + * Stub function for OMAP2 so that common files + * continue to build when custom builds are used +@@ -34,3 +38,31 @@ void __init omap_reserve(void) + omap_secure_ram_reserve_memblock(); + omap_barrier_reserve_memblock(); + } ++ ++static phys_addr_t am33xx_paddr; ++static u32 am33xx_size; ++ ++/* Steal one page physical memory for uncached read DeepSleep */ ++void __init am33xx_reserve(void) ++{ ++ am33xx_size = ALIGN(PAGE_SIZE, SZ_1M); ++ am33xx_paddr = arm_memblock_steal(am33xx_size, SZ_1M); ++ ++ omap_reserve(); ++} ++ ++void __iomem *am33xx_dram_sync; ++ ++void __init am33xx_dram_sync_init(void) ++{ ++ struct map_desc dram_io_desc[1]; ++ ++ dram_io_desc[0].virtual = AM33XX_DRAM_SYNC_VA; ++ dram_io_desc[0].pfn = __phys_to_pfn(am33xx_paddr); ++ dram_io_desc[0].length = am33xx_size; ++ dram_io_desc[0].type = MT_MEMORY_SO; ++ ++ iotable_init(dram_io_desc, ARRAY_SIZE(dram_io_desc)); ++ ++ am33xx_dram_sync = (void __iomem *) dram_io_desc[0].virtual; ++} +--- a/arch/arm/mach-omap2/common.h ++++ b/arch/arm/mach-omap2/common.h +@@ -60,7 +60,7 @@ static inline int omap3_pm_init(void) + } + #endif + +-#if defined(CONFIG_PM) && defined(CONFIG_ARCH_OMAP4) ++#if defined(CONFIG_PM) && (defined(CONFIG_ARCH_OMAP4) || defined(CONFIG_SOC_OMAP5) || defined(CONFIG_SOC_DRA7XX)) + int omap4_pm_init(void); + #else + static inline int omap4_pm_init(void) +@@ -69,6 +69,15 @@ static inline int omap4_pm_init(void) + } + #endif + ++#if defined(CONFIG_PM) && defined(CONFIG_SOC_AM33XX) ++int am33xx_pm_init(void); ++#else ++static inline int am33xx_pm_init(void) ++{ ++ return 0; ++} ++#endif ++ + #ifdef CONFIG_OMAP_MUX + int omap_mux_late_init(void); + #else +@@ -107,10 +116,14 @@ void omap2430_init_late(void); + void omap3430_init_late(void); + void omap35xx_init_late(void); + void omap3630_init_late(void); ++void am33xx_init_late(void); + void am35xx_init_late(void); + void ti81xx_init_late(void); ++void am33xx_init_late(void); ++void omap5_init_late(void); + int omap2_common_pm_late_init(void); + void dra7xx_init_early(void); ++void dra7xx_init_late(void); + + #ifdef CONFIG_SOC_BUS + void omap_soc_device_init(void); +@@ -136,6 +149,14 @@ static inline void am33xx_restart(enum r + } + #endif + ++#ifdef CONFIG_SOC_AM43XX ++void am43xx_restart(enum reboot_mode mode, const char *cmd); ++#else ++static inline void am43xx_restart(enum reboot_mode mode, const char *cmd) ++{ ++} ++#endif ++ + #ifdef CONFIG_ARCH_OMAP3 + void omap3xxx_restart(enum reboot_mode mode, const char *cmd); + #else +@@ -152,6 +173,14 @@ static inline void omap44xx_restart(enum + } + #endif + ++#if defined(CONFIG_SUSPEND) ++void omap2_common_suspend_init(void); ++#else ++inline void omap2_common_suspend_init(void); ++{ ++} ++#endif ++ + /* This gets called from mach-omap2/io.c, do not call this */ + void __init omap2_set_globals_tap(u32 class, void __iomem *tap); + +@@ -165,7 +194,6 @@ void __init ti81xx_map_io(void); + + /* omap_barriers_init() is OMAP4 only */ + void omap_barriers_init(void); +- + /** + * omap_test_timeout - busy-loop, testing a condition + * @cond: condition to test until it evaluates to true +@@ -259,6 +287,8 @@ extern int omap4_enter_lowpower(unsigned + extern int omap4_finish_suspend(unsigned long cpu_state); + extern void omap4_cpu_resume(void); + extern int omap4_hotplug_cpu(unsigned int cpu, unsigned int power_state); ++extern int omap5_finish_suspend(unsigned long cpu_state); ++extern void omap5_cpu_resume(void); + #else + static inline int omap4_enter_lowpower(unsigned int cpu, + unsigned int power_state) +@@ -286,6 +316,14 @@ static inline int omap4_finish_suspend(u + static inline void omap4_cpu_resume(void) + {} + ++static inline int omap5_finish_suspend(unsigned long cpu_state) ++{ ++ return 0; ++} ++ ++static inline void omap5_cpu_resume(void) ++{} ++ + #endif + + struct omap_sdrc_params; +@@ -295,11 +333,17 @@ struct omap2_hsmmc_info; + extern int omap4_twl6030_hsmmc_init(struct omap2_hsmmc_info *controllers); + extern void omap_reserve(void); + ++extern void am33xx_reserve(void); ++extern void am33xx_dram_sync_init(void); ++extern void __iomem *am33xx_dram_sync; ++ + struct omap_hwmod; + extern int omap_dss_reset(struct omap_hwmod *); + + /* SoC specific clock initializer */ + extern int (*omap_clk_init)(void); + ++int __init omapdss_init_of(void); ++ + #endif /* __ASSEMBLER__ */ + #endif /* __ARCH_ARM_MACH_OMAP2PLUS_COMMON_H */ +--- a/arch/arm/mach-omap2/devices.c ++++ b/arch/arm/mach-omap2/devices.c +@@ -37,6 +37,7 @@ + #include "mux.h" + #include "control.h" + #include "devices.h" ++#include "display.h" + + #define L3_MODULES_MAX_LEN 12 + #define L3_MODULES 3 +@@ -466,13 +467,13 @@ static struct platform_device omap_vout_ + .resource = &omap_vout_resource[0], + .id = -1, + }; +-static void omap_init_vout(void) ++ ++int __init omap_init_vout(void) + { +- if (platform_device_register(&omap_vout_device) < 0) +- printk(KERN_ERR "Unable to register OMAP-VOUT device\n"); ++ return platform_device_register(&omap_vout_device); + } + #else +-static inline void omap_init_vout(void) {} ++int __init omap_init_vout(void) { return 0; } + #endif + + #if IS_ENABLED(CONFIG_WL12XX) +@@ -524,9 +525,9 @@ static int __init omap2_init_devices(voi + omap_init_audio(); + omap_init_camera(); + omap_init_hdmi_audio(); +- omap_init_mbox(); + /* If dtb is there, the devices will be created dynamically */ + if (!of_have_populated_dt()) { ++ omap_init_mbox(); + omap_init_mcspi(); + omap_init_sham(); + omap_init_aes(); +@@ -536,7 +537,6 @@ static int __init omap2_init_devices(voi + omap_init_wl12xx_of(); + } + omap_init_sti(); +- omap_init_vout(); + + return 0; + } +--- a/arch/arm/mach-omap2/display.c ++++ b/arch/arm/mach-omap2/display.c +@@ -23,6 +23,8 @@ + #include <linux/clk.h> + #include <linux/err.h> + #include <linux/delay.h> ++#include <linux/of.h> ++#include <linux/of_platform.h> + + #include <video/omapdss.h> + #include "omap_hwmod.h" +@@ -316,6 +318,10 @@ static enum omapdss_version __init omap_ + return OMAPDSS_VER_OMAP4; + else if (soc_is_omap54xx()) + return OMAPDSS_VER_OMAP5; ++ else if (soc_is_dra7xx()) ++ return OMAPDSS_VER_DRA7xx; ++ else if (soc_is_am43xx()) ++ return OMAPDSS_VER_AM43xx; + else + return OMAPDSS_VER_UNKNOWN; + } +@@ -416,6 +422,34 @@ int __init omap_display_init(struct omap + } + } + ++ /* create DRM device */ ++ r = omap_init_drm(); ++ if (r < 0) { ++ pr_err("Unable to register omapdrm device\n"); ++ return r; ++ } ++ ++ /* create vrfb device */ ++ r = omap_init_vrfb(); ++ if (r < 0) { ++ pr_err("Unable to register omapvrfb device\n"); ++ return r; ++ } ++ ++ /* create FB device */ ++ r = omap_init_fb(); ++ if (r < 0) { ++ pr_err("Unable to register omapfb device\n"); ++ return r; ++ } ++ ++ /* create V4L2 display device */ ++ r = omap_init_vout(); ++ if (r < 0) { ++ pr_err("Unable to register omap_vout device\n"); ++ return r; ++ } ++ + return 0; + } + +@@ -564,3 +598,63 @@ int omap_dss_reset(struct omap_hwmod *oh + + return r; + } ++ ++int __init omapdss_init_of(void) ++{ ++ int r; ++ enum omapdss_version ver; ++ ++ static struct omap_dss_board_info board_data = { ++ .dsi_enable_pads = omap_dsi_enable_pads, ++ .dsi_disable_pads = omap_dsi_disable_pads, ++ .get_context_loss_count = omap_pm_get_dev_context_loss_count, ++ .set_min_bus_tput = omap_dss_set_min_bus_tput, ++ }; ++ ++ ver = omap_display_get_version(); ++ ++ if (ver == OMAPDSS_VER_UNKNOWN) { ++ pr_err("DSS not supported on this SoC\n"); ++ return -ENODEV; ++ } ++ ++ board_data.version = ver; ++ ++ omap_display_device.dev.platform_data = &board_data; ++ ++ r = platform_device_register(&omap_display_device); ++ if (r < 0) { ++ pr_err("Unable to register omapdss device\n"); ++ return r; ++ } ++ ++ /* create DRM device */ ++ r = omap_init_drm(); ++ if (r < 0) { ++ pr_err("Unable to register omapdrm device\n"); ++ return r; ++ } ++ ++ /* create vrfb device */ ++ r = omap_init_vrfb(); ++ if (r < 0) { ++ pr_err("Unable to register omapvrfb device\n"); ++ return r; ++ } ++ ++ /* create FB device */ ++ r = omap_init_fb(); ++ if (r < 0) { ++ pr_err("Unable to register omapfb device\n"); ++ return r; ++ } ++ ++ /* create V4L2 display device */ ++ r = omap_init_vout(); ++ if (r < 0) { ++ pr_err("Unable to register omap_vout device\n"); ++ return r; ++ } ++ ++ return 0; ++} +--- a/arch/arm/mach-omap2/display.h ++++ b/arch/arm/mach-omap2/display.h +@@ -26,4 +26,8 @@ struct omap_dss_dispc_dev_attr { + bool has_framedonetv_irq; + }; + ++int omap_init_drm(void); ++int omap_init_vrfb(void); ++int omap_init_fb(void); ++int omap_init_vout(void); + #endif +--- a/arch/arm/mach-omap2/drm.c ++++ b/arch/arm/mach-omap2/drm.c +@@ -26,10 +26,9 @@ + #include <linux/platform_data/omap_drm.h> + + #include "soc.h" +-#include "omap_device.h" +-#include "omap_hwmod.h" ++#include "display.h" + +-#if defined(CONFIG_DRM_OMAP) || (CONFIG_DRM_OMAP_MODULE) ++#if defined(CONFIG_DRM_OMAP) || defined(CONFIG_DRM_OMAP_MODULE) + + static struct omap_drm_platform_data platform_data; + +@@ -42,26 +41,13 @@ static struct platform_device omap_drm_d + .id = 0, + }; + +-static int __init omap_init_drm(void) ++int __init omap_init_drm(void) + { +- struct omap_hwmod *oh = NULL; +- struct platform_device *pdev; +- +- /* lookup and populate the DMM information, if present - OMAP4+ */ +- oh = omap_hwmod_lookup("dmm"); +- +- if (oh) { +- pdev = omap_device_build(oh->name, -1, oh, NULL, 0); +- WARN(IS_ERR(pdev), "Could not build omap_device for %s\n", +- oh->name); +- } +- + platform_data.omaprev = GET_OMAP_TYPE; + + return platform_device_register(&omap_drm_device); + + } +- +-omap_arch_initcall(omap_init_drm); +- ++#else ++int __init omap_init_drm(void) { return 0; } + #endif +--- a/arch/arm/mach-omap2/dss-common.c ++++ /dev/null +@@ -1,215 +0,0 @@ +-/* +- * Copyright (C) 2012 Texas Instruments, Inc.. +- * Author: Tomi Valkeinen <tomi.valkeinen@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 +- * +- */ +- +-/* +- * NOTE: this is a transitional file to help with DT adaptation. +- * This file will be removed when DSS supports DT. +- */ +- +-#include <linux/kernel.h> +-#include <linux/gpio.h> +-#include <linux/platform_device.h> +- +-#include <video/omapdss.h> +-#include <video/omap-panel-data.h> +- +-#include "soc.h" +-#include "dss-common.h" +-#include "mux.h" +- +-#define HDMI_GPIO_CT_CP_HPD 60 /* HPD mode enable/disable */ +-#define HDMI_GPIO_LS_OE 41 /* Level shifter for HDMI */ +-#define HDMI_GPIO_HPD 63 /* Hotplug detect */ +- +-#define PANDA_DVI_TFP410_POWER_DOWN_GPIO 0 +- +-/* DVI Connector */ +-static struct connector_dvi_platform_data omap4_panda_dvi_connector_pdata = { +- .name = "dvi", +- .source = "tfp410.0", +- .i2c_bus_num = 2, +-}; +- +-static struct platform_device omap4_panda_dvi_connector_device = { +- .name = "connector-dvi", +- .id = 0, +- .dev.platform_data = &omap4_panda_dvi_connector_pdata, +-}; +- +-/* TFP410 DPI-to-DVI chip */ +-static struct encoder_tfp410_platform_data omap4_panda_tfp410_pdata = { +- .name = "tfp410.0", +- .source = "dpi.0", +- .data_lines = 24, +- .power_down_gpio = PANDA_DVI_TFP410_POWER_DOWN_GPIO, +-}; +- +-static struct platform_device omap4_panda_tfp410_device = { +- .name = "tfp410", +- .id = 0, +- .dev.platform_data = &omap4_panda_tfp410_pdata, +-}; +- +-/* HDMI Connector */ +-static struct connector_hdmi_platform_data omap4_panda_hdmi_connector_pdata = { +- .name = "hdmi", +- .source = "tpd12s015.0", +-}; +- +-static struct platform_device omap4_panda_hdmi_connector_device = { +- .name = "connector-hdmi", +- .id = 0, +- .dev.platform_data = &omap4_panda_hdmi_connector_pdata, +-}; +- +-/* TPD12S015 HDMI ESD protection & level shifter chip */ +-static struct encoder_tpd12s015_platform_data omap4_panda_tpd_pdata = { +- .name = "tpd12s015.0", +- .source = "hdmi.0", +- +- .ct_cp_hpd_gpio = HDMI_GPIO_CT_CP_HPD, +- .ls_oe_gpio = HDMI_GPIO_LS_OE, +- .hpd_gpio = HDMI_GPIO_HPD, +-}; +- +-static struct platform_device omap4_panda_tpd_device = { +- .name = "tpd12s015", +- .id = 0, +- .dev.platform_data = &omap4_panda_tpd_pdata, +-}; +- +-static struct omap_dss_board_info omap4_panda_dss_data = { +- .default_display_name = "dvi", +-}; +- +-void __init omap4_panda_display_init_of(void) +-{ +- omap_display_init(&omap4_panda_dss_data); +- +- platform_device_register(&omap4_panda_tfp410_device); +- platform_device_register(&omap4_panda_dvi_connector_device); +- +- platform_device_register(&omap4_panda_tpd_device); +- platform_device_register(&omap4_panda_hdmi_connector_device); +-} +- +- +-/* OMAP4 Blaze display data */ +- +-#define DISPLAY_SEL_GPIO 59 /* LCD2/PicoDLP switch */ +-#define DLP_POWER_ON_GPIO 40 +- +-static struct panel_dsicm_platform_data dsi1_panel = { +- .name = "lcd", +- .source = "dsi.0", +- .reset_gpio = 102, +- .use_ext_te = false, +- .ext_te_gpio = 101, +- .pin_config = { +- .num_pins = 6, +- .pins = { 0, 1, 2, 3, 4, 5 }, +- }, +-}; +- +-static struct platform_device sdp4430_lcd_device = { +- .name = "panel-dsi-cm", +- .id = 0, +- .dev.platform_data = &dsi1_panel, +-}; +- +-static struct panel_dsicm_platform_data dsi2_panel = { +- .name = "lcd2", +- .source = "dsi.1", +- .reset_gpio = 104, +- .use_ext_te = false, +- .ext_te_gpio = 103, +- .pin_config = { +- .num_pins = 6, +- .pins = { 0, 1, 2, 3, 4, 5 }, +- }, +-}; +- +-static struct platform_device sdp4430_lcd2_device = { +- .name = "panel-dsi-cm", +- .id = 1, +- .dev.platform_data = &dsi2_panel, +-}; +- +-/* HDMI Connector */ +-static struct connector_hdmi_platform_data sdp4430_hdmi_connector_pdata = { +- .name = "hdmi", +- .source = "tpd12s015.0", +-}; +- +-static struct platform_device sdp4430_hdmi_connector_device = { +- .name = "connector-hdmi", +- .id = 0, +- .dev.platform_data = &sdp4430_hdmi_connector_pdata, +-}; +- +-/* TPD12S015 HDMI ESD protection & level shifter chip */ +-static struct encoder_tpd12s015_platform_data sdp4430_tpd_pdata = { +- .name = "tpd12s015.0", +- .source = "hdmi.0", +- +- .ct_cp_hpd_gpio = HDMI_GPIO_CT_CP_HPD, +- .ls_oe_gpio = HDMI_GPIO_LS_OE, +- .hpd_gpio = HDMI_GPIO_HPD, +-}; +- +-static struct platform_device sdp4430_tpd_device = { +- .name = "tpd12s015", +- .id = 0, +- .dev.platform_data = &sdp4430_tpd_pdata, +-}; +- +- +-static struct omap_dss_board_info sdp4430_dss_data = { +- .default_display_name = "lcd", +-}; +- +-/* +- * we select LCD2 by default (instead of Pico DLP) by setting DISPLAY_SEL_GPIO. +- * Setting DLP_POWER_ON gpio enables the VDLP_2V5 VDLP_1V8 and VDLP_1V0 rails +- * used by picodlp on the 4430sdp platform. Keep this gpio disabled as LCD2 is +- * selected by default +- */ +-void __init omap_4430sdp_display_init_of(void) +-{ +- int r; +- +- r = gpio_request_one(DISPLAY_SEL_GPIO, GPIOF_OUT_INIT_HIGH, +- "display_sel"); +- if (r) +- pr_err("%s: Could not get display_sel GPIO\n", __func__); +- +- r = gpio_request_one(DLP_POWER_ON_GPIO, GPIOF_OUT_INIT_LOW, +- "DLP POWER ON"); +- if (r) +- pr_err("%s: Could not get DLP POWER ON GPIO\n", __func__); +- +- omap_display_init(&sdp4430_dss_data); +- +- platform_device_register(&sdp4430_lcd_device); +- platform_device_register(&sdp4430_lcd2_device); +- +- platform_device_register(&sdp4430_tpd_device); +- platform_device_register(&sdp4430_hdmi_connector_device); +-} +--- a/arch/arm/mach-omap2/dss-common.h ++++ /dev/null +@@ -1,12 +0,0 @@ +-#ifndef __OMAP_DSS_COMMON__ +-#define __OMAP_DSS_COMMON__ +- +-/* +- * NOTE: this is a transitional file to help with DT adaptation. +- * This file will be removed when DSS supports DT. +- */ +- +-void __init omap4_panda_display_init_of(void); +-void __init omap_4430sdp_display_init_of(void); +- +-#endif +--- a/arch/arm/mach-omap2/fb.c ++++ b/arch/arm/mach-omap2/fb.c +@@ -32,6 +32,7 @@ + #include <asm/mach/map.h> + + #include "soc.h" ++#include "display.h" + + #ifdef CONFIG_OMAP2_VRFB + +@@ -64,7 +65,7 @@ static const struct resource omap3_vrfb_ + DEFINE_RES_MEM_NAMED(0xfc000000u, 0x4000000, "vrfb-area-11"), + }; + +-static int __init omap_init_vrfb(void) ++int __init omap_init_vrfb(void) + { + struct platform_device *pdev; + const struct resource *res; +@@ -85,8 +86,8 @@ static int __init omap_init_vrfb(void) + + return PTR_RET(pdev); + } +- +-omap_arch_initcall(omap_init_vrfb); ++#else ++int __init omap_init_vrfb(void) { return 0; } + #endif + + #if defined(CONFIG_FB_OMAP2) || defined(CONFIG_FB_OMAP2_MODULE) +@@ -105,11 +106,10 @@ static struct platform_device omap_fb_de + .num_resources = 0, + }; + +-static int __init omap_init_fb(void) ++int __init omap_init_fb(void) + { + return platform_device_register(&omap_fb_device); + } +- +-omap_arch_initcall(omap_init_fb); +- ++#else ++int __init omap_init_fb(void) { return 0; } + #endif +--- a/arch/arm/mach-omap2/gpmc.c ++++ b/arch/arm/mach-omap2/gpmc.c +@@ -68,6 +68,9 @@ + #define GPMC_ECC_BCH_RESULT_1 0x244 /* not available on OMAP2 */ + #define GPMC_ECC_BCH_RESULT_2 0x248 /* not available on OMAP2 */ + #define GPMC_ECC_BCH_RESULT_3 0x24c /* not available on OMAP2 */ ++#define GPMC_ECC_BCH_RESULT_4 0x300 /* not available on OMAP2 */ ++#define GPMC_ECC_BCH_RESULT_5 0x304 /* not available on OMAP2 */ ++#define GPMC_ECC_BCH_RESULT_6 0x308 /* not available on OMAP2 */ + + /* GPMC ECC control settings */ + #define GPMC_ECC_CTRL_ECCCLEAR 0x100 +@@ -659,13 +662,19 @@ void gpmc_update_nand_reg(struct gpmc_na + + for (i = 0; i < GPMC_BCH_NUM_REMAINDER; i++) { + reg->gpmc_bch_result0[i] = gpmc_base + GPMC_ECC_BCH_RESULT_0 + +- GPMC_BCH_SIZE * i; ++ (GPMC_BCH_SIZE * i); + reg->gpmc_bch_result1[i] = gpmc_base + GPMC_ECC_BCH_RESULT_1 + +- GPMC_BCH_SIZE * i; ++ (GPMC_BCH_SIZE * i); + reg->gpmc_bch_result2[i] = gpmc_base + GPMC_ECC_BCH_RESULT_2 + +- GPMC_BCH_SIZE * i; ++ (GPMC_BCH_SIZE * i); + reg->gpmc_bch_result3[i] = gpmc_base + GPMC_ECC_BCH_RESULT_3 + +- GPMC_BCH_SIZE * i; ++ (GPMC_BCH_SIZE * i); ++ reg->gpmc_bch_result4[i] = gpmc_base + GPMC_ECC_BCH_RESULT_4 + ++ (GPMC_BCH_SIZE * i); ++ reg->gpmc_bch_result5[i] = gpmc_base + GPMC_ECC_BCH_RESULT_5 + ++ (GPMC_BCH_SIZE * i); ++ reg->gpmc_bch_result6[i] = gpmc_base + GPMC_ECC_BCH_RESULT_6 + ++ (GPMC_BCH_SIZE * i); + } + } + +@@ -1340,15 +1349,6 @@ static void __maybe_unused gpmc_read_tim + } + + #ifdef CONFIG_MTD_NAND +- +-static const char * const nand_ecc_opts[] = { +- [OMAP_ECC_HAMMING_CODE_DEFAULT] = "sw", +- [OMAP_ECC_HAMMING_CODE_HW] = "hw", +- [OMAP_ECC_HAMMING_CODE_HW_ROMCODE] = "hw-romcode", +- [OMAP_ECC_BCH4_CODE_HW] = "bch4", +- [OMAP_ECC_BCH8_CODE_HW] = "bch8", +-}; +- + static const char * const nand_xfer_types[] = { + [NAND_OMAP_PREFETCH_POLLED] = "prefetch-polled", + [NAND_OMAP_POLLED] = "polled", +@@ -1377,17 +1377,42 @@ static int gpmc_probe_nand_child(struct + + gpmc_nand_data->cs = val; + gpmc_nand_data->of_node = child; +- +- if (!of_property_read_string(child, "ti,nand-ecc-opt", &s)) +- for (val = 0; val < ARRAY_SIZE(nand_ecc_opts); val++) +- if (!strcasecmp(s, nand_ecc_opts[val])) { +- gpmc_nand_data->ecc_opt = val; +- break; +- } ++ /* Detect availability of ELM module */ ++ gpmc_nand_data->elm_of_node = of_parse_phandle(child, "ti,elm-id", 0); ++ if (gpmc_nand_data->elm_of_node == NULL) ++ gpmc_nand_data->elm_of_node = ++ of_parse_phandle(child, "elm_id", 0); ++ if (gpmc_nand_data->elm_of_node == NULL) ++ pr_warn("%s: ti,elm-id property not found\n", __func__); ++ ++ /* select NAND ecc-scheme */ ++ if (of_property_read_string(child, "ti,nand-ecc-opt", &s)) { ++ pr_err("%s: valid ti,nand-ecc-opt not found\n", __func__); ++ return -ENODEV; ++ } ++ if (!strcmp(s, "ham1") || !strcmp(s, "sw") || !strcmp(s, "hw") || ++ !strcmp(s, "hw-romcode")) ++ gpmc_nand_data->ecc_opt = OMAP_ECC_HAMMING_CODE_HW; ++ else if (!strcmp(s, "bch4")) ++ if (gpmc_nand_data->elm_of_node) ++ gpmc_nand_data->ecc_opt = OMAP_ECC_BCH4_CODE_HW; ++ else ++ gpmc_nand_data->ecc_opt = ++ OMAP_ECC_BCH4_CODE_HW_DETECTION_SW; ++ else if (!strcmp(s, "bch8")) ++ if (gpmc_nand_data->elm_of_node) ++ gpmc_nand_data->ecc_opt = OMAP_ECC_BCH8_CODE_HW; ++ else ++ gpmc_nand_data->ecc_opt = ++ OMAP_ECC_BCH8_CODE_HW_DETECTION_SW; ++ else if (!strcmp(s, "bch16")) ++ gpmc_nand_data->ecc_opt = OMAP_ECC_BCH16_CODE_HW; ++ else ++ pr_err("%s: ti,nand-ecc-opt: invalid property val\n", __func__); + + if (!of_property_read_string(child, "ti,nand-xfer-type", &s)) + for (val = 0; val < ARRAY_SIZE(nand_xfer_types); val++) +- if (!strcasecmp(s, nand_xfer_types[val])) { ++ if (!strcmp(s, nand_xfer_types[val])) { + gpmc_nand_data->xfer_type = val; + break; + } +--- a/arch/arm/mach-omap2/gpmc-nand.c ++++ b/arch/arm/mach-omap2/gpmc-nand.c +@@ -43,28 +43,6 @@ static struct platform_device gpmc_nand_ + .resource = gpmc_nand_resource, + }; + +-static bool gpmc_hwecc_bch_capable(enum omap_ecc ecc_opt) +-{ +- /* support only OMAP3 class */ +- if (!cpu_is_omap34xx() && !soc_is_am33xx()) { +- pr_err("BCH ecc is not supported on this CPU\n"); +- return 0; +- } +- +- /* +- * For now, assume 4-bit mode is only supported on OMAP3630 ES1.x, x>=1 +- * and AM33xx derivates. Other chips may be added if confirmed to work. +- */ +- if ((ecc_opt == OMAP_ECC_BCH4_CODE_HW) && +- (!cpu_is_omap3630() || (GET_OMAP_REVISION() == 0)) && +- (!soc_is_am33xx())) { +- pr_err("BCH 4-bit mode is not supported on this CPU\n"); +- return 0; +- } +- +- return 1; +-} +- + int gpmc_nand_init(struct omap_nand_platform_data *gpmc_nand_data, + struct gpmc_timings *gpmc_t) + { +@@ -127,9 +105,6 @@ int gpmc_nand_init(struct omap_nand_plat + + gpmc_update_nand_reg(&gpmc_nand_data->reg, gpmc_nand_data->cs); + +- if (!gpmc_hwecc_bch_capable(gpmc_nand_data->ecc_opt)) +- return -EINVAL; +- + err = platform_device_register(&gpmc_nand_device); + if (err < 0) { + dev_err(dev, "Unable to register NAND device\n"); +--- a/arch/arm/mach-omap2/io.c ++++ b/arch/arm/mach-omap2/io.c +@@ -322,6 +322,7 @@ void __init ti81xx_map_io(void) + void __init am33xx_map_io(void) + { + iotable_init(omapam33xx_io_desc, ARRAY_SIZE(omapam33xx_io_desc)); ++ am33xx_dram_sync_init(); + } + #endif + +@@ -398,6 +399,7 @@ static void __init __maybe_unused omap_c + { + omap_mux_late_init(); + omap2_common_pm_late_init(); ++ omap2_common_suspend_init(); + omap_soc_device_init(); + } + +@@ -488,21 +490,29 @@ void __init omap3_init_early(void) + void __init omap3430_init_early(void) + { + omap3_init_early(); ++ if (of_have_populated_dt()) ++ omap_clk_init = omap3430_clk_init; + } + + void __init omap35xx_init_early(void) + { + omap3_init_early(); ++ if (of_have_populated_dt()) ++ omap_clk_init = omap3430_clk_init; + } + + void __init omap3630_init_early(void) + { + omap3_init_early(); ++ if (of_have_populated_dt()) ++ omap_clk_init = omap3630_clk_init; + } + + void __init am35xx_init_early(void) + { + omap3_init_early(); ++ if (of_have_populated_dt()) ++ omap_clk_init = am35xx_clk_init; + } + + void __init ti81xx_init_early(void) +@@ -520,7 +530,10 @@ void __init ti81xx_init_early(void) + omap3xxx_clockdomains_init(); + omap3xxx_hwmod_init(); + omap_hwmod_init_postsetup(); +- omap_clk_init = omap3xxx_clk_init; ++ if (of_have_populated_dt()) ++ omap_clk_init = ti81xx_clk_init; ++ else ++ omap_clk_init = omap3xxx_clk_init; + } + + void __init omap3_init_late(void) +@@ -583,6 +596,13 @@ void __init am33xx_init_early(void) + omap_hwmod_init_postsetup(); + omap_clk_init = am33xx_clk_init; + } ++ ++void __init am33xx_init_late(void) ++{ ++ omap_hwmod_force_mstandby_repeated(); ++ omap2_common_pm_late_init(); ++ am33xx_pm_init(); ++} + #endif + + #ifdef CONFIG_SOC_AM43XX +@@ -594,7 +614,15 @@ void __init am43xx_init_early(void) + NULL); + omap2_set_globals_prm(AM33XX_L4_WK_IO_ADDRESS(AM43XX_PRCM_BASE)); + omap2_set_globals_cm(AM33XX_L4_WK_IO_ADDRESS(AM43XX_PRCM_BASE), NULL); ++ omap_prm_base_init(); ++ omap_cm_base_init(); + omap3xxx_check_revision(); ++ am33xx_check_features(); ++ am43xx_powerdomains_init(); ++ am43xx_clockdomains_init(); ++ am33xx_hwmod_init(); ++ omap_hwmod_init_postsetup(); ++ omap_clk_init = am43xx_clk_init; + } + #endif + +@@ -650,6 +678,16 @@ void __init omap5_init_early(void) + omap54xx_clockdomains_init(); + omap54xx_hwmod_init(); + omap_hwmod_init_postsetup(); ++ omap_clk_init = omap5xxx_clk_init; ++} ++ ++void __init omap5_init_late(void) ++{ ++ omap_mux_late_init(); ++ omap2_common_pm_late_init(); ++ omap2_common_suspend_init(); ++ omap4_pm_init(); ++ omap2_clk_enable_autoidle_all(); + } + #endif + +@@ -670,9 +708,17 @@ void __init dra7xx_init_early(void) + dra7xx_clockdomains_init(); + dra7xx_hwmod_init(); + omap_hwmod_init_postsetup(); ++ omap_clk_init = dra7xx_clk_init; + } +-#endif + ++void __init dra7xx_init_late(void) ++{ ++ omap2_common_pm_late_init(); ++ omap2_common_suspend_init(); ++ omap4_pm_init(); ++ omap2_clk_enable_autoidle_all(); ++} ++#endif + + void __init omap_sdrc_init(struct omap_sdrc_params *sdrc_cs0, + struct omap_sdrc_params *sdrc_cs1) +--- a/arch/arm/mach-omap2/Kconfig ++++ b/arch/arm/mach-omap2/Kconfig +@@ -66,11 +66,16 @@ config SOC_OMAP5 + config SOC_AM33XX + bool "TI AM33XX" + depends on ARCH_MULTI_V7 +- select ARCH_OMAP2PLUS ++ default y + select ARM_CPU_SUSPEND if PM ++ select COMMON_CLK + select CPU_V7 ++ select MAILBOX if PM + select MULTI_IRQ_HANDLER +- select COMMON_CLK ++ select ARCH_HAS_RESET_CONTROLLER ++ select OMAP_MBOX_FWK if PM ++ select OMAP2PLUS_MBOX if PM ++ select RESET_TI + + config SOC_AM43XX + bool "TI AM43x" +@@ -81,29 +86,9 @@ config SOC_AM43XX + select ARM_GIC + select COMMON_CLK + select MACH_OMAP_GENERIC +- +-config ARCH_OMAP2PLUS +- bool +- select ARCH_HAS_BANDGAP +- select ARCH_HAS_CPUFREQ +- select ARCH_HAS_HOLES_MEMORYMODEL +- select ARCH_OMAP +- select ARCH_REQUIRE_GPIOLIB +- select CLKDEV_LOOKUP +- select CLKSRC_MMIO +- select GENERIC_CLOCKEVENTS +- select GENERIC_IRQ_CHIP +- select HAVE_CLK +- select OMAP_DM_TIMER +- select PINCTRL +- select PROC_DEVICETREE if PROC_FS +- select SOC_BUS +- select SPARSE_IRQ +- select TI_PRIV_EDMA +- select USE_OF +- help +- Systems based on OMAP2, OMAP3, OMAP4 or OMAP5 +- ++ select MIGHT_HAVE_CACHE_L2X0 ++ select ARCH_HAS_RESET_CONTROLLER ++ select RESET_TI + + if ARCH_OMAP2PLUS + +@@ -141,6 +126,9 @@ config SOC_DRA7XX + select ARM_GIC + select HAVE_SMP + select COMMON_CLK ++ select CROSSBAR ++ select ARCH_HAS_RESET_CONTROLLER ++ select RESET_TI + + comment "OMAP Core Type" + depends on ARCH_OMAP2 +--- a/arch/arm/mach-omap2/Makefile ++++ b/arch/arm/mach-omap2/Makefile +@@ -8,7 +8,7 @@ ccflags-$(CONFIG_ARCH_MULTIPLATFORM) := + # Common support + obj-y := id.o io.o control.o mux.o devices.o fb.o serial.o gpmc.o timer.o pm.o \ + common.o gpio.o dma.o wd_timer.o display.o i2c.o hdq1w.o omap_hwmod.o \ +- omap_device.o sram.o ++ omap_device.o sram.o drm.o + + omap-2-3-common = irq.o + hwmod-common = omap_hwmod.o omap_hwmod_reset.o \ +@@ -60,6 +60,7 @@ AFLAGS_sram34xx.o :=-Wa,-march=armv7-a + obj-$(CONFIG_SOC_OMAP2420) += omap2-restart.o + obj-$(CONFIG_SOC_OMAP2430) += omap2-restart.o + obj-$(CONFIG_SOC_AM33XX) += am33xx-restart.o ++obj-$(CONFIG_SOC_AM43XX) += am33xx-restart.o + obj-$(CONFIG_ARCH_OMAP3) += omap3-restart.o + obj-$(CONFIG_ARCH_OMAP4) += omap4-restart.o + obj-$(CONFIG_SOC_OMAP5) += omap4-restart.o +@@ -91,6 +92,7 @@ obj-$(CONFIG_ARCH_OMAP3) += pm34xx.o sl + obj-$(CONFIG_ARCH_OMAP4) += pm44xx.o omap-mpuss-lowpower.o + obj-$(CONFIG_SOC_OMAP5) += omap-mpuss-lowpower.o + obj-$(CONFIG_SOC_DRA7XX) += omap-mpuss-lowpower.o ++obj-$(CONFIG_SOC_AM33XX) += pm33xx.o sleep33xx.o wkup_m3.o + obj-$(CONFIG_PM_DEBUG) += pm-debug.o + + obj-$(CONFIG_POWER_AVS_OMAP) += sr_device.o +@@ -98,6 +100,7 @@ obj-$(CONFIG_POWER_AVS_OMAP_CLASS3) + + + AFLAGS_sleep24xx.o :=-Wa,-march=armv6 + AFLAGS_sleep34xx.o :=-Wa,-march=armv7-a$(plus_sec) ++AFLAGS_sleep33xx.o :=-Wa,-march=armv7-a$(plus_sec) + + endif + +@@ -112,13 +115,13 @@ obj-$(CONFIG_ARCH_OMAP2) += prm2xxx_3xx + obj-$(CONFIG_ARCH_OMAP3) += prm2xxx_3xxx.o prm3xxx.o cm3xxx.o + obj-$(CONFIG_ARCH_OMAP3) += vc3xxx_data.o vp3xxx_data.o + obj-$(CONFIG_SOC_AM33XX) += prm33xx.o cm33xx.o +-obj-$(CONFIG_SOC_AM43XX) += prm33xx.o cm33xx.o + omap-prcm-4-5-common = cminst44xx.o cm44xx.o prm44xx.o \ + prcm_mpu44xx.o prminst44xx.o \ + vc44xx_data.o vp44xx_data.o + obj-$(CONFIG_ARCH_OMAP4) += $(omap-prcm-4-5-common) + obj-$(CONFIG_SOC_OMAP5) += $(omap-prcm-4-5-common) + obj-$(CONFIG_SOC_DRA7XX) += $(omap-prcm-4-5-common) ++obj-$(CONFIG_SOC_AM43XX) += $(omap-prcm-4-5-common) + + # OMAP voltage domains + voltagedomain-common := voltage.o vc.o vp.o +@@ -146,6 +149,7 @@ obj-$(CONFIG_ARCH_OMAP4) += powerdomain + obj-$(CONFIG_SOC_AM33XX) += $(powerdomain-common) + obj-$(CONFIG_SOC_AM33XX) += powerdomains33xx_data.o + obj-$(CONFIG_SOC_AM43XX) += $(powerdomain-common) ++obj-$(CONFIG_SOC_AM43XX) += powerdomains43xx_data.o + obj-$(CONFIG_SOC_OMAP5) += $(powerdomain-common) + obj-$(CONFIG_SOC_OMAP5) += powerdomains54xx_data.o + obj-$(CONFIG_SOC_DRA7XX) += $(powerdomain-common) +@@ -165,6 +169,7 @@ obj-$(CONFIG_ARCH_OMAP4) += clockdomain + obj-$(CONFIG_SOC_AM33XX) += $(clockdomain-common) + obj-$(CONFIG_SOC_AM33XX) += clockdomains33xx_data.o + obj-$(CONFIG_SOC_AM43XX) += $(clockdomain-common) ++obj-$(CONFIG_SOC_AM43XX) += clockdomains43xx_data.o + obj-$(CONFIG_SOC_OMAP5) += $(clockdomain-common) + obj-$(CONFIG_SOC_OMAP5) += clockdomains54xx_data.o + obj-$(CONFIG_SOC_DRA7XX) += $(clockdomain-common) +@@ -184,10 +189,9 @@ obj-$(CONFIG_ARCH_OMAP3) += clock34xx.o + obj-$(CONFIG_ARCH_OMAP3) += clock3517.o clock36xx.o + obj-$(CONFIG_ARCH_OMAP3) += dpll3xxx.o cclock3xxx_data.o + obj-$(CONFIG_ARCH_OMAP3) += clkt_iclk.o +-obj-$(CONFIG_ARCH_OMAP4) += $(clock-common) cclock44xx_data.o ++obj-$(CONFIG_ARCH_OMAP4) += $(clock-common) + obj-$(CONFIG_ARCH_OMAP4) += dpll3xxx.o dpll44xx.o + obj-$(CONFIG_SOC_AM33XX) += $(clock-common) dpll3xxx.o +-obj-$(CONFIG_SOC_AM33XX) += cclock33xx_data.o + obj-$(CONFIG_SOC_OMAP5) += $(clock-common) + obj-$(CONFIG_SOC_OMAP5) += dpll3xxx.o dpll44xx.o + +@@ -210,6 +214,7 @@ obj-$(CONFIG_ARCH_OMAP3) += omap_hwmod_ + obj-$(CONFIG_ARCH_OMAP3) += omap_hwmod_2xxx_3xxx_interconnect_data.o + obj-$(CONFIG_ARCH_OMAP3) += omap_hwmod_3xxx_data.o + obj-$(CONFIG_SOC_AM33XX) += omap_hwmod_33xx_data.o ++obj-$(CONFIG_SOC_AM43XX) += omap_hwmod_33xx_data.o + obj-$(CONFIG_ARCH_OMAP4) += omap_hwmod_44xx_data.o + obj-$(CONFIG_SOC_OMAP5) += omap_hwmod_54xx_data.o + obj-$(CONFIG_SOC_DRA7XX) += omap_hwmod_7xx_data.o +@@ -228,10 +233,6 @@ endif + # OMAP2420 MSDI controller integration support ("MMC") + obj-$(CONFIG_SOC_OMAP2420) += msdi.o + +-ifneq ($(CONFIG_DRM_OMAP),) +-obj-y += drm.o +-endif +- + # Specific board support + obj-$(CONFIG_MACH_OMAP_GENERIC) += board-generic.o + obj-$(CONFIG_MACH_OMAP_H4) += board-h4.o +@@ -305,4 +306,4 @@ endif + emac-$(CONFIG_TI_DAVINCI_EMAC) := am35xx-emac.o + obj-y += $(emac-m) $(emac-y) + +-obj-y += common-board-devices.o twl-common.o dss-common.o ++obj-y += common-board-devices.o twl-common.o +--- a/arch/arm/mach-omap2/omap4-common.c ++++ b/arch/arm/mach-omap2/omap4-common.c +@@ -181,7 +181,7 @@ static int __init omap_l2_cache_init(voi + * To avoid code running on other OMAPs in + * multi-omap builds + */ +- if (!cpu_is_omap44xx()) ++ if (!cpu_is_omap44xx() && !soc_is_am43xx()) + return -ENODEV; + + /* Static mapping, never released */ +@@ -193,26 +193,32 @@ static int __init omap_l2_cache_init(voi + * 16-way associativity, parity disabled + * Way size - 32KB (es1.0) + * Way size - 64KB (es2.0 +) ++ * Way size - 16KB (am43xx) + */ + 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)); + +- if (omap_rev() == OMAP4430_REV_ES1_0) { ++ if (soc_is_am43xx()) ++ aux_ctrl |= ((0x1 << L2X0_AUX_CTRL_WAY_SIZE_SHIFT) | ++ (1 << L2X0_AUX_CTRL_DATA_PREFETCH_SHIFT) | ++ (1 << L2X0_AUX_CTRL_INSTR_PREFETCH_SHIFT) | ++ (1 << L2X0_AUX_CTRL_EARLY_BRESP_SHIFT)); ++ else if (omap_rev() == OMAP4430_REV_ES1_0) + aux_ctrl |= 0x2 << L2X0_AUX_CTRL_WAY_SIZE_SHIFT; +- } else { ++ 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)); +- } +- if (omap_rev() != OMAP4430_REV_ES1_0) ++ ++ if (soc_is_am43xx() || (omap_rev() != OMAP4430_REV_ES1_0)) + omap_smc1(0x109, aux_ctrl); + + /* Enable PL310 L2 Cache controller */ +- omap_smc1(0x102, 0x1); ++ omap_smc1(0x102, L2X0_CTRL_EN); + + if (of_have_populated_dt()) + l2x0_of_init(aux_ctrl, L2X0_AUX_CTRL_MASK); +@@ -233,7 +239,10 @@ omap_early_initcall(omap_l2_cache_init); + + void __iomem *omap4_get_sar_ram_base(void) + { +- return sar_ram_base; ++ if (sar_ram_base) ++ return sar_ram_base; ++ else ++ return NULL; + } + + /* +--- a/arch/arm/mach-omap2/omap4-sar-layout.h ++++ b/arch/arm/mach-omap2/omap4-sar-layout.h +@@ -31,6 +31,8 @@ + /* 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 ++#define OMAP5_CPU0_WAKEUP_NS_PA_ADDR_OFFSET 0xe00 ++#define OMAP5_CPU1_WAKEUP_NS_PA_ADDR_OFFSET 0xe04 + + #define SAR_BACKUP_STATUS_OFFSET (SAR_BANK3_OFFSET + 0x500) + #define SAR_SECURE_RAM_SIZE_OFFSET (SAR_BANK3_OFFSET + 0x504) +--- a/arch/arm/mach-omap2/omap_device.c ++++ b/arch/arm/mach-omap2/omap_device.c +@@ -35,6 +35,7 @@ + #include <linux/pm_runtime.h> + #include <linux/of.h> + #include <linux/notifier.h> ++#include <linux/suspend.h> + + #include "soc.h" + #include "omap_device.h" +@@ -45,37 +46,32 @@ + static void _add_clkdev(struct omap_device *od, const char *clk_alias, + const char *clk_name) + { ++ int ret; + struct clk *r; +- struct clk_lookup *l; ++ struct device *dev = &od->pdev->dev; ++ struct device_node *node = dev->of_node; + + if (!clk_alias || !clk_name) + return; + +- dev_dbg(&od->pdev->dev, "Creating %s -> %s\n", clk_alias, clk_name); ++ dev_dbg(dev, "Creating %s -> %s\n", clk_alias, clk_name); + +- r = clk_get_sys(dev_name(&od->pdev->dev), clk_alias); ++ r = clk_get(dev, clk_alias); + if (!IS_ERR(r)) { +- dev_warn(&od->pdev->dev, +- "alias %s already exists\n", clk_alias); ++ if (!node) ++ dev_warn(dev, "alias '%s' already exists\n", clk_alias); + clk_put(r); + return; + } + +- r = clk_get(NULL, clk_name); +- if (IS_ERR(r)) { +- dev_err(&od->pdev->dev, +- "clk_get for %s failed\n", clk_name); +- return; +- } ++ if (node) ++ dev_err(dev, "FIXME: clock-name '%s' DOES NOT exist in dt!\n", ++ clk_alias); + +- l = clkdev_alloc(r, clk_alias, dev_name(&od->pdev->dev)); +- if (!l) { +- dev_err(&od->pdev->dev, +- "clkdev_alloc for %s failed\n", clk_alias); +- return; +- } +- +- clkdev_add(l); ++ ret = clk_add_alias(clk_alias, dev_name(dev), (char *)clk_name, dev); ++ if (ret) ++ dev_err(dev, "Failed to alias %s to %s: %d\n", clk_alias, ++ clk_name, ret); + } + + /** +@@ -621,6 +617,13 @@ static int _od_suspend_noirq(struct devi + + if (!ret && !pm_runtime_status_suspended(dev)) { + if (pm_generic_runtime_suspend(dev) == 0) { ++ if (!pm_runtime_suspended(dev)) { ++ /* NOTE: *might* indicate driver race */ ++ dev_dbg(dev, "%s: Force suspending\n", ++ __func__); ++ pm_runtime_set_suspended(dev); ++ od->flags |= OMAP_DEVICE_SUSPEND_FORCED; ++ } + omap_device_idle(pdev); + od->flags |= OMAP_DEVICE_SUSPENDED; + } +@@ -634,10 +637,15 @@ static int _od_resume_noirq(struct devic + struct platform_device *pdev = to_platform_device(dev); + struct omap_device *od = to_omap_device(pdev); + +- if ((od->flags & OMAP_DEVICE_SUSPENDED) && +- !pm_runtime_status_suspended(dev)) { ++ if (od->flags & OMAP_DEVICE_SUSPENDED) { + od->flags &= ~OMAP_DEVICE_SUSPENDED; + omap_device_enable(pdev); ++ ++ if (od->flags & OMAP_DEVICE_SUSPEND_FORCED) { ++ pm_runtime_set_active(dev); ++ od->flags &= ~OMAP_DEVICE_SUSPEND_FORCED; ++ } ++ + pm_generic_runtime_resume(dev); + } + +@@ -850,6 +858,7 @@ static int __init omap_device_late_idle( + { + struct platform_device *pdev = to_platform_device(dev); + struct omap_device *od = to_omap_device(pdev); ++ struct omap_hwmod *oh = NULL; + int i; + + if (!od) +@@ -874,6 +883,19 @@ static int __init omap_device_late_idle( + __func__); + omap_device_idle(pdev); + } ++ } else { ++ /* ++ * There are some IPs that do not have MSTANDBY asserted by default ++ * which is necessary for PER domain transition. If the drivers ++ * are not compiled into the kernel HWMOD code will not change the ++ * state of the IPs if the IP was never enabled, so we keep track of ++ * them here to idle them with a pm_notifier. ++ */ ++ for (i = 0; i < od->hwmods_cnt; i++) { ++ oh = od->hwmods[i]; ++ if (oh->flags & HWMOD_FORCE_MSTANDBY_REPEATED) ++ omap_hwmod_disable_force_mstandby_repeated(oh); ++ } + } + + return 0; +--- a/arch/arm/mach-omap2/omap_device.h ++++ b/arch/arm/mach-omap2/omap_device.h +@@ -38,6 +38,7 @@ extern struct dev_pm_domain omap_device_ + + /* omap_device.flags values */ + #define OMAP_DEVICE_SUSPENDED BIT(0) ++#define OMAP_DEVICE_SUSPEND_FORCED BIT(1) + + /** + * struct omap_device - omap_device wrapper for platform_devices +--- a/arch/arm/mach-omap2/omap-hotplug.c ++++ b/arch/arm/mach-omap2/omap-hotplug.c +@@ -22,6 +22,7 @@ + #include "omap-wakeupgen.h" + #include "common.h" + #include "powerdomain.h" ++#include "soc.h" + + /* + * platform-specific code to shutdown a CPU +@@ -47,7 +48,10 @@ void __ref omap4_cpu_die(unsigned int cp + /* + * Enter into low power state + */ +- omap4_hotplug_cpu(cpu, PWRDM_POWER_OFF); ++ if (soc_is_dra7xx()) ++ omap4_hotplug_cpu(cpu, PWRDM_POWER_RET); ++ else ++ omap4_hotplug_cpu(cpu, PWRDM_POWER_OFF); + + if (omap_secure_apis_support()) + boot_cpu = omap_read_auxcoreboot0(); +--- a/arch/arm/mach-omap2/omap_hwmod_33xx_data.c ++++ b/arch/arm/mach-omap2/omap_hwmod_33xx_data.c +@@ -26,9 +26,11 @@ + #include "cm33xx.h" + #include "prm33xx.h" + #include "prm-regbits-33xx.h" ++#include "prcm43xx.h" + #include "i2c.h" + #include "mmc.h" + #include "wd_timer.h" ++#include "soc.h" + + /* + * IP blocks +@@ -52,7 +54,7 @@ static struct omap_hwmod am33xx_emif_hwm + .name = "emif", + .class = &am33xx_emif_hwmod_class, + .clkdm_name = "l3_clkdm", +- .flags = (HWMOD_INIT_NO_IDLE | HWMOD_INIT_NO_RESET), ++ .flags = HWMOD_INIT_NO_IDLE, + .main_clk = "dpll_ddr_m2_div2_ck", + .prcm = { + .omap4 = { +@@ -74,11 +76,9 @@ static struct omap_hwmod am33xx_l3_main_ + .name = "l3_main", + .class = &am33xx_l3_hwmod_class, + .clkdm_name = "l3_clkdm", +- .flags = (HWMOD_INIT_NO_IDLE | HWMOD_INIT_NO_RESET), +- .main_clk = "l3_gclk", ++ .flags = HWMOD_INIT_NO_IDLE, + .prcm = { + .omap4 = { +- .clkctrl_offs = AM33XX_CM_PER_L3_CLKCTRL_OFFSET, + .modulemode = MODULEMODE_SWCTRL, + }, + }, +@@ -96,11 +96,10 @@ static struct omap_hwmod am33xx_l3_instr + .name = "l3_instr", + .class = &am33xx_l3_hwmod_class, + .clkdm_name = "l3_clkdm", +- .flags = (HWMOD_INIT_NO_IDLE | HWMOD_INIT_NO_RESET), ++ .flags = HWMOD_INIT_NO_IDLE, + .main_clk = "l3_gclk", + .prcm = { + .omap4 = { +- .clkctrl_offs = AM33XX_CM_PER_L3_INSTR_CLKCTRL_OFFSET, + .modulemode = MODULEMODE_SWCTRL, + }, + }, +@@ -119,11 +118,10 @@ static struct omap_hwmod am33xx_l4_ls_hw + .name = "l4_ls", + .class = &am33xx_l4_hwmod_class, + .clkdm_name = "l4ls_clkdm", +- .flags = (HWMOD_INIT_NO_IDLE | HWMOD_INIT_NO_RESET), ++ .flags = HWMOD_INIT_NO_IDLE, + .main_clk = "l4ls_gclk", + .prcm = { + .omap4 = { +- .clkctrl_offs = AM33XX_CM_PER_L4LS_CLKCTRL_OFFSET, + .modulemode = MODULEMODE_SWCTRL, + }, + }, +@@ -133,12 +131,10 @@ static struct omap_hwmod am33xx_l4_ls_hw + static struct omap_hwmod am33xx_l4_hs_hwmod = { + .name = "l4_hs", + .class = &am33xx_l4_hwmod_class, +- .clkdm_name = "l4hs_clkdm", +- .flags = (HWMOD_INIT_NO_IDLE | HWMOD_INIT_NO_RESET), ++ .flags = HWMOD_INIT_NO_IDLE, + .main_clk = "l4hs_gclk", + .prcm = { + .omap4 = { +- .clkctrl_offs = AM33XX_CM_PER_L4HS_CLKCTRL_OFFSET, + .modulemode = MODULEMODE_SWCTRL, + }, + }, +@@ -150,10 +146,9 @@ static struct omap_hwmod am33xx_l4_wkup_ + .name = "l4_wkup", + .class = &am33xx_l4_hwmod_class, + .clkdm_name = "l4_wkup_clkdm", +- .flags = (HWMOD_INIT_NO_IDLE | HWMOD_INIT_NO_RESET), ++ .flags = HWMOD_INIT_NO_IDLE, + .prcm = { + .omap4 = { +- .clkctrl_offs = AM33XX_CM_WKUP_L4WKUP_CLKCTRL_OFFSET, + .modulemode = MODULEMODE_SWCTRL, + }, + }, +@@ -170,11 +165,10 @@ static struct omap_hwmod am33xx_mpu_hwmo + .name = "mpu", + .class = &am33xx_mpu_hwmod_class, + .clkdm_name = "mpu_clkdm", +- .flags = (HWMOD_INIT_NO_IDLE | HWMOD_INIT_NO_RESET), ++ .flags = HWMOD_INIT_NO_IDLE, + .main_clk = "dpll_mpu_m2_ck", + .prcm = { + .omap4 = { +- .clkctrl_offs = AM33XX_CM_MPU_MPU_CLKCTRL_OFFSET, + .modulemode = MODULEMODE_SWCTRL, + }, + }, +@@ -198,13 +192,9 @@ static struct omap_hwmod am33xx_wkup_m3_ + .class = &am33xx_wkup_m3_hwmod_class, + .clkdm_name = "l4_wkup_aon_clkdm", + /* Keep hardreset asserted */ +- .flags = HWMOD_INIT_NO_RESET | HWMOD_NO_IDLEST, +- .main_clk = "dpll_core_m4_div2_ck", ++ .flags = HWMOD_NO_IDLEST, + .prcm = { + .omap4 = { +- .clkctrl_offs = AM33XX_CM_WKUP_WKUP_M3_CLKCTRL_OFFSET, +- .rstctrl_offs = AM33XX_RM_WKUP_RSTCTRL_OFFSET, +- .rstst_offs = AM33XX_RM_WKUP_RSTST_OFFSET, + .modulemode = MODULEMODE_SWCTRL, + }, + }, +@@ -233,8 +223,6 @@ static struct omap_hwmod am33xx_pruss_hw + .main_clk = "pruss_ocp_gclk", + .prcm = { + .omap4 = { +- .clkctrl_offs = AM33XX_CM_PER_PRUSS_CLKCTRL_OFFSET, +- .rstctrl_offs = AM33XX_RM_PER_RSTCTRL_OFFSET, + .modulemode = MODULEMODE_SWCTRL, + }, + }, +@@ -259,9 +247,6 @@ static struct omap_hwmod am33xx_gfx_hwmo + .main_clk = "gfx_fck_div_ck", + .prcm = { + .omap4 = { +- .clkctrl_offs = AM33XX_CM_GFX_GFX_CLKCTRL_OFFSET, +- .rstctrl_offs = AM33XX_RM_GFX_RSTCTRL_OFFSET, +- .rstst_offs = AM33XX_RM_GFX_RSTST_OFFSET, + .modulemode = MODULEMODE_SWCTRL, + }, + }, +@@ -305,11 +290,8 @@ static struct omap_hwmod_class am33xx_ad + static struct omap_hwmod am33xx_adc_tsc_hwmod = { + .name = "adc_tsc", + .class = &am33xx_adc_tsc_hwmod_class, +- .clkdm_name = "l4_wkup_clkdm", +- .main_clk = "adc_tsc_fck", + .prcm = { + .omap4 = { +- .clkctrl_offs = AM33XX_CM_WKUP_ADC_TSC_CLKCTRL_OFFSET, + .modulemode = MODULEMODE_SWCTRL, + }, + }, +@@ -395,6 +377,7 @@ static struct omap_hwmod_class_sysconfig + .sysc_offs = 0x84, + .syss_offs = 0x88, + .sysc_flags = SYSS_HAS_RESET_STATUS, ++ .sysc_fields = &omap_hwmod_sysc_type4, + }; + + static struct omap_hwmod_class am33xx_aes0_hwmod_class = { +@@ -406,10 +389,8 @@ static struct omap_hwmod am33xx_aes0_hwm + .name = "aes", + .class = &am33xx_aes0_hwmod_class, + .clkdm_name = "l3_clkdm", +- .main_clk = "aes0_fck", + .prcm = { + .omap4 = { +- .clkctrl_offs = AM33XX_CM_PER_AES0_CLKCTRL_OFFSET, + .modulemode = MODULEMODE_SWCTRL, + }, + }, +@@ -432,10 +413,8 @@ static struct omap_hwmod am33xx_sha0_hwm + .name = "sham", + .class = &am33xx_sha0_hwmod_class, + .clkdm_name = "l3_clkdm", +- .main_clk = "l3_gclk", + .prcm = { + .omap4 = { +- .clkctrl_offs = AM33XX_CM_PER_SHA0_CLKCTRL_OFFSET, + .modulemode = MODULEMODE_SWCTRL, + }, + }, +@@ -450,11 +429,9 @@ static struct omap_hwmod am33xx_ocmcram_ + .name = "ocmcram", + .class = &am33xx_ocmcram_hwmod_class, + .clkdm_name = "l3_clkdm", +- .flags = (HWMOD_INIT_NO_IDLE | HWMOD_INIT_NO_RESET), +- .main_clk = "l3_gclk", ++ .flags = HWMOD_INIT_NO_IDLE, + .prcm = { + .omap4 = { +- .clkctrl_offs = AM33XX_CM_PER_OCMCRAM_CLKCTRL_OFFSET, + .modulemode = MODULEMODE_SWCTRL, + }, + }, +@@ -501,7 +478,6 @@ static struct omap_hwmod am33xx_smartref + .main_clk = "smartreflex0_fck", + .prcm = { + .omap4 = { +- .clkctrl_offs = AM33XX_CM_WKUP_SMARTREFLEX0_CLKCTRL_OFFSET, + .modulemode = MODULEMODE_SWCTRL, + }, + }, +@@ -515,7 +491,6 @@ static struct omap_hwmod am33xx_smartref + .main_clk = "smartreflex1_fck", + .prcm = { + .omap4 = { +- .clkctrl_offs = AM33XX_CM_WKUP_SMARTREFLEX1_CLKCTRL_OFFSET, + .modulemode = MODULEMODE_SWCTRL, + }, + }, +@@ -532,11 +507,9 @@ static struct omap_hwmod am33xx_control_ + .name = "control", + .class = &am33xx_control_hwmod_class, + .clkdm_name = "l4_wkup_clkdm", +- .flags = (HWMOD_INIT_NO_IDLE | HWMOD_INIT_NO_RESET), +- .main_clk = "dpll_core_m4_div2_ck", ++ .flags = HWMOD_INIT_NO_IDLE, + .prcm = { + .omap4 = { +- .clkctrl_offs = AM33XX_CM_WKUP_CONTROL_CLKCTRL_OFFSET, + .modulemode = MODULEMODE_SWCTRL, + }, + }, +@@ -566,12 +539,11 @@ static struct omap_hwmod am33xx_cpgmac0_ + .name = "cpgmac0", + .class = &am33xx_cpgmac0_hwmod_class, + .clkdm_name = "cpsw_125mhz_clkdm", +- .flags = (HWMOD_SWSUP_SIDLE | HWMOD_SWSUP_MSTANDBY), +- .main_clk = "cpsw_125mhz_gclk", ++ .flags = (HWMOD_SWSUP_SIDLE | HWMOD_SWSUP_MSTANDBY | ++ HWMOD_FORCE_MSTANDBY_REPEATED), + .mpu_rt_idx = 1, + .prcm = { + .omap4 = { +- .clkctrl_offs = AM33XX_CM_PER_CPGMAC0_CLKCTRL_OFFSET, + .modulemode = MODULEMODE_SWCTRL, + }, + }, +@@ -588,7 +560,6 @@ static struct omap_hwmod am33xx_mdio_hwm + .name = "davinci_mdio", + .class = &am33xx_mdio_hwmod_class, + .clkdm_name = "cpsw_125mhz_clkdm", +- .main_clk = "cpsw_125mhz_gclk", + }; + + /* +@@ -603,10 +574,8 @@ static struct omap_hwmod am33xx_dcan0_hw + .name = "d_can0", + .class = &am33xx_dcan_hwmod_class, + .clkdm_name = "l4ls_clkdm", +- .main_clk = "dcan0_fck", + .prcm = { + .omap4 = { +- .clkctrl_offs = AM33XX_CM_PER_DCAN0_CLKCTRL_OFFSET, + .modulemode = MODULEMODE_SWCTRL, + }, + }, +@@ -617,10 +586,8 @@ static struct omap_hwmod am33xx_dcan1_hw + .name = "d_can1", + .class = &am33xx_dcan_hwmod_class, + .clkdm_name = "l4ls_clkdm", +- .main_clk = "dcan1_fck", + .prcm = { + .omap4 = { +- .clkctrl_offs = AM33XX_CM_PER_DCAN1_CLKCTRL_OFFSET, + .modulemode = MODULEMODE_SWCTRL, + }, + }, +@@ -647,10 +614,8 @@ static struct omap_hwmod am33xx_elm_hwmo + .name = "elm", + .class = &am33xx_elm_hwmod_class, + .clkdm_name = "l4ls_clkdm", +- .main_clk = "l4ls_gclk", + .prcm = { + .omap4 = { +- .clkctrl_offs = AM33XX_CM_PER_ELM_CLKCTRL_OFFSET, + .modulemode = MODULEMODE_SWCTRL, + }, + }, +@@ -689,10 +654,8 @@ static struct omap_hwmod am33xx_epwmss0_ + .name = "epwmss0", + .class = &am33xx_epwmss_hwmod_class, + .clkdm_name = "l4ls_clkdm", +- .main_clk = "l4ls_gclk", + .prcm = { + .omap4 = { +- .clkctrl_offs = AM33XX_CM_PER_EPWMSS0_CLKCTRL_OFFSET, + .modulemode = MODULEMODE_SWCTRL, + }, + }, +@@ -703,7 +666,6 @@ static struct omap_hwmod am33xx_ecap0_hw + .name = "ecap0", + .class = &am33xx_ecap_hwmod_class, + .clkdm_name = "l4ls_clkdm", +- .main_clk = "l4ls_gclk", + }; + + /* eqep0 */ +@@ -719,7 +681,6 @@ static struct omap_hwmod am33xx_ehrpwm0_ + .name = "ehrpwm0", + .class = &am33xx_ehrpwm_hwmod_class, + .clkdm_name = "l4ls_clkdm", +- .main_clk = "l4ls_gclk", + }; + + /* epwmss1 */ +@@ -727,10 +688,8 @@ static struct omap_hwmod am33xx_epwmss1_ + .name = "epwmss1", + .class = &am33xx_epwmss_hwmod_class, + .clkdm_name = "l4ls_clkdm", +- .main_clk = "l4ls_gclk", + .prcm = { + .omap4 = { +- .clkctrl_offs = AM33XX_CM_PER_EPWMSS1_CLKCTRL_OFFSET, + .modulemode = MODULEMODE_SWCTRL, + }, + }, +@@ -741,7 +700,6 @@ static struct omap_hwmod am33xx_ecap1_hw + .name = "ecap1", + .class = &am33xx_ecap_hwmod_class, + .clkdm_name = "l4ls_clkdm", +- .main_clk = "l4ls_gclk", + }; + + /* eqep1 */ +@@ -757,7 +715,6 @@ static struct omap_hwmod am33xx_ehrpwm1_ + .name = "ehrpwm1", + .class = &am33xx_ehrpwm_hwmod_class, + .clkdm_name = "l4ls_clkdm", +- .main_clk = "l4ls_gclk", + }; + + /* epwmss2 */ +@@ -765,10 +722,8 @@ static struct omap_hwmod am33xx_epwmss2_ + .name = "epwmss2", + .class = &am33xx_epwmss_hwmod_class, + .clkdm_name = "l4ls_clkdm", +- .main_clk = "l4ls_gclk", + .prcm = { + .omap4 = { +- .clkctrl_offs = AM33XX_CM_PER_EPWMSS2_CLKCTRL_OFFSET, + .modulemode = MODULEMODE_SWCTRL, + }, + }, +@@ -779,7 +734,6 @@ static struct omap_hwmod am33xx_ecap2_hw + .name = "ecap2", + .class = &am33xx_ecap_hwmod_class, + .clkdm_name = "l4ls_clkdm", +- .main_clk = "l4ls_gclk", + }; + + /* eqep2 */ +@@ -795,7 +749,6 @@ static struct omap_hwmod am33xx_ehrpwm2_ + .name = "ehrpwm2", + .class = &am33xx_ehrpwm_hwmod_class, + .clkdm_name = "l4ls_clkdm", +- .main_clk = "l4ls_gclk", + }; + + /* +@@ -825,90 +778,62 @@ static struct omap_gpio_dev_attr gpio_de + }; + + /* gpio0 */ +-static struct omap_hwmod_opt_clk gpio0_opt_clks[] = { +- { .role = "dbclk", .clk = "gpio0_dbclk" }, +-}; + + static struct omap_hwmod am33xx_gpio0_hwmod = { + .name = "gpio1", + .class = &am33xx_gpio_hwmod_class, + .clkdm_name = "l4_wkup_clkdm", + .flags = HWMOD_CONTROL_OPT_CLKS_IN_RESET, +- .main_clk = "dpll_core_m4_div2_ck", + .prcm = { + .omap4 = { +- .clkctrl_offs = AM33XX_CM_WKUP_GPIO0_CLKCTRL_OFFSET, + .modulemode = MODULEMODE_SWCTRL, + }, + }, +- .opt_clks = gpio0_opt_clks, +- .opt_clks_cnt = ARRAY_SIZE(gpio0_opt_clks), + .dev_attr = &gpio_dev_attr, + }; + + /* gpio1 */ +-static struct omap_hwmod_opt_clk gpio1_opt_clks[] = { +- { .role = "dbclk", .clk = "gpio1_dbclk" }, +-}; + + static struct omap_hwmod am33xx_gpio1_hwmod = { + .name = "gpio2", + .class = &am33xx_gpio_hwmod_class, + .clkdm_name = "l4ls_clkdm", + .flags = HWMOD_CONTROL_OPT_CLKS_IN_RESET, +- .main_clk = "l4ls_gclk", + .prcm = { + .omap4 = { +- .clkctrl_offs = AM33XX_CM_PER_GPIO1_CLKCTRL_OFFSET, + .modulemode = MODULEMODE_SWCTRL, + }, + }, +- .opt_clks = gpio1_opt_clks, +- .opt_clks_cnt = ARRAY_SIZE(gpio1_opt_clks), + .dev_attr = &gpio_dev_attr, + }; + + /* gpio2 */ +-static struct omap_hwmod_opt_clk gpio2_opt_clks[] = { +- { .role = "dbclk", .clk = "gpio2_dbclk" }, +-}; + + static struct omap_hwmod am33xx_gpio2_hwmod = { + .name = "gpio3", + .class = &am33xx_gpio_hwmod_class, + .clkdm_name = "l4ls_clkdm", + .flags = HWMOD_CONTROL_OPT_CLKS_IN_RESET, +- .main_clk = "l4ls_gclk", + .prcm = { + .omap4 = { +- .clkctrl_offs = AM33XX_CM_PER_GPIO2_CLKCTRL_OFFSET, + .modulemode = MODULEMODE_SWCTRL, + }, + }, +- .opt_clks = gpio2_opt_clks, +- .opt_clks_cnt = ARRAY_SIZE(gpio2_opt_clks), + .dev_attr = &gpio_dev_attr, + }; + + /* gpio3 */ +-static struct omap_hwmod_opt_clk gpio3_opt_clks[] = { +- { .role = "dbclk", .clk = "gpio3_dbclk" }, +-}; + + static struct omap_hwmod am33xx_gpio3_hwmod = { + .name = "gpio4", + .class = &am33xx_gpio_hwmod_class, + .clkdm_name = "l4ls_clkdm", + .flags = HWMOD_CONTROL_OPT_CLKS_IN_RESET, +- .main_clk = "l4ls_gclk", + .prcm = { + .omap4 = { +- .clkctrl_offs = AM33XX_CM_PER_GPIO3_CLKCTRL_OFFSET, + .modulemode = MODULEMODE_SWCTRL, + }, + }, +- .opt_clks = gpio3_opt_clks, +- .opt_clks_cnt = ARRAY_SIZE(gpio3_opt_clks), + .dev_attr = &gpio_dev_attr, + }; + +@@ -932,11 +857,9 @@ static struct omap_hwmod am33xx_gpmc_hwm + .name = "gpmc", + .class = &am33xx_gpmc_hwmod_class, + .clkdm_name = "l3s_clkdm", +- .flags = (HWMOD_INIT_NO_IDLE | HWMOD_INIT_NO_RESET), +- .main_clk = "l3s_gclk", ++ .flags = HWMOD_INIT_NO_RESET, + .prcm = { + .omap4 = { +- .clkctrl_offs = AM33XX_CM_PER_GPMC_CLKCTRL_OFFSET, + .modulemode = MODULEMODE_SWCTRL, + }, + }, +@@ -971,10 +894,8 @@ static struct omap_hwmod am33xx_i2c1_hwm + .class = &i2c_class, + .clkdm_name = "l4_wkup_clkdm", + .flags = HWMOD_16BIT_REG | HWMOD_SET_DEFAULT_CLOCKACT, +- .main_clk = "dpll_per_m2_div4_wkupdm_ck", + .prcm = { + .omap4 = { +- .clkctrl_offs = AM33XX_CM_WKUP_I2C0_CLKCTRL_OFFSET, + .modulemode = MODULEMODE_SWCTRL, + }, + }, +@@ -987,10 +908,8 @@ static struct omap_hwmod am33xx_i2c2_hwm + .class = &i2c_class, + .clkdm_name = "l4ls_clkdm", + .flags = HWMOD_16BIT_REG | HWMOD_SET_DEFAULT_CLOCKACT, +- .main_clk = "dpll_per_m2_div4_ck", + .prcm = { + .omap4 = { +- .clkctrl_offs = AM33XX_CM_PER_I2C1_CLKCTRL_OFFSET, + .modulemode = MODULEMODE_SWCTRL, + }, + }, +@@ -1003,10 +922,8 @@ static struct omap_hwmod am33xx_i2c3_hwm + .class = &i2c_class, + .clkdm_name = "l4ls_clkdm", + .flags = HWMOD_16BIT_REG | HWMOD_SET_DEFAULT_CLOCKACT, +- .main_clk = "dpll_per_m2_div4_ck", + .prcm = { + .omap4 = { +- .clkctrl_offs = AM33XX_CM_PER_I2C2_CLKCTRL_OFFSET, + .modulemode = MODULEMODE_SWCTRL, + }, + }, +@@ -1065,10 +982,8 @@ static struct omap_hwmod am33xx_mailbox_ + .name = "mailbox", + .class = &am33xx_mailbox_hwmod_class, + .clkdm_name = "l4ls_clkdm", +- .main_clk = "l4ls_gclk", + .prcm = { + .omap4 = { +- .clkctrl_offs = AM33XX_CM_PER_MAILBOX0_CLKCTRL_OFFSET, + .modulemode = MODULEMODE_SWCTRL, + }, + }, +@@ -1098,7 +1013,6 @@ static struct omap_hwmod am33xx_mcasp0_h + .main_clk = "mcasp0_fck", + .prcm = { + .omap4 = { +- .clkctrl_offs = AM33XX_CM_PER_MCASP0_CLKCTRL_OFFSET, + .modulemode = MODULEMODE_SWCTRL, + }, + }, +@@ -1112,7 +1026,6 @@ static struct omap_hwmod am33xx_mcasp1_h + .main_clk = "mcasp1_fck", + .prcm = { + .omap4 = { +- .clkctrl_offs = AM33XX_CM_PER_MCASP1_CLKCTRL_OFFSET, + .modulemode = MODULEMODE_SWCTRL, + }, + }, +@@ -1147,7 +1060,6 @@ static struct omap_hwmod am33xx_mmc0_hwm + .main_clk = "mmc_clk", + .prcm = { + .omap4 = { +- .clkctrl_offs = AM33XX_CM_PER_MMC0_CLKCTRL_OFFSET, + .modulemode = MODULEMODE_SWCTRL, + }, + }, +@@ -1166,7 +1078,6 @@ static struct omap_hwmod am33xx_mmc1_hwm + .main_clk = "mmc_clk", + .prcm = { + .omap4 = { +- .clkctrl_offs = AM33XX_CM_PER_MMC1_CLKCTRL_OFFSET, + .modulemode = MODULEMODE_SWCTRL, + }, + }, +@@ -1184,7 +1095,6 @@ static struct omap_hwmod am33xx_mmc2_hwm + .main_clk = "mmc_clk", + .prcm = { + .omap4 = { +- .clkctrl_offs = AM33XX_CM_PER_MMC2_CLKCTRL_OFFSET, + .modulemode = MODULEMODE_SWCTRL, + }, + }, +@@ -1213,10 +1123,8 @@ static struct omap_hwmod am33xx_rtc_hwmo + .name = "rtc", + .class = &am33xx_rtc_hwmod_class, + .clkdm_name = "l4_rtc_clkdm", +- .main_clk = "clk_32768_ck", + .prcm = { + .omap4 = { +- .clkctrl_offs = AM33XX_CM_RTC_RTC_CLKCTRL_OFFSET, + .modulemode = MODULEMODE_SWCTRL, + }, + }, +@@ -1248,10 +1156,8 @@ static struct omap_hwmod am33xx_spi0_hwm + .name = "spi0", + .class = &am33xx_spi_hwmod_class, + .clkdm_name = "l4ls_clkdm", +- .main_clk = "dpll_per_m2_div4_ck", + .prcm = { + .omap4 = { +- .clkctrl_offs = AM33XX_CM_PER_SPI0_CLKCTRL_OFFSET, + .modulemode = MODULEMODE_SWCTRL, + }, + }, +@@ -1263,10 +1169,8 @@ static struct omap_hwmod am33xx_spi1_hwm + .name = "spi1", + .class = &am33xx_spi_hwmod_class, + .clkdm_name = "l4ls_clkdm", +- .main_clk = "dpll_per_m2_div4_ck", + .prcm = { + .omap4 = { +- .clkctrl_offs = AM33XX_CM_PER_SPI1_CLKCTRL_OFFSET, + .modulemode = MODULEMODE_SWCTRL, + }, + }, +@@ -1289,12 +1193,119 @@ static struct omap_hwmod am33xx_spinlock + .main_clk = "l4ls_gclk", + .prcm = { + .omap4 = { +- .clkctrl_offs = AM33XX_CM_PER_SPINLOCK_CLKCTRL_OFFSET, + .modulemode = MODULEMODE_SWCTRL, + }, + }, + }; + ++static struct omap_hwmod_class_sysconfig am43xx_qspi_sysc = { ++ .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 am43xx_qspi_hwmod_class = { ++ .name = "qspi", ++ .sysc = &am43xx_qspi_sysc, ++}; ++ ++static struct omap_hwmod am43xx_qspi_hwmod = { ++ .name = "qspi", ++ .class = &am43xx_qspi_hwmod_class, ++ .clkdm_name = "l3s_clkdm", ++ .main_clk = "l3s_gclk", ++ .prcm = { ++ .omap4 = { ++ .clkctrl_offs = AM43XX_CM_PER_QSPI_CLKCTRL_OFFSET, ++ .modulemode = MODULEMODE_SWCTRL, ++ }, ++ }, ++}; ++ ++/* 'ocp2scp' class ++ * ++ */ ++ ++ ++static struct omap_hwmod_class am43xx_ocp2scp_hwmod_class = { ++ .name = "ocp2scp", ++}; ++ ++/* ocp2scp0 */ ++static struct omap_hwmod am43xx_ocp2scp0_hwmod = { ++ .name = "ocp2scp0", ++ .class = &am43xx_ocp2scp_hwmod_class, ++ .clkdm_name = "l4ls_clkdm", ++ .main_clk = "l4ls_gclk", ++ .prcm = { ++ .omap4 = { ++ .clkctrl_offs = AM43XX_CM_PER_USBPHYOCP2SCP0_CLKCTRL_OFFSET, ++ .modulemode = MODULEMODE_SWCTRL, ++ }, ++ }, ++}; ++ ++/* ocp2scp1 */ ++static struct omap_hwmod am43xx_ocp2scp1_hwmod = { ++ .name = "ocp2scp1", ++ .class = &am43xx_ocp2scp_hwmod_class, ++ .clkdm_name = "l4ls_clkdm", ++ .main_clk = "l4ls_gclk", ++ .prcm = { ++ .omap4 = { ++ .clkctrl_offs = AM43XX_CM_PER_USBPHYOCP2SCP1_CLKCTRL_OFFSET, ++ .modulemode = MODULEMODE_SWCTRL, ++ }, ++ }, ++}; ++ ++/* 'usb_otg_ss' class */ ++static struct omap_hwmod_class_sysconfig am43xx_usb_otg_ss_sysc = { ++ .rev_offs = 0x0000, ++ .sysc_offs = 0x0010, ++ .sysc_flags = (SYSC_HAS_DMADISABLE | 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 am43xx_usb_otg_ss_hwmod_class = { ++ .name = "usb_otg_ss", ++ .sysc = &am43xx_usb_otg_ss_sysc, ++}; ++ ++/* usb_otg_ss0 */ ++static struct omap_hwmod am43xx_usb_otg_ss0_hwmod = { ++ .name = "usb_otg_ss0", ++ .class = &am43xx_usb_otg_ss_hwmod_class, ++ .clkdm_name = "l3s_clkdm", ++ .main_clk = "l3s_gclk", ++ .prcm = { ++ .omap4 = { ++ .clkctrl_offs = AM43XX_CM_PER_USB_OTG_SS0_CLKCTRL_OFFSET, ++ .modulemode = MODULEMODE_SWCTRL, ++ }, ++ }, ++}; ++ ++/* usb_otg_ss1 */ ++static struct omap_hwmod am43xx_usb_otg_ss1_hwmod = { ++ .name = "usb_otg_ss1", ++ .class = &am43xx_usb_otg_ss_hwmod_class, ++ .clkdm_name = "l3s_clkdm", ++ .main_clk = "l3s_gclk", ++ .prcm = { ++ .omap4 = { ++ .clkctrl_offs = AM43XX_CM_PER_USB_OTG_SS1_CLKCTRL_OFFSET, ++ .modulemode = MODULEMODE_SWCTRL, ++ }, ++ }, ++}; ++ + /* 'timer 2-7' class */ + static struct omap_hwmod_class_sysconfig am33xx_timer_sysc = { + .rev_offs = 0x0000, +@@ -1332,10 +1343,8 @@ static struct omap_hwmod am33xx_timer1_h + .name = "timer1", + .class = &am33xx_timer1ms_hwmod_class, + .clkdm_name = "l4_wkup_clkdm", +- .main_clk = "timer1_fck", + .prcm = { + .omap4 = { +- .clkctrl_offs = AM33XX_CM_WKUP_TIMER1_CLKCTRL_OFFSET, + .modulemode = MODULEMODE_SWCTRL, + }, + }, +@@ -1345,10 +1354,8 @@ static struct omap_hwmod am33xx_timer2_h + .name = "timer2", + .class = &am33xx_timer_hwmod_class, + .clkdm_name = "l4ls_clkdm", +- .main_clk = "timer2_fck", + .prcm = { + .omap4 = { +- .clkctrl_offs = AM33XX_CM_PER_TIMER2_CLKCTRL_OFFSET, + .modulemode = MODULEMODE_SWCTRL, + }, + }, +@@ -1358,10 +1365,8 @@ static struct omap_hwmod am33xx_timer3_h + .name = "timer3", + .class = &am33xx_timer_hwmod_class, + .clkdm_name = "l4ls_clkdm", +- .main_clk = "timer3_fck", + .prcm = { + .omap4 = { +- .clkctrl_offs = AM33XX_CM_PER_TIMER3_CLKCTRL_OFFSET, + .modulemode = MODULEMODE_SWCTRL, + }, + }, +@@ -1371,10 +1376,8 @@ static struct omap_hwmod am33xx_timer4_h + .name = "timer4", + .class = &am33xx_timer_hwmod_class, + .clkdm_name = "l4ls_clkdm", +- .main_clk = "timer4_fck", + .prcm = { + .omap4 = { +- .clkctrl_offs = AM33XX_CM_PER_TIMER4_CLKCTRL_OFFSET, + .modulemode = MODULEMODE_SWCTRL, + }, + }, +@@ -1384,10 +1387,8 @@ static struct omap_hwmod am33xx_timer5_h + .name = "timer5", + .class = &am33xx_timer_hwmod_class, + .clkdm_name = "l4ls_clkdm", +- .main_clk = "timer5_fck", + .prcm = { + .omap4 = { +- .clkctrl_offs = AM33XX_CM_PER_TIMER5_CLKCTRL_OFFSET, + .modulemode = MODULEMODE_SWCTRL, + }, + }, +@@ -1397,10 +1398,8 @@ static struct omap_hwmod am33xx_timer6_h + .name = "timer6", + .class = &am33xx_timer_hwmod_class, + .clkdm_name = "l4ls_clkdm", +- .main_clk = "timer6_fck", + .prcm = { + .omap4 = { +- .clkctrl_offs = AM33XX_CM_PER_TIMER6_CLKCTRL_OFFSET, + .modulemode = MODULEMODE_SWCTRL, + }, + }, +@@ -1410,10 +1409,8 @@ static struct omap_hwmod am33xx_timer7_h + .name = "timer7", + .class = &am33xx_timer_hwmod_class, + .clkdm_name = "l4ls_clkdm", +- .main_clk = "timer7_fck", + .prcm = { + .omap4 = { +- .clkctrl_offs = AM33XX_CM_PER_TIMER7_CLKCTRL_OFFSET, + .modulemode = MODULEMODE_SWCTRL, + }, + }, +@@ -1431,7 +1428,6 @@ static struct omap_hwmod am33xx_tpcc_hwm + .main_clk = "l3_gclk", + .prcm = { + .omap4 = { +- .clkctrl_offs = AM33XX_CM_PER_TPCC_CLKCTRL_OFFSET, + .modulemode = MODULEMODE_SWCTRL, + }, + }, +@@ -1457,11 +1453,11 @@ static struct omap_hwmod am33xx_tptc0_hw + .name = "tptc0", + .class = &am33xx_tptc_hwmod_class, + .clkdm_name = "l3_clkdm", +- .flags = HWMOD_SWSUP_SIDLE | HWMOD_SWSUP_MSTANDBY, ++ .flags = HWMOD_SWSUP_SIDLE | HWMOD_SWSUP_MSTANDBY | ++ HWMOD_FORCE_MSTANDBY_REPEATED, + .main_clk = "l3_gclk", + .prcm = { + .omap4 = { +- .clkctrl_offs = AM33XX_CM_PER_TPTC0_CLKCTRL_OFFSET, + .modulemode = MODULEMODE_SWCTRL, + }, + }, +@@ -1472,11 +1468,11 @@ static struct omap_hwmod am33xx_tptc1_hw + .name = "tptc1", + .class = &am33xx_tptc_hwmod_class, + .clkdm_name = "l3_clkdm", +- .flags = (HWMOD_SWSUP_SIDLE | HWMOD_SWSUP_MSTANDBY), ++ .flags = (HWMOD_SWSUP_SIDLE | HWMOD_SWSUP_MSTANDBY | ++ HWMOD_FORCE_MSTANDBY_REPEATED), + .main_clk = "l3_gclk", + .prcm = { + .omap4 = { +- .clkctrl_offs = AM33XX_CM_PER_TPTC1_CLKCTRL_OFFSET, + .modulemode = MODULEMODE_SWCTRL, + }, + }, +@@ -1487,11 +1483,11 @@ static struct omap_hwmod am33xx_tptc2_hw + .name = "tptc2", + .class = &am33xx_tptc_hwmod_class, + .clkdm_name = "l3_clkdm", +- .flags = (HWMOD_SWSUP_SIDLE | HWMOD_SWSUP_MSTANDBY), ++ .flags = (HWMOD_SWSUP_SIDLE | HWMOD_SWSUP_MSTANDBY | ++ HWMOD_FORCE_MSTANDBY_REPEATED), + .main_clk = "l3_gclk", + .prcm = { + .omap4 = { +- .clkctrl_offs = AM33XX_CM_PER_TPTC2_CLKCTRL_OFFSET, + .modulemode = MODULEMODE_SWCTRL, + }, + }, +@@ -1520,10 +1516,8 @@ static struct omap_hwmod am33xx_uart1_hw + .class = &uart_class, + .clkdm_name = "l4_wkup_clkdm", + .flags = DEBUG_AM33XXUART1_FLAGS | HWMOD_SWSUP_SIDLE_ACT, +- .main_clk = "dpll_per_m2_div4_wkupdm_ck", + .prcm = { + .omap4 = { +- .clkctrl_offs = AM33XX_CM_WKUP_UART0_CLKCTRL_OFFSET, + .modulemode = MODULEMODE_SWCTRL, + }, + }, +@@ -1534,10 +1528,8 @@ static struct omap_hwmod am33xx_uart2_hw + .class = &uart_class, + .clkdm_name = "l4ls_clkdm", + .flags = HWMOD_SWSUP_SIDLE_ACT, +- .main_clk = "dpll_per_m2_div4_ck", + .prcm = { + .omap4 = { +- .clkctrl_offs = AM33XX_CM_PER_UART1_CLKCTRL_OFFSET, + .modulemode = MODULEMODE_SWCTRL, + }, + }, +@@ -1549,10 +1541,8 @@ static struct omap_hwmod am33xx_uart3_hw + .class = &uart_class, + .clkdm_name = "l4ls_clkdm", + .flags = HWMOD_SWSUP_SIDLE_ACT, +- .main_clk = "dpll_per_m2_div4_ck", + .prcm = { + .omap4 = { +- .clkctrl_offs = AM33XX_CM_PER_UART2_CLKCTRL_OFFSET, + .modulemode = MODULEMODE_SWCTRL, + }, + }, +@@ -1563,10 +1553,8 @@ static struct omap_hwmod am33xx_uart4_hw + .class = &uart_class, + .clkdm_name = "l4ls_clkdm", + .flags = HWMOD_SWSUP_SIDLE_ACT, +- .main_clk = "dpll_per_m2_div4_ck", + .prcm = { + .omap4 = { +- .clkctrl_offs = AM33XX_CM_PER_UART3_CLKCTRL_OFFSET, + .modulemode = MODULEMODE_SWCTRL, + }, + }, +@@ -1577,10 +1565,8 @@ static struct omap_hwmod am33xx_uart5_hw + .class = &uart_class, + .clkdm_name = "l4ls_clkdm", + .flags = HWMOD_SWSUP_SIDLE_ACT, +- .main_clk = "dpll_per_m2_div4_ck", + .prcm = { + .omap4 = { +- .clkctrl_offs = AM33XX_CM_PER_UART4_CLKCTRL_OFFSET, + .modulemode = MODULEMODE_SWCTRL, + }, + }, +@@ -1591,10 +1577,8 @@ static struct omap_hwmod am33xx_uart6_hw + .class = &uart_class, + .clkdm_name = "l4ls_clkdm", + .flags = HWMOD_SWSUP_SIDLE_ACT, +- .main_clk = "dpll_per_m2_div4_ck", + .prcm = { + .omap4 = { +- .clkctrl_offs = AM33XX_CM_PER_UART5_CLKCTRL_OFFSET, + .modulemode = MODULEMODE_SWCTRL, + }, + }, +@@ -1627,10 +1611,8 @@ static struct omap_hwmod am33xx_wd_timer + .class = &am33xx_wd_timer_hwmod_class, + .clkdm_name = "l4_wkup_clkdm", + .flags = HWMOD_SWSUP_SIDLE, +- .main_clk = "wdt1_fck", + .prcm = { + .omap4 = { +- .clkctrl_offs = AM33XX_CM_WKUP_WDT1_CLKCTRL_OFFSET, + .modulemode = MODULEMODE_SWCTRL, + }, + }, +@@ -1658,8 +1640,8 @@ static struct omap_hwmod am33xx_usbss_hw + .name = "usb_otg_hs", + .class = &am33xx_usbotg_class, + .clkdm_name = "l3s_clkdm", +- .flags = HWMOD_SWSUP_SIDLE | HWMOD_SWSUP_MSTANDBY, +- .main_clk = "usbotg_fck", ++ .flags = HWMOD_SWSUP_SIDLE | HWMOD_SWSUP_MSTANDBY | ++ HWMOD_FORCE_MSTANDBY_REPEATED, + .prcm = { + .omap4 = { + .clkctrl_offs = AM33XX_CM_PER_USB0_CLKCTRL_OFFSET, +@@ -1668,6 +1650,272 @@ static struct omap_hwmod am33xx_usbss_hw + }, + }; + ++static struct omap_hwmod_class_sysconfig am43xx_synctimer_sysc = { ++ .rev_offs = 0x0, ++ .sysc_offs = 0x4, ++ .sysc_flags = SYSC_HAS_SIDLEMODE, ++ .idlemodes = (SIDLE_FORCE | SIDLE_NO), ++ .sysc_fields = &omap_hwmod_sysc_type1, ++}; ++ ++static struct omap_hwmod_class am43xx_synctimer_hwmod_class = { ++ .name = "synctimer", ++ .sysc = &am43xx_synctimer_sysc, ++}; ++ ++static struct omap_hwmod am43xx_synctimer_hwmod = { ++ .name = "counter_32k", ++ .class = &am43xx_synctimer_hwmod_class, ++ .clkdm_name = "l4_wkup_aon_clkdm", ++ .flags = HWMOD_SWSUP_SIDLE, ++ .prcm = { ++ .omap4 = { ++ .clkctrl_offs = AM43XX_CM_WKUP_SYNCTIMER_CLKCTRL_OFFSET, ++ .modulemode = MODULEMODE_SWCTRL, ++ }, ++ }, ++}; ++ ++static struct omap_hwmod am43xx_timer8_hwmod = { ++ .name = "timer8", ++ .class = &am33xx_timer_hwmod_class, ++ .clkdm_name = "l4ls_clkdm", ++ .prcm = { ++ .omap4 = { ++ .clkctrl_offs = AM43XX_CM_PER_TIMER8_CLKCTRL_OFFSET, ++ .modulemode = MODULEMODE_SWCTRL, ++ }, ++ }, ++}; ++ ++static struct omap_hwmod am43xx_timer9_hwmod = { ++ .name = "timer9", ++ .class = &am33xx_timer_hwmod_class, ++ .clkdm_name = "l4ls_clkdm", ++ .prcm = { ++ .omap4 = { ++ .clkctrl_offs = AM43XX_CM_PER_TIMER9_CLKCTRL_OFFSET, ++ .modulemode = MODULEMODE_SWCTRL, ++ }, ++ }, ++}; ++ ++static struct omap_hwmod am43xx_timer10_hwmod = { ++ .name = "timer10", ++ .class = &am33xx_timer_hwmod_class, ++ .clkdm_name = "l4ls_clkdm", ++ .prcm = { ++ .omap4 = { ++ .clkctrl_offs = AM43XX_CM_PER_TIMER10_CLKCTRL_OFFSET, ++ .modulemode = MODULEMODE_SWCTRL, ++ }, ++ }, ++}; ++ ++static struct omap_hwmod am43xx_timer11_hwmod = { ++ .name = "timer11", ++ .class = &am33xx_timer_hwmod_class, ++ .clkdm_name = "l4ls_clkdm", ++ .prcm = { ++ .omap4 = { ++ .clkctrl_offs = AM43XX_CM_PER_TIMER11_CLKCTRL_OFFSET, ++ .modulemode = MODULEMODE_SWCTRL, ++ }, ++ }, ++}; ++ ++static struct omap_hwmod am43xx_epwmss3_hwmod = { ++ .name = "epwmss3", ++ .class = &am33xx_epwmss_hwmod_class, ++ .clkdm_name = "l4ls_clkdm", ++ .prcm = { ++ .omap4 = { ++ .clkctrl_offs = AM43XX_CM_PER_EPWMSS3_CLKCTRL_OFFSET, ++ .modulemode = MODULEMODE_SWCTRL, ++ }, ++ }, ++}; ++ ++static struct omap_hwmod am43xx_ehrpwm3_hwmod = { ++ .name = "ehrpwm3", ++ .class = &am33xx_ehrpwm_hwmod_class, ++ .clkdm_name = "l4ls_clkdm", ++}; ++ ++static struct omap_hwmod am43xx_epwmss4_hwmod = { ++ .name = "epwmss4", ++ .class = &am33xx_epwmss_hwmod_class, ++ .clkdm_name = "l4ls_clkdm", ++ .prcm = { ++ .omap4 = { ++ .clkctrl_offs = AM43XX_CM_PER_EPWMSS4_CLKCTRL_OFFSET, ++ .modulemode = MODULEMODE_SWCTRL, ++ }, ++ }, ++}; ++ ++static struct omap_hwmod am43xx_ehrpwm4_hwmod = { ++ .name = "ehrpwm4", ++ .class = &am33xx_ehrpwm_hwmod_class, ++ .clkdm_name = "l4ls_clkdm", ++}; ++ ++static struct omap_hwmod am43xx_epwmss5_hwmod = { ++ .name = "epwmss5", ++ .class = &am33xx_epwmss_hwmod_class, ++ .clkdm_name = "l4ls_clkdm", ++ .prcm = { ++ .omap4 = { ++ .clkctrl_offs = AM43XX_CM_PER_EPWMSS5_CLKCTRL_OFFSET, ++ .modulemode = MODULEMODE_SWCTRL, ++ }, ++ }, ++}; ++ ++static struct omap_hwmod am43xx_ehrpwm5_hwmod = { ++ .name = "ehrpwm5", ++ .class = &am33xx_ehrpwm_hwmod_class, ++ .clkdm_name = "l4ls_clkdm", ++}; ++ ++static struct omap_hwmod am43xx_spi2_hwmod = { ++ .name = "spi2", ++ .class = &am33xx_spi_hwmod_class, ++ .clkdm_name = "l4ls_clkdm", ++ .prcm = { ++ .omap4 = { ++ .clkctrl_offs = AM43XX_CM_PER_SPI2_CLKCTRL_OFFSET, ++ .modulemode = MODULEMODE_SWCTRL, ++ }, ++ }, ++ .dev_attr = &mcspi_attrib, ++}; ++ ++static struct omap_hwmod am43xx_spi3_hwmod = { ++ .name = "spi3", ++ .class = &am33xx_spi_hwmod_class, ++ .clkdm_name = "l4ls_clkdm", ++ .prcm = { ++ .omap4 = { ++ .clkctrl_offs = AM43XX_CM_PER_SPI3_CLKCTRL_OFFSET, ++ .modulemode = MODULEMODE_SWCTRL, ++ }, ++ }, ++ .dev_attr = &mcspi_attrib, ++}; ++ ++static struct omap_hwmod am43xx_spi4_hwmod = { ++ .name = "spi4", ++ .class = &am33xx_spi_hwmod_class, ++ .clkdm_name = "l4ls_clkdm", ++ .prcm = { ++ .omap4 = { ++ .clkctrl_offs = AM43XX_CM_PER_SPI4_CLKCTRL_OFFSET, ++ .modulemode = MODULEMODE_SWCTRL, ++ }, ++ }, ++ .dev_attr = &mcspi_attrib, ++}; ++ ++static struct omap_hwmod am43xx_gpio4_hwmod = { ++ .name = "gpio5", ++ .class = &am33xx_gpio_hwmod_class, ++ .clkdm_name = "l4ls_clkdm", ++ .flags = HWMOD_CONTROL_OPT_CLKS_IN_RESET, ++ .prcm = { ++ .omap4 = { ++ .clkctrl_offs = AM43XX_CM_PER_GPIO4_CLKCTRL_OFFSET, ++ .modulemode = MODULEMODE_SWCTRL, ++ }, ++ }, ++ .dev_attr = &gpio_dev_attr, ++}; ++ ++static struct omap_hwmod am43xx_gpio5_hwmod = { ++ .name = "gpio6", ++ .class = &am33xx_gpio_hwmod_class, ++ .clkdm_name = "l4ls_clkdm", ++ .flags = HWMOD_CONTROL_OPT_CLKS_IN_RESET, ++ .prcm = { ++ .omap4 = { ++ .clkctrl_offs = AM43XX_CM_PER_GPIO5_CLKCTRL_OFFSET, ++ .modulemode = MODULEMODE_SWCTRL, ++ }, ++ }, ++ .dev_attr = &gpio_dev_attr, ++}; ++ ++/* Display sub system - DSS */ ++ ++static struct omap_hwmod_dma_info am43xx_dss_sdma_chs[] = { ++ { .name = "dispc", .dma_req = 5 }, ++ { .dma_req = -1 }, ++}; ++ ++struct omap_dss_dispc_dev_attr am43xx_dss_dispc_dev_attr = { ++ .manager_count = 1, ++ .has_framedonetv_irq = 0 ++}; ++ ++ ++static struct omap_hwmod_class_sysconfig am43xx_dispc_sysc = { ++ .rev_offs = 0x0000, ++ .sysc_offs = 0x0010, ++ .syss_offs = 0x0014, ++ .sysc_flags = (SYSC_HAS_SIDLEMODE | SYSC_HAS_MIDLEMODE), ++ .idlemodes = (SIDLE_FORCE | SIDLE_NO | SIDLE_SMART), ++ .sysc_fields = &omap_hwmod_sysc_type1, ++}; ++ ++static struct omap_hwmod_class am43xx_dispc_hwmod_class = { ++ .name = "dispc", ++ .sysc = &am43xx_dispc_sysc, ++}; ++ ++ ++ ++static struct omap_hwmod am43xx_dss_core_hwmod = { ++ .name = "dss_core", ++ .class = &omap2_dss_hwmod_class, ++ .clkdm_name = "dss_clkdm", ++ .main_clk = "disp_clk", ++ .sdma_reqs = am43xx_dss_sdma_chs, ++ .prcm = { ++ .omap4 = { ++ .clkctrl_offs = AM43XX_CM_PER_DSS_CLKCTRL_OFFSET, ++ .modulemode = MODULEMODE_SWCTRL, ++ }, ++ }, ++}; ++ ++/* display controller -dispc*/ ++ ++static struct omap_hwmod am43xx_dss_dispc_hwmod = { ++ .name = "dss_dispc", ++ .class = &am43xx_dispc_hwmod_class, ++ .clkdm_name = "dss_clkdm", ++ .main_clk = "disp_clk", ++ .prcm = { ++ .omap4 = { ++ .clkctrl_offs = AM43XX_CM_PER_DSS_CLKCTRL_OFFSET, ++ }, ++ }, ++ .dev_attr = &am43xx_dss_dispc_dev_attr, ++}; ++ ++/*RFBI*/ ++ ++static struct omap_hwmod am43xx_dss_rfbi_hwmod = { ++ .name = "dss_rfbi", ++ .class = &omap2_rfbi_hwmod_class, ++ .clkdm_name = "dss_clkdm", ++ .main_clk = "disp_clk", ++ .prcm = { ++ .omap4 = { ++ .clkctrl_offs = AM43XX_CM_PER_DSS_CLKCTRL_OFFSET, ++ }, ++ }, ++}; + + /* + * Interfaces +@@ -1766,7 +2014,6 @@ static struct omap_hwmod_ocp_if am33xx_p + static struct omap_hwmod_ocp_if am33xx_wkup_m3__l4_wkup = { + .master = &am33xx_wkup_m3_hwmod, + .slave = &am33xx_l4_wkup_hwmod, +- .clk = "dpll_core_m4_div2_ck", + .user = OCP_USER_MPU | OCP_USER_SDMA, + }; + +@@ -1782,7 +2029,6 @@ static struct omap_hwmod_ocp_if am33xx_g + static struct omap_hwmod_ocp_if am33xx_l4_wkup__wkup_m3 = { + .master = &am33xx_l4_wkup_hwmod, + .slave = &am33xx_wkup_m3_hwmod, +- .clk = "dpll_core_m4_div2_ck", + .user = OCP_USER_MPU | OCP_USER_SDMA, + }; + +@@ -1824,7 +2070,6 @@ static struct omap_hwmod_ocp_if am33xx_l + static struct omap_hwmod_ocp_if am33xx_l4_wkup__smartreflex0 = { + .master = &am33xx_l4_wkup_hwmod, + .slave = &am33xx_smartreflex0_hwmod, +- .clk = "dpll_core_m4_div2_ck", + .user = OCP_USER_MPU, + }; + +@@ -1832,7 +2077,6 @@ static struct omap_hwmod_ocp_if am33xx_l + static struct omap_hwmod_ocp_if am33xx_l4_wkup__smartreflex1 = { + .master = &am33xx_l4_wkup_hwmod, + .slave = &am33xx_smartreflex1_hwmod, +- .clk = "dpll_core_m4_div2_ck", + .user = OCP_USER_MPU, + }; + +@@ -1840,7 +2084,6 @@ static struct omap_hwmod_ocp_if am33xx_l + static struct omap_hwmod_ocp_if am33xx_l4_wkup__control = { + .master = &am33xx_l4_wkup_hwmod, + .slave = &am33xx_control_hwmod, +- .clk = "dpll_core_m4_div2_ck", + .user = OCP_USER_MPU, + }; + +@@ -1896,7 +2139,6 @@ static struct omap_hwmod_ocp_if am33xx_l + static struct omap_hwmod_ocp_if am33xx_l4_wkup__i2c1 = { + .master = &am33xx_l4_wkup_hwmod, + .slave = &am33xx_i2c1_hwmod, +- .clk = "dpll_core_m4_div2_ck", + .user = OCP_USER_MPU, + }; + +@@ -1904,7 +2146,6 @@ static struct omap_hwmod_ocp_if am33xx_l + static struct omap_hwmod_ocp_if am33xx_l4_wkup__gpio0 = { + .master = &am33xx_l4_wkup_hwmod, + .slave = &am33xx_gpio0_hwmod, +- .clk = "dpll_core_m4_div2_ck", + .user = OCP_USER_MPU | OCP_USER_SDMA, + }; + +@@ -2237,6 +2478,45 @@ static struct omap_hwmod_ocp_if am33xx_l + .user = OCP_USER_MPU, + }; + ++static struct omap_hwmod_ocp_if am43xx_l3_s__qspi = { ++ .master = &am33xx_l3_s_hwmod, ++ .slave = &am43xx_qspi_hwmod, ++ .clk = "l3s_gclk", ++ .user = OCP_USER_MPU | OCP_USER_SDMA, ++}; ++ ++/* l3_main_1 -> usb_otg_ss0 */ ++static struct omap_hwmod_ocp_if am43xx_l3_s__usbotgss0 = { ++ .master = &am33xx_l3_s_hwmod, ++ .slave = &am43xx_usb_otg_ss0_hwmod, ++ .clk = "l3s_gclk", ++ .user = OCP_USER_MPU | OCP_USER_SDMA, ++}; ++ ++/* l3_main_1 -> usb_otg_ss1 */ ++static struct omap_hwmod_ocp_if am43xx_l3_s__usbotgss1 = { ++ .master = &am33xx_l3_s_hwmod, ++ .slave = &am43xx_usb_otg_ss1_hwmod, ++ .clk = "l3s_gclk", ++ .user = OCP_USER_MPU | OCP_USER_SDMA, ++}; ++ ++/* l4 ls -> ocp2scp0 */ ++static struct omap_hwmod_ocp_if am33xx_l4_ls__ocp2scp0 = { ++ .master = &am33xx_l4_ls_hwmod, ++ .slave = &am43xx_ocp2scp0_hwmod, ++ .clk = "l4ls_gclk", ++ .user = OCP_USER_MPU, ++}; ++ ++/* l4 ls -> ocp2scp0 */ ++static struct omap_hwmod_ocp_if am33xx_l4_ls__ocp2scp1 = { ++ .master = &am33xx_l4_ls_hwmod, ++ .slave = &am43xx_ocp2scp1_hwmod, ++ .clk = "l4ls_gclk", ++ .user = OCP_USER_MPU, ++}; ++ + /* l4 ls -> mcspi0 */ + static struct omap_hwmod_ocp_if am33xx_l4_ls__mcspi0 = { + .master = &am33xx_l4_ls_hwmod, +@@ -2257,7 +2537,6 @@ static struct omap_hwmod_ocp_if am33xx_l + static struct omap_hwmod_ocp_if am33xx_l4_wkup__timer1 = { + .master = &am33xx_l4_wkup_hwmod, + .slave = &am33xx_timer1_hwmod, +- .clk = "dpll_core_m4_div2_ck", + .user = OCP_USER_MPU, + }; + +@@ -2375,7 +2654,6 @@ static struct omap_hwmod_ocp_if am33xx_l + static struct omap_hwmod_ocp_if am33xx_l4_wkup__uart1 = { + .master = &am33xx_l4_wkup_hwmod, + .slave = &am33xx_uart1_hwmod, +- .clk = "dpll_core_m4_div2_ck", + .user = OCP_USER_MPU, + }; + +@@ -2423,7 +2701,6 @@ static struct omap_hwmod_ocp_if am33xx_l + static struct omap_hwmod_ocp_if am33xx_l4_wkup__wd_timer1 = { + .master = &am33xx_l4_wkup_hwmod, + .slave = &am33xx_wd_timer1_hwmod, +- .clk = "dpll_core_m4_div2_ck", + .user = OCP_USER_MPU, + }; + +@@ -2480,8 +2757,473 @@ static struct omap_hwmod_ocp_if am33xx_l + .user = OCP_USER_MPU | OCP_USER_SDMA, + }; + ++static struct omap_hwmod_ocp_if am33xx_l4_wkup__synctimer = { ++ .master = &am33xx_l4_wkup_hwmod, ++ .slave = &am43xx_synctimer_hwmod, ++ .clk = "sys_clkin_ck", ++ .user = OCP_USER_MPU, ++}; ++ ++static struct omap_hwmod_ocp_if am43xx_l4_ls__timer8 = { ++ .master = &am33xx_l4_ls_hwmod, ++ .slave = &am43xx_timer8_hwmod, ++ .clk = "l4ls_gclk", ++ .user = OCP_USER_MPU, ++}; ++ ++static struct omap_hwmod_ocp_if am43xx_l4_ls__timer9 = { ++ .master = &am33xx_l4_ls_hwmod, ++ .slave = &am43xx_timer9_hwmod, ++ .clk = "l4ls_gclk", ++ .user = OCP_USER_MPU, ++}; ++ ++static struct omap_hwmod_ocp_if am43xx_l4_ls__timer10 = { ++ .master = &am33xx_l4_ls_hwmod, ++ .slave = &am43xx_timer10_hwmod, ++ .clk = "l4ls_gclk", ++ .user = OCP_USER_MPU, ++}; ++ ++static struct omap_hwmod_ocp_if am43xx_l4_ls__timer11 = { ++ .master = &am33xx_l4_ls_hwmod, ++ .slave = &am43xx_timer11_hwmod, ++ .clk = "l4ls_gclk", ++ .user = OCP_USER_MPU, ++}; ++ ++static struct omap_hwmod_ocp_if am43xx_l4_ls__epwmss3 = { ++ .master = &am33xx_l4_ls_hwmod, ++ .slave = &am43xx_epwmss3_hwmod, ++ .clk = "l4ls_gclk", ++ .user = OCP_USER_MPU, ++}; ++ ++static struct omap_hwmod_ocp_if am43xx_epwmss3__ehrpwm3 = { ++ .master = &am43xx_epwmss3_hwmod, ++ .slave = &am43xx_ehrpwm3_hwmod, ++ .clk = "l4ls_gclk", ++ .user = OCP_USER_MPU, ++}; ++ ++static struct omap_hwmod_ocp_if am43xx_l4_ls__epwmss4 = { ++ .master = &am33xx_l4_ls_hwmod, ++ .slave = &am43xx_epwmss4_hwmod, ++ .clk = "l4ls_gclk", ++ .user = OCP_USER_MPU, ++}; ++ ++static struct omap_hwmod_ocp_if am43xx_epwmss4__ehrpwm4 = { ++ .master = &am43xx_epwmss4_hwmod, ++ .slave = &am43xx_ehrpwm4_hwmod, ++ .clk = "l4ls_gclk", ++ .user = OCP_USER_MPU, ++}; ++ ++static struct omap_hwmod_ocp_if am43xx_l4_ls__epwmss5 = { ++ .master = &am33xx_l4_ls_hwmod, ++ .slave = &am43xx_epwmss5_hwmod, ++ .clk = "l4ls_gclk", ++ .user = OCP_USER_MPU, ++}; ++ ++static struct omap_hwmod_ocp_if am43xx_epwmss5__ehrpwm5 = { ++ .master = &am43xx_epwmss5_hwmod, ++ .slave = &am43xx_ehrpwm5_hwmod, ++ .clk = "l4ls_gclk", ++ .user = OCP_USER_MPU, ++}; ++ ++static struct omap_hwmod_ocp_if am43xx_l4_ls__mcspi2 = { ++ .master = &am33xx_l4_ls_hwmod, ++ .slave = &am43xx_spi2_hwmod, ++ .clk = "l4ls_gclk", ++ .user = OCP_USER_MPU, ++}; ++ ++static struct omap_hwmod_ocp_if am43xx_l4_ls__mcspi3 = { ++ .master = &am33xx_l4_ls_hwmod, ++ .slave = &am43xx_spi3_hwmod, ++ .clk = "l4ls_gclk", ++ .user = OCP_USER_MPU, ++}; ++ ++static struct omap_hwmod_ocp_if am43xx_l4_ls__mcspi4 = { ++ .master = &am33xx_l4_ls_hwmod, ++ .slave = &am43xx_spi4_hwmod, ++ .clk = "l4ls_gclk", ++ .user = OCP_USER_MPU, ++}; ++ ++static struct omap_hwmod_ocp_if am43xx_l4_ls__gpio4 = { ++ .master = &am33xx_l4_ls_hwmod, ++ .slave = &am43xx_gpio4_hwmod, ++ .clk = "l4ls_gclk", ++ .user = OCP_USER_MPU | OCP_USER_SDMA, ++}; ++ ++static struct omap_hwmod_ocp_if am43xx_l4_ls__gpio5 = { ++ .master = &am33xx_l4_ls_hwmod, ++ .slave = &am43xx_gpio5_hwmod, ++ .clk = "l4ls_gclk", ++ .user = OCP_USER_MPU | OCP_USER_SDMA, ++}; ++ ++static struct omap_hwmod_ocp_if am43xx_l3_main__pruss = { ++ .master = &am33xx_l3_main_hwmod, ++ .slave = &am33xx_pruss_hwmod, ++ .clk = "dpll_core_m4_ck", ++ .user = OCP_USER_MPU, ++}; ++ ++/* rng */ ++static struct omap_hwmod_class_sysconfig am33xx_rng_sysc = { ++ .rev_offs = 0x1fe0, ++ .sysc_offs = 0x1fe4, ++ .sysc_flags = SYSC_HAS_AUTOIDLE | SYSC_HAS_SIDLEMODE, ++ .idlemodes = SIDLE_FORCE | SIDLE_NO, ++ .sysc_fields = &omap_hwmod_sysc_type1, ++}; ++ ++static struct omap_hwmod_class am33xx_rng_hwmod_class = { ++ .name = "rng", ++ .sysc = &am33xx_rng_sysc, ++}; ++ ++static struct omap_hwmod am33xx_rng_hwmod = { ++ .name = "rng", ++ .class = &am33xx_rng_hwmod_class, ++ .clkdm_name = "l4ls_clkdm", ++ .flags = HWMOD_SWSUP_SIDLE, ++ .prcm = { ++ .omap4 = { ++ .modulemode = MODULEMODE_SWCTRL, ++ }, ++ }, ++}; ++ ++static struct omap_hwmod_ocp_if am33xx_l4_per__rng = { ++ .master = &am33xx_l4_ls_hwmod, ++ .slave = &am33xx_rng_hwmod, ++ .clk = "rng_fck", ++ .user = OCP_USER_MPU, ++}; ++ ++static struct omap_hwmod_class_sysconfig am43xx_des_sysc = { ++ .rev_offs = 0x30, ++ .sysc_offs = 0x34, ++ .syss_offs = 0x38, ++ .sysc_flags = SYSS_HAS_RESET_STATUS, ++}; ++ ++static struct omap_hwmod_class am43xx_des_hwmod_class = { ++ .name = "des", ++ .sysc = &am43xx_des_sysc, ++}; ++ ++static struct omap_hwmod am43xx_des_hwmod = { ++ .name = "des", ++ .class = &am43xx_des_hwmod_class, ++ .clkdm_name = "l3_clkdm", ++ .prcm = { ++ .omap4 = { ++ .clkctrl_offs = AM43XX_CM_PER_DES_CLKCTRL_OFFSET, ++ .modulemode = MODULEMODE_SWCTRL, ++ }, ++ }, ++}; ++ ++static struct omap_hwmod_ocp_if am43xx_l3_main__des = { ++ .master = &am33xx_l3_main_hwmod, ++ .slave = &am43xx_des_hwmod, ++ .clk = "l3_gclk", ++ .user = OCP_USER_MPU, ++}; ++ ++/* DSS -> L3 Main */ ++static struct omap_hwmod_ocp_if am43xx_dss__l3_main = { ++ .master = &am43xx_dss_core_hwmod, ++ .slave = &am33xx_l3_main_hwmod, ++ .clk = "disp_clk", ++ .user = OCP_USER_MPU | OCP_USER_SDMA, ++}; ++ ++/* L4-ls -> DSS */ ++static struct omap_hwmod_ocp_if am43xx_l4_ls__dss = { ++ .master = &am33xx_l4_ls_hwmod, ++ .slave = &am43xx_dss_core_hwmod, ++ .clk = "l4ls_gclk", ++ .user = OCP_USER_MPU | OCP_USER_SDMA, ++}; ++ ++/* L4_ls -> dss_dispc */ ++static struct omap_hwmod_ocp_if am43xx_l4_ls__dss_dispc = { ++ .master = &am33xx_l4_ls_hwmod, ++ .slave = &am43xx_dss_dispc_hwmod, ++ .clk = "l4ls_gclk", ++ .user = OCP_USER_MPU | OCP_USER_SDMA, ++}; ++ ++/* L4_ls -> dss_rfbi */ ++static struct omap_hwmod_ocp_if am43xx_l4_ls__dss_rfbi = { ++ .master = &am33xx_l4_ls_hwmod, ++ .slave = &am43xx_dss_rfbi_hwmod, ++ .clk = "l4ls_gclk", ++ .user = OCP_USER_MPU | OCP_USER_SDMA, ++}; ++ ++#define CLKCTRL(oh, clkctrl) ((oh).prcm.omap4.clkctrl_offs = (clkctrl)) ++ ++static void am43xx_hwmod_clkctrl(void) ++{ ++ CLKCTRL(am33xx_uart2_hwmod, AM43XX_CM_PER_UART1_CLKCTRL_OFFSET); ++ CLKCTRL(am33xx_uart3_hwmod, AM43XX_CM_PER_UART2_CLKCTRL_OFFSET); ++ CLKCTRL(am33xx_uart4_hwmod, AM43XX_CM_PER_UART3_CLKCTRL_OFFSET); ++ CLKCTRL(am33xx_uart5_hwmod, AM43XX_CM_PER_UART4_CLKCTRL_OFFSET); ++ CLKCTRL(am33xx_uart6_hwmod, AM43XX_CM_PER_UART5_CLKCTRL_OFFSET); ++ CLKCTRL(am33xx_dcan0_hwmod, AM43XX_CM_PER_DCAN0_CLKCTRL_OFFSET); ++ CLKCTRL(am33xx_dcan1_hwmod, AM43XX_CM_PER_DCAN1_CLKCTRL_OFFSET); ++ CLKCTRL(am33xx_elm_hwmod, AM43XX_CM_PER_ELM_CLKCTRL_OFFSET); ++ CLKCTRL(am33xx_epwmss0_hwmod, AM43XX_CM_PER_EPWMSS0_CLKCTRL_OFFSET); ++ CLKCTRL(am33xx_epwmss1_hwmod, AM43XX_CM_PER_EPWMSS1_CLKCTRL_OFFSET); ++ CLKCTRL(am33xx_epwmss2_hwmod, AM43XX_CM_PER_EPWMSS2_CLKCTRL_OFFSET); ++ CLKCTRL(am33xx_gpio1_hwmod, AM43XX_CM_PER_GPIO1_CLKCTRL_OFFSET); ++ CLKCTRL(am33xx_gpio2_hwmod, AM43XX_CM_PER_GPIO2_CLKCTRL_OFFSET); ++ CLKCTRL(am33xx_gpio3_hwmod, AM43XX_CM_PER_GPIO3_CLKCTRL_OFFSET); ++ CLKCTRL(am33xx_i2c2_hwmod, AM43XX_CM_PER_I2C1_CLKCTRL_OFFSET); ++ CLKCTRL(am33xx_i2c3_hwmod, AM43XX_CM_PER_I2C2_CLKCTRL_OFFSET); ++ CLKCTRL(am33xx_mailbox_hwmod, AM43XX_CM_PER_MAILBOX0_CLKCTRL_OFFSET); ++ CLKCTRL(am33xx_mmc0_hwmod, AM43XX_CM_PER_MMC0_CLKCTRL_OFFSET); ++ CLKCTRL(am33xx_mmc1_hwmod, AM43XX_CM_PER_MMC1_CLKCTRL_OFFSET); ++ CLKCTRL(am33xx_spi0_hwmod, AM43XX_CM_PER_SPI0_CLKCTRL_OFFSET); ++ CLKCTRL(am33xx_spi1_hwmod, AM43XX_CM_PER_SPI1_CLKCTRL_OFFSET); ++ CLKCTRL(am33xx_spinlock_hwmod, AM43XX_CM_PER_SPINLOCK_CLKCTRL_OFFSET); ++ CLKCTRL(am33xx_timer2_hwmod, AM43XX_CM_PER_TIMER2_CLKCTRL_OFFSET); ++ CLKCTRL(am33xx_timer3_hwmod, AM43XX_CM_PER_TIMER3_CLKCTRL_OFFSET); ++ CLKCTRL(am33xx_timer4_hwmod, AM43XX_CM_PER_TIMER4_CLKCTRL_OFFSET); ++ CLKCTRL(am33xx_timer5_hwmod, AM43XX_CM_PER_TIMER5_CLKCTRL_OFFSET); ++ CLKCTRL(am33xx_timer6_hwmod, AM43XX_CM_PER_TIMER6_CLKCTRL_OFFSET); ++ CLKCTRL(am33xx_timer7_hwmod, AM43XX_CM_PER_TIMER7_CLKCTRL_OFFSET); ++ CLKCTRL(am33xx_wkup_m3_hwmod, AM43XX_CM_WKUP_WKUP_M3_CLKCTRL_OFFSET); ++ CLKCTRL(am33xx_control_hwmod, AM43XX_CM_WKUP_CONTROL_CLKCTRL_OFFSET); ++ CLKCTRL(am33xx_smartreflex0_hwmod, ++ AM43XX_CM_WKUP_SMARTREFLEX0_CLKCTRL_OFFSET); ++ CLKCTRL(am33xx_smartreflex1_hwmod, ++ AM43XX_CM_WKUP_SMARTREFLEX1_CLKCTRL_OFFSET); ++ CLKCTRL(am33xx_uart1_hwmod, AM43XX_CM_WKUP_UART0_CLKCTRL_OFFSET); ++ CLKCTRL(am33xx_timer1_hwmod, AM43XX_CM_WKUP_TIMER1_CLKCTRL_OFFSET); ++ CLKCTRL(am33xx_i2c1_hwmod, AM43XX_CM_WKUP_I2C0_CLKCTRL_OFFSET); ++ CLKCTRL(am33xx_gpio0_hwmod, AM43XX_CM_WKUP_GPIO0_CLKCTRL_OFFSET); ++ CLKCTRL(am33xx_adc_tsc_hwmod, AM43XX_CM_WKUP_ADC_TSC_CLKCTRL_OFFSET); ++ CLKCTRL(am33xx_wd_timer1_hwmod, AM43XX_CM_WKUP_WDT1_CLKCTRL_OFFSET); ++ CLKCTRL(am33xx_l4_wkup_hwmod, AM43XX_CM_WKUP_L4WKUP_CLKCTRL_OFFSET); ++ CLKCTRL(am33xx_rtc_hwmod, AM43XX_CM_RTC_RTC_CLKCTRL_OFFSET); ++ CLKCTRL(am33xx_mmc2_hwmod, AM43XX_CM_PER_MMC2_CLKCTRL_OFFSET); ++ CLKCTRL(am33xx_gpmc_hwmod, AM43XX_CM_PER_GPMC_CLKCTRL_OFFSET); ++ CLKCTRL(am33xx_mcasp0_hwmod, AM43XX_CM_PER_MCASP0_CLKCTRL_OFFSET); ++ CLKCTRL(am33xx_mcasp1_hwmod, AM43XX_CM_PER_MCASP1_CLKCTRL_OFFSET); ++ CLKCTRL(am33xx_l4_ls_hwmod, AM43XX_CM_PER_L4LS_CLKCTRL_OFFSET); ++ CLKCTRL(am33xx_l3_main_hwmod, AM43XX_CM_PER_L3_CLKCTRL_OFFSET); ++ CLKCTRL(am33xx_tpcc_hwmod, AM43XX_CM_PER_TPCC_CLKCTRL_OFFSET); ++ CLKCTRL(am33xx_tptc0_hwmod, AM43XX_CM_PER_TPTC0_CLKCTRL_OFFSET); ++ CLKCTRL(am33xx_tptc1_hwmod, AM43XX_CM_PER_TPTC1_CLKCTRL_OFFSET); ++ CLKCTRL(am33xx_tptc2_hwmod, AM43XX_CM_PER_TPTC2_CLKCTRL_OFFSET); ++ CLKCTRL(am33xx_cpgmac0_hwmod, AM43XX_CM_PER_CPGMAC0_CLKCTRL_OFFSET); ++ CLKCTRL(am33xx_pruss_hwmod, AM43XX_CM_PER_PRUSS_CLKCTRL_OFFSET); ++ CLKCTRL(am33xx_gfx_hwmod, AM43XX_CM_GFX_GFX_CLKCTRL_OFFSET); ++ CLKCTRL(am33xx_l4_hs_hwmod, AM43XX_CM_PER_L4HS_CLKCTRL_OFFSET); ++ CLKCTRL(am33xx_mpu_hwmod , AM43XX_CM_MPU_MPU_CLKCTRL_OFFSET); ++ CLKCTRL(am33xx_l3_instr_hwmod , AM43XX_CM_PER_L3_INSTR_CLKCTRL_OFFSET); ++ CLKCTRL(am33xx_ocmcram_hwmod , AM43XX_CM_PER_OCMCRAM_CLKCTRL_OFFSET); ++ CLKCTRL(am33xx_sha0_hwmod , AM43XX_CM_PER_SHA0_CLKCTRL_OFFSET); ++ CLKCTRL(am33xx_aes0_hwmod , AM43XX_CM_PER_AES0_CLKCTRL_OFFSET); ++ CLKCTRL(am33xx_rng_hwmod , AM43XX_CM_PER_RNG_CLKCTRL_OFFSET); ++} ++ ++static void am33xx_hwmod_clkctrl(void) ++{ ++ CLKCTRL(am33xx_uart2_hwmod, AM33XX_CM_PER_UART1_CLKCTRL_OFFSET); ++ CLKCTRL(am33xx_uart3_hwmod, AM33XX_CM_PER_UART2_CLKCTRL_OFFSET); ++ CLKCTRL(am33xx_uart4_hwmod, AM33XX_CM_PER_UART3_CLKCTRL_OFFSET); ++ CLKCTRL(am33xx_uart5_hwmod, AM33XX_CM_PER_UART4_CLKCTRL_OFFSET); ++ CLKCTRL(am33xx_uart6_hwmod, AM33XX_CM_PER_UART5_CLKCTRL_OFFSET); ++ CLKCTRL(am33xx_dcan0_hwmod, AM33XX_CM_PER_DCAN0_CLKCTRL_OFFSET); ++ CLKCTRL(am33xx_dcan1_hwmod, AM33XX_CM_PER_DCAN1_CLKCTRL_OFFSET); ++ CLKCTRL(am33xx_elm_hwmod, AM33XX_CM_PER_ELM_CLKCTRL_OFFSET); ++ CLKCTRL(am33xx_epwmss0_hwmod, AM33XX_CM_PER_EPWMSS0_CLKCTRL_OFFSET); ++ CLKCTRL(am33xx_epwmss1_hwmod, AM33XX_CM_PER_EPWMSS1_CLKCTRL_OFFSET); ++ CLKCTRL(am33xx_epwmss2_hwmod, AM33XX_CM_PER_EPWMSS2_CLKCTRL_OFFSET); ++ CLKCTRL(am33xx_gpio1_hwmod, AM33XX_CM_PER_GPIO1_CLKCTRL_OFFSET); ++ CLKCTRL(am33xx_gpio2_hwmod, AM33XX_CM_PER_GPIO2_CLKCTRL_OFFSET); ++ CLKCTRL(am33xx_gpio3_hwmod, AM33XX_CM_PER_GPIO3_CLKCTRL_OFFSET); ++ CLKCTRL(am33xx_i2c2_hwmod, AM33XX_CM_PER_I2C1_CLKCTRL_OFFSET); ++ CLKCTRL(am33xx_i2c3_hwmod, AM33XX_CM_PER_I2C2_CLKCTRL_OFFSET); ++ CLKCTRL(am33xx_mailbox_hwmod, AM33XX_CM_PER_MAILBOX0_CLKCTRL_OFFSET); ++ CLKCTRL(am33xx_mcasp0_hwmod, AM33XX_CM_PER_MCASP0_CLKCTRL_OFFSET); ++ CLKCTRL(am33xx_mcasp1_hwmod, AM33XX_CM_PER_MCASP1_CLKCTRL_OFFSET); ++ CLKCTRL(am33xx_mmc0_hwmod, AM33XX_CM_PER_MMC0_CLKCTRL_OFFSET); ++ CLKCTRL(am33xx_mmc1_hwmod, AM33XX_CM_PER_MMC1_CLKCTRL_OFFSET); ++ CLKCTRL(am33xx_spi0_hwmod, AM33XX_CM_PER_SPI0_CLKCTRL_OFFSET); ++ CLKCTRL(am33xx_spi1_hwmod, AM33XX_CM_PER_SPI1_CLKCTRL_OFFSET); ++ CLKCTRL(am33xx_spinlock_hwmod, AM33XX_CM_PER_SPINLOCK_CLKCTRL_OFFSET); ++ CLKCTRL(am33xx_timer2_hwmod, AM33XX_CM_PER_TIMER2_CLKCTRL_OFFSET); ++ CLKCTRL(am33xx_timer3_hwmod, AM33XX_CM_PER_TIMER3_CLKCTRL_OFFSET); ++ CLKCTRL(am33xx_timer4_hwmod, AM33XX_CM_PER_TIMER4_CLKCTRL_OFFSET); ++ CLKCTRL(am33xx_timer5_hwmod, AM33XX_CM_PER_TIMER5_CLKCTRL_OFFSET); ++ CLKCTRL(am33xx_timer6_hwmod, AM33XX_CM_PER_TIMER6_CLKCTRL_OFFSET); ++ CLKCTRL(am33xx_timer7_hwmod, AM33XX_CM_PER_TIMER7_CLKCTRL_OFFSET); ++ CLKCTRL(am33xx_wkup_m3_hwmod, AM33XX_CM_WKUP_WKUP_M3_CLKCTRL_OFFSET); ++ CLKCTRL(am33xx_control_hwmod, AM33XX_CM_WKUP_CONTROL_CLKCTRL_OFFSET); ++ CLKCTRL(am33xx_smartreflex0_hwmod, ++ AM33XX_CM_WKUP_SMARTREFLEX0_CLKCTRL_OFFSET); ++ CLKCTRL(am33xx_smartreflex1_hwmod, ++ AM33XX_CM_WKUP_SMARTREFLEX1_CLKCTRL_OFFSET); ++ CLKCTRL(am33xx_uart1_hwmod, AM33XX_CM_WKUP_UART0_CLKCTRL_OFFSET); ++ CLKCTRL(am33xx_timer1_hwmod, AM33XX_CM_WKUP_TIMER1_CLKCTRL_OFFSET); ++ CLKCTRL(am33xx_i2c1_hwmod, AM33XX_CM_WKUP_I2C0_CLKCTRL_OFFSET); ++ CLKCTRL(am33xx_gpio0_hwmod, AM33XX_CM_WKUP_GPIO0_CLKCTRL_OFFSET); ++ CLKCTRL(am33xx_adc_tsc_hwmod, AM33XX_CM_WKUP_ADC_TSC_CLKCTRL_OFFSET); ++ CLKCTRL(am33xx_wd_timer1_hwmod, AM33XX_CM_WKUP_WDT1_CLKCTRL_OFFSET); ++ CLKCTRL(am33xx_rtc_hwmod, AM33XX_CM_RTC_RTC_CLKCTRL_OFFSET); ++ CLKCTRL(am33xx_mmc2_hwmod, AM33XX_CM_PER_MMC2_CLKCTRL_OFFSET); ++ CLKCTRL(am33xx_gpmc_hwmod, AM33XX_CM_PER_GPMC_CLKCTRL_OFFSET); ++ CLKCTRL(am33xx_l4_ls_hwmod, AM33XX_CM_PER_L4LS_CLKCTRL_OFFSET); ++ CLKCTRL(am33xx_l4_wkup_hwmod, AM33XX_CM_WKUP_L4WKUP_CLKCTRL_OFFSET); ++ CLKCTRL(am33xx_l3_main_hwmod, AM33XX_CM_PER_L3_CLKCTRL_OFFSET); ++ CLKCTRL(am33xx_tpcc_hwmod, AM33XX_CM_PER_TPCC_CLKCTRL_OFFSET); ++ CLKCTRL(am33xx_tptc0_hwmod, AM33XX_CM_PER_TPTC0_CLKCTRL_OFFSET); ++ CLKCTRL(am33xx_tptc1_hwmod, AM33XX_CM_PER_TPTC1_CLKCTRL_OFFSET); ++ CLKCTRL(am33xx_tptc2_hwmod, AM33XX_CM_PER_TPTC2_CLKCTRL_OFFSET); ++ CLKCTRL(am33xx_gfx_hwmod, AM33XX_CM_GFX_GFX_CLKCTRL_OFFSET); ++ CLKCTRL(am33xx_l4_hs_hwmod, AM33XX_CM_PER_L4HS_CLKCTRL_OFFSET); ++ CLKCTRL(am33xx_cpgmac0_hwmod, AM33XX_CM_PER_CPGMAC0_CLKCTRL_OFFSET); ++ CLKCTRL(am33xx_pruss_hwmod, AM33XX_CM_PER_PRUSS_CLKCTRL_OFFSET); ++ CLKCTRL(am33xx_mpu_hwmod , AM33XX_CM_MPU_MPU_CLKCTRL_OFFSET); ++ CLKCTRL(am33xx_l3_instr_hwmod , AM33XX_CM_PER_L3_INSTR_CLKCTRL_OFFSET); ++ CLKCTRL(am33xx_ocmcram_hwmod , AM33XX_CM_PER_OCMCRAM_CLKCTRL_OFFSET); ++ CLKCTRL(am33xx_sha0_hwmod , AM33XX_CM_PER_SHA0_CLKCTRL_OFFSET); ++ CLKCTRL(am33xx_aes0_hwmod , AM33XX_CM_PER_AES0_CLKCTRL_OFFSET); ++ CLKCTRL(am33xx_rng_hwmod, AM33XX_CM_PER_RNG_CLKCTRL_OFFSET); ++} ++ ++#define RSTCTRL(oh, rstctrl) ((oh).prcm.omap4.rstctrl_offs = (rstctrl)) ++ ++static void am43xx_hwmod_rstctrl(void) ++{ ++ RSTCTRL(am33xx_pruss_hwmod, AM43XX_RM_PER_RSTCTRL_OFFSET); ++ RSTCTRL(am33xx_gfx_hwmod, AM43XX_RM_GFX_RSTCTRL_OFFSET); ++ RSTCTRL(am33xx_wkup_m3_hwmod, AM43XX_RM_WKUP_RSTCTRL_OFFSET); ++} ++ ++static void am33xx_hwmod_rstctrl(void) ++{ ++ RSTCTRL(am33xx_pruss_hwmod, AM33XX_RM_PER_RSTCTRL_OFFSET); ++ RSTCTRL(am33xx_gfx_hwmod, AM33XX_RM_GFX_RSTCTRL_OFFSET); ++ RSTCTRL(am33xx_wkup_m3_hwmod, AM33XX_RM_WKUP_RSTCTRL_OFFSET); ++} ++ ++#define RSTST(oh, rstst) ((oh).prcm.omap4.rstst_offs = (rstst)) ++ ++static void am43xx_hwmod_rstst(void) ++{ ++ RSTST(am33xx_gfx_hwmod, AM43XX_RM_GFX_RSTST_OFFSET); ++ RSTST(am33xx_wkup_m3_hwmod, AM43XX_RM_WKUP_RSTST_OFFSET); ++} ++ ++static void am33xx_hwmod_rstst(void) ++{ ++ RSTST(am33xx_gfx_hwmod, AM33XX_RM_GFX_RSTST_OFFSET); ++ RSTST(am33xx_wkup_m3_hwmod, AM33XX_RM_WKUP_RSTST_OFFSET); ++} ++ ++static void am43xx_hwmod_clockdomain(void) ++{ ++ am33xx_l4_hs_hwmod.clkdm_name = "l3_clkdm"; ++ am33xx_adc_tsc_hwmod.clkdm_name = "l3s_tsc_clkdm"; ++} ++ ++static void am33xx_hwmod_clockdomain(void) ++{ ++ am33xx_l4_hs_hwmod.clkdm_name = "l4hs_clkdm"; ++ am33xx_adc_tsc_hwmod.clkdm_name = "l4_wkup_clkdm"; ++} ++ ++#define AM43XX_L4_WKUP_OCPIF_CLK "sys_clkin_ck" ++ ++static void am43xx_hwmod_ocpif_clk(void) ++{ ++ am33xx_l4_wkup__wkup_m3.clk = AM43XX_L4_WKUP_OCPIF_CLK; ++ am33xx_l4_wkup__control.clk = AM43XX_L4_WKUP_OCPIF_CLK; ++ am33xx_l4_wkup__smartreflex0.clk = AM43XX_L4_WKUP_OCPIF_CLK; ++ am33xx_l4_wkup__smartreflex1.clk = AM43XX_L4_WKUP_OCPIF_CLK; ++ am33xx_l4_wkup__uart1.clk = AM43XX_L4_WKUP_OCPIF_CLK; ++ am33xx_l4_wkup__timer1.clk = AM43XX_L4_WKUP_OCPIF_CLK; ++ am33xx_l4_wkup__i2c1.clk = AM43XX_L4_WKUP_OCPIF_CLK; ++ am33xx_l4_wkup__gpio0.clk = AM43XX_L4_WKUP_OCPIF_CLK; ++ am33xx_l4_wkup__wd_timer1.clk = AM43XX_L4_WKUP_OCPIF_CLK; ++ am33xx_wkup_m3__l4_wkup.clk = AM43XX_L4_WKUP_OCPIF_CLK; ++ am33xx_control_hwmod.main_clk = AM43XX_L4_WKUP_OCPIF_CLK; ++} ++ ++#define AM33XX_L4_WKUP_OCPIF_CLK "dpll_core_m4_div2_ck" ++ ++static void am33xx_hwmod_ocpif_clk(void) ++{ ++ am33xx_l4_wkup__wkup_m3.clk = AM33XX_L4_WKUP_OCPIF_CLK; ++ am33xx_l4_wkup__control.clk = AM33XX_L4_WKUP_OCPIF_CLK; ++ am33xx_l4_wkup__smartreflex0.clk = AM33XX_L4_WKUP_OCPIF_CLK; ++ am33xx_l4_wkup__smartreflex1.clk = AM33XX_L4_WKUP_OCPIF_CLK; ++ am33xx_l4_wkup__uart1.clk = AM33XX_L4_WKUP_OCPIF_CLK; ++ am33xx_l4_wkup__timer1.clk = AM33XX_L4_WKUP_OCPIF_CLK; ++ am33xx_l4_wkup__i2c1.clk = AM33XX_L4_WKUP_OCPIF_CLK; ++ am33xx_l4_wkup__gpio0.clk = AM33XX_L4_WKUP_OCPIF_CLK; ++ am33xx_l4_wkup__wd_timer1.clk = AM33XX_L4_WKUP_OCPIF_CLK; ++ am33xx_wkup_m3__l4_wkup.clk = AM33XX_L4_WKUP_OCPIF_CLK; ++ am33xx_control_hwmod.main_clk = AM33XX_L4_WKUP_OCPIF_CLK; ++} ++ ++static struct omap_hwmod_ocp_if *am43xx_hwmod_ocp_ifs[] __initdata = { ++ &am33xx_l4_wkup__synctimer, ++ &am43xx_l4_ls__timer8, ++ &am43xx_l4_ls__timer9, ++ &am43xx_l4_ls__timer10, ++ &am43xx_l4_ls__timer11, ++ &am43xx_l4_ls__epwmss3, ++ &am43xx_epwmss3__ehrpwm3, ++ &am43xx_l4_ls__epwmss4, ++ &am43xx_epwmss4__ehrpwm4, ++ &am43xx_l4_ls__epwmss5, ++ &am43xx_epwmss5__ehrpwm5, ++ &am43xx_l4_ls__mcspi2, ++ &am43xx_l4_ls__mcspi3, ++ &am43xx_l4_ls__mcspi4, ++ &am43xx_l4_ls__gpio4, ++ &am43xx_l4_ls__gpio5, ++ &am43xx_l3_main__pruss, ++ &am43xx_l3_main__des, ++ &am43xx_l3_s__qspi, ++ &am43xx_l3_s__usbotgss0, ++ &am43xx_l3_s__usbotgss1, ++ &am33xx_l4_ls__ocp2scp0, ++ &am33xx_l4_ls__ocp2scp1, ++ &am43xx_dss__l3_main, ++ &am43xx_l4_ls__dss, ++ &am43xx_l4_ls__dss_dispc, ++ &am43xx_l4_ls__dss_rfbi, ++ NULL, ++}; ++ + static struct omap_hwmod_ocp_if *am33xx_hwmod_ocp_ifs[] __initdata = { + &am33xx_l3_main__emif, ++ &am33xx_l3_main__debugss, ++ &am33xx_l4_hs__pruss, ++ &am33xx_l3_main__lcdc, ++ &am33xx_l3_s__usbss, ++ &am33xx_l4_wkup__rtc, ++ NULL, ++}; ++ ++static struct omap_hwmod_ocp_if *amx3xx_hwmod_ocp_ifs[] __initdata = { + &am33xx_mpu__l3_main, + &am33xx_mpu__prcm, + &am33xx_l3_s__l4_ls, +@@ -2494,19 +3236,16 @@ static struct omap_hwmod_ocp_if *am33xx_ + &am33xx_pruss__l3_main, + &am33xx_wkup_m3__l4_wkup, + &am33xx_gfx__l3_main, +- &am33xx_l3_main__debugss, + &am33xx_l4_wkup__wkup_m3, + &am33xx_l4_wkup__control, + &am33xx_l4_wkup__smartreflex0, + &am33xx_l4_wkup__smartreflex1, + &am33xx_l4_wkup__uart1, + &am33xx_l4_wkup__timer1, +- &am33xx_l4_wkup__rtc, + &am33xx_l4_wkup__i2c1, + &am33xx_l4_wkup__gpio0, + &am33xx_l4_wkup__adc_tsc, + &am33xx_l4_wkup__wd_timer1, +- &am33xx_l4_hs__pruss, + &am33xx_l4_per__dcan0, + &am33xx_l4_per__dcan1, + &am33xx_l4_per__gpio1, +@@ -2547,23 +3286,46 @@ static struct omap_hwmod_ocp_if *am33xx_ + &am33xx_epwmss2__eqep2, + &am33xx_epwmss2__ehrpwm2, + &am33xx_l3_s__gpmc, +- &am33xx_l3_main__lcdc, + &am33xx_l4_ls__mcspi0, + &am33xx_l4_ls__mcspi1, + &am33xx_l3_main__tptc0, + &am33xx_l3_main__tptc1, + &am33xx_l3_main__tptc2, + &am33xx_l3_main__ocmc, +- &am33xx_l3_s__usbss, + &am33xx_l4_hs__cpgmac0, + &am33xx_cpgmac0__mdio, + &am33xx_l3_main__sha0, + &am33xx_l3_main__aes0, ++ &am33xx_l4_per__rng, + NULL, + }; + + int __init am33xx_hwmod_init(void) + { ++ int ret; ++ + omap_hwmod_init(); +- return omap_hwmod_register_links(am33xx_hwmod_ocp_ifs); ++ ++ if (soc_is_am33xx()) { ++ am33xx_hwmod_clkctrl(); ++ am33xx_hwmod_rstctrl(); ++ am33xx_hwmod_rstst(); ++ am33xx_hwmod_clockdomain(); ++ am33xx_hwmod_ocpif_clk(); ++ } else { ++ am43xx_hwmod_clkctrl(); ++ am43xx_hwmod_rstctrl(); ++ am43xx_hwmod_rstst(); ++ am43xx_hwmod_clockdomain(); ++ am43xx_hwmod_ocpif_clk(); ++ } ++ ++ ret = omap_hwmod_register_links(amx3xx_hwmod_ocp_ifs); ++ if (ret < 0) ++ return ret; ++ ++ if (soc_is_am33xx()) ++ return omap_hwmod_register_links(am33xx_hwmod_ocp_ifs); ++ else ++ return omap_hwmod_register_links(am43xx_hwmod_ocp_ifs); + } +--- a/arch/arm/mach-omap2/omap_hwmod_3xxx_data.c ++++ b/arch/arm/mach-omap2/omap_hwmod_3xxx_data.c +@@ -200,7 +200,6 @@ static struct omap_timer_capability_dev_ + static struct omap_hwmod omap3xxx_timer1_hwmod = { + .name = "timer1", + .mpu_irqs = omap2_timer1_mpu_irqs, +- .main_clk = "gpt1_fck", + .prcm = { + .omap2 = { + .prcm_reg_id = 1, +@@ -219,7 +218,6 @@ static struct omap_hwmod omap3xxx_timer1 + static struct omap_hwmod omap3xxx_timer2_hwmod = { + .name = "timer2", + .mpu_irqs = omap2_timer2_mpu_irqs, +- .main_clk = "gpt2_fck", + .prcm = { + .omap2 = { + .prcm_reg_id = 1, +@@ -237,7 +235,6 @@ static struct omap_hwmod omap3xxx_timer2 + static struct omap_hwmod omap3xxx_timer3_hwmod = { + .name = "timer3", + .mpu_irqs = omap2_timer3_mpu_irqs, +- .main_clk = "gpt3_fck", + .prcm = { + .omap2 = { + .prcm_reg_id = 1, +@@ -255,7 +252,6 @@ static struct omap_hwmod omap3xxx_timer3 + static struct omap_hwmod omap3xxx_timer4_hwmod = { + .name = "timer4", + .mpu_irqs = omap2_timer4_mpu_irqs, +- .main_clk = "gpt4_fck", + .prcm = { + .omap2 = { + .prcm_reg_id = 1, +@@ -273,7 +269,6 @@ static struct omap_hwmod omap3xxx_timer4 + static struct omap_hwmod omap3xxx_timer5_hwmod = { + .name = "timer5", + .mpu_irqs = omap2_timer5_mpu_irqs, +- .main_clk = "gpt5_fck", + .prcm = { + .omap2 = { + .prcm_reg_id = 1, +@@ -292,7 +287,6 @@ static struct omap_hwmod omap3xxx_timer5 + static struct omap_hwmod omap3xxx_timer6_hwmod = { + .name = "timer6", + .mpu_irqs = omap2_timer6_mpu_irqs, +- .main_clk = "gpt6_fck", + .prcm = { + .omap2 = { + .prcm_reg_id = 1, +@@ -311,7 +305,6 @@ static struct omap_hwmod omap3xxx_timer6 + static struct omap_hwmod omap3xxx_timer7_hwmod = { + .name = "timer7", + .mpu_irqs = omap2_timer7_mpu_irqs, +- .main_clk = "gpt7_fck", + .prcm = { + .omap2 = { + .prcm_reg_id = 1, +@@ -330,7 +323,6 @@ static struct omap_hwmod omap3xxx_timer7 + static struct omap_hwmod omap3xxx_timer8_hwmod = { + .name = "timer8", + .mpu_irqs = omap2_timer8_mpu_irqs, +- .main_clk = "gpt8_fck", + .prcm = { + .omap2 = { + .prcm_reg_id = 1, +@@ -349,7 +341,6 @@ static struct omap_hwmod omap3xxx_timer8 + static struct omap_hwmod omap3xxx_timer9_hwmod = { + .name = "timer9", + .mpu_irqs = omap2_timer9_mpu_irqs, +- .main_clk = "gpt9_fck", + .prcm = { + .omap2 = { + .prcm_reg_id = 1, +@@ -368,7 +359,6 @@ static struct omap_hwmod omap3xxx_timer9 + static struct omap_hwmod omap3xxx_timer10_hwmod = { + .name = "timer10", + .mpu_irqs = omap2_timer10_mpu_irqs, +- .main_clk = "gpt10_fck", + .prcm = { + .omap2 = { + .prcm_reg_id = 1, +@@ -387,7 +377,6 @@ static struct omap_hwmod omap3xxx_timer1 + static struct omap_hwmod omap3xxx_timer11_hwmod = { + .name = "timer11", + .mpu_irqs = omap2_timer11_mpu_irqs, +- .main_clk = "gpt11_fck", + .prcm = { + .omap2 = { + .prcm_reg_id = 1, +@@ -411,7 +400,6 @@ static struct omap_hwmod_irq_info omap3x + static struct omap_hwmod omap3xxx_timer12_hwmod = { + .name = "timer12", + .mpu_irqs = omap3xxx_timer12_mpu_irqs, +- .main_clk = "gpt12_fck", + .prcm = { + .omap2 = { + .prcm_reg_id = 1, +@@ -467,7 +455,6 @@ static struct omap_hwmod_class omap3xxx_ + static struct omap_hwmod omap3xxx_wd_timer2_hwmod = { + .name = "wd_timer2", + .class = &omap3xxx_wd_timer_hwmod_class, +- .main_clk = "wdt2_fck", + .prcm = { + .omap2 = { + .prcm_reg_id = 1, +@@ -489,7 +476,6 @@ static struct omap_hwmod omap3xxx_uart1_ + .name = "uart1", + .mpu_irqs = omap2_uart1_mpu_irqs, + .sdma_reqs = omap2_uart1_sdma_reqs, +- .main_clk = "uart1_fck", + .flags = DEBUG_TI81XXUART1_FLAGS | HWMOD_SWSUP_SIDLE_ACT, + .prcm = { + .omap2 = { +@@ -508,7 +494,6 @@ static struct omap_hwmod omap3xxx_uart2_ + .name = "uart2", + .mpu_irqs = omap2_uart2_mpu_irqs, + .sdma_reqs = omap2_uart2_sdma_reqs, +- .main_clk = "uart2_fck", + .flags = DEBUG_TI81XXUART2_FLAGS | HWMOD_SWSUP_SIDLE_ACT, + .prcm = { + .omap2 = { +@@ -527,7 +512,6 @@ static struct omap_hwmod omap3xxx_uart3_ + .name = "uart3", + .mpu_irqs = omap2_uart3_mpu_irqs, + .sdma_reqs = omap2_uart3_sdma_reqs, +- .main_clk = "uart3_fck", + .flags = DEBUG_OMAP3UART3_FLAGS | DEBUG_TI81XXUART3_FLAGS | + HWMOD_SWSUP_SIDLE_ACT, + .prcm = { +@@ -807,7 +791,6 @@ static struct omap_hwmod omap3xxx_i2c1_h + .flags = HWMOD_16BIT_REG | HWMOD_SET_DEFAULT_CLOCKACT, + .mpu_irqs = omap2_i2c1_mpu_irqs, + .sdma_reqs = omap2_i2c1_sdma_reqs, +- .main_clk = "i2c1_fck", + .prcm = { + .omap2 = { + .module_offs = CORE_MOD, +@@ -832,7 +815,6 @@ static struct omap_hwmod omap3xxx_i2c2_h + .flags = HWMOD_16BIT_REG | HWMOD_SET_DEFAULT_CLOCKACT, + .mpu_irqs = omap2_i2c2_mpu_irqs, + .sdma_reqs = omap2_i2c2_sdma_reqs, +- .main_clk = "i2c2_fck", + .prcm = { + .omap2 = { + .module_offs = CORE_MOD, +@@ -868,7 +850,6 @@ static struct omap_hwmod omap3xxx_i2c3_h + .flags = HWMOD_16BIT_REG | HWMOD_SET_DEFAULT_CLOCKACT, + .mpu_irqs = i2c3_mpu_irqs, + .sdma_reqs = i2c3_sdma_reqs, +- .main_clk = "i2c3_fck", + .prcm = { + .omap2 = { + .module_offs = CORE_MOD, +@@ -911,17 +892,11 @@ static struct omap_gpio_dev_attr gpio_de + }; + + /* gpio1 */ +-static struct omap_hwmod_opt_clk gpio1_opt_clks[] = { +- { .role = "dbclk", .clk = "gpio1_dbck", }, +-}; + + static struct omap_hwmod omap3xxx_gpio1_hwmod = { + .name = "gpio1", + .flags = HWMOD_CONTROL_OPT_CLKS_IN_RESET, + .mpu_irqs = omap2_gpio1_irqs, +- .main_clk = "gpio1_ick", +- .opt_clks = gpio1_opt_clks, +- .opt_clks_cnt = ARRAY_SIZE(gpio1_opt_clks), + .prcm = { + .omap2 = { + .prcm_reg_id = 1, +@@ -936,17 +911,11 @@ static struct omap_hwmod omap3xxx_gpio1_ + }; + + /* gpio2 */ +-static struct omap_hwmod_opt_clk gpio2_opt_clks[] = { +- { .role = "dbclk", .clk = "gpio2_dbck", }, +-}; + + static struct omap_hwmod omap3xxx_gpio2_hwmod = { + .name = "gpio2", + .flags = HWMOD_CONTROL_OPT_CLKS_IN_RESET, + .mpu_irqs = omap2_gpio2_irqs, +- .main_clk = "gpio2_ick", +- .opt_clks = gpio2_opt_clks, +- .opt_clks_cnt = ARRAY_SIZE(gpio2_opt_clks), + .prcm = { + .omap2 = { + .prcm_reg_id = 1, +@@ -961,17 +930,11 @@ static struct omap_hwmod omap3xxx_gpio2_ + }; + + /* gpio3 */ +-static struct omap_hwmod_opt_clk gpio3_opt_clks[] = { +- { .role = "dbclk", .clk = "gpio3_dbck", }, +-}; + + static struct omap_hwmod omap3xxx_gpio3_hwmod = { + .name = "gpio3", + .flags = HWMOD_CONTROL_OPT_CLKS_IN_RESET, + .mpu_irqs = omap2_gpio3_irqs, +- .main_clk = "gpio3_ick", +- .opt_clks = gpio3_opt_clks, +- .opt_clks_cnt = ARRAY_SIZE(gpio3_opt_clks), + .prcm = { + .omap2 = { + .prcm_reg_id = 1, +@@ -986,17 +949,11 @@ static struct omap_hwmod omap3xxx_gpio3_ + }; + + /* gpio4 */ +-static struct omap_hwmod_opt_clk gpio4_opt_clks[] = { +- { .role = "dbclk", .clk = "gpio4_dbck", }, +-}; + + static struct omap_hwmod omap3xxx_gpio4_hwmod = { + .name = "gpio4", + .flags = HWMOD_CONTROL_OPT_CLKS_IN_RESET, + .mpu_irqs = omap2_gpio4_irqs, +- .main_clk = "gpio4_ick", +- .opt_clks = gpio4_opt_clks, +- .opt_clks_cnt = ARRAY_SIZE(gpio4_opt_clks), + .prcm = { + .omap2 = { + .prcm_reg_id = 1, +@@ -1016,17 +973,11 @@ static struct omap_hwmod_irq_info omap3x + { .irq = -1 }, + }; + +-static struct omap_hwmod_opt_clk gpio5_opt_clks[] = { +- { .role = "dbclk", .clk = "gpio5_dbck", }, +-}; + + static struct omap_hwmod omap3xxx_gpio5_hwmod = { + .name = "gpio5", + .flags = HWMOD_CONTROL_OPT_CLKS_IN_RESET, + .mpu_irqs = omap3xxx_gpio5_irqs, +- .main_clk = "gpio5_ick", +- .opt_clks = gpio5_opt_clks, +- .opt_clks_cnt = ARRAY_SIZE(gpio5_opt_clks), + .prcm = { + .omap2 = { + .prcm_reg_id = 1, +@@ -1046,17 +997,11 @@ static struct omap_hwmod_irq_info omap3x + { .irq = -1 }, + }; + +-static struct omap_hwmod_opt_clk gpio6_opt_clks[] = { +- { .role = "dbclk", .clk = "gpio6_dbck", }, +-}; + + static struct omap_hwmod omap3xxx_gpio6_hwmod = { + .name = "gpio6", + .flags = HWMOD_CONTROL_OPT_CLKS_IN_RESET, + .mpu_irqs = omap3xxx_gpio6_irqs, +- .main_clk = "gpio6_ick", +- .opt_clks = gpio6_opt_clks, +- .opt_clks_cnt = ARRAY_SIZE(gpio6_opt_clks), + .prcm = { + .omap2 = { + .prcm_reg_id = 1, +@@ -1100,7 +1045,6 @@ static struct omap_hwmod omap3xxx_dma_sy + .name = "dma", + .class = &omap3xxx_dma_hwmod_class, + .mpu_irqs = omap2_dma_system_irqs, +- .main_clk = "core_l3_ick", + .prcm = { + .omap2 = { + .module_offs = CORE_MOD, +@@ -1135,15 +1079,7 @@ static struct omap_hwmod_class omap3xxx_ + }; + + /* McBSP functional clock mapping */ +-static struct omap_hwmod_opt_clk mcbsp15_opt_clks[] = { +- { .role = "pad_fck", .clk = "mcbsp_clks" }, +- { .role = "prcm_fck", .clk = "core_96m_fck" }, +-}; + +-static struct omap_hwmod_opt_clk mcbsp234_opt_clks[] = { +- { .role = "pad_fck", .clk = "mcbsp_clks" }, +- { .role = "prcm_fck", .clk = "per_96m_fck" }, +-}; + + /* mcbsp1 */ + static struct omap_hwmod_irq_info omap3xxx_mcbsp1_irqs[] = { +@@ -1158,7 +1094,6 @@ static struct omap_hwmod omap3xxx_mcbsp1 + .class = &omap3xxx_mcbsp_hwmod_class, + .mpu_irqs = omap3xxx_mcbsp1_irqs, + .sdma_reqs = omap2_mcbsp1_sdma_reqs, +- .main_clk = "mcbsp1_fck", + .prcm = { + .omap2 = { + .prcm_reg_id = 1, +@@ -1168,8 +1103,6 @@ static struct omap_hwmod omap3xxx_mcbsp1 + .idlest_idle_bit = OMAP3430_ST_MCBSP1_SHIFT, + }, + }, +- .opt_clks = mcbsp15_opt_clks, +- .opt_clks_cnt = ARRAY_SIZE(mcbsp15_opt_clks), + }; + + /* mcbsp2 */ +@@ -1189,7 +1122,6 @@ static struct omap_hwmod omap3xxx_mcbsp2 + .class = &omap3xxx_mcbsp_hwmod_class, + .mpu_irqs = omap3xxx_mcbsp2_irqs, + .sdma_reqs = omap2_mcbsp2_sdma_reqs, +- .main_clk = "mcbsp2_fck", + .prcm = { + .omap2 = { + .prcm_reg_id = 1, +@@ -1199,8 +1131,6 @@ static struct omap_hwmod omap3xxx_mcbsp2 + .idlest_idle_bit = OMAP3430_ST_MCBSP2_SHIFT, + }, + }, +- .opt_clks = mcbsp234_opt_clks, +- .opt_clks_cnt = ARRAY_SIZE(mcbsp234_opt_clks), + .dev_attr = &omap34xx_mcbsp2_dev_attr, + }; + +@@ -1221,7 +1151,6 @@ static struct omap_hwmod omap3xxx_mcbsp3 + .class = &omap3xxx_mcbsp_hwmod_class, + .mpu_irqs = omap3xxx_mcbsp3_irqs, + .sdma_reqs = omap2_mcbsp3_sdma_reqs, +- .main_clk = "mcbsp3_fck", + .prcm = { + .omap2 = { + .prcm_reg_id = 1, +@@ -1231,8 +1160,6 @@ static struct omap_hwmod omap3xxx_mcbsp3 + .idlest_idle_bit = OMAP3430_ST_MCBSP3_SHIFT, + }, + }, +- .opt_clks = mcbsp234_opt_clks, +- .opt_clks_cnt = ARRAY_SIZE(mcbsp234_opt_clks), + .dev_attr = &omap34xx_mcbsp3_dev_attr, + }; + +@@ -1255,7 +1182,6 @@ static struct omap_hwmod omap3xxx_mcbsp4 + .class = &omap3xxx_mcbsp_hwmod_class, + .mpu_irqs = omap3xxx_mcbsp4_irqs, + .sdma_reqs = omap3xxx_mcbsp4_sdma_chs, +- .main_clk = "mcbsp4_fck", + .prcm = { + .omap2 = { + .prcm_reg_id = 1, +@@ -1265,8 +1191,6 @@ static struct omap_hwmod omap3xxx_mcbsp4 + .idlest_idle_bit = OMAP3430_ST_MCBSP4_SHIFT, + }, + }, +- .opt_clks = mcbsp234_opt_clks, +- .opt_clks_cnt = ARRAY_SIZE(mcbsp234_opt_clks), + }; + + /* mcbsp5 */ +@@ -1288,7 +1212,6 @@ static struct omap_hwmod omap3xxx_mcbsp5 + .class = &omap3xxx_mcbsp_hwmod_class, + .mpu_irqs = omap3xxx_mcbsp5_irqs, + .sdma_reqs = omap3xxx_mcbsp5_sdma_chs, +- .main_clk = "mcbsp5_fck", + .prcm = { + .omap2 = { + .prcm_reg_id = 1, +@@ -1298,8 +1221,6 @@ static struct omap_hwmod omap3xxx_mcbsp5 + .idlest_idle_bit = OMAP3430_ST_MCBSP5_SHIFT, + }, + }, +- .opt_clks = mcbsp15_opt_clks, +- .opt_clks_cnt = ARRAY_SIZE(mcbsp15_opt_clks), + }; + + /* 'mcbsp sidetone' class */ +@@ -1324,7 +1245,6 @@ static struct omap_hwmod omap3xxx_mcbsp2 + .name = "mcbsp2_sidetone", + .class = &omap3xxx_mcbsp_sidetone_hwmod_class, + .mpu_irqs = omap3xxx_mcbsp2_sidetone_irqs, +- .main_clk = "mcbsp2_fck", + .prcm = { + .omap2 = { + .prcm_reg_id = 1, +@@ -1346,7 +1266,6 @@ static struct omap_hwmod omap3xxx_mcbsp3 + .name = "mcbsp3_sidetone", + .class = &omap3xxx_mcbsp_sidetone_hwmod_class, + .mpu_irqs = omap3xxx_mcbsp3_sidetone_irqs, +- .main_clk = "mcbsp3_fck", + .prcm = { + .omap2 = { + .prcm_reg_id = 1, +@@ -1571,7 +1490,6 @@ static struct omap_hwmod omap34xx_mcspi1 + .name = "mcspi1", + .mpu_irqs = omap2_mcspi1_mpu_irqs, + .sdma_reqs = omap2_mcspi1_sdma_reqs, +- .main_clk = "mcspi1_fck", + .prcm = { + .omap2 = { + .module_offs = CORE_MOD, +@@ -1594,7 +1512,6 @@ static struct omap_hwmod omap34xx_mcspi2 + .name = "mcspi2", + .mpu_irqs = omap2_mcspi2_mpu_irqs, + .sdma_reqs = omap2_mcspi2_sdma_reqs, +- .main_clk = "mcspi2_fck", + .prcm = { + .omap2 = { + .module_offs = CORE_MOD, +@@ -1630,7 +1547,6 @@ static struct omap_hwmod omap34xx_mcspi3 + .name = "mcspi3", + .mpu_irqs = omap34xx_mcspi3_mpu_irqs, + .sdma_reqs = omap34xx_mcspi3_sdma_reqs, +- .main_clk = "mcspi3_fck", + .prcm = { + .omap2 = { + .module_offs = CORE_MOD, +@@ -1664,7 +1580,6 @@ static struct omap_hwmod omap34xx_mcspi4 + .name = "mcspi4", + .mpu_irqs = omap34xx_mcspi4_mpu_irqs, + .sdma_reqs = omap34xx_mcspi4_sdma_reqs, +- .main_clk = "mcspi4_fck", + .prcm = { + .omap2 = { + .module_offs = CORE_MOD, +@@ -1707,7 +1622,6 @@ static struct omap_hwmod_irq_info omap3x + static struct omap_hwmod omap3xxx_usbhsotg_hwmod = { + .name = "usb_otg_hs", + .mpu_irqs = omap3xxx_usbhsotg_mpu_irqs, +- .main_clk = "hsotgusb_ick", + .prcm = { + .omap2 = { + .prcm_reg_id = 1, +@@ -1782,9 +1696,6 @@ static struct omap_hwmod_dma_info omap34 + { .dma_req = -1 } + }; + +-static struct omap_hwmod_opt_clk omap34xx_mmc1_opt_clks[] = { +- { .role = "dbck", .clk = "omap_32k_fck", }, +-}; + + static struct omap_mmc_dev_attr mmc1_dev_attr = { + .flags = OMAP_HSMMC_SUPPORTS_DUAL_VOLT, +@@ -1800,9 +1711,6 @@ static struct omap_hwmod omap3xxx_pre_es + .name = "mmc1", + .mpu_irqs = omap34xx_mmc1_mpu_irqs, + .sdma_reqs = omap34xx_mmc1_sdma_reqs, +- .opt_clks = omap34xx_mmc1_opt_clks, +- .opt_clks_cnt = ARRAY_SIZE(omap34xx_mmc1_opt_clks), +- .main_clk = "mmchs1_fck", + .prcm = { + .omap2 = { + .module_offs = CORE_MOD, +@@ -1820,9 +1728,6 @@ static struct omap_hwmod omap3xxx_es3plu + .name = "mmc1", + .mpu_irqs = omap34xx_mmc1_mpu_irqs, + .sdma_reqs = omap34xx_mmc1_sdma_reqs, +- .opt_clks = omap34xx_mmc1_opt_clks, +- .opt_clks_cnt = ARRAY_SIZE(omap34xx_mmc1_opt_clks), +- .main_clk = "mmchs1_fck", + .prcm = { + .omap2 = { + .module_offs = CORE_MOD, +@@ -1849,9 +1754,6 @@ static struct omap_hwmod_dma_info omap34 + { .dma_req = -1 } + }; + +-static struct omap_hwmod_opt_clk omap34xx_mmc2_opt_clks[] = { +- { .role = "dbck", .clk = "omap_32k_fck", }, +-}; + + /* See 35xx errata 2.1.1.128 in SPRZ278F */ + static struct omap_mmc_dev_attr mmc2_pre_es3_dev_attr = { +@@ -1862,9 +1764,6 @@ static struct omap_hwmod omap3xxx_pre_es + .name = "mmc2", + .mpu_irqs = omap34xx_mmc2_mpu_irqs, + .sdma_reqs = omap34xx_mmc2_sdma_reqs, +- .opt_clks = omap34xx_mmc2_opt_clks, +- .opt_clks_cnt = ARRAY_SIZE(omap34xx_mmc2_opt_clks), +- .main_clk = "mmchs2_fck", + .prcm = { + .omap2 = { + .module_offs = CORE_MOD, +@@ -1882,9 +1781,6 @@ static struct omap_hwmod omap3xxx_es3plu + .name = "mmc2", + .mpu_irqs = omap34xx_mmc2_mpu_irqs, + .sdma_reqs = omap34xx_mmc2_sdma_reqs, +- .opt_clks = omap34xx_mmc2_opt_clks, +- .opt_clks_cnt = ARRAY_SIZE(omap34xx_mmc2_opt_clks), +- .main_clk = "mmchs2_fck", + .prcm = { + .omap2 = { + .module_offs = CORE_MOD, +@@ -1910,17 +1806,11 @@ static struct omap_hwmod_dma_info omap34 + { .dma_req = -1 } + }; + +-static struct omap_hwmod_opt_clk omap34xx_mmc3_opt_clks[] = { +- { .role = "dbck", .clk = "omap_32k_fck", }, +-}; + + static struct omap_hwmod omap3xxx_mmc3_hwmod = { + .name = "mmc3", + .mpu_irqs = omap34xx_mmc3_mpu_irqs, + .sdma_reqs = omap34xx_mmc3_sdma_reqs, +- .opt_clks = omap34xx_mmc3_opt_clks, +- .opt_clks_cnt = ARRAY_SIZE(omap34xx_mmc3_opt_clks), +- .main_clk = "mmchs3_fck", + .prcm = { + .omap2 = { + .prcm_reg_id = 1, +@@ -1954,9 +1844,6 @@ static struct omap_hwmod_class omap3xxx_ + .sysc = &omap3xxx_usb_host_hs_sysc, + }; + +-static struct omap_hwmod_opt_clk omap3xxx_usb_host_hs_opt_clks[] = { +- { .role = "ehci_logic_fck", .clk = "usbhost_120m_fck", }, +-}; + + static struct omap_hwmod_irq_info omap3xxx_usb_host_hs_irqs[] = { + { .name = "ohci-irq", .irq = 76 + OMAP_INTC_START, }, +@@ -1969,7 +1856,6 @@ static struct omap_hwmod omap3xxx_usb_ho + .class = &omap3xxx_usb_host_hs_hwmod_class, + .clkdm_name = "l3_init_clkdm", + .mpu_irqs = omap3xxx_usb_host_hs_irqs, +- .main_clk = "usbhost_48m_fck", + .prcm = { + .omap2 = { + .module_offs = OMAP3430ES2_USBHOST_MOD, +@@ -1980,8 +1866,6 @@ static struct omap_hwmod omap3xxx_usb_ho + .idlest_stdby_bit = OMAP3430ES2_ST_USBHOST_STDBY_SHIFT, + }, + }, +- .opt_clks = omap3xxx_usb_host_hs_opt_clks, +- .opt_clks_cnt = ARRAY_SIZE(omap3xxx_usb_host_hs_opt_clks), + + /* + * Errata: USBHOST Configured In Smart-Idle Can Lead To a Deadlock +@@ -2062,7 +1946,6 @@ static struct omap_hwmod omap3xxx_usb_tl + .class = &omap3xxx_usb_tll_hs_hwmod_class, + .clkdm_name = "l3_init_clkdm", + .mpu_irqs = omap3xxx_usb_tll_hs_irqs, +- .main_clk = "usbtll_fck", + .prcm = { + .omap2 = { + .module_offs = CORE_MOD, +@@ -2139,7 +2022,6 @@ static struct omap_hwmod omap3xxx_counte + .class = &omap3xxx_counter_hwmod_class, + .clkdm_name = "wkup_clkdm", + .flags = HWMOD_SWSUP_SIDLE, +- .main_clk = "wkup_32k_fck", + .prcm = { + .omap2 = { + .module_offs = WKUP_MOD, +@@ -2181,7 +2063,6 @@ static struct omap_hwmod omap3xxx_gpmc_h + .class = &omap3xxx_gpmc_hwmod_class, + .clkdm_name = "core_l3_clkdm", + .mpu_irqs = omap3xxx_gpmc_irqs, +- .main_clk = "gpmc_fck", + /* + * XXX HWMOD_INIT_NO_RESET should not be needed for this IP + * block. It is not being added due to any known bugs with +--- a/arch/arm/mach-omap2/omap_hwmod_44xx_data.c ++++ b/arch/arm/mach-omap2/omap_hwmod_44xx_data.c +@@ -334,7 +334,6 @@ static struct omap_hwmod omap44xx_counte + .class = &omap44xx_counter_hwmod_class, + .clkdm_name = "l4_wkup_clkdm", + .flags = HWMOD_SWSUP_SIDLE, +- .main_clk = "sys_32k_ck", + .prcm = { + .omap4 = { + .clkctrl_offs = OMAP4_CM_WKUP_SYNCTIMER_CLKCTRL_OFFSET, +@@ -479,7 +478,6 @@ static struct omap_hwmod omap44xx_dma_sy + .class = &omap44xx_dma_hwmod_class, + .clkdm_name = "l3_dma_clkdm", + .mpu_irqs = omap44xx_dma_system_irqs, +- .main_clk = "l3_div_ck", + .prcm = { + .omap4 = { + .clkctrl_offs = OMAP4_CM_SDMA_SDMA_CLKCTRL_OFFSET, +@@ -514,7 +512,6 @@ static struct omap_hwmod omap44xx_dmic_h + .name = "dmic", + .class = &omap44xx_dmic_hwmod_class, + .clkdm_name = "abe_clkdm", +- .main_clk = "func_dmic_abe_gfclk", + .prcm = { + .omap4 = { + .clkctrl_offs = OMAP4_CM1_ABE_DMIC_CLKCTRL_OFFSET, +@@ -914,8 +911,6 @@ static struct omap_hwmod omap44xx_emif1_ + .name = "emif1", + .class = &omap44xx_emif_hwmod_class, + .clkdm_name = "l3_emif_clkdm", +- .flags = HWMOD_INIT_NO_IDLE | HWMOD_INIT_NO_RESET, +- .main_clk = "ddrphy_ck", + .prcm = { + .omap4 = { + .clkctrl_offs = OMAP4_CM_MEMIF_EMIF_1_CLKCTRL_OFFSET, +@@ -930,8 +925,6 @@ static struct omap_hwmod omap44xx_emif2_ + .name = "emif2", + .class = &omap44xx_emif_hwmod_class, + .clkdm_name = "l3_emif_clkdm", +- .flags = HWMOD_INIT_NO_IDLE | HWMOD_INIT_NO_RESET, +- .main_clk = "ddrphy_ck", + .prcm = { + .omap4 = { + .clkctrl_offs = OMAP4_CM_MEMIF_EMIF_2_CLKCTRL_OFFSET, +@@ -1015,15 +1008,11 @@ static struct omap_gpio_dev_attr gpio_de + }; + + /* gpio1 */ +-static struct omap_hwmod_opt_clk gpio1_opt_clks[] = { +- { .role = "dbclk", .clk = "gpio1_dbclk" }, +-}; + + static struct omap_hwmod omap44xx_gpio1_hwmod = { + .name = "gpio1", + .class = &omap44xx_gpio_hwmod_class, + .clkdm_name = "l4_wkup_clkdm", +- .main_clk = "l4_wkup_clk_mux_ck", + .prcm = { + .omap4 = { + .clkctrl_offs = OMAP4_CM_WKUP_GPIO1_CLKCTRL_OFFSET, +@@ -1031,22 +1020,16 @@ static struct omap_hwmod omap44xx_gpio1_ + .modulemode = MODULEMODE_HWCTRL, + }, + }, +- .opt_clks = gpio1_opt_clks, +- .opt_clks_cnt = ARRAY_SIZE(gpio1_opt_clks), + .dev_attr = &gpio_dev_attr, + }; + + /* gpio2 */ +-static struct omap_hwmod_opt_clk gpio2_opt_clks[] = { +- { .role = "dbclk", .clk = "gpio2_dbclk" }, +-}; + + static struct omap_hwmod omap44xx_gpio2_hwmod = { + .name = "gpio2", + .class = &omap44xx_gpio_hwmod_class, + .clkdm_name = "l4_per_clkdm", + .flags = HWMOD_CONTROL_OPT_CLKS_IN_RESET, +- .main_clk = "l4_div_ck", + .prcm = { + .omap4 = { + .clkctrl_offs = OMAP4_CM_L4PER_GPIO2_CLKCTRL_OFFSET, +@@ -1054,22 +1037,16 @@ static struct omap_hwmod omap44xx_gpio2_ + .modulemode = MODULEMODE_HWCTRL, + }, + }, +- .opt_clks = gpio2_opt_clks, +- .opt_clks_cnt = ARRAY_SIZE(gpio2_opt_clks), + .dev_attr = &gpio_dev_attr, + }; + + /* gpio3 */ +-static struct omap_hwmod_opt_clk gpio3_opt_clks[] = { +- { .role = "dbclk", .clk = "gpio3_dbclk" }, +-}; + + static struct omap_hwmod omap44xx_gpio3_hwmod = { + .name = "gpio3", + .class = &omap44xx_gpio_hwmod_class, + .clkdm_name = "l4_per_clkdm", + .flags = HWMOD_CONTROL_OPT_CLKS_IN_RESET, +- .main_clk = "l4_div_ck", + .prcm = { + .omap4 = { + .clkctrl_offs = OMAP4_CM_L4PER_GPIO3_CLKCTRL_OFFSET, +@@ -1077,22 +1054,16 @@ static struct omap_hwmod omap44xx_gpio3_ + .modulemode = MODULEMODE_HWCTRL, + }, + }, +- .opt_clks = gpio3_opt_clks, +- .opt_clks_cnt = ARRAY_SIZE(gpio3_opt_clks), + .dev_attr = &gpio_dev_attr, + }; + + /* gpio4 */ +-static struct omap_hwmod_opt_clk gpio4_opt_clks[] = { +- { .role = "dbclk", .clk = "gpio4_dbclk" }, +-}; + + static struct omap_hwmod omap44xx_gpio4_hwmod = { + .name = "gpio4", + .class = &omap44xx_gpio_hwmod_class, + .clkdm_name = "l4_per_clkdm", + .flags = HWMOD_CONTROL_OPT_CLKS_IN_RESET, +- .main_clk = "l4_div_ck", + .prcm = { + .omap4 = { + .clkctrl_offs = OMAP4_CM_L4PER_GPIO4_CLKCTRL_OFFSET, +@@ -1100,22 +1071,16 @@ static struct omap_hwmod omap44xx_gpio4_ + .modulemode = MODULEMODE_HWCTRL, + }, + }, +- .opt_clks = gpio4_opt_clks, +- .opt_clks_cnt = ARRAY_SIZE(gpio4_opt_clks), + .dev_attr = &gpio_dev_attr, + }; + + /* gpio5 */ +-static struct omap_hwmod_opt_clk gpio5_opt_clks[] = { +- { .role = "dbclk", .clk = "gpio5_dbclk" }, +-}; + + static struct omap_hwmod omap44xx_gpio5_hwmod = { + .name = "gpio5", + .class = &omap44xx_gpio_hwmod_class, + .clkdm_name = "l4_per_clkdm", + .flags = HWMOD_CONTROL_OPT_CLKS_IN_RESET, +- .main_clk = "l4_div_ck", + .prcm = { + .omap4 = { + .clkctrl_offs = OMAP4_CM_L4PER_GPIO5_CLKCTRL_OFFSET, +@@ -1123,22 +1088,16 @@ static struct omap_hwmod omap44xx_gpio5_ + .modulemode = MODULEMODE_HWCTRL, + }, + }, +- .opt_clks = gpio5_opt_clks, +- .opt_clks_cnt = ARRAY_SIZE(gpio5_opt_clks), + .dev_attr = &gpio_dev_attr, + }; + + /* gpio6 */ +-static struct omap_hwmod_opt_clk gpio6_opt_clks[] = { +- { .role = "dbclk", .clk = "gpio6_dbclk" }, +-}; + + static struct omap_hwmod omap44xx_gpio6_hwmod = { + .name = "gpio6", + .class = &omap44xx_gpio_hwmod_class, + .clkdm_name = "l4_per_clkdm", + .flags = HWMOD_CONTROL_OPT_CLKS_IN_RESET, +- .main_clk = "l4_div_ck", + .prcm = { + .omap4 = { + .clkctrl_offs = OMAP4_CM_L4PER_GPIO6_CLKCTRL_OFFSET, +@@ -1146,8 +1105,6 @@ static struct omap_hwmod omap44xx_gpio6_ + .modulemode = MODULEMODE_HWCTRL, + }, + }, +- .opt_clks = gpio6_opt_clks, +- .opt_clks_cnt = ARRAY_SIZE(gpio6_opt_clks), + .dev_attr = &gpio_dev_attr, + }; + +@@ -1184,7 +1141,7 @@ static struct omap_hwmod omap44xx_gpmc_h + * the kernel from the board file or DT data. + * HWMOD_INIT_NO_RESET should be removed ASAP. + */ +- .flags = HWMOD_INIT_NO_IDLE | HWMOD_INIT_NO_RESET, ++ .flags = HWMOD_INIT_NO_RESET, + .prcm = { + .omap4 = { + .clkctrl_offs = OMAP4_CM_L3_2_GPMC_CLKCTRL_OFFSET, +@@ -1337,7 +1294,6 @@ static struct omap_hwmod omap44xx_i2c1_h + .class = &omap44xx_i2c_hwmod_class, + .clkdm_name = "l4_per_clkdm", + .flags = HWMOD_16BIT_REG | HWMOD_SET_DEFAULT_CLOCKACT, +- .main_clk = "func_96m_fclk", + .prcm = { + .omap4 = { + .clkctrl_offs = OMAP4_CM_L4PER_I2C1_CLKCTRL_OFFSET, +@@ -1354,7 +1310,6 @@ static struct omap_hwmod omap44xx_i2c2_h + .class = &omap44xx_i2c_hwmod_class, + .clkdm_name = "l4_per_clkdm", + .flags = HWMOD_16BIT_REG | HWMOD_SET_DEFAULT_CLOCKACT, +- .main_clk = "func_96m_fclk", + .prcm = { + .omap4 = { + .clkctrl_offs = OMAP4_CM_L4PER_I2C2_CLKCTRL_OFFSET, +@@ -1371,7 +1326,6 @@ static struct omap_hwmod omap44xx_i2c3_h + .class = &omap44xx_i2c_hwmod_class, + .clkdm_name = "l4_per_clkdm", + .flags = HWMOD_16BIT_REG | HWMOD_SET_DEFAULT_CLOCKACT, +- .main_clk = "func_96m_fclk", + .prcm = { + .omap4 = { + .clkctrl_offs = OMAP4_CM_L4PER_I2C3_CLKCTRL_OFFSET, +@@ -1388,7 +1342,6 @@ static struct omap_hwmod omap44xx_i2c4_h + .class = &omap44xx_i2c_hwmod_class, + .clkdm_name = "l4_per_clkdm", + .flags = HWMOD_16BIT_REG | HWMOD_SET_DEFAULT_CLOCKACT, +- .main_clk = "func_96m_fclk", + .prcm = { + .omap4 = { + .clkctrl_offs = OMAP4_CM_L4PER_I2C4_CLKCTRL_OFFSET, +@@ -1542,7 +1495,6 @@ static struct omap_hwmod omap44xx_kbd_hw + .name = "kbd", + .class = &omap44xx_kbd_hwmod_class, + .clkdm_name = "l4_wkup_clkdm", +- .main_clk = "sys_32k_ck", + .prcm = { + .omap4 = { + .clkctrl_offs = OMAP4_CM_WKUP_KEYBOARD_CLKCTRL_OFFSET, +@@ -1643,16 +1595,11 @@ static struct omap_hwmod_class omap44xx_ + }; + + /* mcbsp1 */ +-static struct omap_hwmod_opt_clk mcbsp1_opt_clks[] = { +- { .role = "pad_fck", .clk = "pad_clks_ck" }, +- { .role = "prcm_fck", .clk = "mcbsp1_sync_mux_ck" }, +-}; + + static struct omap_hwmod omap44xx_mcbsp1_hwmod = { + .name = "mcbsp1", + .class = &omap44xx_mcbsp_hwmod_class, + .clkdm_name = "abe_clkdm", +- .main_clk = "func_mcbsp1_gfclk", + .prcm = { + .omap4 = { + .clkctrl_offs = OMAP4_CM1_ABE_MCBSP1_CLKCTRL_OFFSET, +@@ -1660,21 +1607,14 @@ static struct omap_hwmod omap44xx_mcbsp1 + .modulemode = MODULEMODE_SWCTRL, + }, + }, +- .opt_clks = mcbsp1_opt_clks, +- .opt_clks_cnt = ARRAY_SIZE(mcbsp1_opt_clks), + }; + + /* mcbsp2 */ +-static struct omap_hwmod_opt_clk mcbsp2_opt_clks[] = { +- { .role = "pad_fck", .clk = "pad_clks_ck" }, +- { .role = "prcm_fck", .clk = "mcbsp2_sync_mux_ck" }, +-}; + + static struct omap_hwmod omap44xx_mcbsp2_hwmod = { + .name = "mcbsp2", + .class = &omap44xx_mcbsp_hwmod_class, + .clkdm_name = "abe_clkdm", +- .main_clk = "func_mcbsp2_gfclk", + .prcm = { + .omap4 = { + .clkctrl_offs = OMAP4_CM1_ABE_MCBSP2_CLKCTRL_OFFSET, +@@ -1682,21 +1622,14 @@ static struct omap_hwmod omap44xx_mcbsp2 + .modulemode = MODULEMODE_SWCTRL, + }, + }, +- .opt_clks = mcbsp2_opt_clks, +- .opt_clks_cnt = ARRAY_SIZE(mcbsp2_opt_clks), + }; + + /* mcbsp3 */ +-static struct omap_hwmod_opt_clk mcbsp3_opt_clks[] = { +- { .role = "pad_fck", .clk = "pad_clks_ck" }, +- { .role = "prcm_fck", .clk = "mcbsp3_sync_mux_ck" }, +-}; + + static struct omap_hwmod omap44xx_mcbsp3_hwmod = { + .name = "mcbsp3", + .class = &omap44xx_mcbsp_hwmod_class, + .clkdm_name = "abe_clkdm", +- .main_clk = "func_mcbsp3_gfclk", + .prcm = { + .omap4 = { + .clkctrl_offs = OMAP4_CM1_ABE_MCBSP3_CLKCTRL_OFFSET, +@@ -1704,21 +1637,14 @@ static struct omap_hwmod omap44xx_mcbsp3 + .modulemode = MODULEMODE_SWCTRL, + }, + }, +- .opt_clks = mcbsp3_opt_clks, +- .opt_clks_cnt = ARRAY_SIZE(mcbsp3_opt_clks), + }; + + /* mcbsp4 */ +-static struct omap_hwmod_opt_clk mcbsp4_opt_clks[] = { +- { .role = "pad_fck", .clk = "pad_clks_ck" }, +- { .role = "prcm_fck", .clk = "mcbsp4_sync_mux_ck" }, +-}; + + static struct omap_hwmod omap44xx_mcbsp4_hwmod = { + .name = "mcbsp4", + .class = &omap44xx_mcbsp_hwmod_class, + .clkdm_name = "l4_per_clkdm", +- .main_clk = "per_mcbsp4_gfclk", + .prcm = { + .omap4 = { + .clkctrl_offs = OMAP4_CM_L4PER_MCBSP4_CLKCTRL_OFFSET, +@@ -1726,8 +1652,6 @@ static struct omap_hwmod omap44xx_mcbsp4 + .modulemode = MODULEMODE_SWCTRL, + }, + }, +- .opt_clks = mcbsp4_opt_clks, +- .opt_clks_cnt = ARRAY_SIZE(mcbsp4_opt_clks), + }; + + /* +@@ -1768,7 +1692,6 @@ static struct omap_hwmod omap44xx_mcpdm_ + * results 'slow motion' audio playback. + */ + .flags = HWMOD_EXT_OPT_MAIN_CLK | HWMOD_SWSUP_SIDLE, +- .main_clk = "pad_clks_ck", + .prcm = { + .omap4 = { + .clkctrl_offs = OMAP4_CM1_ABE_PDM_CLKCTRL_OFFSET, +@@ -1823,7 +1746,6 @@ static struct omap_hwmod omap44xx_mcspi1 + .class = &omap44xx_mcspi_hwmod_class, + .clkdm_name = "l4_per_clkdm", + .sdma_reqs = omap44xx_mcspi1_sdma_reqs, +- .main_clk = "func_48m_fclk", + .prcm = { + .omap4 = { + .clkctrl_offs = OMAP4_CM_L4PER_MCSPI1_CLKCTRL_OFFSET, +@@ -1853,7 +1775,6 @@ static struct omap_hwmod omap44xx_mcspi2 + .class = &omap44xx_mcspi_hwmod_class, + .clkdm_name = "l4_per_clkdm", + .sdma_reqs = omap44xx_mcspi2_sdma_reqs, +- .main_clk = "func_48m_fclk", + .prcm = { + .omap4 = { + .clkctrl_offs = OMAP4_CM_L4PER_MCSPI2_CLKCTRL_OFFSET, +@@ -1883,7 +1804,6 @@ static struct omap_hwmod omap44xx_mcspi3 + .class = &omap44xx_mcspi_hwmod_class, + .clkdm_name = "l4_per_clkdm", + .sdma_reqs = omap44xx_mcspi3_sdma_reqs, +- .main_clk = "func_48m_fclk", + .prcm = { + .omap4 = { + .clkctrl_offs = OMAP4_CM_L4PER_MCSPI3_CLKCTRL_OFFSET, +@@ -1911,7 +1831,6 @@ static struct omap_hwmod omap44xx_mcspi4 + .class = &omap44xx_mcspi_hwmod_class, + .clkdm_name = "l4_per_clkdm", + .sdma_reqs = omap44xx_mcspi4_sdma_reqs, +- .main_clk = "func_48m_fclk", + .prcm = { + .omap4 = { + .clkctrl_offs = OMAP4_CM_L4PER_MCSPI4_CLKCTRL_OFFSET, +@@ -1961,7 +1880,6 @@ static struct omap_hwmod omap44xx_mmc1_h + .class = &omap44xx_mmc_hwmod_class, + .clkdm_name = "l3_init_clkdm", + .sdma_reqs = omap44xx_mmc1_sdma_reqs, +- .main_clk = "hsmmc1_fclk", + .prcm = { + .omap4 = { + .clkctrl_offs = OMAP4_CM_L3INIT_MMC1_CLKCTRL_OFFSET, +@@ -1984,7 +1902,6 @@ static struct omap_hwmod omap44xx_mmc2_h + .class = &omap44xx_mmc_hwmod_class, + .clkdm_name = "l3_init_clkdm", + .sdma_reqs = omap44xx_mmc2_sdma_reqs, +- .main_clk = "hsmmc2_fclk", + .prcm = { + .omap4 = { + .clkctrl_offs = OMAP4_CM_L3INIT_MMC2_CLKCTRL_OFFSET, +@@ -2006,7 +1923,6 @@ static struct omap_hwmod omap44xx_mmc3_h + .class = &omap44xx_mmc_hwmod_class, + .clkdm_name = "l4_per_clkdm", + .sdma_reqs = omap44xx_mmc3_sdma_reqs, +- .main_clk = "func_48m_fclk", + .prcm = { + .omap4 = { + .clkctrl_offs = OMAP4_CM_L4PER_MMCSD3_CLKCTRL_OFFSET, +@@ -2028,7 +1944,6 @@ static struct omap_hwmod omap44xx_mmc4_h + .class = &omap44xx_mmc_hwmod_class, + .clkdm_name = "l4_per_clkdm", + .sdma_reqs = omap44xx_mmc4_sdma_reqs, +- .main_clk = "func_48m_fclk", + .prcm = { + .omap4 = { + .clkctrl_offs = OMAP4_CM_L4PER_MMCSD4_CLKCTRL_OFFSET, +@@ -2050,7 +1965,6 @@ static struct omap_hwmod omap44xx_mmc5_h + .class = &omap44xx_mmc_hwmod_class, + .clkdm_name = "l4_per_clkdm", + .sdma_reqs = omap44xx_mmc5_sdma_reqs, +- .main_clk = "func_48m_fclk", + .prcm = { + .omap4 = { + .clkctrl_offs = OMAP4_CM_L4PER_MMCSD5_CLKCTRL_OFFSET, +@@ -2193,7 +2107,7 @@ static struct omap_hwmod omap44xx_mpu_hw + .name = "mpu", + .class = &omap44xx_mpu_hwmod_class, + .clkdm_name = "mpuss_clkdm", +- .flags = HWMOD_INIT_NO_IDLE | HWMOD_INIT_NO_RESET, ++ .flags = HWMOD_INIT_NO_IDLE, + .main_clk = "dpll_mpu_m2_ck", + .prcm = { + .omap4 = { +@@ -2261,7 +2175,6 @@ static struct omap_hwmod omap44xx_ocp2sc + * So listing ocp2scp_usb_phy_phy_48m as a main_clk here seems + * to be the best workaround. + */ +- .main_clk = "ocp2scp_usb_phy_phy_48m", + .prcm = { + .omap4 = { + .clkctrl_offs = OMAP4_CM_L3INIT_USBPHYOCP2SCP_CLKCTRL_OFFSET, +@@ -2629,7 +2542,6 @@ static struct omap_hwmod omap44xx_timer1 + .class = &omap44xx_timer_1ms_hwmod_class, + .clkdm_name = "l4_wkup_clkdm", + .flags = HWMOD_SET_DEFAULT_CLOCKACT, +- .main_clk = "dmt1_clk_mux", + .prcm = { + .omap4 = { + .clkctrl_offs = OMAP4_CM_WKUP_TIMER1_CLKCTRL_OFFSET, +@@ -2646,7 +2558,6 @@ static struct omap_hwmod omap44xx_timer2 + .class = &omap44xx_timer_1ms_hwmod_class, + .clkdm_name = "l4_per_clkdm", + .flags = HWMOD_SET_DEFAULT_CLOCKACT, +- .main_clk = "cm2_dm2_mux", + .prcm = { + .omap4 = { + .clkctrl_offs = OMAP4_CM_L4PER_DMTIMER2_CLKCTRL_OFFSET, +@@ -2661,7 +2572,6 @@ static struct omap_hwmod omap44xx_timer3 + .name = "timer3", + .class = &omap44xx_timer_hwmod_class, + .clkdm_name = "l4_per_clkdm", +- .main_clk = "cm2_dm3_mux", + .prcm = { + .omap4 = { + .clkctrl_offs = OMAP4_CM_L4PER_DMTIMER3_CLKCTRL_OFFSET, +@@ -2676,7 +2586,6 @@ static struct omap_hwmod omap44xx_timer4 + .name = "timer4", + .class = &omap44xx_timer_hwmod_class, + .clkdm_name = "l4_per_clkdm", +- .main_clk = "cm2_dm4_mux", + .prcm = { + .omap4 = { + .clkctrl_offs = OMAP4_CM_L4PER_DMTIMER4_CLKCTRL_OFFSET, +@@ -2691,7 +2600,6 @@ static struct omap_hwmod omap44xx_timer5 + .name = "timer5", + .class = &omap44xx_timer_hwmod_class, + .clkdm_name = "abe_clkdm", +- .main_clk = "timer5_sync_mux", + .prcm = { + .omap4 = { + .clkctrl_offs = OMAP4_CM1_ABE_TIMER5_CLKCTRL_OFFSET, +@@ -2707,7 +2615,6 @@ static struct omap_hwmod omap44xx_timer6 + .name = "timer6", + .class = &omap44xx_timer_hwmod_class, + .clkdm_name = "abe_clkdm", +- .main_clk = "timer6_sync_mux", + .prcm = { + .omap4 = { + .clkctrl_offs = OMAP4_CM1_ABE_TIMER6_CLKCTRL_OFFSET, +@@ -2723,7 +2630,6 @@ static struct omap_hwmod omap44xx_timer7 + .name = "timer7", + .class = &omap44xx_timer_hwmod_class, + .clkdm_name = "abe_clkdm", +- .main_clk = "timer7_sync_mux", + .prcm = { + .omap4 = { + .clkctrl_offs = OMAP4_CM1_ABE_TIMER7_CLKCTRL_OFFSET, +@@ -2739,7 +2645,6 @@ static struct omap_hwmod omap44xx_timer8 + .name = "timer8", + .class = &omap44xx_timer_hwmod_class, + .clkdm_name = "abe_clkdm", +- .main_clk = "timer8_sync_mux", + .prcm = { + .omap4 = { + .clkctrl_offs = OMAP4_CM1_ABE_TIMER8_CLKCTRL_OFFSET, +@@ -2755,7 +2660,6 @@ static struct omap_hwmod omap44xx_timer9 + .name = "timer9", + .class = &omap44xx_timer_hwmod_class, + .clkdm_name = "l4_per_clkdm", +- .main_clk = "cm2_dm9_mux", + .prcm = { + .omap4 = { + .clkctrl_offs = OMAP4_CM_L4PER_DMTIMER9_CLKCTRL_OFFSET, +@@ -2772,7 +2676,6 @@ static struct omap_hwmod omap44xx_timer1 + .class = &omap44xx_timer_1ms_hwmod_class, + .clkdm_name = "l4_per_clkdm", + .flags = HWMOD_SET_DEFAULT_CLOCKACT, +- .main_clk = "cm2_dm10_mux", + .prcm = { + .omap4 = { + .clkctrl_offs = OMAP4_CM_L4PER_DMTIMER10_CLKCTRL_OFFSET, +@@ -2788,7 +2691,6 @@ static struct omap_hwmod omap44xx_timer1 + .name = "timer11", + .class = &omap44xx_timer_hwmod_class, + .clkdm_name = "l4_per_clkdm", +- .main_clk = "cm2_dm11_mux", + .prcm = { + .omap4 = { + .clkctrl_offs = OMAP4_CM_L4PER_DMTIMER11_CLKCTRL_OFFSET, +@@ -2827,7 +2729,6 @@ static struct omap_hwmod omap44xx_uart1_ + .class = &omap44xx_uart_hwmod_class, + .clkdm_name = "l4_per_clkdm", + .flags = HWMOD_SWSUP_SIDLE_ACT, +- .main_clk = "func_48m_fclk", + .prcm = { + .omap4 = { + .clkctrl_offs = OMAP4_CM_L4PER_UART1_CLKCTRL_OFFSET, +@@ -2843,7 +2744,6 @@ static struct omap_hwmod omap44xx_uart2_ + .class = &omap44xx_uart_hwmod_class, + .clkdm_name = "l4_per_clkdm", + .flags = HWMOD_SWSUP_SIDLE_ACT, +- .main_clk = "func_48m_fclk", + .prcm = { + .omap4 = { + .clkctrl_offs = OMAP4_CM_L4PER_UART2_CLKCTRL_OFFSET, +@@ -2859,7 +2759,6 @@ static struct omap_hwmod omap44xx_uart3_ + .class = &omap44xx_uart_hwmod_class, + .clkdm_name = "l4_per_clkdm", + .flags = DEBUG_OMAP4UART3_FLAGS | HWMOD_SWSUP_SIDLE_ACT, +- .main_clk = "func_48m_fclk", + .prcm = { + .omap4 = { + .clkctrl_offs = OMAP4_CM_L4PER_UART3_CLKCTRL_OFFSET, +@@ -2875,7 +2774,6 @@ static struct omap_hwmod omap44xx_uart4_ + .class = &omap44xx_uart_hwmod_class, + .clkdm_name = "l4_per_clkdm", + .flags = DEBUG_OMAP4UART4_FLAGS | HWMOD_SWSUP_SIDLE_ACT, +- .main_clk = "func_48m_fclk", + .prcm = { + .omap4 = { + .clkctrl_offs = OMAP4_CM_L4PER_UART4_CLKCTRL_OFFSET, +@@ -2954,7 +2852,6 @@ static struct omap_hwmod omap44xx_usb_ho + .name = "usb_host_hs", + .class = &omap44xx_usb_host_hs_hwmod_class, + .clkdm_name = "l3_init_clkdm", +- .main_clk = "usb_host_hs_fck", + .prcm = { + .omap4 = { + .clkctrl_offs = OMAP4_CM_L3INIT_USB_HOST_CLKCTRL_OFFSET, +@@ -3036,16 +2933,12 @@ static struct omap_hwmod_class omap44xx_ + }; + + /* usb_otg_hs */ +-static struct omap_hwmod_opt_clk usb_otg_hs_opt_clks[] = { +- { .role = "xclk", .clk = "usb_otg_hs_xclk" }, +-}; + + static struct omap_hwmod omap44xx_usb_otg_hs_hwmod = { + .name = "usb_otg_hs", + .class = &omap44xx_usb_otg_hs_hwmod_class, + .clkdm_name = "l3_init_clkdm", + .flags = HWMOD_SWSUP_SIDLE | HWMOD_SWSUP_MSTANDBY, +- .main_clk = "usb_otg_hs_ick", + .prcm = { + .omap4 = { + .clkctrl_offs = OMAP4_CM_L3INIT_USB_OTG_CLKCTRL_OFFSET, +@@ -3053,8 +2946,6 @@ static struct omap_hwmod omap44xx_usb_ot + .modulemode = MODULEMODE_HWCTRL, + }, + }, +- .opt_clks = usb_otg_hs_opt_clks, +- .opt_clks_cnt = ARRAY_SIZE(usb_otg_hs_opt_clks), + }; + + /* +@@ -3082,7 +2973,6 @@ static struct omap_hwmod omap44xx_usb_tl + .name = "usb_tll_hs", + .class = &omap44xx_usb_tll_hs_hwmod_class, + .clkdm_name = "l3_init_clkdm", +- .main_clk = "usb_tll_hs_ick", + .prcm = { + .omap4 = { + .clkctrl_offs = OMAP4_CM_L3INIT_USB_TLL_CLKCTRL_OFFSET, +@@ -3121,7 +3011,6 @@ static struct omap_hwmod omap44xx_wd_tim + .name = "wd_timer2", + .class = &omap44xx_wd_timer_hwmod_class, + .clkdm_name = "l4_wkup_clkdm", +- .main_clk = "sys_32k_ck", + .prcm = { + .omap4 = { + .clkctrl_offs = OMAP4_CM_WKUP_WDT2_CLKCTRL_OFFSET, +@@ -4791,6 +4680,105 @@ static struct omap_hwmod_ocp_if omap44xx + .user = OCP_USER_MPU | OCP_USER_SDMA, + }; + ++/* ++ Crypto modules AES0/1 belong to: ++ PD_L4_PER power domain ++ CD_L4_SEC clock domain ++ On the L3, the AES modules are mapped to ++ L3_CLK2: Peripherals and multimedia sub clock domain ++*/ ++ ++static struct omap_hwmod_class_sysconfig omap4_aes1_sysc = { ++ .rev_offs = 0x80, ++ .sysc_offs = 0x84, ++ .syss_offs = 0x88, ++ .sysc_flags = SYSS_HAS_RESET_STATUS, ++ .sysc_fields = &omap_hwmod_sysc_type4, ++}; ++ ++static struct omap_hwmod_class omap4_aes1_hwmod_class = { ++ .name = "aes1", ++ .sysc = &omap4_aes1_sysc, ++}; ++ ++static struct omap_hwmod omap4_aes1_hwmod = { ++ .name = "aes", ++ .class = &omap4_aes1_hwmod_class, ++ .clkdm_name = "l4_secure_clkdm", ++ .main_clk = "aes1_fck", ++ .prcm = { ++ .omap4 = { ++ .clkctrl_offs = OMAP4_CM_L4SEC_AES1_CLKCTRL_OFFSET, ++ .context_offs = OMAP4_RM_L4SEC_AES1_CONTEXT_OFFSET, ++ .modulemode = MODULEMODE_SWCTRL, ++ }, ++ }, ++}; ++ ++/* l3_main_2 -> aes1 */ ++static struct omap_hwmod_addr_space omap4_aes1_addrs[] = { ++ { ++ .pa_start = 0x4B500000, ++ .pa_end = 0x4B500000 + SZ_1M - 1, ++ .flags = ADDR_TYPE_RT ++ }, ++ { } ++}; ++ ++static struct omap_hwmod_ocp_if omap4_l3_main_2__aes1 = { ++ .master = &omap44xx_l3_main_2_hwmod, ++ .slave = &omap4_aes1_hwmod, ++ .clk = "aes1_fck", ++ .addr = omap4_aes1_addrs, ++ .user = OCP_USER_MPU | OCP_USER_SDMA, ++}; ++ ++/* DES3DES */ ++static struct omap_hwmod_class_sysconfig omap4_des_sysc = { ++ .rev_offs = 0x30, ++ .sysc_offs = 0x34, ++ .syss_offs = 0x38, ++ .sysc_flags = SYSS_HAS_RESET_STATUS, ++ .sysc_fields = &omap_hwmod_sysc_type4, ++}; ++ ++static struct omap_hwmod_class omap4_des_hwmod_class = { ++ .name = "des", ++ .sysc = &omap4_des_sysc, ++}; ++ ++ ++static struct omap_hwmod omap4_des_hwmod = { ++ .name = "des", ++ .class = &omap4_des_hwmod_class, ++ .clkdm_name = "l4_secure_clkdm", ++ .main_clk = "des_fck", ++ .prcm = { ++ .omap4 = { ++ .clkctrl_offs = OMAP4_CM_L4SEC_DES3DES_CLKCTRL_OFFSET, ++ .context_offs = OMAP4_RM_L4SEC_DES3DES_CONTEXT_OFFSET, ++ .modulemode = MODULEMODE_SWCTRL, ++ }, ++ }, ++}; ++ ++static struct omap_hwmod_addr_space omap4_des_addrs[] = { ++ { ++ .pa_start = 0x480A4000, ++ .pa_end = 0x481A4000, ++ .flags = ADDR_TYPE_RT ++ }, ++ { } ++}; ++ ++static struct omap_hwmod_ocp_if omap4_l4_per__des = { ++ .master = &omap44xx_l4_per_hwmod, ++ .slave = &omap4_des_hwmod, ++ .clk = "des_fck", ++ .addr = omap4_des_addrs, ++ .user = OCP_USER_MPU | OCP_USER_SDMA, ++}; ++ + static struct omap_hwmod_ocp_if *omap44xx_hwmod_ocp_ifs[] __initdata = { + &omap44xx_l3_main_1__dmm, + &omap44xx_mpu__dmm, +@@ -4945,6 +4933,8 @@ static struct omap_hwmod_ocp_if *omap44x + &omap44xx_l4_abe__wd_timer3_dma, + &omap44xx_mpu__emif1, + &omap44xx_mpu__emif2, ++ &omap4_l3_main_2__aes1, ++ &omap4_l4_per__des, + NULL, + }; + +--- a/arch/arm/mach-omap2/omap_hwmod_54xx_data.c ++++ b/arch/arm/mach-omap2/omap_hwmod_54xx_data.c +@@ -234,7 +234,6 @@ static struct omap_hwmod omap54xx_counte + .class = &omap54xx_counter_hwmod_class, + .clkdm_name = "wkupaon_clkdm", + .flags = HWMOD_SWSUP_SIDLE, +- .main_clk = "wkupaon_iclk_mux", + .prcm = { + .omap4 = { + .clkctrl_offs = OMAP54XX_CM_WKUPAON_COUNTER_32K_CLKCTRL_OFFSET, +@@ -288,7 +287,6 @@ static struct omap_hwmod omap54xx_dma_sy + .class = &omap54xx_dma_hwmod_class, + .clkdm_name = "dma_clkdm", + .mpu_irqs = omap54xx_dma_system_irqs, +- .main_clk = "l3_iclk_div", + .prcm = { + .omap4 = { + .clkctrl_offs = OMAP54XX_CM_DMA_DMA_SYSTEM_CLKCTRL_OFFSET, +@@ -323,7 +321,6 @@ static struct omap_hwmod omap54xx_dmic_h + .name = "dmic", + .class = &omap54xx_dmic_hwmod_class, + .clkdm_name = "abe_clkdm", +- .main_clk = "dmic_gfclk", + .prcm = { + .omap4 = { + .clkctrl_offs = OMAP54XX_CM_ABE_DMIC_CLKCTRL_OFFSET, +@@ -334,6 +331,235 @@ static struct omap_hwmod omap54xx_dmic_h + }; + + /* ++ * 'dss' class ++ * display sub-system ++ */ ++static struct omap_hwmod_class_sysconfig omap54xx_dss_sysc = { ++ .rev_offs = 0x0000, ++ .syss_offs = 0x0014, ++ .sysc_flags = SYSS_HAS_RESET_STATUS, ++}; ++ ++static struct omap_hwmod_class omap54xx_dss_hwmod_class = { ++ .name = "dss", ++ .sysc = &omap54xx_dss_sysc, ++ .reset = omap_dss_reset, ++}; ++ ++/* dss */ ++static struct omap_hwmod_opt_clk dss_opt_clks[] = { ++ { .role = "32khz_clk", .clk = "dss_32khz_clk" }, ++ { .role = "sys_clk", .clk = "dss_sys_clk" }, ++ { .role = "hdmi_clk", .clk = "dss_48mhz_clk" }, ++}; ++ ++static struct omap_hwmod omap54xx_dss_hwmod = { ++ .name = "dss_core", ++ .class = &omap54xx_dss_hwmod_class, ++ .clkdm_name = "dss_clkdm", ++ .flags = HWMOD_CONTROL_OPT_CLKS_IN_RESET, ++ .main_clk = "dss_dss_clk", ++ .prcm = { ++ .omap4 = { ++ .clkctrl_offs = OMAP54XX_CM_DSS_DSS_CLKCTRL_OFFSET, ++ .context_offs = OMAP54XX_RM_DSS_DSS_CONTEXT_OFFSET, ++ .modulemode = MODULEMODE_SWCTRL, ++ }, ++ }, ++ .opt_clks = dss_opt_clks, ++ .opt_clks_cnt = ARRAY_SIZE(dss_opt_clks), ++}; ++ ++/* ++ * 'dispc' class ++ * display controller ++ */ ++ ++static struct omap_hwmod_class_sysconfig omap54xx_dispc_sysc = { ++ .rev_offs = 0x0000, ++ .sysc_offs = 0x0010, ++ .syss_offs = 0x0014, ++ .sysc_flags = (SYSC_HAS_AUTOIDLE | SYSC_HAS_CLOCKACTIVITY | ++ SYSC_HAS_ENAWAKEUP | SYSC_HAS_MIDLEMODE | ++ SYSC_HAS_SIDLEMODE | SYSC_HAS_SOFTRESET | ++ SYSS_HAS_RESET_STATUS), ++ .idlemodes = (SIDLE_FORCE | SIDLE_NO | SIDLE_SMART | ++ MSTANDBY_FORCE | MSTANDBY_NO | MSTANDBY_SMART), ++ .sysc_fields = &omap_hwmod_sysc_type1, ++}; ++ ++static struct omap_hwmod_class omap54xx_dispc_hwmod_class = { ++ .name = "dispc", ++ .sysc = &omap54xx_dispc_sysc, ++}; ++ ++/* dss_dispc */ ++static struct omap_hwmod_opt_clk dss_dispc_opt_clks[] = { ++ { .role = "sys_clk", .clk = "dss_sys_clk" }, ++}; ++ ++/* dss_dispc dev_attr */ ++static struct omap_dss_dispc_dev_attr dss_dispc_dev_attr = { ++ .has_framedonetv_irq = 1, ++ .manager_count = 4, ++}; ++ ++static struct omap_hwmod omap54xx_dss_dispc_hwmod = { ++ .name = "dss_dispc", ++ .class = &omap54xx_dispc_hwmod_class, ++ .clkdm_name = "dss_clkdm", ++ .main_clk = "dss_dss_clk", ++ .prcm = { ++ .omap4 = { ++ .clkctrl_offs = OMAP54XX_CM_DSS_DSS_CLKCTRL_OFFSET, ++ .flags = HWMOD_OMAP4_NO_CONTEXT_LOSS_BIT, ++ }, ++ }, ++ .opt_clks = dss_dispc_opt_clks, ++ .opt_clks_cnt = ARRAY_SIZE(dss_dispc_opt_clks), ++ .dev_attr = &dss_dispc_dev_attr, ++}; ++ ++/* ++ * 'dsi1' class ++ * display serial interface controller ++ */ ++ ++static struct omap_hwmod_class_sysconfig omap54xx_dsi1_sysc = { ++ .rev_offs = 0x0000, ++ .sysc_offs = 0x0010, ++ .syss_offs = 0x0014, ++ .sysc_flags = (SYSC_HAS_AUTOIDLE | SYSC_HAS_CLOCKACTIVITY | ++ SYSC_HAS_ENAWAKEUP | SYSC_HAS_SIDLEMODE | ++ SYSC_HAS_SOFTRESET | SYSS_HAS_RESET_STATUS), ++ .idlemodes = (SIDLE_FORCE | SIDLE_NO | SIDLE_SMART), ++ .sysc_fields = &omap_hwmod_sysc_type1, ++}; ++ ++static struct omap_hwmod_class omap54xx_dsi1_hwmod_class = { ++ .name = "dsi1", ++ .sysc = &omap54xx_dsi1_sysc, ++}; ++ ++/* dss_dsi1_a */ ++static struct omap_hwmod_opt_clk dss_dsi1_a_opt_clks[] = { ++ { .role = "sys_clk", .clk = "dss_sys_clk" }, ++}; ++ ++static struct omap_hwmod omap54xx_dss_dsi1_a_hwmod = { ++ .name = "dss_dsi1", ++ .class = &omap54xx_dsi1_hwmod_class, ++ .clkdm_name = "dss_clkdm", ++ .main_clk = "dss_dss_clk", ++ .prcm = { ++ .omap4 = { ++ .clkctrl_offs = OMAP54XX_CM_DSS_DSS_CLKCTRL_OFFSET, ++ .flags = HWMOD_OMAP4_NO_CONTEXT_LOSS_BIT, ++ }, ++ }, ++ .opt_clks = dss_dsi1_a_opt_clks, ++ .opt_clks_cnt = ARRAY_SIZE(dss_dsi1_a_opt_clks), ++}; ++ ++/* dss_dsi1_c */ ++static struct omap_hwmod_opt_clk dss_dsi1_c_opt_clks[] = { ++ { .role = "sys_clk", .clk = "dss_sys_clk" }, ++}; ++ ++static struct omap_hwmod omap54xx_dss_dsi1_c_hwmod = { ++ .name = "dss_dsi2", ++ .class = &omap54xx_dsi1_hwmod_class, ++ .clkdm_name = "dss_clkdm", ++ .main_clk = "dss_dss_clk", ++ .prcm = { ++ .omap4 = { ++ .clkctrl_offs = OMAP54XX_CM_DSS_DSS_CLKCTRL_OFFSET, ++ .flags = HWMOD_OMAP4_NO_CONTEXT_LOSS_BIT, ++ }, ++ }, ++ .opt_clks = dss_dsi1_c_opt_clks, ++ .opt_clks_cnt = ARRAY_SIZE(dss_dsi1_c_opt_clks), ++}; ++ ++/* ++ * 'hdmi' class ++ * hdmi controller ++ */ ++ ++static struct omap_hwmod_class_sysconfig omap54xx_hdmi_sysc = { ++ .rev_offs = 0x0000, ++ .sysc_offs = 0x0010, ++ .sysc_flags = (SYSC_HAS_RESET_STATUS | SYSC_HAS_SIDLEMODE | ++ SYSC_HAS_SOFTRESET), ++ .idlemodes = (SIDLE_FORCE | SIDLE_NO | SIDLE_SMART | ++ SIDLE_SMART_WKUP), ++ .sysc_fields = &omap_hwmod_sysc_type2, ++}; ++ ++static struct omap_hwmod_class omap54xx_hdmi_hwmod_class = { ++ .name = "hdmi", ++ .sysc = &omap54xx_hdmi_sysc, ++}; ++ ++static struct omap_hwmod_opt_clk dss_hdmi_opt_clks[] = { ++ { .role = "sys_clk", .clk = "dss_sys_clk" }, ++}; ++ ++static struct omap_hwmod omap54xx_dss_hdmi_hwmod = { ++ .name = "dss_hdmi", ++ .class = &omap54xx_hdmi_hwmod_class, ++ .clkdm_name = "dss_clkdm", ++ .main_clk = "dss_48mhz_clk", ++ .prcm = { ++ .omap4 = { ++ .clkctrl_offs = OMAP54XX_CM_DSS_DSS_CLKCTRL_OFFSET, ++ .flags = HWMOD_OMAP4_NO_CONTEXT_LOSS_BIT, ++ }, ++ }, ++ .opt_clks = dss_hdmi_opt_clks, ++ .opt_clks_cnt = ARRAY_SIZE(dss_hdmi_opt_clks), ++}; ++ ++/* ++ * 'rfbi' class ++ * remote frame buffer interface ++ */ ++ ++static struct omap_hwmod_class_sysconfig omap54xx_rfbi_sysc = { ++ .rev_offs = 0x0000, ++ .sysc_offs = 0x0010, ++ .syss_offs = 0x0014, ++ .sysc_flags = (SYSC_HAS_AUTOIDLE | SYSC_HAS_SIDLEMODE | ++ SYSC_HAS_SOFTRESET | SYSS_HAS_RESET_STATUS), ++ .idlemodes = (SIDLE_FORCE | SIDLE_NO | SIDLE_SMART), ++ .sysc_fields = &omap_hwmod_sysc_type1, ++}; ++ ++static struct omap_hwmod_class omap54xx_rfbi_hwmod_class = { ++ .name = "rfbi", ++ .sysc = &omap54xx_rfbi_sysc, ++}; ++ ++/* dss_rfbi */ ++static struct omap_hwmod_opt_clk dss_rfbi_opt_clks[] = { ++ { .role = "ick", .clk = "l3_iclk_div" }, ++}; ++ ++static struct omap_hwmod omap54xx_dss_rfbi_hwmod = { ++ .name = "dss_rfbi", ++ .class = &omap54xx_rfbi_hwmod_class, ++ .clkdm_name = "dss_clkdm", ++ .prcm = { ++ .omap4 = { ++ .clkctrl_offs = OMAP54XX_CM_DSS_DSS_CLKCTRL_OFFSET, ++ .flags = HWMOD_OMAP4_NO_CONTEXT_LOSS_BIT, ++ }, ++ }, ++ .opt_clks = dss_rfbi_opt_clks, ++ .opt_clks_cnt = ARRAY_SIZE(dss_rfbi_opt_clks), ++}; ++ ++/* + * 'emif' class + * external memory interface no1 (wrapper) + */ +@@ -352,8 +578,6 @@ static struct omap_hwmod omap54xx_emif1_ + .name = "emif1", + .class = &omap54xx_emif_hwmod_class, + .clkdm_name = "emif_clkdm", +- .flags = HWMOD_INIT_NO_IDLE | HWMOD_INIT_NO_RESET, +- .main_clk = "dpll_core_h11x2_ck", + .prcm = { + .omap4 = { + .clkctrl_offs = OMAP54XX_CM_EMIF_EMIF1_CLKCTRL_OFFSET, +@@ -368,8 +592,6 @@ static struct omap_hwmod omap54xx_emif2_ + .name = "emif2", + .class = &omap54xx_emif_hwmod_class, + .clkdm_name = "emif_clkdm", +- .flags = HWMOD_INIT_NO_IDLE | HWMOD_INIT_NO_RESET, +- .main_clk = "dpll_core_h11x2_ck", + .prcm = { + .omap4 = { + .clkctrl_offs = OMAP54XX_CM_EMIF_EMIF2_CLKCTRL_OFFSET, +@@ -409,15 +631,11 @@ static struct omap_gpio_dev_attr gpio_de + }; + + /* gpio1 */ +-static struct omap_hwmod_opt_clk gpio1_opt_clks[] = { +- { .role = "dbclk", .clk = "gpio1_dbclk" }, +-}; + + static struct omap_hwmod omap54xx_gpio1_hwmod = { + .name = "gpio1", + .class = &omap54xx_gpio_hwmod_class, + .clkdm_name = "wkupaon_clkdm", +- .main_clk = "wkupaon_iclk_mux", + .prcm = { + .omap4 = { + .clkctrl_offs = OMAP54XX_CM_WKUPAON_GPIO1_CLKCTRL_OFFSET, +@@ -425,22 +643,16 @@ static struct omap_hwmod omap54xx_gpio1_ + .modulemode = MODULEMODE_HWCTRL, + }, + }, +- .opt_clks = gpio1_opt_clks, +- .opt_clks_cnt = ARRAY_SIZE(gpio1_opt_clks), + .dev_attr = &gpio_dev_attr, + }; + + /* gpio2 */ +-static struct omap_hwmod_opt_clk gpio2_opt_clks[] = { +- { .role = "dbclk", .clk = "gpio2_dbclk" }, +-}; + + static struct omap_hwmod omap54xx_gpio2_hwmod = { + .name = "gpio2", + .class = &omap54xx_gpio_hwmod_class, + .clkdm_name = "l4per_clkdm", + .flags = HWMOD_CONTROL_OPT_CLKS_IN_RESET, +- .main_clk = "l4_root_clk_div", + .prcm = { + .omap4 = { + .clkctrl_offs = OMAP54XX_CM_L4PER_GPIO2_CLKCTRL_OFFSET, +@@ -448,22 +660,16 @@ static struct omap_hwmod omap54xx_gpio2_ + .modulemode = MODULEMODE_HWCTRL, + }, + }, +- .opt_clks = gpio2_opt_clks, +- .opt_clks_cnt = ARRAY_SIZE(gpio2_opt_clks), + .dev_attr = &gpio_dev_attr, + }; + + /* gpio3 */ +-static struct omap_hwmod_opt_clk gpio3_opt_clks[] = { +- { .role = "dbclk", .clk = "gpio3_dbclk" }, +-}; + + static struct omap_hwmod omap54xx_gpio3_hwmod = { + .name = "gpio3", + .class = &omap54xx_gpio_hwmod_class, + .clkdm_name = "l4per_clkdm", + .flags = HWMOD_CONTROL_OPT_CLKS_IN_RESET, +- .main_clk = "l4_root_clk_div", + .prcm = { + .omap4 = { + .clkctrl_offs = OMAP54XX_CM_L4PER_GPIO3_CLKCTRL_OFFSET, +@@ -471,22 +677,16 @@ static struct omap_hwmod omap54xx_gpio3_ + .modulemode = MODULEMODE_HWCTRL, + }, + }, +- .opt_clks = gpio3_opt_clks, +- .opt_clks_cnt = ARRAY_SIZE(gpio3_opt_clks), + .dev_attr = &gpio_dev_attr, + }; + + /* gpio4 */ +-static struct omap_hwmod_opt_clk gpio4_opt_clks[] = { +- { .role = "dbclk", .clk = "gpio4_dbclk" }, +-}; + + static struct omap_hwmod omap54xx_gpio4_hwmod = { + .name = "gpio4", + .class = &omap54xx_gpio_hwmod_class, + .clkdm_name = "l4per_clkdm", + .flags = HWMOD_CONTROL_OPT_CLKS_IN_RESET, +- .main_clk = "l4_root_clk_div", + .prcm = { + .omap4 = { + .clkctrl_offs = OMAP54XX_CM_L4PER_GPIO4_CLKCTRL_OFFSET, +@@ -494,22 +694,16 @@ static struct omap_hwmod omap54xx_gpio4_ + .modulemode = MODULEMODE_HWCTRL, + }, + }, +- .opt_clks = gpio4_opt_clks, +- .opt_clks_cnt = ARRAY_SIZE(gpio4_opt_clks), + .dev_attr = &gpio_dev_attr, + }; + + /* gpio5 */ +-static struct omap_hwmod_opt_clk gpio5_opt_clks[] = { +- { .role = "dbclk", .clk = "gpio5_dbclk" }, +-}; + + static struct omap_hwmod omap54xx_gpio5_hwmod = { + .name = "gpio5", + .class = &omap54xx_gpio_hwmod_class, + .clkdm_name = "l4per_clkdm", + .flags = HWMOD_CONTROL_OPT_CLKS_IN_RESET, +- .main_clk = "l4_root_clk_div", + .prcm = { + .omap4 = { + .clkctrl_offs = OMAP54XX_CM_L4PER_GPIO5_CLKCTRL_OFFSET, +@@ -517,22 +711,16 @@ static struct omap_hwmod omap54xx_gpio5_ + .modulemode = MODULEMODE_HWCTRL, + }, + }, +- .opt_clks = gpio5_opt_clks, +- .opt_clks_cnt = ARRAY_SIZE(gpio5_opt_clks), + .dev_attr = &gpio_dev_attr, + }; + + /* gpio6 */ +-static struct omap_hwmod_opt_clk gpio6_opt_clks[] = { +- { .role = "dbclk", .clk = "gpio6_dbclk" }, +-}; + + static struct omap_hwmod omap54xx_gpio6_hwmod = { + .name = "gpio6", + .class = &omap54xx_gpio_hwmod_class, + .clkdm_name = "l4per_clkdm", + .flags = HWMOD_CONTROL_OPT_CLKS_IN_RESET, +- .main_clk = "l4_root_clk_div", + .prcm = { + .omap4 = { + .clkctrl_offs = OMAP54XX_CM_L4PER_GPIO6_CLKCTRL_OFFSET, +@@ -540,22 +728,16 @@ static struct omap_hwmod omap54xx_gpio6_ + .modulemode = MODULEMODE_HWCTRL, + }, + }, +- .opt_clks = gpio6_opt_clks, +- .opt_clks_cnt = ARRAY_SIZE(gpio6_opt_clks), + .dev_attr = &gpio_dev_attr, + }; + + /* gpio7 */ +-static struct omap_hwmod_opt_clk gpio7_opt_clks[] = { +- { .role = "dbclk", .clk = "gpio7_dbclk" }, +-}; + + static struct omap_hwmod omap54xx_gpio7_hwmod = { + .name = "gpio7", + .class = &omap54xx_gpio_hwmod_class, + .clkdm_name = "l4per_clkdm", + .flags = HWMOD_CONTROL_OPT_CLKS_IN_RESET, +- .main_clk = "l4_root_clk_div", + .prcm = { + .omap4 = { + .clkctrl_offs = OMAP54XX_CM_L4PER_GPIO7_CLKCTRL_OFFSET, +@@ -563,22 +745,16 @@ static struct omap_hwmod omap54xx_gpio7_ + .modulemode = MODULEMODE_HWCTRL, + }, + }, +- .opt_clks = gpio7_opt_clks, +- .opt_clks_cnt = ARRAY_SIZE(gpio7_opt_clks), + .dev_attr = &gpio_dev_attr, + }; + + /* gpio8 */ +-static struct omap_hwmod_opt_clk gpio8_opt_clks[] = { +- { .role = "dbclk", .clk = "gpio8_dbclk" }, +-}; + + static struct omap_hwmod omap54xx_gpio8_hwmod = { + .name = "gpio8", + .class = &omap54xx_gpio_hwmod_class, + .clkdm_name = "l4per_clkdm", + .flags = HWMOD_CONTROL_OPT_CLKS_IN_RESET, +- .main_clk = "l4_root_clk_div", + .prcm = { + .omap4 = { + .clkctrl_offs = OMAP54XX_CM_L4PER_GPIO8_CLKCTRL_OFFSET, +@@ -586,8 +762,6 @@ static struct omap_hwmod omap54xx_gpio8_ + .modulemode = MODULEMODE_HWCTRL, + }, + }, +- .opt_clks = gpio8_opt_clks, +- .opt_clks_cnt = ARRAY_SIZE(gpio8_opt_clks), + .dev_attr = &gpio_dev_attr, + }; + +@@ -626,7 +800,6 @@ static struct omap_hwmod omap54xx_i2c1_h + .class = &omap54xx_i2c_hwmod_class, + .clkdm_name = "l4per_clkdm", + .flags = HWMOD_16BIT_REG | HWMOD_SET_DEFAULT_CLOCKACT, +- .main_clk = "func_96m_fclk", + .prcm = { + .omap4 = { + .clkctrl_offs = OMAP54XX_CM_L4PER_I2C1_CLKCTRL_OFFSET, +@@ -643,7 +816,6 @@ static struct omap_hwmod omap54xx_i2c2_h + .class = &omap54xx_i2c_hwmod_class, + .clkdm_name = "l4per_clkdm", + .flags = HWMOD_16BIT_REG | HWMOD_SET_DEFAULT_CLOCKACT, +- .main_clk = "func_96m_fclk", + .prcm = { + .omap4 = { + .clkctrl_offs = OMAP54XX_CM_L4PER_I2C2_CLKCTRL_OFFSET, +@@ -660,7 +832,6 @@ static struct omap_hwmod omap54xx_i2c3_h + .class = &omap54xx_i2c_hwmod_class, + .clkdm_name = "l4per_clkdm", + .flags = HWMOD_16BIT_REG | HWMOD_SET_DEFAULT_CLOCKACT, +- .main_clk = "func_96m_fclk", + .prcm = { + .omap4 = { + .clkctrl_offs = OMAP54XX_CM_L4PER_I2C3_CLKCTRL_OFFSET, +@@ -677,7 +848,6 @@ static struct omap_hwmod omap54xx_i2c4_h + .class = &omap54xx_i2c_hwmod_class, + .clkdm_name = "l4per_clkdm", + .flags = HWMOD_16BIT_REG | HWMOD_SET_DEFAULT_CLOCKACT, +- .main_clk = "func_96m_fclk", + .prcm = { + .omap4 = { + .clkctrl_offs = OMAP54XX_CM_L4PER_I2C4_CLKCTRL_OFFSET, +@@ -694,7 +864,6 @@ static struct omap_hwmod omap54xx_i2c5_h + .class = &omap54xx_i2c_hwmod_class, + .clkdm_name = "l4per_clkdm", + .flags = HWMOD_16BIT_REG | HWMOD_SET_DEFAULT_CLOCKACT, +- .main_clk = "func_96m_fclk", + .prcm = { + .omap4 = { + .clkctrl_offs = OMAP54XX_CM_L4PER_I2C5_CLKCTRL_OFFSET, +@@ -729,7 +898,6 @@ static struct omap_hwmod omap54xx_kbd_hw + .name = "kbd", + .class = &omap54xx_kbd_hwmod_class, + .clkdm_name = "wkupaon_clkdm", +- .main_clk = "sys_32k_ck", + .prcm = { + .omap4 = { + .clkctrl_offs = OMAP54XX_CM_WKUPAON_KBD_CLKCTRL_OFFSET, +@@ -792,16 +960,11 @@ static struct omap_hwmod_class omap54xx_ + }; + + /* mcbsp1 */ +-static struct omap_hwmod_opt_clk mcbsp1_opt_clks[] = { +- { .role = "pad_fck", .clk = "pad_clks_ck" }, +- { .role = "prcm_fck", .clk = "mcbsp1_sync_mux_ck" }, +-}; + + static struct omap_hwmod omap54xx_mcbsp1_hwmod = { + .name = "mcbsp1", + .class = &omap54xx_mcbsp_hwmod_class, + .clkdm_name = "abe_clkdm", +- .main_clk = "mcbsp1_gfclk", + .prcm = { + .omap4 = { + .clkctrl_offs = OMAP54XX_CM_ABE_MCBSP1_CLKCTRL_OFFSET, +@@ -809,21 +972,14 @@ static struct omap_hwmod omap54xx_mcbsp1 + .modulemode = MODULEMODE_SWCTRL, + }, + }, +- .opt_clks = mcbsp1_opt_clks, +- .opt_clks_cnt = ARRAY_SIZE(mcbsp1_opt_clks), + }; + + /* mcbsp2 */ +-static struct omap_hwmod_opt_clk mcbsp2_opt_clks[] = { +- { .role = "pad_fck", .clk = "pad_clks_ck" }, +- { .role = "prcm_fck", .clk = "mcbsp2_sync_mux_ck" }, +-}; + + static struct omap_hwmod omap54xx_mcbsp2_hwmod = { + .name = "mcbsp2", + .class = &omap54xx_mcbsp_hwmod_class, + .clkdm_name = "abe_clkdm", +- .main_clk = "mcbsp2_gfclk", + .prcm = { + .omap4 = { + .clkctrl_offs = OMAP54XX_CM_ABE_MCBSP2_CLKCTRL_OFFSET, +@@ -831,21 +987,14 @@ static struct omap_hwmod omap54xx_mcbsp2 + .modulemode = MODULEMODE_SWCTRL, + }, + }, +- .opt_clks = mcbsp2_opt_clks, +- .opt_clks_cnt = ARRAY_SIZE(mcbsp2_opt_clks), + }; + + /* mcbsp3 */ +-static struct omap_hwmod_opt_clk mcbsp3_opt_clks[] = { +- { .role = "pad_fck", .clk = "pad_clks_ck" }, +- { .role = "prcm_fck", .clk = "mcbsp3_sync_mux_ck" }, +-}; + + static struct omap_hwmod omap54xx_mcbsp3_hwmod = { + .name = "mcbsp3", + .class = &omap54xx_mcbsp_hwmod_class, + .clkdm_name = "abe_clkdm", +- .main_clk = "mcbsp3_gfclk", + .prcm = { + .omap4 = { + .clkctrl_offs = OMAP54XX_CM_ABE_MCBSP3_CLKCTRL_OFFSET, +@@ -853,8 +1002,6 @@ static struct omap_hwmod omap54xx_mcbsp3 + .modulemode = MODULEMODE_SWCTRL, + }, + }, +- .opt_clks = mcbsp3_opt_clks, +- .opt_clks_cnt = ARRAY_SIZE(mcbsp3_opt_clks), + }; + + /* +@@ -896,7 +1043,6 @@ static struct omap_hwmod omap54xx_mcpdm_ + */ + + .flags = HWMOD_EXT_OPT_MAIN_CLK, +- .main_clk = "pad_clks_ck", + .prcm = { + .omap4 = { + .clkctrl_offs = OMAP54XX_CM_ABE_MCPDM_CLKCTRL_OFFSET, +@@ -938,7 +1084,6 @@ static struct omap_hwmod omap54xx_mcspi1 + .name = "mcspi1", + .class = &omap54xx_mcspi_hwmod_class, + .clkdm_name = "l4per_clkdm", +- .main_clk = "func_48m_fclk", + .prcm = { + .omap4 = { + .clkctrl_offs = OMAP54XX_CM_L4PER_MCSPI1_CLKCTRL_OFFSET, +@@ -959,7 +1104,6 @@ static struct omap_hwmod omap54xx_mcspi2 + .name = "mcspi2", + .class = &omap54xx_mcspi_hwmod_class, + .clkdm_name = "l4per_clkdm", +- .main_clk = "func_48m_fclk", + .prcm = { + .omap4 = { + .clkctrl_offs = OMAP54XX_CM_L4PER_MCSPI2_CLKCTRL_OFFSET, +@@ -980,7 +1124,6 @@ static struct omap_hwmod omap54xx_mcspi3 + .name = "mcspi3", + .class = &omap54xx_mcspi_hwmod_class, + .clkdm_name = "l4per_clkdm", +- .main_clk = "func_48m_fclk", + .prcm = { + .omap4 = { + .clkctrl_offs = OMAP54XX_CM_L4PER_MCSPI3_CLKCTRL_OFFSET, +@@ -1001,7 +1144,6 @@ static struct omap_hwmod omap54xx_mcspi4 + .name = "mcspi4", + .class = &omap54xx_mcspi_hwmod_class, + .clkdm_name = "l4per_clkdm", +- .main_clk = "func_48m_fclk", + .prcm = { + .omap4 = { + .clkctrl_offs = OMAP54XX_CM_L4PER_MCSPI4_CLKCTRL_OFFSET, +@@ -1035,9 +1177,6 @@ static struct omap_hwmod_class omap54xx_ + }; + + /* mmc1 */ +-static struct omap_hwmod_opt_clk mmc1_opt_clks[] = { +- { .role = "32khz_clk", .clk = "mmc1_32khz_clk" }, +-}; + + /* mmc1 dev_attr */ + static struct omap_mmc_dev_attr mmc1_dev_attr = { +@@ -1048,7 +1187,6 @@ static struct omap_hwmod omap54xx_mmc1_h + .name = "mmc1", + .class = &omap54xx_mmc_hwmod_class, + .clkdm_name = "l3init_clkdm", +- .main_clk = "mmc1_fclk", + .prcm = { + .omap4 = { + .clkctrl_offs = OMAP54XX_CM_L3INIT_MMC1_CLKCTRL_OFFSET, +@@ -1056,8 +1194,6 @@ static struct omap_hwmod omap54xx_mmc1_h + .modulemode = MODULEMODE_SWCTRL, + }, + }, +- .opt_clks = mmc1_opt_clks, +- .opt_clks_cnt = ARRAY_SIZE(mmc1_opt_clks), + .dev_attr = &mmc1_dev_attr, + }; + +@@ -1066,7 +1202,6 @@ static struct omap_hwmod omap54xx_mmc2_h + .name = "mmc2", + .class = &omap54xx_mmc_hwmod_class, + .clkdm_name = "l3init_clkdm", +- .main_clk = "mmc2_fclk", + .prcm = { + .omap4 = { + .clkctrl_offs = OMAP54XX_CM_L3INIT_MMC2_CLKCTRL_OFFSET, +@@ -1081,7 +1216,6 @@ static struct omap_hwmod omap54xx_mmc3_h + .name = "mmc3", + .class = &omap54xx_mmc_hwmod_class, + .clkdm_name = "l4per_clkdm", +- .main_clk = "func_48m_fclk", + .prcm = { + .omap4 = { + .clkctrl_offs = OMAP54XX_CM_L4PER_MMC3_CLKCTRL_OFFSET, +@@ -1096,7 +1230,6 @@ static struct omap_hwmod omap54xx_mmc4_h + .name = "mmc4", + .class = &omap54xx_mmc_hwmod_class, + .clkdm_name = "l4per_clkdm", +- .main_clk = "func_48m_fclk", + .prcm = { + .omap4 = { + .clkctrl_offs = OMAP54XX_CM_L4PER_MMC4_CLKCTRL_OFFSET, +@@ -1111,7 +1244,6 @@ static struct omap_hwmod omap54xx_mmc5_h + .name = "mmc5", + .class = &omap54xx_mmc_hwmod_class, + .clkdm_name = "l4per_clkdm", +- .main_clk = "func_96m_fclk", + .prcm = { + .omap4 = { + .clkctrl_offs = OMAP54XX_CM_L4PER_MMC5_CLKCTRL_OFFSET, +@@ -1135,7 +1267,7 @@ static struct omap_hwmod omap54xx_mpu_hw + .name = "mpu", + .class = &omap54xx_mpu_hwmod_class, + .clkdm_name = "mpu_clkdm", +- .flags = HWMOD_INIT_NO_IDLE | HWMOD_INIT_NO_RESET, ++ .flags = HWMOD_INIT_NO_IDLE, + .main_clk = "dpll_mpu_m2_ck", + .prcm = { + .omap4 = { +@@ -1146,6 +1278,42 @@ static struct omap_hwmod omap54xx_mpu_hw + }; + + /* ++ * 'ocp2scp' class ++ * bridge to transform ocp interface protocol to scp (serial control port) ++ * protocol ++ */ ++ ++static struct omap_hwmod_class_sysconfig omap54xx_ocp2scp_sysc = { ++ .rev_offs = 0x0000, ++ .sysc_offs = 0x0010, ++ .syss_offs = 0x0014, ++ .sysc_flags = (SYSC_HAS_AUTOIDLE | SYSC_HAS_SIDLEMODE | ++ SYSC_HAS_SOFTRESET | SYSS_HAS_RESET_STATUS), ++ .idlemodes = (SIDLE_FORCE | SIDLE_NO | SIDLE_SMART), ++ .sysc_fields = &omap_hwmod_sysc_type1, ++}; ++ ++static struct omap_hwmod_class omap54xx_ocp2scp_hwmod_class = { ++ .name = "ocp2scp", ++ .sysc = &omap54xx_ocp2scp_sysc, ++}; ++ ++/* ocp2scp1 */ ++static struct omap_hwmod omap54xx_ocp2scp1_hwmod = { ++ .name = "ocp2scp1", ++ .class = &omap54xx_ocp2scp_hwmod_class, ++ .clkdm_name = "l3init_clkdm", ++ .main_clk = "l4_root_clk_div", ++ .prcm = { ++ .omap4 = { ++ .clkctrl_offs = OMAP54XX_CM_L3INIT_OCP2SCP1_CLKCTRL_OFFSET, ++ .context_offs = OMAP54XX_RM_L3INIT_OCP2SCP1_CONTEXT_OFFSET, ++ .modulemode = MODULEMODE_HWCTRL, ++ }, ++ }, ++}; ++ ++/* + * 'timer' class + * general purpose timer module with accurate 1ms tick + * This class contains several variants: ['timer_1ms', 'timer'] +@@ -1187,7 +1355,6 @@ static struct omap_hwmod omap54xx_timer1 + .name = "timer1", + .class = &omap54xx_timer_1ms_hwmod_class, + .clkdm_name = "wkupaon_clkdm", +- .main_clk = "timer1_gfclk_mux", + .flags = HWMOD_SET_DEFAULT_CLOCKACT, + .prcm = { + .omap4 = { +@@ -1203,7 +1370,6 @@ static struct omap_hwmod omap54xx_timer2 + .name = "timer2", + .class = &omap54xx_timer_1ms_hwmod_class, + .clkdm_name = "l4per_clkdm", +- .main_clk = "timer2_gfclk_mux", + .flags = HWMOD_SET_DEFAULT_CLOCKACT, + .prcm = { + .omap4 = { +@@ -1219,7 +1385,6 @@ static struct omap_hwmod omap54xx_timer3 + .name = "timer3", + .class = &omap54xx_timer_hwmod_class, + .clkdm_name = "l4per_clkdm", +- .main_clk = "timer3_gfclk_mux", + .prcm = { + .omap4 = { + .clkctrl_offs = OMAP54XX_CM_L4PER_TIMER3_CLKCTRL_OFFSET, +@@ -1234,7 +1399,6 @@ static struct omap_hwmod omap54xx_timer4 + .name = "timer4", + .class = &omap54xx_timer_hwmod_class, + .clkdm_name = "l4per_clkdm", +- .main_clk = "timer4_gfclk_mux", + .prcm = { + .omap4 = { + .clkctrl_offs = OMAP54XX_CM_L4PER_TIMER4_CLKCTRL_OFFSET, +@@ -1249,7 +1413,6 @@ static struct omap_hwmod omap54xx_timer5 + .name = "timer5", + .class = &omap54xx_timer_hwmod_class, + .clkdm_name = "abe_clkdm", +- .main_clk = "timer5_gfclk_mux", + .prcm = { + .omap4 = { + .clkctrl_offs = OMAP54XX_CM_ABE_TIMER5_CLKCTRL_OFFSET, +@@ -1264,7 +1427,6 @@ static struct omap_hwmod omap54xx_timer6 + .name = "timer6", + .class = &omap54xx_timer_hwmod_class, + .clkdm_name = "abe_clkdm", +- .main_clk = "timer6_gfclk_mux", + .prcm = { + .omap4 = { + .clkctrl_offs = OMAP54XX_CM_ABE_TIMER6_CLKCTRL_OFFSET, +@@ -1279,7 +1441,6 @@ static struct omap_hwmod omap54xx_timer7 + .name = "timer7", + .class = &omap54xx_timer_hwmod_class, + .clkdm_name = "abe_clkdm", +- .main_clk = "timer7_gfclk_mux", + .prcm = { + .omap4 = { + .clkctrl_offs = OMAP54XX_CM_ABE_TIMER7_CLKCTRL_OFFSET, +@@ -1294,7 +1455,6 @@ static struct omap_hwmod omap54xx_timer8 + .name = "timer8", + .class = &omap54xx_timer_hwmod_class, + .clkdm_name = "abe_clkdm", +- .main_clk = "timer8_gfclk_mux", + .prcm = { + .omap4 = { + .clkctrl_offs = OMAP54XX_CM_ABE_TIMER8_CLKCTRL_OFFSET, +@@ -1309,7 +1469,6 @@ static struct omap_hwmod omap54xx_timer9 + .name = "timer9", + .class = &omap54xx_timer_hwmod_class, + .clkdm_name = "l4per_clkdm", +- .main_clk = "timer9_gfclk_mux", + .prcm = { + .omap4 = { + .clkctrl_offs = OMAP54XX_CM_L4PER_TIMER9_CLKCTRL_OFFSET, +@@ -1324,7 +1483,6 @@ static struct omap_hwmod omap54xx_timer1 + .name = "timer10", + .class = &omap54xx_timer_1ms_hwmod_class, + .clkdm_name = "l4per_clkdm", +- .main_clk = "timer10_gfclk_mux", + .flags = HWMOD_SET_DEFAULT_CLOCKACT, + .prcm = { + .omap4 = { +@@ -1340,7 +1498,6 @@ static struct omap_hwmod omap54xx_timer1 + .name = "timer11", + .class = &omap54xx_timer_hwmod_class, + .clkdm_name = "l4per_clkdm", +- .main_clk = "timer11_gfclk_mux", + .prcm = { + .omap4 = { + .clkctrl_offs = OMAP54XX_CM_L4PER_TIMER11_CLKCTRL_OFFSET, +@@ -1377,7 +1534,6 @@ static struct omap_hwmod omap54xx_uart1_ + .name = "uart1", + .class = &omap54xx_uart_hwmod_class, + .clkdm_name = "l4per_clkdm", +- .main_clk = "func_48m_fclk", + .prcm = { + .omap4 = { + .clkctrl_offs = OMAP54XX_CM_L4PER_UART1_CLKCTRL_OFFSET, +@@ -1392,7 +1548,6 @@ static struct omap_hwmod omap54xx_uart2_ + .name = "uart2", + .class = &omap54xx_uart_hwmod_class, + .clkdm_name = "l4per_clkdm", +- .main_clk = "func_48m_fclk", + .prcm = { + .omap4 = { + .clkctrl_offs = OMAP54XX_CM_L4PER_UART2_CLKCTRL_OFFSET, +@@ -1408,7 +1563,6 @@ static struct omap_hwmod omap54xx_uart3_ + .class = &omap54xx_uart_hwmod_class, + .clkdm_name = "l4per_clkdm", + .flags = DEBUG_OMAP4UART3_FLAGS, +- .main_clk = "func_48m_fclk", + .prcm = { + .omap4 = { + .clkctrl_offs = OMAP54XX_CM_L4PER_UART3_CLKCTRL_OFFSET, +@@ -1424,7 +1578,6 @@ static struct omap_hwmod omap54xx_uart4_ + .class = &omap54xx_uart_hwmod_class, + .clkdm_name = "l4per_clkdm", + .flags = DEBUG_OMAP4UART4_FLAGS, +- .main_clk = "func_48m_fclk", + .prcm = { + .omap4 = { + .clkctrl_offs = OMAP54XX_CM_L4PER_UART4_CLKCTRL_OFFSET, +@@ -1439,7 +1592,6 @@ static struct omap_hwmod omap54xx_uart5_ + .name = "uart5", + .class = &omap54xx_uart_hwmod_class, + .clkdm_name = "l4per_clkdm", +- .main_clk = "func_48m_fclk", + .prcm = { + .omap4 = { + .clkctrl_offs = OMAP54XX_CM_L4PER_UART5_CLKCTRL_OFFSET, +@@ -1454,7 +1606,6 @@ static struct omap_hwmod omap54xx_uart6_ + .name = "uart6", + .class = &omap54xx_uart_hwmod_class, + .clkdm_name = "l4per_clkdm", +- .main_clk = "func_48m_fclk", + .prcm = { + .omap4 = { + .clkctrl_offs = OMAP54XX_CM_L4PER_UART6_CLKCTRL_OFFSET, +@@ -1465,6 +1616,145 @@ static struct omap_hwmod omap54xx_uart6_ + }; + + /* ++ * 'usb_host_hs' class ++ * high-speed multi-port usb host controller ++ */ ++ ++static struct omap_hwmod_class_sysconfig omap54xx_usb_host_hs_sysc = { ++ .rev_offs = 0x0000, ++ .sysc_offs = 0x0010, ++ .sysc_flags = (SYSC_HAS_MIDLEMODE | SYSC_HAS_RESET_STATUS | ++ SYSC_HAS_SIDLEMODE | SYSC_HAS_SOFTRESET), ++ .idlemodes = (SIDLE_FORCE | SIDLE_NO | SIDLE_SMART | ++ SIDLE_SMART_WKUP | MSTANDBY_FORCE | MSTANDBY_NO | ++ MSTANDBY_SMART | MSTANDBY_SMART_WKUP), ++ .sysc_fields = &omap_hwmod_sysc_type2, ++}; ++ ++static struct omap_hwmod_class omap54xx_usb_host_hs_hwmod_class = { ++ .name = "usb_host_hs", ++ .sysc = &omap54xx_usb_host_hs_sysc, ++}; ++ ++static struct omap_hwmod_opt_clk usb_host_hs_opt_clks[] = { ++ { .role = "hsic60m_p2_clk", .clk = "usb_host_hs_hsic60m_p2_clk" }, ++ { .role = "hsic60m_p3_clk", .clk = "usb_host_hs_hsic60m_p3_clk" }, ++ { .role = "utmi_p1_clk", .clk = "usb_host_hs_utmi_p1_clk" }, ++ { .role = "utmi_p2_clk", .clk = "usb_host_hs_utmi_p2_clk" }, ++ { .role = "utmi_p3_clk", .clk = "usb_host_hs_utmi_p3_clk" }, ++ { .role = "hsic480m_p1_clk", .clk = "usb_host_hs_hsic480m_p1_clk" }, ++ { .role = "hsic60m_p1_clk", .clk = "usb_host_hs_hsic60m_p1_clk" }, ++ { .role = "hsic480m_p3_clk", .clk = "usb_host_hs_hsic480m_p3_clk" }, ++ { .role = "hsic480m_p2_clk", .clk = "usb_host_hs_hsic480m_p2_clk" }, ++}; ++ ++static struct omap_hwmod omap54xx_usb_host_hs_hwmod = { ++ .name = "usb_host_hs", ++ .class = &omap54xx_usb_host_hs_hwmod_class, ++ .clkdm_name = "l3init_clkdm", ++ /* ++ * Errata: USBHOST Configured In Smart-Idle Can Lead To a Deadlock ++ * id: i660 ++ * ++ * Description: ++ * In the following configuration : ++ * - USBHOST module is set to smart-idle mode ++ * - PRCM asserts idle_req to the USBHOST module ( This typically ++ * happens when the system is going to a low power mode : all ports ++ * have been suspended, the master part of the USBHOST module has ++ * entered the standby state, and SW has cut the functional clocks) ++ * - an USBHOST interrupt occurs before the module is able to answer ++ * idle_ack, typically a remote wakeup IRQ. ++ * Then the USB HOST module will enter a deadlock situation where it ++ * is no more accessible nor functional. ++ * ++ * Workaround: ++ * Don't use smart idle; use only force idle, hence HWMOD_SWSUP_SIDLE ++ */ ++ ++ /* ++ * Errata: USB host EHCI may stall when entering smart-standby mode ++ * Id: i571 ++ * ++ * Description: ++ * When the USBHOST module is set to smart-standby mode, and when it is ++ * ready to enter the standby state (i.e. all ports are suspended and ++ * all attached devices are in suspend mode), then it can wrongly assert ++ * the Mstandby signal too early while there are still some residual OCP ++ * transactions ongoing. If this condition occurs, the internal state ++ * machine may go to an undefined state and the USB link may be stuck ++ * upon the next resume. ++ * ++ * Workaround: ++ * Don't use smart standby; use only force standby, ++ * hence HWMOD_SWSUP_MSTANDBY ++ */ ++ ++ /* ++ * During system boot; If the hwmod framework resets the module ++ * the module will have smart idle settings; which can lead to deadlock ++ * (above Errata Id:i660); so, dont reset the module during boot; ++ * Use HWMOD_INIT_NO_RESET. ++ */ ++ ++ .flags = HWMOD_SWSUP_SIDLE | HWMOD_SWSUP_MSTANDBY | ++ HWMOD_INIT_NO_RESET, ++ .main_clk = "l3init_60m_fclk", ++ .prcm = { ++ .omap4 = { ++ .clkctrl_offs = OMAP54XX_CM_L3INIT_USB_HOST_HS_CLKCTRL_OFFSET, ++ .context_offs = OMAP54XX_RM_L3INIT_USB_HOST_HS_CONTEXT_OFFSET, ++ .modulemode = MODULEMODE_SWCTRL, ++ }, ++ }, ++ .opt_clks = usb_host_hs_opt_clks, ++ .opt_clks_cnt = ARRAY_SIZE(usb_host_hs_opt_clks), ++}; ++ ++/* ++ * 'usb_tll_hs' class ++ * usb_tll_hs module is the adapter on the usb_host_hs ports ++ */ ++ ++static struct omap_hwmod_class_sysconfig omap54xx_usb_tll_hs_sysc = { ++ .rev_offs = 0x0000, ++ .sysc_offs = 0x0010, ++ .syss_offs = 0x0014, ++ .sysc_flags = (SYSC_HAS_AUTOIDLE | SYSC_HAS_CLOCKACTIVITY | ++ SYSC_HAS_ENAWAKEUP | SYSC_HAS_SIDLEMODE | ++ SYSC_HAS_SOFTRESET | SYSS_HAS_RESET_STATUS), ++ .idlemodes = (SIDLE_FORCE | SIDLE_NO | SIDLE_SMART), ++ .sysc_fields = &omap_hwmod_sysc_type1, ++}; ++ ++static struct omap_hwmod_class omap54xx_usb_tll_hs_hwmod_class = { ++ .name = "usb_tll_hs", ++ .sysc = &omap54xx_usb_tll_hs_sysc, ++}; ++ ++static struct omap_hwmod_opt_clk usb_tll_hs_opt_clks[] = { ++ { .role = "usb_ch2_clk", .clk = "usb_tll_hs_usb_ch2_clk" }, ++ { .role = "usb_ch0_clk", .clk = "usb_tll_hs_usb_ch0_clk" }, ++ { .role = "usb_ch1_clk", .clk = "usb_tll_hs_usb_ch1_clk" }, ++}; ++ ++static struct omap_hwmod omap54xx_usb_tll_hs_hwmod = { ++ .name = "usb_tll_hs", ++ .class = &omap54xx_usb_tll_hs_hwmod_class, ++ .clkdm_name = "l3init_clkdm", ++ .main_clk = "l4_root_clk_div", ++ .prcm = { ++ .omap4 = { ++ .clkctrl_offs = OMAP54XX_CM_L3INIT_USB_TLL_HS_CLKCTRL_OFFSET, ++ .context_offs = OMAP54XX_RM_L3INIT_USB_TLL_HS_CONTEXT_OFFSET, ++ .modulemode = MODULEMODE_HWCTRL, ++ }, ++ }, ++ .opt_clks = usb_tll_hs_opt_clks, ++ .opt_clks_cnt = ARRAY_SIZE(usb_tll_hs_opt_clks), ++}; ++ ++/* + * 'usb_otg_ss' class + * 2.0 super speed (usb_otg_ss) controller + */ +@@ -1486,16 +1776,12 @@ static struct omap_hwmod_class omap54xx_ + }; + + /* usb_otg_ss */ +-static struct omap_hwmod_opt_clk usb_otg_ss_opt_clks[] = { +- { .role = "refclk960m", .clk = "usb_otg_ss_refclk960m" }, +-}; + + static struct omap_hwmod omap54xx_usb_otg_ss_hwmod = { + .name = "usb_otg_ss", + .class = &omap54xx_usb_otg_ss_hwmod_class, + .clkdm_name = "l3init_clkdm", + .flags = HWMOD_SWSUP_SIDLE, +- .main_clk = "dpll_core_h13x2_ck", + .prcm = { + .omap4 = { + .clkctrl_offs = OMAP54XX_CM_L3INIT_USB_OTG_SS_CLKCTRL_OFFSET, +@@ -1503,8 +1789,6 @@ static struct omap_hwmod omap54xx_usb_ot + .modulemode = MODULEMODE_HWCTRL, + }, + }, +- .opt_clks = usb_otg_ss_opt_clks, +- .opt_clks_cnt = ARRAY_SIZE(usb_otg_ss_opt_clks), + }; + + /* +@@ -1535,7 +1819,6 @@ static struct omap_hwmod omap54xx_wd_tim + .name = "wd_timer2", + .class = &omap54xx_wd_timer_hwmod_class, + .clkdm_name = "wkupaon_clkdm", +- .main_clk = "sys_32k_ck", + .prcm = { + .omap4 = { + .clkctrl_offs = OMAP54XX_CM_WKUPAON_WD_TIMER2_CLKCTRL_OFFSET, +@@ -1545,6 +1828,76 @@ static struct omap_hwmod omap54xx_wd_tim + }, + }; + ++/* ++ * 'ocp2scp' class ++ * bridge to transform ocp interface protocol to scp (serial control port) ++ * protocol ++ */ ++/* ocp2scp3 */ ++static struct omap_hwmod omap54xx_ocp2scp3_hwmod; ++/* l4_cfg -> ocp2scp3 */ ++static struct omap_hwmod_ocp_if omap54xx_l4_cfg__ocp2scp3 = { ++ .master = &omap54xx_l4_cfg_hwmod, ++ .slave = &omap54xx_ocp2scp3_hwmod, ++ .clk = "l4_root_clk_div", ++ .user = OCP_USER_MPU | OCP_USER_SDMA, ++}; ++ ++static struct omap_hwmod omap54xx_ocp2scp3_hwmod = { ++ .name = "ocp2scp3", ++ .class = &omap54xx_ocp2scp_hwmod_class, ++ .clkdm_name = "l3init_clkdm", ++ .prcm = { ++ .omap4 = { ++ .clkctrl_offs = OMAP54XX_CM_L3INIT_OCP2SCP3_CLKCTRL_OFFSET, ++ .context_offs = OMAP54XX_RM_L3INIT_OCP2SCP3_CONTEXT_OFFSET, ++ .modulemode = MODULEMODE_HWCTRL, ++ }, ++ }, ++}; ++ ++/* ++ * 'sata' class ++ * sata: serial ata interface gen2 compliant ( 1 rx/ 1 tx) ++ */ ++ ++static struct omap_hwmod_class_sysconfig omap54xx_sata_sysc = { ++ .sysc_offs = 0x0000, ++ .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 omap54xx_sata_hwmod_class = { ++ .name = "sata", ++ .sysc = &omap54xx_sata_sysc, ++}; ++ ++/* sata */ ++static struct omap_hwmod omap54xx_sata_hwmod = { ++ .name = "sata", ++ .class = &omap54xx_sata_hwmod_class, ++ .clkdm_name = "l3init_clkdm", ++ .flags = HWMOD_SWSUP_SIDLE | HWMOD_SWSUP_MSTANDBY, ++ .main_clk = "func_48m_fclk", ++ .prcm = { ++ .omap4 = { ++ .clkctrl_offs = OMAP54XX_CM_L3INIT_SATA_CLKCTRL_OFFSET, ++ .context_offs = OMAP54XX_RM_L3INIT_SATA_CONTEXT_OFFSET, ++ .modulemode = MODULEMODE_SWCTRL, ++ }, ++ }, ++}; ++ ++/* l4_cfg -> sata */ ++static struct omap_hwmod_ocp_if omap54xx_l4_cfg__sata = { ++ .master = &omap54xx_l4_cfg_hwmod, ++ .slave = &omap54xx_sata_hwmod, ++ .clk = "l3_iclk_div", ++ .user = OCP_USER_MPU | OCP_USER_SDMA, ++}; + + /* + * Interfaces +@@ -1712,6 +2065,54 @@ static struct omap_hwmod_ocp_if omap54xx + .user = OCP_USER_MPU, + }; + ++/* l3_main_2 -> dss */ ++static struct omap_hwmod_ocp_if omap54xx_l3_main_2__dss = { ++ .master = &omap54xx_l3_main_2_hwmod, ++ .slave = &omap54xx_dss_hwmod, ++ .clk = "l3_iclk_div", ++ .user = OCP_USER_MPU | OCP_USER_SDMA, ++}; ++ ++/* l3_main_2 -> dss_dispc */ ++static struct omap_hwmod_ocp_if omap54xx_l3_main_2__dss_dispc = { ++ .master = &omap54xx_l3_main_2_hwmod, ++ .slave = &omap54xx_dss_dispc_hwmod, ++ .clk = "l3_iclk_div", ++ .user = OCP_USER_MPU | OCP_USER_SDMA, ++}; ++ ++/* l3_main_2 -> dss_dsi1_a */ ++static struct omap_hwmod_ocp_if omap54xx_l3_main_2__dss_dsi1_a = { ++ .master = &omap54xx_l3_main_2_hwmod, ++ .slave = &omap54xx_dss_dsi1_a_hwmod, ++ .clk = "l3_iclk_div", ++ .user = OCP_USER_MPU | OCP_USER_SDMA, ++}; ++ ++/* l3_main_2 -> dss_dsi1_c */ ++static struct omap_hwmod_ocp_if omap54xx_l3_main_2__dss_dsi1_c = { ++ .master = &omap54xx_l3_main_2_hwmod, ++ .slave = &omap54xx_dss_dsi1_c_hwmod, ++ .clk = "l3_iclk_div", ++ .user = OCP_USER_MPU | OCP_USER_SDMA, ++}; ++ ++/* l3_main_2 -> dss_hdmi */ ++static struct omap_hwmod_ocp_if omap54xx_l3_main_2__dss_hdmi = { ++ .master = &omap54xx_l3_main_2_hwmod, ++ .slave = &omap54xx_dss_hdmi_hwmod, ++ .clk = "l3_iclk_div", ++ .user = OCP_USER_MPU | OCP_USER_SDMA, ++}; ++ ++/* l3_main_2 -> dss_rfbi */ ++static struct omap_hwmod_ocp_if omap54xx_l3_main_2__dss_rfbi = { ++ .master = &omap54xx_l3_main_2_hwmod, ++ .slave = &omap54xx_dss_rfbi_hwmod, ++ .clk = "l3_iclk_div", ++ .user = OCP_USER_MPU | OCP_USER_SDMA, ++}; ++ + /* mpu -> emif1 */ + static struct omap_hwmod_ocp_if omap54xx_mpu__emif1 = { + .master = &omap54xx_mpu_hwmod, +@@ -1960,6 +2361,14 @@ static struct omap_hwmod_ocp_if omap54xx + .user = OCP_USER_MPU | OCP_USER_SDMA, + }; + ++/* l4_cfg -> ocp2scp1 */ ++static struct omap_hwmod_ocp_if omap54xx_l4_cfg__ocp2scp1 = { ++ .master = &omap54xx_l4_cfg_hwmod, ++ .slave = &omap54xx_ocp2scp1_hwmod, ++ .clk = "l4_root_clk_div", ++ .user = OCP_USER_MPU | OCP_USER_SDMA, ++}; ++ + /* l4_wkup -> timer1 */ + static struct omap_hwmod_ocp_if omap54xx_l4_wkup__timer1 = { + .master = &omap54xx_l4_wkup_hwmod, +@@ -2096,6 +2505,22 @@ static struct omap_hwmod_ocp_if omap54xx + .user = OCP_USER_MPU | OCP_USER_SDMA, + }; + ++/* l4_cfg -> usb_host_hs */ ++static struct omap_hwmod_ocp_if omap54xx_l4_cfg__usb_host_hs = { ++ .master = &omap54xx_l4_cfg_hwmod, ++ .slave = &omap54xx_usb_host_hs_hwmod, ++ .clk = "l3_iclk_div", ++ .user = OCP_USER_MPU | OCP_USER_SDMA, ++}; ++ ++/* l4_cfg -> usb_tll_hs */ ++static struct omap_hwmod_ocp_if omap54xx_l4_cfg__usb_tll_hs = { ++ .master = &omap54xx_l4_cfg_hwmod, ++ .slave = &omap54xx_usb_tll_hs_hwmod, ++ .clk = "l4_root_clk_div", ++ .user = OCP_USER_MPU | OCP_USER_SDMA, ++}; ++ + /* l4_cfg -> usb_otg_ss */ + static struct omap_hwmod_ocp_if omap54xx_l4_cfg__usb_otg_ss = { + .master = &omap54xx_l4_cfg_hwmod, +@@ -2132,6 +2557,12 @@ static struct omap_hwmod_ocp_if *omap54x + &omap54xx_l4_wkup__counter_32k, + &omap54xx_l4_cfg__dma_system, + &omap54xx_l4_abe__dmic, ++ &omap54xx_l3_main_2__dss, ++ &omap54xx_l3_main_2__dss_dispc, ++ &omap54xx_l3_main_2__dss_dsi1_a, ++ &omap54xx_l3_main_2__dss_dsi1_c, ++ &omap54xx_l3_main_2__dss_hdmi, ++ &omap54xx_l3_main_2__dss_rfbi, + &omap54xx_mpu__emif1, + &omap54xx_mpu__emif2, + &omap54xx_l4_wkup__gpio1, +@@ -2163,6 +2594,7 @@ static struct omap_hwmod_ocp_if *omap54x + &omap54xx_l4_per__mmc4, + &omap54xx_l4_per__mmc5, + &omap54xx_l4_cfg__mpu, ++ &omap54xx_l4_cfg__ocp2scp1, + &omap54xx_l4_wkup__timer1, + &omap54xx_l4_per__timer2, + &omap54xx_l4_per__timer3, +@@ -2180,8 +2612,12 @@ static struct omap_hwmod_ocp_if *omap54x + &omap54xx_l4_per__uart4, + &omap54xx_l4_per__uart5, + &omap54xx_l4_per__uart6, ++ &omap54xx_l4_cfg__usb_host_hs, ++ &omap54xx_l4_cfg__usb_tll_hs, + &omap54xx_l4_cfg__usb_otg_ss, + &omap54xx_l4_wkup__wd_timer2, ++ &omap54xx_l4_cfg__ocp2scp3, ++ &omap54xx_l4_cfg__sata, + NULL, + }; + +--- a/arch/arm/mach-omap2/omap_hwmod_7xx_data.c ++++ b/arch/arm/mach-omap2/omap_hwmod_7xx_data.c +@@ -242,7 +242,6 @@ static struct omap_hwmod dra7xx_counter_ + .class = &dra7xx_counter_hwmod_class, + .clkdm_name = "wkupaon_clkdm", + .flags = HWMOD_SWSUP_SIDLE, +- .main_clk = "wkupaon_iclk_mux", + .prcm = { + .omap4 = { + .clkctrl_offs = DRA7XX_CM_WKUPAON_COUNTER_32K_CLKCTRL_OFFSET, +@@ -273,6 +272,56 @@ static struct omap_hwmod dra7xx_ctrl_mod + }; + + /* ++ * 'gmac' class ++ * cpsw/gmac sub system ++ */ ++static struct omap_hwmod_class_sysconfig dra7xx_gmac_sysc = { ++ .rev_offs = 0x0, ++ .sysc_offs = 0x8, ++ .syss_offs = 0x4, ++ .sysc_flags = (SYSC_HAS_SIDLEMODE | SYSC_HAS_MIDLEMODE | ++ SYSS_HAS_RESET_STATUS), ++ .idlemodes = (SIDLE_FORCE | SIDLE_NO | MSTANDBY_FORCE | ++ MSTANDBY_NO), ++ .sysc_fields = &omap_hwmod_sysc_type3, ++}; ++ ++static struct omap_hwmod_class dra7xx_gmac_hwmod_class = { ++ .name = "gmac", ++ .sysc = &dra7xx_gmac_sysc, ++}; ++ ++static struct omap_hwmod dra7xx_gmac_hwmod = { ++ .name = "gmac", ++ .class = &dra7xx_gmac_hwmod_class, ++ .clkdm_name = "gmac_clkdm", ++ .flags = (HWMOD_SWSUP_SIDLE | HWMOD_SWSUP_MSTANDBY), ++ .main_clk = "dpll_gmac_ck", ++ .mpu_rt_idx = 1, ++ .prcm = { ++ .omap4 = { ++ .clkctrl_offs = DRA7XX_CM_GMAC_GMAC_CLKCTRL_OFFSET, ++ .context_offs = DRA7XX_RM_GMAC_GMAC_CONTEXT_OFFSET, ++ .modulemode = MODULEMODE_SWCTRL, ++ }, ++ }, ++}; ++ ++/* ++ * 'mdio' class ++ */ ++static struct omap_hwmod_class dra7xx_mdio_hwmod_class = { ++ .name = "davinci_mdio", ++}; ++ ++static struct omap_hwmod dra7xx_mdio_hwmod = { ++ .name = "davinci_mdio", ++ .class = &dra7xx_mdio_hwmod_class, ++ .clkdm_name = "gmac_clkdm", ++ .main_clk = "dpll_gmac_ck", ++}; ++ ++/* + * 'dcan' class + * + */ +@@ -325,8 +374,8 @@ static struct omap_hwmod_class_sysconfig + SYSC_HAS_SIDLEMODE | 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_WKUP), ++ MSTANDBY_FORCE | MSTANDBY_NO | ++ MSTANDBY_SMART), + .sysc_fields = &omap_hwmod_sysc_type1, + }; + +@@ -356,7 +405,6 @@ static struct omap_hwmod dra7xx_dma_syst + .class = &dra7xx_dma_hwmod_class, + .clkdm_name = "dma_clkdm", + .mpu_irqs = dra7xx_dma_system_irqs, +- .main_clk = "l3_iclk_div", + .prcm = { + .omap4 = { + .clkctrl_offs = DRA7XX_CM_DMA_DMA_SYSTEM_CLKCTRL_OFFSET, +@@ -561,6 +609,40 @@ static struct omap_hwmod_class dra7xx_gp + .rev = 2, + }; + ++static struct omap_hwmod_class_sysconfig dra7xx_aes_sysc = { ++ .rev_offs = 0x0080, ++ .sysc_offs = 0x0084, ++ .syss_offs = 0x0088, ++ .sysc_flags = (SYSC_HAS_AUTOIDLE | ++ SYSC_HAS_SIDLEMODE | SYSC_HAS_SOFTRESET | ++ SYSS_HAS_RESET_STATUS), ++ .idlemodes = (SIDLE_FORCE | SIDLE_NO | SIDLE_SMART), ++ .sysc_fields = &omap_hwmod_sysc_type4, ++}; ++ ++static struct omap_hwmod_class_sysconfig dra7xx_des_sysc = { ++ .rev_offs = 0x0030, ++ .sysc_offs = 0x0034, ++ .syss_offs = 0x0038, ++ .sysc_flags = (SYSC_HAS_AUTOIDLE | ++ SYSC_HAS_SIDLEMODE | SYSC_HAS_SOFTRESET | ++ SYSS_HAS_RESET_STATUS), ++ .idlemodes = (SIDLE_FORCE | SIDLE_NO), ++ .sysc_fields = &omap_hwmod_sysc_type4, ++}; ++ ++static struct omap_hwmod_class dra7xx_aes_hwmod_class = { ++ .name = "aes", ++ .sysc = &dra7xx_aes_sysc, ++ .rev = 2, ++}; ++ ++static struct omap_hwmod_class dra7xx_des_hwmod_class = { ++ .name = "des", ++ .sysc = &dra7xx_des_sysc, ++ .rev = 2, ++}; ++ + /* gpio dev_attr */ + static struct omap_gpio_dev_attr gpio_dev_attr = { + .bank_width = 32, +@@ -568,15 +650,11 @@ static struct omap_gpio_dev_attr gpio_de + }; + + /* gpio1 */ +-static struct omap_hwmod_opt_clk gpio1_opt_clks[] = { +- { .role = "dbclk", .clk = "gpio1_dbclk" }, +-}; + + static struct omap_hwmod dra7xx_gpio1_hwmod = { + .name = "gpio1", + .class = &dra7xx_gpio_hwmod_class, + .clkdm_name = "wkupaon_clkdm", +- .main_clk = "wkupaon_iclk_mux", + .prcm = { + .omap4 = { + .clkctrl_offs = DRA7XX_CM_WKUPAON_GPIO1_CLKCTRL_OFFSET, +@@ -584,22 +662,16 @@ static struct omap_hwmod dra7xx_gpio1_hw + .modulemode = MODULEMODE_HWCTRL, + }, + }, +- .opt_clks = gpio1_opt_clks, +- .opt_clks_cnt = ARRAY_SIZE(gpio1_opt_clks), + .dev_attr = &gpio_dev_attr, + }; + + /* gpio2 */ +-static struct omap_hwmod_opt_clk gpio2_opt_clks[] = { +- { .role = "dbclk", .clk = "gpio2_dbclk" }, +-}; + + static struct omap_hwmod dra7xx_gpio2_hwmod = { + .name = "gpio2", + .class = &dra7xx_gpio_hwmod_class, + .clkdm_name = "l4per_clkdm", + .flags = HWMOD_CONTROL_OPT_CLKS_IN_RESET, +- .main_clk = "l3_iclk_div", + .prcm = { + .omap4 = { + .clkctrl_offs = DRA7XX_CM_L4PER_GPIO2_CLKCTRL_OFFSET, +@@ -607,22 +679,16 @@ static struct omap_hwmod dra7xx_gpio2_hw + .modulemode = MODULEMODE_HWCTRL, + }, + }, +- .opt_clks = gpio2_opt_clks, +- .opt_clks_cnt = ARRAY_SIZE(gpio2_opt_clks), + .dev_attr = &gpio_dev_attr, + }; + + /* gpio3 */ +-static struct omap_hwmod_opt_clk gpio3_opt_clks[] = { +- { .role = "dbclk", .clk = "gpio3_dbclk" }, +-}; + + static struct omap_hwmod dra7xx_gpio3_hwmod = { + .name = "gpio3", + .class = &dra7xx_gpio_hwmod_class, + .clkdm_name = "l4per_clkdm", + .flags = HWMOD_CONTROL_OPT_CLKS_IN_RESET, +- .main_clk = "l3_iclk_div", + .prcm = { + .omap4 = { + .clkctrl_offs = DRA7XX_CM_L4PER_GPIO3_CLKCTRL_OFFSET, +@@ -630,22 +696,16 @@ static struct omap_hwmod dra7xx_gpio3_hw + .modulemode = MODULEMODE_HWCTRL, + }, + }, +- .opt_clks = gpio3_opt_clks, +- .opt_clks_cnt = ARRAY_SIZE(gpio3_opt_clks), + .dev_attr = &gpio_dev_attr, + }; + + /* gpio4 */ +-static struct omap_hwmod_opt_clk gpio4_opt_clks[] = { +- { .role = "dbclk", .clk = "gpio4_dbclk" }, +-}; + + static struct omap_hwmod dra7xx_gpio4_hwmod = { + .name = "gpio4", + .class = &dra7xx_gpio_hwmod_class, + .clkdm_name = "l4per_clkdm", + .flags = HWMOD_CONTROL_OPT_CLKS_IN_RESET, +- .main_clk = "l3_iclk_div", + .prcm = { + .omap4 = { + .clkctrl_offs = DRA7XX_CM_L4PER_GPIO4_CLKCTRL_OFFSET, +@@ -653,22 +713,16 @@ static struct omap_hwmod dra7xx_gpio4_hw + .modulemode = MODULEMODE_HWCTRL, + }, + }, +- .opt_clks = gpio4_opt_clks, +- .opt_clks_cnt = ARRAY_SIZE(gpio4_opt_clks), + .dev_attr = &gpio_dev_attr, + }; + + /* gpio5 */ +-static struct omap_hwmod_opt_clk gpio5_opt_clks[] = { +- { .role = "dbclk", .clk = "gpio5_dbclk" }, +-}; + + static struct omap_hwmod dra7xx_gpio5_hwmod = { + .name = "gpio5", + .class = &dra7xx_gpio_hwmod_class, + .clkdm_name = "l4per_clkdm", + .flags = HWMOD_CONTROL_OPT_CLKS_IN_RESET, +- .main_clk = "l3_iclk_div", + .prcm = { + .omap4 = { + .clkctrl_offs = DRA7XX_CM_L4PER_GPIO5_CLKCTRL_OFFSET, +@@ -676,22 +730,16 @@ static struct omap_hwmod dra7xx_gpio5_hw + .modulemode = MODULEMODE_HWCTRL, + }, + }, +- .opt_clks = gpio5_opt_clks, +- .opt_clks_cnt = ARRAY_SIZE(gpio5_opt_clks), + .dev_attr = &gpio_dev_attr, + }; + + /* gpio6 */ +-static struct omap_hwmod_opt_clk gpio6_opt_clks[] = { +- { .role = "dbclk", .clk = "gpio6_dbclk" }, +-}; + + static struct omap_hwmod dra7xx_gpio6_hwmod = { + .name = "gpio6", + .class = &dra7xx_gpio_hwmod_class, + .clkdm_name = "l4per_clkdm", + .flags = HWMOD_CONTROL_OPT_CLKS_IN_RESET, +- .main_clk = "l3_iclk_div", + .prcm = { + .omap4 = { + .clkctrl_offs = DRA7XX_CM_L4PER_GPIO6_CLKCTRL_OFFSET, +@@ -699,22 +747,16 @@ static struct omap_hwmod dra7xx_gpio6_hw + .modulemode = MODULEMODE_HWCTRL, + }, + }, +- .opt_clks = gpio6_opt_clks, +- .opt_clks_cnt = ARRAY_SIZE(gpio6_opt_clks), + .dev_attr = &gpio_dev_attr, + }; + + /* gpio7 */ +-static struct omap_hwmod_opt_clk gpio7_opt_clks[] = { +- { .role = "dbclk", .clk = "gpio7_dbclk" }, +-}; + + static struct omap_hwmod dra7xx_gpio7_hwmod = { + .name = "gpio7", + .class = &dra7xx_gpio_hwmod_class, + .clkdm_name = "l4per_clkdm", + .flags = HWMOD_CONTROL_OPT_CLKS_IN_RESET, +- .main_clk = "l3_iclk_div", + .prcm = { + .omap4 = { + .clkctrl_offs = DRA7XX_CM_L4PER_GPIO7_CLKCTRL_OFFSET, +@@ -722,22 +764,16 @@ static struct omap_hwmod dra7xx_gpio7_hw + .modulemode = MODULEMODE_HWCTRL, + }, + }, +- .opt_clks = gpio7_opt_clks, +- .opt_clks_cnt = ARRAY_SIZE(gpio7_opt_clks), + .dev_attr = &gpio_dev_attr, + }; + + /* gpio8 */ +-static struct omap_hwmod_opt_clk gpio8_opt_clks[] = { +- { .role = "dbclk", .clk = "gpio8_dbclk" }, +-}; + + static struct omap_hwmod dra7xx_gpio8_hwmod = { + .name = "gpio8", + .class = &dra7xx_gpio_hwmod_class, + .clkdm_name = "l4per_clkdm", + .flags = HWMOD_CONTROL_OPT_CLKS_IN_RESET, +- .main_clk = "l3_iclk_div", + .prcm = { + .omap4 = { + .clkctrl_offs = DRA7XX_CM_L4PER_GPIO8_CLKCTRL_OFFSET, +@@ -745,11 +781,35 @@ static struct omap_hwmod dra7xx_gpio8_hw + .modulemode = MODULEMODE_HWCTRL, + }, + }, +- .opt_clks = gpio8_opt_clks, +- .opt_clks_cnt = ARRAY_SIZE(gpio8_opt_clks), + .dev_attr = &gpio_dev_attr, + }; + ++static struct omap_hwmod dra7xx_aes_hwmod = { ++ .name = "aes", ++ .class = &dra7xx_aes_hwmod_class, ++ .clkdm_name = "l4sec_clkdm", ++ .prcm = { ++ .omap4 = { ++ .clkctrl_offs = DRA7XX_CM_L4SEC_AES1_CLKCTRL_OFFSET, ++ .context_offs = DRA7XX_RM_L4SEC_AES1_CONTEXT_OFFSET, ++ .modulemode = MODULEMODE_HWCTRL, ++ }, ++ }, ++}; ++ ++static struct omap_hwmod dra7xx_des_hwmod = { ++ .name = "des", ++ .class = &dra7xx_des_hwmod_class, ++ .clkdm_name = "l4sec_clkdm", ++ .prcm = { ++ .omap4 = { ++ .clkctrl_offs = DRA7XX_CM_L4SEC_DES3DES_CLKCTRL_OFFSET, ++ .context_offs = DRA7XX_RM_L4SEC_DES3DES_CONTEXT_OFFSET, ++ .modulemode = MODULEMODE_HWCTRL, ++ }, ++ }, ++}; ++ + /* + * 'gpmc' class + * +@@ -859,7 +919,6 @@ static struct omap_hwmod dra7xx_i2c1_hwm + .class = &dra7xx_i2c_hwmod_class, + .clkdm_name = "l4per_clkdm", + .flags = HWMOD_16BIT_REG | HWMOD_SET_DEFAULT_CLOCKACT, +- .main_clk = "func_96m_fclk", + .prcm = { + .omap4 = { + .clkctrl_offs = DRA7XX_CM_L4PER_I2C1_CLKCTRL_OFFSET, +@@ -876,7 +935,6 @@ static struct omap_hwmod dra7xx_i2c2_hwm + .class = &dra7xx_i2c_hwmod_class, + .clkdm_name = "l4per_clkdm", + .flags = HWMOD_16BIT_REG | HWMOD_SET_DEFAULT_CLOCKACT, +- .main_clk = "func_96m_fclk", + .prcm = { + .omap4 = { + .clkctrl_offs = DRA7XX_CM_L4PER_I2C2_CLKCTRL_OFFSET, +@@ -893,7 +951,6 @@ static struct omap_hwmod dra7xx_i2c3_hwm + .class = &dra7xx_i2c_hwmod_class, + .clkdm_name = "l4per_clkdm", + .flags = HWMOD_16BIT_REG | HWMOD_SET_DEFAULT_CLOCKACT, +- .main_clk = "func_96m_fclk", + .prcm = { + .omap4 = { + .clkctrl_offs = DRA7XX_CM_L4PER_I2C3_CLKCTRL_OFFSET, +@@ -910,7 +967,6 @@ static struct omap_hwmod dra7xx_i2c4_hwm + .class = &dra7xx_i2c_hwmod_class, + .clkdm_name = "l4per_clkdm", + .flags = HWMOD_16BIT_REG | HWMOD_SET_DEFAULT_CLOCKACT, +- .main_clk = "func_96m_fclk", + .prcm = { + .omap4 = { + .clkctrl_offs = DRA7XX_CM_L4PER_I2C4_CLKCTRL_OFFSET, +@@ -927,7 +983,6 @@ static struct omap_hwmod dra7xx_i2c5_hwm + .class = &dra7xx_i2c_hwmod_class, + .clkdm_name = "ipu_clkdm", + .flags = HWMOD_16BIT_REG | HWMOD_SET_DEFAULT_CLOCKACT, +- .main_clk = "func_96m_fclk", + .prcm = { + .omap4 = { + .clkctrl_offs = DRA7XX_CM_IPU_I2C5_CLKCTRL_OFFSET, +@@ -939,6 +994,207 @@ static struct omap_hwmod dra7xx_i2c5_hwm + }; + + /* ++ * 'mailbox' class ++ * ++ */ ++ ++static struct omap_hwmod_class_sysconfig dra7xx_mailbox_sysc = { ++ .rev_offs = 0x0000, ++ .sysc_offs = 0x0010, ++ .sysc_flags = (SYSC_HAS_RESET_STATUS | SYSC_HAS_SIDLEMODE | ++ SYSC_HAS_SOFTRESET), ++ .idlemodes = (SIDLE_FORCE | SIDLE_NO | SIDLE_SMART), ++ .sysc_fields = &omap_hwmod_sysc_type2, ++}; ++ ++static struct omap_hwmod_class dra7xx_mailbox_hwmod_class = { ++ .name = "mailbox", ++ .sysc = &dra7xx_mailbox_sysc, ++}; ++ ++/* mailbox1 */ ++static struct omap_hwmod dra7xx_mailbox1_hwmod = { ++ .name = "mailbox1", ++ .class = &dra7xx_mailbox_hwmod_class, ++ .clkdm_name = "l4cfg_clkdm", ++ .main_clk = "l3_iclk_div", ++ .prcm = { ++ .omap4 = { ++ .clkctrl_offs = DRA7XX_CM_L4CFG_MAILBOX1_CLKCTRL_OFFSET, ++ .context_offs = DRA7XX_RM_L4CFG_MAILBOX1_CONTEXT_OFFSET, ++ }, ++ }, ++}; ++ ++/* mailbox2 */ ++static struct omap_hwmod dra7xx_mailbox2_hwmod = { ++ .name = "mailbox2", ++ .class = &dra7xx_mailbox_hwmod_class, ++ .clkdm_name = "l4cfg_clkdm", ++ .main_clk = "l3_iclk_div", ++ .prcm = { ++ .omap4 = { ++ .clkctrl_offs = DRA7XX_CM_L4CFG_MAILBOX2_CLKCTRL_OFFSET, ++ .context_offs = DRA7XX_RM_L4CFG_MAILBOX2_CONTEXT_OFFSET, ++ }, ++ }, ++}; ++ ++/* mailbox3 */ ++static struct omap_hwmod dra7xx_mailbox3_hwmod = { ++ .name = "mailbox3", ++ .class = &dra7xx_mailbox_hwmod_class, ++ .clkdm_name = "l4cfg_clkdm", ++ .main_clk = "l3_iclk_div", ++ .prcm = { ++ .omap4 = { ++ .clkctrl_offs = DRA7XX_CM_L4CFG_MAILBOX3_CLKCTRL_OFFSET, ++ .context_offs = DRA7XX_RM_L4CFG_MAILBOX3_CONTEXT_OFFSET, ++ }, ++ }, ++}; ++ ++/* mailbox4 */ ++static struct omap_hwmod dra7xx_mailbox4_hwmod = { ++ .name = "mailbox4", ++ .class = &dra7xx_mailbox_hwmod_class, ++ .clkdm_name = "l4cfg_clkdm", ++ .main_clk = "l3_iclk_div", ++ .prcm = { ++ .omap4 = { ++ .clkctrl_offs = DRA7XX_CM_L4CFG_MAILBOX4_CLKCTRL_OFFSET, ++ .context_offs = DRA7XX_RM_L4CFG_MAILBOX4_CONTEXT_OFFSET, ++ }, ++ }, ++}; ++ ++/* mailbox5 */ ++static struct omap_hwmod dra7xx_mailbox5_hwmod = { ++ .name = "mailbox5", ++ .class = &dra7xx_mailbox_hwmod_class, ++ .clkdm_name = "l4cfg_clkdm", ++ .main_clk = "l3_iclk_div", ++ .prcm = { ++ .omap4 = { ++ .clkctrl_offs = DRA7XX_CM_L4CFG_MAILBOX5_CLKCTRL_OFFSET, ++ .context_offs = DRA7XX_RM_L4CFG_MAILBOX5_CONTEXT_OFFSET, ++ }, ++ }, ++}; ++ ++/* mailbox6 */ ++static struct omap_hwmod dra7xx_mailbox6_hwmod = { ++ .name = "mailbox6", ++ .class = &dra7xx_mailbox_hwmod_class, ++ .clkdm_name = "l4cfg_clkdm", ++ .main_clk = "l3_iclk_div", ++ .prcm = { ++ .omap4 = { ++ .clkctrl_offs = DRA7XX_CM_L4CFG_MAILBOX6_CLKCTRL_OFFSET, ++ .context_offs = DRA7XX_RM_L4CFG_MAILBOX6_CONTEXT_OFFSET, ++ }, ++ }, ++}; ++ ++/* mailbox7 */ ++static struct omap_hwmod dra7xx_mailbox7_hwmod = { ++ .name = "mailbox7", ++ .class = &dra7xx_mailbox_hwmod_class, ++ .clkdm_name = "l4cfg_clkdm", ++ .main_clk = "l3_iclk_div", ++ .prcm = { ++ .omap4 = { ++ .clkctrl_offs = DRA7XX_CM_L4CFG_MAILBOX7_CLKCTRL_OFFSET, ++ .context_offs = DRA7XX_RM_L4CFG_MAILBOX7_CONTEXT_OFFSET, ++ }, ++ }, ++}; ++ ++/* mailbox8 */ ++static struct omap_hwmod dra7xx_mailbox8_hwmod = { ++ .name = "mailbox8", ++ .class = &dra7xx_mailbox_hwmod_class, ++ .clkdm_name = "l4cfg_clkdm", ++ .main_clk = "l3_iclk_div", ++ .prcm = { ++ .omap4 = { ++ .clkctrl_offs = DRA7XX_CM_L4CFG_MAILBOX8_CLKCTRL_OFFSET, ++ .context_offs = DRA7XX_RM_L4CFG_MAILBOX8_CONTEXT_OFFSET, ++ }, ++ }, ++}; ++ ++/* mailbox9 */ ++static struct omap_hwmod dra7xx_mailbox9_hwmod = { ++ .name = "mailbox9", ++ .class = &dra7xx_mailbox_hwmod_class, ++ .clkdm_name = "l4cfg_clkdm", ++ .main_clk = "l3_iclk_div", ++ .prcm = { ++ .omap4 = { ++ .clkctrl_offs = DRA7XX_CM_L4CFG_MAILBOX9_CLKCTRL_OFFSET, ++ .context_offs = DRA7XX_RM_L4CFG_MAILBOX9_CONTEXT_OFFSET, ++ }, ++ }, ++}; ++ ++/* mailbox10 */ ++static struct omap_hwmod dra7xx_mailbox10_hwmod = { ++ .name = "mailbox10", ++ .class = &dra7xx_mailbox_hwmod_class, ++ .clkdm_name = "l4cfg_clkdm", ++ .main_clk = "l3_iclk_div", ++ .prcm = { ++ .omap4 = { ++ .clkctrl_offs = DRA7XX_CM_L4CFG_MAILBOX10_CLKCTRL_OFFSET, ++ .context_offs = DRA7XX_RM_L4CFG_MAILBOX10_CONTEXT_OFFSET, ++ }, ++ }, ++}; ++ ++/* mailbox11 */ ++static struct omap_hwmod dra7xx_mailbox11_hwmod = { ++ .name = "mailbox11", ++ .class = &dra7xx_mailbox_hwmod_class, ++ .clkdm_name = "l4cfg_clkdm", ++ .main_clk = "l3_iclk_div", ++ .prcm = { ++ .omap4 = { ++ .clkctrl_offs = DRA7XX_CM_L4CFG_MAILBOX11_CLKCTRL_OFFSET, ++ .context_offs = DRA7XX_RM_L4CFG_MAILBOX11_CONTEXT_OFFSET, ++ }, ++ }, ++}; ++ ++/* mailbox12 */ ++static struct omap_hwmod dra7xx_mailbox12_hwmod = { ++ .name = "mailbox12", ++ .class = &dra7xx_mailbox_hwmod_class, ++ .clkdm_name = "l4cfg_clkdm", ++ .main_clk = "l3_iclk_div", ++ .prcm = { ++ .omap4 = { ++ .clkctrl_offs = DRA7XX_CM_L4CFG_MAILBOX12_CLKCTRL_OFFSET, ++ .context_offs = DRA7XX_RM_L4CFG_MAILBOX12_CONTEXT_OFFSET, ++ }, ++ }, ++}; ++ ++/* mailbox13 */ ++static struct omap_hwmod dra7xx_mailbox13_hwmod = { ++ .name = "mailbox13", ++ .class = &dra7xx_mailbox_hwmod_class, ++ .clkdm_name = "l4cfg_clkdm", ++ .main_clk = "l3_iclk_div", ++ .prcm = { ++ .omap4 = { ++ .clkctrl_offs = DRA7XX_CM_L4CFG_MAILBOX13_CLKCTRL_OFFSET, ++ .context_offs = DRA7XX_RM_L4CFG_MAILBOX13_CONTEXT_OFFSET, ++ }, ++ }, ++}; ++ ++/* + * 'mcspi' class + * + */ +@@ -969,7 +1225,6 @@ static struct omap_hwmod dra7xx_mcspi1_h + .name = "mcspi1", + .class = &dra7xx_mcspi_hwmod_class, + .clkdm_name = "l4per_clkdm", +- .main_clk = "func_48m_fclk", + .prcm = { + .omap4 = { + .clkctrl_offs = DRA7XX_CM_L4PER_MCSPI1_CLKCTRL_OFFSET, +@@ -990,7 +1245,6 @@ static struct omap_hwmod dra7xx_mcspi2_h + .name = "mcspi2", + .class = &dra7xx_mcspi_hwmod_class, + .clkdm_name = "l4per_clkdm", +- .main_clk = "func_48m_fclk", + .prcm = { + .omap4 = { + .clkctrl_offs = DRA7XX_CM_L4PER_MCSPI2_CLKCTRL_OFFSET, +@@ -1011,7 +1265,6 @@ static struct omap_hwmod dra7xx_mcspi3_h + .name = "mcspi3", + .class = &dra7xx_mcspi_hwmod_class, + .clkdm_name = "l4per_clkdm", +- .main_clk = "func_48m_fclk", + .prcm = { + .omap4 = { + .clkctrl_offs = DRA7XX_CM_L4PER_MCSPI3_CLKCTRL_OFFSET, +@@ -1032,7 +1285,6 @@ static struct omap_hwmod dra7xx_mcspi4_h + .name = "mcspi4", + .class = &dra7xx_mcspi_hwmod_class, + .clkdm_name = "l4per_clkdm", +- .main_clk = "func_48m_fclk", + .prcm = { + .omap4 = { + .clkctrl_offs = DRA7XX_CM_L4PER_MCSPI4_CLKCTRL_OFFSET, +@@ -1066,9 +1318,6 @@ static struct omap_hwmod_class dra7xx_mm + }; + + /* mmc1 */ +-static struct omap_hwmod_opt_clk mmc1_opt_clks[] = { +- { .role = "clk32k", .clk = "mmc1_clk32k" }, +-}; + + /* mmc1 dev_attr */ + static struct omap_mmc_dev_attr mmc1_dev_attr = { +@@ -1079,7 +1328,6 @@ static struct omap_hwmod dra7xx_mmc1_hwm + .name = "mmc1", + .class = &dra7xx_mmc_hwmod_class, + .clkdm_name = "l3init_clkdm", +- .main_clk = "mmc1_fclk_div", + .prcm = { + .omap4 = { + .clkctrl_offs = DRA7XX_CM_L3INIT_MMC1_CLKCTRL_OFFSET, +@@ -1087,21 +1335,15 @@ static struct omap_hwmod dra7xx_mmc1_hwm + .modulemode = MODULEMODE_SWCTRL, + }, + }, +- .opt_clks = mmc1_opt_clks, +- .opt_clks_cnt = ARRAY_SIZE(mmc1_opt_clks), + .dev_attr = &mmc1_dev_attr, + }; + + /* mmc2 */ +-static struct omap_hwmod_opt_clk mmc2_opt_clks[] = { +- { .role = "clk32k", .clk = "mmc2_clk32k" }, +-}; + + static struct omap_hwmod dra7xx_mmc2_hwmod = { + .name = "mmc2", + .class = &dra7xx_mmc_hwmod_class, + .clkdm_name = "l3init_clkdm", +- .main_clk = "mmc2_fclk_div", + .prcm = { + .omap4 = { + .clkctrl_offs = DRA7XX_CM_L3INIT_MMC2_CLKCTRL_OFFSET, +@@ -1109,20 +1351,14 @@ static struct omap_hwmod dra7xx_mmc2_hwm + .modulemode = MODULEMODE_SWCTRL, + }, + }, +- .opt_clks = mmc2_opt_clks, +- .opt_clks_cnt = ARRAY_SIZE(mmc2_opt_clks), + }; + + /* mmc3 */ +-static struct omap_hwmod_opt_clk mmc3_opt_clks[] = { +- { .role = "clk32k", .clk = "mmc3_clk32k" }, +-}; + + static struct omap_hwmod dra7xx_mmc3_hwmod = { + .name = "mmc3", + .class = &dra7xx_mmc_hwmod_class, + .clkdm_name = "l4per_clkdm", +- .main_clk = "mmc3_gfclk_div", + .prcm = { + .omap4 = { + .clkctrl_offs = DRA7XX_CM_L4PER_MMC3_CLKCTRL_OFFSET, +@@ -1130,20 +1366,14 @@ static struct omap_hwmod dra7xx_mmc3_hwm + .modulemode = MODULEMODE_SWCTRL, + }, + }, +- .opt_clks = mmc3_opt_clks, +- .opt_clks_cnt = ARRAY_SIZE(mmc3_opt_clks), + }; + + /* mmc4 */ +-static struct omap_hwmod_opt_clk mmc4_opt_clks[] = { +- { .role = "clk32k", .clk = "mmc4_clk32k" }, +-}; + + static struct omap_hwmod dra7xx_mmc4_hwmod = { + .name = "mmc4", + .class = &dra7xx_mmc_hwmod_class, + .clkdm_name = "l4per_clkdm", +- .main_clk = "mmc4_gfclk_div", + .prcm = { + .omap4 = { + .clkctrl_offs = DRA7XX_CM_L4PER_MMC4_CLKCTRL_OFFSET, +@@ -1151,8 +1381,6 @@ static struct omap_hwmod dra7xx_mmc4_hwm + .modulemode = MODULEMODE_SWCTRL, + }, + }, +- .opt_clks = mmc4_opt_clks, +- .opt_clks_cnt = ARRAY_SIZE(mmc4_opt_clks), + }; + + /* +@@ -1215,6 +1443,30 @@ static struct omap_hwmod dra7xx_ocp2scp1 + }, + }; + ++/* ocp2scp3 */ ++static struct omap_hwmod dra7xx_ocp2scp3_hwmod; ++ ++/* l4_cfg -> ocp2scp3 */ ++static struct omap_hwmod_ocp_if dra7xx_l4_cfg__ocp2scp3 = { ++ .master = &dra7xx_l4_cfg_hwmod, ++ .slave = &dra7xx_ocp2scp3_hwmod, ++ .clk = "l4_root_clk_div", ++ .user = OCP_USER_MPU | OCP_USER_SDMA, ++}; ++ ++static struct omap_hwmod dra7xx_ocp2scp3_hwmod = { ++ .name = "ocp2scp3", ++ .class = &dra7xx_ocp2scp_hwmod_class, ++ .clkdm_name = "l3init_clkdm", ++ .prcm = { ++ .omap4 = { ++ .clkctrl_offs = DRA7XX_CM_L3INIT_OCP2SCP3_CLKCTRL_OFFSET, ++ .context_offs = DRA7XX_RM_L3INIT_OCP2SCP3_CONTEXT_OFFSET, ++ .modulemode = MODULEMODE_HWCTRL, ++ }, ++ }, ++}; ++ + /* + * 'qspi' class + * +@@ -1249,6 +1501,38 @@ static struct omap_hwmod dra7xx_qspi_hwm + }; + + /* ++ * 'rtcss' class ++ * ++ */ ++static struct omap_hwmod_class_sysconfig dra7xx_rtcss_sysc = { ++ .sysc_offs = 0x0078, ++ .sysc_flags = SYSC_HAS_SIDLEMODE, ++ .idlemodes = (SIDLE_FORCE | SIDLE_NO | SIDLE_SMART | ++ SIDLE_SMART_WKUP), ++ .sysc_fields = &omap_hwmod_sysc_type3, ++}; ++ ++static struct omap_hwmod_class dra7xx_rtcss_hwmod_class = { ++ .name = "rtcss", ++ .sysc = &dra7xx_rtcss_sysc, ++}; ++ ++/* rtcss */ ++static struct omap_hwmod dra7xx_rtcss_hwmod = { ++ .name = "rtcss", ++ .class = &dra7xx_rtcss_hwmod_class, ++ .clkdm_name = "rtc_clkdm", ++ .main_clk = "sys_32k_ck", ++ .prcm = { ++ .omap4 = { ++ .clkctrl_offs = DRA7XX_CM_RTC_RTCSS_CLKCTRL_OFFSET, ++ .context_offs = DRA7XX_RM_RTC_RTCSS_CONTEXT_OFFSET, ++ .modulemode = MODULEMODE_SWCTRL, ++ }, ++ }, ++}; ++ ++/* + * 'sata' class + * + */ +@@ -1268,9 +1552,6 @@ static struct omap_hwmod_class dra7xx_sa + }; + + /* sata */ +-static struct omap_hwmod_opt_clk sata_opt_clks[] = { +- { .role = "ref_clk", .clk = "sata_ref_clk" }, +-}; + + static struct omap_hwmod dra7xx_sata_hwmod = { + .name = "sata", +@@ -1285,8 +1566,6 @@ static struct omap_hwmod dra7xx_sata_hwm + .modulemode = MODULEMODE_SWCTRL, + }, + }, +- .opt_clks = sata_opt_clks, +- .opt_clks_cnt = ARRAY_SIZE(sata_opt_clks), + }; + + /* +@@ -1449,7 +1728,6 @@ static struct omap_hwmod dra7xx_timer1_h + .name = "timer1", + .class = &dra7xx_timer_1ms_hwmod_class, + .clkdm_name = "wkupaon_clkdm", +- .main_clk = "timer1_gfclk_mux", + .prcm = { + .omap4 = { + .clkctrl_offs = DRA7XX_CM_WKUPAON_TIMER1_CLKCTRL_OFFSET, +@@ -1464,7 +1742,6 @@ static struct omap_hwmod dra7xx_timer2_h + .name = "timer2", + .class = &dra7xx_timer_1ms_hwmod_class, + .clkdm_name = "l4per_clkdm", +- .main_clk = "timer2_gfclk_mux", + .prcm = { + .omap4 = { + .clkctrl_offs = DRA7XX_CM_L4PER_TIMER2_CLKCTRL_OFFSET, +@@ -1479,7 +1756,6 @@ static struct omap_hwmod dra7xx_timer3_h + .name = "timer3", + .class = &dra7xx_timer_hwmod_class, + .clkdm_name = "l4per_clkdm", +- .main_clk = "timer3_gfclk_mux", + .prcm = { + .omap4 = { + .clkctrl_offs = DRA7XX_CM_L4PER_TIMER3_CLKCTRL_OFFSET, +@@ -1494,7 +1770,6 @@ static struct omap_hwmod dra7xx_timer4_h + .name = "timer4", + .class = &dra7xx_timer_secure_hwmod_class, + .clkdm_name = "l4per_clkdm", +- .main_clk = "timer4_gfclk_mux", + .prcm = { + .omap4 = { + .clkctrl_offs = DRA7XX_CM_L4PER_TIMER4_CLKCTRL_OFFSET, +@@ -1509,7 +1784,6 @@ static struct omap_hwmod dra7xx_timer5_h + .name = "timer5", + .class = &dra7xx_timer_hwmod_class, + .clkdm_name = "ipu_clkdm", +- .main_clk = "timer5_gfclk_mux", + .prcm = { + .omap4 = { + .clkctrl_offs = DRA7XX_CM_IPU_TIMER5_CLKCTRL_OFFSET, +@@ -1524,7 +1798,6 @@ static struct omap_hwmod dra7xx_timer6_h + .name = "timer6", + .class = &dra7xx_timer_hwmod_class, + .clkdm_name = "ipu_clkdm", +- .main_clk = "timer6_gfclk_mux", + .prcm = { + .omap4 = { + .clkctrl_offs = DRA7XX_CM_IPU_TIMER6_CLKCTRL_OFFSET, +@@ -1539,7 +1812,6 @@ static struct omap_hwmod dra7xx_timer7_h + .name = "timer7", + .class = &dra7xx_timer_hwmod_class, + .clkdm_name = "ipu_clkdm", +- .main_clk = "timer7_gfclk_mux", + .prcm = { + .omap4 = { + .clkctrl_offs = DRA7XX_CM_IPU_TIMER7_CLKCTRL_OFFSET, +@@ -1554,7 +1826,6 @@ static struct omap_hwmod dra7xx_timer8_h + .name = "timer8", + .class = &dra7xx_timer_hwmod_class, + .clkdm_name = "ipu_clkdm", +- .main_clk = "timer8_gfclk_mux", + .prcm = { + .omap4 = { + .clkctrl_offs = DRA7XX_CM_IPU_TIMER8_CLKCTRL_OFFSET, +@@ -1569,7 +1840,6 @@ static struct omap_hwmod dra7xx_timer9_h + .name = "timer9", + .class = &dra7xx_timer_hwmod_class, + .clkdm_name = "l4per_clkdm", +- .main_clk = "timer9_gfclk_mux", + .prcm = { + .omap4 = { + .clkctrl_offs = DRA7XX_CM_L4PER_TIMER9_CLKCTRL_OFFSET, +@@ -1584,7 +1854,6 @@ static struct omap_hwmod dra7xx_timer10_ + .name = "timer10", + .class = &dra7xx_timer_1ms_hwmod_class, + .clkdm_name = "l4per_clkdm", +- .main_clk = "timer10_gfclk_mux", + .prcm = { + .omap4 = { + .clkctrl_offs = DRA7XX_CM_L4PER_TIMER10_CLKCTRL_OFFSET, +@@ -1599,7 +1868,6 @@ static struct omap_hwmod dra7xx_timer11_ + .name = "timer11", + .class = &dra7xx_timer_hwmod_class, + .clkdm_name = "l4per_clkdm", +- .main_clk = "timer11_gfclk_mux", + .prcm = { + .omap4 = { + .clkctrl_offs = DRA7XX_CM_L4PER_TIMER11_CLKCTRL_OFFSET, +@@ -1636,8 +1904,7 @@ static struct omap_hwmod dra7xx_uart1_hw + .name = "uart1", + .class = &dra7xx_uart_hwmod_class, + .clkdm_name = "l4per_clkdm", +- .main_clk = "uart1_gfclk_mux", +- .flags = HWMOD_SWSUP_SIDLE_ACT, ++ .flags = DEBUG_OMAP2UART1_FLAGS | HWMOD_SWSUP_SIDLE_ACT, + .prcm = { + .omap4 = { + .clkctrl_offs = DRA7XX_CM_L4PER_UART1_CLKCTRL_OFFSET, +@@ -1652,7 +1919,6 @@ static struct omap_hwmod dra7xx_uart2_hw + .name = "uart2", + .class = &dra7xx_uart_hwmod_class, + .clkdm_name = "l4per_clkdm", +- .main_clk = "uart2_gfclk_mux", + .flags = HWMOD_SWSUP_SIDLE_ACT, + .prcm = { + .omap4 = { +@@ -1668,7 +1934,6 @@ static struct omap_hwmod dra7xx_uart3_hw + .name = "uart3", + .class = &dra7xx_uart_hwmod_class, + .clkdm_name = "l4per_clkdm", +- .main_clk = "uart3_gfclk_mux", + .flags = HWMOD_SWSUP_SIDLE_ACT, + .prcm = { + .omap4 = { +@@ -1684,7 +1949,6 @@ static struct omap_hwmod dra7xx_uart4_hw + .name = "uart4", + .class = &dra7xx_uart_hwmod_class, + .clkdm_name = "l4per_clkdm", +- .main_clk = "uart4_gfclk_mux", + .flags = HWMOD_SWSUP_SIDLE_ACT, + .prcm = { + .omap4 = { +@@ -1700,7 +1964,6 @@ static struct omap_hwmod dra7xx_uart5_hw + .name = "uart5", + .class = &dra7xx_uart_hwmod_class, + .clkdm_name = "l4per_clkdm", +- .main_clk = "uart5_gfclk_mux", + .flags = HWMOD_SWSUP_SIDLE_ACT, + .prcm = { + .omap4 = { +@@ -1716,7 +1979,6 @@ static struct omap_hwmod dra7xx_uart6_hw + .name = "uart6", + .class = &dra7xx_uart_hwmod_class, + .clkdm_name = "ipu_clkdm", +- .main_clk = "uart6_gfclk_mux", + .flags = HWMOD_SWSUP_SIDLE_ACT, + .prcm = { + .omap4 = { +@@ -1732,8 +1994,20 @@ static struct omap_hwmod dra7xx_uart6_hw + * + */ + ++static struct omap_hwmod_class_sysconfig dra7xx_usb_otg_ss_sysc = { ++ .rev_offs = 0x0000, ++ .sysc_offs = 0x0010, ++ .sysc_flags = (SYSC_HAS_DMADISABLE | 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 dra7xx_usb_otg_ss_hwmod_class = { + .name = "usb_otg_ss", ++ .sysc = &dra7xx_usb_otg_ss_sysc, + }; + + /* usb_otg_ss1 */ +@@ -1873,7 +2147,6 @@ static struct omap_hwmod dra7xx_wd_timer + .name = "wd_timer2", + .class = &dra7xx_wd_timer_hwmod_class, + .clkdm_name = "wkupaon_clkdm", +- .main_clk = "sys_32k_ck", + .prcm = { + .omap4 = { + .clkctrl_offs = DRA7XX_CM_WKUPAON_WD_TIMER2_CLKCTRL_OFFSET, +@@ -1883,6 +2156,39 @@ static struct omap_hwmod dra7xx_wd_timer + }, + }; + ++/* ++ * 'vpe' class ++ * ++ */ ++ ++static struct omap_hwmod_class_sysconfig dra7xx_vpe_sysc = { ++ .sysc_offs = 0x0010, ++ .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 dra7xx_vpe_hwmod_class = { ++ .name = "vpe", ++ .sysc = &dra7xx_vpe_sysc, ++}; ++ ++/* vpe */ ++static struct omap_hwmod dra7xx_vpe_hwmod = { ++ .name = "vpe", ++ .class = &dra7xx_vpe_hwmod_class, ++ .clkdm_name = "vpe_clkdm", ++ .main_clk = "dpll_core_h23x2_ck", ++ .prcm = { ++ .omap4 = { ++ .clkctrl_offs = DRA7XX_CM_VPE_VPE_CLKCTRL_OFFSET, ++ .context_offs = DRA7XX_RM_VPE_VPE_CONTEXT_OFFSET, ++ .modulemode = MODULEMODE_HWCTRL, ++ }, ++ }, ++}; + + /* + * Interfaces +@@ -2000,6 +2306,19 @@ static struct omap_hwmod_ocp_if dra7xx_l + .user = OCP_USER_MPU | OCP_USER_SDMA, + }; + ++static struct omap_hwmod_ocp_if dra7xx_l4_per2__cpgmac0 = { ++ .master = &dra7xx_l4_per2_hwmod, ++ .slave = &dra7xx_gmac_hwmod, ++ .clk = "dpll_gmac_ck", ++ .user = OCP_USER_MPU, ++}; ++ ++static struct omap_hwmod_ocp_if dra7xx_gmac__mdio = { ++ .master = &dra7xx_gmac_hwmod, ++ .slave = &dra7xx_mdio_hwmod, ++ .user = OCP_USER_MPU, ++}; ++ + /* l4_wkup -> dcan1 */ + static struct omap_hwmod_ocp_if dra7xx_l4_wkup__dcan1 = { + .master = &dra7xx_l4_wkup_hwmod, +@@ -2089,6 +2408,14 @@ static struct omap_hwmod_ocp_if dra7xx_l + .user = OCP_USER_MPU | OCP_USER_SDMA, + }; + ++/* l3_main_1 -> aes */ ++static struct omap_hwmod_ocp_if dra7xx_l3_main_1__aes = { ++ .master = &dra7xx_l3_main_1_hwmod, ++ .slave = &dra7xx_aes_hwmod, ++ .clk = "l3_iclk_div", ++ .user = OCP_USER_MPU | OCP_USER_SDMA, ++}; ++ + static struct omap_hwmod_addr_space dra7xx_elm_addrs[] = { + { + .pa_start = 0x48078000, +@@ -2171,6 +2498,14 @@ static struct omap_hwmod_ocp_if dra7xx_l + .user = OCP_USER_MPU | OCP_USER_SDMA, + }; + ++/* l4_per1 -> des */ ++static struct omap_hwmod_ocp_if dra7xx_l4_per1__des = { ++ .master = &dra7xx_l4_per1_hwmod, ++ .slave = &dra7xx_des_hwmod, ++ .clk = "l3_iclk_div", ++ .user = OCP_USER_MPU | OCP_USER_SDMA, ++}; ++ + static struct omap_hwmod_addr_space dra7xx_gpmc_addrs[] = { + { + .pa_start = 0x50000000, +@@ -2247,6 +2582,110 @@ static struct omap_hwmod_ocp_if dra7xx_l + .user = OCP_USER_MPU | OCP_USER_SDMA, + }; + ++/* l4_cfg -> mailbox1 */ ++static struct omap_hwmod_ocp_if dra7xx_l4_cfg__mailbox1 = { ++ .master = &dra7xx_l4_cfg_hwmod, ++ .slave = &dra7xx_mailbox1_hwmod, ++ .clk = "l3_iclk_div", ++ .user = OCP_USER_MPU | OCP_USER_SDMA, ++}; ++ ++/* l4_per3 -> mailbox2 */ ++static struct omap_hwmod_ocp_if dra7xx_l4_per3__mailbox2 = { ++ .master = &dra7xx_l4_per3_hwmod, ++ .slave = &dra7xx_mailbox2_hwmod, ++ .clk = "l3_iclk_div", ++ .user = OCP_USER_MPU | OCP_USER_SDMA, ++}; ++ ++/* l4_per3 -> mailbox3 */ ++static struct omap_hwmod_ocp_if dra7xx_l4_per3__mailbox3 = { ++ .master = &dra7xx_l4_per3_hwmod, ++ .slave = &dra7xx_mailbox3_hwmod, ++ .clk = "l3_iclk_div", ++ .user = OCP_USER_MPU | OCP_USER_SDMA, ++}; ++ ++/* l4_per3 -> mailbox4 */ ++static struct omap_hwmod_ocp_if dra7xx_l4_per3__mailbox4 = { ++ .master = &dra7xx_l4_per3_hwmod, ++ .slave = &dra7xx_mailbox4_hwmod, ++ .clk = "l3_iclk_div", ++ .user = OCP_USER_MPU | OCP_USER_SDMA, ++}; ++ ++/* l4_per3 -> mailbox5 */ ++static struct omap_hwmod_ocp_if dra7xx_l4_per3__mailbox5 = { ++ .master = &dra7xx_l4_per3_hwmod, ++ .slave = &dra7xx_mailbox5_hwmod, ++ .clk = "l3_iclk_div", ++ .user = OCP_USER_MPU | OCP_USER_SDMA, ++}; ++ ++/* l4_per3 -> mailbox6 */ ++static struct omap_hwmod_ocp_if dra7xx_l4_per3__mailbox6 = { ++ .master = &dra7xx_l4_per3_hwmod, ++ .slave = &dra7xx_mailbox6_hwmod, ++ .clk = "l3_iclk_div", ++ .user = OCP_USER_MPU | OCP_USER_SDMA, ++}; ++ ++/* l4_per3 -> mailbox7 */ ++static struct omap_hwmod_ocp_if dra7xx_l4_per3__mailbox7 = { ++ .master = &dra7xx_l4_per3_hwmod, ++ .slave = &dra7xx_mailbox7_hwmod, ++ .clk = "l3_iclk_div", ++ .user = OCP_USER_MPU | OCP_USER_SDMA, ++}; ++ ++/* l4_per3 -> mailbox8 */ ++static struct omap_hwmod_ocp_if dra7xx_l4_per3__mailbox8 = { ++ .master = &dra7xx_l4_per3_hwmod, ++ .slave = &dra7xx_mailbox8_hwmod, ++ .clk = "l3_iclk_div", ++ .user = OCP_USER_MPU | OCP_USER_SDMA, ++}; ++ ++/* l4_per3 -> mailbox9 */ ++static struct omap_hwmod_ocp_if dra7xx_l4_per3__mailbox9 = { ++ .master = &dra7xx_l4_per3_hwmod, ++ .slave = &dra7xx_mailbox9_hwmod, ++ .clk = "l3_iclk_div", ++ .user = OCP_USER_MPU | OCP_USER_SDMA, ++}; ++ ++/* l4_per3 -> mailbox10 */ ++static struct omap_hwmod_ocp_if dra7xx_l4_per3__mailbox10 = { ++ .master = &dra7xx_l4_per3_hwmod, ++ .slave = &dra7xx_mailbox10_hwmod, ++ .clk = "l3_iclk_div", ++ .user = OCP_USER_MPU | OCP_USER_SDMA, ++}; ++ ++/* l4_per3 -> mailbox11 */ ++static struct omap_hwmod_ocp_if dra7xx_l4_per3__mailbox11 = { ++ .master = &dra7xx_l4_per3_hwmod, ++ .slave = &dra7xx_mailbox11_hwmod, ++ .clk = "l3_iclk_div", ++ .user = OCP_USER_MPU | OCP_USER_SDMA, ++}; ++ ++/* l4_per3 -> mailbox12 */ ++static struct omap_hwmod_ocp_if dra7xx_l4_per3__mailbox12 = { ++ .master = &dra7xx_l4_per3_hwmod, ++ .slave = &dra7xx_mailbox12_hwmod, ++ .clk = "l3_iclk_div", ++ .user = OCP_USER_MPU | OCP_USER_SDMA, ++}; ++ ++/* l4_per3 -> mailbox13 */ ++static struct omap_hwmod_ocp_if dra7xx_l4_per3__mailbox13 = { ++ .master = &dra7xx_l4_per3_hwmod, ++ .slave = &dra7xx_mailbox13_hwmod, ++ .clk = "l3_iclk_div", ++ .user = OCP_USER_MPU | OCP_USER_SDMA, ++}; ++ + /* l4_per1 -> mcspi1 */ + static struct omap_hwmod_ocp_if dra7xx_l4_per1__mcspi1 = { + .master = &dra7xx_l4_per1_hwmod, +@@ -2319,21 +2758,11 @@ static struct omap_hwmod_ocp_if dra7xx_l + .user = OCP_USER_MPU | OCP_USER_SDMA, + }; + +-static struct omap_hwmod_addr_space dra7xx_ocp2scp1_addrs[] = { +- { +- .pa_start = 0x4a080000, +- .pa_end = 0x4a08001f, +- .flags = ADDR_TYPE_RT +- }, +- { } +-}; +- + /* l4_cfg -> ocp2scp1 */ + static struct omap_hwmod_ocp_if dra7xx_l4_cfg__ocp2scp1 = { + .master = &dra7xx_l4_cfg_hwmod, + .slave = &dra7xx_ocp2scp1_hwmod, + .clk = "l4_root_clk_div", +- .addr = dra7xx_ocp2scp1_addrs, + .user = OCP_USER_MPU | OCP_USER_SDMA, + }; + +@@ -2355,6 +2784,14 @@ static struct omap_hwmod_ocp_if dra7xx_l + .user = OCP_USER_MPU | OCP_USER_SDMA, + }; + ++/* l4_per3 -> rtcss */ ++static struct omap_hwmod_ocp_if dra7xx_l4_per3__rtcss = { ++ .master = &dra7xx_l4_per3_hwmod, ++ .slave = &dra7xx_rtcss_hwmod, ++ .clk = "l4_root_clk_div", ++ .user = OCP_USER_MPU | OCP_USER_SDMA, ++}; ++ + static struct omap_hwmod_addr_space dra7xx_sata_addrs[] = { + { + .name = "sysc", +@@ -2636,6 +3073,14 @@ static struct omap_hwmod_ocp_if dra7xx_l + .user = OCP_USER_MPU | OCP_USER_SDMA, + }; + ++/* l4_per3 -> vpe */ ++static struct omap_hwmod_ocp_if dra7xx_l4_per3__vpe = { ++ .master = &dra7xx_l4_per3_hwmod, ++ .slave = &dra7xx_vpe_hwmod, ++ .clk = "l3_iclk_div", ++ .user = OCP_USER_MPU | OCP_USER_SDMA, ++}; ++ + static struct omap_hwmod_ocp_if *dra7xx_hwmod_ocp_ifs[] __initdata = { + &dra7xx_l3_main_2__l3_instr, + &dra7xx_l4_cfg__l3_main_1, +@@ -2653,10 +3098,13 @@ static struct omap_hwmod_ocp_if *dra7xx_ + &dra7xx_l4_wkup__ctrl_module_wkup, + &dra7xx_l4_wkup__dcan1, + &dra7xx_l4_per2__dcan2, ++ &dra7xx_l4_per2__cpgmac0, ++ &dra7xx_gmac__mdio, + &dra7xx_l4_cfg__dma_system, + &dra7xx_l3_main_1__dss, + &dra7xx_l3_main_1__dispc, + &dra7xx_l3_main_1__hdmi, ++ &dra7xx_l3_main_1__aes, + &dra7xx_l4_per1__elm, + &dra7xx_l4_wkup__gpio1, + &dra7xx_l4_per1__gpio2, +@@ -2673,6 +3121,19 @@ static struct omap_hwmod_ocp_if *dra7xx_ + &dra7xx_l4_per1__i2c3, + &dra7xx_l4_per1__i2c4, + &dra7xx_l4_per1__i2c5, ++ &dra7xx_l4_cfg__mailbox1, ++ &dra7xx_l4_per3__mailbox2, ++ &dra7xx_l4_per3__mailbox3, ++ &dra7xx_l4_per3__mailbox4, ++ &dra7xx_l4_per3__mailbox5, ++ &dra7xx_l4_per3__mailbox6, ++ &dra7xx_l4_per3__mailbox7, ++ &dra7xx_l4_per3__mailbox8, ++ &dra7xx_l4_per3__mailbox9, ++ &dra7xx_l4_per3__mailbox10, ++ &dra7xx_l4_per3__mailbox11, ++ &dra7xx_l4_per3__mailbox12, ++ &dra7xx_l4_per3__mailbox13, + &dra7xx_l4_per1__mcspi1, + &dra7xx_l4_per1__mcspi2, + &dra7xx_l4_per1__mcspi3, +@@ -2683,7 +3144,9 @@ static struct omap_hwmod_ocp_if *dra7xx_ + &dra7xx_l4_per1__mmc4, + &dra7xx_l4_cfg__mpu, + &dra7xx_l4_cfg__ocp2scp1, ++ &dra7xx_l4_cfg__ocp2scp3, + &dra7xx_l3_main_1__qspi, ++ &dra7xx_l4_per3__rtcss, + &dra7xx_l4_cfg__sata, + &dra7xx_l4_cfg__smartreflex_core, + &dra7xx_l4_cfg__smartreflex_mpu, +@@ -2705,6 +3168,7 @@ static struct omap_hwmod_ocp_if *dra7xx_ + &dra7xx_l4_per1__uart4, + &dra7xx_l4_per1__uart5, + &dra7xx_l4_per1__uart6, ++ &dra7xx_l4_per1__des, + &dra7xx_l4_per3__usb_otg_ss1, + &dra7xx_l4_per3__usb_otg_ss2, + &dra7xx_l4_per3__usb_otg_ss3, +@@ -2714,6 +3178,7 @@ static struct omap_hwmod_ocp_if *dra7xx_ + &dra7xx_l3_main_1__vcp2, + &dra7xx_l4_per2__vcp2, + &dra7xx_l4_wkup__wd_timer2, ++ &dra7xx_l4_per3__vpe, + NULL, + }; + +--- a/arch/arm/mach-omap2/omap_hwmod.c ++++ b/arch/arm/mach-omap2/omap_hwmod.c +@@ -141,6 +141,7 @@ + #include <linux/cpu.h> + #include <linux/of.h> + #include <linux/of_address.h> ++#include <linux/suspend.h> + + #include <asm/system_misc.h> + +@@ -208,6 +209,9 @@ static struct omap_hwmod *mpu_oh; + /* io_chain_lock: used to serialize reconfigurations of the I/O chain */ + static DEFINE_SPINLOCK(io_chain_lock); + ++/* _oh_force_mstandby_repeated_list for tracking nonstandard mstandby hwmods */ ++static LIST_HEAD(_oh_force_mstandby_repeated_list); ++ + /* + * linkspace: ptr to a buffer that struct omap_hwmod_link records are + * allocated from - used to reduce the number of small memory +@@ -656,6 +660,8 @@ static struct clockdomain *_get_clkdm(st + if (oh->clkdm) { + return oh->clkdm; + } else if (oh->_clk) { ++ if (__clk_get_flags(oh->_clk) & CLK_IS_BASIC) ++ return NULL; + clk = to_clk_hw_omap(__clk_get_hw(oh->_clk)); + return clk->clkdm; + } +@@ -728,14 +734,18 @@ static int _del_initiator_dep(struct oma + * functional clock pointer) if a main_clk is present. Returns 0 on + * success or -EINVAL on error. + */ +-static int _init_main_clk(struct omap_hwmod *oh) ++static int _init_main_clk(struct omap_hwmod *oh, struct device_node *np) + { + int ret = 0; + +- if (!oh->main_clk) ++ if (!oh->main_clk && !of_get_property(np, "clocks", NULL)) + return 0; + +- oh->_clk = clk_get(NULL, oh->main_clk); ++ if (oh->main_clk) ++ oh->_clk = clk_get(NULL, oh->main_clk); ++ else ++ oh->_clk = of_clk_get_by_name(np, "fck"); ++ + if (IS_ERR(oh->_clk)) { + pr_warning("omap_hwmod: %s: cannot clk_get main_clk %s\n", + oh->name, oh->main_clk); +@@ -801,6 +811,63 @@ static int _init_interface_clks(struct o + return ret; + } + ++static const char **_parse_opt_clks_dt(struct omap_hwmod *oh, ++ struct device_node *np, ++ int *opt_clks_cnt) ++{ ++ int i, clks_cnt; ++ const char *clk_name; ++ const char **opt_clk_names; ++ ++ clks_cnt = of_property_count_strings(np, "clock-names"); ++ if (!clks_cnt) ++ return NULL; ++ ++ opt_clk_names = kzalloc(sizeof(char *)*clks_cnt, GFP_KERNEL); ++ if (!opt_clk_names) ++ return NULL; ++ ++ for (i = 0; i < clks_cnt; i++) { ++ of_property_read_string_index(np, "clock-names", i, &clk_name); ++ if (!strcmp(clk_name, "fck")) ++ continue; ++ opt_clk_names[(*opt_clks_cnt)++] = clk_name; ++ } ++ return opt_clk_names; ++} ++ ++static int _init_opt_clks_dt(struct omap_hwmod *oh, struct device_node *np) ++{ ++ struct clk *c; ++ int i, opt_clks_cnt = 0; ++ int ret = 0; ++ const char **opt_clk_names; ++ ++ opt_clk_names = _parse_opt_clks_dt(oh, np, &opt_clks_cnt); ++ if (!opt_clk_names) ++ return -EINVAL; ++ ++ oh->opt_clks = kzalloc(sizeof(struct omap_hwmod_opt_clk *) ++ * opt_clks_cnt, GFP_KERNEL); ++ if (!oh->opt_clks) ++ return -ENOMEM; ++ ++ oh->opt_clks_cnt = opt_clks_cnt; ++ ++ for (i = 0; i < opt_clks_cnt; i++) { ++ c = of_clk_get_by_name(np, opt_clk_names[i]); ++ if (IS_ERR(c)) { ++ pr_warn("omap_hwmod: %s: cannot clk_get opt_clk %s\n", ++ oh->name, opt_clk_names[i]); ++ ret = -EINVAL; ++ } ++ oh->opt_clks[i]._clk = c; ++ oh->opt_clks[i].role = opt_clk_names[i]; ++ clk_prepare(oh->opt_clks[i]._clk); ++ } ++ return ret; ++} ++ + /** + * _init_opt_clk - get a struct clk * for the the hwmod's optional clocks + * @oh: struct omap_hwmod * +@@ -808,13 +875,16 @@ static int _init_interface_clks(struct o + * Called from _init_clocks(). Populates the @oh omap_hwmod_opt_clk + * clock pointers. Returns 0 on success or -EINVAL on error. + */ +-static int _init_opt_clks(struct omap_hwmod *oh) ++static int _init_opt_clks(struct omap_hwmod *oh, struct device_node *np) + { + struct omap_hwmod_opt_clk *oc; + struct clk *c; + int i; + int ret = 0; + ++ if (of_get_property(np, "clocks", NULL)) ++ return _init_opt_clks_dt(oh, np); ++ + for (i = oh->opt_clks_cnt, oc = oh->opt_clks; i > 0; i--, oc++) { + c = clk_get(NULL, oc->clk); + if (IS_ERR(c)) { +@@ -1544,7 +1614,7 @@ static int _init_clkdm(struct omap_hwmod + if (!oh->clkdm) { + pr_warning("omap_hwmod: %s: could not associate to clkdm %s\n", + oh->name, oh->clkdm_name); +- return -EINVAL; ++ return 0; + } + + pr_debug("omap_hwmod: %s: associated to clkdm %s\n", +@@ -1563,7 +1633,8 @@ static int _init_clkdm(struct omap_hwmod + * Resolves all clock names embedded in the hwmod. Returns 0 on + * success, or a negative error code on failure. + */ +-static int _init_clocks(struct omap_hwmod *oh, void *data) ++static int _init_clocks(struct omap_hwmod *oh, void *data, ++ struct device_node *np) + { + int ret = 0; + +@@ -1575,9 +1646,9 @@ static int _init_clocks(struct omap_hwmo + if (soc_ops.init_clkdm) + ret |= soc_ops.init_clkdm(oh); + +- ret |= _init_main_clk(oh); ++ ret |= _init_main_clk(oh, np); + ret |= _init_interface_clks(oh); +- ret |= _init_opt_clks(oh); ++ ret |= _init_opt_clks(oh, np); + + if (!ret) + oh->_state = _HWMOD_STATE_CLKS_INITED; +@@ -2363,11 +2434,11 @@ static struct device_node *of_dev_hwmod_ + * are part of the device's address space can be ioremapped properly. + * No return value. + */ +-static void __init _init_mpu_rt_base(struct omap_hwmod *oh, void *data) ++static void __init _init_mpu_rt_base(struct omap_hwmod *oh, void *data, ++ struct device_node *np) + { + struct omap_hwmod_addr_space *mem; + void __iomem *va_start = NULL; +- struct device_node *np; + + if (!oh) + return; +@@ -2383,12 +2454,10 @@ static void __init _init_mpu_rt_base(str + oh->name); + + /* Extract the IO space from device tree blob */ +- if (!of_have_populated_dt()) ++ if (!np) + return; + +- np = of_dev_hwmod_lookup(of_find_node_by_name(NULL, "ocp"), oh); +- if (np) +- va_start = of_iomap(np, oh->mpu_rt_idx); ++ va_start = of_iomap(np, oh->mpu_rt_idx); + } else { + va_start = ioremap(mem->pa_start, mem->pa_end - mem->pa_start); + } +@@ -2420,19 +2489,31 @@ static void __init _init_mpu_rt_base(str + static int __init _init(struct omap_hwmod *oh, void *data) + { + int r; ++ struct device_node *np = NULL; + + if (oh->_state != _HWMOD_STATE_REGISTERED) + return 0; + ++ /* If booting with DT, parse the DT node for IO space/clocks etc */ ++ if (of_have_populated_dt()) ++ np = of_dev_hwmod_lookup(of_find_node_by_name(NULL, "ocp"), oh); ++ + if (oh->class->sysc) +- _init_mpu_rt_base(oh, NULL); ++ _init_mpu_rt_base(oh, NULL, np); + +- r = _init_clocks(oh, NULL); ++ r = _init_clocks(oh, NULL, np); + if (r < 0) { + WARN(1, "omap_hwmod: %s: couldn't init clocks\n", oh->name); + return -EINVAL; + } + ++ if (np) { ++ if (of_find_property(np, "ti,no-reset", NULL)) ++ oh->flags |= HWMOD_INIT_NO_RESET; ++ if (of_find_property(np, "ti,no-idle", NULL)) ++ oh->flags |= HWMOD_INIT_NO_IDLE; ++ } ++ + oh->_state = _HWMOD_STATE_INITIALIZED; + + return 0; +@@ -3826,6 +3907,75 @@ int omap_hwmod_disable_wakeup(struct oma + return 0; + } + ++/* ++ * There are some IPs that do not have MSTANDBY asserted by default ++ * which is necessary for PER domain transition. If the drivers ++ * are not compiled into the kernel HWMOD code will not change the ++ * state of the IPs if the IP was never enabled, so we keep track of ++ * them here to idle them with a pm_notifier. ++ */ ++ ++static int _omap_mstandby_pm_notifier(struct notifier_block *self, ++ unsigned long action, void *dev) ++{ ++ struct omap_hwmod_list *oh_list_item = NULL; ++ switch (action) { ++ case PM_POST_SUSPEND: ++ list_for_each_entry(oh_list_item, ++ &_oh_force_mstandby_repeated_list, oh_list) { ++ omap_hwmod_enable(oh_list_item->oh); ++ omap_hwmod_idle(oh_list_item->oh); ++ } ++ } ++ ++ return NOTIFY_DONE; ++} ++ ++struct notifier_block pm_nb = { ++ .notifier_call = _omap_mstandby_pm_notifier, ++}; ++ ++static int _check_for_force_mstandby_repeated(struct omap_hwmod *oh, void *data) ++{ ++ if (oh->flags & HWMOD_FORCE_MSTANDBY_REPEATED) ++ omap_hwmod_enable_force_mstandby_repeated(oh); ++ ++ return 0; ++} ++ ++int omap_hwmod_force_mstandby_repeated(void) ++{ ++ omap_hwmod_for_each(_check_for_force_mstandby_repeated, NULL); ++ register_pm_notifier(&pm_nb); ++ return 0; ++} ++ ++int omap_hwmod_enable_force_mstandby_repeated(struct omap_hwmod *oh) ++{ ++ struct omap_hwmod_list *oh_list_item = NULL; ++ ++ oh_list_item = kzalloc(sizeof(*oh_list_item), GFP_KERNEL); ++ oh_list_item->oh = oh; ++ list_add(&oh_list_item->oh_list, &_oh_force_mstandby_repeated_list); ++ ++ return 0; ++} ++ ++int omap_hwmod_disable_force_mstandby_repeated(struct omap_hwmod *oh) ++{ ++ struct omap_hwmod_list *oh_list_item, *tmp; ++ ++ list_for_each_entry_safe(oh_list_item, tmp, ++ &_oh_force_mstandby_repeated_list, oh_list) { ++ if (oh_list_item->oh == oh) { ++ list_del(&oh_list_item->oh_list); ++ kfree(oh_list_item); ++ } ++ } ++ ++ return 0; ++} ++ + /** + * omap_hwmod_assert_hardreset - assert the HW reset line of submodules + * contained in the hwmod module. +@@ -4115,6 +4265,7 @@ void __init omap_hwmod_init(void) + soc_ops.assert_hardreset = _omap2_assert_hardreset; + soc_ops.deassert_hardreset = _omap2_deassert_hardreset; + soc_ops.is_hardreset_asserted = _omap2_is_hardreset_asserted; ++ soc_ops.init_clkdm = _init_clkdm; + } else if (cpu_is_omap44xx() || soc_is_omap54xx() || soc_is_dra7xx()) { + soc_ops.enable_module = _omap4_enable_module; + soc_ops.disable_module = _omap4_disable_module; +@@ -4125,6 +4276,14 @@ void __init omap_hwmod_init(void) + soc_ops.init_clkdm = _init_clkdm; + soc_ops.update_context_lost = _omap4_update_context_lost; + soc_ops.get_context_lost = _omap4_get_context_lost; ++ } else if (soc_is_am43xx()) { ++ soc_ops.enable_module = _omap4_enable_module; ++ soc_ops.disable_module = _omap4_disable_module; ++ soc_ops.wait_target_ready = _omap4_wait_target_ready; ++ soc_ops.assert_hardreset = _omap4_assert_hardreset; ++ soc_ops.deassert_hardreset = _omap4_deassert_hardreset; ++ soc_ops.is_hardreset_asserted = _omap4_is_hardreset_asserted; ++ soc_ops.init_clkdm = _init_clkdm; + } else if (soc_is_am33xx()) { + soc_ops.enable_module = _am33xx_enable_module; + soc_ops.disable_module = _am33xx_disable_module; +--- a/arch/arm/mach-omap2/omap_hwmod_common_data.c ++++ b/arch/arm/mach-omap2/omap_hwmod_common_data.c +@@ -59,6 +59,16 @@ struct omap_hwmod_sysc_fields omap_hwmod + .sidle_shift = SYSC_TYPE3_SIDLEMODE_SHIFT, + }; + ++/** ++ * struct omap_hwmod_sysc_type4 - TYPE4 sysconfig scheme. ++ * Used by some IPs on AM33xx ++ */ ++struct omap_hwmod_sysc_fields omap_hwmod_sysc_type4 = { ++ .sidle_shift = SYSC_TYPE4_SIDLEMODE_SHIFT, ++ .srst_shift = SYSC_TYPE4_SOFTRESET_SHIFT, ++ .autoidle_shift = SYSC_TYPE4_AUTOIDLE_SHIFT, ++}; ++ + struct omap_dss_dispc_dev_attr omap2_3_dss_dispc_dev_attr = { + .manager_count = 2, + .has_framedonetv_irq = 0 +--- a/arch/arm/mach-omap2/omap_hwmod.h ++++ b/arch/arm/mach-omap2/omap_hwmod.h +@@ -41,6 +41,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; ++extern struct omap_hwmod_sysc_fields omap_hwmod_sysc_type4; + + /* + * OCP SYSCONFIG bit shifts/masks TYPE1. These are for IPs compliant +@@ -81,6 +82,16 @@ extern struct omap_hwmod_sysc_fields oma + #define SYSC_TYPE3_MIDLEMODE_SHIFT 2 + #define SYSC_TYPE3_MIDLEMODE_MASK (0x3 << SYSC_TYPE3_MIDLEMODE_SHIFT) + ++/* ++ * OCP SYSCONFIG bit shifts/masks TYPE4. ++ */ ++#define SYSC_TYPE4_SIDLEMODE_SHIFT 2 ++#define SYSC_TYPE4_SIDLEMODE_MASK (0x3 << SYSC_TYPE4_SIDLEMODE_SHIFT) ++#define SYSC_TYPE4_SOFTRESET_SHIFT 1 ++#define SYSC_TYPE4_SOFTRESET_MASK (1 << SYSC_TYPE4_SOFTRESET_SHIFT) ++#define SYSC_TYPE4_AUTOIDLE_SHIFT 0 ++#define SYSC_TYPE4_AUTOIDLE_MASK (1 << SYSC_TYPE4_AUTOIDLE_SHIFT) ++ + /* OCP SYSSTATUS bit shifts/masks */ + #define SYSS_RESETDONE_SHIFT 0 + #define SYSS_RESETDONE_MASK (1 << SYSS_RESETDONE_SHIFT) +@@ -528,6 +539,7 @@ struct omap_hwmod_omap4_prcm { + #define HWMOD_BLOCK_WFI (1 << 10) + #define HWMOD_FORCE_MSTANDBY (1 << 11) + #define HWMOD_SWSUP_SIDLE_ACT (1 << 12) ++#define HWMOD_FORCE_MSTANDBY_REPEATED (1 << 13) + + /* + * omap_hwmod._int_flags definitions +@@ -678,6 +690,11 @@ struct omap_hwmod { + u8 _postsetup_state; + }; + ++struct omap_hwmod_list { ++ struct omap_hwmod *oh; ++ struct list_head oh_list; ++}; ++ + struct omap_hwmod *omap_hwmod_lookup(const char *name); + int omap_hwmod_for_each(int (*fn)(struct omap_hwmod *oh, void *data), + void *data); +@@ -731,6 +748,10 @@ int omap_hwmod_no_setup_reset(struct oma + + int omap_hwmod_pad_route_irq(struct omap_hwmod *oh, int pad_idx, int irq_idx); + ++int omap_hwmod_force_mstandby_repeated(void); ++int omap_hwmod_enable_force_mstandby_repeated(struct omap_hwmod *oh); ++int omap_hwmod_disable_force_mstandby_repeated(struct omap_hwmod *oh); ++ + extern void __init omap_hwmod_init(void); + + const char *omap_hwmod_get_main_clk(struct omap_hwmod *oh); +--- a/arch/arm/mach-omap2/omap-mpuss-lowpower.c ++++ b/arch/arm/mach-omap2/omap-mpuss-lowpower.c +@@ -56,6 +56,7 @@ + #include "omap4-sar-layout.h" + #include "pm.h" + #include "prcm_mpu44xx.h" ++#include "prcm_mpu54xx.h" + #include "prminst44xx.h" + #include "prcm44xx.h" + #include "prm44xx.h" +@@ -84,11 +85,13 @@ struct cpu_pm_ops { + int (*finish_suspend)(unsigned long cpu_state); + void (*resume)(void); + void (*scu_prepare)(unsigned int cpu_id, unsigned int cpu_state); ++ void (*hotplug_restart)(void); + }; + + static DEFINE_PER_CPU(struct omap4_cpu_pm_info, omap4_pm_info); + static struct powerdomain *mpuss_pd; + static void __iomem *sar_base; ++static u32 cpu_context_offset; + + static int default_finish_suspend(unsigned long cpu_state) + { +@@ -106,6 +109,7 @@ struct cpu_pm_ops omap_pm_ops = { + .finish_suspend = default_finish_suspend, + .resume = dummy_cpu_resume, + .scu_prepare = dummy_scu_prepare, ++ .hotplug_restart = dummy_cpu_resume, + }; + + /* +@@ -116,7 +120,8 @@ static inline void set_cpu_wakeup_addr(u + { + struct omap4_cpu_pm_info *pm_info = &per_cpu(omap4_pm_info, cpu_id); + +- __raw_writel(addr, pm_info->wkup_sar_addr); ++ if (pm_info->wkup_sar_addr) ++ __raw_writel(addr, pm_info->wkup_sar_addr); + } + + /* +@@ -127,6 +132,9 @@ static void scu_pwrst_prepare(unsigned i + struct omap4_cpu_pm_info *pm_info = &per_cpu(omap4_pm_info, cpu_id); + u32 scu_pwr_st; + ++ if (!pm_info->scu_sar_addr) ++ return; ++ + switch (cpu_state) { + case PWRDM_POWER_RET: + scu_pwr_st = SCU_PM_DORMANT; +@@ -161,14 +169,14 @@ static inline void cpu_clear_prev_logic_ + + if (cpu_id) { + reg = omap4_prcm_mpu_read_inst_reg(OMAP4430_PRCM_MPU_CPU1_INST, +- OMAP4_RM_CPU1_CPU1_CONTEXT_OFFSET); ++ cpu_context_offset); + omap4_prcm_mpu_write_inst_reg(reg, OMAP4430_PRCM_MPU_CPU1_INST, +- OMAP4_RM_CPU1_CPU1_CONTEXT_OFFSET); ++ cpu_context_offset); + } else { + reg = omap4_prcm_mpu_read_inst_reg(OMAP4430_PRCM_MPU_CPU0_INST, +- OMAP4_RM_CPU0_CPU0_CONTEXT_OFFSET); ++ cpu_context_offset); + omap4_prcm_mpu_write_inst_reg(reg, OMAP4430_PRCM_MPU_CPU0_INST, +- OMAP4_RM_CPU0_CPU0_CONTEXT_OFFSET); ++ cpu_context_offset); + } + } + +@@ -179,7 +187,8 @@ static void l2x0_pwrst_prepare(unsigned + { + struct omap4_cpu_pm_info *pm_info = &per_cpu(omap4_pm_info, cpu_id); + +- __raw_writel(save_state, pm_info->l2x0_sar_addr); ++ if (pm_info->l2x0_sar_addr) ++ __raw_writel(save_state, pm_info->l2x0_sar_addr); + } + + /* +@@ -235,6 +244,8 @@ int omap4_enter_lowpower(unsigned int cp + save_state = 1; + break; + case PWRDM_POWER_RET: ++ save_state = 0; ++ break; + default: + /* + * CPUx CSWR is invalid hardware state. Also CPUx OSWR +@@ -304,7 +315,7 @@ int omap4_hotplug_cpu(unsigned int cpu, + + pwrdm_clear_all_prev_pwrst(pm_info->pwrdm); + pwrdm_set_next_pwrst(pm_info->pwrdm, power_state); +- set_cpu_wakeup_addr(cpu, virt_to_phys(pm_info->secondary_startup)); ++ set_cpu_wakeup_addr(cpu, virt_to_phys(omap_pm_ops.hotplug_restart)); + omap_pm_ops.scu_prepare(cpu, power_state); + + /* +@@ -320,11 +331,26 @@ int omap4_hotplug_cpu(unsigned int cpu, + + + /* ++ * Enable Mercury Fast HG retention mode by default. ++ */ ++static void enable_mercury_retention_mode(void) ++{ ++ u32 reg; ++ ++ reg = omap4_prcm_mpu_read_inst_reg(OMAP54XX_PRCM_MPU_DEVICE_INST, ++ OMAP54XX_PRCM_MPU_PRM_PSCON_COUNT_OFFSET); ++ reg |= BIT(24) | BIT(25); ++ omap4_prcm_mpu_write_inst_reg(reg, OMAP54XX_PRCM_MPU_DEVICE_INST, ++ OMAP54XX_PRCM_MPU_PRM_PSCON_COUNT_OFFSET); ++} ++ ++/* + * Initialise OMAP4 MPUSS + */ + int __init omap4_mpuss_init(void) + { + struct omap4_cpu_pm_info *pm_info; ++ u32 cpu_wakeup_addr = 0; + + if (omap_rev() == OMAP4430_REV_ES1_0) { + WARN(1, "Power Management not supported on OMAP4430 ES1.0\n"); +@@ -334,10 +360,16 @@ int __init omap4_mpuss_init(void) + sar_base = omap4_get_sar_ram_base(); + + /* Initilaise per CPU PM information */ ++ if (cpu_is_omap44xx()) ++ cpu_wakeup_addr = CPU0_WAKEUP_NS_PA_ADDR_OFFSET; ++ else if (soc_is_omap54xx()) ++ cpu_wakeup_addr = OMAP5_CPU0_WAKEUP_NS_PA_ADDR_OFFSET; + pm_info = &per_cpu(omap4_pm_info, 0x0); +- pm_info->scu_sar_addr = sar_base + SCU_OFFSET0; +- pm_info->wkup_sar_addr = sar_base + CPU0_WAKEUP_NS_PA_ADDR_OFFSET; +- pm_info->l2x0_sar_addr = sar_base + L2X0_SAVE_OFFSET0; ++ if (sar_base) { ++ pm_info->scu_sar_addr = sar_base + SCU_OFFSET0; ++ pm_info->wkup_sar_addr = sar_base + cpu_wakeup_addr; ++ pm_info->l2x0_sar_addr = sar_base + L2X0_SAVE_OFFSET0; ++ } + pm_info->pwrdm = pwrdm_lookup("cpu0_pwrdm"); + if (!pm_info->pwrdm) { + pr_err("Lookup failed for CPU0 pwrdm\n"); +@@ -351,14 +383,17 @@ int __init omap4_mpuss_init(void) + /* Initialise CPU0 power domain state to ON */ + pwrdm_set_next_pwrst(pm_info->pwrdm, PWRDM_POWER_ON); + ++ if (cpu_is_omap44xx()) ++ cpu_wakeup_addr = CPU1_WAKEUP_NS_PA_ADDR_OFFSET; ++ else if (soc_is_omap54xx()) ++ cpu_wakeup_addr = OMAP5_CPU1_WAKEUP_NS_PA_ADDR_OFFSET; ++ + pm_info = &per_cpu(omap4_pm_info, 0x1); +- pm_info->scu_sar_addr = sar_base + SCU_OFFSET1; +- pm_info->wkup_sar_addr = sar_base + CPU1_WAKEUP_NS_PA_ADDR_OFFSET; +- pm_info->l2x0_sar_addr = sar_base + L2X0_SAVE_OFFSET1; +- if (cpu_is_omap446x()) +- pm_info->secondary_startup = omap4460_secondary_startup; +- else +- pm_info->secondary_startup = omap4_secondary_startup; ++ if (sar_base) { ++ pm_info->scu_sar_addr = sar_base + SCU_OFFSET1; ++ pm_info->wkup_sar_addr = sar_base + cpu_wakeup_addr; ++ pm_info->l2x0_sar_addr = sar_base + L2X0_SAVE_OFFSET1; ++ } + + pm_info->pwrdm = pwrdm_lookup("cpu1_pwrdm"); + if (!pm_info->pwrdm) { +@@ -382,19 +417,32 @@ int __init omap4_mpuss_init(void) + mpuss_clear_prev_logic_pwrst(); + + /* Save device type on scratchpad for low level code to use */ +- if (omap_type() != OMAP2_DEVICE_TYPE_GP) +- __raw_writel(1, sar_base + OMAP_TYPE_OFFSET); +- else +- __raw_writel(0, sar_base + OMAP_TYPE_OFFSET); ++ if (sar_base) { ++ if (omap_type() != OMAP2_DEVICE_TYPE_GP) ++ __raw_writel(1, sar_base + OMAP_TYPE_OFFSET); ++ else ++ __raw_writel(0, sar_base + OMAP_TYPE_OFFSET); + +- save_l2x0_context(); ++ save_l2x0_context(); ++ } + + if (cpu_is_omap44xx()) { + omap_pm_ops.finish_suspend = omap4_finish_suspend; ++ omap_pm_ops.hotplug_restart = omap4_secondary_startup; + omap_pm_ops.resume = omap4_cpu_resume; + omap_pm_ops.scu_prepare = scu_pwrst_prepare; ++ cpu_context_offset = OMAP4_RM_CPU0_CPU0_CONTEXT_OFFSET; ++ } else if (soc_is_omap54xx() || soc_is_dra7xx()) { ++ omap_pm_ops.finish_suspend = omap5_finish_suspend; ++ omap_pm_ops.hotplug_restart = omap5_secondary_startup; ++ omap_pm_ops.resume = omap5_cpu_resume; ++ cpu_context_offset = OMAP54XX_RM_CPU0_CPU0_CONTEXT_OFFSET; ++ enable_mercury_retention_mode(); + } + ++ if (cpu_is_omap446x()) ++ omap_pm_ops.hotplug_restart = omap4460_secondary_startup; ++ + return 0; + } + +--- a/arch/arm/mach-omap2/omap-secure.h ++++ b/arch/arm/mach-omap2/omap-secure.h +@@ -34,6 +34,10 @@ + #define OMAP4_HAL_SAVEHW_INDEX 0x1b + #define OMAP4_HAL_SAVEALL_INDEX 0x1c + #define OMAP4_HAL_SAVEGIC_INDEX 0x1d ++#define OMAP5_HAL_SAVESECURERAM_INDEX 0x1c ++#define OMAP5_HAL_SAVEHW_INDEX 0x1d ++#define OMAP5_HAL_SAVEALL_INDEX 0x1e ++#define OMAP5_HAL_SAVEGIC_INDEX 0x1f + + /* Secure Monitor mode APIs */ + #define OMAP4_MON_SCU_PWR_INDEX 0x108 +@@ -41,6 +45,13 @@ + #define OMAP4_MON_L2X0_CTRL_INDEX 0x102 + #define OMAP4_MON_L2X0_AUXCTRL_INDEX 0x109 + #define OMAP4_MON_L2X0_PREFETCH_INDEX 0x113 ++#define OMAP5_MON_CACHES_CLEAN_INDEX 0x103 ++#define OMAP5_MON_AUX_CTRL_INDEX 0x107 ++#define OMAP5_MON_L2AUX_CTRL_INDEX 0x104 ++ ++#define OMAP5_MON_AMBA_IF_INDEX 0x108 ++ ++#define OMAP5_DRA7_MON_SET_CNTFRQ_INDEX 0x109 + + /* Secure PPA(Primary Protected Application) APIs */ + #define OMAP4_PPA_L2_POR_INDEX 0x23 +--- a/arch/arm/mach-omap2/omap-smp.c ++++ b/arch/arm/mach-omap2/omap-smp.c +@@ -41,6 +41,8 @@ + + u16 pm44xx_errata; + ++extern unsigned long arch_timer_freq; ++ + /* SCU base address */ + static void __iomem *scu_base; + +@@ -66,6 +68,13 @@ static void omap4_secondary_init(unsigne + 4, 0, 0, 0, 0, 0); + + /* ++ * Configure the CNTFRQ register for the secondary cpu's which ++ * indicates the frequency of the cpu local timers. ++ */ ++ if (soc_is_omap54xx() || soc_is_dra7xx()) ++ omap_smc1(OMAP5_DRA7_MON_SET_CNTFRQ_INDEX, arch_timer_freq); ++ ++ /* + * Synchronise with the boot thread. + */ + spin_lock(&boot_lock); +--- a/arch/arm/mach-omap2/omap-wakeupgen.c ++++ b/arch/arm/mach-omap2/omap-wakeupgen.c +@@ -33,8 +33,11 @@ + #include "omap4-sar-layout.h" + #include "common.h" + +-#define MAX_NR_REG_BANKS 5 +-#define MAX_IRQS 160 ++/* maximum value correspond to that of AM43x */ ++#define MAX_NR_REG_BANKS 7 ++#define MAX_IRQS 224 ++#define DEFAULT_NR_REG_BANKS 5 ++#define DEFAULT_IRQS 160 + #define WKG_MASK_ALL 0x00000000 + #define WKG_UNMASK_ALL 0xffffffff + #define CPU_ENA_OFFSET 0x400 +@@ -47,9 +50,9 @@ static void __iomem *wakeupgen_base; + static void __iomem *sar_base; + static DEFINE_RAW_SPINLOCK(wakeupgen_lock); + static unsigned int irq_target_cpu[MAX_IRQS]; +-static unsigned int irq_banks = MAX_NR_REG_BANKS; +-static unsigned int max_irqs = MAX_IRQS; +-static unsigned int omap_secure_apis; ++static unsigned int irq_banks = DEFAULT_NR_REG_BANKS; ++static unsigned int max_irqs = DEFAULT_IRQS; ++static unsigned int omap_secure_apis, secure_api_index; + + /* + * Static helper functions. +@@ -314,7 +317,7 @@ static void irq_sar_clear(void) + static void irq_save_secure_context(void) + { + u32 ret; +- ret = omap_secure_dispatcher(OMAP4_HAL_SAVEGIC_INDEX, ++ ret = omap_secure_dispatcher(secure_api_index, + FLAG_START_CRITICAL, + 0, 0, 0, 0, 0); + if (ret != API_HAL_RET_VALUE_OK) +@@ -376,8 +379,8 @@ static struct notifier_block irq_notifie + + static void __init irq_pm_init(void) + { +- /* FIXME: Remove this when MPU OSWR support is added */ +- if (!soc_is_omap54xx()) ++ /* No OFF mode support on dra7xx */ ++ if (!soc_is_dra7xx()) + cpu_pm_register_notifier(&irq_notifier_block); + } + #else +@@ -402,6 +405,8 @@ int __init omap_wakeupgen_init(void) + { + int i; + unsigned int boot_cpu = smp_processor_id(); ++ u32 val; ++ bool am43x = soc_is_am43xx() ? true : false; + + /* Not supported on OMAP4 ES1.0 silicon */ + if (omap_rev() == OMAP4430_REV_ES1_0) { +@@ -418,12 +423,19 @@ int __init omap_wakeupgen_init(void) + irq_banks = OMAP4_NR_BANKS; + max_irqs = OMAP4_NR_IRQS; + omap_secure_apis = 1; ++ secure_api_index = OMAP4_HAL_SAVEGIC_INDEX; ++ } else if (soc_is_omap54xx()) { ++ secure_api_index = OMAP5_HAL_SAVEGIC_INDEX; ++ } else if (am43x) { ++ irq_banks = MAX_NR_REG_BANKS; ++ max_irqs = MAX_IRQS; + } + + /* Clear all IRQ bitmasks at wakeupGen level */ + for (i = 0; i < irq_banks; i++) { + wakeupgen_writel(0, i, CPU0_ID); +- wakeupgen_writel(0, i, CPU1_ID); ++ if (!am43x) ++ wakeupgen_writel(0, i, CPU1_ID); + } + + /* +@@ -443,6 +455,19 @@ int __init omap_wakeupgen_init(void) + for (i = 0; i < max_irqs; i++) + irq_target_cpu[i] = boot_cpu; + ++ /* ++ * Enables OMAP5 ES2 PM Mode using ES2_PM_MODE in AMBA_IF_MODE ++ * 0x0: ES1 behavior, CPU cores would enter and exit OFF mode together. ++ * 0x1: ES2 behavior, CPU cores are allowed to enter/exit OFF mode ++ * independently. ++ * This needs to be set one time thanks to always ON domain. ++ */ ++ if (soc_is_omap54xx()) { ++ val = __raw_readl(wakeupgen_base + OMAP_AMBA_IF_MODE); ++ val |= BIT(5); ++ omap_smc1(OMAP5_MON_AMBA_IF_INDEX, val); ++ } ++ + irq_hotplug_init(); + irq_pm_init(); + +--- a/arch/arm/mach-omap2/omap-wakeupgen.h ++++ b/arch/arm/mach-omap2/omap-wakeupgen.h +@@ -27,6 +27,7 @@ + #define OMAP_WKG_ENB_E_1 0x420 + #define OMAP_AUX_CORE_BOOT_0 0x800 + #define OMAP_AUX_CORE_BOOT_1 0x804 ++#define OMAP_AMBA_IF_MODE 0x80c + #define OMAP_PTMSYNCREQ_MASK 0xc00 + #define OMAP_PTMSYNCREQ_EN 0xc04 + #define OMAP_TIMESTAMPCYCLELO 0xc08 +--- a/arch/arm/mach-omap2/opp.c ++++ b/arch/arm/mach-omap2/opp.c +@@ -17,6 +17,7 @@ + * GNU General Public License for more details. + */ + #include <linux/module.h> ++#include <linux/of.h> + #include <linux/opp.h> + #include <linux/cpu.h> + +@@ -40,6 +41,9 @@ int __init omap_init_opp_table(struct om + { + int i, r; + ++ if (of_have_populated_dt()) ++ return -EINVAL; ++ + if (!opp_def || !opp_def_size) { + pr_err("%s: invalid params!\n", __func__); + return -EINVAL; +--- /dev/null ++++ b/arch/arm/mach-omap2/pm33xx.c +@@ -0,0 +1,387 @@ ++/* ++ * AM33XX Power Management Routines ++ * ++ * Copyright (C) 2012 Texas Instruments Incorporated - http://www.ti.com/ ++ * Vaibhav Bedia <vaibhav.bedia@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/kernel.h> ++#include <linux/init.h> ++#include <linux/cpu.h> ++#include <linux/err.h> ++#include <linux/firmware.h> ++#include <linux/io.h> ++#include <linux/platform_device.h> ++#include <linux/sched.h> ++#include <linux/suspend.h> ++#include <linux/completion.h> ++#include <linux/module.h> ++#include <linux/interrupt.h> ++#include <linux/ti_emif.h> ++#include <linux/omap-mailbox.h> ++ ++#include <asm/suspend.h> ++#include <asm/proc-fns.h> ++#include <asm/sizes.h> ++#include <asm/fncpy.h> ++#include <asm/system_misc.h> ++ ++#include "pm.h" ++#include "cm33xx.h" ++#include "pm33xx.h" ++#include "common.h" ++#include "clockdomain.h" ++#include "powerdomain.h" ++#include "soc.h" ++#include "sram.h" ++ ++static void __iomem *am33xx_emif_base; ++static struct powerdomain *cefuse_pwrdm, *gfx_pwrdm, *per_pwrdm, *mpu_pwrdm; ++static struct clockdomain *gfx_l4ls_clkdm; ++static struct clockdomain *l3s_clkdm, *l4fw_clkdm, *clk_24mhz_clkdm; ++ ++static struct am33xx_pm_context *am33xx_pm; ++ ++static DECLARE_COMPLETION(am33xx_pm_sync); ++ ++static void (*am33xx_do_wfi_sram)(struct am33xx_suspend_params *); ++ ++static struct am33xx_suspend_params susp_params; ++ ++#ifdef CONFIG_SUSPEND ++ ++static int am33xx_do_sram_idle(long unsigned int unused) ++{ ++ am33xx_do_wfi_sram(&susp_params); ++ return 0; ++} ++ ++static int am33xx_pm_suspend(unsigned int state) ++{ ++ int i, ret = 0; ++ int status = 0; ++ struct wkup_m3_wakeup_src wakeup_src; ++ ++ if (state == PM_SUSPEND_STANDBY) { ++ clkdm_wakeup(l3s_clkdm); ++ clkdm_wakeup(l4fw_clkdm); ++ clkdm_wakeup(clk_24mhz_clkdm); ++ } ++ ++ /* Try to put GFX to sleep */ ++ omap_set_pwrdm_state(gfx_pwrdm, PWRDM_POWER_OFF); ++ ++ ret = cpu_suspend(0, am33xx_do_sram_idle); ++ ++ status = pwrdm_read_pwrst(gfx_pwrdm); ++ if (status != PWRDM_POWER_OFF) ++ pr_err("PM: GFX domain did not transition\n"); ++ ++ /* ++ * BUG: GFX_L4LS clock domain needs to be woken up to ++ * ensure thet L4LS clock domain does not get stuck in transition ++ * If that happens L3 module does not get disabled, thereby leading ++ * to PER power domain transition failing ++ */ ++ clkdm_wakeup(gfx_l4ls_clkdm); ++ clkdm_sleep(gfx_l4ls_clkdm); ++ ++ if (ret) { ++ pr_err("PM: Kernel suspend failure\n"); ++ } else { ++ i = wkup_m3_pm_status(); ++ switch (i) { ++ case 0: ++ pr_info("PM: Successfully put all powerdomains to target state\n"); ++ ++ /* ++ * The PRCM registers on AM335x do not contain ++ * previous state information like those present on ++ * OMAP4 so we must manually indicate transition so ++ * state counters are properly incremented ++ */ ++ pwrdm_post_transition(mpu_pwrdm); ++ pwrdm_post_transition(per_pwrdm); ++ break; ++ case 1: ++ pr_err("PM: Could not transition all powerdomains to target state\n"); ++ ret = -1; ++ break; ++ default: ++ pr_err("PM: CM3 returned unknown result = %d\n", i); ++ ret = -1; ++ } ++ /* print the wakeup reason */ ++ wakeup_src = wkup_m3_wake_src(); ++ ++ pr_info("PM: Wakeup source %s\n", wakeup_src.src); ++ } ++ ++ return ret; ++} ++ ++static int am33xx_pm_enter(suspend_state_t suspend_state) ++{ ++ int ret = 0; ++ ++ switch (suspend_state) { ++ case PM_SUSPEND_STANDBY: ++ case PM_SUSPEND_MEM: ++ ret = am33xx_pm_suspend(suspend_state); ++ break; ++ default: ++ ret = -EINVAL; ++ } ++ ++ return ret; ++} ++ ++ ++static void am33xx_m3_state_machine_reset(void) ++{ ++ int i; ++ ++ am33xx_pm->ipc.reg1 = IPC_CMD_RESET; ++ ++ wkup_m3_pm_set_cmd(&am33xx_pm->ipc); ++ ++ am33xx_pm->state = M3_STATE_MSG_FOR_RESET; ++ ++ if (!wkup_m3_ping()) { ++ i = wait_for_completion_timeout(&am33xx_pm_sync, ++ msecs_to_jiffies(500)); ++ if (!i) { ++ WARN(1, "PM: MPU<->CM3 sync failure\n"); ++ am33xx_pm->state = M3_STATE_UNKNOWN; ++ } ++ } else { ++ pr_warn("PM: Unable to ping CM3\n"); ++ } ++} ++ ++static int am33xx_pm_begin(suspend_state_t state) ++{ ++ int i; ++ ++ cpu_idle_poll_ctrl(true); ++ ++ switch (state) { ++ case PM_SUSPEND_MEM: ++ am33xx_pm->ipc.reg1 = IPC_CMD_DS0; ++ break; ++ case PM_SUSPEND_STANDBY: ++ am33xx_pm->ipc.reg1 = IPC_CMD_STANDBY; ++ break; ++ } ++ ++ am33xx_pm->ipc.reg2 = DS_IPC_DEFAULT; ++ am33xx_pm->ipc.reg3 = DS_IPC_DEFAULT; ++ ++ wkup_m3_pm_set_cmd(&am33xx_pm->ipc); ++ ++ am33xx_pm->state = M3_STATE_MSG_FOR_LP; ++ ++ if (!wkup_m3_ping()) { ++ i = wait_for_completion_timeout(&am33xx_pm_sync, ++ msecs_to_jiffies(500)); ++ if (!i) { ++ WARN(1, "PM: MPU<->CM3 sync failure\n"); ++ return -1; ++ } ++ } else { ++ pr_warn("PM: Unable to ping CM3\n"); ++ return -1; ++ } ++ ++ return 0; ++} ++ ++static void am33xx_pm_end(void) ++{ ++ am33xx_m3_state_machine_reset(); ++ ++ cpu_idle_poll_ctrl(false); ++ ++ return; ++} ++ ++static int am33xx_pm_valid(suspend_state_t state) ++{ ++ switch (state) { ++ case PM_SUSPEND_STANDBY: ++ case PM_SUSPEND_MEM: ++ return 1; ++ default: ++ return 0; ++ } ++} ++ ++static const struct platform_suspend_ops am33xx_pm_ops = { ++ .begin = am33xx_pm_begin, ++ .end = am33xx_pm_end, ++ .enter = am33xx_pm_enter, ++ .valid = am33xx_pm_valid, ++}; ++#endif /* CONFIG_SUSPEND */ ++ ++static void am33xx_txev_handler(void) ++{ ++ switch (am33xx_pm->state) { ++ case M3_STATE_RESET: ++ am33xx_pm->state = M3_STATE_INITED; ++ complete(&am33xx_pm_sync); ++ break; ++ case M3_STATE_MSG_FOR_RESET: ++ am33xx_pm->state = M3_STATE_INITED; ++ complete(&am33xx_pm_sync); ++ break; ++ case M3_STATE_MSG_FOR_LP: ++ complete(&am33xx_pm_sync); ++ break; ++ case M3_STATE_UNKNOWN: ++ pr_warn("PM: Unknown CM3 State\n"); ++ } ++ ++ return; ++} ++ ++static void am33xx_m3_fw_ready_cb(void) ++{ ++ int ret = 0; ++ ++ ret = wkup_m3_prepare(); ++ if (ret) { ++ pr_err("PM: Could not prepare WKUP_M3\n"); ++ return; ++ } ++ ++ ret = wait_for_completion_timeout(&am33xx_pm_sync, ++ msecs_to_jiffies(500)); ++ ++ if (WARN(ret == 0, "PM: MPU<->CM3 sync failure\n")) ++ return; ++ ++ am33xx_pm->ver = wkup_m3_fw_version_read(); ++ ++ if (am33xx_pm->ver == M3_VERSION_UNKNOWN || ++ am33xx_pm->ver < M3_BASELINE_VERSION) { ++ pr_warn("PM: CM3 Firmware Version %x not supported\n", ++ am33xx_pm->ver); ++ return; ++ } else { ++ pr_info("PM: CM3 Firmware Version = 0x%x\n", ++ am33xx_pm->ver); ++ } ++ ++#ifdef CONFIG_SUSPEND ++ suspend_set_ops(&am33xx_pm_ops); ++#endif /* CONFIG_SUSPEND */ ++} ++ ++static struct wkup_m3_ops am33xx_wkup_m3_ops = { ++ .txev_handler = am33xx_txev_handler, ++ .firmware_loaded = am33xx_m3_fw_ready_cb, ++}; ++ ++/* ++ * Push the minimal suspend-resume code to SRAM ++ */ ++void am33xx_push_sram_idle(void) ++{ ++ am33xx_do_wfi_sram = (void *)omap_sram_push ++ (am33xx_do_wfi, am33xx_do_wfi_sz); ++} ++ ++static int __init am33xx_map_emif(void) ++{ ++ am33xx_emif_base = ioremap(AM33XX_EMIF_BASE, SZ_32K); ++ ++ if (!am33xx_emif_base) ++ return -ENOMEM; ++ ++ return 0; ++} ++ ++int __init am33xx_pm_init(void) ++{ ++ int ret; ++ u32 temp; ++ ++ if (!soc_is_am33xx()) ++ return -ENODEV; ++ ++ gfx_pwrdm = pwrdm_lookup("gfx_pwrdm"); ++ per_pwrdm = pwrdm_lookup("per_pwrdm"); ++ mpu_pwrdm = pwrdm_lookup("mpu_pwrdm"); ++ ++ gfx_l4ls_clkdm = clkdm_lookup("gfx_l4ls_gfx_clkdm"); ++ l3s_clkdm = clkdm_lookup("l3s_clkdm"); ++ l4fw_clkdm = clkdm_lookup("l4fw_clkdm"); ++ clk_24mhz_clkdm = clkdm_lookup("clk_24mhz_clkdm"); ++ ++ if ((!gfx_pwrdm) || (!per_pwrdm) || (!mpu_pwrdm) || (!gfx_l4ls_clkdm) || ++ (!l3s_clkdm) || (!l4fw_clkdm) || (!clk_24mhz_clkdm)) { ++ ret = -ENODEV; ++ goto err; ++ } ++ ++ am33xx_pm = kzalloc(sizeof(*am33xx_pm), GFP_KERNEL); ++ if (!am33xx_pm) { ++ pr_err("Memory allocation failed\n"); ++ ret = -ENOMEM; ++ return ret; ++ } ++ ++ ret = am33xx_map_emif(); ++ if (ret) { ++ pr_err("PM: Could not ioremap EMIF\n"); ++ goto err; ++ } ++ ++ /* Determine Memory Type */ ++ temp = readl(am33xx_emif_base + EMIF_SDRAM_CONFIG); ++ temp = (temp & SDRAM_TYPE_MASK) >> SDRAM_TYPE_SHIFT; ++ /* Parameters to pass to aseembly code */ ++ susp_params.emif_addr_virt = am33xx_emif_base; ++ susp_params.dram_sync = am33xx_dram_sync; ++ susp_params.mem_type = temp; ++ am33xx_pm->ipc.reg4 = temp; ++ ++ (void) clkdm_for_each(omap_pm_clkdms_setup, NULL); ++ ++ /* CEFUSE domain can be turned off post bootup */ ++ cefuse_pwrdm = pwrdm_lookup("cefuse_pwrdm"); ++ if (cefuse_pwrdm) ++ omap_set_pwrdm_state(cefuse_pwrdm, PWRDM_POWER_OFF); ++ else ++ pr_err("PM: Failed to get cefuse_pwrdm\n"); ++ ++ am33xx_pm->state = M3_STATE_RESET; ++ ++ wkup_m3_set_ops(&am33xx_wkup_m3_ops); ++ ++ /* m3 may have already loaded but ops were not set yet, ++ * manually invoke */ ++ ++ if (wkup_m3_is_valid()) ++ am33xx_m3_fw_ready_cb(); ++ ++ /* Physical resume address to be used by ROM code */ ++ am33xx_pm->ipc.reg0 = (AM33XX_OCMC_END - ++ am33xx_do_wfi_sz + am33xx_resume_offset + 0x4); ++ ++ return 0; ++ ++err: ++ kfree(am33xx_pm); ++ return ret; ++} +--- /dev/null ++++ b/arch/arm/mach-omap2/pm33xx.h +@@ -0,0 +1,77 @@ ++/* ++ * AM33XX Power Management Routines ++ * ++ * Copyright (C) 2012 Texas Instruments Inc. ++ * Vaibhav Bedia <vaibhav.bedia@ti.com> ++ * ++ * This program is free software; you can redistribute it and/or ++ * modify it under the terms of the GNU General Public License as ++ * published by the Free Software Foundation version 2. ++ * ++ * This program is distributed "as is" WITHOUT ANY WARRANTY of any ++ * kind, whether express or implied; without even the implied warranty ++ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ */ ++#ifndef __ARCH_ARM_MACH_OMAP2_PM33XX_H ++#define __ARCH_ARM_MACH_OMAP2_PM33XX_H ++ ++#include "wkup_m3.h" ++ ++#ifndef __ASSEMBLER__ ++ ++struct am33xx_pm_context { ++ struct am33xx_ipc_regs ipc; ++ struct firmware *firmware; ++ struct omap_mbox *mbox; ++ u8 state; ++ u32 ver; ++}; ++ ++/* ++ * Params passed to suspend routine ++ * ++ * These are used to load into registers by suspend code, ++ * entries here must always be in sync with the suspend code ++ * in arm/mach-omap2/sleep33xx.S ++ */ ++struct am33xx_suspend_params { ++ void __iomem *emif_addr_virt; ++ u32 mem_type; ++ void __iomem *dram_sync; ++}; ++ ++ ++#endif ++ ++#define IPC_CMD_DS0 0x4 ++#define IPC_CMD_STANDBY 0xc ++#define IPC_CMD_RESET 0xe ++#define DS_IPC_DEFAULT 0xffffffff ++#define M3_VERSION_UNKNOWN 0x0000ffff ++#define M3_BASELINE_VERSION 0x21 ++ ++#define M3_STATE_UNKNOWN 0 ++#define M3_STATE_RESET 1 ++#define M3_STATE_INITED 2 ++#define M3_STATE_MSG_FOR_LP 3 ++#define M3_STATE_MSG_FOR_RESET 4 ++ ++#define AM33XX_OCMC_END 0x40310000 ++#define AM33XX_EMIF_BASE 0x4C000000 ++ ++#define MEM_TYPE_DDR2 2 ++ ++/* ++ * 9-4 = VTT GPIO PIN (6 Bits) ++ * 3 = VTT Status (1 Bit) ++ * 2-0 = Memory Type (2 Bits) ++*/ ++#define MEM_TYPE_SHIFT (0x0) ++#define MEM_TYPE_MASK (0x7 << 0) ++#define VTT_STAT_SHIFT (0x3) ++#define VTT_STAT_MASK (0x1 << 3) ++#define VTT_GPIO_PIN_SHIFT (0x4) ++#define VTT_GPIO_PIN_MASK (0x2f << 4) ++ ++#endif +--- a/arch/arm/mach-omap2/pm44xx.c ++++ b/arch/arm/mach-omap2/pm44xx.c +@@ -35,6 +35,7 @@ struct power_state { + }; + + static LIST_HEAD(pwrst_list); ++u32 cpu_suspend_state; + + #ifdef CONFIG_SUSPEND + static int omap4_pm_suspend(void) +@@ -52,7 +53,10 @@ static int omap4_pm_suspend(void) + /* Set targeted power domain states by suspend */ + list_for_each_entry(pwrst, &pwrst_list, node) { + omap_set_pwrdm_state(pwrst->pwrdm, pwrst->next_state); +- pwrdm_set_logic_retst(pwrst->pwrdm, PWRDM_POWER_OFF); ++ if (!strcmp(pwrst->pwrdm->name, "mpu_pwrdm")) ++ pwrdm_set_logic_retst(pwrst->pwrdm, PWRDM_POWER_ON); ++ else ++ pwrdm_set_logic_retst(pwrst->pwrdm, PWRDM_POWER_OFF); + } + + /* +@@ -64,7 +68,7 @@ static int omap4_pm_suspend(void) + * domain CSWR is not supported by hardware. + * More details can be found in OMAP4430 TRM section 4.3.4.2. + */ +- omap4_enter_lowpower(cpu_id, PWRDM_POWER_OFF); ++ omap4_enter_lowpower(cpu_id, cpu_suspend_state); + + /* Restore next powerdomain state */ + list_for_each_entry(pwrst, &pwrst_list, node) { +@@ -199,6 +203,32 @@ static inline int omap4_init_static_deps + } + + /** ++ * omap5_dra7_init_static_deps - Init static clkdm dependencies on OMAP5 ++ * and DRA7 ++ * ++ * The dynamic dependency between MPUSS -> EMIF is broken and has ++ * not worked as expected. The hardware recommendation is to ++ * enable static dependencies for these to avoid system ++ * lock ups or random crashes. ++ */ ++static inline int omap5_dra7_init_static_deps(void) ++{ ++ struct clockdomain *mpuss_clkdm, *emif_clkdm; ++ int ret; ++ ++ mpuss_clkdm = clkdm_lookup("mpu_clkdm"); ++ emif_clkdm = clkdm_lookup("emif_clkdm"); ++ if (!mpuss_clkdm || !emif_clkdm) ++ return -EINVAL; ++ ++ ret = clkdm_add_wkdep(mpuss_clkdm, emif_clkdm); ++ if (ret) ++ pr_err("Failed to add MPUSS -> EMIF wakeup dependency\n"); ++ ++ return ret; ++} ++ ++/** + * omap4_pm_init - Init routine for OMAP4+ devices + * + * Initializes all powerdomain and clockdomain target states +@@ -222,10 +252,14 @@ int __init omap4_pm_init(void) + goto err2; + } + +- if (cpu_is_omap44xx()) { ++ if (cpu_is_omap44xx()) + ret = omap4_init_static_deps(); +- if (ret) +- goto err2; ++ else if (soc_is_omap54xx() || soc_is_dra7xx()) ++ ret = omap5_dra7_init_static_deps(); ++ ++ if (ret) { ++ pr_err("Failed to initialise static dependencies.\n"); ++ goto err2; + } + + ret = omap4_mpuss_init(); +@@ -246,6 +280,11 @@ int __init omap4_pm_init(void) + if (cpu_is_omap44xx()) + omap4_idle_init(); + ++ if (soc_is_dra7xx()) ++ cpu_suspend_state = PWRDM_POWER_RET; ++ else ++ cpu_suspend_state = PWRDM_POWER_OFF; ++ + err2: + return ret; + } +--- a/arch/arm/mach-omap2/pm.c ++++ b/arch/arm/mach-omap2/pm.c +@@ -266,7 +266,12 @@ static void __init omap4_init_voltages(v + + static inline void omap_init_cpufreq(void) + { +- struct platform_device_info devinfo = { .name = "omap-cpufreq", }; ++ struct platform_device_info devinfo = { }; ++ ++ if (!of_have_populated_dt()) ++ devinfo.name = "omap-cpufreq"; ++ else ++ devinfo.name = "cpufreq-cpu0"; + platform_device_register_full(&devinfo); + } + +@@ -300,13 +305,16 @@ int __init omap2_common_pm_late_init(voi + /* Smartreflex device init */ + omap_devinit_smartreflex(); + +- /* cpufreq dummy device instantiation */ +- omap_init_cpufreq(); + } + +-#ifdef CONFIG_SUSPEND +- suspend_set_ops(&omap_pm_ops); +-#endif ++ /* cpufreq dummy device instantiation */ ++ omap_init_cpufreq(); + + return 0; + } ++ ++void __init omap2_common_suspend_init(void) ++{ ++ suspend_set_ops(&omap_pm_ops); ++} ++ +--- a/arch/arm/mach-omap2/pm.h ++++ b/arch/arm/mach-omap2/pm.h +@@ -82,6 +82,11 @@ extern unsigned int omap3_do_wfi_sz; + /* ... and its pointer from SRAM after copy */ + extern void (*omap3_do_wfi_sram)(void); + ++/* am33xx_do_wfi function pointer and size, for copy to SRAM */ ++extern void am33xx_do_wfi(void); ++extern unsigned int am33xx_do_wfi_sz; ++extern unsigned int am33xx_resume_offset; ++ + /* save_secure_ram_context function pointer and size, for copy to SRAM */ + extern int save_secure_ram_context(u32 *addr); + extern unsigned int save_secure_ram_context_sz; +--- a/arch/arm/mach-omap2/powerdomain.h ++++ b/arch/arm/mach-omap2/powerdomain.h +@@ -254,6 +254,7 @@ extern void omap242x_powerdomains_init(v + extern void omap243x_powerdomains_init(void); + extern void omap3xxx_powerdomains_init(void); + extern void am33xx_powerdomains_init(void); ++extern void am43xx_powerdomains_init(void); + extern void omap44xx_powerdomains_init(void); + extern void omap54xx_powerdomains_init(void); + extern void dra7xx_powerdomains_init(void); +--- /dev/null ++++ b/arch/arm/mach-omap2/powerdomains43xx_data.c +@@ -0,0 +1,145 @@ ++/* ++ * AM43xx Power domains framework ++ * ++ * Copyright (C) 2013 Texas Instruments, Inc. ++ * ++ * This file is made by modifying the file generated automatically ++ * from the OMAP hardware databases. ++ * ++ * 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 "powerdomain.h" ++ ++#include "prcm-common.h" ++#include "prcm44xx.h" ++#include "prcm43xx.h" ++ ++static struct powerdomain gfx_43xx_pwrdm = { ++ .name = "gfx_pwrdm", ++ .voltdm = { .name = "core" }, ++ .prcm_offs = AM43XX_PRM_GFX_INST, ++ .prcm_partition = AM43XX_PRM_PARTITION, ++ .pwrsts = PWRSTS_OFF_ON, ++ .banks = 1, ++ .pwrsts_mem_ret = { ++ [0] = PWRSTS_OFF_RET, /* gfx_mem */ ++ }, ++ .pwrsts_mem_on = { ++ [0] = PWRSTS_ON, /* gfx_mem */ ++ }, ++ .flags = PWRDM_HAS_LOWPOWERSTATECHANGE, ++}; ++ ++static struct powerdomain mpu_43xx_pwrdm = { ++ .name = "mpu_pwrdm", ++ .voltdm = { .name = "mpu" }, ++ .prcm_offs = AM43XX_PRM_MPU_INST, ++ .prcm_partition = AM43XX_PRM_PARTITION, ++ .pwrsts = PWRSTS_OFF_RET_ON, ++ .pwrsts_logic_ret = PWRSTS_OFF_RET, ++ .banks = 3, ++ .pwrsts_mem_ret = { ++ [0] = PWRSTS_OFF_RET, /* mpu_l1 */ ++ [1] = PWRSTS_OFF_RET, /* mpu_l2 */ ++ [2] = PWRSTS_OFF_RET, /* mpu_ram */ ++ }, ++ .pwrsts_mem_on = { ++ [0] = PWRSTS_ON, /* mpu_l1 */ ++ [1] = PWRSTS_ON, /* mpu_l2 */ ++ [2] = PWRSTS_ON, /* mpu_ram */ ++ }, ++ .flags = PWRDM_HAS_LOWPOWERSTATECHANGE, ++}; ++ ++static struct powerdomain rtc_43xx_pwrdm = { ++ .name = "rtc_pwrdm", ++ .voltdm = { .name = "rtc" }, ++ .prcm_offs = AM43XX_PRM_RTC_INST, ++ .prcm_partition = AM43XX_PRM_PARTITION, ++ .pwrsts = PWRSTS_ON, ++}; ++ ++static struct powerdomain wkup_43xx_pwrdm = { ++ .name = "wkup_pwrdm", ++ .voltdm = { .name = "core" }, ++ .prcm_offs = AM43XX_PRM_WKUP_INST, ++ .prcm_partition = AM43XX_PRM_PARTITION, ++ .pwrsts = PWRSTS_ON, ++ .banks = 1, ++ .pwrsts_mem_ret = { ++ [0] = PWRSTS_OFF, /* debugss_mem */ ++ }, ++ .pwrsts_mem_on = { ++ [0] = PWRSTS_ON, /* debugss_mem */ ++ }, ++}; ++ ++static struct powerdomain tamper_43xx_pwrdm = { ++ .name = "tamper_pwrdm", ++ .voltdm = { .name = "tamper" }, ++ .prcm_offs = AM43XX_PRM_TAMPER_INST, ++ .prcm_partition = AM43XX_PRM_PARTITION, ++ .pwrsts = PWRSTS_ON, ++}; ++ ++static struct powerdomain cefuse_43xx_pwrdm = { ++ .name = "cefuse_pwrdm", ++ .voltdm = { .name = "core" }, ++ .prcm_offs = AM43XX_PRM_CEFUSE_INST, ++ .prcm_partition = AM43XX_PRM_PARTITION, ++ .pwrsts = PWRSTS_OFF_ON, ++ .flags = PWRDM_HAS_LOWPOWERSTATECHANGE, ++}; ++ ++static struct powerdomain per_43xx_pwrdm = { ++ .name = "per_pwrdm", ++ .voltdm = { .name = "core" }, ++ .prcm_offs = AM43XX_PRM_PER_INST, ++ .prcm_partition = AM43XX_PRM_PARTITION, ++ .pwrsts = PWRSTS_OFF_RET_ON, ++ .pwrsts_logic_ret = PWRSTS_OFF_RET, ++ .banks = 4, ++ .pwrsts_mem_ret = { ++ [0] = PWRSTS_OFF_RET, /* icss_mem */ ++ [1] = PWRSTS_OFF_RET, /* per_mem */ ++ [2] = PWRSTS_OFF_RET, /* ram1_mem */ ++ [3] = PWRSTS_OFF_RET, /* ram2_mem */ ++ }, ++ .pwrsts_mem_on = { ++ [0] = PWRSTS_OFF_RET, /* icss_mem */ ++ [1] = PWRSTS_ON, /* per_mem */ ++ [2] = PWRSTS_OFF_RET, /* ram1_mem */ ++ [3] = PWRSTS_OFF_RET, /* ram2_mem */ ++ }, ++ .flags = PWRDM_HAS_LOWPOWERSTATECHANGE, ++}; ++ ++static struct powerdomain *powerdomains_am43xx[] __initdata = { ++ &gfx_43xx_pwrdm, ++ &mpu_43xx_pwrdm, ++ &rtc_43xx_pwrdm, ++ &wkup_43xx_pwrdm, ++ &tamper_43xx_pwrdm, ++ &cefuse_43xx_pwrdm, ++ &per_43xx_pwrdm, ++ NULL ++}; ++ ++static int am43xx_check_vcvp(void) ++{ ++ return 0; ++} ++ ++void __init am43xx_powerdomains_init(void) ++{ ++ omap4_pwrdm_operations.pwrdm_has_voltdm = am43xx_check_vcvp; ++ pwrdm_register_platform_funcs(&omap4_pwrdm_operations); ++ pwrdm_register_pwrdms(powerdomains_am43xx); ++ pwrdm_complete_init(); ++} +--- /dev/null ++++ b/arch/arm/mach-omap2/prcm43xx.h +@@ -0,0 +1,149 @@ ++/* ++ * AM43x PRCM defines ++ * ++ * Copyright (C) 2013 Texas Instruments Incorporated - http://www.ti.com/ ++ * ++ * This file is licensed under the terms of the GNU General Public License ++ * version 2. This program is licensed "as is" without any warranty of any ++ * kind, whether express or implied. ++ */ ++ ++#ifndef __ARCH_ARM_MACH_OMAP2_PRCM_43XX_H ++#define __ARCH_ARM_MACH_OMAP2_PRCM_43XX_H ++ ++#define AM43XX_PRM_PARTITION 1 ++#define AM43XX_CM_PARTITION 1 ++ ++/* PRM instances */ ++#define AM43XX_PRM_OCP_SOCKET_INST 0x0000 ++#define AM43XX_PRM_MPU_INST 0x0300 ++#define AM43XX_PRM_GFX_INST 0x0400 ++#define AM43XX_PRM_RTC_INST 0x0500 ++#define AM43XX_PRM_TAMPER_INST 0x0600 ++#define AM43XX_PRM_CEFUSE_INST 0x0700 ++#define AM43XX_PRM_PER_INST 0x0800 ++#define AM43XX_PRM_WKUP_INST 0x2000 ++#define AM43XX_PRM_DEVICE_INST 0x4000 ++ ++/* RM RSTCTRL offsets */ ++#define AM43XX_RM_PER_RSTCTRL_OFFSET 0x0010 ++#define AM43XX_RM_GFX_RSTCTRL_OFFSET 0x0010 ++#define AM43XX_RM_WKUP_RSTCTRL_OFFSET 0x0010 ++ ++/* RM RSTST offsets */ ++#define AM43XX_RM_GFX_RSTST_OFFSET 0x0014 ++#define AM43XX_RM_WKUP_RSTST_OFFSET 0x0014 ++ ++/* CM instances */ ++#define AM43XX_CM_WKUP_INST 0x2800 ++#define AM43XX_CM_DEVICE_INST 0x4100 ++#define AM43XX_CM_DPLL_INST 0x4200 ++#define AM43XX_CM_MPU_INST 0x8300 ++#define AM43XX_CM_GFX_INST 0x8400 ++#define AM43XX_CM_RTC_INST 0x8500 ++#define AM43XX_CM_TAMPER_INST 0x8600 ++#define AM43XX_CM_CEFUSE_INST 0x8700 ++#define AM43XX_CM_PER_INST 0x8800 ++ ++/* CD offsets */ ++#define AM43XX_CM_WKUP_L3_AON_CDOFFS 0x0000 ++#define AM43XX_CM_WKUP_L3S_TSC_CDOFFS 0x0100 ++#define AM43XX_CM_WKUP_L4_WKUP_AON_CDOFFS 0x0200 ++#define AM43XX_CM_WKUP_WKUP_CDOFFS 0x0300 ++#define AM43XX_CM_MPU_MPU_CDOFFS 0x0000 ++#define AM43XX_CM_GFX_GFX_L3_CDOFFS 0x0000 ++#define AM43XX_CM_RTC_RTC_CDOFFS 0x0000 ++#define AM43XX_CM_TAMPER_TAMPER_CDOFFS 0x0000 ++#define AM43XX_CM_CEFUSE_CEFUSE_CDOFFS 0x0000 ++#define AM43XX_CM_PER_L3_CDOFFS 0x0000 ++#define AM43XX_CM_PER_L3S_CDOFFS 0x0200 ++#define AM43XX_CM_PER_ICSS_CDOFFS 0x0300 ++#define AM43XX_CM_PER_L4LS_CDOFFS 0x0400 ++#define AM43XX_CM_PER_EMIF_CDOFFS 0x0700 ++#define AM43XX_CM_PER_DSS_CDOFFS 0x0a00 ++#define AM43XX_CM_PER_CPSW_CDOFFS 0x0b00 ++#define AM43XX_CM_PER_OCPWP_L3_CDOFFS 0x0c00 ++ ++/* CLK CTRL offsets */ ++#define AM43XX_CM_PER_UART1_CLKCTRL_OFFSET 0x0580 ++#define AM43XX_CM_PER_UART2_CLKCTRL_OFFSET 0x0588 ++#define AM43XX_CM_PER_UART3_CLKCTRL_OFFSET 0x0590 ++#define AM43XX_CM_PER_UART4_CLKCTRL_OFFSET 0x0598 ++#define AM43XX_CM_PER_UART5_CLKCTRL_OFFSET 0x05a0 ++#define AM43XX_CM_PER_DCAN0_CLKCTRL_OFFSET 0x0428 ++#define AM43XX_CM_PER_DCAN1_CLKCTRL_OFFSET 0x0430 ++#define AM43XX_CM_PER_ELM_CLKCTRL_OFFSET 0x0468 ++#define AM43XX_CM_PER_EPWMSS0_CLKCTRL_OFFSET 0x0438 ++#define AM43XX_CM_PER_EPWMSS1_CLKCTRL_OFFSET 0x0440 ++#define AM43XX_CM_PER_EPWMSS2_CLKCTRL_OFFSET 0x0448 ++#define AM43XX_CM_PER_GPIO1_CLKCTRL_OFFSET 0x0478 ++#define AM43XX_CM_PER_GPIO2_CLKCTRL_OFFSET 0x0480 ++#define AM43XX_CM_PER_GPIO3_CLKCTRL_OFFSET 0x0488 ++#define AM43XX_CM_PER_I2C1_CLKCTRL_OFFSET 0x04a8 ++#define AM43XX_CM_PER_I2C2_CLKCTRL_OFFSET 0x04b0 ++#define AM43XX_CM_PER_MAILBOX0_CLKCTRL_OFFSET 0x04b8 ++#define AM43XX_CM_PER_MMC0_CLKCTRL_OFFSET 0x04c0 ++#define AM43XX_CM_PER_MMC1_CLKCTRL_OFFSET 0x04c8 ++#define AM43XX_CM_PER_DES_CLKCTRL_OFFSET 0x0030 ++#define AM43XX_CM_PER_RNG_CLKCTRL_OFFSET 0x04e0 ++#define AM43XX_CM_PER_SPI0_CLKCTRL_OFFSET 0x0500 ++#define AM43XX_CM_PER_SPI1_CLKCTRL_OFFSET 0x0508 ++#define AM43XX_CM_PER_SPINLOCK_CLKCTRL_OFFSET 0x0528 ++#define AM43XX_CM_PER_TIMER2_CLKCTRL_OFFSET 0x0530 ++#define AM43XX_CM_PER_TIMER3_CLKCTRL_OFFSET 0x0538 ++#define AM43XX_CM_PER_TIMER4_CLKCTRL_OFFSET 0x0540 ++#define AM43XX_CM_PER_TIMER5_CLKCTRL_OFFSET 0x0548 ++#define AM43XX_CM_PER_TIMER6_CLKCTRL_OFFSET 0x0550 ++#define AM43XX_CM_PER_TIMER7_CLKCTRL_OFFSET 0x0558 ++#define AM43XX_CM_WKUP_WKUP_M3_CLKCTRL_OFFSET 0x0228 ++#define AM43XX_CM_WKUP_CONTROL_CLKCTRL_OFFSET 0x0360 ++#define AM43XX_CM_WKUP_SMARTREFLEX0_CLKCTRL_OFFSET 0x0350 ++#define AM43XX_CM_WKUP_SMARTREFLEX1_CLKCTRL_OFFSET 0x0358 ++#define AM43XX_CM_WKUP_UART0_CLKCTRL_OFFSET 0x0348 ++#define AM43XX_CM_WKUP_TIMER1_CLKCTRL_OFFSET 0x0328 ++#define AM43XX_CM_WKUP_I2C0_CLKCTRL_OFFSET 0x0340 ++#define AM43XX_CM_WKUP_GPIO0_CLKCTRL_OFFSET 0x0368 ++#define AM43XX_CM_WKUP_ADC_TSC_CLKCTRL_OFFSET 0x0120 ++#define AM43XX_CM_WKUP_WDT1_CLKCTRL_OFFSET 0x0338 ++#define AM43XX_CM_WKUP_L4WKUP_CLKCTRL_OFFSET 0x0220 ++#define AM43XX_CM_RTC_RTC_CLKCTRL_OFFSET 0x0020 ++#define AM43XX_CM_PER_MMC2_CLKCTRL_OFFSET 0x0248 ++#define AM43XX_CM_PER_QSPI_CLKCTRL_OFFSET 0x0258 ++#define AM43XX_CM_PER_USB_OTG_SS0_CLKCTRL_OFFSET 0x0260 ++#define AM43XX_CM_PER_USBPHYOCP2SCP0_CLKCTRL_OFFSET 0x05B8 ++#define AM43XX_CM_PER_USB_OTG_SS1_CLKCTRL_OFFSET 0x0268 ++#define AM43XX_CM_PER_USBPHYOCP2SCP1_CLKCTRL_OFFSET 0x05C0 ++#define AM43XX_CM_PER_GPMC_CLKCTRL_OFFSET 0x0220 ++#define AM43XX_CM_PER_MCASP0_CLKCTRL_OFFSET 0x0238 ++#define AM43XX_CM_PER_MCASP1_CLKCTRL_OFFSET 0x0240 ++#define AM43XX_CM_PER_L4LS_CLKCTRL_OFFSET 0x0420 ++#define AM43XX_CM_PER_L3_CLKCTRL_OFFSET 0x0020 ++#define AM43XX_CM_PER_TPCC_CLKCTRL_OFFSET 0x0078 ++#define AM43XX_CM_PER_TPTC0_CLKCTRL_OFFSET 0x0080 ++#define AM43XX_CM_PER_TPTC1_CLKCTRL_OFFSET 0x0088 ++#define AM43XX_CM_PER_TPTC2_CLKCTRL_OFFSET 0x0090 ++#define AM43XX_CM_PER_CPGMAC0_CLKCTRL_OFFSET 0x0b20 ++#define AM43XX_CM_PER_PRUSS_CLKCTRL_OFFSET 0x0320 ++#define AM43XX_CM_GFX_GFX_CLKCTRL_OFFSET 0x0020 ++#define AM43XX_CM_PER_L4HS_CLKCTRL_OFFSET 0x00a0 ++#define AM43XX_CM_MPU_MPU_CLKCTRL_OFFSET 0x0020 ++#define AM43XX_CM_PER_L3_INSTR_CLKCTRL_OFFSET 0x0040 ++#define AM43XX_CM_PER_OCMCRAM_CLKCTRL_OFFSET 0x0050 ++#define AM43XX_CM_PER_SHA0_CLKCTRL_OFFSET 0x0058 ++#define AM43XX_CM_PER_AES0_CLKCTRL_OFFSET 0x0028 ++#define AM43XX_CM_PER_TIMER8_CLKCTRL_OFFSET 0x0560 ++#define AM43XX_CM_PER_TIMER9_CLKCTRL_OFFSET 0x0568 ++#define AM43XX_CM_PER_TIMER10_CLKCTRL_OFFSET 0x0570 ++#define AM43XX_CM_PER_TIMER11_CLKCTRL_OFFSET 0x0578 ++#define AM43XX_CM_WKUP_SYNCTIMER_CLKCTRL_OFFSET 0x0230 ++#define AM43XX_CM_PER_EPWMSS3_CLKCTRL_OFFSET 0x0450 ++#define AM43XX_CM_PER_EPWMSS4_CLKCTRL_OFFSET 0x0458 ++#define AM43XX_CM_PER_EPWMSS5_CLKCTRL_OFFSET 0x0460 ++#define AM43XX_CM_PER_SPI2_CLKCTRL_OFFSET 0x0510 ++#define AM43XX_CM_PER_SPI3_CLKCTRL_OFFSET 0x0518 ++#define AM43XX_CM_PER_SPI4_CLKCTRL_OFFSET 0x0520 ++#define AM43XX_CM_PER_GPIO4_CLKCTRL_OFFSET 0x0490 ++#define AM43XX_CM_PER_GPIO5_CLKCTRL_OFFSET 0x0498 ++#define AM43XX_CM_PER_DSS_CLKCTRL_OFFSET 0x0a20 ++ ++#endif +--- a/arch/arm/mach-omap2/prminst44xx.c ++++ b/arch/arm/mach-omap2/prminst44xx.c +@@ -182,12 +182,10 @@ void omap4_prminst_global_warm_sw_reset( + v = omap4_prminst_read_inst_reg(OMAP4430_PRM_PARTITION, dev_inst, + OMAP4_PRM_RSTCTRL_OFFSET); + v |= OMAP4430_RST_GLOBAL_WARM_SW_MASK; +- omap4_prminst_write_inst_reg(v, OMAP4430_PRM_PARTITION, +- OMAP4430_PRM_DEVICE_INST, ++ omap4_prminst_write_inst_reg(v, OMAP4430_PRM_PARTITION, dev_inst, + OMAP4_PRM_RSTCTRL_OFFSET); + + /* OCP barrier */ +- v = omap4_prminst_read_inst_reg(OMAP4430_PRM_PARTITION, +- OMAP4430_PRM_DEVICE_INST, ++ v = omap4_prminst_read_inst_reg(OMAP4430_PRM_PARTITION, dev_inst, + OMAP4_PRM_RSTCTRL_OFFSET); + } +--- /dev/null ++++ b/arch/arm/mach-omap2/sleep33xx.S +@@ -0,0 +1,362 @@ ++/* ++ * Low level suspend code for AM33XX SoCs ++ * ++ * Copyright (C) 2012 Texas Instruments Incorporated - http://www.ti.com/ ++ * Vaibhav Bedia <vaibhav.bedia@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/linkage.h> ++#include <linux/ti_emif.h> ++#include <asm/memory.h> ++#include <asm/assembler.h> ++ ++#include "cm33xx.h" ++#include "pm33xx.h" ++#include "prm33xx.h" ++ ++#define EMIF_POWER_MGMT_WAIT_SELF_REFRESH_8192_CYCLES 0x00a0 ++#define EMIF_POWER_MGMT_SR_TIMER_MASK 0x00f0 ++ ++#define EMIF_POWER_MGMT_SELF_REFRESH_MODE 0x0200 ++#define EMIF_POWER_MGMT_SELF_REFRESH_MODE_MASK 0x0700 ++#define EMIF_POWER_MGMT_DELAY_PERIOD 0x1000 ++ ++#define AM33XX_CM_CLKCTRL_MODULEMODE_DISABLE 0x0003 ++#define AM33XX_CM_CLKCTRL_MODULEMODE_ENABLE 0x0002 ++ ++ .text ++ .align 3 ++ ++/* ++ * This routine is executed from internal RAM and expects some ++ * parameters to be passed in r0 _strictly_ in following order: ++ * 1) emif_addr_virt - ioremapped EMIF address ++ * 2) mem_type - 2 -> DDR2, 3-> DDR3 ++ * 3) dram_sync_word - uncached word in SDRAM ++ * ++ * The code loads these values taking r0 value as reference to ++ * the array in registers starting from r0, i.e emif_addr_virt ++ * goes to r1, mem_type goes to r2 and and so on. These are ++ * then saved into memory locations before proceeding with the ++ * sleep sequence and hence registers r0, r1 etc can still be ++ * used in the rest of the sleep code. ++ */ ++ ++ENTRY(am33xx_do_wfi) ++ stmfd sp!, {r4 - r11, lr} @ save registers on stack ++ ++ ldm r0, {r1-r3} @ gather values passed ++ ++ /* Save the values passed */ ++ str r1, emif_addr_virt ++ str r2, mem_type ++ str r3, dram_sync_word ++ ++ /* ++ * Flush all data from the L1 and L2 data cache before disabling ++ * SCTLR.C bit. ++ */ ++ ldr r1, kernel_flush ++ blx r1 ++ ++ /* ++ * 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 and L2 data cache. ++ */ ++ ldr r1, kernel_flush ++ blx r1 ++ ++ ldr r0, emif_addr_virt ++ /* Save EMIF configuration */ ++ ldr r1, [r0, #EMIF_SDRAM_CONFIG] ++ str r1, emif_sdcfg_val ++ ldr r1, [r0, #EMIF_SDRAM_REFRESH_CONTROL] ++ str r1, emif_ref_ctrl_val ++ ldr r1, [r0, #EMIF_SDRAM_TIMING_1] ++ str r1, emif_timing1_val ++ ldr r1, [r0, #EMIF_SDRAM_TIMING_2] ++ str r1, emif_timing2_val ++ ldr r1, [r0, #EMIF_SDRAM_TIMING_3] ++ str r1, emif_timing3_val ++ ldr r1, [r0, #EMIF_POWER_MANAGEMENT_CONTROL] ++ str r1, emif_pmcr_val ++ ldr r1, [r0, #EMIF_POWER_MANAGEMENT_CTRL_SHDW] ++ str r1, emif_pmcr_shdw_val ++ ldr r1, [r0, #EMIF_SDRAM_OUTPUT_IMPEDANCE_CALIBRATION_CONFIG] ++ str r1, emif_zqcfg_val ++ ldr r1, [r0, #EMIF_DDR_PHY_CTRL_1] ++ str r1, emif_rd_lat_val ++ ++ /* Put SDRAM in self-refresh */ ++ ldr r1, [r0, #EMIF_POWER_MANAGEMENT_CONTROL] ++ bic r1, r1, #EMIF_POWER_MGMT_SR_TIMER_MASK ++ orr r1, r1, #EMIF_POWER_MGMT_WAIT_SELF_REFRESH_8192_CYCLES ++ str r1, [r0, #EMIF_POWER_MANAGEMENT_CONTROL] ++ str r1, [r0, #EMIF_POWER_MANAGEMENT_CTRL_SHDW] ++ ++ ldr r1, [r0, #EMIF_POWER_MANAGEMENT_CONTROL] ++ bic r1, r1, #EMIF_POWER_MGMT_SELF_REFRESH_MODE_MASK ++ orr r1, r1, #EMIF_POWER_MGMT_SELF_REFRESH_MODE ++ str r1, [r0, #EMIF_POWER_MANAGEMENT_CONTROL] ++ ++ ldr r1, dram_sync_word @ a dummy access to DDR as per spec ++ ldr r2, [r1, #0] ++ ++ ++ mov r1, #EMIF_POWER_MGMT_DELAY_PERIOD @ Wait for system ++wait_self_refresh: @ to enter SR ++ subs r1, r1, #1 ++ bne wait_self_refresh ++ ++ /* Disable EMIF */ ++ ldr r1, virt_emif_clkctrl ++ ldr r2, [r1] ++ bic r2, r2, #AM33XX_CM_CLKCTRL_MODULEMODE_DISABLE ++ str r2, [r1] ++ ++ ldr r1, virt_emif_clkctrl ++wait_emif_disable: ++ ldr r2, [r1] ++ ldr r3, module_disabled_val ++ cmp r2, r3 ++ bne wait_emif_disable ++ ++ /* ++ * For the MPU WFI to be registered as an interrupt ++ * to WKUP_M3, MPU_CLKCTRL.MODULEMODE needs to be set ++ * to DISABLED ++ */ ++ ldr r1, virt_mpu_clkctrl ++ ldr r2, [r1] ++ bic r2, r2, #AM33XX_CM_CLKCTRL_MODULEMODE_DISABLE ++ str r2, [r1] ++ ++ /* ++ * 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 ++ * 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. Thirteen ++ * NOPs as per Cortex-A8 pipeline. ++ */ ++ wfi ++ ++ nop ++ nop ++ nop ++ nop ++ nop ++ nop ++ nop ++ nop ++ nop ++ nop ++ nop ++ nop ++ nop ++ ++ /* We come here in case of an abort due to a late interrupt */ ++ ++ /* Set MPU_CLKCTRL.MODULEMODE back to ENABLE */ ++ ldr r1, virt_mpu_clkctrl ++ mov r2, #AM33XX_CM_CLKCTRL_MODULEMODE_ENABLE ++ str r2, [r1] ++ ++ /* Re-enable EMIF */ ++ ldr r1, virt_emif_clkctrl ++ mov r2, #AM33XX_CM_CLKCTRL_MODULEMODE_ENABLE ++ str r2, [r1] ++wait_emif_enable: ++ ldr r3, [r1] ++ cmp r2, r3 ++ bne wait_emif_enable ++ ++ /* Disable EMIF self-refresh */ ++ ldr r0, emif_addr_virt ++ ldr r1, [r0, #EMIF_POWER_MANAGEMENT_CONTROL] ++ bic r1, r1, #LP_MODE_MASK ++ str r1, [r0, #EMIF_POWER_MANAGEMENT_CONTROL] ++ str r1, [r0, #EMIF_POWER_MANAGEMENT_CTRL_SHDW] ++ ++ /* ++ * A write to SDRAM CONFIG register triggers ++ * an init sequence and hence it must be done ++ * at the end for DDR2 ++ */ ++ ldr r0, emif_addr_virt ++ add r0, r0, #EMIF_SDRAM_CONFIG ++ ldr r4, emif_sdcfg_val ++ str r4, [r0] ++ ++ /* ++ * Set SCTLR.C bit to allow data cache allocation ++ */ ++ mrc p15, 0, r0, c1, c0, 0 ++ orr r0, r0, #(1 << 2) @ Enable the C bit ++ mcr p15, 0, r0, c1, c0, 0 ++ isb ++ ++ /* EMIF needs some time before read/write possible */ ++ mov r0, #EMIF_POWER_MGMT_DELAY_PERIOD ++wait_abt: ++ subs r0, r0, #1 ++ bne wait_abt ++ ++ /* Let the suspend code know about the abort */ ++ mov r0, #1 ++ ldmfd sp!, {r4 - r11, pc} @ restore regs and return ++ENDPROC(am33xx_do_wfi) ++ ++ .align ++ENTRY(am33xx_resume_offset) ++ .word . - am33xx_do_wfi ++ ++ENTRY(am33xx_resume_from_deep_sleep) ++ /* Re-enable EMIF */ ++ ldr r0, phys_emif_clkctrl ++ mov r1, #AM33XX_CM_CLKCTRL_MODULEMODE_ENABLE ++ str r1, [r0] ++wait_emif_enable1: ++ ldr r2, [r0] ++ cmp r1, r2 ++ bne wait_emif_enable1 ++ ++ /* Config EMIF Timings */ ++ ldr r0, emif_phys_addr ++ ldr r1, emif_rd_lat_val ++ str r1, [r0, #EMIF_DDR_PHY_CTRL_1] ++ str r1, [r0, #EMIF_DDR_PHY_CTRL_1_SHDW] ++ ldr r1, emif_timing1_val ++ str r1, [r0, #EMIF_SDRAM_TIMING_1] ++ str r1, [r0, #EMIF_SDRAM_TIMING_1_SHDW] ++ ldr r1, emif_timing2_val ++ str r1, [r0, #EMIF_SDRAM_TIMING_2] ++ str r1, [r0, #EMIF_SDRAM_TIMING_2_SHDW] ++ ldr r1, emif_timing3_val ++ str r1, [r0, #EMIF_SDRAM_TIMING_3] ++ str r1, [r0, #EMIF_SDRAM_TIMING_3_SHDW] ++ ldr r1, emif_ref_ctrl_val ++ str r1, [r0, #EMIF_SDRAM_REFRESH_CONTROL] ++ str r1, [r0, #EMIF_SDRAM_REFRESH_CTRL_SHDW] ++ ldr r1, emif_pmcr_val ++ str r1, [r0, #EMIF_POWER_MANAGEMENT_CONTROL] ++ ldr r1, emif_pmcr_shdw_val ++ str r1, [r0, #EMIF_POWER_MANAGEMENT_CTRL_SHDW] ++ ++ /* ++ * Output impedence calib needed only for DDR3 ++ * but since the initial state of this will be ++ * disabled for DDR2 no harm in restoring the ++ * old configuration ++ */ ++ ldr r1, emif_zqcfg_val ++ str r1, [r0, #EMIF_SDRAM_OUTPUT_IMPEDANCE_CALIBRATION_CONFIG] ++ ++ /* Write to SDRAM_CONFIG only for DDR2 */ ++ ldr r2, mem_type ++ cmp r2, #MEM_TYPE_DDR2 ++ bne resume_to_ddr ++ ++ /* ++ * A write to SDRAM CONFIG register triggers ++ * an init sequence and hence it must be done ++ * at the end for DDR2 ++ */ ++ ldr r1, emif_sdcfg_val ++ str r1, [r0, #EMIF_SDRAM_CONFIG] ++ ++resume_to_ddr: ++ /* EMIF needs some time before read/write possible */ ++ mov r0, #EMIF_POWER_MGMT_DELAY_PERIOD ++wait_resume: ++ subs r0, r0, #1 ++ bne wait_resume ++ ++ /* We are back. Branch to the common CPU resume routine */ ++ mov r0, #0 ++ ldr pc, resume_addr ++ENDPROC(am33xx_resume_from_deep_sleep) ++ ++ ++/* ++ * Local variables ++ */ ++ .align ++resume_addr: ++ .word cpu_resume - PAGE_OFFSET + 0x80000000 ++kernel_flush: ++ .word v7_flush_dcache_all ++ddr_start: ++ .word PAGE_OFFSET ++emif_phys_addr: ++ .word AM33XX_EMIF_BASE ++virt_mpu_clkctrl: ++ .word AM33XX_CM_MPU_MPU_CLKCTRL ++virt_emif_clkctrl: ++ .word AM33XX_CM_PER_EMIF_CLKCTRL ++phys_emif_clkctrl: ++ .word (AM33XX_CM_BASE + AM33XX_CM_PER_MOD + \ ++ AM33XX_CM_PER_EMIF_CLKCTRL_OFFSET) ++module_disabled_val: ++ .word 0x30000 ++ ++/* DDR related defines */ ++dram_sync_word: ++ .word 0xDEADBEEF ++mem_type: ++ .word 0xDEADBEEF ++emif_addr_virt: ++ .word 0xDEADBEEF ++emif_rd_lat_val: ++ .word 0xDEADBEEF ++emif_timing1_val: ++ .word 0xDEADBEEF ++emif_timing2_val: ++ .word 0xDEADBEEF ++emif_timing3_val: ++ .word 0xDEADBEEF ++emif_sdcfg_val: ++ .word 0xDEADBEEF ++emif_ref_ctrl_val: ++ .word 0xDEADBEEF ++emif_zqcfg_val: ++ .word 0xDEADBEEF ++emif_pmcr_val: ++ .word 0xDEADBEEF ++emif_pmcr_shdw_val: ++ .word 0xDEADBEEF ++ ++ .align 3 ++ENTRY(am33xx_do_wfi_sz) ++ .word . - am33xx_do_wfi +--- a/arch/arm/mach-omap2/sleep44xx.S ++++ b/arch/arm/mach-omap2/sleep44xx.S +@@ -330,6 +330,141 @@ skip_l2en: + ENDPROC(omap4_cpu_resume) + #endif /* CONFIG_ARCH_OMAP4 */ + ++#ifdef CONFIG_SOC_OMAP5 ++/* ++ * ================================ ++ * == OMAP5 CPU suspend finisher == ++ * ================================ ++ * ++ * OMAP5 MPUSS states for the context save: ++ * save_state = ++ * 0 - Nothing lost and no need to save: MPUSS INA/CSWR ++ * 1 - CPUx L1 and logic lost: CPU OFF, MPUSS INA/CSWR ++ * 2 - CPUx L1 and logic lost + GIC lost: MPUSS OSWR ++ * 3 - CPUx L1 and logic lost + GIC + L2 lost: DEVICE OFF ++ */ ++ENTRY(omap5_finish_suspend) ++ stmfd sp!, {r4-r12, lr} ++ cmp r0, #0x0 ++ beq do_wfi @ No lowpower state, jump to WFI ++ ++ /* ++ * Flush all data from the L1 data cache before disabling ++ * SCTLR.C bit. ++ */ ++ bl omap4_get_sar_ram_base ++ ldr r9, [r0, #OMAP_TYPE_OFFSET] ++ cmp r9, #0x1 @ Check for HS device ++ bne skip_secure_l1_clean_op ++ mov r0, #0 @ Clean secure L1 ++ stmfd r13!, {r4-r12, r14} ++ ldr r12, =OMAP5_MON_CACHES_CLEAN_INDEX ++ DO_SMC ++ ldmfd r13!, {r4-r12, r14} ++skip_secure_l1_clean_op: ++ bl v7_flush_dcache_louis ++ ++ /* ++ * 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 ++ ++ /* Clean and Invalidate L1 data cache. */ ++ bl v7_flush_dcache_louis ++ ++ /* ++ * Take CPU out of Symmetric Multiprocessing (SMP) mode and thus ++ * preventing the CPU from receiving cache, TLB, or BTB ++ * maintenance operations broadcast by other CPUs in the cluster. ++ */ ++ 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) @ Disable SMP bit ++ mcrne p15, 0, r0, c1, c0, 1 ++ isb ++ dsb ++ ++ 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] @ Retrieve L2 state ++ ldrne r0, [r8, #L2X0_SAVE_OFFSET1] ++ cmp r0, #3 ++ bne do_wfi ++ bl omap4_get_sar_ram_base ++ ldr r9, [r0, #OMAP_TYPE_OFFSET] ++ cmp r9, #0x1 @ Check for HS device ++ bne skip_secure_l2_clean_op ++ mov r0, #1 @ Clean secure L2 ++ stmfd r13!, {r4-r12, r14} ++ ldr r12, =OMAP5_MON_CACHES_CLEAN_INDEX ++ DO_SMC ++ ldmfd r13!, {r4-r12, r14} ++skip_secure_l2_clean_op: ++ mov r0, #2 @ Flush L2 ++ bl v7_flush_dcache_all ++ ++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 ++ 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 ++ dsb ++ ldmfd sp!, {r4-r12, pc} ++ENDPROC(omap5_finish_suspend) ++ ++ENTRY(omap5_cpu_resume) ++#ifdef CONFIG_ARM_ERRATA_761171 ++ /* ++ * Work around for errata for 761171. Streaming write that will not ++ * allocate in L2 could lead to data corruption. ++ */ ++ mrc p15, 0, r0, c0, c0, 0 @ read main ID register ++ and r5, r0, #0x00f00000 @ variant ++ and r6, r0, #0x0000000f @ revision ++ orr r6, r6, r5, lsr #20-4 @ combine variant and revision ++ cmp r6, #0x03 @ Present before r0p3 ++ bgt 1f ++ mrc p15, 0, r0, c1, c0, 1 @ Read Auxctrl ++ orr r0, r0, #0x3 << 27 @ bits[28:27]-L1_mode3_threshold ++ ldr r12, =OMAP5_MON_AUX_CTRL_INDEX ++ dsb ++ smc #0 ++ dsb ++1: ++#endif ++ mrc p15, 1, r0, c15, c0, 0 @ Read L2 ACTLR ++ cmp r0, #0x118 @ Check if it is already set ++ beq skip_sec_l2 ++ ldr r0, =0x118 @ Setup L2 ACTLR = 0x118 ++ ldr r12, =OMAP5_MON_L2AUX_CTRL_INDEX ++ dsb ++ smc #0 ++ dsb ++skip_sec_l2: ++ b cpu_resume @ Jump to generic resume ++ENDPROC(omap5_cpu_resume) ++#endif /* CONFIG_SOC_OMAP5 */ ++ + #endif /* defined(CONFIG_SMP) && defined(CONFIG_PM) */ + + #ifndef CONFIG_OMAP4_ERRATA_I688 +--- a/arch/arm/mach-omap2/sram.c ++++ b/arch/arm/mach-omap2/sram.c +@@ -154,7 +154,7 @@ static void __init omap2_map_sram(void) + omap_sram_size -= SZ_16K; + } + #endif +- if (cpu_is_omap34xx()) { ++ if (cpu_is_omap34xx() || soc_is_am33xx()) { + /* + * SRAM must be marked as non-cached on OMAP3 since the + * CORE DPLL M2 divider change code (in SRAM) runs with the +@@ -285,10 +285,18 @@ static inline int omap34xx_sram_init(voi + } + #endif /* CONFIG_ARCH_OMAP3 */ + ++#ifdef CONFIG_SOC_AM33XX + static inline int am33xx_sram_init(void) + { ++ am33xx_push_sram_idle(); + return 0; + } ++#else ++static inline int am33xx_sram_init(void) ++{ ++ return 0; ++} ++#endif + + int __init omap_sram_init(void) + { +--- a/arch/arm/mach-omap2/sram.h ++++ b/arch/arm/mach-omap2/sram.h +@@ -62,8 +62,10 @@ extern unsigned long omap3_sram_configur + + #ifdef CONFIG_PM + extern void omap_push_sram_idle(void); ++extern void am33xx_push_sram_idle(void); + #else + static inline void omap_push_sram_idle(void) {} ++static inline void am33xx_push_sram_idle(void) {} + #endif /* CONFIG_PM */ + + #endif /* __ASSEMBLY__ */ +--- a/arch/arm/mach-omap2/timer.c ++++ b/arch/arm/mach-omap2/timer.c +@@ -55,6 +55,7 @@ + #include "soc.h" + #include "common.h" + #include "powerdomain.h" ++#include "omap-secure.h" + + #define REALTIME_COUNTER_BASE 0x48243200 + #define INCREMENTER_NUMERATOR_OFFSET 0x10 +@@ -65,6 +66,7 @@ + + static struct omap_dm_timer clkev; + static struct clock_event_device clockevent_gpt; ++unsigned long arch_timer_freq; + + static irqreturn_t omap2_gp_timer_interrupt(int irq, void *dev_id) + { +@@ -118,6 +120,29 @@ static void omap2_gp_timer_set_mode(enum + } + } + ++static void omap_clkevt_suspend(struct clock_event_device *unused) ++{ ++ struct omap_hwmod *oh; ++ ++ oh = omap_hwmod_lookup(clockevent_gpt.name); ++ if (!oh) ++ return; ++ ++ omap_hwmod_idle(oh); ++} ++ ++static void omap_clkevt_resume(struct clock_event_device *unused) ++{ ++ struct omap_hwmod *oh; ++ ++ oh = omap_hwmod_lookup(clockevent_gpt.name); ++ if (!oh) ++ return; ++ ++ omap_hwmod_enable(oh); ++ __omap_dm_timer_int_enable(&clkev, OMAP_TIMER_INT_OVERFLOW); ++} ++ + static struct clock_event_device clockevent_gpt = { + .features = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT, + .rating = 300, +@@ -276,8 +301,13 @@ static int __init omap_dm_timer_init_one + if (!timer->io_base) + return -ENXIO; + ++ omap_hwmod_setup_one(oh_name); ++ + /* After the dmtimer is using hwmod these clocks won't be needed */ +- timer->fclk = clk_get(NULL, omap_hwmod_get_main_clk(oh)); ++ if (oh->_clk) ++ timer->fclk = oh->_clk; ++ else ++ timer->fclk = clk_get(NULL, omap_hwmod_get_main_clk(oh)); + if (IS_ERR(timer->fclk)) + return PTR_ERR(timer->fclk); + +@@ -297,7 +327,6 @@ static int __init omap_dm_timer_init_one + + clk_put(src); + +- omap_hwmod_setup_one(oh_name); + omap_hwmod_enable(oh); + __omap_dm_timer_init_regs(timer); + +@@ -323,6 +352,11 @@ static void __init omap2_gp_clockevent_i + clkev.id = gptimer_id; + clkev.errata = omap_dm_timer_get_errata(); + ++ if (soc_is_am33xx()) { ++ clockevent_gpt.suspend = omap_clkevt_suspend; ++ clockevent_gpt.resume = omap_clkevt_resume; ++ } ++ + /* + * For clock-event timers we never read the timer counter and + * so we are not impacted by errata i103 and i767. Therefore, +@@ -515,6 +549,10 @@ static void __init realtime_counter_init + num = 8; + den = 25; + break; ++ case 20000000: ++ num = 192; ++ den = 625; ++ break; + case 2600000: + num = 384; + den = 1625; +@@ -542,6 +580,9 @@ static void __init realtime_counter_init + reg |= den; + __raw_writel(reg, base + INCREMENTER_DENUMERATOR_RELOAD_OFFSET); + ++ arch_timer_freq = (rate / den) * num; ++ omap_smc1(OMAP5_DRA7_MON_SET_CNTFRQ_INDEX, arch_timer_freq); ++ + iounmap(base); + } + #else +--- a/arch/arm/mach-omap2/twl-common.c ++++ b/arch/arm/mach-omap2/twl-common.c +@@ -24,6 +24,7 @@ + #include <linux/i2c/twl.h> + #include <linux/gpio.h> + #include <linux/string.h> ++#include <linux/phy/phy.h> + #include <linux/regulator/machine.h> + #include <linux/regulator/fixed.h> + +@@ -90,8 +91,18 @@ void __init omap_pmic_late_init(void) + } + + #if defined(CONFIG_ARCH_OMAP3) ++struct phy_consumer consumers[] = { ++ PHY_CONSUMER("musb-hdrc.0", "usb"), ++}; ++ ++struct phy_init_data init_data = { ++ .consumers = consumers, ++ .num_consumers = ARRAY_SIZE(consumers), ++}; ++ + static struct twl4030_usb_data omap3_usb_pdata = { + .usb_mode = T2_USB_MODE_ULPI, ++ .init_data = &init_data, + }; + + static int omap3_batt_table[] = { +--- a/arch/arm/mach-omap2/usb.h ++++ b/arch/arm/mach-omap2/usb.h +@@ -58,7 +58,6 @@ struct usbhs_phy_data { + int reset_gpio; + int vcc_gpio; + bool vcc_polarity; /* 1 active high, 0 active low */ +- void *platform_data; + }; + + extern void usb_musb_init(struct omap_musb_board_data *board_data); +--- a/arch/arm/mach-omap2/usb-host.c ++++ b/arch/arm/mach-omap2/usb-host.c +@@ -435,6 +435,7 @@ int usbhs_init_phys(struct usbhs_phy_dat + struct platform_device *pdev; + char *phy_id; + struct platform_device_info pdevinfo; ++ struct usb_phy_gen_xceiv_platform_data nop_pdata; + + for (i = 0; i < num_phys; i++) { + +@@ -455,11 +456,18 @@ int usbhs_init_phys(struct usbhs_phy_dat + return -ENOMEM; + } + ++ /* set platform data */ ++ memset(&nop_pdata, 0, sizeof(nop_pdata)); ++ if (gpio_is_valid(phy->vcc_gpio)) ++ nop_pdata.needs_vcc = true; ++ nop_pdata.gpio_reset = phy->reset_gpio; ++ nop_pdata.type = USB_PHY_TYPE_USB2; ++ + /* create a NOP PHY device */ + memset(&pdevinfo, 0, sizeof(pdevinfo)); + pdevinfo.name = nop_name; + pdevinfo.id = phy->port; +- pdevinfo.data = phy->platform_data; ++ pdevinfo.data = &nop_pdata; + pdevinfo.size_data = + sizeof(struct usb_phy_gen_xceiv_platform_data); + scnprintf(phy_id, MAX_STR, "usb_phy_gen_xceiv.%d", +@@ -474,14 +482,6 @@ int usbhs_init_phys(struct usbhs_phy_dat + + usb_bind_phy("ehci-omap.0", phy->port - 1, phy_id); + +- /* Do we need RESET regulator ? */ +- if (gpio_is_valid(phy->reset_gpio)) { +- scnprintf(rail_name, MAX_STR, +- "hsusb%d_reset", phy->port); +- usbhs_add_regulator(rail_name, phy_id, "reset", +- phy->reset_gpio, 1); +- } +- + /* Do we need VCC regulator ? */ + if (gpio_is_valid(phy->vcc_gpio)) { + scnprintf(rail_name, MAX_STR, "hsusb%d_vcc", phy->port); +--- a/arch/arm/mach-omap2/wd_timer.c ++++ b/arch/arm/mach-omap2/wd_timer.c +@@ -123,6 +123,11 @@ static int __init omap_init_wdt(void) + + pdata.read_reset_sources = prm_read_reset_sources; + ++ if (cpu_is_omap44xx() || soc_is_omap54xx()) ++ pdata.ip_rev = WDTIMER2_IP4; ++ else ++ pdata.ip_rev = WDTIMER2_IP3; ++ + pdev = omap_device_build(dev_name, id, oh, &pdata, + sizeof(struct omap_wd_timer_platform_data)); + WARN(IS_ERR(pdev), "Can't build omap_device for %s:%s.\n", +--- /dev/null ++++ b/arch/arm/mach-omap2/wkup_m3.c +@@ -0,0 +1,410 @@ ++/* ++* AM33XX Power Management Routines ++ * ++ * Copyright (C) 2012 Texas Instruments Incorporated - http://www.ti.com/ ++ * Vaibhav Bedia <vaibhav.bedia@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/kernel.h> ++#include <linux/init.h> ++#include <linux/slab.h> ++#include <linux/cpu.h> ++#include <linux/err.h> ++#include <linux/firmware.h> ++#include <linux/io.h> ++#include <linux/platform_device.h> ++#include <linux/pm_runtime.h> ++#include <linux/module.h> ++#include <linux/interrupt.h> ++#include <linux/of.h> ++#include <linux/omap-mailbox.h> ++ ++#include "pm33xx.h" ++#include "omap_device.h" ++ ++#define WKUP_M3_WAKE_SRC_MASK 0xFF ++ ++#define WKUP_M3_STATUS_RESP_SHIFT 16 ++#define WKUP_M3_STATUS_RESP_MASK (0xffff << 16) ++ ++#define WKUP_M3_FW_VERSION_SHIFT 0 ++#define WKUP_M3_FW_VERSION_MASK 0xffff ++ ++/* AM33XX M3_TXEV_EOI register */ ++#define AM33XX_CONTROL_M3_TXEV_EOI 0x00 ++ ++#define AM33XX_M3_TXEV_ACK (0x1 << 0) ++#define AM33XX_M3_TXEV_ENABLE (0x0 << 0) ++ ++/* AM33XX IPC message registers */ ++#define AM33XX_CONTROL_IPC_MSG_REG0 0x04 ++#define AM33XX_CONTROL_IPC_MSG_REG1 0x08 ++#define AM33XX_CONTROL_IPC_MSG_REG2 0x0c ++#define AM33XX_CONTROL_IPC_MSG_REG3 0x10 ++#define AM33XX_CONTROL_IPC_MSG_REG4 0x14 ++#define AM33XX_CONTROL_IPC_MSG_REG5 0x18 ++#define AM33XX_CONTROL_IPC_MSG_REG6 0x1c ++#define AM33XX_CONTROL_IPC_MSG_REG7 0x20 ++ ++struct wkup_m3_context { ++ struct device *dev; ++ void __iomem *code; ++ void __iomem *ipc; ++ u8 is_valid; ++ struct wkup_m3_ops *ops; ++ struct omap_mbox *mbox; ++}; ++ ++struct wkup_m3_wakeup_src wakeups[] = { ++ {.irq_nr = 35, .src = "USB0_PHY"}, ++ {.irq_nr = 36, .src = "USB1_PHY"}, ++ {.irq_nr = 40, .src = "I2C0"}, ++ {.irq_nr = 41, .src = "RTC Timer"}, ++ {.irq_nr = 42, .src = "RTC Alarm"}, ++ {.irq_nr = 43, .src = "Timer0"}, ++ {.irq_nr = 44, .src = "Timer1"}, ++ {.irq_nr = 45, .src = "UART"}, ++ {.irq_nr = 46, .src = "GPIO0"}, ++ {.irq_nr = 48, .src = "MPU_WAKE"}, ++ {.irq_nr = 49, .src = "WDT0"}, ++ {.irq_nr = 50, .src = "WDT1"}, ++ {.irq_nr = 51, .src = "ADC_TSC"}, ++ {.irq_nr = 0, .src = "Unknown"}, ++}; ++ ++static struct wkup_m3_context *wkup_m3; ++ ++static void am33xx_txev_eoi(void) ++{ ++ writel(AM33XX_M3_TXEV_ACK, ++ wkup_m3->ipc + AM33XX_CONTROL_M3_TXEV_EOI); ++} ++ ++static void am33xx_txev_enable(void) ++{ ++ writel(AM33XX_M3_TXEV_ENABLE, ++ wkup_m3->ipc + AM33XX_CONTROL_M3_TXEV_EOI); ++} ++ ++static void am33xx_ctrl_ipc_write(struct am33xx_ipc_regs *ipc_regs) ++{ ++ writel(ipc_regs->reg0, ++ wkup_m3->ipc + AM33XX_CONTROL_IPC_MSG_REG0); ++ writel(ipc_regs->reg1, ++ wkup_m3->ipc + AM33XX_CONTROL_IPC_MSG_REG1); ++ writel(ipc_regs->reg2, ++ wkup_m3->ipc + AM33XX_CONTROL_IPC_MSG_REG2); ++ writel(ipc_regs->reg3, ++ wkup_m3->ipc + AM33XX_CONTROL_IPC_MSG_REG3); ++ writel(ipc_regs->reg4, ++ wkup_m3->ipc + AM33XX_CONTROL_IPC_MSG_REG4); ++ writel(ipc_regs->reg5, ++ wkup_m3->ipc + AM33XX_CONTROL_IPC_MSG_REG5); ++ writel(ipc_regs->reg6, ++ wkup_m3->ipc + AM33XX_CONTROL_IPC_MSG_REG6); ++ writel(ipc_regs->reg7, ++ wkup_m3->ipc + AM33XX_CONTROL_IPC_MSG_REG7); ++} ++ ++static void am33xx_ctrl_ipc_read(struct am33xx_ipc_regs *ipc_regs) ++{ ++ ipc_regs->reg0 = readl(wkup_m3->ipc ++ + AM33XX_CONTROL_IPC_MSG_REG0); ++ ipc_regs->reg1 = readl(wkup_m3->ipc ++ + AM33XX_CONTROL_IPC_MSG_REG1); ++ ipc_regs->reg2 = readl(wkup_m3->ipc ++ + AM33XX_CONTROL_IPC_MSG_REG2); ++ ipc_regs->reg3 = readl(wkup_m3->ipc ++ + AM33XX_CONTROL_IPC_MSG_REG3); ++ ipc_regs->reg4 = readl(wkup_m3->ipc ++ + AM33XX_CONTROL_IPC_MSG_REG4); ++ ipc_regs->reg5 = readl(wkup_m3->ipc ++ + AM33XX_CONTROL_IPC_MSG_REG5); ++ ipc_regs->reg6 = readl(wkup_m3->ipc ++ + AM33XX_CONTROL_IPC_MSG_REG6); ++ ipc_regs->reg7 = readl(wkup_m3->ipc ++ + AM33XX_CONTROL_IPC_MSG_REG7); ++} ++ ++int wkup_m3_is_valid() ++{ ++ return wkup_m3->is_valid; ++} ++ ++int wkup_m3_ping(void) ++{ ++ int ret = 0; ++ ++ if (!wkup_m3->mbox) { ++ pr_err("PM: No IPC channel to communicate with wkup_m3!\n"); ++ return -EIO; ++ } ++ ++ /* ++ * Write a dummy message to the mailbox in order to trigger the RX ++ * interrupt to alert the M3 that data is available in the IPC ++ * registers. ++ */ ++ ret = omap_mbox_msg_send(wkup_m3->mbox, 0xABCDABCD); ++ ++ return ret; ++} ++ ++struct wkup_m3_wakeup_src wkup_m3_wake_src(void) ++{ ++ struct am33xx_ipc_regs ipc_regs; ++ unsigned int wakeup_src_idx; ++ int j; ++ ++ am33xx_ctrl_ipc_read(&ipc_regs); ++ ++ wakeup_src_idx = ipc_regs.reg6 & WKUP_M3_WAKE_SRC_MASK; ++ ++ for (j = 0; j < ARRAY_SIZE(wakeups)-1; j++) { ++ if (wakeups[j].irq_nr == wakeup_src_idx) ++ return wakeups[j]; ++ } ++ ++ return wakeups[j]; ++} ++ ++ ++int wkup_m3_pm_status(void) ++{ ++ unsigned int i; ++ struct am33xx_ipc_regs ipc_regs; ++ ++ am33xx_ctrl_ipc_read(&ipc_regs); ++ ++ i = WKUP_M3_STATUS_RESP_MASK & ipc_regs.reg1; ++ i >>= __ffs(WKUP_M3_STATUS_RESP_MASK); ++ ++ return i; ++} ++ ++/* ++ * Invalidate M3 firmware version before hardreset. ++ * Write invalid version in lower 4 nibbles of parameter ++ * register (ipc_regs + 0x8). ++ */ ++ ++static void wkup_m3_fw_version_clear(void) ++{ ++ struct am33xx_ipc_regs ipc_regs; ++ ++ am33xx_ctrl_ipc_read(&ipc_regs); ++ ipc_regs.reg2 = 0xFFFF0000; ++ am33xx_ctrl_ipc_write(&ipc_regs); ++ ++ return; ++} ++ ++int wkup_m3_fw_version_read(void) ++{ ++ struct am33xx_ipc_regs ipc_regs; ++ ++ am33xx_ctrl_ipc_read(&ipc_regs); ++ ++ return ipc_regs.reg2 & WKUP_M3_FW_VERSION_MASK; ++} ++ ++void wkup_m3_pm_set_cmd(struct am33xx_ipc_regs *ipc_regs) ++{ ++ am33xx_ctrl_ipc_write(ipc_regs); ++} ++ ++void wkup_m3_set_ops(struct wkup_m3_ops *ops) ++{ ++ wkup_m3->ops = ops; ++} ++ ++static irqreturn_t wkup_m3_txev_handler(int irq, void *unused) ++{ ++ am33xx_txev_eoi(); ++ ++ if (wkup_m3->ops && wkup_m3->ops->firmware_loaded) ++ wkup_m3->ops->txev_handler(); ++ ++ am33xx_txev_enable(); ++ ++ return IRQ_HANDLED; ++} ++ ++int wkup_m3_prepare(void) ++{ ++ int ret = 0; ++ struct platform_device *pdev = to_platform_device(wkup_m3->dev); ++ ++ wkup_m3->mbox = omap_mbox_get("wkup_m3", NULL); ++ ++ if (IS_ERR(wkup_m3->mbox)) { ++ ret = -EBUSY; ++ pr_err("PM: IPC Request for A8->M3 Channel failed!\n"); ++ return ret; ++ } ++ ++ wkup_m3_fw_version_clear(); ++ ++ /* check that the code is loaded */ ++ ret = omap_device_deassert_hardreset(pdev, "wkup_m3"); ++ ++ return ret; ++} ++ ++static int wkup_m3_copy_code(const u8 *data, size_t size) ++{ ++ if (size > SZ_16K) ++ return -ENOMEM; ++ ++ memcpy_toio(wkup_m3->code, data, size); ++ ++ return 0; ++} ++ ++static void wkup_m3_firmware_cb(const struct firmware *fw, void *context) ++{ ++ int ret = 0; ++ ++ /* no firmware found */ ++ if (!fw) { ++ pr_err("PM: request_firmware failed\n"); ++ return; ++ } ++ ++ ret = wkup_m3_copy_code(fw->data, fw->size); ++ ++ if (ret) { ++ pr_info("PM: Failed to copy firmware for M3"); ++ } else { ++ if (wkup_m3->ops && wkup_m3->ops->firmware_loaded) ++ wkup_m3->ops->firmware_loaded(); ++ ++ wkup_m3->is_valid = true; ++ } ++ ++ return; ++} ++ ++static int wkup_m3_probe(struct platform_device *pdev) ++{ ++ int irq, ret = 0; ++ struct resource *res; ++ ++ pm_runtime_enable(&pdev->dev); ++ ++ ret = pm_runtime_get_sync(&pdev->dev); ++ if (IS_ERR_VALUE(ret)) { ++ dev_err(&pdev->dev, "pm_runtime_get_sync() failed\n"); ++ return ret; ++ } ++ ++ irq = platform_get_irq(pdev, 0); ++ if (!irq) { ++ dev_err(&pdev->dev, "no irq resource\n"); ++ ret = -ENXIO; ++ goto err; ++ } ++ ++ res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "m3_umem"); ++ if (!res) { ++ dev_err(&pdev->dev, "no memory resource\n"); ++ ret = -ENXIO; ++ goto err; ++ } ++ ++ wkup_m3 = devm_kzalloc(&pdev->dev, sizeof(*wkup_m3), GFP_KERNEL); ++ if (!wkup_m3) { ++ pr_err("Memory allocation failed\n"); ++ ret = -ENOMEM; ++ goto err; ++ } ++ ++ wkup_m3->dev = &pdev->dev; ++ ++ wkup_m3->code = devm_request_and_ioremap(wkup_m3->dev, res); ++ if (!wkup_m3->code) { ++ dev_err(wkup_m3->dev, "could not ioremap\n"); ++ ret = -EADDRNOTAVAIL; ++ goto err; ++ } ++ ++ res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "ipc_regs"); ++ if (!res) { ++ dev_err(&pdev->dev, "no memory resource for ipc\n"); ++ ret = -ENXIO; ++ goto err; ++ } ++ ++ wkup_m3->ipc = devm_request_and_ioremap(wkup_m3->dev, res); ++ if (!wkup_m3->ipc) { ++ dev_err(wkup_m3->dev, "could not ioremap ipc_mem\n"); ++ ret = -EADDRNOTAVAIL; ++ goto err; ++ } ++ ++ ret = devm_request_irq(wkup_m3->dev, irq, wkup_m3_txev_handler, ++ IRQF_DISABLED, "wkup_m3_txev", NULL); ++ if (ret) { ++ dev_err(wkup_m3->dev, "request_irq failed\n"); ++ goto err; ++ } ++ ++ wkup_m3->is_valid = false; ++ ++ pr_info("PM: Loading am335x-pm-firmware.bin"); ++ ++ /* We don't want to delay boot */ ++ ret = request_firmware_nowait(THIS_MODULE, 0, "am335x-pm-firmware.bin", ++ &pdev->dev, GFP_KERNEL, NULL, ++ wkup_m3_firmware_cb); ++ ++err: ++ return ret; ++} ++ ++static int wkup_m3_remove(struct platform_device *pdev) ++{ ++ return 0; ++} ++ ++static struct of_device_id wkup_m3_dt_ids[] = { ++ { .compatible = "ti,am3353-wkup-m3" }, ++ { } ++}; ++MODULE_DEVICE_TABLE(of, wkup_m3_dt_ids); ++ ++static int wkup_m3_rpm_suspend(struct device *dev) ++{ ++ return -EBUSY; ++} ++ ++static int wkup_m3_rpm_resume(struct device *dev) ++{ ++ return 0; ++} ++ ++static const struct dev_pm_ops wkup_m3_ops = { ++ SET_RUNTIME_PM_OPS(wkup_m3_rpm_suspend, wkup_m3_rpm_resume, NULL) ++}; ++ ++static struct platform_driver wkup_m3_driver = { ++ .probe = wkup_m3_probe, ++ .remove = wkup_m3_remove, ++ .driver = { ++ .name = "wkup_m3", ++ .owner = THIS_MODULE, ++ .of_match_table = of_match_ptr(wkup_m3_dt_ids), ++ .pm = &wkup_m3_ops, ++ }, ++}; ++ ++module_platform_driver(wkup_m3_driver); +--- /dev/null ++++ b/arch/arm/mach-omap2/wkup_m3.h +@@ -0,0 +1,60 @@ ++/* ++ * TI Wakeup M3 Power Management Routines ++ * ++ * Copyright (C) 2013 Texas Instruments Incorporated - http://www.ti.com/ ++ * Dave Gerlach <d-gerlach@ti.com> ++ * ++ * This program is free software; you can redistribute it and/or ++ * modify it under the terms of the GNU General Public License as ++ * published by the Free Software Foundation version 2. ++ * ++ * This program is distributed "as is" WITHOUT ANY WARRANTY of any ++ * kind, whether express or implied; without even the implied warranty ++ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ */ ++ ++#ifndef __ASSEMBLER__ ++ ++/** ++ * struct wkup_m3_ops - Callbacks for allowing pm code to interact with wkup_m3. ++ * ++ * @txev_handler: Callback to allow pm code to react to response from wkup_m3 ++ * after pinging it using wkup_m3_ping. ++ * ++ * @firmware_loaded: Callback invoked when the firmware has been loaded to the ++ * m3 to allow the pm code to enable suspend/resume ops. ++ */ ++ ++struct wkup_m3_ops { ++ void (*txev_handler)(void); ++ void (*firmware_loaded)(void); ++}; ++ ++struct wkup_m3_wakeup_src { ++ int irq_nr; ++ char src[10]; ++}; ++ ++struct am33xx_ipc_regs { ++ u32 reg0; ++ u32 reg1; ++ u32 reg2; ++ u32 reg3; ++ u32 reg4; ++ u32 reg5; ++ u32 reg6; ++ u32 reg7; ++}; ++ ++int wkup_m3_prepare(void); ++void wkup_m3_set_ops(struct wkup_m3_ops *ops); ++int wkup_m3_ping(void); ++struct wkup_m3_wakeup_src wkup_m3_wake_src(void); ++int wkup_m3_pm_status(void); ++int wkup_m3_is_valid(void); ++int wkup_m3_fw_version_read(void); ++void wkup_m3_pm_set_cmd(struct am33xx_ipc_regs *ipc_regs); ++ ++#endif ++ +--- a/arch/arm/Makefile ++++ b/arch/arm/Makefile +@@ -314,6 +314,8 @@ $(INSTALL_TARGETS): + + %.dtb: | scripts + $(Q)$(MAKE) $(build)=$(boot)/dts MACHINE=$(MACHINE) $(boot)/dts/$@ ++uImage.%: uImage ++ $(Q)$(MAKE) $(build)=$(boot) MACHINE=$(MACHINE) $(boot)/$@ + + PHONY += dtbs + dtbs: scripts +--- a/arch/arm/plat-omap/include/plat/dmtimer.h ++++ b/arch/arm/plat-omap/include/plat/dmtimer.h +@@ -336,8 +336,11 @@ static inline void __omap_dm_timer_enabl + if (timer->posted) + return; + +- if (timer->errata & OMAP_TIMER_ERRATA_I103_I767) ++ if (timer->errata & OMAP_TIMER_ERRATA_I103_I767) { ++ timer->posted = OMAP_TIMER_NONPOSTED; ++ __omap_dm_timer_write(timer, OMAP_TIMER_IF_CTRL_REG, 0, 0); + return; ++ } + + __omap_dm_timer_write(timer, OMAP_TIMER_IF_CTRL_REG, + OMAP_TIMER_CTRL_POSTED, 0); +--- /dev/null ++++ b/Documentation/ABI/testing/configfs-usb-gadget-mass-storage +@@ -0,0 +1,31 @@ ++What: /config/usb-gadget/gadget/functions/mass_storage.name ++Date: Oct 2013 ++KenelVersion: 3.13 ++Description: ++ The attributes: ++ ++ stall - Set to permit function to halt bulk endpoints. ++ Disabled on some USB devices known not to work ++ correctly. You should set it to true. ++ num_buffers - Number of pipeline buffers. Valid numbers ++ are 2..4. Available only if ++ CONFIG_USB_GADGET_DEBUG_FILES is set. ++ ++What: /config/usb-gadget/gadget/functions/mass_storage.name/lun.name ++Date: Oct 2013 ++KenelVersion: 3.13 ++Description: ++ The attributes: ++ ++ file - The path to the backing file for the LUN. ++ Required if LUN is not marked as removable. ++ ro - Flag specifying access to the LUN shall be ++ read-only. This is implied if CD-ROM emulation ++ is enabled as well as when it was impossible ++ to open "filename" in R/W mode. ++ removable - Flag specifying that LUN shall be indicated as ++ being removable. ++ cdrom - Flag specifying that LUN shall be reported as ++ being a CD-ROM. ++ nofua - Flag specifying that FUA flag ++ in SCSI WRITE(10,12) +--- /dev/null ++++ b/Documentation/devicetree/bindings/arm/omap/crossbar.txt +@@ -0,0 +1,24 @@ ++* TI - IRQ/DMA Crossbar ++ ++This version is an implementation of the Crossbar IRQ/DMA IP ++ ++Required properties: ++- compatible : Should be "ti,dra-crossbar" ++- crossbar-name: Name of the controller to which crossbar output is routed ++- reg: Contains crossbar register address range ++- reg-width: Represents the width of the individual registers ++- crossbar-lines: Default mappings.Should contain the crossbar-name ++ device name, int/dma request number, crossbar number, ++ register offset in the same order. ++ ++Examples: ++ crossbar_mpu: mpuirq@4a002a48 { ++ compatible = "crossbar"; ++ crossbar-name = "mpu-irq"; ++ reg = <0x4a002a48 0x0130>; ++ reg-width = <16>; ++ crossbar-lines = "mpu-irq", "rtc-ss-alarm", <0x9f 0xd9 0x12c>, ++ "mpu-irq", "mcasp3-arevt", <0x9e 0x96 0x12a>, ++ "mpu-irq", "mcasp3-axevt", <0x9d 0x97 0x128>; ++ }; ++ +--- /dev/null ++++ b/Documentation/devicetree/bindings/arm/omap/dmm.txt +@@ -0,0 +1,17 @@ ++OMAP Dynamic Memory Manager (DMM) bindings ++ ++Required properties: ++- compatible: Must be "ti,omap4-dmm" for OMAP4 family ++ Must be "ti,omap5-dmm" for OMAP5 family ++- reg: Contains timer register address range (base address and length) ++- interrupts: Contains interrupt information (source, etc) for the DMM IRQ ++- ti,hwmods: Name of the hwmod associated to the counter, which is typically ++ "dmm" ++ ++Example: ++ ++dmm: dmm@4e000000 { ++ compatible = "ti,omap4-dmm"; ++ reg = <0x4e000000 0x800>; ++ ti,hwmods = "dmm"; ++}; +--- a/Documentation/devicetree/bindings/arm/omap/omap.txt ++++ b/Documentation/devicetree/bindings/arm/omap/omap.txt +@@ -21,7 +21,8 @@ Required properties: + Optional properties: + - ti,no_idle_on_suspend: When present, it prevents the PM to idle the module + during suspend. +- ++- ti,no-reset: When present, the module should not be reset ++- ti,no-idle: When present, the module should not be idled + + Example: + +@@ -60,5 +61,8 @@ Boards: + - AM43x EPOS EVM + compatible = "ti,am43x-epos-evm", "ti,am4372", "ti,am43" + ++- AM437x GP EVM ++ compatible = "ti,am437x-gp-evm", "ti,am4372", "ti,am43" ++ + - DRA7 EVM: Software Developement Board for DRA7XX + compatible = "ti,dra7-evm", "ti,dra7" +--- /dev/null ++++ b/Documentation/devicetree/bindings/arm/omap/prcm.txt +@@ -0,0 +1,13 @@ ++TI Power Reset Clock Manager (PRCM) ++ ++Properties: ++- compatible: "ti,am4372-prcm" for prcm in am43x SoC's ++ "ti,am3352-prcm" for prcm in am335x SoC's ++- #reset-cells: 1 (refer generic reset bindings for details) ++ ++example: ++ prcm: prcm@44df0000 { ++ compatible = "ti,am4372-prcm"; ++ reg = <0x44df0000 0xa000>; ++ #reset-cells = <1>; ++ }; +--- a/Documentation/devicetree/bindings/ata/ahci-platform.txt ++++ b/Documentation/devicetree/bindings/ata/ahci-platform.txt +@@ -4,7 +4,8 @@ SATA nodes are defined to describe on-ch + Each SATA controller should have its own node. + + Required properties: +-- compatible : compatible list, contains "snps,spear-ahci" ++- compatible : compatible list, contains "snps,spear-ahci", ++ snps,exynos5440-ahci or "snps,dwc-ahci" + - interrupts : <interrupt mapping for SATA IRQ> + - reg : <registers mapping> + +--- /dev/null ++++ b/Documentation/devicetree/bindings/ata/ti-sata.txt +@@ -0,0 +1,31 @@ ++* Texas Instruments SATA Controller Wrapper ++ ++Required properties: ++- compatible : "ti,sata" ++- ti,hwmods : "sata" ++- reg : Register mapping ++- #address-cells: <1> ++- #size-cells : <1> ++- ranges : allows valid translation between child's address space and parent's ++ address space. ++- Must contain at least one child node for the SATA controller core ++ ++Example: ++ ++ sata: sata@4a141100 { ++ compatible = "ti,sata"; ++ ti,hwmods = "sata"; ++ reg = <0x4a141100 0x7>; ++ #address-cells = <1>; ++ #size-cells = <1>; ++ ranges; ++ dwc-ahci@4a140000 { ++ compatible = "snps,dwc-ahci"; ++ reg = <0x4a140000 0x1100>; ++ interrupts = <GIC_SPI 54 IRQ_TYPE_LEVEL_HIGH>; ++ phys = <&sata_phy>; ++ phy-names = "sata-phy"; ++ clocks = <&sata_ref_clk>; ++ clock-names = "optclk"; ++ }; ++ }; +--- /dev/null ++++ b/Documentation/devicetree/bindings/clock/clk-palmas.txt +@@ -0,0 +1,35 @@ ++* Palmas 32KHz clocks * ++ ++Palmas device has two clock output pins for 32KHz, KG and KG_AUDIO. ++ ++This binding uses the common clock binding ./clock-bindings.txt. ++ ++Required properties: ++- compatible : "ti,palmas-clk32kg" for clk32kg clock ++ "ti,palmas-clk32kgaudio" for clk32kgaudio clock ++- #clock-cells : shall be set to 0. ++ ++Optional property: ++- ti,external-sleep-control: The external enable input pins controlled the ++ enable/disable of clocks. The external enable input pins ENABLE1, ++ ENABLE2 and NSLEEP. The valid values for the external pins are: ++ PALMAS_EXT_CONTROL_PIN_ENABLE1 for ENABLE1 pin ++ PALMAS_EXT_CONTROL_PIN_ENABLE2 for ENABLE2 pin ++ PALMAS_EXT_CONTROL_PIN_NSLEEP for NSLEEP pin ++ Option 0 or missing this property means the clock is enabled/disabled ++ via register access and these pins do not have any control. ++ The macros of external control pins for DTS is defined at ++ dt-bindings/mfd/palmas.h ++ ++Example: ++ #include <dt-bindings/mfd/palmas.h> ++ ... ++ palmas: tps65913@58 { ++ ... ++ clk32kg: palmas_clk32k@0 { ++ compatible = "ti,palmas-clk32kg"; ++ #clock-cells = <0>; ++ ti,external-sleep-control = <PALMAS_EXT_CONTROL_PIN_NSLEEP>; ++ }; ++ ... ++ }; +--- /dev/null ++++ b/Documentation/devicetree/bindings/clock/divider-clock.txt +@@ -0,0 +1,90 @@ ++Binding for simple divider clock. ++ ++This binding uses the common clock binding[1]. It assumes a ++register-mapped adjustable clock rate divider that does not gate and has ++only one input clock or parent. By default the value programmed into ++the register is one less than the actual divisor value. E.g: ++ ++register value actual divisor value ++0 1 ++1 2 ++2 3 ++ ++This assumption may be modified by the following optional properties: ++ ++index-starts-at-one - valid divisor values start at 1, not the default ++of 0. E.g: ++register value actual divisor value ++1 1 ++2 2 ++3 3 ++ ++index-power-of-two - valid divisor values are powers of two. E.g: ++register value actual divisor value ++0 1 ++1 2 ++2 4 ++ ++index-allow-zero - same as index_one, but zero is divide-by-1. E.g: ++register value actual divisor value ++0 1 ++1 1 ++2 2 ++ ++Additionally a table of valid dividers may be supplied like so: ++ ++ table = <4 0>, <8, 1>; ++ ++where the first value in the pair is the divider and the second value is ++the programmed register bitfield. ++ ++The binding must also provide the register to control the divider and ++the mask for the corresponding control bits. Optionally the number of ++bits to shift that mask, if necessary. If the shift value is missing it ++is the same as supplying a zero shift. ++ ++[1] Documentation/devicetree/bindings/clock/clock-bindings.txt ++ ++Required properties: ++- compatible : shall be "divider-clock". ++- #clock-cells : from common clock binding; shall be set to 0. ++- clocks : link to phandle of parent clock ++- reg : base address for register controlling adjustable divider ++- bit-mask : arbitrary bitmask for programming the adjustable divider ++ ++Optional properties: ++- clock-output-names : from common clock binding. ++- table : array of integer pairs defining divisors & bitfield values ++- bit-shift : number of bits to shift the bit-mask, defaults to ++ (ffs(mask) - 1) if not present ++- minimum-divider : min divisor for dividing the input clock rate, only ++ needed if the first divisor is offset from the default value ++- maximum-divider : max divisor for dividing the input clock rate, only ++ needed if the max divisor is less than (mask + 1). ++- index-starts-at-one : valid divisor programming starts at 1, not zero ++- index-power-of-two : valid divisor programming must be a power of two ++- index-allow-zero : implies index-one, and programming zero results in ++ divide-by-one ++- hiword-mask : lower half of the register programs the divider, upper ++ half of the register indicates bits that were updated in the lower ++ half ++ ++Examples: ++ clock_foo: clock_foo@4a008100 { ++ compatible = "divider-clock"; ++ #clock-cells = <0>; ++ clocks = <&clock_baz>; ++ reg = <0x4a008100 0x4> ++ mask = <0x3> ++ maximum-divider = <3> ++ }; ++ ++ clock_bar: clock_bar@4a008108 { ++ #clock-cells = <0>; ++ compatible = "divider-clock"; ++ clocks = <&clock_foo>; ++ reg = <0x4a008108 0x4>; ++ mask = <0x1>; ++ shift = <0>; ++ table = < 4 0 >, < 8 1 >; ++ }; +--- /dev/null ++++ b/Documentation/devicetree/bindings/clock/gate-clock.txt +@@ -0,0 +1,36 @@ ++Binding for simple gate clock. ++ ++This binding uses the common clock binding[1]. It assumes a ++register-mapped clock gate controlled by a single bit that has only one ++input clock or parent. By default setting the specified bit gates the ++clock signal and clearing the bit ungates it. ++ ++The binding must provide the register to control the gate and the bit ++shift for the corresponding gate control bit. Some clocks set the bit to ++gate the clock signal, and clear it to ungate the clock signal. The ++optional "set-bit-to-disable" specifies this behavior. ++ ++[1] Documentation/devicetree/bindings/clock/clock-bindings.txt ++ ++Required properties: ++- compatible : shall be "gate-clock". ++- #clock-cells : from common clock binding; shall be set to 0. ++- clocks : link to phandle of parent clock ++- reg : base address for register controlling adjustable gate ++- bit-shift : bit shift for programming the clock gate ++ ++Optional properties: ++- clock-output-names : from common clock binding. ++- set-bit-to-disable : inverts default gate programming. Setting the bit ++ gates the clock and clearing the bit ungates the clock. ++- hiword-mask : lower half of the register controls the gate, upper half ++ of the register indicates bits that were updated in the lower half ++ ++Examples: ++ clock_foo: clock_foo@4a008100 { ++ compatible = "gate-clock"; ++ #clock-cells = <0>; ++ clocks = <&clock_bar>; ++ reg = <0x4a008100 0x4> ++ bit-shift = <3> ++ }; +--- /dev/null ++++ b/Documentation/devicetree/bindings/clock/mux-clock.txt +@@ -0,0 +1,79 @@ ++Binding for simple mux clock. ++ ++This binding uses the common clock binding[1]. It assumes a ++register-mapped multiplexer with multiple input clock signals or ++parents, one of which can be selected as output. This clock does not ++gate or adjust the parent rate via a divider or multiplier. ++ ++By default the "clocks" property lists the parents in the same order ++as they are programmed into the regster. E.g: ++ ++ clocks = <&foo_clock>, <&bar_clock>, <&baz_clock>; ++ ++results in programming the register as follows: ++ ++register value selected parent clock ++0 foo_clock ++1 bar_clock ++2 baz_clock ++ ++Some clock controller IPs do not allow a value of zero to be programmed ++into the register, instead indexing begins at 1. The optional property ++"index-starts-at-one" modified the scheme as follows: ++ ++register value selected clock parent ++1 foo_clock ++2 bar_clock ++3 baz_clock ++ ++Additionally an optional table of bit and parent pairs may be supplied ++like so: ++ ++ table = <&foo_clock 0x0>, <&bar_clock, 0x2>, <&baz_clock, 0x4>; ++ ++where the first value in the pair is the parent clock and the second ++value is the bitfield to be programmed into the register. ++ ++The binding must provide the register to control the mux and the mask ++for the corresponding control bits. Optionally the number of bits to ++shift that mask if necessary. If the shift value is missing it is the ++same as supplying a zero shift. ++ ++[1] Documentation/devicetree/bindings/clock/clock-bindings.txt ++ ++Required properties: ++- compatible : shall be "mux-clock". ++- #clock-cells : from common clock binding; shall be set to 0. ++- clocks : link phandles of parent clocks ++- reg : base address for register controlling adjustable mux ++- bit-mask : arbitrary bitmask for programming the adjustable mux ++ ++Optional properties: ++- clock-output-names : From common clock binding. ++- table : array of integer pairs defining parents & bitfield values ++- bit-shift : number of bits to shift the bit-mask, defaults to ++ (ffs(mask) - 1) if not present ++- index-starts-at-one : valid input select programming starts at 1, not ++ zero ++- hiword-mask : lower half of the register programs the mux, upper half ++ of the register indicates bits that were updated in the lower half ++ ++Examples: ++ clock: clock@4a008100 { ++ compatible = "mux-clock"; ++ #clock-cells = <0>; ++ clocks = <&clock_foo>, <&clock_bar>, <&clock_baz>; ++ reg = <0x4a008100 0x4> ++ mask = <0x3>; ++ index-starts-at-one; ++ }; ++ ++ clock: clock@4a008100 { ++ #clock-cells = <0>; ++ compatible = "mux-clock"; ++ clocks = <&clock_foo>, <&clock_bar>, <&clock_baz>; ++ reg = <0x4a008100 0x4>; ++ mask = <0x3>; ++ shift = <0>; ++ table = <&clock_foo 1>, <&clock_bar 2>, <&clock_baz 3>; ++ }; +--- /dev/null ++++ b/Documentation/devicetree/bindings/clock/ti/apll.txt +@@ -0,0 +1,33 @@ ++Binding for Texas Instruments APLL clock. ++ ++This binding uses the common clock binding[1]. It assumes a ++register-mapped APLL with usually two selectable input clocks ++(reference clock and bypass clock), with analog phase locked ++loop logic for multiplying the input clock to a desired output ++clock. This clock also typically supports different operation ++modes (locked, low power stop etc.) APLL mostly behaves like ++a subtype of a DPLL [2], although a simplified one at that. ++ ++[1] Documentation/devicetree/bindings/clock/clock-bindings.txt ++[2] Documentation/devicetree/bindings/clock/ti/dpll.txt ++ ++Required properties: ++- compatible : shall be "ti,dra7-apll-clock" ++- #clock-cells : from common clock binding; shall be set to 0. ++- clocks : link phandles of parent clocks (clk-ref and clk-bypass) ++- reg : address and length of the register set for controlling the APLL. ++ It contains the information of registers in the same order as described by ++ reg-names. ++- reg-names: array of the register names for controlling the device, sorted ++ in the same order as the reg property. ++ "control" - contains the control register base address ++ "idlest" - contains the idlest register base address ++ ++Examples: ++ apll_pcie_ck: apll_pcie_ck@4a008200 { ++ #clock-cells = <0>; ++ clocks = <&apll_pcie_in_clk_mux>, <&dpll_pcie_ref_ck>; ++ reg = <0x4a00821c 0x4>, <0x4a008220 0x4>; ++ reg-names = "control", "idlest"; ++ compatible = "ti,dra7-apll-clock"; ++ }; +--- /dev/null ++++ b/Documentation/devicetree/bindings/clock/ti/autoidle.txt +@@ -0,0 +1,48 @@ ++Binding for Texas Instruments autoidling clock. ++ ++This binding uses the common clock binding[1]. Autoidle clocks ++are inherited clocks from basic divider-clock [2] or ++fixed-factor-clock [3] and just add autoidle support on top of ++this. Autoidle is an OMAP clock feature, which allows the clock ++to gate autonomously by hardware when they are no longer needed. ++The autoidle feature must be enabled manually for these clocks. ++Otherwise the clocks behave exactly as their base clock type. ++ ++[1] Documentation/devicetree/bindings/clock/clock-bindings.txt ++[2] Documentation/devicetree/bindings/clock/divider-clock.txt ++[3] Documentation/devicetree/bindings/clock/fixed-factor-clock.txt ++ ++Required properties: ++- compatible : shall be one of: ++ "ti,divider-clock", ++ "ti,fixed-factor-clock" ++- ti,autoidle-shift : bit shift of the autoidle enable bit for the clock ++- reg : base address for the control register of this clock ++ ++Optional properties: ++- ti,autoidle-low : autoidle is enabled by setting the bit to 0 ++ ++Other properties as per the base clock type. ++ ++Examples: ++ dpll_abe_m2x2_ck: dpll_abe_m2x2_ck@4a0051f0 { ++ #clock-cells = <0>; ++ compatible = "ti,divider-clock"; ++ clocks = <&dpll_abe_x2_ck>; ++ ti,autoidle-shift = <8>; ++ reg = <0x4a0051f0 0x4>; ++ bit-mask = <0x1f>; ++ index-starts-at-one; ++ ti,autoidle-low; ++ }; ++ ++ dpll_usb_clkdcoldo_ck: dpll_usb_clkdcoldo_ck@4a0081b4 { ++ #clock-cells = <0>; ++ compatible = "ti,fixed-factor-clock"; ++ clocks = <&dpll_usb_ck>; ++ ti,autoidle-shift = <8>; ++ clock-div = <1>; ++ reg = <0x4a0081b4 0x4>; ++ clock-mult = <1>; ++ ti,autoidle-low; ++ }; +--- /dev/null ++++ b/Documentation/devicetree/bindings/clock/ti/clockdomain.txt +@@ -0,0 +1,19 @@ ++Binding for Texas Instruments clockdomain. ++ ++This binding uses the common clock binding[1]. Every clock on ++TI SoC belongs to one clockdomain, but software only needs this ++information for specific clocks which require their parent ++clockdomain to be controlled when the clock is enabled/disabled. ++ ++[1] Documentation/devicetree/bindings/clock/clock-bindings.txt ++ ++Required properties: ++- compatible : shall be "ti,clockdomain" ++- #clock-cells : from common clock binding; shall be set to 0. ++- clocks : link phandles of clocks within this domain ++ ++Examples: ++ dss_clkdm: dss_clkdm { ++ compatible = "ti,clockdomain"; ++ clocks = <&dss1_alwon_fck_3430es2>, <&dss_ick_3430es2>; ++ }; +--- /dev/null ++++ b/Documentation/devicetree/bindings/clock/ti/dpll.txt +@@ -0,0 +1,68 @@ ++Binding for Texas Instruments DPLL clock. ++ ++This binding uses the common clock binding[1]. It assumes a ++register-mapped DPLL with usually two selectable input clocks ++(reference clock and bypass clock), with digital phase locked ++loop logic for multiplying the input clock to a desired output ++clock. This clock also typically supports different operation ++modes (locked, low power stop etc.) This binding has several ++sub-types, which effectively result in slightly different setup ++for the actual DPLL clock. ++ ++[1] Documentation/devicetree/bindings/clock/clock-bindings.txt ++ ++Required properties: ++- compatible : shall be one of: ++ "ti,omap4-dpll-x2-clock", ++ "ti,omap3-dpll-clock", ++ "ti,omap3-dpll-core-clock", ++ "ti,omap3-dpll-per-clock", ++ "ti,omap3-dpll-per-j-type-clock", ++ "ti,omap4-dpll-clock", ++ "ti,omap4-dpll-core-clock", ++ "ti,omap4-dpll-m4xen-clock", ++ "ti,omap4-dpll-j-type-clock", ++ "ti,omap4-dpll-no-gate-clock", ++ "ti,omap4-dpll-no-gate-j-type-clock", ++ ++- #clock-cells : from common clock binding; shall be set to 0. ++- clocks : link phandles of parent clocks, first entry lists reference clock ++ and second entry bypass clock ++- reg : address and length of the register set for controlling the DPLL. ++ It contains the information of registers in the same order as described by ++ reg-names. ++- reg-names : array of the register names for controlling the device, sorted ++ in the same order as the reg property. ++ "control" - contains the control register base address ++ "idlest" - contains the idle status register base address ++ "autoidle" - contains the autoidle register base address ++ "mult-div1" - contains the multiplier / divider register base address ++ ++Optional properties: ++- ti,modes : available modes for the DPLL, bitmask of: ++ 0x02 - DPLL supports low power stop mode ++ 0x20 - DPLL can be put to low power bypass mode ++ 0x80 - DPLL can be put to lock mode (running) ++ Other values currently unsupported. ++- ti,clkdm-name : clockdomain name for the DPLL ++ ++Examples: ++ dpll_core_ck: dpll_core_ck@44e00490 { ++ #clock-cells = <0>; ++ compatible = "ti,omap4-dpll-core-clock"; ++ clocks = <&sys_clkin_ck>, <&sys_clkin_ck>; ++ reg = <0x44e00490 0x4>, <0x44e0045c 0x4>, <0x0 0x4>, ++ <0x44e00468 0x4>; ++ reg-names = "control", "idlest", "autoidle", "mult-div1"; ++ }; ++ ++ dpll2_ck: dpll2_ck@48004004 { ++ #clock-cells = <0>; ++ compatible = "ti,omap3-dpll-clock"; ++ clocks = <&sys_ck>, <&dpll2_fck>; ++ ti,modes = <0xa2>; ++ reg = <0x48004004 0x4>, <0x48004024 0x4>, <0x48004034 0x4>, ++ <0x48004040 0x4>; ++ reg-names = "control", "idlest", "autoidle", "mult-div1"; ++ ti,clkdm-name = "dpll2_clkdm"; ++ }; +--- /dev/null ++++ b/Documentation/devicetree/bindings/clock/ti/gate.txt +@@ -0,0 +1,73 @@ ++Binding for Texas Instruments gate clock. ++ ++This binding uses the common clock binding[1]. This clock is ++quite much similar to the basic gate-clock [2], however, ++it supports a number of additional features. If no register ++is provided for this clock, the code assumes that a clockdomain ++will be controlled instead and the corresponding hw-ops for ++that is used. ++ ++[1] Documentation/devicetree/bindings/clock/clock-bindings.txt ++[2] Documentation/devicetree/bindings/clock/gate-clock.txt ++[3] Documentation/devicetree/bindings/clock/ti/clockdomain.txt ++ ++Required properties: ++- compatible : shall be one of: ++ "ti,gate-clock" - basic gate clock ++ "ti,dss-gate-clock" - gate clock with DSS specific hardware handling ++ "ti,am35xx-gate-clock" - gate clock with AM35xx specific hardware handling ++ "ti,clkdm-gate-clock" - clockdomain gate clock, which derives its functional ++ clock directly from a clockdomain, see [3] how ++ to map clockdomains properly ++ "ti,hsdiv-gate-clock" - gate clock with OMAP36xx specific hardware handling, ++ required for a hardware errata ++- #clock-cells : from common clock binding; shall be set to 0 ++- clocks : link to phandle of parent clock ++- reg : base address for register controlling adjustable gate, not needed for ++ ti,clkdm-gate-clock type ++- ti,enable-bit : bit shift for programming the clock gate, not needed for ++ ti,clkdm-gate-clock type ++ ++Optional properties: ++- ti,set-bit-to-disable : inverts default gate programming. Setting the bit ++ gates the clock and clearing the bit ungates the clock. ++ ++Examples: ++ mmchs2_fck: mmchs2_fck@48004a00 { ++ #clock-cells = <0>; ++ compatible = "ti,gate-clock"; ++ clocks = <&core_96m_fck>; ++ reg = <0x48004a00 0x4>; ++ ti,enable-bit = <25>; ++ }; ++ ++ dss1_alwon_fck_3430es2: dss1_alwon_fck_3430es2@48004e00 { ++ #clock-cells = <0>; ++ compatible = "ti,dss-gate-clock"; ++ clocks = <&dpll4_m4x2_ck>; ++ reg = <0x48004e00 0x4>; ++ ti,enable-bit = <0>; ++ }; ++ ++ emac_ick: emac_ick@4800259c { ++ #clock-cells = <0>; ++ compatible = "ti,am35xx-gate-clock"; ++ clocks = <&ipss_ick>; ++ reg = <0x4800259c 0x4>; ++ ti,enable-bit = <1>; ++ }; ++ ++ emu_src_ck: emu_src_ck { ++ #clock-cells = <0>; ++ compatible = "ti,clkdm-gate-clock"; ++ clocks = <&emu_src_mux_ck>; ++ }; ++ ++ dpll4_m2x2_ck: dpll4_m2x2_ck@48004d00 { ++ #clock-cells = <0>; ++ compatible = "ti,hsdiv-gate-clock"; ++ clocks = <&dpll4_m2x2_mul_ck>; ++ ti,enable-bit = <0x1b>; ++ reg = <0x48004d00 0x4>; ++ ti,set-bit-to-disable; ++ }; +--- /dev/null ++++ b/Documentation/devicetree/bindings/clock/ti/interface.txt +@@ -0,0 +1,53 @@ ++Binding for Texas Instruments interface clock. ++ ++This binding uses the common clock binding[1]. This clock is ++quite much similar to the basic gate-clock [2], however, ++it supports a number of additional features, including ++companion clock finding (match corresponding functional gate ++clock) and hardware autoidle enable / disable. ++ ++[1] Documentation/devicetree/bindings/clock/clock-bindings.txt ++[2] Documentation/devicetree/bindings/clock/gate-clock.txt ++ ++Required properties: ++- compatible : shall be one of: ++ "ti,omap3-interface-clock" - basic OMAP3 interface clock ++ "ti,omap3-no-wait-interface-clock" - interface clock which has no hardware ++ capability for waiting clock to be ready ++ "ti,omap3-hsotgusb-interface-clock" - interface clock with USB specific HW ++ handling ++ "ti,omap3-dss-interface-clock" - interface clock with DSS specific HW handling ++ "ti,omap3-ssi-interface-clock" - interface clock with SSI specific HW handling ++ "ti,am35xx-interface-clock" - interface clock with AM35xx specific HW handling ++- #clock-cells : from common clock binding; shall be set to 0 ++- clocks : link to phandle of parent clock ++- reg : base address for the control register ++ ++Optional properties: ++- ti,enable-bit : bit shift for the bit enabling/disabling the clock ++ (default 0) ++ ++Examples: ++ aes1_ick: aes1_ick@48004a14 { ++ #clock-cells = <0>; ++ compatible = "ti,omap3-interface-clock"; ++ clocks = <&security_l4_ick2>; ++ reg = <0x48004a14 0x4>; ++ ti,enable-bit = <3>; ++ }; ++ ++ cam_ick: cam_ick@48004f10 { ++ #clock-cells = <0>; ++ compatible = "ti,omap3-no-wait-interface-clock"; ++ clocks = <&l4_ick>; ++ reg = <0x48004f10 0x4>; ++ ti,enable-bit = <0>; ++ }; ++ ++ ssi_ick_3430es2: ssi_ick_3430es2@48004a10 { ++ #clock-cells = <0>; ++ compatible = "ti,omap3-ssi-interface-clock"; ++ clocks = <&ssi_l4_ick>; ++ reg = <0x48004a10 0x4>; ++ ti,enable-bit = <0>; ++ }; +--- a/Documentation/devicetree/bindings/dma/atmel-dma.txt ++++ b/Documentation/devicetree/bindings/dma/atmel-dma.txt +@@ -28,7 +28,7 @@ The three cells in order are: + dependent: + - bit 7-0: peripheral identifier for the hardware handshaking interface. The + identifier can be different for tx and rx. +- - bit 11-8: FIFO configuration. 0 for half FIFO, 1 for ALAP, 1 for ASAP. ++ - bit 11-8: FIFO configuration. 0 for half FIFO, 1 for ALAP, 2 for ASAP. + + Example: + +--- /dev/null ++++ b/Documentation/devicetree/bindings/extcon/extcon-gpio-usbvid.txt +@@ -0,0 +1,20 @@ ++EXTCON FOR USB VIA GPIO ++ ++Required Properties: ++ - compatible : Should be "ti,gpio-usb-vid" for USB VBUS-ID detector ++ using gpios or "ti,gpio-usb-id" for USB ID pin detector ++ - gpios : phandle and args ID pin gpio and VBUS gpio. ++ The first gpio used for ID pin detection ++ and the second used for VBUS detection. ++ ID pin gpio is mandatory and VBUS is optional ++ depending on implementation. ++ ++Please refer to ../gpio/gpio.txt for details of the common GPIO bindings ++ ++Example: ++ ++ gpio_usbvid_extcon1 { ++ compatible = "ti,gpio-usb-vid"; ++ gpios = <&gpio1 1 0>, ++ <&gpio2 2 0>; ++ }; +--- a/Documentation/devicetree/bindings/extcon/extcon-palmas.txt ++++ b/Documentation/devicetree/bindings/extcon/extcon-palmas.txt +@@ -2,7 +2,8 @@ EXTCON FOR PALMAS/TWL CHIPS + + PALMAS USB COMPARATOR + Required Properties: +- - compatible : Should be "ti,palmas-usb" or "ti,twl6035-usb" ++ - compatible : Should be "ti,palmas-usb-vid". "ti,twl6035-usb" and ++ "ti,palmas-usb" is deprecated and is kept for backward compatibility. + + Optional Properties: + - ti,wakeup : To enable the wakeup comparator in probe +--- /dev/null ++++ b/Documentation/devicetree/bindings/gpio/gpio-pcf857x.txt +@@ -0,0 +1,71 @@ ++* PCF857x-compatible I/O expanders ++ ++The PCF857x-compatible chips have "quasi-bidirectional" I/O lines that can be ++driven high by a pull-up current source or driven low to ground. This combines ++the direction and output level into a single bit per line, which can't be read ++back. We can't actually know at initialization time whether a line is configured ++(a) as output and driving the signal low/high, or (b) as input and reporting a ++low/high value, without knowing the last value written since the chip came out ++of reset (if any). The only reliable solution for setting up line direction is ++thus to do it explicitly. ++ ++Required Properties: ++ ++ - compatible: should be one of the following. ++ - "maxim,max7328": For the Maxim MAX7378 ++ - "maxim,max7329": For the Maxim MAX7329 ++ - "nxp,pca8574": For the NXP PCA8574 ++ - "nxp,pca8575": For the NXP PCA8575 ++ - "nxp,pca9670": For the NXP PCA9670 ++ - "nxp,pca9671": For the NXP PCA9671 ++ - "nxp,pca9672": For the NXP PCA9672 ++ - "nxp,pca9673": For the NXP PCA9673 ++ - "nxp,pca9674": For the NXP PCA9674 ++ - "nxp,pca9675": For the NXP PCA9675 ++ - "nxp,pcf8574": For the NXP PCF8574 ++ - "nxp,pcf8574a": For the NXP PCF8574A ++ - "nxp,pcf8575": For the NXP PCF8575 ++ - "ti,tca9554": For the TI TCA9554 ++ ++ - reg: I2C slave address. ++ ++ - gpio-controller: Marks the device node as a gpio controller. ++ - #gpio-cells: Should be 2. The first cell is the GPIO number and the second ++ cell specifies GPIO flags, as defined in <dt-bindings/gpio/gpio.h>. Only the ++ GPIO_ACTIVE_HIGH and GPIO_ACTIVE_LOW flags are supported. ++ ++Optional Properties: ++ ++ - lines-initial-states: Bitmask that specifies the initial state of each ++ line. When a bit is set to zero, the corresponding line will be initialized to ++ the input (pulled-up) state. When the bit is set to one, the line will be ++ initialized the the low-level output state. If the property is not specified ++ all lines will be initialized to the input state. ++ ++ The I/O expander can detect input state changes, and thus optionally act as ++ an interrupt controller. When the expander interrupt line is connected all the ++ following properties must be set. For more information please see the ++ interrupt controller device tree bindings documentation available at ++ Documentation/devicetree/bindings/interrupt-controller/interrupts.txt. ++ ++ - interrupt-controller: Identifies the node as an interrupt controller. ++ - #interrupt-cells: Number of cells to encode an interrupt source, shall be 2. ++ - interrupt-parent: phandle of the parent interrupt controller. ++ - interrupts: Interrupt specifier for the controllers interrupt. ++ ++ ++Please refer to gpio.txt in this directory for details of the common GPIO ++bindings used by client devices. ++ ++Example: PCF8575 I/O expander node ++ ++ pcf8575: gpio@20 { ++ compatible = "nxp,pcf8575"; ++ reg = <0x20>; ++ interrupt-parent = <&irqpin2>; ++ interrupts = <3 0>; ++ gpio-controller; ++ #gpio-cells = <2>; ++ interrupt-controller; ++ #interrupt-cells = <2>; ++ }; +--- /dev/null ++++ b/Documentation/devicetree/bindings/hwrng/omap_rng.txt +@@ -0,0 +1,22 @@ ++OMAP SoC HWRNG Module ++ ++Required properties: ++ ++- compatible : Should contain entries for this and backward compatible ++ RNG versions: ++ - "ti,omap2-rng" for OMAP2. ++ - "ti,omap4-rng" for OMAP4, OMAP5 and AM33XX. ++ Note that these two versions are incompatible. ++- ti,hwmods: Name of the hwmod associated with the RNG module ++- reg : Offset and length of the register set for the module ++- interrupts : the interrupt number for the RNG module. ++ Only used for "ti,omap4-rng". ++ ++Example: ++/* AM335x */ ++rng: rng@48310000 { ++ compatible = "ti,omap4-rng"; ++ ti,hwmods = "rng"; ++ reg = <0x48310000 0x2000>; ++ interrupts = <111>; ++}; +--- /dev/null ++++ b/Documentation/devicetree/bindings/input/touchscreen/atmel_mxt_ts.txt +@@ -0,0 +1,108 @@ ++Atmel MaxTouch Touchscreen ++-------------------------- ++Required properties: ++ - compatible: "atmel,mXT244" or "atmel,qt602240_ts" ++ or "atmel,atmel_mxt_ts" ++ - reg: I2C address of the chip ++ - interrupts: interrupt signal to which the chip is connected ++ - atmel,x-line: Number of x lines the touch object occupies in pixels ++ - atmel,y-line: Number of y lines the touch object occupies in pixels ++ - atmel,x-size: Horizontal resolution of touchscreen in pixels ++ - atmel,y-size: Vertical resolution of touchscreen in pixels ++ - atmel,blen: Sets the gain of the analog circuit in front of ADC ++ Gain setting depends on package type. Range: 0-3 ++ - atmel,threshold: Channel detection threshold value. Range: 0-255 ++ Typical: 30-80. Lower the threshold, higher the ++ sensitivity ++ - atmel,voltage: Nominal AVdd in uV for analog circuitry, greater than ++ or less than base voltage of 2.7V, used for optimizing ++ capacitive sensing. For example, if you want to ++ program an optimum voltage of 2.8V in your design, ++ specify 2800000 for this parameter ++ - atmel,orientation: touchscreen orientation, must be one of following, ++ as defined inside include/linux/i2c/atmel_mxt_ts.h ++ - 0: MXT_NORMAL - normal ++ - 1: MXT_DIAGONAL - diagonal ++ - 2: MXT_HORIZONTAL_FLIP - horizonally flipped ++ - 3: MXT_ROTATED_90_COUNTER - rotated by 90 degrees ++ counter-clockwise ++ - 4: MXT_VERTICAL_FLIP - vertically flipped ++ - 5: MXT_ROTATED_90 - rotated by 90 degress clockwise ++ - 6: MXT_ROTATED_180 - rotated by 180 degrees ++ - 7: MXT_DIAGONAL_COUNTER - diagonal counter ++ ++Optional properties: ++ - atmel,config: list of 8-bit register values for controller objects ++ in the following order. Number of objects and values depends on the ++ particular model of Atmel touch screen you are using. Please check ++ with your Atmel representative for helping you tune these values ++ GEN_COMMAND, GEN_POWER, GEN_ACQUIRE, TOUCH_MULTI ++ TOUCH_KEYARRAY, MXT244_COMMSCONFIG_T18, SPT_GPIOPWM, PROCI_GRIPFACE, ++ PROCG_NOISE, TOUCH_PROXIMITY, PROCI_ONETOUCH, SPT_SELFTEST, ++ PROCI_TWOTOUCH, SPT_CTECONFIG ++ Note: These register values can be specified here according to ++ the specific controller and platform configuration desired. The ++ driver does not configure these registers by default and leaves it ++ to the platform dts file to supply them ++ ++Example: ++ ++ &i2c1 { ++ mXT244:mXT244@4a { ++ reg = <0x4a>; ++ }; ++ }; ++ ++ &mXT244 { ++ compatible = "atmel,mXT244"; ++ interrupts = <0 119 0x4>; ++ ++ atmel,config = < ++ /* MXT244_GEN_COMMAND(6) */ ++ 0x00 0x00 0x00 0x00 0x00 0x00 ++ /* MXT244_GEN_POWER(7) */ ++ 0x20 0xff 0x32 ++ /* MXT244_GEN_ACQUIRE(8) */ ++ 0x0a 0x00 0x05 0x00 0x00 0x00 0x09 0x23 ++ /* MXT244_TOUCH_MULTI(9) */ ++ 0x00 0x00 0x00 0x13 0x0b 0x00 0x00 0x00 0x02 0x00 ++ 0x00 0x01 0x01 0x0e 0x0a 0x0a 0x0a 0x0a 0x00 0x00 ++ 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 ++ 0x00 ++ /* MXT244_TOUCH_KEYARRAY(15) */ ++ 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 ++ 0x00 ++ /* MXT244_COMMSCONFIG_T18(2) */ ++ 0x00 0x00 ++ /* MXT244_SPT_GPIOPWM(19) */ ++ 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 ++ 0x00 0x00 0x00 0x00 0x00 0x00 ++ /* MXT244_PROCI_GRIPFACE(20) */ ++ 0x07 0x00 0x00 0x00 0x00 0x00 0x00 0x50 0x28 0x04 ++ 0x0f 0x0a ++ /* MXT244_PROCG_NOISE(22) */ ++ 0x05 0x00 0x00 0x00 0x00 0x00 0x00 0x03 0x23 0x00 ++ 0x00 0x05 0x0f 0x19 0x23 0x2d 0x03 ++ /* MXT244_TOUCH_PROXIMITY(23) */ ++ 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 ++ 0x00 0x00 0x00 0x00 0x00 ++ /* MXT244_PROCI_ONETOUCH(24) */ ++ 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 ++ 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 ++ /* MXT244_SPT_SELFTEST(25) */ ++ 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 ++ 0x00 0x00 0x00 0x00 ++ /* MXT244_PROCI_TWOTOUCH(27) */ ++ 0x00 0x00 0x00 0x00 0x00 0x00 0x00 ++ /* MXT244_SPT_CTECONFIG(28) */ ++ 0x00 0x00 0x02 0x08 0x10 0x00 >; ++ ++ atmel,x_line = <18>; ++ atmel,y_line = <12>; ++ atmel,x_size = <800>; ++ atmel,y_size = <480>; ++ atmel,blen = <0x01>; ++ atmel,threshold = <30>; ++ atmel,voltage = <2800000>; ++ atmel,orient = <0x4>; ++ }; +--- /dev/null ++++ b/Documentation/devicetree/bindings/input/touchscreen/pixcir_i2c_ts.txt +@@ -0,0 +1,26 @@ ++* Pixcir I2C touchscreen controllers ++ ++Required properties: ++- compatible: must be "pixcir,pixcir_ts" or "pixcir,pixcir_tangoc" ++- reg: I2C address of the chip ++- interrupts: interrupt to which the chip is connected ++- attb-gpio: GPIO connected to the ATTB line of the chip ++- x-size: horizontal resolution of touchscreen ++- y-size: vertical resolution of touchscreen ++ ++Example: ++ ++ i2c@00000000 { ++ /* ... */ ++ ++ pixcir_ts@5c { ++ compatible = "pixcir,pixcir_ts"; ++ reg = <0x5c>; ++ interrupts = <2 0>; ++ attb-gpio = <&gpf 2 0 2>; ++ x-size = <800>; ++ y-size = <600>; ++ }; ++ ++ /* ... */ ++ }; +--- a/Documentation/devicetree/bindings/input/touchscreen/ti-tsc-adc.txt ++++ b/Documentation/devicetree/bindings/input/touchscreen/ti-tsc-adc.txt +@@ -6,7 +6,7 @@ Required properties: + ti,wires: Wires refer to application modes i.e. 4/5/8 wire touchscreen + support on the platform. + ti,x-plate-resistance: X plate resistance +- ti,coordiante-readouts: The sequencer supports a total of 16 ++ ti,coordinate-readouts: The sequencer supports a total of 16 + programmable steps each step is used to + read a single coordinate. A single + readout is enough but multiple reads can +--- /dev/null ++++ b/Documentation/devicetree/bindings/mailbox/omap-mailbox.txt +@@ -0,0 +1,76 @@ ++OMAP2+ Mailbox Driver ++===================== ++ ++The OMAP mailbox hardware facilitates communication between different ++processors using a queued mailbox interrupt mechanism. The IP block is ++external to the various processor subsystems and is connected on an ++interconnect bus. The communication is achieved through a set of ++registers for message storage and interrupt configuration registers. ++ ++Each mailbox IP block has a certain number of h/w fifo queues and output ++interrupt lines. An output interrupt line is routed to a specific interrupt ++controller on a processor subsystem, and there can be more than one line ++going to a specific processor's interrupt controller. The interrupt line ++connections are fixed for an instance and are dictated by the IP integration ++into the SoC. Each interrupt line is programmable through a set of interrupt ++configuration registers, and have a rx and tx interrupt source per h/w fifo. ++Communication between different processors is achieved through the appropriate ++programming of the rx and tx interrupt sources on the appropriate interrupt ++lines. ++ ++The number of h/w fifo queues and interrupt lines dictate the usable registers. ++All the current OMAP SoCs except for the newest DRA7xx SoC has a single IP ++instance. DRA7xx has multiple instances with different number of h/w fifo ++queues and interrupt lines between different instances. The interrupt lines ++can also be routed to different processor sub-systems on DRA7xx as they are ++routed through the Crossbar, a kind of interrupt router/multiplexer. ++ ++The above two varying SoC IP integration parameters are defined specifically ++through the "ti,mbox-num-users" and "ti,mbox-num-fifos" device-tree properties. ++These are defined in the DT nodes since these design parameters can vary between ++one instance to another in an SoC (eg: DRA7xx) even though the base IP design ++is identical. ++ ++Required properties: ++-------------------- ++- compatible: Should be one of the following, ++ "ti,omap2-mailbox" for ++ OMAP2420, OMAP2430, OMAP3430, OMAP3630 SoCs ++ "ti,omap4-mailbox" for ++ OMAP44xx, OMAP54xx, AM33xx, AM43xx, DRA7xx SoCs ++- reg: Contains the mailbox register address range (base address ++ and length) ++- interrupts: Contains the interrupt information for the mailbox ++ device. The format is dependent on which interrupt ++ controller the OMAP device uses ++- ti,hwmods: Name of the hwmod associated with the mailbox ++- ti,mbox-num-users: Number of targets (processor devices) that the mailbox device ++ can interrupt ++- ti,mbox-num-fifos: Number of h/w fifos within the mailbox device ++- ti,mbox-names: Array of the names of the mailboxes ++- ti,mbox-data: Mailbox descriptor data private to each mailbox. The 4 ++ cells represent the following data, ++ Cell #1 (tx_id) - mailbox fifo id used for ++ transmitting messages ++ Cell #2 (rx_id) - mailbox fifo id on which messages ++ are received ++ Cell #3 (irq_id) - irq identifier index number to use ++ from the interrupts data ++ Cell #4 (usr_id) - mailbox user id for identifying the ++ interrupt into the MPU interrupt ++ controller. ++ ++Example: ++-------- ++ ++/* OMAP4 */ ++mailbox: mailbox@4a0f4000 { ++ compatible = "ti,omap4-mailbox"; ++ reg = <0x4a0f4000 0x200>; ++ interrupts = <GIC_SPI 47 IRQ_TYPE_LEVEL_HIGH>; ++ ti,hwmods = "mailbox"; ++ ti,mbox-num-users = <3>; ++ ti,mbox-num-fifos = <8>; ++ ti,mbox-names = "mbox-ipu", "mbox-dsp"; ++ ti,mbox-data = <0 1 0 0>, <3 2 0 0>; ++}; +--- /dev/null ++++ b/Documentation/devicetree/bindings/mfd/tps65218.txt +@@ -0,0 +1,27 @@ ++The TPS65218 Integrated Power Management Chips. ++These chips are connected to an i2c bus. ++ ++Required properties: ++- compatible : Must be "ti,tps65218"; ++- interrupts : This i2c device has an IRQ line connected to the main SoC ++- interrupt-controller : Since the tps65218 support several interrupts ++ internally, it is considered as an interrupt controller cascaded to the SoC. ++- #interrupt-cells = <2>; ++- interrupt-parent : The parent interrupt controller. ++ ++Optional node: ++- Child nodes contain in the tps65218. ++ It supports a number of features. ++ The children nodes will thus depend of the capability of the variant. ++ ++Example: ++/* ++ * Integrated Power Management Chip ++ */ ++tps@24 { ++ compatible = "ti,tps65218"; ++ reg = <0x24>; ++ interrupt-controller; ++ #interrupt-cells = <2>; ++ interrupt-parent = <&gic>; ++}; +--- a/Documentation/devicetree/bindings/mfd/twl6040.txt ++++ b/Documentation/devicetree/bindings/mfd/twl6040.txt +@@ -19,6 +19,8 @@ Required properties: + + Optional properties, nodes: + - enable-active-high: To power on the twl6040 during boot. ++- clocks: phandle to the clk32k clock provider ++- clock-names: Must be "clk32k" + + Vibra functionality + Required properties: +--- a/Documentation/devicetree/bindings/mmc/ti-omap-hsmmc.txt ++++ b/Documentation/devicetree/bindings/mmc/ti-omap-hsmmc.txt +@@ -20,8 +20,29 @@ ti,dual-volt: boolean, supports dual vol + ti,non-removable: non-removable slot (like eMMC) + ti,needs-special-reset: Requires a special softreset sequence + ti,needs-special-hs-handling: HSMMC IP needs special setting for handling High Speed ++dmas: List of DMA specifiers with the controller specific format ++as described in the generic DMA client binding. A tx and rx ++specifier is required. ++dma-names: List of DMA request names. These strings correspond ++1:1 with the DMA specifiers listed in dmas. The string naming is ++to be "rx" and "tx" for RX and TX DMA requests, respectively. ++ ++Examples: ++ ++[hwmod populated DMA resources] ++ ++ mmc1: mmc@0x4809c000 { ++ compatible = "ti,omap4-hsmmc"; ++ reg = <0x4809c000 0x400>; ++ ti,hwmods = "mmc1"; ++ ti,dual-volt; ++ bus-width = <4>; ++ vmmc-supply = <&vmmc>; /* phandle to regulator node */ ++ ti,non-removable; ++ }; ++ ++[generic DMA request binding] + +-Example: + mmc1: mmc@0x4809c000 { + compatible = "ti,omap4-hsmmc"; + reg = <0x4809c000 0x400>; +@@ -30,4 +51,7 @@ Example: + bus-width = <4>; + vmmc-supply = <&vmmc>; /* phandle to regulator node */ + ti,non-removable; ++ dmas = <&edma 24 ++ &edma 25>; ++ dma-names = "tx", "rx"; + }; +--- a/Documentation/devicetree/bindings/mtd/gpmc-nand.txt ++++ b/Documentation/devicetree/bindings/mtd/gpmc-nand.txt +@@ -21,13 +21,11 @@ Optional properties: + is wired that way. If not specified, a bus + width of 8 is assumed. + +- - ti,nand-ecc-opt: A string setting the ECC layout to use. One of: +- +- "sw" Software method (default) +- "hw" Hardware method +- "hw-romcode" gpmc hamming mode method & romcode layout ++ - ti,nand-ecc-scheme: A string setting the ECC layout to use. One of: ++ "ham1" 1-bit Hamming ecc code + "bch4" 4-bit BCH ecc code + "bch8" 8-bit BCH ecc code ++ "bch16" 16-bit BCH ecc code + + - ti,nand-xfer-type: A string setting the data transfer type. One of: + +@@ -36,8 +34,11 @@ Optional properties: + "prefetch-dma" Prefetch enabled sDMA mode + "prefetch-irq" Prefetch enabled irq mode + +- - elm_id: Specifies elm device node. This is required to support BCH +- error correction using ELM module. ++ - ti,elm-id: Specifies pHandle of the ELM devicetree node. ++ ELM is an on-chip hardware engine on TI SoC which is used for ++ locating ECC errors for BCHx algorithms. SoC devices which have ++ ELM hardware engines should specify this device node in .dtsi ++ Using ELM for ECC error correction frees some CPU cycles. + + For inline partiton table parsing (optional): + +--- /dev/null ++++ b/Documentation/devicetree/bindings/net/cpsw-phy-sel.txt +@@ -0,0 +1,28 @@ ++TI CPSW Phy mode Selection Device Tree Bindings ++----------------------------------------------- ++ ++Required properties: ++- compatible : Should be "ti,am3352-cpsw-phy-sel" ++- reg : physical base address and size of the cpsw ++ registers map ++- reg-names : names of the register map given in "reg" node ++ ++Optional properties: ++-rmii-clock-ext : If present, the driver will configure the RMII ++ interface to external clock usage ++ ++Examples: ++ ++ phy_sel: cpsw-phy-sel@44e10650 { ++ compatible = "ti,am3352-cpsw-phy-sel"; ++ reg= <0x44e10650 0x4>; ++ reg-names = "gmii-sel"; ++ }; ++ ++(or) ++ phy_sel: cpsw-phy-sel@44e10650 { ++ compatible = "ti,am3352-cpsw-phy-sel"; ++ reg= <0x44e10650 0x4>; ++ reg-names = "gmii-sel"; ++ rmii-clock-ext; ++ }; +--- /dev/null ++++ b/Documentation/devicetree/bindings/net/smsc95xx.txt +@@ -0,0 +1,16 @@ ++* Smart Mixed-Signal Connectivity (SMSC) 95xx Controller ++ ++Required properties: ++None ++ ++Optional properties: ++- mac-address - Read the mac address that was stored by uBoot ++- local-address - Read the mac address that was stored by uBoot ++- address - Read the mac address that was stored by uBoot ++ ++Examples: ++ ++smsc0: smsc95xx@0 { ++ /* Filled in by U-Boot */ ++ mac-address = [ 00 00 00 00 00 00 ]; ++}; +--- /dev/null ++++ b/Documentation/devicetree/bindings/phy/omap-phy.txt +@@ -0,0 +1,78 @@ ++OMAP PHY: DT DOCUMENTATION FOR PHYs in OMAP PLATFORM ++ ++OMAP CONTROL PHY ++ ++Required properties: ++ - compatible: Should be one of ++ "ti,control-phy-otghs" - if it has otghs_control mailbox register as on OMAP4. ++ "ti,control-phy-usb2" - if it has Power down bit in control_dev_conf register ++ e.g. USB2_PHY on OMAP5. ++ "ti,control-phy-pipe3" - if it has DPLL and individual Rx & Tx power control ++ e.g. USB3 PHY and SATA PHY on OMAP5. ++ "ti,control-phy-dra7usb2" - if it has power down register like USB2 PHY on ++ DRA7 platform. ++ "ti,control-phy-am437usb2" - if it has power down register like USB2 PHY on ++ AM437 platform. ++ - reg : Address and length of the register set for the device. It contains ++ the address of "otghs_control" for control-phy-otghs or "power" register ++ for other types. ++ - reg-names: should be "otghs_control" control-phy-otghs and "power" for ++ other types. ++ ++omap_control_otghs: omap-control-phy@4a002300 { ++ compatible = "ti,control-phy-otghs"; ++ reg = <0x4a00233c 0x4>; ++ reg-names = "otghs_control"; ++}; ++ ++OMAP USB2 PHY ++ ++Required properties: ++ - compatible: Should be either of ++ * "ti,omap-usb2" for OMAP4,OMAP5,DRA7 ++ * "ti,am437x-usb2" for AM437x ++ - reg : Address and length of the register set for the device. ++ - #phy-cells: determine the number of cells that should be given in the ++ phandle while referencing this phy. ++ ++Optional properties: ++ - ctrl-module : phandle of the control module used by PHY driver to power on ++ the PHY. ++ ++This is usually a subnode of ocp2scp to which it is connected. ++ ++usb2phy@4a0ad080 { ++ compatible = "ti,omap-usb2"; ++ reg = <0x4a0ad080 0x58>; ++ ctrl-module = <&omap_control_usb>; ++ #phy-cells = <0>; ++}; ++ ++OMAP PIPE3 PHY ++ ++Required properties: ++ - compatible: Should be "ti,phy-pipe3-usb3" or "ti,phy-pipe3-sata" ++ - reg : Address and length of the register set for the device. ++ - reg-names: The names of the register addresses corresponding to the registers ++ filled in "reg". ++ - #phy-cells: determine the number of cells that should be given in the ++ phandle while referencing this phy. ++ - clocks: phandle to PHY clocks i.e. 32KHz wakup clock, 960MHz clock and lfps clock. ++ Use as per Documentation/devicetree/bindings/clock/clock-bindings.txt ++ - clock-names: should contain "wkupclk", "refclk1" and "refclk2" ++ ++Optional properties: ++ - ctrl-module : phandle of the control module used by PHY driver to power on ++ the PHY. ++ ++This is usually a subnode of ocp2scp to which it is connected. ++ ++usb3phy@4a084400 { ++ compatible = "ti,omap-usb3"; ++ reg = <0x4a084400 0x80>, ++ <0x4a084800 0x64>, ++ <0x4a084c00 0x40>; ++ reg-names = "phy_rx", "phy_tx", "pll_ctrl"; ++ ctrl-module = <&omap_control_usb>; ++ #phy-cells = <0>; ++}; +--- /dev/null ++++ b/Documentation/devicetree/bindings/phy/phy-bindings.txt +@@ -0,0 +1,66 @@ ++This document explains only the device tree data binding. For general ++information about PHY subsystem refer to Documentation/phy.txt ++ ++PHY device node ++=============== ++ ++Required Properties: ++#phy-cells: Number of cells in a PHY specifier; The meaning of all those ++ cells is defined by the binding for the phy node. The PHY ++ provider can use the values in cells to find the appropriate ++ PHY. ++ ++For example: ++ ++phys: phy { ++ compatible = "xxx"; ++ reg = <...>; ++ . ++ . ++ #phy-cells = <1>; ++ . ++ . ++}; ++ ++That node describes an IP block (PHY provider) that implements 2 different PHYs. ++In order to differentiate between these 2 PHYs, an additonal specifier should be ++given while trying to get a reference to it. ++ ++PHY user node ++============= ++ ++Required Properties: ++phys : the phandle for the PHY device (used by the PHY subsystem) ++phy-names : the names of the PHY corresponding to the PHYs present in the ++ *phys* phandle ++ ++Example 1: ++usb1: usb_otg_ss@xxx { ++ compatible = "xxx"; ++ reg = <xxx>; ++ . ++ . ++ phys = <&usb2_phy>, <&usb3_phy>; ++ phy-names = "usb2phy", "usb3phy"; ++ . ++ . ++}; ++ ++This node represents a controller that uses two PHYs, one for usb2 and one for ++usb3. ++ ++Example 2: ++usb2: usb_otg_ss@xxx { ++ compatible = "xxx"; ++ reg = <xxx>; ++ . ++ . ++ phys = <&phys 1>; ++ phy-names = "usbphy"; ++ . ++ . ++}; ++ ++This node represents a controller that uses one of the PHYs of the PHY provider ++device defined previously. Note that the phy handle has an additional specifier ++"1" to differentiate between the two PHYs. +--- /dev/null ++++ b/Documentation/devicetree/bindings/regulator/ti-avs-class0.txt +@@ -0,0 +1,66 @@ ++Texas Instrument SmartReflex AVS Class 0 Regulator ++ ++Required properties: ++- compatible: "ti,avsclass0" ++- reg: Should contain Efuse registers location and length ++- avs-supply: The supply for AVS block ++- efuse-settings: An array of 2-tuples items, and each item consists ++ of Voltage index and efuse offset(from reg) like: <voltage offset> ++ voltage: Voltage index in microvolts (also called nominal voltage) ++ offset: ofset in bytes from base provided in reg ++ NOTE: min_uV, max_uV are pickedup from this list ++ ++Optional properties: ++- voltage-tolerance: Specify the voltage tolerance in percentage ++- ti,avsclass0-microvolt-values: Boolean property indicating that the efuse ++ values are in microvolts ++ ++Example #1: single rails: ++soc.dtsi: ++avs_mpu: regulator-avs@0x40200000 { ++ compatible = "ti,avsclass0"; ++ reg = <0x40200000 0x20>; ++ efuse-settings = <975000 0 ++ 1075000 4 ++ 1200000 8>; ++}; ++ ++avs_core: regulator-avs@0x40300000 { ++ compatible = "ti,avsclass0"; ++ reg = <0x40300000 0x20>; ++ efuse-settings = <975000 0 ++ 1050000 4>; ++}; ++ ++board.dtsi: ++&avs_mpu { ++ avs-supply = <&vcc>; ++}; ++&avs_core { ++ avs-supply = <&smps2>; ++}; ++ ++Example #2: Ganged (combined) rails: ++soc.dtsi: ++avs_mpu: regulator-avs@0x40200000 { ++ compatible = "ti,avsclass0"; ++ reg = <0x40200000 0x20>; ++ efuse-settings = <975000 0 ++ 1075000 4 ++ 1200000 8>; ++}; ++ ++avs_core: regulator-avs@0x40300000 { ++ compatible = "ti,avsclass0"; ++ reg = <0x40300000 0x20>; ++ efuse-settings = <975000 0 ++ 1050000 4>; ++}; ++ ++board.dtsi: ++&avs_mpu { ++ avs-supply = <&smps3>; ++}; ++&avs_core { ++ avs-supply = <&smps3>; ++}; +--- /dev/null ++++ b/Documentation/devicetree/bindings/regulator/tps65218.txt +@@ -0,0 +1,22 @@ ++TPS65218 family of regulators ++ ++Required properties: ++For tps65218 regulators/LDOs ++- compatible: ++ - "ti,tps65218-dcdc1" for DCDC1 ++ - "ti,tps65218-dcdc2" for DCDC2 ++ - "ti,tps65218-dcdc3" for DCDC3 ++ - "ti,tps65218-dcdc4" for DCDC4 ++ - "ti,tps65218-dcdc5" for DCDC5 ++ - "ti,tps65218-dcdc6" for DCDC6 ++ - "ti,tps65218-ldo1" for LDO1 LDO ++ ++Optional properties: ++- Any optional property defined in bindings/regulator/regulator.txt ++ ++Example: ++ xyz: regulator@0 { ++ compatible = "ti,tps65218-dcdc1"; ++ regulator-min-microvolt = <1000000>; ++ regulator-max-microvolt = <3000000>; ++ }; +--- /dev/null ++++ b/Documentation/devicetree/bindings/sound/davinci-evm-audio.txt +@@ -0,0 +1,58 @@ ++* Texas Instruments SoC audio setups with TLV320AIC3X Codec ++ ++Required properties: ++- compatible : "ti,da830-evm-audio" : forDM365/DA8xx/OMAPL1x/AM33xx ++- ti,model : The user-visible name of this sound complex. ++- ti,audio-codec : The phandle of the TLV320AIC3x audio codec ++- ti,mcasp-controller : The phandle of the McASP controller ++- ti,codec-clock-rate : The Codec Clock rate (in Hz) applied to the Codec ++- ti,audio-routing : A list of the connections between audio components. ++ Each entry is a pair of strings, the first being the connection's sink, ++ the second being the connection's source. Valid names for sources and ++ sinks are the codec's pins, and the jacks on the board: ++ ++ TLV320AIC3X pins: ++ ++ * LLOUT ++ * RLOUT ++ * MONO_LOUT ++ * HPLOUT ++ * HPROUT ++ * HPLCOM ++ * HPRCOM ++ * MIC3L ++ * MIC3R ++ * LINE1L ++ * LINE2L ++ * LINE1R ++ * LINE2R ++ ++ Board connectors: ++ ++ * Headphone Jack ++ * Line Out ++ * Mic Jack ++ * Line In ++ ++ ++Example: ++ ++sound { ++ compatible = "ti,da830-evm-audio"; ++ ti,model = "DA830 EVM"; ++ ti,audio-codec = <&tlv320aic3x>; ++ ti,mcasp-controller = <&mcasp1>; ++ ti,codec-clock-rate = <12000000>; ++ ti,audio-routing = ++ "Headphone Jack", "HPLOUT", ++ "Headphone Jack", "HPROUT", ++ "Line Out", "LLOUT", ++ "Line Out", "RLOUT", ++ "MIC3L", "Mic Bias 2V", ++ "MIC3R", "Mic Bias 2V", ++ "Mic Bias 2V", "Mic Jack", ++ "LINE1L", "Line In", ++ "LINE2L", "Line In", ++ "LINE1R", "Line In", ++ "LINE2R", "Line In"; ++}; +--- a/Documentation/devicetree/bindings/sound/davinci-mcasp-audio.txt ++++ b/Documentation/devicetree/bindings/sound/davinci-mcasp-audio.txt +@@ -6,15 +6,21 @@ Required properties: + "ti,da830-mcasp-audio" : for both DA830 & DA850 platforms + "ti,omap2-mcasp-audio" : for OMAP2 platforms (TI81xx, AM33xx) + +-- reg : Should contain McASP registers offset and length +-- interrupts : Interrupt number for McASP ++- reg : Should contain McASP registers address and length for mpu and ++ optionally for dma controller access. ++- reg-names : The mandatory reg-range must be named "mpu" and the optional DMA ++ reg-range must be named "dma". For backward compatibility it is ++ good to keep "mpu" first in the list. + - op-mode : I2S/DIT ops mode. + - tdm-slots : Slots for TDM operation. +-- num-serializer : Serializers used by McASP. +-- serial-dir : A list of serializer pin mode. The list number should be equal +- to "num-serializer" parameter. Each entry is a number indication +- serializer pin direction. (0 - INACTIVE, 1 - TX, 2 - RX) +- ++- serial-dir : A list of serializer configuration. Each entry is a number ++ indication serializer pin direction. ++ (0 - INACTIVE, 1 - TX, 2 - RX) ++- dmas: two element list of DMA controller phandles and DMA request line ++ ordered pairs. ++- dma-names: identifier string for each DMA request line in the dmas property. ++ These strings correspond 1:1 with the ordered pairs in dmas. The dma ++ identifiers must be "rx" and "tx". + + Optional properties: + +@@ -23,6 +29,8 @@ Optional properties: + - rx-num-evt : FIFO levels. + - sram-size-playback : size of sram to be allocated during playback + - sram-size-capture : size of sram to be allocated during capture ++- interrupts : Interrupt numbers for McASP, currently not used by the driver ++- interrupt-names : Known interrupt names are "tx" and "rx" + + Example: + +@@ -31,10 +39,11 @@ mcasp0: mcasp0@1d00000 { + #address-cells = <1>; + #size-cells = <0>; + reg = <0x100000 0x3000>; ++ reg-names "mpu"; + interrupts = <82 83>; ++ interrupts-names = "tx", "rx"; + op-mode = <0>; /* MCASP_IIS_MODE */ + tdm-slots = <2>; +- num-serializer = <16>; + serial-dir = < + 0 0 0 0 /* 0: INACTIVE, 1: TX, 2: RX */ + 0 0 0 0 +--- a/Documentation/devicetree/bindings/sound/tlv320aic3x.txt ++++ b/Documentation/devicetree/bindings/sound/tlv320aic3x.txt +@@ -24,10 +24,36 @@ Optional properties: + 3 - MICBIAS output is connected to AVDD, + If this node is not mentioned or if the value is incorrect, then MicBias + is powered down. ++- AVDD-supply, IOVDD-supply, DRVDD-supply, DVDD-supply : power supplies for the ++ device as covered in Documentation/devicetree/bindings/regulator/regulator.txt ++ ++CODEC output pins: ++ * LLOUT ++ * RLOUT ++ * MONO_LOUT ++ * HPLOUT ++ * HPROUT ++ * HPLCOM ++ * HPRCOM ++ ++CODEC input pins: ++ * MIC3L ++ * MIC3R ++ * LINE1L ++ * LINE2L ++ * LINE1R ++ * LINE2R ++ ++The pins can be used in referring sound node's audio-routing property. + + Example: + + tlv320aic3x: tlv320aic3x@1b { + compatible = "ti,tlv320aic3x"; + reg = <0x1b>; ++ ++ AVDD-supply = <®ulator>; ++ IOVDD-supply = <®ulator>; ++ DRVDD-supply = <®ulator>; ++ DVDD-supply = <®ulator>; + }; +--- a/Documentation/devicetree/bindings/spi/omap-spi.txt ++++ b/Documentation/devicetree/bindings/spi/omap-spi.txt +@@ -2,8 +2,8 @@ OMAP2+ McSPI device + + Required properties: + - compatible : +- - "ti,omap2-spi" for OMAP2 & OMAP3. +- - "ti,omap4-spi" for OMAP4+. ++ - "ti,omap2-mcspi" for OMAP2 & OMAP3. ++ - "ti,omap4-mcspi" for OMAP4+. + - ti,spi-num-cs : Number of chipselect supported by the instance. + - ti,hwmods: Name of the hwmod associated to the McSPI + - ti,pindir-d0-out-d1-in: Select the D0 pin as output and D1 as +--- a/Documentation/devicetree/bindings/usb/dwc3.txt ++++ b/Documentation/devicetree/bindings/usb/dwc3.txt +@@ -6,11 +6,13 @@ Required properties: + - compatible: must be "snps,dwc3" + - reg : Address and length of the register set for the device + - interrupts: Interrupts used by the dwc3 controller. ++ ++Optional properties: + - usb-phy : array of phandle for the PHY device. The first element + in the array is expected to be a handle to the USB2/HS PHY and + the second element is expected to be a handle to the USB3/SS PHY +- +-Optional properties: ++ - phys: from the *Generic PHY* bindings ++ - phy-names: from the *Generic PHY* bindings + - tx-fifo-resize: determines if the FIFO *has* to be reallocated. + + This is usually a subnode to DWC3 glue to which it is connected. +--- a/Documentation/devicetree/bindings/usb/omap-usb.txt ++++ b/Documentation/devicetree/bindings/usb/omap-usb.txt +@@ -3,9 +3,6 @@ OMAP GLUE AND OTHER OMAP SPECIFIC COMPON + OMAP MUSB GLUE + - compatible : Should be "ti,omap4-musb" or "ti,omap3-musb" + - ti,hwmods : must be "usb_otg_hs" +- - ti,has-mailbox : to specify that omap uses an external mailbox +- (in control module) to communicate with the musb core during device connect +- and disconnect. + - multipoint : Should be "1" indicating the musb controller supports + multipoint. This is a MUSB configuration-specific setting. + - num-eps : Specifies the number of endpoints. This is also a +@@ -19,6 +16,9 @@ OMAP MUSB GLUE + - power : Should be "50". This signifies the controller can supply up to + 100mA when operating in host mode. + - usb-phy : the phandle for the PHY device ++ - phys : the phandle for the PHY device (used by generic PHY framework) ++ - phy-names : the names of the PHY corresponding to the PHYs present in the ++ *phy* phandle. + + Optional properties: + - ctrl-module : phandle of the control module this glue uses to write to +@@ -28,11 +28,12 @@ SOC specific device node entry + usb_otg_hs: usb_otg_hs@4a0ab000 { + compatible = "ti,omap4-musb"; + ti,hwmods = "usb_otg_hs"; +- ti,has-mailbox; + multipoint = <1>; + num-eps = <16>; + ram-bits = <12>; + ctrl-module = <&omap_control_usb>; ++ phys = <&usb2_phy>; ++ phy-names = "usb2-phy"; + }; + + Board specific device node entry +@@ -74,26 +75,3 @@ omap_dwc3 { + utmi-mode = <2>; + ranges; + }; +- +-OMAP CONTROL USB +- +-Required properties: +- - compatible: Should be "ti,omap-control-usb" +- - reg : Address and length of the register set for the device. It contains +- the address of "control_dev_conf" and "otghs_control" or "phy_power_usb" +- depending upon omap4 or omap5. +- - reg-names: The names of the register addresses corresponding to the registers +- filled in "reg". +- - ti,type: This is used to differentiate whether the control module has +- usb mailbox or usb3 phy power. omap4 has usb mailbox in control module to +- notify events to the musb core and omap5 has usb3 phy power register to +- power on usb3 phy. Should be "1" if it has mailbox and "2" if it has usb3 +- phy power. +- +-omap_control_usb: omap-control-usb@4a002300 { +- compatible = "ti,omap-control-usb"; +- reg = <0x4a002300 0x4>, +- <0x4a00233c 0x4>; +- reg-names = "control_dev_conf", "otghs_control"; +- ti,type = <1>; +-}; +--- a/Documentation/devicetree/bindings/usb/usb-nop-xceiv.txt ++++ b/Documentation/devicetree/bindings/usb/usb-nop-xceiv.txt +@@ -15,7 +15,7 @@ Optional properties: + + - vcc-supply: phandle to the regulator that provides RESET to the PHY. + +-- reset-supply: phandle to the regulator that provides power to the PHY. ++- reset-gpios: Should specify the GPIO for reset. + + Example: + +@@ -25,10 +25,9 @@ Example: + clocks = <&osc 0>; + clock-names = "main_clk"; + vcc-supply = <&hsusb1_vcc_regulator>; +- reset-supply = <&hsusb1_reset_regulator>; ++ reset-gpios = <&gpio1 7 GPIO_ACTIVE_LOW>; + }; + + hsusb1_phy is a NOP USB PHY device that gets its clock from an oscillator + and expects that clock to be configured to 19.2MHz by the NOP PHY driver. +-hsusb1_vcc_regulator provides power to the PHY and hsusb1_reset_regulator +-controls RESET. ++hsusb1_vcc_regulator provides power to the PHY and GPIO 7 controls RESET. +--- a/Documentation/devicetree/bindings/usb/usb-phy.txt ++++ /dev/null +@@ -1,42 +0,0 @@ +-USB PHY +- +-OMAP USB2 PHY +- +-Required properties: +- - compatible: Should be "ti,omap-usb2" +- - reg : Address and length of the register set for the device. +- +-Optional properties: +- - ctrl-module : phandle of the control module used by PHY driver to power on +- the PHY. +- +-This is usually a subnode of ocp2scp to which it is connected. +- +-usb2phy@4a0ad080 { +- compatible = "ti,omap-usb2"; +- reg = <0x4a0ad080 0x58>; +- ctrl-module = <&omap_control_usb>; +-}; +- +-OMAP USB3 PHY +- +-Required properties: +- - compatible: Should be "ti,omap-usb3" +- - reg : Address and length of the register set for the device. +- - reg-names: The names of the register addresses corresponding to the registers +- filled in "reg". +- +-Optional properties: +- - ctrl-module : phandle of the control module used by PHY driver to power on +- the PHY. +- +-This is usually a subnode of ocp2scp to which it is connected. +- +-usb3phy@4a084400 { +- compatible = "ti,omap-usb3"; +- reg = <0x4a084400 0x80>, +- <0x4a084800 0x64>, +- <0x4a084c00 0x40>; +- reg-names = "phy_rx", "phy_tx", "pll_ctrl"; +- ctrl-module = <&omap_control_usb>; +-}; +--- /dev/null ++++ b/Documentation/devicetree/bindings/video/da8xx-fb.txt +@@ -0,0 +1,42 @@ ++TI LCD Controller on DA830/DA850/AM335x SoC's ++ ++Required properties: ++- compatible: ++ DA830, DA850 - "ti,da8xx-tilcdc" ++ AM335x SoC's - "ti,am33xx-tilcdc" ++- reg: Address range of lcdc register set ++- interrupts: lcdc interrupt ++- display-timings: typical videomode of lcd panel, represented as child. ++ Refer Documentation/devicetree/bindings/video/display-timing.txt for ++ display timing binding details. If multiple videomodes are mentioned ++ in display timings node, typical videomode has to be mentioned as the ++ native mode or it has to be first child (driver cares only for native ++ videomode). ++ ++Recommended properties: ++- ti,hwmods: Name of the hwmod associated to the LCDC ++ ++Example for am335x SoC's: ++ ++lcdc@4830e000 { ++ compatible = "ti,am33xx-tilcdc"; ++ reg = <0x4830e000 0x1000>; ++ interrupts = <36>; ++ ti,hwmods = "lcdc"; ++ status = "okay"; ++ display-timings { ++ 800x480p62 { ++ clock-frequency = <30000000>; ++ hactive = <800>; ++ vactive = <480>; ++ hfront-porch = <39>; ++ hback-porch = <39>; ++ hsync-len = <47>; ++ vback-porch = <29>; ++ vfront-porch = <13>; ++ vsync-len = <2>; ++ hsync-active = <1>; ++ vsync-active = <1>; ++ }; ++ }; ++}; +--- /dev/null ++++ b/Documentation/phy.txt +@@ -0,0 +1,166 @@ ++ PHY SUBSYSTEM ++ Kishon Vijay Abraham I <kishon@ti.com> ++ ++This document explains the Generic PHY Framework along with the APIs provided, ++and how-to-use. ++ ++1. Introduction ++ ++*PHY* is the abbreviation for physical layer. It is used to connect a device ++to the physical medium e.g., the USB controller has a PHY to provide functions ++such as serialization, de-serialization, encoding, decoding and is responsible ++for obtaining the required data transmission rate. Note that some USB ++controllers have PHY functionality embedded into it and others use an external ++PHY. Other peripherals that use PHY include Wireless LAN, Ethernet, ++SATA etc. ++ ++The intention of creating this framework is to bring the PHY drivers spread ++all over the Linux kernel to drivers/phy to increase code re-use and for ++better code maintainability. ++ ++This framework will be of use only to devices that use external PHY (PHY ++functionality is not embedded within the controller). ++ ++2. Registering/Unregistering the PHY provider ++ ++PHY provider refers to an entity that implements one or more PHY instances. ++For the simple case where the PHY provider implements only a single instance of ++the PHY, the framework provides its own implementation of of_xlate in ++of_phy_simple_xlate. If the PHY provider implements multiple instances, it ++should provide its own implementation of of_xlate. of_xlate is used only for ++dt boot case. ++ ++#define of_phy_provider_register(dev, xlate) \ ++ __of_phy_provider_register((dev), THIS_MODULE, (xlate)) ++ ++#define devm_of_phy_provider_register(dev, xlate) \ ++ __devm_of_phy_provider_register((dev), THIS_MODULE, (xlate)) ++ ++of_phy_provider_register and devm_of_phy_provider_register macros can be used to ++register the phy_provider and it takes device and of_xlate as ++arguments. For the dt boot case, all PHY providers should use one of the above ++2 macros to register the PHY provider. ++ ++void devm_of_phy_provider_unregister(struct device *dev, ++ struct phy_provider *phy_provider); ++void of_phy_provider_unregister(struct phy_provider *phy_provider); ++ ++devm_of_phy_provider_unregister and of_phy_provider_unregister can be used to ++unregister the PHY. ++ ++3. Creating the PHY ++ ++The PHY driver should create the PHY in order for other peripheral controllers ++to make use of it. The PHY framework provides 2 APIs to create the PHY. ++ ++struct phy *phy_create(struct device *dev, const struct phy_ops *ops, ++ struct phy_init_data *init_data); ++struct phy *devm_phy_create(struct device *dev, const struct phy_ops *ops, ++ struct phy_init_data *init_data); ++ ++The PHY drivers can use one of the above 2 APIs to create the PHY by passing ++the device pointer, phy ops and init_data. ++phy_ops is a set of function pointers for performing PHY operations such as ++init, exit, power_on and power_off. *init_data* is mandatory to get a reference ++to the PHY in the case of non-dt boot. See section *Board File Initialization* ++on how init_data should be used. ++ ++Inorder to dereference the private data (in phy_ops), the phy provider driver ++can use phy_set_drvdata() after creating the PHY and use phy_get_drvdata() in ++phy_ops to get back the private data. ++ ++4. Getting a reference to the PHY ++ ++Before the controller can make use of the PHY, it has to get a reference to ++it. This framework provides the following APIs to get a reference to the PHY. ++ ++struct phy *phy_get(struct device *dev, const char *string); ++struct phy *devm_phy_get(struct device *dev, const char *string); ++ ++phy_get and devm_phy_get can be used to get the PHY. In the case of dt boot, ++the string arguments should contain the phy name as given in the dt data and ++in the case of non-dt boot, it should contain the label of the PHY. ++The only difference between the two APIs is that devm_phy_get associates the ++device with the PHY using devres on successful PHY get. On driver detach, ++release function is invoked on the the devres data and devres data is freed. ++ ++5. Releasing a reference to the PHY ++ ++When the controller no longer needs the PHY, it has to release the reference ++to the PHY it has obtained using the APIs mentioned in the above section. The ++PHY framework provides 2 APIs to release a reference to the PHY. ++ ++void phy_put(struct phy *phy); ++void devm_phy_put(struct device *dev, struct phy *phy); ++ ++Both these APIs are used to release a reference to the PHY and devm_phy_put ++destroys the devres associated with this PHY. ++ ++6. Destroying the PHY ++ ++When the driver that created the PHY is unloaded, it should destroy the PHY it ++created using one of the following 2 APIs. ++ ++void phy_destroy(struct phy *phy); ++void devm_phy_destroy(struct device *dev, struct phy *phy); ++ ++Both these APIs destroy the PHY and devm_phy_destroy destroys the devres ++associated with this PHY. ++ ++7. PM Runtime ++ ++This subsystem is pm runtime enabled. So while creating the PHY, ++pm_runtime_enable of the phy device created by this subsystem is called and ++while destroying the PHY, pm_runtime_disable is called. Note that the phy ++device created by this subsystem will be a child of the device that calls ++phy_create (PHY provider device). ++ ++So pm_runtime_get_sync of the phy_device created by this subsystem will invoke ++pm_runtime_get_sync of PHY provider device because of parent-child relationship. ++It should also be noted that phy_power_on and phy_power_off performs ++phy_pm_runtime_get_sync and phy_pm_runtime_put respectively. ++There are exported APIs like phy_pm_runtime_get, phy_pm_runtime_get_sync, ++phy_pm_runtime_put, phy_pm_runtime_put_sync, phy_pm_runtime_allow and ++phy_pm_runtime_forbid for performing PM operations. ++ ++8. Board File Initialization ++ ++Certain board file initialization is necessary in order to get a reference ++to the PHY in the case of non-dt boot. ++Say we have a single device that implements 3 PHYs that of USB, SATA and PCIe, ++then in the board file the following initialization should be done. ++ ++struct phy_consumer consumers[] = { ++ PHY_CONSUMER("dwc3.0", "usb"), ++ PHY_CONSUMER("pcie.0", "pcie"), ++ PHY_CONSUMER("sata.0", "sata"), ++}; ++PHY_CONSUMER takes 2 parameters, first is the device name of the controller ++(PHY consumer) and second is the port name. ++ ++struct phy_init_data init_data = { ++ .consumers = consumers, ++ .num_consumers = ARRAY_SIZE(consumers), ++}; ++ ++static const struct platform_device pipe3_phy_dev = { ++ .name = "pipe3-phy", ++ .id = -1, ++ .dev = { ++ .platform_data = { ++ .init_data = &init_data, ++ }, ++ }, ++}; ++ ++then, while doing phy_create, the PHY driver should pass this init_data ++ phy_create(dev, ops, pdata->init_data); ++ ++and the controller driver (phy consumer) should pass the port name along with ++the device to get a reference to the PHY ++ phy_get(dev, "pcie"); ++ ++9. DeviceTree Binding ++ ++The documentation for PHY dt binding can be found @ ++Documentation/devicetree/bindings/phy/phy-bindings.txt +--- a/drivers/ata/ahci.h ++++ b/drivers/ata/ahci.h +@@ -322,6 +322,7 @@ struct ahci_host_priv { + u32 em_buf_sz; /* EM buffer size in byte */ + u32 em_msg_type; /* EM message type */ + struct clk *clk; /* Only for platforms supporting clk */ ++ struct phy *phy; /* If platforms use phy */ + void *plat_data; /* Other platform data */ + }; + +--- a/drivers/ata/ahci_platform.c ++++ b/drivers/ata/ahci_platform.c +@@ -23,6 +23,7 @@ + #include <linux/platform_device.h> + #include <linux/libata.h> + #include <linux/ahci_platform.h> ++#include <linux/phy/phy.h> + #include "ahci.h" + + static void ahci_host_stop(struct ata_host *host); +@@ -141,16 +142,32 @@ static int ahci_probe(struct platform_de + } + } + ++ hpriv->phy = devm_phy_get(dev, "sata-phy"); ++ if (IS_ERR(hpriv->phy)) { ++ dev_dbg(dev, "can't get sata-phy\n"); ++ /* return only if -EPROBE_DEFER */ ++ if (PTR_ERR(hpriv->phy) == -EPROBE_DEFER) { ++ rc = -EPROBE_DEFER; ++ goto disable_unprepare_clk; ++ } ++ } ++ ++ if (!IS_ERR(hpriv->phy)) { ++ phy_init(hpriv->phy); ++ phy_power_on(hpriv->phy); ++ } ++ + /* + * Some platforms might need to prepare for mmio region access, + * which could be done in the following init call. So, the mmio + * region shouldn't be accessed before init (if provided) has + * returned successfully. + */ ++ + if (pdata && pdata->init) { + rc = pdata->init(dev, hpriv->mmio); + if (rc) +- goto disable_unprepare_clk; ++ goto disable_phy; + } + + ahci_save_initial_config(dev, hpriv, +@@ -220,6 +237,12 @@ static int ahci_probe(struct platform_de + pdata_exit: + if (pdata && pdata->exit) + pdata->exit(dev); ++disable_phy: ++ if (!IS_ERR(hpriv->phy)) { ++ phy_power_off(hpriv->phy); ++ phy_exit(hpriv->phy); ++ } ++ + disable_unprepare_clk: + if (!IS_ERR(hpriv->clk)) + clk_disable_unprepare(hpriv->clk); +@@ -238,6 +261,11 @@ static void ahci_host_stop(struct ata_ho + if (pdata && pdata->exit) + pdata->exit(dev); + ++ if (!IS_ERR(hpriv->phy)) { ++ phy_power_off(hpriv->phy); ++ phy_exit(hpriv->phy); ++ } ++ + if (!IS_ERR(hpriv->clk)) { + clk_disable_unprepare(hpriv->clk); + clk_put(hpriv->clk); +@@ -328,6 +356,7 @@ static SIMPLE_DEV_PM_OPS(ahci_pm_ops, ah + static const struct of_device_id ahci_of_match[] = { + { .compatible = "snps,spear-ahci", }, + { .compatible = "snps,exynos5440-ahci", }, ++ { .compatible = "snps,dwc-ahci", }, + {}, + }; + MODULE_DEVICE_TABLE(of, ahci_of_match); +--- a/drivers/ata/Kconfig ++++ b/drivers/ata/Kconfig +@@ -137,6 +137,13 @@ config SATA_SIL24 + + If unsure, say N. + ++config SATA_TI ++ tristate "Texas Instruments SATA Wrapper driver" ++ depends on ARCH_OMAP ++ help ++ This options enables SATA Wrapper driver for Texas Instruments SoCs. ++ It is found on OMAP5 and DRA7. ++ + config ATA_SFF + bool "ATA SFF support (for legacy IDE and PATA)" + default y +--- a/drivers/ata/Makefile ++++ b/drivers/ata/Makefile +@@ -11,6 +11,7 @@ obj-$(CONFIG_SATA_SIL24) += sata_sil24.o + obj-$(CONFIG_SATA_DWC) += sata_dwc_460ex.o + obj-$(CONFIG_SATA_HIGHBANK) += sata_highbank.o libahci.o + obj-$(CONFIG_AHCI_IMX) += ahci_imx.o ++obj-$(CONFIG_SATA_TI) += sata_ti.o + + # SFF w/ custom DMA + obj-$(CONFIG_PDC_ADMA) += pdc_adma.o +--- /dev/null ++++ b/drivers/ata/sata_ti.c +@@ -0,0 +1,160 @@ ++/** ++ * sata-ti.c - Texas Instruments Specific SATA Glue layer ++ * ++ * Copyright (C) 2013 Texas Instruments Incorporated - http://www.ti.com ++ * ++ * Authors: Roger Quadros <rogerq@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 of ++ * the License 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. ++ */ ++ ++#include <linux/module.h> ++#include <linux/kernel.h> ++#include <linux/slab.h> ++#include <linux/platform_device.h> ++#include <linux/ioport.h> ++#include <linux/io.h> ++#include <linux/pm_runtime.h> ++#include <linux/of.h> ++#include <linux/of_platform.h> ++ ++/* ++ * All these registers belong to OMAP's Wrapper around the ++ * DesignWare SATA Core. ++ */ ++ ++#define SATA_SYSCONFIG 0x0000 ++#define SATA_CDRLOCK 0x0004 ++ ++struct ti_sata { ++ struct device *dev; ++ void __iomem *base; ++}; ++ ++static int ti_sata_probe(struct platform_device *pdev) ++{ ++ struct device_node *np = pdev->dev.of_node; ++ struct device *dev = &pdev->dev; ++ struct ti_sata *sata; ++ struct resource *res; ++ void __iomem *base; ++ int ret; ++ ++ if (!np) { ++ dev_err(dev, "device node not found\n"); ++ return -EINVAL; ++ } ++ ++ sata = devm_kzalloc(dev, sizeof(*sata), GFP_KERNEL); ++ if (!sata) ++ return -ENOMEM; ++ ++ platform_set_drvdata(pdev, sata); ++ ++ res = platform_get_resource(pdev, IORESOURCE_MEM, 0); ++ if (!res) { ++ dev_err(dev, "missing memory base resource\n"); ++ return -EINVAL; ++ } ++ ++ base = devm_ioremap_resource(dev, res); ++ if (IS_ERR(base)) ++ return PTR_ERR(base); ++ ++ sata->dev = dev; ++ sata->base = base; ++ ++ pm_runtime_enable(dev); ++ ret = pm_runtime_get_sync(dev); ++ if (ret < 0) { ++ dev_err(dev, "pm_runtime_get_sync failed with err %d\n", ++ ret); ++ goto runtime_disable; ++ } ++ ++ ret = of_platform_populate(np, NULL, NULL, dev); ++ if (ret) { ++ dev_err(&pdev->dev, "failed to create TI SATA children\n"); ++ goto runtime_put; ++ } ++ ++ return 0; ++ ++runtime_put: ++ pm_runtime_put_sync(dev); ++ ++runtime_disable: ++ pm_runtime_disable(dev); ++ ++ return ret; ++} ++ ++static int ti_sata_remove_child(struct device *dev, void *c) ++{ ++ struct platform_device *pdev = to_platform_device(dev); ++ ++ platform_device_unregister(pdev); ++ ++ return 0; ++} ++ ++static int ti_sata_remove(struct platform_device *pdev) ++{ ++ pm_runtime_put_sync(&pdev->dev); ++ pm_runtime_disable(&pdev->dev); ++ device_for_each_child(&pdev->dev, NULL, ti_sata_remove_child); ++ ++ return 0; ++} ++ ++static const struct of_device_id of_ti_sata_match[] = { ++ { ++ .compatible = "ti,sata" ++ }, ++ { }, ++}; ++MODULE_DEVICE_TABLE(of, of_ti_sata_match); ++ ++#ifdef CONFIG_PM ++ ++static int ti_sata_resume(struct device *dev) ++{ ++ pm_runtime_disable(dev); ++ pm_runtime_set_active(dev); ++ pm_runtime_enable(dev); ++ ++ return 0; ++} ++ ++static const struct dev_pm_ops ti_sata_dev_pm_ops = { ++ .resume = ti_sata_resume, ++}; ++ ++#define DEV_PM_OPS (&ti_sata_dev_pm_ops) ++#else ++#define DEV_PM_OPS NULL ++#endif /* CONFIG_PM */ ++ ++static struct platform_driver ti_sata_driver = { ++ .probe = ti_sata_probe, ++ .remove = ti_sata_remove, ++ .driver = { ++ .name = "ti-sata", ++ .of_match_table = of_ti_sata_match, ++ .pm = DEV_PM_OPS, ++ }, ++}; ++ ++module_platform_driver(ti_sata_driver); ++ ++MODULE_ALIAS("platform:ti-sata"); ++MODULE_AUTHOR("Roger Quadros <rogerq@ti.com>"); ++MODULE_LICENSE("GPL v2"); ++MODULE_DESCRIPTION("TI SATA Glue Layer"); +--- a/drivers/clk/clk.c ++++ b/drivers/clk/clk.c +@@ -2196,6 +2196,12 @@ struct clk *of_clk_get_from_provider(str + return clk; + } + ++int of_clk_get_parent_count(struct device_node *np) ++{ ++ return of_count_phandle_with_args(np, "clocks", "#clock-cells"); ++} ++EXPORT_SYMBOL_GPL(of_clk_get_parent_count); ++ + const char *of_clk_get_parent_name(struct device_node *np, int index) + { + struct of_phandle_args clkspec; +--- a/drivers/clk/clk-divider.c ++++ b/drivers/clk/clk-divider.c +@@ -1,7 +1,7 @@ + /* + * Copyright (C) 2011 Sascha Hauer, Pengutronix <s.hauer@pengutronix.de> + * Copyright (C) 2011 Richard Zhao, Linaro <richard.zhao@linaro.org> +- * Copyright (C) 2011-2012 Mike Turquette, Linaro Ltd <mturquette@linaro.org> ++ * Copyright (C) 2011-2013 Mike Turquette, Linaro Ltd <mturquette@linaro.org> + * + * 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 +@@ -17,6 +17,8 @@ + #include <linux/err.h> + #include <linux/string.h> + #include <linux/log2.h> ++#include <linux/of.h> ++#include <linux/of_address.h> + + /* + * DOC: basic adjustable divider clock that cannot gate +@@ -30,8 +32,6 @@ + + #define to_clk_divider(_hw) container_of(_hw, struct clk_divider, hw) + +-#define div_mask(d) ((1 << ((d)->width)) - 1) +- + static unsigned int _get_table_maxdiv(const struct clk_div_table *table) + { + unsigned int maxdiv = 0; +@@ -46,12 +46,12 @@ static unsigned int _get_table_maxdiv(co + static unsigned int _get_maxdiv(struct clk_divider *divider) + { + if (divider->flags & CLK_DIVIDER_ONE_BASED) +- return div_mask(divider); ++ return divider->mask; + if (divider->flags & CLK_DIVIDER_POWER_OF_TWO) +- return 1 << div_mask(divider); ++ return 1 << divider->mask; + if (divider->table) + return _get_table_maxdiv(divider->table); +- return div_mask(divider) + 1; ++ return divider->mask + 1; + } + + static unsigned int _get_table_div(const struct clk_div_table *table, +@@ -105,7 +105,7 @@ static unsigned long clk_divider_recalc_ + unsigned int div, val; + + val = clk_readl(divider->reg) >> divider->shift; +- val &= div_mask(divider); ++ val &= divider->mask; + + div = _get_div(divider, val); + if (!div) { +@@ -221,17 +221,17 @@ static int clk_divider_set_rate(struct c + div = parent_rate / rate; + value = _get_val(divider, div); + +- if (value > div_mask(divider)) +- value = div_mask(divider); ++ if (value > divider->mask) ++ value = divider->mask; + + if (divider->lock) + spin_lock_irqsave(divider->lock, flags); + + if (divider->flags & CLK_DIVIDER_HIWORD_MASK) { +- val = div_mask(divider) << (divider->shift + 16); ++ val = divider->mask << (divider->shift + 16); + } else { + val = clk_readl(divider->reg); +- val &= ~(div_mask(divider) << divider->shift); ++ val &= ~(divider->mask << divider->shift); + } + val |= value << divider->shift; + clk_writel(val, divider->reg); +@@ -251,7 +251,7 @@ EXPORT_SYMBOL_GPL(clk_divider_ops); + + static struct clk *_register_divider(struct device *dev, const char *name, + const char *parent_name, unsigned long flags, +- void __iomem *reg, u8 shift, u8 width, ++ void __iomem *reg, u8 shift, u32 mask, + u8 clk_divider_flags, const struct clk_div_table *table, + spinlock_t *lock) + { +@@ -260,8 +260,9 @@ static struct clk *_register_divider(str + struct clk_init_data init; + + if (clk_divider_flags & CLK_DIVIDER_HIWORD_MASK) { +- if (width + shift > 16) { +- pr_warn("divider value exceeds LOWORD field\n"); ++ if ((mask << shift) & 0xffff0000) { ++ pr_warn("%s: divider value exceeds LOWORD field\n", ++ __func__); + return ERR_PTR(-EINVAL); + } + } +@@ -282,7 +283,7 @@ static struct clk *_register_divider(str + /* struct clk_divider assignments */ + div->reg = reg; + div->shift = shift; +- div->width = width; ++ div->mask = mask; + div->flags = clk_divider_flags; + div->lock = lock; + div->hw.init = &init; +@@ -315,7 +316,7 @@ struct clk *clk_register_divider(struct + u8 clk_divider_flags, spinlock_t *lock) + { + return _register_divider(dev, name, parent_name, flags, reg, shift, +- width, clk_divider_flags, NULL, lock); ++ ((1 << width) - 1), clk_divider_flags, NULL, lock); + } + EXPORT_SYMBOL_GPL(clk_register_divider); + +@@ -340,6 +341,103 @@ struct clk *clk_register_divider_table(s + spinlock_t *lock) + { + return _register_divider(dev, name, parent_name, flags, reg, shift, +- width, clk_divider_flags, table, lock); ++ ((1 << width) - 1), clk_divider_flags, table, lock); + } + EXPORT_SYMBOL_GPL(clk_register_divider_table); ++ ++#ifdef CONFIG_OF ++struct clk_div_table *of_clk_get_div_table(struct device_node *node) ++{ ++ int i; ++ u32 table_size; ++ struct clk_div_table *table; ++ const __be32 *tablespec; ++ u32 val; ++ ++ tablespec = of_get_property(node, "table", &table_size); ++ ++ if (!tablespec) ++ return NULL; ++ ++ table_size /= sizeof(struct clk_div_table); ++ ++ table = kzalloc(sizeof(struct clk_div_table) * table_size, GFP_KERNEL); ++ if (!table) { ++ pr_err("%s: unable to allocate memory for %s table\n", __func__, node->name); ++ return NULL; ++ } ++ ++ for (i = 0; i < table_size; i++) { ++ of_property_read_u32_index(node, "table", i * 2, &val); ++ table[i].div = val; ++ of_property_read_u32_index(node, "table", i * 2 + 1, &val); ++ table[i].val = val; ++ } ++ ++ return table; ++} ++ ++/** ++ * of_divider_clk_setup() - Setup function for simple div rate clock ++ */ ++void of_divider_clk_setup(struct device_node *node) ++{ ++ struct clk *clk; ++ const char *clk_name = node->name; ++ void __iomem *reg; ++ const char *parent_name; ++ u8 clk_divider_flags = 0; ++ u32 mask = 0; ++ u32 shift = 0; ++ struct clk_div_table *table; ++ u32 flags = 0; ++ ++ of_property_read_string(node, "clock-output-names", &clk_name); ++ ++ parent_name = of_clk_get_parent_name(node, 0); ++ ++ reg = of_iomap(node, 0); ++ if (!reg) { ++ pr_err("%s: no memory mapped for property reg\n", __func__); ++ return; ++ } ++ ++ if (of_property_read_u32(node, "bit-mask", &mask)) { ++ pr_err("%s: missing bit-mask property for %s\n", __func__, node->name); ++ return; ++ } ++ ++ if (of_property_read_u32(node, "bit-shift", &shift)) { ++ shift = __ffs(mask); ++ pr_debug("%s: bit-shift property defaults to 0x%x for %s\n", ++ __func__, shift, node->name); ++ } ++ ++ if (of_property_read_bool(node, "index-starts-at-one")) ++ clk_divider_flags |= CLK_DIVIDER_ONE_BASED; ++ ++ if (of_property_read_bool(node, "index-power-of-two")) ++ clk_divider_flags |= CLK_DIVIDER_POWER_OF_TWO; ++ ++ if (of_property_read_bool(node, "index-allow-zero")) ++ clk_divider_flags |= CLK_DIVIDER_ALLOW_ZERO; ++ ++ if (of_property_read_bool(node, "hiword-mask")) ++ clk_divider_flags |= CLK_DIVIDER_HIWORD_MASK; ++ ++ if (of_property_read_bool(node, "set-rate-parent")) ++ flags |= CLK_SET_RATE_PARENT; ++ ++ table = of_clk_get_div_table(node); ++ if (IS_ERR(table)) ++ return; ++ ++ clk = _register_divider(NULL, clk_name, parent_name, flags, reg, shift, ++ mask, clk_divider_flags, table, NULL); ++ ++ if (!IS_ERR(clk)) ++ of_clk_add_provider(node, of_clk_src_simple_get, clk); ++} ++EXPORT_SYMBOL_GPL(of_divider_clk_setup); ++CLK_OF_DECLARE(divider_clk, "divider-clock", of_divider_clk_setup); ++#endif +--- a/drivers/clk/clk-fixed-factor.c ++++ b/drivers/clk/clk-fixed-factor.c +@@ -109,6 +109,7 @@ void __init of_fixed_factor_clk_setup(st + const char *clk_name = node->name; + const char *parent_name; + u32 div, mult; ++ u32 flags = 0; + + if (of_property_read_u32(node, "clock-div", &div)) { + pr_err("%s Fixed factor clock <%s> must have a clock-div property\n", +@@ -125,7 +126,10 @@ void __init of_fixed_factor_clk_setup(st + of_property_read_string(node, "clock-output-names", &clk_name); + parent_name = of_clk_get_parent_name(node, 0); + +- clk = clk_register_fixed_factor(NULL, clk_name, parent_name, 0, ++ if (of_property_read_bool(node, "set-rate-parent")) ++ flags |= CLK_SET_RATE_PARENT; ++ ++ clk = clk_register_fixed_factor(NULL, clk_name, parent_name, flags, + mult, div); + if (!IS_ERR(clk)) + of_clk_add_provider(node, of_clk_src_simple_get, clk); +--- a/drivers/clk/clk-gate.c ++++ b/drivers/clk/clk-gate.c +@@ -15,6 +15,8 @@ + #include <linux/io.h> + #include <linux/err.h> + #include <linux/string.h> ++#include <linux/of.h> ++#include <linux/of_address.h> + + /** + * DOC: basic gatable clock which can gate and ungate it's ouput +@@ -162,3 +164,52 @@ struct clk *clk_register_gate(struct dev + return clk; + } + EXPORT_SYMBOL_GPL(clk_register_gate); ++ ++#ifdef CONFIG_OF ++/** ++ * of_gate_clk_setup() - Setup function for simple gate rate clock ++ */ ++void of_gate_clk_setup(struct device_node *node) ++{ ++ struct clk *clk; ++ const char *clk_name = node->name; ++ void __iomem *reg; ++ const char *parent_name; ++ u8 clk_gate_flags = 0; ++ u32 bit_idx = 0; ++ u32 flags = 0; ++ ++ of_property_read_string(node, "clock-output-names", &clk_name); ++ ++ parent_name = of_clk_get_parent_name(node, 0); ++ ++ reg = of_iomap(node, 0); ++ if (!reg) { ++ pr_err("%s: no memory mapped for property reg\n", __func__); ++ return; ++ } ++ ++ if (of_property_read_u32(node, "bit-shift", &bit_idx)) { ++ pr_err("%s: missing bit-shift property for %s\n", ++ __func__, node->name); ++ return; ++ } ++ ++ if (of_property_read_bool(node, "set-bit-to-disable")) ++ clk_gate_flags |= CLK_GATE_SET_TO_DISABLE; ++ ++ if (of_property_read_bool(node, "hiword-mask")) ++ clk_gate_flags |= CLK_GATE_HIWORD_MASK; ++ ++ if (of_property_read_bool(node, "set-rate-parent")) ++ flags |= CLK_SET_RATE_PARENT; ++ ++ clk = clk_register_gate(NULL, clk_name, parent_name, flags, reg, ++ bit_idx, clk_gate_flags, NULL); ++ ++ if (!IS_ERR(clk)) ++ of_clk_add_provider(node, of_clk_src_simple_get, clk); ++} ++EXPORT_SYMBOL_GPL(of_gate_clk_setup); ++CLK_OF_DECLARE(gate_clk, "gate-clock", of_gate_clk_setup); ++#endif +--- a/drivers/clk/clk-mux.c ++++ b/drivers/clk/clk-mux.c +@@ -1,7 +1,7 @@ + /* + * Copyright (C) 2011 Sascha Hauer, Pengutronix <s.hauer@pengutronix.de> + * Copyright (C) 2011 Richard Zhao, Linaro <richard.zhao@linaro.org> +- * Copyright (C) 2011-2012 Mike Turquette, Linaro Ltd <mturquette@linaro.org> ++ * Copyright (C) 2011-2013 Mike Turquette, Linaro Ltd <mturquette@linaro.org> + * + * 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 +@@ -16,6 +16,8 @@ + #include <linux/slab.h> + #include <linux/io.h> + #include <linux/err.h> ++#include <linux/of.h> ++#include <linux/of_address.h> + + /* + * DOC: basic adjustable multiplexer clock that cannot gate +@@ -177,3 +179,71 @@ struct clk *clk_register_mux(struct devi + NULL, lock); + } + EXPORT_SYMBOL_GPL(clk_register_mux); ++ ++#ifdef CONFIG_OF ++/** ++ * of_mux_clk_setup() - Setup function for simple mux rate clock ++ */ ++void of_mux_clk_setup(struct device_node *node) ++{ ++ struct clk *clk; ++ const char *clk_name = node->name; ++ void __iomem *reg; ++ int num_parents; ++ const char **parent_names; ++ int i; ++ u8 clk_mux_flags = 0; ++ u32 mask = 0; ++ u32 shift = 0; ++ u32 flags = 0; ++ ++ of_property_read_string(node, "clock-output-names", &clk_name); ++ ++ num_parents = of_clk_get_parent_count(node); ++ if (num_parents < 1) { ++ pr_err("%s: mux-clock %s must have parent(s)\n", ++ __func__, node->name); ++ return; ++ } ++ ++ parent_names = kzalloc((sizeof(char*) * num_parents), ++ GFP_KERNEL); ++ ++ for (i = 0; i < num_parents; i++) ++ parent_names[i] = of_clk_get_parent_name(node, i); ++ ++ reg = of_iomap(node, 0); ++ if (!reg) { ++ pr_err("%s: no memory mapped for property reg\n", __func__); ++ return; ++ } ++ ++ if (of_property_read_u32(node, "bit-mask", &mask)) { ++ pr_err("%s: missing bit-mask property for %s\n", __func__, node->name); ++ return; ++ } ++ ++ if (of_property_read_u32(node, "bit-shift", &shift)) { ++ shift = __ffs(mask); ++ pr_debug("%s: bit-shift property defaults to 0x%x for %s\n", ++ __func__, shift, node->name); ++ } ++ ++ if (of_property_read_bool(node, "index-starts-at-one")) ++ clk_mux_flags |= CLK_MUX_INDEX_ONE; ++ ++ if (of_property_read_bool(node, "hiword-mask")) ++ clk_mux_flags |= CLK_MUX_HIWORD_MASK; ++ ++ if (of_property_read_bool(node, "set-rate-parent")) ++ flags |= CLK_SET_RATE_PARENT; ++ ++ clk = clk_register_mux_table(NULL, clk_name, parent_names, num_parents, ++ flags, reg, shift, mask, clk_mux_flags, NULL, NULL); ++ ++ if (!IS_ERR(clk)) ++ of_clk_add_provider(node, of_clk_src_simple_get, clk); ++} ++EXPORT_SYMBOL_GPL(of_mux_clk_setup); ++CLK_OF_DECLARE(mux_clk, "mux-clock", of_mux_clk_setup); ++#endif +--- /dev/null ++++ b/drivers/clk/clk-palmas.c +@@ -0,0 +1,305 @@ ++/* ++ * Clock driver for Palmas device. ++ * ++ * Copyright (c) 2013, NVIDIA Corporation. ++ * ++ * Author: Laxman Dewangan <ldewangan@nvidia.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. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this program; if not, write to the Free Software ++ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA ++ * 02111-1307, USA ++ */ ++ ++#include <linux/clk.h> ++#include <linux/clkdev.h> ++#include <linux/clk-provider.h> ++#include <linux/mfd/palmas.h> ++#include <linux/module.h> ++#include <linux/of.h> ++#include <linux/of_device.h> ++#include <linux/platform_device.h> ++#include <linux/slab.h> ++ ++#define PALMAS_CLOCK_DT_EXT_CONTROL_ENABLE1 1 ++#define PALMAS_CLOCK_DT_EXT_CONTROL_ENABLE2 2 ++#define PALMAS_CLOCK_DT_EXT_CONTROL_NSLEEP 3 ++ ++struct palmas_clk32k_desc { ++ const char *clk_name; ++ unsigned int control_reg; ++ unsigned int enable_mask; ++ unsigned int sleep_mask; ++ unsigned int sleep_reqstr_id; ++ int delay; ++}; ++ ++struct palmas_clock_info { ++ struct device *dev; ++ struct clk *clk; ++ struct clk_hw hw; ++ struct palmas *palmas; ++ struct palmas_clk32k_desc *clk_desc; ++ int ext_control_pin; ++}; ++ ++static inline struct palmas_clock_info *to_palmas_clks_info(struct clk_hw *hw) ++{ ++ return container_of(hw, struct palmas_clock_info, hw); ++} ++ ++static unsigned long palmas_clks_recalc_rate(struct clk_hw *hw, ++ unsigned long parent_rate) ++{ ++ return 32768; ++} ++ ++static int palmas_clks_prepare(struct clk_hw *hw) ++{ ++ struct palmas_clock_info *cinfo = to_palmas_clks_info(hw); ++ int ret; ++ ++ ret = palmas_update_bits(cinfo->palmas, PALMAS_RESOURCE_BASE, ++ cinfo->clk_desc->control_reg, ++ cinfo->clk_desc->enable_mask, ++ cinfo->clk_desc->enable_mask); ++ if (ret < 0) ++ dev_err(cinfo->dev, "Reg 0x%02x update failed, %d\n", ++ cinfo->clk_desc->control_reg, ret); ++ else if (cinfo->clk_desc->delay) ++ udelay(cinfo->clk_desc->delay); ++ ++ return ret; ++} ++ ++static void palmas_clks_unprepare(struct clk_hw *hw) ++{ ++ struct palmas_clock_info *cinfo = to_palmas_clks_info(hw); ++ int ret; ++ ++ /* ++ * Clock can be disabled through external pin if it is externally ++ * controlled. ++ */ ++ if (cinfo->ext_control_pin) ++ return; ++ ++ ret = palmas_update_bits(cinfo->palmas, PALMAS_RESOURCE_BASE, ++ cinfo->clk_desc->control_reg, ++ cinfo->clk_desc->enable_mask, 0); ++ if (ret < 0) ++ dev_err(cinfo->dev, "Reg 0x%02x update failed, %d\n", ++ cinfo->clk_desc->control_reg, ret); ++ ++} ++ ++static int palmas_clks_is_prepared(struct clk_hw *hw) ++{ ++ struct palmas_clock_info *cinfo = to_palmas_clks_info(hw); ++ int ret; ++ u32 val; ++ ++ if (cinfo->ext_control_pin) ++ return 1; ++ ++ ret = palmas_read(cinfo->palmas, PALMAS_RESOURCE_BASE, ++ cinfo->clk_desc->control_reg, &val); ++ if (ret < 0) { ++ dev_err(cinfo->dev, "Reg 0x%02x read failed, %d\n", ++ cinfo->clk_desc->control_reg, ret); ++ return ret; ++ } ++ return !!(val & cinfo->clk_desc->enable_mask); ++} ++ ++static struct clk_ops palmas_clks_ops = { ++ .prepare = palmas_clks_prepare, ++ .unprepare = palmas_clks_unprepare, ++ .is_prepared = palmas_clks_is_prepared, ++ .recalc_rate = palmas_clks_recalc_rate, ++}; ++ ++struct palmas_clks_of_match { ++ struct clk_init_data init; ++ struct palmas_clk32k_desc desc; ++}; ++ ++static struct palmas_clks_of_match palmas_of_clk32kg = { ++ .init = { ++ .name = "clk32kg", ++ .ops = &palmas_clks_ops, ++ .flags = CLK_IS_ROOT | CLK_IGNORE_UNUSED, ++ }, ++ .desc = { ++ .clk_name = "clk32kg", ++ .control_reg = PALMAS_CLK32KG_CTRL, ++ .enable_mask = PALMAS_CLK32KG_CTRL_MODE_ACTIVE, ++ .sleep_mask = PALMAS_CLK32KG_CTRL_MODE_SLEEP, ++ .sleep_reqstr_id = PALMAS_EXTERNAL_REQSTR_ID_CLK32KG, ++ .delay = 200, ++ }, ++}; ++ ++static struct palmas_clks_of_match palmas_of_clk32kgaudio = { ++ .init = { ++ .name = "clk32kgaudio", ++ .ops = &palmas_clks_ops, ++ .flags = CLK_IS_ROOT | CLK_IGNORE_UNUSED, ++ }, ++ .desc = { ++ .clk_name = "clk32kgaudio", ++ .control_reg = PALMAS_CLK32KGAUDIO_CTRL, ++ .enable_mask = PALMAS_CLK32KG_CTRL_MODE_ACTIVE, ++ .sleep_mask = PALMAS_CLK32KG_CTRL_MODE_SLEEP, ++ .sleep_reqstr_id = PALMAS_EXTERNAL_REQSTR_ID_CLK32KGAUDIO, ++ .delay = 200, ++ }, ++}; ++ ++static struct of_device_id of_palmas_clks_match_tbl[] = { ++ { .compatible = "ti,palmas-clk32kg", .data = &palmas_of_clk32kg, }, ++ { .compatible = "ti,palmas-clk32kgaudio", .data = &palmas_of_clk32kgaudio, }, ++ {}, ++}; ++MODULE_DEVICE_TABLE(of, of_palmas_clks_match_tbl); ++ ++static void palmas_clks_get_clk_data(struct platform_device *pdev, ++ struct palmas_clock_info *cinfo) ++{ ++ struct device_node *node = pdev->dev.of_node; ++ unsigned int prop; ++ int ret; ++ ++ ret = of_property_read_u32(node, "ti,external-sleep-control", ++ &prop); ++ if (ret) ++ return; ++ ++ switch (prop) { ++ case PALMAS_CLOCK_DT_EXT_CONTROL_ENABLE1: ++ prop = PALMAS_EXT_CONTROL_ENABLE1; ++ break; ++ case PALMAS_CLOCK_DT_EXT_CONTROL_ENABLE2: ++ prop = PALMAS_EXT_CONTROL_ENABLE2; ++ break; ++ case PALMAS_CLOCK_DT_EXT_CONTROL_NSLEEP: ++ prop = PALMAS_EXT_CONTROL_NSLEEP; ++ break; ++ default: ++ dev_warn(&pdev->dev, "%s: Invalid ext control option: %u\n", ++ node->name, prop); ++ prop = 0; ++ break; ++ } ++ cinfo->ext_control_pin = prop; ++} ++ ++static int palmas_clks_init_configure(struct palmas_clock_info *cinfo) ++{ ++ int ret; ++ ++ ret = palmas_update_bits(cinfo->palmas, PALMAS_RESOURCE_BASE, ++ cinfo->clk_desc->control_reg, ++ cinfo->clk_desc->sleep_mask, 0); ++ if (ret < 0) { ++ dev_err(cinfo->dev, "Reg 0x%02x update failed, %d\n", ++ cinfo->clk_desc->control_reg, ret); ++ return ret; ++ } ++ ++ if (cinfo->ext_control_pin) { ++ ret = clk_prepare(cinfo->clk); ++ if (ret < 0) { ++ dev_err(cinfo->dev, "Clock prep failed, %d\n", ret); ++ return ret; ++ } ++ ++ ret = palmas_ext_control_req_config(cinfo->palmas, ++ cinfo->clk_desc->sleep_reqstr_id, ++ cinfo->ext_control_pin, true); ++ if (ret < 0) { ++ dev_err(cinfo->dev, "Ext config for %s failed, %d\n", ++ cinfo->clk_desc->clk_name, ret); ++ return ret; ++ } ++ } ++ ++ return ret; ++} ++static int palmas_clks_probe(struct platform_device *pdev) ++{ ++ struct palmas *palmas = dev_get_drvdata(pdev->dev.parent); ++ struct device_node *node = pdev->dev.of_node; ++ struct palmas_clks_of_match *match_data; ++ const struct of_device_id *match; ++ struct palmas_clock_info *cinfo; ++ struct clk *clk; ++ int ret; ++ ++ match = of_match_device(of_palmas_clks_match_tbl, &pdev->dev); ++ match_data = (struct palmas_clks_of_match *) match->data; ++ ++ cinfo = devm_kzalloc(&pdev->dev, sizeof(*cinfo), GFP_KERNEL); ++ if (!cinfo) ++ return -ENOMEM; ++ ++ palmas_clks_get_clk_data(pdev, cinfo); ++ platform_set_drvdata(pdev, cinfo); ++ ++ cinfo->dev = &pdev->dev; ++ cinfo->palmas = palmas; ++ ++ cinfo->clk_desc = &match_data->desc; ++ cinfo->hw.init = &match_data->init; ++ clk = devm_clk_register(&pdev->dev, &cinfo->hw); ++ if (IS_ERR(clk)) { ++ ret = PTR_ERR(clk); ++ dev_err(&pdev->dev, "Fail to register clock %s, %d\n", ++ match_data->desc.clk_name, ret); ++ return ret; ++ } ++ ++ cinfo->clk = clk; ++ ret = palmas_clks_init_configure(cinfo); ++ if (ret < 0) { ++ dev_err(&pdev->dev, "Clock config failed, %d\n", ret); ++ return ret; ++ } ++ ++ ret = of_clk_add_provider(node, of_clk_src_simple_get, cinfo->clk); ++ if (ret < 0) ++ dev_err(&pdev->dev, "Fail to add clock driver, %d\n", ret); ++ return ret; ++} ++ ++static int palmas_clks_remove(struct platform_device *pdev) ++{ ++ of_clk_del_provider(pdev->dev.of_node); ++ return 0; ++} ++ ++static struct platform_driver palmas_clks_driver = { ++ .driver = { ++ .name = "palmas-clk", ++ .owner = THIS_MODULE, ++ .of_match_table = of_palmas_clks_match_tbl, ++ }, ++ .probe = palmas_clks_probe, ++ .remove = palmas_clks_remove, ++}; ++ ++module_platform_driver(palmas_clks_driver); ++ ++MODULE_DESCRIPTION("Clock driver for Palmas Series Devices"); ++MODULE_ALIAS("platform:palmas-clk"); ++MODULE_AUTHOR("Laxman Dewangan <ldewangan@nvidia.com>"); ++MODULE_LICENSE("GPL v2"); +--- a/drivers/clk/Kconfig ++++ b/drivers/clk/Kconfig +@@ -93,6 +93,13 @@ config CLK_PPC_CORENET + This adds the clock driver support for Freescale PowerPC corenet + platforms using common clock framework. + ++config COMMON_CLK_PALMAS ++ bool "Clock driver for TI Palmas devices" ++ depends on MFD_PALMAS ++ ---help--- ++ This driver supports TI Palmas devices 32KHz output KG and KG_AUDIO ++ using common clock framework. ++ + endmenu + + source "drivers/clk/mvebu/Kconfig" +--- a/drivers/clk/Makefile ++++ b/drivers/clk/Makefile +@@ -32,6 +32,7 @@ obj-$(CONFIG_ARCH_VT8500) += clk-vt8500. + obj-$(CONFIG_ARCH_ZYNQ) += zynq/ + obj-$(CONFIG_ARCH_TEGRA) += tegra/ + obj-$(CONFIG_PLAT_SAMSUNG) += samsung/ ++obj-$(CONFIG_ARCH_OMAP) += ti/ + + obj-$(CONFIG_X86) += x86/ + +@@ -43,3 +44,4 @@ obj-$(CONFIG_COMMON_CLK_SI5351) += clk-s + obj-$(CONFIG_COMMON_CLK_S2MPS11) += clk-s2mps11.o + obj-$(CONFIG_CLK_TWL6040) += clk-twl6040.o + obj-$(CONFIG_CLK_PPC_CORENET) += clk-ppc-corenet.o ++obj-$(CONFIG_COMMON_CLK_PALMAS) += clk-palmas.o +--- /dev/null ++++ b/drivers/clk/ti/apll.c +@@ -0,0 +1,212 @@ ++/* ++ * OMAP APLL clock support ++ * ++ * Copyright (C) 2013 Texas Instruments, Inc. ++ * ++ * 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 "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-provider.h> ++#include <linux/module.h> ++#include <linux/slab.h> ++#include <linux/io.h> ++#include <linux/err.h> ++#include <linux/string.h> ++#include <linux/log2.h> ++#include <linux/of.h> ++#include <linux/of_address.h> ++#include <linux/clk/ti.h> ++#include <linux/delay.h> ++ ++#define APLL_FORCE_LOCK 0x1 ++#define APLL_AUTO_IDLE 0x2 ++#define MAX_APLL_WAIT_TRIES 1000000 ++ ++static int dra7_apll_enable(struct clk_hw *hw) ++{ ++ struct clk_hw_omap *clk = to_clk_hw_omap(hw); ++ int r = 0, i = 0; ++ struct dpll_data *ad; ++ const char *clk_name; ++ u8 state = 1; ++ u32 v; ++ ++ ad = clk->dpll_data; ++ if (!ad) ++ return -EINVAL; ++ ++ clk_name = __clk_get_name(clk->hw.clk); ++ ++ state <<= __ffs(ad->idlest_mask); ++ ++ /* Check is already locked */ ++ if ((readl(ad->idlest_reg) & ad->idlest_mask) == state) ++ return r; ++ ++ v = readl(ad->control_reg); ++ v &= ~ad->enable_mask; ++ v |= APLL_FORCE_LOCK << __ffs(ad->enable_mask); ++ writel(v, ad->control_reg); ++ ++ state <<= __ffs(ad->idlest_mask); ++ ++ while (((readl(ad->idlest_reg) & ad->idlest_mask) != state) && ++ i < MAX_APLL_WAIT_TRIES) { ++ i++; ++ udelay(1); ++ } ++ ++ if (i == MAX_APLL_WAIT_TRIES) { ++ pr_warn("clock: %s failed transition to '%s'\n", ++ clk_name, (state) ? "locked" : "bypassed"); ++ } else { ++ pr_debug("clock: %s transition to '%s' in %d loops\n", ++ clk_name, (state) ? "locked" : "bypassed", i); ++ ++ r = 0; ++ } ++ ++ return r; ++} ++ ++static void dra7_apll_disable(struct clk_hw *hw) ++{ ++ struct clk_hw_omap *clk = to_clk_hw_omap(hw); ++ struct dpll_data *ad; ++ u8 state = 1; ++ u32 v; ++ ++ ad = clk->dpll_data; ++ ++ state <<= __ffs(ad->idlest_mask); ++ ++ v = readl(ad->control_reg); ++ v &= ~ad->enable_mask; ++ v |= APLL_AUTO_IDLE << __ffs(ad->enable_mask); ++ writel(v, ad->control_reg); ++} ++ ++static u8 dra7_init_apll_parent(struct clk_hw *hw) ++{ ++ return 0; ++} ++ ++static const struct clk_ops apll_ck_ops = { ++ .enable = &dra7_apll_enable, ++ .disable = &dra7_apll_disable, ++ .get_parent = &dra7_init_apll_parent, ++}; ++ ++static struct clk *omap_clk_register_apll(struct device *dev, const char *name, ++ const char **parent_names, int num_parents, unsigned long flags, ++ struct dpll_data *dpll_data, const char *clkdm_name, ++ const struct clk_ops *ops) ++{ ++ struct clk *clk; ++ struct clk_init_data init = { 0 }; ++ struct clk_hw_omap *clk_hw; ++ ++ clk_hw = kzalloc(sizeof(*clk_hw), GFP_KERNEL); ++ if (!clk_hw) { ++ pr_err("%s: could not allocate clk_hw_omap\n", __func__); ++ return ERR_PTR(-ENOMEM); ++ } ++ ++ clk_hw->dpll_data = dpll_data; ++ clk_hw->hw.init = &init; ++ ++ init.name = name; ++ init.ops = ops; ++ init.flags = flags; ++ init.parent_names = parent_names; ++ init.num_parents = num_parents; ++ ++ /* register the clock */ ++ clk = clk_register(dev, &clk_hw->hw); ++ ++ return clk; ++} ++ ++void __init of_dra7_apll_setup(struct device_node *node) ++{ ++ const struct clk_ops *ops; ++ struct clk *clk; ++ const char *clk_name = node->name; ++ int num_parents; ++ const char **parent_names = NULL; ++ u8 apll_flags = 0; ++ struct dpll_data *ad; ++ u32 idlest_mask = 0x1; ++ u32 autoidle_mask = 0x3; ++ int i; ++ ++ ops = &apll_ck_ops; ++ ad = kzalloc(sizeof(*ad), GFP_KERNEL); ++ if (!ad) { ++ pr_err("%s: could not allocate dpll_data\n", __func__); ++ return; ++ } ++ ++ of_property_read_string(node, "clock-output-names", &clk_name); ++ ++ num_parents = of_clk_get_parent_count(node); ++ if (num_parents < 1) { ++ pr_err("%s: omap dpll %s must have parent(s)\n", ++ __func__, node->name); ++ goto cleanup; ++ } ++ ++ parent_names = kzalloc(sizeof(char *) * num_parents, GFP_KERNEL); ++ ++ for (i = 0; i < num_parents; i++) ++ parent_names[i] = of_clk_get_parent_name(node, i); ++ ++ ad->clk_ref = of_clk_get(node, 0); ++ ad->clk_bypass = of_clk_get(node, 1); ++ ++ if (IS_ERR(ad->clk_ref)) { ++ pr_err("%s: ti,clk-ref for %s not found\n", __func__, ++ clk_name); ++ goto cleanup; ++ } ++ ++ if (IS_ERR(ad->clk_bypass)) { ++ pr_err("%s: ti,clk-bypass for %s not found\n", __func__, ++ clk_name); ++ goto cleanup; ++ } ++ ++ i = of_property_match_string(node, "reg-names", "control"); ++ if (i >= 0) ++ ad->control_reg = of_iomap(node, i); ++ ++ i = of_property_match_string(node, "reg-names", "idlest"); ++ if (i >= 0) ++ ad->idlest_reg = of_iomap(node, i); ++ ++ ad->idlest_mask = idlest_mask; ++ ad->enable_mask = autoidle_mask; ++ ++ clk = omap_clk_register_apll(NULL, clk_name, parent_names, ++ num_parents, apll_flags, ad, ++ NULL, ops); ++ ++ if (!IS_ERR(clk)) ++ of_clk_add_provider(node, of_clk_src_simple_get, clk); ++ return; ++ ++cleanup: ++ kfree(parent_names); ++ kfree(ad); ++ return; ++} ++CLK_OF_DECLARE(dra7_apll_clock, "ti,dra7-apll-clock", of_dra7_apll_setup); +--- /dev/null ++++ b/drivers/clk/ti/autoidle.c +@@ -0,0 +1,121 @@ ++/* ++ * OMAP clock autoidle support ++ * ++ * Copyright (C) 2013 Texas Instruments, Inc. ++ * ++ * Tero Kristo <t-kristo@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-provider.h> ++#include <linux/slab.h> ++#include <linux/io.h> ++#include <linux/of.h> ++#include <linux/of_address.h> ++ ++struct clk_omap_autoidle { ++ void __iomem *reg; ++ u8 shift; ++ u8 flags; ++ const char *name; ++ struct list_head node; ++}; ++ ++#define AUTOIDLE_LOW 0x1 ++ ++static LIST_HEAD(autoidle_clks); ++ ++static void omap_allow_autoidle(struct clk_omap_autoidle *clk) ++{ ++ u32 val; ++ ++ val = readl(clk->reg); ++ ++ if (clk->flags & AUTOIDLE_LOW) ++ val &= ~(1 << clk->shift); ++ else ++ val |= (1 << clk->shift); ++ ++ writel(val, clk->reg); ++} ++ ++static void omap_deny_autoidle(struct clk_omap_autoidle *clk) ++{ ++ u32 val; ++ ++ val = readl(clk->reg); ++ ++ if (clk->flags & AUTOIDLE_LOW) ++ val |= (1 << clk->shift); ++ else ++ val &= ~(1 << clk->shift); ++ ++ writel(val, clk->reg); ++} ++ ++void of_omap_clk_allow_autoidle_all(void) ++{ ++ struct clk_omap_autoidle *c; ++ ++ list_for_each_entry(c, &autoidle_clks, node) ++ omap_allow_autoidle(c); ++} ++ ++void of_omap_clk_deny_autoidle_all(void) ++{ ++ struct clk_omap_autoidle *c; ++ ++ list_for_each_entry(c, &autoidle_clks, node) ++ omap_deny_autoidle(c); ++} ++ ++static void __init of_omap_autoidle_setup(struct device_node *node) ++{ ++ u32 shift; ++ void __iomem *reg; ++ struct clk_omap_autoidle *clk; ++ ++ if (of_property_read_u32(node, "ti,autoidle-shift", &shift)) ++ return; ++ ++ reg = of_iomap(node, 0); ++ ++ clk = kzalloc(sizeof(*clk), GFP_KERNEL); ++ ++ if (!clk) { ++ pr_err("%s: kzalloc failed\n", __func__); ++ return; ++ } ++ ++ clk->shift = shift; ++ clk->name = node->name; ++ clk->reg = reg; ++ ++ if (of_property_read_bool(node, "ti,autoidle-low")) ++ clk->flags |= AUTOIDLE_LOW; ++ ++ list_add(&clk->node, &autoidle_clks); ++} ++ ++static void __init of_omap_divider_setup(struct device_node *node) ++{ ++ of_divider_clk_setup(node); ++ of_omap_autoidle_setup(node); ++} ++CLK_OF_DECLARE(omap_divider_clock, "ti,divider-clock", of_omap_divider_setup); ++ ++static void __init of_omap_fixed_factor_setup(struct device_node *node) ++{ ++ of_fixed_factor_clk_setup(node); ++ of_omap_autoidle_setup(node); ++} ++CLK_OF_DECLARE(omap_fixed_factor_clock, "ti,fixed-factor-clock", ++ of_omap_fixed_factor_setup); +--- /dev/null ++++ b/drivers/clk/ti/clk-33xx.c +@@ -0,0 +1,163 @@ ++/* ++ * AM33XX Clock init ++ * ++ * Copyright (C) 2013 Texas Instruments, Inc ++ * Tero Kristo (t-kristo@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/kernel.h> ++#include <linux/list.h> ++#include <linux/clk-provider.h> ++#include <linux/clk/ti.h> ++ ++static struct omap_dt_clk am33xx_clks[] = { ++ DT_CLK(NULL, "clk_32768_ck", "clk_32768_ck"), ++ DT_CLK(NULL, "clk_rc32k_ck", "clk_rc32k_ck"), ++ DT_CLK(NULL, "virt_19200000_ck", "virt_19200000_ck"), ++ DT_CLK(NULL, "virt_24000000_ck", "virt_24000000_ck"), ++ DT_CLK(NULL, "virt_25000000_ck", "virt_25000000_ck"), ++ DT_CLK(NULL, "virt_26000000_ck", "virt_26000000_ck"), ++ DT_CLK(NULL, "sys_clkin_ck", "sys_clkin_ck"), ++ DT_CLK(NULL, "tclkin_ck", "tclkin_ck"), ++ DT_CLK(NULL, "dpll_core_ck", "dpll_core_ck"), ++ DT_CLK(NULL, "dpll_core_x2_ck", "dpll_core_x2_ck"), ++ DT_CLK(NULL, "dpll_core_m4_ck", "dpll_core_m4_ck"), ++ DT_CLK(NULL, "dpll_core_m5_ck", "dpll_core_m5_ck"), ++ DT_CLK(NULL, "dpll_core_m6_ck", "dpll_core_m6_ck"), ++ DT_CLK(NULL, "dpll_mpu_ck", "dpll_mpu_ck"), ++ DT_CLK("cpu0", NULL, "dpll_mpu_ck"), ++ DT_CLK(NULL, "dpll_mpu_m2_ck", "dpll_mpu_m2_ck"), ++ DT_CLK(NULL, "dpll_ddr_ck", "dpll_ddr_ck"), ++ DT_CLK(NULL, "dpll_ddr_m2_ck", "dpll_ddr_m2_ck"), ++ DT_CLK(NULL, "dpll_ddr_m2_div2_ck", "dpll_ddr_m2_div2_ck"), ++ DT_CLK(NULL, "dpll_disp_ck", "dpll_disp_ck"), ++ DT_CLK(NULL, "dpll_disp_m2_ck", "dpll_disp_m2_ck"), ++ DT_CLK(NULL, "dpll_per_ck", "dpll_per_ck"), ++ DT_CLK(NULL, "dpll_per_m2_ck", "dpll_per_m2_ck"), ++ DT_CLK(NULL, "dpll_per_m2_div4_wkupdm_ck", "dpll_per_m2_div4_wkupdm_ck"), ++ DT_CLK(NULL, "dpll_per_m2_div4_ck", "dpll_per_m2_div4_ck"), ++ DT_CLK(NULL, "adc_tsc_fck", "adc_tsc_fck"), ++ DT_CLK(NULL, "cefuse_fck", "cefuse_fck"), ++ DT_CLK(NULL, "clkdiv32k_ck", "clkdiv32k_ck"), ++ DT_CLK(NULL, "clkdiv32k_ick", "clkdiv32k_ick"), ++ DT_CLK(NULL, "dcan0_fck", "dcan0_fck"), ++ DT_CLK("481cc000.d_can", NULL, "dcan0_fck"), ++ DT_CLK(NULL, "dcan1_fck", "dcan1_fck"), ++ DT_CLK("481d0000.d_can", NULL, "dcan1_fck"), ++ DT_CLK(NULL, "pruss_ocp_gclk", "pruss_ocp_gclk"), ++ DT_CLK(NULL, "mcasp0_fck", "mcasp0_fck"), ++ DT_CLK(NULL, "mcasp1_fck", "mcasp1_fck"), ++ DT_CLK(NULL, "mmu_fck", "mmu_fck"), ++ DT_CLK(NULL, "smartreflex0_fck", "smartreflex0_fck"), ++ DT_CLK(NULL, "smartreflex1_fck", "smartreflex1_fck"), ++ DT_CLK(NULL, "sha0_fck", "sha0_fck"), ++ DT_CLK(NULL, "rng_fck", "rng_fck"), ++ DT_CLK(NULL, "aes0_fck", "aes0_fck"), ++ DT_CLK(NULL, "timer1_fck", "timer1_fck"), ++ DT_CLK(NULL, "timer2_fck", "timer2_fck"), ++ DT_CLK(NULL, "timer3_fck", "timer3_fck"), ++ DT_CLK(NULL, "timer4_fck", "timer4_fck"), ++ DT_CLK(NULL, "timer5_fck", "timer5_fck"), ++ DT_CLK(NULL, "timer6_fck", "timer6_fck"), ++ DT_CLK(NULL, "timer7_fck", "timer7_fck"), ++ DT_CLK(NULL, "usbotg_fck", "usbotg_fck"), ++ DT_CLK(NULL, "ieee5000_fck", "ieee5000_fck"), ++ DT_CLK(NULL, "wdt1_fck", "wdt1_fck"), ++ DT_CLK(NULL, "l4_rtc_gclk", "l4_rtc_gclk"), ++ DT_CLK(NULL, "l3_gclk", "l3_gclk"), ++ DT_CLK(NULL, "dpll_core_m4_div2_ck", "dpll_core_m4_div2_ck"), ++ DT_CLK(NULL, "l4hs_gclk", "l4hs_gclk"), ++ DT_CLK(NULL, "l3s_gclk", "l3s_gclk"), ++ DT_CLK(NULL, "l4fw_gclk", "l4fw_gclk"), ++ DT_CLK(NULL, "l4ls_gclk", "l4ls_gclk"), ++ DT_CLK(NULL, "clk_24mhz", "clk_24mhz"), ++ DT_CLK(NULL, "sysclk_div_ck", "sysclk_div_ck"), ++ DT_CLK(NULL, "cpsw_125mhz_gclk", "cpsw_125mhz_gclk"), ++ DT_CLK(NULL, "cpsw_cpts_rft_clk", "cpsw_cpts_rft_clk"), ++ DT_CLK(NULL, "gpio0_dbclk_mux_ck", "gpio0_dbclk_mux_ck"), ++ DT_CLK(NULL, "gpio0_dbclk", "gpio0_dbclk"), ++ DT_CLK(NULL, "gpio1_dbclk", "gpio1_dbclk"), ++ DT_CLK(NULL, "gpio2_dbclk", "gpio2_dbclk"), ++ DT_CLK(NULL, "gpio3_dbclk", "gpio3_dbclk"), ++ DT_CLK(NULL, "lcd_gclk", "lcd_gclk"), ++ DT_CLK(NULL, "mmc_clk", "mmc_clk"), ++ DT_CLK(NULL, "gfx_fclk_clksel_ck", "gfx_fclk_clksel_ck"), ++ DT_CLK(NULL, "gfx_fck_div_ck", "gfx_fck_div_ck"), ++ DT_CLK(NULL, "sysclkout_pre_ck", "sysclkout_pre_ck"), ++ DT_CLK(NULL, "clkout2_div_ck", "clkout2_div_ck"), ++ DT_CLK(NULL, "timer_32k_ck", "clkdiv32k_ick"), ++ DT_CLK(NULL, "timer_sys_ck", "sys_clkin_ck"), ++ DT_CLK(NULL, "dbg_sysclk_ck", "dbg_sysclk_ck"), ++ DT_CLK(NULL, "dbg_clka_ck", "dbg_clka_ck"), ++ DT_CLK(NULL, "stm_pmd_clock_mux_ck", "stm_pmd_clock_mux_ck"), ++ DT_CLK(NULL, "trace_pmd_clk_mux_ck", "trace_pmd_clk_mux_ck"), ++ DT_CLK(NULL, "stm_clk_div_ck", "stm_clk_div_ck"), ++ DT_CLK(NULL, "trace_clk_div_ck", "trace_clk_div_ck"), ++ DT_CLK(NULL, "clkout2_ck", "clkout2_ck"), ++ DT_CLK("48300200.ehrpwm", "tbclk", "ehrpwm0_tbclk"), ++ DT_CLK("48302200.ehrpwm", "tbclk", "ehrpwm1_tbclk"), ++ DT_CLK("48304200.ehrpwm", "tbclk", "ehrpwm2_tbclk"), ++ { .node_name = NULL }, ++}; ++ ++static const char *enable_init_clks[] = { ++ "dpll_ddr_m2_ck", ++ "dpll_mpu_m2_ck", ++ "l3_gclk", ++ "l4hs_gclk", ++ "l4fw_gclk", ++ "l4ls_gclk", ++ /* Required for external peripherals like, Audio codecs */ ++ "clkout2_ck", ++}; ++ ++int __init am33xx_clk_init(void) ++{ ++ struct clk *clk1, *clk2; ++ ++ of_clk_init(NULL); ++ ++ omap_dt_clocks_register(am33xx_clks); ++ ++ omap2_clk_disable_autoidle_all(); ++ ++ omap2_clk_enable_init_clocks(enable_init_clks, ++ ARRAY_SIZE(enable_init_clks)); ++ ++ /* TRM ERRATA: Timer 3 & 6 default parent (TCLKIN) may not be always ++ * physically present, in such a case HWMOD enabling of ++ * clock would be failure with default parent. And timer ++ * probe thinks clock is already enabled, this leads to ++ * crash upon accessing timer 3 & 6 registers in probe. ++ * Fix by setting parent of both these timers to master ++ * oscillator clock. ++ */ ++ ++ clk1 = clk_get_sys(NULL, "sys_clkin_ck"); ++ clk2 = clk_get_sys(NULL, "timer3_fck"); ++ clk_set_parent(clk2, clk1); ++ ++ clk2 = clk_get_sys(NULL, "timer6_fck"); ++ clk_set_parent(clk2, clk1); ++ /* ++ * The On-Chip 32K RC Osc clock is not an accurate clock-source as per ++ * the design/spec, so as a result, for example, timer which supposed ++ * to get expired @60Sec, but will expire somewhere ~@40Sec, which is ++ * not expected by any use-case, so change WDT1 clock source to PRCM ++ * 32KHz clock. ++ */ ++ clk1 = clk_get_sys(NULL, "wdt1_fck"); ++ clk2 = clk_get_sys(NULL, "clkdiv32k_ick"); ++ clk_set_parent(clk1, clk2); ++ ++ return 0; ++} +--- /dev/null ++++ b/drivers/clk/ti/clk-3xxx.c +@@ -0,0 +1,388 @@ ++/* ++ * OMAP3 Clock init ++ * ++ * Copyright (C) 2013 Texas Instruments, Inc ++ * Tero Kristo (t-kristo@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/kernel.h> ++#include <linux/list.h> ++#include <linux/clk-provider.h> ++#include <linux/clk/ti.h> ++ ++ ++static struct omap_dt_clk omap3xxx_clks[] = { ++ DT_CLK(NULL, "apb_pclk", "dummy_apb_pclk"), ++ DT_CLK(NULL, "omap_32k_fck", "omap_32k_fck"), ++ DT_CLK(NULL, "virt_12m_ck", "virt_12m_ck"), ++ DT_CLK(NULL, "virt_13m_ck", "virt_13m_ck"), ++ DT_CLK(NULL, "virt_19200000_ck", "virt_19200000_ck"), ++ DT_CLK(NULL, "virt_26000000_ck", "virt_26000000_ck"), ++ DT_CLK(NULL, "virt_38_4m_ck", "virt_38_4m_ck"), ++ DT_CLK(NULL, "osc_sys_ck", "osc_sys_ck"), ++ DT_CLK("twl", "fck", "osc_sys_ck"), ++ DT_CLK(NULL, "sys_ck", "sys_ck"), ++ DT_CLK(NULL, "omap_96m_alwon_fck", "omap_96m_alwon_fck"), ++ DT_CLK("etb", "emu_core_alwon_ck", "emu_core_alwon_ck"), ++ DT_CLK(NULL, "sys_altclk", "sys_altclk"), ++ DT_CLK(NULL, "mcbsp_clks", "mcbsp_clks"), ++ DT_CLK(NULL, "sys_clkout1", "sys_clkout1"), ++ DT_CLK(NULL, "dpll1_ck", "dpll1_ck"), ++ DT_CLK(NULL, "dpll1_x2_ck", "dpll1_x2_ck"), ++ DT_CLK(NULL, "dpll1_x2m2_ck", "dpll1_x2m2_ck"), ++ DT_CLK(NULL, "dpll3_ck", "dpll3_ck"), ++ DT_CLK(NULL, "core_ck", "core_ck"), ++ DT_CLK(NULL, "dpll3_x2_ck", "dpll3_x2_ck"), ++ DT_CLK(NULL, "dpll3_m2_ck", "dpll3_m2_ck"), ++ DT_CLK(NULL, "dpll3_m2x2_ck", "dpll3_m2x2_ck"), ++ DT_CLK(NULL, "dpll3_m3_ck", "dpll3_m3_ck"), ++ DT_CLK(NULL, "dpll3_m3x2_ck", "dpll3_m3x2_ck"), ++ DT_CLK(NULL, "dpll4_ck", "dpll4_ck"), ++ DT_CLK(NULL, "dpll4_x2_ck", "dpll4_x2_ck"), ++ DT_CLK(NULL, "omap_96m_fck", "omap_96m_fck"), ++ DT_CLK(NULL, "cm_96m_fck", "cm_96m_fck"), ++ DT_CLK(NULL, "omap_54m_fck", "omap_54m_fck"), ++ DT_CLK(NULL, "omap_48m_fck", "omap_48m_fck"), ++ DT_CLK(NULL, "omap_12m_fck", "omap_12m_fck"), ++ DT_CLK(NULL, "dpll4_m2_ck", "dpll4_m2_ck"), ++ DT_CLK(NULL, "dpll4_m2x2_ck", "dpll4_m2x2_ck"), ++ DT_CLK(NULL, "dpll4_m3_ck", "dpll4_m3_ck"), ++ DT_CLK(NULL, "dpll4_m3x2_ck", "dpll4_m3x2_ck"), ++ DT_CLK(NULL, "dpll4_m4_ck", "dpll4_m4_ck"), ++ DT_CLK(NULL, "dpll4_m4x2_ck", "dpll4_m4x2_ck"), ++ DT_CLK(NULL, "dpll4_m5_ck", "dpll4_m5_ck"), ++ DT_CLK(NULL, "dpll4_m5x2_ck", "dpll4_m5x2_ck"), ++ DT_CLK(NULL, "dpll4_m6_ck", "dpll4_m6_ck"), ++ DT_CLK(NULL, "dpll4_m6x2_ck", "dpll4_m6x2_ck"), ++ DT_CLK("etb", "emu_per_alwon_ck", "emu_per_alwon_ck"), ++ DT_CLK(NULL, "clkout2_src_ck", "clkout2_src_ck"), ++ DT_CLK(NULL, "sys_clkout2", "sys_clkout2"), ++ DT_CLK(NULL, "corex2_fck", "corex2_fck"), ++ DT_CLK(NULL, "dpll1_fck", "dpll1_fck"), ++ DT_CLK(NULL, "mpu_ck", "mpu_ck"), ++ DT_CLK(NULL, "arm_fck", "arm_fck"), ++ DT_CLK("etb", "emu_mpu_alwon_ck", "emu_mpu_alwon_ck"), ++ DT_CLK(NULL, "l3_ick", "l3_ick"), ++ DT_CLK(NULL, "l4_ick", "l4_ick"), ++ DT_CLK(NULL, "rm_ick", "rm_ick"), ++ DT_CLK(NULL, "gpt10_fck", "gpt10_fck"), ++ DT_CLK(NULL, "gpt11_fck", "gpt11_fck"), ++ DT_CLK(NULL, "core_96m_fck", "core_96m_fck"), ++ DT_CLK(NULL, "mmchs2_fck", "mmchs2_fck"), ++ DT_CLK(NULL, "mmchs1_fck", "mmchs1_fck"), ++ DT_CLK(NULL, "i2c3_fck", "i2c3_fck"), ++ DT_CLK(NULL, "i2c2_fck", "i2c2_fck"), ++ DT_CLK(NULL, "i2c1_fck", "i2c1_fck"), ++ DT_CLK(NULL, "mcbsp5_fck", "mcbsp5_fck"), ++ DT_CLK(NULL, "mcbsp1_fck", "mcbsp1_fck"), ++ DT_CLK(NULL, "core_48m_fck", "core_48m_fck"), ++ DT_CLK(NULL, "mcspi4_fck", "mcspi4_fck"), ++ DT_CLK(NULL, "mcspi3_fck", "mcspi3_fck"), ++ DT_CLK(NULL, "mcspi2_fck", "mcspi2_fck"), ++ DT_CLK(NULL, "mcspi1_fck", "mcspi1_fck"), ++ DT_CLK(NULL, "uart2_fck", "uart2_fck"), ++ DT_CLK(NULL, "uart1_fck", "uart1_fck"), ++ DT_CLK(NULL, "core_12m_fck", "core_12m_fck"), ++ DT_CLK("omap_hdq.0", "fck", "hdq_fck"), ++ DT_CLK(NULL, "hdq_fck", "hdq_fck"), ++ DT_CLK(NULL, "core_l3_ick", "core_l3_ick"), ++ DT_CLK(NULL, "sdrc_ick", "sdrc_ick"), ++ DT_CLK(NULL, "gpmc_fck", "gpmc_fck"), ++ DT_CLK(NULL, "core_l4_ick", "core_l4_ick"), ++ DT_CLK("omap_hsmmc.1", "ick", "mmchs2_ick"), ++ DT_CLK("omap_hsmmc.0", "ick", "mmchs1_ick"), ++ DT_CLK(NULL, "mmchs2_ick", "mmchs2_ick"), ++ DT_CLK(NULL, "mmchs1_ick", "mmchs1_ick"), ++ DT_CLK("omap_hdq.0", "ick", "hdq_ick"), ++ DT_CLK(NULL, "hdq_ick", "hdq_ick"), ++ DT_CLK("omap2_mcspi.4", "ick", "mcspi4_ick"), ++ DT_CLK("omap2_mcspi.3", "ick", "mcspi3_ick"), ++ DT_CLK("omap2_mcspi.2", "ick", "mcspi2_ick"), ++ DT_CLK("omap2_mcspi.1", "ick", "mcspi1_ick"), ++ DT_CLK(NULL, "mcspi4_ick", "mcspi4_ick"), ++ DT_CLK(NULL, "mcspi3_ick", "mcspi3_ick"), ++ DT_CLK(NULL, "mcspi2_ick", "mcspi2_ick"), ++ DT_CLK(NULL, "mcspi1_ick", "mcspi1_ick"), ++ DT_CLK("omap_i2c.3", "ick", "i2c3_ick"), ++ DT_CLK("omap_i2c.2", "ick", "i2c2_ick"), ++ DT_CLK("omap_i2c.1", "ick", "i2c1_ick"), ++ DT_CLK(NULL, "i2c3_ick", "i2c3_ick"), ++ DT_CLK(NULL, "i2c2_ick", "i2c2_ick"), ++ DT_CLK(NULL, "i2c1_ick", "i2c1_ick"), ++ DT_CLK(NULL, "uart2_ick", "uart2_ick"), ++ DT_CLK(NULL, "uart1_ick", "uart1_ick"), ++ DT_CLK(NULL, "gpt11_ick", "gpt11_ick"), ++ DT_CLK(NULL, "gpt10_ick", "gpt10_ick"), ++ DT_CLK("omap-mcbsp.5", "ick", "mcbsp5_ick"), ++ DT_CLK("omap-mcbsp.1", "ick", "mcbsp1_ick"), ++ DT_CLK(NULL, "mcbsp5_ick", "mcbsp5_ick"), ++ DT_CLK(NULL, "mcbsp1_ick", "mcbsp1_ick"), ++ DT_CLK(NULL, "omapctrl_ick", "omapctrl_ick"), ++ DT_CLK(NULL, "dss_tv_fck", "dss_tv_fck"), ++ DT_CLK(NULL, "dss_96m_fck", "dss_96m_fck"), ++ DT_CLK(NULL, "dss2_alwon_fck", "dss2_alwon_fck"), ++ DT_CLK(NULL, "gpt1_fck", "gpt1_fck"), ++ DT_CLK(NULL, "aes2_ick", "aes2_ick"), ++ DT_CLK(NULL, "wkup_32k_fck", "wkup_32k_fck"), ++ DT_CLK(NULL, "gpio1_dbck", "gpio1_dbck"), ++ DT_CLK(NULL, "sha12_ick", "sha12_ick"), ++ DT_CLK(NULL, "wdt2_fck", "wdt2_fck"), ++ DT_CLK("omap_wdt", "ick", "wdt2_ick"), ++ DT_CLK(NULL, "wdt2_ick", "wdt2_ick"), ++ DT_CLK(NULL, "wdt1_ick", "wdt1_ick"), ++ DT_CLK(NULL, "gpio1_ick", "gpio1_ick"), ++ DT_CLK(NULL, "omap_32ksync_ick", "omap_32ksync_ick"), ++ DT_CLK(NULL, "gpt12_ick", "gpt12_ick"), ++ DT_CLK(NULL, "gpt1_ick", "gpt1_ick"), ++ DT_CLK(NULL, "per_96m_fck", "per_96m_fck"), ++ DT_CLK(NULL, "per_48m_fck", "per_48m_fck"), ++ DT_CLK(NULL, "uart3_fck", "uart3_fck"), ++ DT_CLK(NULL, "gpt2_fck", "gpt2_fck"), ++ DT_CLK(NULL, "gpt3_fck", "gpt3_fck"), ++ DT_CLK(NULL, "gpt4_fck", "gpt4_fck"), ++ DT_CLK(NULL, "gpt5_fck", "gpt5_fck"), ++ DT_CLK(NULL, "gpt6_fck", "gpt6_fck"), ++ DT_CLK(NULL, "gpt7_fck", "gpt7_fck"), ++ DT_CLK(NULL, "gpt8_fck", "gpt8_fck"), ++ DT_CLK(NULL, "gpt9_fck", "gpt9_fck"), ++ DT_CLK(NULL, "per_32k_alwon_fck", "per_32k_alwon_fck"), ++ DT_CLK(NULL, "gpio6_dbck", "gpio6_dbck"), ++ DT_CLK(NULL, "gpio5_dbck", "gpio5_dbck"), ++ DT_CLK(NULL, "gpio4_dbck", "gpio4_dbck"), ++ DT_CLK(NULL, "gpio3_dbck", "gpio3_dbck"), ++ DT_CLK(NULL, "gpio2_dbck", "gpio2_dbck"), ++ DT_CLK(NULL, "wdt3_fck", "wdt3_fck"), ++ DT_CLK(NULL, "per_l4_ick", "per_l4_ick"), ++ DT_CLK(NULL, "gpio6_ick", "gpio6_ick"), ++ DT_CLK(NULL, "gpio5_ick", "gpio5_ick"), ++ DT_CLK(NULL, "gpio4_ick", "gpio4_ick"), ++ DT_CLK(NULL, "gpio3_ick", "gpio3_ick"), ++ DT_CLK(NULL, "gpio2_ick", "gpio2_ick"), ++ DT_CLK(NULL, "wdt3_ick", "wdt3_ick"), ++ DT_CLK(NULL, "uart3_ick", "uart3_ick"), ++ DT_CLK(NULL, "uart4_ick", "uart4_ick"), ++ DT_CLK(NULL, "gpt9_ick", "gpt9_ick"), ++ DT_CLK(NULL, "gpt8_ick", "gpt8_ick"), ++ DT_CLK(NULL, "gpt7_ick", "gpt7_ick"), ++ DT_CLK(NULL, "gpt6_ick", "gpt6_ick"), ++ DT_CLK(NULL, "gpt5_ick", "gpt5_ick"), ++ DT_CLK(NULL, "gpt4_ick", "gpt4_ick"), ++ DT_CLK(NULL, "gpt3_ick", "gpt3_ick"), ++ DT_CLK(NULL, "gpt2_ick", "gpt2_ick"), ++ DT_CLK("omap-mcbsp.2", "ick", "mcbsp2_ick"), ++ DT_CLK("omap-mcbsp.3", "ick", "mcbsp3_ick"), ++ DT_CLK("omap-mcbsp.4", "ick", "mcbsp4_ick"), ++ DT_CLK(NULL, "mcbsp4_ick", "mcbsp2_ick"), ++ DT_CLK(NULL, "mcbsp3_ick", "mcbsp3_ick"), ++ DT_CLK(NULL, "mcbsp2_ick", "mcbsp4_ick"), ++ DT_CLK(NULL, "mcbsp2_fck", "mcbsp2_fck"), ++ DT_CLK(NULL, "mcbsp3_fck", "mcbsp3_fck"), ++ DT_CLK(NULL, "mcbsp4_fck", "mcbsp4_fck"), ++ DT_CLK("etb", "emu_src_ck", "emu_src_ck"), ++ DT_CLK(NULL, "emu_src_ck", "emu_src_ck"), ++ DT_CLK(NULL, "pclk_fck", "pclk_fck"), ++ DT_CLK(NULL, "pclkx2_fck", "pclkx2_fck"), ++ DT_CLK(NULL, "atclk_fck", "atclk_fck"), ++ DT_CLK(NULL, "traceclk_src_fck", "traceclk_src_fck"), ++ DT_CLK(NULL, "traceclk_fck", "traceclk_fck"), ++ DT_CLK(NULL, "secure_32k_fck", "secure_32k_fck"), ++ DT_CLK(NULL, "gpt12_fck", "gpt12_fck"), ++ DT_CLK(NULL, "wdt1_fck", "wdt1_fck"), ++ DT_CLK(NULL, "timer_32k_ck", "omap_32k_fck"), ++ DT_CLK(NULL, "timer_sys_ck", "sys_ck"), ++ DT_CLK(NULL, "cpufreq_ck", "dpll1_ck"), ++ { .node_name = NULL }, ++}; ++ ++static struct omap_dt_clk omap34xx_omap36xx_clks[] = { ++ DT_CLK(NULL, "aes1_ick", "aes1_ick"), ++ DT_CLK("omap_rng", "ick", "rng_ick"), ++ DT_CLK(NULL, "sha11_ick", "sha11_ick"), ++ DT_CLK(NULL, "des1_ick", "des1_ick"), ++ DT_CLK(NULL, "cam_mclk", "cam_mclk"), ++ DT_CLK(NULL, "cam_ick", "cam_ick"), ++ DT_CLK(NULL, "csi2_96m_fck", "csi2_96m_fck"), ++ DT_CLK(NULL, "security_l3_ick", "security_l3_ick"), ++ DT_CLK(NULL, "pka_ick", "pka_ick"), ++ DT_CLK(NULL, "icr_ick", "icr_ick"), ++ DT_CLK("omap-aes", "ick", "aes2_ick"), ++ DT_CLK("omap-sham", "ick", "sha12_ick"), ++ DT_CLK(NULL, "des2_ick", "des2_ick"), ++ DT_CLK(NULL, "mspro_ick", "mspro_ick"), ++ DT_CLK(NULL, "mailboxes_ick", "mailboxes_ick"), ++ DT_CLK(NULL, "ssi_l4_ick", "ssi_l4_ick"), ++ DT_CLK(NULL, "sr1_fck", "sr1_fck"), ++ DT_CLK(NULL, "sr2_fck", "sr2_fck"), ++ DT_CLK(NULL, "sr_l4_ick", "sr_l4_ick"), ++ DT_CLK(NULL, "security_l4_ick2", "security_l4_ick2"), ++ DT_CLK(NULL, "wkup_l4_ick", "wkup_l4_ick"), ++ DT_CLK(NULL, "dpll2_fck", "dpll2_fck"), ++ DT_CLK(NULL, "iva2_ck", "iva2_ck"), ++ DT_CLK(NULL, "modem_fck", "modem_fck"), ++ DT_CLK(NULL, "sad2d_ick", "sad2d_ick"), ++ DT_CLK(NULL, "mad2d_ick", "mad2d_ick"), ++ DT_CLK(NULL, "mspro_fck", "mspro_fck"), ++ DT_CLK(NULL, "dpll2_ck", "dpll2_ck"), ++ DT_CLK(NULL, "dpll2_m2_ck", "dpll2_m2_ck"), ++ { .node_name = NULL }, ++}; ++ ++static struct omap_dt_clk omap36xx_omap3430es2plus_clks[] = { ++ DT_CLK(NULL, "ssi_ssr_fck", "ssi_ssr_fck_3430es2"), ++ DT_CLK(NULL, "ssi_sst_fck", "ssi_sst_fck_3430es2"), ++ DT_CLK("musb-omap2430", "ick", "hsotgusb_ick_3430es2"), ++ DT_CLK(NULL, "hsotgusb_ick", "hsotgusb_ick_3430es2"), ++ DT_CLK(NULL, "ssi_ick", "ssi_ick_3430es2"), ++ DT_CLK(NULL, "usim_fck", "usim_fck"), ++ DT_CLK(NULL, "usim_ick", "usim_ick"), ++ { .node_name = NULL }, ++}; ++ ++static struct omap_dt_clk omap3430es1_clks[] = { ++ DT_CLK(NULL, "gfx_l3_ck", "gfx_l3_ck"), ++ DT_CLK(NULL, "gfx_l3_fck", "gfx_l3_fck"), ++ DT_CLK(NULL, "gfx_l3_ick", "gfx_l3_ick"), ++ DT_CLK(NULL, "gfx_cg1_ck", "gfx_cg1_ck"), ++ DT_CLK(NULL, "gfx_cg2_ck", "gfx_cg2_ck"), ++ DT_CLK(NULL, "d2d_26m_fck", "d2d_26m_fck"), ++ DT_CLK(NULL, "fshostusb_fck", "fshostusb_fck"), ++ DT_CLK(NULL, "ssi_ssr_fck", "ssi_ssr_fck_3430es1"), ++ DT_CLK(NULL, "ssi_sst_fck", "ssi_sst_fck_3430es1"), ++ DT_CLK("musb-omap2430", "ick", "hsotgusb_ick_3430es1"), ++ DT_CLK(NULL, "hsotgusb_ick", "hsotgusb_ick_3430es1"), ++ DT_CLK(NULL, "fac_ick", "fac_ick"), ++ DT_CLK(NULL, "ssi_ick", "ssi_ick_3430es1"), ++ DT_CLK(NULL, "usb_l4_ick", "usb_l4_ick"), ++ DT_CLK(NULL, "dss1_alwon_fck", "dss1_alwon_fck_3430es1"), ++ DT_CLK("omapdss_dss", "ick", "dss_ick_3430es1"), ++ DT_CLK(NULL, "dss_ick", "dss_ick_3430es1"), ++ { .node_name = NULL }, ++}; ++ ++static struct omap_dt_clk omap36xx_am35xx_omap3430es2plus_clks[] = { ++ DT_CLK(NULL, "virt_16_8m_ck", "virt_16_8m_ck"), ++ DT_CLK(NULL, "dpll5_ck", "dpll5_ck"), ++ DT_CLK(NULL, "dpll5_m2_ck", "dpll5_m2_ck"), ++ DT_CLK(NULL, "sgx_fck", "sgx_fck"), ++ DT_CLK(NULL, "sgx_ick", "sgx_ick"), ++ DT_CLK(NULL, "cpefuse_fck", "cpefuse_fck"), ++ DT_CLK(NULL, "ts_fck", "ts_fck"), ++ DT_CLK(NULL, "usbtll_fck", "usbtll_fck"), ++ DT_CLK(NULL, "usbtll_ick", "usbtll_ick"), ++ DT_CLK("omap_hsmmc.2", "ick", "mmchs3_ick"), ++ DT_CLK(NULL, "mmchs3_ick", "mmchs3_ick"), ++ DT_CLK(NULL, "mmchs3_fck", "mmchs3_fck"), ++ DT_CLK(NULL, "dss1_alwon_fck", "dss1_alwon_fck_3430es2"), ++ DT_CLK("omapdss_dss", "ick", "dss_ick_3430es2"), ++ DT_CLK(NULL, "dss_ick", "dss_ick_3430es2"), ++ DT_CLK(NULL, "usbhost_120m_fck", "usbhost_120m_fck"), ++ DT_CLK(NULL, "usbhost_48m_fck", "usbhost_48m_fck"), ++ DT_CLK(NULL, "usbhost_ick", "usbhost_ick"), ++ { .node_name = NULL }, ++}; ++ ++static struct omap_dt_clk am35xx_clks[] = { ++ DT_CLK(NULL, "ipss_ick", "ipss_ick"), ++ DT_CLK(NULL, "rmii_ck", "rmii_ck"), ++ DT_CLK(NULL, "pclk_ck", "pclk_ck"), ++ DT_CLK(NULL, "emac_ick", "emac_ick"), ++ DT_CLK(NULL, "emac_fck", "emac_fck"), ++ DT_CLK("davinci_emac.0", NULL, "emac_ick"), ++ DT_CLK("davinci_mdio.0", NULL, "emac_fck"), ++ DT_CLK("vpfe-capture", "master", "vpfe_ick"), ++ DT_CLK("vpfe-capture", "slave", "vpfe_fck"), ++ DT_CLK(NULL, "hsotgusb_ick", "hsotgusb_ick_am35xx"), ++ DT_CLK(NULL, "hsotgusb_fck", "hsotgusb_fck_am35xx"), ++ DT_CLK(NULL, "hecc_ck", "hecc_ck"), ++ DT_CLK(NULL, "uart4_ick", "uart4_ick_am35xx"), ++ DT_CLK(NULL, "uart4_fck", "uart4_fck_am35xx"), ++ { .node_name = NULL }, ++}; ++ ++static const char *enable_init_clks[] = { ++ "sdrc_ick", ++ "gpmc_fck", ++ "omapctrl_ick", ++}; ++ ++enum { ++ OMAP3_SOC_AM35XX, ++ OMAP3_SOC_OMAP3430_ES1, ++ OMAP3_SOC_OMAP3430_ES2_PLUS, ++ OMAP3_SOC_OMAP3630, ++ OMAP3_SOC_TI81XX, ++}; ++ ++static int __init omap3xxx_clk_init(int soc_type) ++{ ++ of_clk_init(NULL); ++ ++ if (soc_type == OMAP3_SOC_AM35XX || soc_type == OMAP3_SOC_OMAP3630 || ++ soc_type == OMAP3_SOC_OMAP3430_ES1 || ++ soc_type == OMAP3_SOC_OMAP3430_ES2_PLUS) ++ omap_dt_clocks_register(omap3xxx_clks); ++ ++ if (soc_type == OMAP3_SOC_AM35XX) ++ omap_dt_clocks_register(am35xx_clks); ++ ++ if (soc_type == OMAP3_SOC_OMAP3630 || soc_type == OMAP3_SOC_AM35XX || ++ soc_type == OMAP3_SOC_OMAP3430_ES2_PLUS) ++ omap_dt_clocks_register(omap36xx_am35xx_omap3430es2plus_clks); ++ ++ if (soc_type == OMAP3_SOC_OMAP3430_ES1) ++ omap_dt_clocks_register(omap3430es1_clks); ++ ++ if (soc_type == OMAP3_SOC_OMAP3430_ES2_PLUS || ++ soc_type == OMAP3_SOC_OMAP3630) ++ omap_dt_clocks_register(omap36xx_omap3430es2plus_clks); ++ ++ if (soc_type == OMAP3_SOC_OMAP3430_ES1 || ++ soc_type == OMAP3_SOC_OMAP3430_ES2_PLUS || ++ soc_type == OMAP3_SOC_OMAP3630) ++ omap_dt_clocks_register(omap34xx_omap36xx_clks); ++ ++ omap2_clk_disable_autoidle_all(); ++ ++ omap2_clk_enable_init_clocks(enable_init_clks, ++ ARRAY_SIZE(enable_init_clks)); ++ ++ pr_info("Clocking rate (Crystal/Core/MPU): %ld.%01ld/%ld/%ld MHz\n", ++ (clk_get_rate(clk_get_sys(NULL, "osc_sys_ck")) / 1000000), ++ (clk_get_rate(clk_get_sys(NULL, "osc_sys_ck")) / 100000) % 10, ++ (clk_get_rate(clk_get_sys(NULL, "core_ck")) / 1000000), ++ (clk_get_rate(clk_get_sys(NULL, "arm_fck")) / 1000000)); ++ ++ if (soc_type != OMAP3_SOC_TI81XX && soc_type != OMAP3_SOC_OMAP3430_ES1) ++ omap3_clk_lock_dpll5(); ++ ++ return 0; ++} ++ ++int __init omap3430_clk_init(void) ++{ ++ return omap3xxx_clk_init(OMAP3_SOC_OMAP3430_ES2_PLUS); ++} ++ ++int __init omap3630_clk_init(void) ++{ ++ return omap3xxx_clk_init(OMAP3_SOC_OMAP3630); ++} ++ ++int __init am35xx_clk_init(void) ++{ ++ return omap3xxx_clk_init(OMAP3_SOC_AM35XX); ++} ++ ++int __init ti81xx_clk_init(void) ++{ ++ return omap3xxx_clk_init(OMAP3_SOC_TI81XX); ++} +--- /dev/null ++++ b/drivers/clk/ti/clk-43xx.c +@@ -0,0 +1,136 @@ ++/* ++ * AM43XX Clock init ++ * ++ * Copyright (C) 2013 Texas Instruments, Inc ++ * Tero Kristo (t-kristo@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/kernel.h> ++#include <linux/list.h> ++#include <linux/clk-provider.h> ++#include <linux/clk/ti.h> ++ ++ ++static struct omap_dt_clk am43xx_clks[] = { ++ DT_CLK(NULL, "clk_32768_ck", "clk_32768_ck"), ++ DT_CLK(NULL, "clk_rc32k_ck", "clk_rc32k_ck"), ++ DT_CLK(NULL, "virt_19200000_ck", "virt_19200000_ck"), ++ DT_CLK(NULL, "virt_24000000_ck", "virt_24000000_ck"), ++ DT_CLK(NULL, "virt_25000000_ck", "virt_25000000_ck"), ++ DT_CLK(NULL, "virt_26000000_ck", "virt_26000000_ck"), ++ DT_CLK(NULL, "sys_clkin_ck", "sys_clkin_ck"), ++ DT_CLK(NULL, "tclkin_ck", "tclkin_ck"), ++ DT_CLK(NULL, "dpll_core_ck", "dpll_core_ck"), ++ DT_CLK(NULL, "dpll_core_x2_ck", "dpll_core_x2_ck"), ++ DT_CLK(NULL, "dpll_core_m4_ck", "dpll_core_m4_ck"), ++ DT_CLK(NULL, "dpll_core_m5_ck", "dpll_core_m5_ck"), ++ DT_CLK(NULL, "dpll_core_m6_ck", "dpll_core_m6_ck"), ++ DT_CLK(NULL, "dpll_mpu_ck", "dpll_mpu_ck"), ++ DT_CLK(NULL, "dpll_mpu_m2_ck", "dpll_mpu_m2_ck"), ++ DT_CLK(NULL, "dpll_ddr_ck", "dpll_ddr_ck"), ++ DT_CLK(NULL, "dpll_ddr_m2_ck", "dpll_ddr_m2_ck"), ++ DT_CLK(NULL, "dpll_disp_ck", "dpll_disp_ck"), ++ DT_CLK(NULL, "dpll_disp_m2_ck", "dpll_disp_m2_ck"), ++ DT_CLK(NULL, "dpll_per_ck", "dpll_per_ck"), ++ DT_CLK(NULL, "dpll_per_m2_ck", "dpll_per_m2_ck"), ++ DT_CLK(NULL, "dpll_per_m2_div4_wkupdm_ck", "dpll_per_m2_div4_wkupdm_ck"), ++ DT_CLK(NULL, "dpll_per_m2_div4_ck", "dpll_per_m2_div4_ck"), ++ DT_CLK(NULL, "adc_tsc_fck", "adc_tsc_fck"), ++ DT_CLK(NULL, "clkdiv32k_ck", "clkdiv32k_ck"), ++ DT_CLK(NULL, "clkdiv32k_ick", "clkdiv32k_ick"), ++ DT_CLK(NULL, "dcan0_fck", "dcan0_fck"), ++ DT_CLK(NULL, "dcan1_fck", "dcan1_fck"), ++ DT_CLK(NULL, "pruss_ocp_gclk", "pruss_ocp_gclk"), ++ DT_CLK(NULL, "mcasp0_fck", "mcasp0_fck"), ++ DT_CLK(NULL, "mcasp1_fck", "mcasp1_fck"), ++ DT_CLK(NULL, "smartreflex0_fck", "smartreflex0_fck"), ++ DT_CLK(NULL, "smartreflex1_fck", "smartreflex1_fck"), ++ DT_CLK(NULL, "sha0_fck", "sha0_fck"), ++ DT_CLK(NULL, "rng_fck", "rng_fck"), ++ DT_CLK(NULL, "aes0_fck", "aes0_fck"), ++ DT_CLK(NULL, "timer1_fck", "timer1_fck"), ++ DT_CLK(NULL, "timer2_fck", "timer2_fck"), ++ DT_CLK(NULL, "timer3_fck", "timer3_fck"), ++ DT_CLK(NULL, "timer4_fck", "timer4_fck"), ++ DT_CLK(NULL, "timer5_fck", "timer5_fck"), ++ DT_CLK(NULL, "timer6_fck", "timer6_fck"), ++ DT_CLK(NULL, "timer7_fck", "timer7_fck"), ++ DT_CLK(NULL, "wdt1_fck", "wdt1_fck"), ++ DT_CLK(NULL, "l3_gclk", "l3_gclk"), ++ DT_CLK(NULL, "dpll_core_m4_div2_ck", "dpll_core_m4_div2_ck"), ++ DT_CLK(NULL, "l4hs_gclk", "l4hs_gclk"), ++ DT_CLK(NULL, "l3s_gclk", "l3s_gclk"), ++ DT_CLK(NULL, "l4ls_gclk", "l4ls_gclk"), ++ DT_CLK(NULL, "clk_24mhz", "clk_24mhz"), ++ DT_CLK(NULL, "cpsw_125mhz_gclk", "cpsw_125mhz_gclk"), ++ DT_CLK(NULL, "cpsw_cpts_rft_clk", "cpsw_cpts_rft_clk"), ++ DT_CLK(NULL, "gpio0_dbclk_mux_ck", "gpio0_dbclk_mux_ck"), ++ DT_CLK(NULL, "gpio0_dbclk", "gpio0_dbclk"), ++ DT_CLK(NULL, "gpio1_dbclk", "gpio1_dbclk"), ++ DT_CLK(NULL, "gpio2_dbclk", "gpio2_dbclk"), ++ DT_CLK(NULL, "gpio3_dbclk", "gpio3_dbclk"), ++ DT_CLK(NULL, "gpio4_dbclk", "gpio4_dbclk"), ++ DT_CLK(NULL, "gpio5_dbclk", "gpio5_dbclk"), ++ DT_CLK(NULL, "mmc_clk", "mmc_clk"), ++ DT_CLK(NULL, "gfx_fclk_clksel_ck", "gfx_fclk_clksel_ck"), ++ DT_CLK(NULL, "gfx_fck_div_ck", "gfx_fck_div_ck"), ++ DT_CLK(NULL, "timer_32k_ck", "clkdiv32k_ick"), ++ DT_CLK(NULL, "timer_sys_ck", "sys_clkin_ck"), ++ DT_CLK(NULL, "sysclk_div", "sysclk_div"), ++ DT_CLK(NULL, "disp_clk", "disp_clk"), ++ DT_CLK(NULL, "clk_32k_mosc_ck", "clk_32k_mosc_ck"), ++ DT_CLK(NULL, "clk_32k_tpm_ck", "clk_32k_tpm_ck"), ++ DT_CLK(NULL, "dpll_extdev_ck", "dpll_extdev_ck"), ++ DT_CLK(NULL, "dpll_extdev_m2_ck", "dpll_extdev_m2_ck"), ++ DT_CLK(NULL, "mux_synctimer32k_ck", "mux_synctimer32k_ck"), ++ DT_CLK(NULL, "synctimer_32kclk", "synctimer_32kclk"), ++ DT_CLK(NULL, "timer8_fck", "timer8_fck"), ++ DT_CLK(NULL, "timer9_fck", "timer9_fck"), ++ DT_CLK(NULL, "timer10_fck", "timer10_fck"), ++ DT_CLK(NULL, "timer11_fck", "timer11_fck"), ++ DT_CLK(NULL, "cpsw_50m_clkdiv", "cpsw_50m_clkdiv"), ++ DT_CLK(NULL, "cpsw_5m_clkdiv", "cpsw_5m_clkdiv"), ++ DT_CLK(NULL, "dpll_ddr_x2_ck", "dpll_ddr_x2_ck"), ++ DT_CLK(NULL, "dpll_ddr_m4_ck", "dpll_ddr_m4_ck"), ++ DT_CLK(NULL, "dpll_per_clkdcoldo", "dpll_per_clkdcoldo"), ++ DT_CLK(NULL, "dll_aging_clk_div", "dll_aging_clk_div"), ++ DT_CLK(NULL, "div_core_25m_ck", "div_core_25m_ck"), ++ DT_CLK(NULL, "func_12m_clk", "func_12m_clk"), ++ DT_CLK(NULL, "vtp_clk_div", "vtp_clk_div"), ++ DT_CLK(NULL, "usbphy_32khz_clkmux", "usbphy_32khz_clkmux"), ++ { .node_name = NULL }, ++}; ++ ++int __init am43xx_clk_init(void) ++{ ++ struct clk *clk1, *clk2; ++ ++ of_clk_init(NULL); ++ ++ omap_dt_clocks_register(am43xx_clks); ++ ++ omap2_clk_disable_autoidle_all(); ++ ++ /* ++ * The external 32KHz RTC clock source may not always be available ++ * on board like in the case of ePOS EVM. By default sync timer, which ++ * is used as clock source, feeds of this clock. This is a problem. ++ * Change the parent of sync timer to PER PLL 32KHz clock instead ++ * which is always present. This has a side effect that in low power ++ * modes, sync timer will stop. ++ */ ++ clk1 = clk_get_sys(NULL, "mux_synctimer32k_ck"); ++ clk2 = clk_get_sys(NULL, "clkdiv32k_ick"); ++ clk_set_parent(clk1, clk2); ++ ++ return 0; ++} +--- /dev/null ++++ b/drivers/clk/ti/clk-44xx.c +@@ -0,0 +1,307 @@ ++/* ++ * OMAP4 Clock data ++ * ++ * Copyright (C) 2009-2012 Texas Instruments, Inc. ++ * Copyright (C) 2009-2010 Nokia Corporation ++ * ++ * Paul Walmsley (paul@pwsan.com) ++ * Rajendra Nayak (rnayak@ti.com) ++ * Benoit Cousson (b-cousson@ti.com) ++ * Mike Turquette (mturquette@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. ++ * ++ * XXX Some of the ES1 clocks have been removed/changed; once support ++ * is added for discriminating clocks by ES level, these should be added back ++ * in. ++ * ++ * XXX All of the remaining MODULEMODE clock nodes should be removed ++ * once the drivers are updated to use pm_runtime or to use the appropriate ++ * upstream clock node for rate/parent selection. ++ */ ++ ++#include <linux/kernel.h> ++#include <linux/list.h> ++#include <linux/clk-private.h> ++#include <linux/clkdev.h> ++#include <linux/clk/ti.h> ++ ++/* ++ * OMAP4 ABE DPLL default frequency. In OMAP4460 TRM version V, section ++ * "3.6.3.2.3 CM1_ABE Clock Generator" states that the "DPLL_ABE_X2_CLK ++ * must be set to 196.608 MHz" and hence, the DPLL locked frequency is ++ * half of this value. ++ */ ++#define OMAP4_DPLL_ABE_DEFFREQ 98304000 ++ ++/* ++ * OMAP4 USB DPLL default frequency. In OMAP4430 TRM version V, section ++ * "3.6.3.9.5 DPLL_USB Preferred Settings" shows that the preferred ++ * locked frequency for the USB DPLL is 960MHz. ++ */ ++#define OMAP4_DPLL_USB_DEFFREQ 960000000 ++ ++static struct omap_dt_clk omap44xx_clks[] = { ++ DT_CLK(NULL, "extalt_clkin_ck", "extalt_clkin_ck"), ++ DT_CLK(NULL, "pad_clks_src_ck", "pad_clks_src_ck"), ++ DT_CLK(NULL, "pad_clks_ck", "pad_clks_ck"), ++ DT_CLK(NULL, "pad_slimbus_core_clks_ck", "pad_slimbus_core_clks_ck"), ++ DT_CLK(NULL, "secure_32k_clk_src_ck", "secure_32k_clk_src_ck"), ++ DT_CLK(NULL, "slimbus_src_clk", "slimbus_src_clk"), ++ DT_CLK(NULL, "slimbus_clk", "slimbus_clk"), ++ DT_CLK(NULL, "sys_32k_ck", "sys_32k_ck"), ++ DT_CLK(NULL, "virt_12000000_ck", "virt_12000000_ck"), ++ DT_CLK(NULL, "virt_13000000_ck", "virt_13000000_ck"), ++ DT_CLK(NULL, "virt_16800000_ck", "virt_16800000_ck"), ++ DT_CLK(NULL, "virt_19200000_ck", "virt_19200000_ck"), ++ DT_CLK(NULL, "virt_26000000_ck", "virt_26000000_ck"), ++ DT_CLK(NULL, "virt_27000000_ck", "virt_27000000_ck"), ++ DT_CLK(NULL, "virt_38400000_ck", "virt_38400000_ck"), ++ DT_CLK(NULL, "sys_clkin_ck", "sys_clkin_ck"), ++ DT_CLK(NULL, "tie_low_clock_ck", "tie_low_clock_ck"), ++ DT_CLK(NULL, "utmi_phy_clkout_ck", "utmi_phy_clkout_ck"), ++ DT_CLK(NULL, "xclk60mhsp1_ck", "xclk60mhsp1_ck"), ++ DT_CLK(NULL, "xclk60mhsp2_ck", "xclk60mhsp2_ck"), ++ DT_CLK(NULL, "xclk60motg_ck", "xclk60motg_ck"), ++ DT_CLK(NULL, "abe_dpll_bypass_clk_mux_ck", "abe_dpll_bypass_clk_mux_ck"), ++ DT_CLK(NULL, "abe_dpll_refclk_mux_ck", "abe_dpll_refclk_mux_ck"), ++ DT_CLK(NULL, "dpll_abe_ck", "dpll_abe_ck"), ++ DT_CLK(NULL, "dpll_abe_x2_ck", "dpll_abe_x2_ck"), ++ DT_CLK(NULL, "dpll_abe_m2x2_ck", "dpll_abe_m2x2_ck"), ++ DT_CLK(NULL, "abe_24m_fclk", "abe_24m_fclk"), ++ DT_CLK(NULL, "abe_clk", "abe_clk"), ++ DT_CLK(NULL, "aess_fclk", "aess_fclk"), ++ DT_CLK(NULL, "dpll_abe_m3x2_ck", "dpll_abe_m3x2_ck"), ++ DT_CLK(NULL, "core_hsd_byp_clk_mux_ck", "core_hsd_byp_clk_mux_ck"), ++ DT_CLK(NULL, "dpll_core_ck", "dpll_core_ck"), ++ DT_CLK(NULL, "dpll_core_x2_ck", "dpll_core_x2_ck"), ++ DT_CLK(NULL, "dpll_core_m6x2_ck", "dpll_core_m6x2_ck"), ++ DT_CLK(NULL, "dbgclk_mux_ck", "dbgclk_mux_ck"), ++ DT_CLK(NULL, "dpll_core_m2_ck", "dpll_core_m2_ck"), ++ DT_CLK(NULL, "ddrphy_ck", "ddrphy_ck"), ++ DT_CLK(NULL, "dpll_core_m5x2_ck", "dpll_core_m5x2_ck"), ++ DT_CLK(NULL, "div_core_ck", "div_core_ck"), ++ DT_CLK(NULL, "div_iva_hs_clk", "div_iva_hs_clk"), ++ DT_CLK(NULL, "div_mpu_hs_clk", "div_mpu_hs_clk"), ++ DT_CLK(NULL, "dpll_core_m4x2_ck", "dpll_core_m4x2_ck"), ++ DT_CLK(NULL, "dll_clk_div_ck", "dll_clk_div_ck"), ++ DT_CLK(NULL, "dpll_abe_m2_ck", "dpll_abe_m2_ck"), ++ DT_CLK(NULL, "dpll_core_m3x2_ck", "dpll_core_m3x2_ck"), ++ DT_CLK(NULL, "dpll_core_m7x2_ck", "dpll_core_m7x2_ck"), ++ DT_CLK(NULL, "iva_hsd_byp_clk_mux_ck", "iva_hsd_byp_clk_mux_ck"), ++ DT_CLK(NULL, "dpll_iva_ck", "dpll_iva_ck"), ++ DT_CLK(NULL, "dpll_iva_x2_ck", "dpll_iva_x2_ck"), ++ DT_CLK(NULL, "dpll_iva_m4x2_ck", "dpll_iva_m4x2_ck"), ++ DT_CLK(NULL, "dpll_iva_m5x2_ck", "dpll_iva_m5x2_ck"), ++ DT_CLK(NULL, "dpll_mpu_ck", "dpll_mpu_ck"), ++ DT_CLK(NULL, "dpll_mpu_m2_ck", "dpll_mpu_m2_ck"), ++ DT_CLK(NULL, "per_hs_clk_div_ck", "per_hs_clk_div_ck"), ++ DT_CLK(NULL, "per_hsd_byp_clk_mux_ck", "per_hsd_byp_clk_mux_ck"), ++ DT_CLK(NULL, "dpll_per_ck", "dpll_per_ck"), ++ DT_CLK(NULL, "dpll_per_m2_ck", "dpll_per_m2_ck"), ++ DT_CLK(NULL, "dpll_per_x2_ck", "dpll_per_x2_ck"), ++ DT_CLK(NULL, "dpll_per_m2x2_ck", "dpll_per_m2x2_ck"), ++ DT_CLK(NULL, "dpll_per_m3x2_ck", "dpll_per_m3x2_ck"), ++ DT_CLK(NULL, "dpll_per_m4x2_ck", "dpll_per_m4x2_ck"), ++ DT_CLK(NULL, "dpll_per_m5x2_ck", "dpll_per_m5x2_ck"), ++ DT_CLK(NULL, "dpll_per_m6x2_ck", "dpll_per_m6x2_ck"), ++ DT_CLK(NULL, "dpll_per_m7x2_ck", "dpll_per_m7x2_ck"), ++ DT_CLK(NULL, "usb_hs_clk_div_ck", "usb_hs_clk_div_ck"), ++ DT_CLK(NULL, "dpll_usb_ck", "dpll_usb_ck"), ++ DT_CLK(NULL, "dpll_usb_clkdcoldo_ck", "dpll_usb_clkdcoldo_ck"), ++ DT_CLK(NULL, "dpll_usb_m2_ck", "dpll_usb_m2_ck"), ++ DT_CLK(NULL, "ducati_clk_mux_ck", "ducati_clk_mux_ck"), ++ DT_CLK(NULL, "func_12m_fclk", "func_12m_fclk"), ++ DT_CLK(NULL, "func_24m_clk", "func_24m_clk"), ++ DT_CLK(NULL, "func_24mc_fclk", "func_24mc_fclk"), ++ DT_CLK(NULL, "func_48m_fclk", "func_48m_fclk"), ++ DT_CLK(NULL, "func_48mc_fclk", "func_48mc_fclk"), ++ DT_CLK(NULL, "func_64m_fclk", "func_64m_fclk"), ++ DT_CLK(NULL, "func_96m_fclk", "func_96m_fclk"), ++ DT_CLK(NULL, "init_60m_fclk", "init_60m_fclk"), ++ DT_CLK(NULL, "l3_div_ck", "l3_div_ck"), ++ DT_CLK(NULL, "l4_div_ck", "l4_div_ck"), ++ DT_CLK(NULL, "lp_clk_div_ck", "lp_clk_div_ck"), ++ DT_CLK(NULL, "l4_wkup_clk_mux_ck", "l4_wkup_clk_mux_ck"), ++ DT_CLK("smp_twd", NULL, "mpu_periphclk"), ++ DT_CLK(NULL, "ocp_abe_iclk", "ocp_abe_iclk"), ++ DT_CLK(NULL, "per_abe_24m_fclk", "per_abe_24m_fclk"), ++ DT_CLK(NULL, "per_abe_nc_fclk", "per_abe_nc_fclk"), ++ DT_CLK(NULL, "syc_clk_div_ck", "syc_clk_div_ck"), ++ DT_CLK(NULL, "aes1_fck", "aes1_fck"), ++ DT_CLK(NULL, "aes2_fck", "aes2_fck"), ++ DT_CLK(NULL, "dmic_sync_mux_ck", "dmic_sync_mux_ck"), ++ DT_CLK(NULL, "func_dmic_abe_gfclk", "func_dmic_abe_gfclk"), ++ DT_CLK(NULL, "dss_sys_clk", "dss_sys_clk"), ++ DT_CLK(NULL, "dss_tv_clk", "dss_tv_clk"), ++ DT_CLK(NULL, "dss_dss_clk", "dss_dss_clk"), ++ DT_CLK(NULL, "dss_48mhz_clk", "dss_48mhz_clk"), ++ DT_CLK(NULL, "dss_fck", "dss_fck"), ++ DT_CLK("omapdss_dss", "ick", "dss_fck"), ++ DT_CLK(NULL, "fdif_fck", "fdif_fck"), ++ DT_CLK(NULL, "gpio1_dbclk", "gpio1_dbclk"), ++ DT_CLK(NULL, "gpio2_dbclk", "gpio2_dbclk"), ++ DT_CLK(NULL, "gpio3_dbclk", "gpio3_dbclk"), ++ DT_CLK(NULL, "gpio4_dbclk", "gpio4_dbclk"), ++ DT_CLK(NULL, "gpio5_dbclk", "gpio5_dbclk"), ++ DT_CLK(NULL, "gpio6_dbclk", "gpio6_dbclk"), ++ DT_CLK(NULL, "sgx_clk_mux", "sgx_clk_mux"), ++ DT_CLK(NULL, "hsi_fck", "hsi_fck"), ++ DT_CLK(NULL, "iss_ctrlclk", "iss_ctrlclk"), ++ DT_CLK(NULL, "mcasp_sync_mux_ck", "mcasp_sync_mux_ck"), ++ DT_CLK(NULL, "func_mcasp_abe_gfclk", "func_mcasp_abe_gfclk"), ++ DT_CLK(NULL, "mcbsp1_sync_mux_ck", "mcbsp1_sync_mux_ck"), ++ DT_CLK(NULL, "func_mcbsp1_gfclk", "func_mcbsp1_gfclk"), ++ DT_CLK(NULL, "mcbsp2_sync_mux_ck", "mcbsp2_sync_mux_ck"), ++ DT_CLK(NULL, "func_mcbsp2_gfclk", "func_mcbsp2_gfclk"), ++ DT_CLK(NULL, "mcbsp3_sync_mux_ck", "mcbsp3_sync_mux_ck"), ++ DT_CLK(NULL, "func_mcbsp3_gfclk", "func_mcbsp3_gfclk"), ++ DT_CLK(NULL, "mcbsp4_sync_mux_ck", "mcbsp4_sync_mux_ck"), ++ DT_CLK(NULL, "per_mcbsp4_gfclk", "per_mcbsp4_gfclk"), ++ DT_CLK(NULL, "hsmmc1_fclk", "hsmmc1_fclk"), ++ DT_CLK(NULL, "hsmmc2_fclk", "hsmmc2_fclk"), ++ DT_CLK(NULL, "ocp2scp_usb_phy_phy_48m", "ocp2scp_usb_phy_phy_48m"), ++ DT_CLK(NULL, "sha2md5_fck", "sha2md5_fck"), ++ DT_CLK(NULL, "slimbus1_fclk_1", "slimbus1_fclk_1"), ++ DT_CLK(NULL, "slimbus1_fclk_0", "slimbus1_fclk_0"), ++ DT_CLK(NULL, "slimbus1_fclk_2", "slimbus1_fclk_2"), ++ DT_CLK(NULL, "slimbus1_slimbus_clk", "slimbus1_slimbus_clk"), ++ DT_CLK(NULL, "slimbus2_fclk_1", "slimbus2_fclk_1"), ++ DT_CLK(NULL, "slimbus2_fclk_0", "slimbus2_fclk_0"), ++ DT_CLK(NULL, "slimbus2_slimbus_clk", "slimbus2_slimbus_clk"), ++ DT_CLK(NULL, "smartreflex_core_fck", "smartreflex_core_fck"), ++ DT_CLK(NULL, "smartreflex_iva_fck", "smartreflex_iva_fck"), ++ DT_CLK(NULL, "smartreflex_mpu_fck", "smartreflex_mpu_fck"), ++ DT_CLK(NULL, "dmt1_clk_mux", "dmt1_clk_mux"), ++ DT_CLK(NULL, "cm2_dm10_mux", "cm2_dm10_mux"), ++ DT_CLK(NULL, "cm2_dm11_mux", "cm2_dm11_mux"), ++ DT_CLK(NULL, "cm2_dm2_mux", "cm2_dm2_mux"), ++ DT_CLK(NULL, "cm2_dm3_mux", "cm2_dm3_mux"), ++ DT_CLK(NULL, "cm2_dm4_mux", "cm2_dm4_mux"), ++ DT_CLK(NULL, "timer5_sync_mux", "timer5_sync_mux"), ++ DT_CLK(NULL, "timer6_sync_mux", "timer6_sync_mux"), ++ DT_CLK(NULL, "timer7_sync_mux", "timer7_sync_mux"), ++ DT_CLK(NULL, "timer8_sync_mux", "timer8_sync_mux"), ++ DT_CLK(NULL, "cm2_dm9_mux", "cm2_dm9_mux"), ++ DT_CLK(NULL, "usb_host_fs_fck", "usb_host_fs_fck"), ++ DT_CLK("usbhs_omap", "fs_fck", "usb_host_fs_fck"), ++ DT_CLK(NULL, "utmi_p1_gfclk", "utmi_p1_gfclk"), ++ DT_CLK(NULL, "usb_host_hs_utmi_p1_clk", "usb_host_hs_utmi_p1_clk"), ++ DT_CLK(NULL, "utmi_p2_gfclk", "utmi_p2_gfclk"), ++ DT_CLK(NULL, "usb_host_hs_utmi_p2_clk", "usb_host_hs_utmi_p2_clk"), ++ DT_CLK(NULL, "usb_host_hs_utmi_p3_clk", "usb_host_hs_utmi_p3_clk"), ++ DT_CLK(NULL, "usb_host_hs_hsic480m_p1_clk", "usb_host_hs_hsic480m_p1_clk"), ++ DT_CLK(NULL, "usb_host_hs_hsic60m_p1_clk", "usb_host_hs_hsic60m_p1_clk"), ++ DT_CLK(NULL, "usb_host_hs_hsic60m_p2_clk", "usb_host_hs_hsic60m_p2_clk"), ++ DT_CLK(NULL, "usb_host_hs_hsic480m_p2_clk", "usb_host_hs_hsic480m_p2_clk"), ++ DT_CLK(NULL, "usb_host_hs_func48mclk", "usb_host_hs_func48mclk"), ++ DT_CLK(NULL, "usb_host_hs_fck", "usb_host_hs_fck"), ++ DT_CLK("usbhs_omap", "hs_fck", "usb_host_hs_fck"), ++ DT_CLK(NULL, "otg_60m_gfclk", "otg_60m_gfclk"), ++ DT_CLK(NULL, "usb_otg_hs_xclk", "usb_otg_hs_xclk"), ++ DT_CLK(NULL, "usb_otg_hs_ick", "usb_otg_hs_ick"), ++ DT_CLK("musb-omap2430", "ick", "usb_otg_hs_ick"), ++ DT_CLK(NULL, "usb_phy_cm_clk32k", "usb_phy_cm_clk32k"), ++ DT_CLK(NULL, "usb_tll_hs_usb_ch2_clk", "usb_tll_hs_usb_ch2_clk"), ++ DT_CLK(NULL, "usb_tll_hs_usb_ch0_clk", "usb_tll_hs_usb_ch0_clk"), ++ DT_CLK(NULL, "usb_tll_hs_usb_ch1_clk", "usb_tll_hs_usb_ch1_clk"), ++ DT_CLK(NULL, "usb_tll_hs_ick", "usb_tll_hs_ick"), ++ DT_CLK("usbhs_omap", "usbtll_ick", "usb_tll_hs_ick"), ++ DT_CLK("usbhs_tll", "usbtll_ick", "usb_tll_hs_ick"), ++ DT_CLK(NULL, "usim_ck", "usim_ck"), ++ DT_CLK(NULL, "usim_fclk", "usim_fclk"), ++ DT_CLK(NULL, "pmd_stm_clock_mux_ck", "pmd_stm_clock_mux_ck"), ++ DT_CLK(NULL, "pmd_trace_clk_mux_ck", "pmd_trace_clk_mux_ck"), ++ DT_CLK(NULL, "stm_clk_div_ck", "stm_clk_div_ck"), ++ DT_CLK(NULL, "trace_clk_div_ck", "trace_clk_div_ck"), ++ DT_CLK(NULL, "auxclk0_src_ck", "auxclk0_src_ck"), ++ DT_CLK(NULL, "auxclk0_ck", "auxclk0_ck"), ++ DT_CLK(NULL, "auxclkreq0_ck", "auxclkreq0_ck"), ++ DT_CLK(NULL, "auxclk1_src_ck", "auxclk1_src_ck"), ++ DT_CLK(NULL, "auxclk1_ck", "auxclk1_ck"), ++ DT_CLK(NULL, "auxclkreq1_ck", "auxclkreq1_ck"), ++ DT_CLK(NULL, "auxclk2_src_ck", "auxclk2_src_ck"), ++ DT_CLK(NULL, "auxclk2_ck", "auxclk2_ck"), ++ DT_CLK(NULL, "auxclkreq2_ck", "auxclkreq2_ck"), ++ DT_CLK(NULL, "auxclk3_src_ck", "auxclk3_src_ck"), ++ DT_CLK(NULL, "auxclk3_ck", "auxclk3_ck"), ++ DT_CLK(NULL, "auxclkreq3_ck", "auxclkreq3_ck"), ++ DT_CLK(NULL, "auxclk4_src_ck", "auxclk4_src_ck"), ++ DT_CLK(NULL, "auxclk4_ck", "auxclk4_ck"), ++ DT_CLK(NULL, "auxclkreq4_ck", "auxclkreq4_ck"), ++ DT_CLK(NULL, "auxclk5_src_ck", "auxclk5_src_ck"), ++ DT_CLK(NULL, "auxclk5_ck", "auxclk5_ck"), ++ DT_CLK(NULL, "auxclkreq5_ck", "auxclkreq5_ck"), ++ DT_CLK(NULL, "timer_32k_ck", "sys_32k_ck"), ++ DT_CLK("omap_timer.1", "timer_sys_ck", "sys_clkin_ck"), ++ DT_CLK("omap_timer.2", "timer_sys_ck", "sys_clkin_ck"), ++ DT_CLK("omap_timer.3", "timer_sys_ck", "sys_clkin_ck"), ++ DT_CLK("omap_timer.4", "timer_sys_ck", "sys_clkin_ck"), ++ DT_CLK("omap_timer.9", "timer_sys_ck", "sys_clkin_ck"), ++ DT_CLK("omap_timer.10", "timer_sys_ck", "sys_clkin_ck"), ++ DT_CLK("omap_timer.11", "timer_sys_ck", "sys_clkin_ck"), ++ DT_CLK("omap_timer.5", "timer_sys_ck", "syc_clk_div_ck"), ++ DT_CLK("omap_timer.6", "timer_sys_ck", "syc_clk_div_ck"), ++ DT_CLK("omap_timer.7", "timer_sys_ck", "syc_clk_div_ck"), ++ DT_CLK("omap_timer.8", "timer_sys_ck", "syc_clk_div_ck"), ++ DT_CLK("4a318000.timer", "timer_sys_ck", "sys_clkin_ck"), ++ DT_CLK("48032000.timer", "timer_sys_ck", "sys_clkin_ck"), ++ DT_CLK("48034000.timer", "timer_sys_ck", "sys_clkin_ck"), ++ DT_CLK("48036000.timer", "timer_sys_ck", "sys_clkin_ck"), ++ DT_CLK("4803e000.timer", "timer_sys_ck", "sys_clkin_ck"), ++ DT_CLK("48086000.timer", "timer_sys_ck", "sys_clkin_ck"), ++ DT_CLK("48088000.timer", "timer_sys_ck", "sys_clkin_ck"), ++ DT_CLK("40138000.timer", "timer_sys_ck", "syc_clk_div_ck"), ++ DT_CLK("4013a000.timer", "timer_sys_ck", "syc_clk_div_ck"), ++ DT_CLK("4013c000.timer", "timer_sys_ck", "syc_clk_div_ck"), ++ DT_CLK("4013e000.timer", "timer_sys_ck", "syc_clk_div_ck"), ++ DT_CLK(NULL, "cpufreq_ck", "dpll_mpu_ck"), ++ DT_CLK(NULL, "bandgap_fclk", "bandgap_fclk"), ++ DT_CLK(NULL, "div_ts_ck", "div_ts_ck"), ++ DT_CLK(NULL, "bandgap_ts_fclk", "bandgap_ts_fclk"), ++ { .node_name = NULL }, ++}; ++ ++int __init omap4xxx_clk_init(void) ++{ ++ int rc; ++ struct clk *abe_dpll_ref, *abe_dpll, *sys_32k_ck, *usb_dpll; ++ ++ of_clk_init(NULL); ++ ++ omap_dt_clocks_register(omap44xx_clks); ++ ++ omap2_clk_disable_autoidle_all(); ++ ++ /* ++ * A set rate of ABE DPLL inturn triggers a set rate of USB DPLL ++ * when its in bypass. So always lock USB before ABE DPLL. ++ */ ++ /* ++ * Lock USB DPLL on OMAP4 devices so that the L3INIT power ++ * domain can transition to retention state when not in use. ++ */ ++ usb_dpll = clk_get_sys(NULL, "dpll_usb_ck"); ++ rc = clk_set_rate(usb_dpll, OMAP4_DPLL_USB_DEFFREQ); ++ if (rc) ++ pr_err("%s: failed to configure USB DPLL!\n", __func__); ++ ++ /* ++ * On OMAP4460 the ABE DPLL fails to turn on if in idle low-power ++ * state when turning the ABE clock domain. Workaround this by ++ * locking the ABE DPLL on boot. ++ * Lock the ABE DPLL in any case to avoid issues with audio. ++ */ ++ abe_dpll_ref = clk_get_sys(NULL, "abe_dpll_refclk_mux_ck"); ++ sys_32k_ck = clk_get_sys(NULL, "sys_32k_ck"); ++ rc = clk_set_parent(abe_dpll_ref, sys_32k_ck); ++ abe_dpll = clk_get_sys(NULL, "dpll_abe_ck"); ++ if (!rc) ++ rc = clk_set_rate(abe_dpll, OMAP4_DPLL_ABE_DEFFREQ); ++ if (rc) ++ pr_err("%s: failed to configure ABE DPLL!\n", __func__); ++ ++ return 0; ++} +--- /dev/null ++++ b/drivers/clk/ti/clk-54xx.c +@@ -0,0 +1,231 @@ ++/* ++ * OMAP5 Clock init ++ * ++ * Copyright (C) 2013 Texas Instruments, Inc. ++ * ++ * Tero Kristo (t-kristo@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/list.h> ++#include <linux/clk-private.h> ++#include <linux/clkdev.h> ++#include <linux/io.h> ++#include <linux/clk/ti.h> ++ ++#define OMAP5_DPLL_ABE_DEFFREQ 98304000 ++ ++/* ++ * OMAP543x TRM, section "3.6.3.9.5 DPLL_USB Preferred Settings" ++ * states it must be at 960MHz ++ */ ++#define OMAP5_DPLL_USB_DEFFREQ 960000000 ++ ++static struct omap_dt_clk omap54xx_clks[] = { ++ DT_CLK(NULL, "pad_clks_src_ck", "pad_clks_src_ck"), ++ DT_CLK(NULL, "pad_clks_ck", "pad_clks_ck"), ++ DT_CLK(NULL, "secure_32k_clk_src_ck", "secure_32k_clk_src_ck"), ++ DT_CLK(NULL, "slimbus_src_clk", "slimbus_src_clk"), ++ DT_CLK(NULL, "slimbus_clk", "slimbus_clk"), ++ DT_CLK(NULL, "sys_32k_ck", "sys_32k_ck"), ++ DT_CLK(NULL, "virt_12000000_ck", "virt_12000000_ck"), ++ DT_CLK(NULL, "virt_13000000_ck", "virt_13000000_ck"), ++ DT_CLK(NULL, "virt_16800000_ck", "virt_16800000_ck"), ++ DT_CLK(NULL, "virt_19200000_ck", "virt_19200000_ck"), ++ DT_CLK(NULL, "virt_26000000_ck", "virt_26000000_ck"), ++ DT_CLK(NULL, "virt_27000000_ck", "virt_27000000_ck"), ++ DT_CLK(NULL, "virt_38400000_ck", "virt_38400000_ck"), ++ DT_CLK(NULL, "sys_clkin", "sys_clkin"), ++ DT_CLK(NULL, "xclk60mhsp1_ck", "xclk60mhsp1_ck"), ++ DT_CLK(NULL, "xclk60mhsp2_ck", "xclk60mhsp2_ck"), ++ DT_CLK(NULL, "abe_dpll_bypass_clk_mux", "abe_dpll_bypass_clk_mux"), ++ DT_CLK(NULL, "abe_dpll_clk_mux", "abe_dpll_clk_mux"), ++ DT_CLK(NULL, "dpll_abe_ck", "dpll_abe_ck"), ++ DT_CLK(NULL, "dpll_abe_x2_ck", "dpll_abe_x2_ck"), ++ DT_CLK(NULL, "dpll_abe_m2x2_ck", "dpll_abe_m2x2_ck"), ++ DT_CLK(NULL, "abe_24m_fclk", "abe_24m_fclk"), ++ DT_CLK(NULL, "abe_clk", "abe_clk"), ++ DT_CLK(NULL, "abe_iclk", "abe_iclk"), ++ DT_CLK(NULL, "abe_lp_clk_div", "abe_lp_clk_div"), ++ DT_CLK(NULL, "dpll_abe_m3x2_ck", "dpll_abe_m3x2_ck"), ++ DT_CLK(NULL, "dpll_core_ck", "dpll_core_ck"), ++ DT_CLK(NULL, "dpll_core_x2_ck", "dpll_core_x2_ck"), ++ DT_CLK(NULL, "dpll_core_h21x2_ck", "dpll_core_h21x2_ck"), ++ DT_CLK(NULL, "c2c_fclk", "c2c_fclk"), ++ DT_CLK(NULL, "c2c_iclk", "c2c_iclk"), ++ DT_CLK(NULL, "custefuse_sys_gfclk_div", "custefuse_sys_gfclk_div"), ++ DT_CLK(NULL, "dpll_core_h11x2_ck", "dpll_core_h11x2_ck"), ++ DT_CLK(NULL, "dpll_core_h12x2_ck", "dpll_core_h12x2_ck"), ++ DT_CLK(NULL, "dpll_core_h13x2_ck", "dpll_core_h13x2_ck"), ++ DT_CLK(NULL, "dpll_core_h14x2_ck", "dpll_core_h14x2_ck"), ++ DT_CLK(NULL, "dpll_core_h22x2_ck", "dpll_core_h22x2_ck"), ++ DT_CLK(NULL, "dpll_core_h23x2_ck", "dpll_core_h23x2_ck"), ++ DT_CLK(NULL, "dpll_core_h24x2_ck", "dpll_core_h24x2_ck"), ++ DT_CLK(NULL, "dpll_core_m2_ck", "dpll_core_m2_ck"), ++ DT_CLK(NULL, "dpll_core_m3x2_ck", "dpll_core_m3x2_ck"), ++ DT_CLK(NULL, "iva_dpll_hs_clk_div", "iva_dpll_hs_clk_div"), ++ DT_CLK(NULL, "dpll_iva_ck", "dpll_iva_ck"), ++ DT_CLK(NULL, "dpll_iva_x2_ck", "dpll_iva_x2_ck"), ++ DT_CLK(NULL, "dpll_iva_h11x2_ck", "dpll_iva_h11x2_ck"), ++ DT_CLK(NULL, "dpll_iva_h12x2_ck", "dpll_iva_h12x2_ck"), ++ DT_CLK(NULL, "mpu_dpll_hs_clk_div", "mpu_dpll_hs_clk_div"), ++ DT_CLK(NULL, "dpll_mpu_ck", "dpll_mpu_ck"), ++ DT_CLK(NULL, "dpll_mpu_m2_ck", "dpll_mpu_m2_ck"), ++ DT_CLK(NULL, "per_dpll_hs_clk_div", "per_dpll_hs_clk_div"), ++ DT_CLK(NULL, "dpll_per_ck", "dpll_per_ck"), ++ DT_CLK(NULL, "dpll_per_x2_ck", "dpll_per_x2_ck"), ++ DT_CLK(NULL, "dpll_per_h11x2_ck", "dpll_per_h11x2_ck"), ++ DT_CLK(NULL, "dpll_per_h12x2_ck", "dpll_per_h12x2_ck"), ++ DT_CLK(NULL, "dpll_per_h14x2_ck", "dpll_per_h14x2_ck"), ++ DT_CLK(NULL, "dpll_per_m2_ck", "dpll_per_m2_ck"), ++ DT_CLK(NULL, "dpll_per_m2x2_ck", "dpll_per_m2x2_ck"), ++ DT_CLK(NULL, "dpll_per_m3x2_ck", "dpll_per_m3x2_ck"), ++ DT_CLK(NULL, "dpll_unipro1_ck", "dpll_unipro1_ck"), ++ DT_CLK(NULL, "dpll_unipro1_clkdcoldo", "dpll_unipro1_clkdcoldo"), ++ DT_CLK(NULL, "dpll_unipro1_m2_ck", "dpll_unipro1_m2_ck"), ++ DT_CLK(NULL, "dpll_unipro2_ck", "dpll_unipro2_ck"), ++ DT_CLK(NULL, "dpll_unipro2_clkdcoldo", "dpll_unipro2_clkdcoldo"), ++ DT_CLK(NULL, "dpll_unipro2_m2_ck", "dpll_unipro2_m2_ck"), ++ DT_CLK(NULL, "usb_dpll_hs_clk_div", "usb_dpll_hs_clk_div"), ++ DT_CLK(NULL, "dpll_usb_ck", "dpll_usb_ck"), ++ DT_CLK(NULL, "dpll_usb_clkdcoldo", "dpll_usb_clkdcoldo"), ++ DT_CLK(NULL, "dpll_usb_m2_ck", "dpll_usb_m2_ck"), ++ DT_CLK(NULL, "dss_syc_gfclk_div", "dss_syc_gfclk_div"), ++ DT_CLK(NULL, "func_128m_clk", "func_128m_clk"), ++ DT_CLK(NULL, "func_12m_fclk", "func_12m_fclk"), ++ DT_CLK(NULL, "func_24m_clk", "func_24m_clk"), ++ DT_CLK(NULL, "func_48m_fclk", "func_48m_fclk"), ++ DT_CLK(NULL, "func_96m_fclk", "func_96m_fclk"), ++ DT_CLK(NULL, "l3_iclk_div", "l3_iclk_div"), ++ DT_CLK(NULL, "gpu_l3_iclk", "gpu_l3_iclk"), ++ DT_CLK(NULL, "l3init_60m_fclk", "l3init_60m_fclk"), ++ DT_CLK(NULL, "wkupaon_iclk_mux", "wkupaon_iclk_mux"), ++ DT_CLK(NULL, "l3instr_ts_gclk_div", "l3instr_ts_gclk_div"), ++ DT_CLK(NULL, "l4_root_clk_div", "l4_root_clk_div"), ++ DT_CLK(NULL, "dss_32khz_clk", "dss_32khz_clk"), ++ DT_CLK(NULL, "dss_48mhz_clk", "dss_48mhz_clk"), ++ DT_CLK(NULL, "dss_dss_clk", "dss_dss_clk"), ++ DT_CLK(NULL, "dss_sys_clk", "dss_sys_clk"), ++ DT_CLK(NULL, "gpio1_dbclk", "gpio1_dbclk"), ++ DT_CLK(NULL, "gpio2_dbclk", "gpio2_dbclk"), ++ DT_CLK(NULL, "gpio3_dbclk", "gpio3_dbclk"), ++ DT_CLK(NULL, "gpio4_dbclk", "gpio4_dbclk"), ++ DT_CLK(NULL, "gpio5_dbclk", "gpio5_dbclk"), ++ DT_CLK(NULL, "gpio6_dbclk", "gpio6_dbclk"), ++ DT_CLK(NULL, "gpio7_dbclk", "gpio7_dbclk"), ++ DT_CLK(NULL, "gpio8_dbclk", "gpio8_dbclk"), ++ DT_CLK(NULL, "iss_ctrlclk", "iss_ctrlclk"), ++ DT_CLK(NULL, "lli_txphy_clk", "lli_txphy_clk"), ++ DT_CLK(NULL, "lli_txphy_ls_clk", "lli_txphy_ls_clk"), ++ DT_CLK(NULL, "mmc1_32khz_clk", "mmc1_32khz_clk"), ++ DT_CLK(NULL, "sata_ref_clk", "sata_ref_clk"), ++ DT_CLK(NULL, "slimbus1_slimbus_clk", "slimbus1_slimbus_clk"), ++ DT_CLK(NULL, "usb_host_hs_hsic480m_p1_clk", "usb_host_hs_hsic480m_p1_clk"), ++ DT_CLK(NULL, "usb_host_hs_hsic480m_p2_clk", "usb_host_hs_hsic480m_p2_clk"), ++ DT_CLK(NULL, "usb_host_hs_hsic480m_p3_clk", "usb_host_hs_hsic480m_p3_clk"), ++ DT_CLK(NULL, "usb_host_hs_hsic60m_p1_clk", "usb_host_hs_hsic60m_p1_clk"), ++ DT_CLK(NULL, "usb_host_hs_hsic60m_p2_clk", "usb_host_hs_hsic60m_p2_clk"), ++ DT_CLK(NULL, "usb_host_hs_hsic60m_p3_clk", "usb_host_hs_hsic60m_p3_clk"), ++ DT_CLK(NULL, "usb_host_hs_utmi_p1_clk", "usb_host_hs_utmi_p1_clk"), ++ DT_CLK(NULL, "usb_host_hs_utmi_p2_clk", "usb_host_hs_utmi_p2_clk"), ++ DT_CLK(NULL, "usb_host_hs_utmi_p3_clk", "usb_host_hs_utmi_p3_clk"), ++ DT_CLK(NULL, "usb_otg_ss_refclk960m", "usb_otg_ss_refclk960m"), ++ DT_CLK(NULL, "usb_phy_cm_clk32k", "usb_phy_cm_clk32k"), ++ DT_CLK(NULL, "usb_tll_hs_usb_ch0_clk", "usb_tll_hs_usb_ch0_clk"), ++ DT_CLK(NULL, "usb_tll_hs_usb_ch1_clk", "usb_tll_hs_usb_ch1_clk"), ++ DT_CLK(NULL, "usb_tll_hs_usb_ch2_clk", "usb_tll_hs_usb_ch2_clk"), ++ DT_CLK(NULL, "aess_fclk", "aess_fclk"), ++ DT_CLK(NULL, "dmic_sync_mux_ck", "dmic_sync_mux_ck"), ++ DT_CLK(NULL, "dmic_gfclk", "dmic_gfclk"), ++ DT_CLK(NULL, "fdif_fclk", "fdif_fclk"), ++ DT_CLK(NULL, "gpu_core_gclk_mux", "gpu_core_gclk_mux"), ++ DT_CLK(NULL, "gpu_hyd_gclk_mux", "gpu_hyd_gclk_mux"), ++ DT_CLK(NULL, "hsi_fclk", "hsi_fclk"), ++ DT_CLK(NULL, "mcasp_sync_mux_ck", "mcasp_sync_mux_ck"), ++ DT_CLK(NULL, "mcasp_gfclk", "mcasp_gfclk"), ++ DT_CLK(NULL, "mcbsp1_sync_mux_ck", "mcbsp1_sync_mux_ck"), ++ DT_CLK(NULL, "mcbsp1_gfclk", "mcbsp1_gfclk"), ++ DT_CLK(NULL, "mcbsp2_sync_mux_ck", "mcbsp2_sync_mux_ck"), ++ DT_CLK(NULL, "mcbsp2_gfclk", "mcbsp2_gfclk"), ++ DT_CLK(NULL, "mcbsp3_sync_mux_ck", "mcbsp3_sync_mux_ck"), ++ DT_CLK(NULL, "mcbsp3_gfclk", "mcbsp3_gfclk"), ++ DT_CLK(NULL, "mmc1_fclk_mux", "mmc1_fclk_mux"), ++ DT_CLK(NULL, "mmc1_fclk", "mmc1_fclk"), ++ DT_CLK(NULL, "mmc2_fclk_mux", "mmc2_fclk_mux"), ++ DT_CLK(NULL, "mmc2_fclk", "mmc2_fclk"), ++ DT_CLK(NULL, "timer10_gfclk_mux", "timer10_gfclk_mux"), ++ DT_CLK(NULL, "timer11_gfclk_mux", "timer11_gfclk_mux"), ++ DT_CLK(NULL, "timer1_gfclk_mux", "timer1_gfclk_mux"), ++ DT_CLK(NULL, "timer2_gfclk_mux", "timer2_gfclk_mux"), ++ DT_CLK(NULL, "timer3_gfclk_mux", "timer3_gfclk_mux"), ++ DT_CLK(NULL, "timer4_gfclk_mux", "timer4_gfclk_mux"), ++ DT_CLK(NULL, "timer5_gfclk_mux", "timer5_gfclk_mux"), ++ DT_CLK(NULL, "timer6_gfclk_mux", "timer6_gfclk_mux"), ++ DT_CLK(NULL, "timer7_gfclk_mux", "timer7_gfclk_mux"), ++ DT_CLK(NULL, "timer8_gfclk_mux", "timer8_gfclk_mux"), ++ DT_CLK(NULL, "timer9_gfclk_mux", "timer9_gfclk_mux"), ++ DT_CLK(NULL, "utmi_p1_gfclk", "utmi_p1_gfclk"), ++ DT_CLK(NULL, "utmi_p2_gfclk", "utmi_p2_gfclk"), ++ DT_CLK(NULL, "auxclk0_src_ck", "auxclk0_src_ck"), ++ DT_CLK(NULL, "auxclk0_ck", "auxclk0_ck"), ++ DT_CLK(NULL, "auxclkreq0_ck", "auxclkreq0_ck"), ++ DT_CLK(NULL, "auxclk1_src_ck", "auxclk1_src_ck"), ++ DT_CLK(NULL, "auxclk1_ck", "auxclk1_ck"), ++ DT_CLK(NULL, "auxclkreq1_ck", "auxclkreq1_ck"), ++ DT_CLK(NULL, "auxclk2_src_ck", "auxclk2_src_ck"), ++ DT_CLK(NULL, "auxclk2_ck", "auxclk2_ck"), ++ DT_CLK(NULL, "auxclkreq2_ck", "auxclkreq2_ck"), ++ DT_CLK(NULL, "auxclk3_src_ck", "auxclk3_src_ck"), ++ DT_CLK(NULL, "auxclk3_ck", "auxclk3_ck"), ++ DT_CLK(NULL, "auxclkreq3_ck", "auxclkreq3_ck"), ++ DT_CLK(NULL, "timer_32k_ck", "sys_32k_ck"), ++ DT_CLK("omap_timer.1", "sys_ck", "sys_clkin"), ++ DT_CLK("omap_timer.2", "sys_ck", "sys_clkin"), ++ DT_CLK("omap_timer.3", "sys_ck", "sys_clkin"), ++ DT_CLK("omap_timer.4", "sys_ck", "sys_clkin"), ++ DT_CLK("omap_timer.9", "sys_ck", "sys_clkin"), ++ DT_CLK("omap_timer.10", "sys_ck", "sys_clkin"), ++ DT_CLK("omap_timer.11", "sys_ck", "sys_clkin"), ++ DT_CLK("omap_timer.5", "sys_ck", "dss_syc_gfclk_div"), ++ DT_CLK("omap_timer.6", "sys_ck", "dss_syc_gfclk_div"), ++ DT_CLK("omap_timer.7", "sys_ck", "dss_syc_gfclk_div"), ++ DT_CLK("omap_timer.8", "sys_ck", "dss_syc_gfclk_div"), ++ { .node_name = NULL }, ++}; ++ ++int __init omap5xxx_clk_init(void) ++{ ++ int rc; ++ struct clk *abe_dpll_ref, *abe_dpll, *sys_32k_ck, *usb_dpll; ++ ++ of_clk_init(NULL); ++ ++ omap_dt_clocks_register(omap54xx_clks); ++ ++ omap2_clk_disable_autoidle_all(); ++ ++ abe_dpll_ref = clk_get_sys(NULL, "abe_dpll_clk_mux"); ++ sys_32k_ck = clk_get_sys(NULL, "sys_32k_ck"); ++ rc = clk_set_parent(abe_dpll_ref, sys_32k_ck); ++ abe_dpll = clk_get_sys(NULL, "dpll_abe_ck"); ++ if (!rc) ++ rc = clk_set_rate(abe_dpll, OMAP5_DPLL_ABE_DEFFREQ); ++ if (rc) ++ pr_err("%s: failed to configure ABE DPLL!\n", __func__); ++ ++ usb_dpll = clk_get_sys(NULL, "dpll_usb_ck"); ++ rc = clk_set_rate(usb_dpll, OMAP5_DPLL_USB_DEFFREQ); ++ if (rc) ++ pr_err("%s: failed to configure USB DPLL!\n", __func__); ++ ++ usb_dpll = clk_get_sys(NULL, "dpll_usb_m2_ck"); ++ rc = clk_set_rate(usb_dpll, OMAP5_DPLL_USB_DEFFREQ/2); ++ if (rc) ++ pr_err("%s: failed to set USB_DPLL M2 OUT\n", __func__); ++ ++ return 0; ++} +--- /dev/null ++++ b/drivers/clk/ti/clk-7xx.c +@@ -0,0 +1,325 @@ ++/* ++ * DRA7 Clock init ++ * ++ * Copyright (C) 2013 Texas Instruments, Inc. ++ * ++ * Tero Kristo (t-kristo@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/list.h> ++#include <linux/clk-private.h> ++#include <linux/clkdev.h> ++#include <linux/clk/ti.h> ++ ++#define DRA7_DPLL_ABE_DEFFREQ 361267200 ++#define DRA7_DPLL_GMAC_DEFFREQ 1000000000 ++#define DRA7_DPLL_USB_DEFFREQ 960000000 ++ ++ ++static struct omap_dt_clk dra7xx_clks[] = { ++ DT_CLK(NULL, "atl_clkin0_ck", "atl_clkin0_ck"), ++ DT_CLK(NULL, "atl_clkin1_ck", "atl_clkin1_ck"), ++ DT_CLK(NULL, "atl_clkin2_ck", "atl_clkin2_ck"), ++ DT_CLK(NULL, "atlclkin3_ck", "atlclkin3_ck"), ++ DT_CLK(NULL, "hdmi_clkin_ck", "hdmi_clkin_ck"), ++ DT_CLK(NULL, "mlb_clkin_ck", "mlb_clkin_ck"), ++ DT_CLK(NULL, "mlbp_clkin_ck", "mlbp_clkin_ck"), ++ DT_CLK(NULL, "pciesref_acs_clk_ck", "pciesref_acs_clk_ck"), ++ DT_CLK(NULL, "ref_clkin0_ck", "ref_clkin0_ck"), ++ DT_CLK(NULL, "ref_clkin1_ck", "ref_clkin1_ck"), ++ DT_CLK(NULL, "ref_clkin2_ck", "ref_clkin2_ck"), ++ DT_CLK(NULL, "ref_clkin3_ck", "ref_clkin3_ck"), ++ DT_CLK(NULL, "rmii_clk_ck", "rmii_clk_ck"), ++ DT_CLK(NULL, "sdvenc_clkin_ck", "sdvenc_clkin_ck"), ++ DT_CLK(NULL, "secure_32k_clk_src_ck", "secure_32k_clk_src_ck"), ++ DT_CLK(NULL, "sys_32k_ck", "sys_32k_ck"), ++ DT_CLK(NULL, "virt_12000000_ck", "virt_12000000_ck"), ++ DT_CLK(NULL, "virt_13000000_ck", "virt_13000000_ck"), ++ DT_CLK(NULL, "virt_16800000_ck", "virt_16800000_ck"), ++ DT_CLK(NULL, "virt_19200000_ck", "virt_19200000_ck"), ++ DT_CLK(NULL, "virt_20000000_ck", "virt_20000000_ck"), ++ DT_CLK(NULL, "virt_26000000_ck", "virt_26000000_ck"), ++ DT_CLK(NULL, "virt_27000000_ck", "virt_27000000_ck"), ++ DT_CLK(NULL, "virt_38400000_ck", "virt_38400000_ck"), ++ DT_CLK(NULL, "sys_clkin1", "sys_clkin1"), ++ DT_CLK(NULL, "sys_clkin2", "sys_clkin2"), ++ DT_CLK(NULL, "usb_otg_clkin_ck", "usb_otg_clkin_ck"), ++ DT_CLK(NULL, "video1_clkin_ck", "video1_clkin_ck"), ++ DT_CLK(NULL, "video1_m2_clkin_ck", "video1_m2_clkin_ck"), ++ DT_CLK(NULL, "video2_clkin_ck", "video2_clkin_ck"), ++ DT_CLK(NULL, "video2_m2_clkin_ck", "video2_m2_clkin_ck"), ++ DT_CLK(NULL, "abe_dpll_sys_clk_mux", "abe_dpll_sys_clk_mux"), ++ DT_CLK(NULL, "abe_dpll_bypass_clk_mux", "abe_dpll_bypass_clk_mux"), ++ DT_CLK(NULL, "abe_dpll_clk_mux", "abe_dpll_clk_mux"), ++ DT_CLK(NULL, "dpll_abe_ck", "dpll_abe_ck"), ++ DT_CLK(NULL, "dpll_abe_x2_ck", "dpll_abe_x2_ck"), ++ DT_CLK(NULL, "dpll_abe_m2x2_ck", "dpll_abe_m2x2_ck"), ++ DT_CLK(NULL, "abe_24m_fclk", "abe_24m_fclk"), ++ DT_CLK(NULL, "abe_clk", "abe_clk"), ++ DT_CLK(NULL, "aess_fclk", "aess_fclk"), ++ DT_CLK(NULL, "abe_giclk_div", "abe_giclk_div"), ++ DT_CLK(NULL, "abe_lp_clk_div", "abe_lp_clk_div"), ++ DT_CLK(NULL, "abe_sys_clk_div", "abe_sys_clk_div"), ++ DT_CLK(NULL, "adc_gfclk_mux", "adc_gfclk_mux"), ++ DT_CLK(NULL, "dpll_pcie_ref_ck", "dpll_pcie_ref_ck"), ++ DT_CLK(NULL, "dpll_pcie_ref_m2ldo_ck", "dpll_pcie_ref_m2ldo_ck"), ++ DT_CLK(NULL, "apll_pcie_ck", "apll_pcie_ck"), ++ DT_CLK(NULL, "apll_pcie_clkvcoldo", "apll_pcie_clkvcoldo"), ++ DT_CLK(NULL, "apll_pcie_clkvcoldo_div", "apll_pcie_clkvcoldo_div"), ++ DT_CLK(NULL, "apll_pcie_m2_ck", "apll_pcie_m2_ck"), ++ DT_CLK(NULL, "sys_clk1_dclk_div", "sys_clk1_dclk_div"), ++ DT_CLK(NULL, "sys_clk2_dclk_div", "sys_clk2_dclk_div"), ++ DT_CLK(NULL, "dpll_abe_m2_ck", "dpll_abe_m2_ck"), ++ DT_CLK(NULL, "per_abe_x1_dclk_div", "per_abe_x1_dclk_div"), ++ DT_CLK(NULL, "dpll_abe_m3x2_ck", "dpll_abe_m3x2_ck"), ++ DT_CLK(NULL, "dpll_core_ck", "dpll_core_ck"), ++ DT_CLK(NULL, "dpll_core_x2_ck", "dpll_core_x2_ck"), ++ DT_CLK(NULL, "dpll_core_h12x2_ck", "dpll_core_h12x2_ck"), ++ DT_CLK(NULL, "mpu_dpll_hs_clk_div", "mpu_dpll_hs_clk_div"), ++ DT_CLK(NULL, "dpll_mpu_ck", "dpll_mpu_ck"), ++ DT_CLK(NULL, "dpll_mpu_m2_ck", "dpll_mpu_m2_ck"), ++ DT_CLK(NULL, "mpu_dclk_div", "mpu_dclk_div"), ++ DT_CLK(NULL, "dsp_dpll_hs_clk_div", "dsp_dpll_hs_clk_div"), ++ DT_CLK(NULL, "dpll_dsp_ck", "dpll_dsp_ck"), ++ DT_CLK(NULL, "dpll_dsp_m2_ck", "dpll_dsp_m2_ck"), ++ DT_CLK(NULL, "dsp_gclk_div", "dsp_gclk_div"), ++ DT_CLK(NULL, "iva_dpll_hs_clk_div", "iva_dpll_hs_clk_div"), ++ DT_CLK(NULL, "dpll_iva_ck", "dpll_iva_ck"), ++ DT_CLK(NULL, "dpll_iva_m2_ck", "dpll_iva_m2_ck"), ++ DT_CLK(NULL, "iva_dclk", "iva_dclk"), ++ DT_CLK(NULL, "dpll_gpu_ck", "dpll_gpu_ck"), ++ DT_CLK(NULL, "dpll_gpu_m2_ck", "dpll_gpu_m2_ck"), ++ DT_CLK(NULL, "gpu_dclk", "gpu_dclk"), ++ DT_CLK(NULL, "dpll_core_m2_ck", "dpll_core_m2_ck"), ++ DT_CLK(NULL, "core_dpll_out_dclk_div", "core_dpll_out_dclk_div"), ++ DT_CLK(NULL, "dpll_ddr_ck", "dpll_ddr_ck"), ++ DT_CLK(NULL, "dpll_ddr_m2_ck", "dpll_ddr_m2_ck"), ++ DT_CLK(NULL, "emif_phy_dclk_div", "emif_phy_dclk_div"), ++ DT_CLK(NULL, "dpll_gmac_ck", "dpll_gmac_ck"), ++ DT_CLK(NULL, "dpll_gmac_m2_ck", "dpll_gmac_m2_ck"), ++ DT_CLK(NULL, "gmac_250m_dclk_div", "gmac_250m_dclk_div"), ++ DT_CLK(NULL, "video2_dclk_div", "video2_dclk_div"), ++ DT_CLK(NULL, "video1_dclk_div", "video1_dclk_div"), ++ DT_CLK(NULL, "hdmi_dclk_div", "hdmi_dclk_div"), ++ DT_CLK(NULL, "per_dpll_hs_clk_div", "per_dpll_hs_clk_div"), ++ DT_CLK(NULL, "dpll_per_ck", "dpll_per_ck"), ++ DT_CLK(NULL, "dpll_per_m2_ck", "dpll_per_m2_ck"), ++ DT_CLK(NULL, "func_96m_aon_dclk_div", "func_96m_aon_dclk_div"), ++ DT_CLK(NULL, "usb_dpll_hs_clk_div", "usb_dpll_hs_clk_div"), ++ DT_CLK(NULL, "dpll_usb_ck", "dpll_usb_ck"), ++ DT_CLK(NULL, "dpll_usb_m2_ck", "dpll_usb_m2_ck"), ++ DT_CLK(NULL, "l3init_480m_dclk_div", "l3init_480m_dclk_div"), ++ DT_CLK(NULL, "usb_otg_dclk_div", "usb_otg_dclk_div"), ++ DT_CLK(NULL, "sata_dclk_div", "sata_dclk_div"), ++ DT_CLK(NULL, "dpll_pcie_ref_m2_ck", "dpll_pcie_ref_m2_ck"), ++ DT_CLK(NULL, "pcie2_dclk_div", "pcie2_dclk_div"), ++ DT_CLK(NULL, "pcie_dclk_div", "pcie_dclk_div"), ++ DT_CLK(NULL, "emu_dclk_div", "emu_dclk_div"), ++ DT_CLK(NULL, "secure_32k_dclk_div", "secure_32k_dclk_div"), ++ DT_CLK(NULL, "eve_dpll_hs_clk_div", "eve_dpll_hs_clk_div"), ++ DT_CLK(NULL, "dpll_eve_ck", "dpll_eve_ck"), ++ DT_CLK(NULL, "dpll_eve_m2_ck", "dpll_eve_m2_ck"), ++ DT_CLK(NULL, "eve_dclk_div", "eve_dclk_div"), ++ DT_CLK(NULL, "clkoutmux0_clk_mux", "clkoutmux0_clk_mux"), ++ DT_CLK(NULL, "clkoutmux1_clk_mux", "clkoutmux1_clk_mux"), ++ DT_CLK(NULL, "clkoutmux2_clk_mux", "clkoutmux2_clk_mux"), ++ DT_CLK(NULL, "custefuse_sys_gfclk_div", "custefuse_sys_gfclk_div"), ++ DT_CLK(NULL, "dpll_core_h13x2_ck", "dpll_core_h13x2_ck"), ++ DT_CLK(NULL, "dpll_core_h14x2_ck", "dpll_core_h14x2_ck"), ++ DT_CLK(NULL, "dpll_core_h22x2_ck", "dpll_core_h22x2_ck"), ++ DT_CLK(NULL, "dpll_core_h23x2_ck", "dpll_core_h23x2_ck"), ++ DT_CLK(NULL, "dpll_core_h24x2_ck", "dpll_core_h24x2_ck"), ++ DT_CLK(NULL, "dpll_ddr_x2_ck", "dpll_ddr_x2_ck"), ++ DT_CLK(NULL, "dpll_ddr_h11x2_ck", "dpll_ddr_h11x2_ck"), ++ DT_CLK(NULL, "dpll_dsp_x2_ck", "dpll_dsp_x2_ck"), ++ DT_CLK(NULL, "dpll_dsp_m3x2_ck", "dpll_dsp_m3x2_ck"), ++ DT_CLK(NULL, "dpll_gmac_x2_ck", "dpll_gmac_x2_ck"), ++ DT_CLK(NULL, "dpll_gmac_h11x2_ck", "dpll_gmac_h11x2_ck"), ++ DT_CLK(NULL, "dpll_gmac_h12x2_ck", "dpll_gmac_h12x2_ck"), ++ DT_CLK(NULL, "dpll_gmac_h13x2_ck", "dpll_gmac_h13x2_ck"), ++ DT_CLK(NULL, "dpll_gmac_m3x2_ck", "dpll_gmac_m3x2_ck"), ++ DT_CLK(NULL, "dpll_per_x2_ck", "dpll_per_x2_ck"), ++ DT_CLK(NULL, "dpll_per_h11x2_ck", "dpll_per_h11x2_ck"), ++ DT_CLK(NULL, "dpll_per_h12x2_ck", "dpll_per_h12x2_ck"), ++ DT_CLK(NULL, "dpll_per_h13x2_ck", "dpll_per_h13x2_ck"), ++ DT_CLK(NULL, "dpll_per_h14x2_ck", "dpll_per_h14x2_ck"), ++ DT_CLK(NULL, "dpll_per_m2x2_ck", "dpll_per_m2x2_ck"), ++ DT_CLK(NULL, "dpll_usb_clkdcoldo", "dpll_usb_clkdcoldo"), ++ DT_CLK(NULL, "eve_clk", "eve_clk"), ++ DT_CLK(NULL, "func_128m_clk", "func_128m_clk"), ++ DT_CLK(NULL, "func_12m_fclk", "func_12m_fclk"), ++ DT_CLK(NULL, "func_24m_clk", "func_24m_clk"), ++ DT_CLK(NULL, "func_48m_fclk", "func_48m_fclk"), ++ DT_CLK(NULL, "func_96m_fclk", "func_96m_fclk"), ++ DT_CLK(NULL, "gmii_m_clk_div", "gmii_m_clk_div"), ++ DT_CLK(NULL, "hdmi_clk2_div", "hdmi_clk2_div"), ++ DT_CLK(NULL, "hdmi_div_clk", "hdmi_div_clk"), ++ DT_CLK(NULL, "hdmi_dpll_clk_mux", "hdmi_dpll_clk_mux"), ++ DT_CLK(NULL, "l3_iclk_div", "l3_iclk_div"), ++ DT_CLK(NULL, "l3init_60m_fclk", "l3init_60m_fclk"), ++ DT_CLK(NULL, "l4_root_clk_div", "l4_root_clk_div"), ++ DT_CLK(NULL, "mlb_clk", "mlb_clk"), ++ DT_CLK(NULL, "mlbp_clk", "mlbp_clk"), ++ DT_CLK(NULL, "per_abe_x1_gfclk2_div", "per_abe_x1_gfclk2_div"), ++ DT_CLK(NULL, "timer_sys_clk_div", "timer_sys_clk_div"), ++ DT_CLK(NULL, "video1_clk2_div", "video1_clk2_div"), ++ DT_CLK(NULL, "video1_div_clk", "video1_div_clk"), ++ DT_CLK(NULL, "video1_dpll_clk_mux", "video1_dpll_clk_mux"), ++ DT_CLK(NULL, "video2_clk2_div", "video2_clk2_div"), ++ DT_CLK(NULL, "video2_div_clk", "video2_div_clk"), ++ DT_CLK(NULL, "video2_dpll_clk_mux", "video2_dpll_clk_mux"), ++ DT_CLK(NULL, "wkupaon_iclk_mux", "wkupaon_iclk_mux"), ++ DT_CLK(NULL, "dss_32khz_clk", "dss_32khz_clk"), ++ DT_CLK(NULL, "dss_48mhz_clk", "dss_48mhz_clk"), ++ DT_CLK(NULL, "dss_dss_clk", "dss_dss_clk"), ++ DT_CLK(NULL, "dss_hdmi_clk", "dss_hdmi_clk"), ++ DT_CLK(NULL, "dss_video1_clk", "dss_video1_clk"), ++ DT_CLK(NULL, "dss_video2_clk", "dss_video2_clk"), ++ DT_CLK(NULL, "dss_deshdcp_clk", "dss_deshdcp_clk"), ++ DT_CLK(NULL, "gpio1_dbclk", "gpio1_dbclk"), ++ DT_CLK(NULL, "gpio2_dbclk", "gpio2_dbclk"), ++ DT_CLK(NULL, "gpio3_dbclk", "gpio3_dbclk"), ++ DT_CLK(NULL, "gpio4_dbclk", "gpio4_dbclk"), ++ DT_CLK(NULL, "gpio5_dbclk", "gpio5_dbclk"), ++ DT_CLK(NULL, "gpio6_dbclk", "gpio6_dbclk"), ++ DT_CLK(NULL, "gpio7_dbclk", "gpio7_dbclk"), ++ DT_CLK(NULL, "gpio8_dbclk", "gpio8_dbclk"), ++ DT_CLK(NULL, "mmc1_clk32k", "mmc1_clk32k"), ++ DT_CLK(NULL, "mmc2_clk32k", "mmc2_clk32k"), ++ DT_CLK(NULL, "mmc3_clk32k", "mmc3_clk32k"), ++ DT_CLK(NULL, "mmc4_clk32k", "mmc4_clk32k"), ++ DT_CLK(NULL, "sata_ref_clk", "sata_ref_clk"), ++ DT_CLK(NULL, "usb_otg_ss1_refclk960m", "usb_otg_ss1_refclk960m"), ++ DT_CLK(NULL, "usb_otg_ss2_refclk960m", "usb_otg_ss2_refclk960m"), ++ DT_CLK(NULL, "usb_phy1_always_on_clk32k", "usb_phy1_always_on_clk32k"), ++ DT_CLK(NULL, "usb_phy2_always_on_clk32k", "usb_phy2_always_on_clk32k"), ++ DT_CLK(NULL, "usb_phy3_always_on_clk32k", "usb_phy3_always_on_clk32k"), ++ DT_CLK(NULL, "atl_dpll_clk_mux", "atl_dpll_clk_mux"), ++ DT_CLK(NULL, "atl_gfclk_mux", "atl_gfclk_mux"), ++ DT_CLK(NULL, "dcan1_sys_clk_mux", "dcan1_sys_clk_mux"), ++ DT_CLK(NULL, "gmac_gmii_ref_clk_div", "gmac_gmii_ref_clk_div"), ++ DT_CLK(NULL, "gmac_rft_clk_mux", "gmac_rft_clk_mux"), ++ DT_CLK(NULL, "gpu_core_gclk_mux", "gpu_core_gclk_mux"), ++ DT_CLK(NULL, "gpu_hyd_gclk_mux", "gpu_hyd_gclk_mux"), ++ DT_CLK(NULL, "ipu1_gfclk_mux", "ipu1_gfclk_mux"), ++ DT_CLK(NULL, "l3instr_ts_gclk_div", "l3instr_ts_gclk_div"), ++ DT_CLK(NULL, "mcasp1_ahclkr_mux", "mcasp1_ahclkr_mux"), ++ DT_CLK(NULL, "mcasp1_ahclkx_mux", "mcasp1_ahclkx_mux"), ++ DT_CLK(NULL, "mcasp1_aux_gfclk_mux", "mcasp1_aux_gfclk_mux"), ++ DT_CLK(NULL, "mcasp2_ahclkr_mux", "mcasp2_ahclkr_mux"), ++ DT_CLK(NULL, "mcasp2_ahclkx_mux", "mcasp2_ahclkx_mux"), ++ DT_CLK(NULL, "mcasp2_aux_gfclk_mux", "mcasp2_aux_gfclk_mux"), ++ DT_CLK(NULL, "mcasp3_ahclkx_mux", "mcasp3_ahclkx_mux"), ++ DT_CLK(NULL, "mcasp3_aux_gfclk_mux", "mcasp3_aux_gfclk_mux"), ++ DT_CLK(NULL, "mcasp4_ahclkx_mux", "mcasp4_ahclkx_mux"), ++ DT_CLK(NULL, "mcasp4_aux_gfclk_mux", "mcasp4_aux_gfclk_mux"), ++ DT_CLK(NULL, "mcasp5_ahclkx_mux", "mcasp5_ahclkx_mux"), ++ DT_CLK(NULL, "mcasp5_aux_gfclk_mux", "mcasp5_aux_gfclk_mux"), ++ DT_CLK(NULL, "mcasp6_ahclkx_mux", "mcasp6_ahclkx_mux"), ++ DT_CLK(NULL, "mcasp6_aux_gfclk_mux", "mcasp6_aux_gfclk_mux"), ++ DT_CLK(NULL, "mcasp7_ahclkx_mux", "mcasp7_ahclkx_mux"), ++ DT_CLK(NULL, "mcasp7_aux_gfclk_mux", "mcasp7_aux_gfclk_mux"), ++ DT_CLK(NULL, "mcasp8_ahclk_mux", "mcasp8_ahclk_mux"), ++ DT_CLK(NULL, "mcasp8_aux_gfclk_mux", "mcasp8_aux_gfclk_mux"), ++ DT_CLK(NULL, "mmc1_fclk_mux", "mmc1_fclk_mux"), ++ DT_CLK(NULL, "mmc1_fclk_div", "mmc1_fclk_div"), ++ DT_CLK(NULL, "mmc2_fclk_mux", "mmc2_fclk_mux"), ++ DT_CLK(NULL, "mmc2_fclk_div", "mmc2_fclk_div"), ++ DT_CLK(NULL, "mmc3_gfclk_mux", "mmc3_gfclk_mux"), ++ DT_CLK(NULL, "mmc3_gfclk_div", "mmc3_gfclk_div"), ++ DT_CLK(NULL, "mmc4_gfclk_mux", "mmc4_gfclk_mux"), ++ DT_CLK(NULL, "mmc4_gfclk_div", "mmc4_gfclk_div"), ++ DT_CLK(NULL, "qspi_gfclk_mux", "qspi_gfclk_mux"), ++ DT_CLK(NULL, "qspi_gfclk_div", "qspi_gfclk_div"), ++ DT_CLK(NULL, "timer10_gfclk_mux", "timer10_gfclk_mux"), ++ DT_CLK(NULL, "timer11_gfclk_mux", "timer11_gfclk_mux"), ++ DT_CLK(NULL, "timer13_gfclk_mux", "timer13_gfclk_mux"), ++ DT_CLK(NULL, "timer14_gfclk_mux", "timer14_gfclk_mux"), ++ DT_CLK(NULL, "timer15_gfclk_mux", "timer15_gfclk_mux"), ++ DT_CLK(NULL, "timer16_gfclk_mux", "timer16_gfclk_mux"), ++ DT_CLK(NULL, "timer1_gfclk_mux", "timer1_gfclk_mux"), ++ DT_CLK(NULL, "timer2_gfclk_mux", "timer2_gfclk_mux"), ++ DT_CLK(NULL, "timer3_gfclk_mux", "timer3_gfclk_mux"), ++ DT_CLK(NULL, "timer4_gfclk_mux", "timer4_gfclk_mux"), ++ DT_CLK(NULL, "timer5_gfclk_mux", "timer5_gfclk_mux"), ++ DT_CLK(NULL, "timer6_gfclk_mux", "timer6_gfclk_mux"), ++ DT_CLK(NULL, "timer7_gfclk_mux", "timer7_gfclk_mux"), ++ DT_CLK(NULL, "timer8_gfclk_mux", "timer8_gfclk_mux"), ++ DT_CLK(NULL, "timer9_gfclk_mux", "timer9_gfclk_mux"), ++ DT_CLK(NULL, "uart10_gfclk_mux", "uart10_gfclk_mux"), ++ DT_CLK(NULL, "uart1_gfclk_mux", "uart1_gfclk_mux"), ++ DT_CLK(NULL, "uart2_gfclk_mux", "uart2_gfclk_mux"), ++ DT_CLK(NULL, "uart3_gfclk_mux", "uart3_gfclk_mux"), ++ DT_CLK(NULL, "uart4_gfclk_mux", "uart4_gfclk_mux"), ++ DT_CLK(NULL, "uart5_gfclk_mux", "uart5_gfclk_mux"), ++ DT_CLK(NULL, "uart6_gfclk_mux", "uart6_gfclk_mux"), ++ DT_CLK(NULL, "uart7_gfclk_mux", "uart7_gfclk_mux"), ++ DT_CLK(NULL, "uart8_gfclk_mux", "uart8_gfclk_mux"), ++ DT_CLK(NULL, "uart9_gfclk_mux", "uart9_gfclk_mux"), ++ DT_CLK(NULL, "vip1_gclk_mux", "vip1_gclk_mux"), ++ DT_CLK(NULL, "vip2_gclk_mux", "vip2_gclk_mux"), ++ DT_CLK(NULL, "vip3_gclk_mux", "vip3_gclk_mux"), ++ DT_CLK(NULL, "timer_32k_ck", "sys_32k_ck"), ++ DT_CLK("4ae18000.timer", "timer_sys_ck", "sys_clkin2"), ++ DT_CLK("48032000.timer", "timer_sys_ck", "sys_clkin2"), ++ DT_CLK("48034000.timer", "timer_sys_ck", "sys_clkin2"), ++ DT_CLK("48036000.timer", "timer_sys_ck", "sys_clkin2"), ++ DT_CLK("4803e000.timer", "timer_sys_ck", "sys_clkin2"), ++ DT_CLK("48086000.timer", "timer_sys_ck", "sys_clkin2"), ++ DT_CLK("48088000.timer", "timer_sys_ck", "sys_clkin2"), ++ DT_CLK("48820000.timer", "timer_sys_ck", "timer_sys_clk_div"), ++ DT_CLK("48822000.timer", "timer_sys_ck", "timer_sys_clk_div"), ++ DT_CLK("48824000.timer", "timer_sys_ck", "timer_sys_clk_div"), ++ DT_CLK("48826000.timer", "timer_sys_ck", "timer_sys_clk_div"), ++ DT_CLK(NULL, "sys_clkin", "sys_clkin1"), ++ { .node_name = NULL }, ++}; ++ ++int __init dra7xx_clk_init(void) ++{ ++ int rc; ++ struct clk *abe_dpll_mux, *sys_clkin2, *dpll_ck, *deshdcp_clk; ++ ++ of_clk_init(NULL); ++ ++ omap_dt_clocks_register(dra7xx_clks); ++ ++ omap2_clk_disable_autoidle_all(); ++ ++ abe_dpll_mux = clk_get_sys(NULL, "abe_dpll_sys_clk_mux"); ++ sys_clkin2 = clk_get_sys(NULL, "sys_clkin2"); ++ dpll_ck = clk_get_sys(NULL, "dpll_abe_ck"); ++ ++ rc = clk_set_parent(abe_dpll_mux, sys_clkin2); ++ if (!rc) ++ rc = clk_set_rate(dpll_ck, DRA7_DPLL_ABE_DEFFREQ); ++ if (rc) ++ pr_err("%s: failed to configure ABE DPLL!\n", __func__); ++ ++ dpll_ck = clk_get_sys(NULL, "dpll_gmac_ck"); ++ rc = clk_set_rate(dpll_ck, DRA7_DPLL_GMAC_DEFFREQ); ++ if (rc) ++ pr_err("%s: failed to configure GMAC DPLL!\n", __func__); ++ ++ dpll_ck = clk_get_sys(NULL, "dpll_usb_ck"); ++ rc = clk_set_rate(dpll_ck, DRA7_DPLL_USB_DEFFREQ); ++ if (rc) ++ pr_err("%s: failed to configure USB DPLL!\n", __func__); ++ ++ dpll_ck = clk_get_sys(NULL, "dpll_usb_m2_ck"); ++ rc = clk_set_rate(dpll_ck, DRA7_DPLL_USB_DEFFREQ/2); ++ if (rc) ++ pr_err("%s: failed to set USB_DPLL M2 OUT\n", __func__); ++ ++ deshdcp_clk = clk_get_sys(NULL, "dss_deshdcp_clk"); ++ rc = clk_prepare_enable(deshdcp_clk); ++ if (rc) ++ pr_err("%s: failed to enable DESHDCP clock\n", __func__); ++ ++ return rc; ++} +--- /dev/null ++++ b/drivers/clk/ti/clk.c +@@ -0,0 +1,52 @@ ++/* ++ * TI clock support ++ * ++ * Copyright (C) 2013 Texas Instruments, Inc. ++ * ++ * Tero Kristo <t-kristo@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-provider.h> ++#include <linux/clkdev.h> ++#include <linux/clk/ti.h> ++#include <linux/of.h> ++ ++/** ++ * omap_dt_clocks_register - register DT duplicate clocks during boot ++ * @oclks: list of clocks to register ++ * ++ * Register duplicate or non-standard DT clock entries during boot. By ++ * default, DT clocks are found based on their node name. If any ++ * additional con-id / dev-id -> clock mapping is required, use this ++ * function to list these. ++ */ ++void __init omap_dt_clocks_register(struct omap_dt_clk oclks[]) ++{ ++ struct omap_dt_clk *c; ++ struct device_node *node; ++ struct clk *clk; ++ struct of_phandle_args clkspec; ++ ++ for (c = oclks; c->node_name != NULL; c++) { ++ node = of_find_node_by_name(NULL, c->node_name); ++ clkspec.np = node; ++ clk = of_clk_get_from_provider(&clkspec); ++ ++ if (!IS_ERR(clk)) { ++ c->lk.clk = clk; ++ clkdev_add(&c->lk); ++ } else { ++ pr_warn("%s: failed to lookup clock node %s\n", ++ __func__, c->node_name); ++ } ++ } ++} +--- /dev/null ++++ b/drivers/clk/ti/clockdomain.c +@@ -0,0 +1,46 @@ ++/* ++ * OMAP clockdomain support ++ * ++ * Copyright (C) 2013 Texas Instruments, Inc. ++ * ++ * Tero Kristo <t-kristo@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-provider.h> ++#include <linux/slab.h> ++#include <linux/of.h> ++#include <linux/of_address.h> ++#include <linux/clk/ti.h> ++ ++void __init of_omap_clockdomain_setup(struct device_node *node) ++{ ++ struct clk *clk; ++ struct clk_hw *clk_hw; ++ const char *clkdm_name = node->name; ++ int i; ++ int num_clks; ++ ++ num_clks = of_count_phandle_with_args(node, "clocks", "#clock-cells"); ++ ++ for (i = 0; i < num_clks; i++) { ++ clk = of_clk_get(node, i); ++ if (__clk_get_flags(clk) & CLK_IS_BASIC) { ++ pr_warn("%s: can't setup clkdm for basic clk %s\n", ++ __func__, __clk_get_name(clk)); ++ continue; ++ } ++ clk_hw = __clk_get_hw(clk); ++ to_clk_hw_omap(clk_hw)->clkdm_name = clkdm_name; ++ omap2_init_clk_clkdm(clk_hw); ++ } ++} ++CLK_OF_DECLARE(omap_clockdomain, "ti,clockdomain", of_omap_clockdomain_setup); +--- /dev/null ++++ b/drivers/clk/ti/dpll.c +@@ -0,0 +1,476 @@ ++/* ++ * OMAP DPLL clock support ++ * ++ * Copyright (C) 2013 Texas Instruments, Inc. ++ * ++ * Tero Kristo <t-kristo@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-provider.h> ++#include <linux/slab.h> ++#include <linux/err.h> ++#include <linux/of.h> ++#include <linux/of_address.h> ++#include <linux/clk/ti.h> ++ ++static const struct clk_ops dpll_m4xen_ck_ops = { ++ .enable = &omap3_noncore_dpll_enable, ++ .disable = &omap3_noncore_dpll_disable, ++ .recalc_rate = &omap4_dpll_regm4xen_recalc, ++ .round_rate = &omap4_dpll_regm4xen_round_rate, ++ .set_rate = &omap3_noncore_dpll_set_rate, ++ .get_parent = &omap2_init_dpll_parent, ++}; ++ ++static const struct clk_ops dpll_core_ck_ops = { ++ .recalc_rate = &omap3_dpll_recalc, ++ .get_parent = &omap2_init_dpll_parent, ++}; ++ ++static const struct clk_ops omap3_dpll_core_ck_ops = { ++ .init = &omap2_init_clk_clkdm, ++ .get_parent = &omap2_init_dpll_parent, ++ .recalc_rate = &omap3_dpll_recalc, ++ .round_rate = &omap2_dpll_round_rate, ++}; ++ ++static const struct clk_ops dpll_ck_ops = { ++ .enable = &omap3_noncore_dpll_enable, ++ .disable = &omap3_noncore_dpll_disable, ++ .recalc_rate = &omap3_dpll_recalc, ++ .round_rate = &omap2_dpll_round_rate, ++ .set_rate = &omap3_noncore_dpll_set_rate, ++ .get_parent = &omap2_init_dpll_parent, ++ .init = &omap2_init_clk_clkdm, ++}; ++ ++static const struct clk_ops dpll_no_gate_ck_ops = { ++ .recalc_rate = &omap3_dpll_recalc, ++ .get_parent = &omap2_init_dpll_parent, ++ .round_rate = &omap2_dpll_round_rate, ++ .set_rate = &omap3_noncore_dpll_set_rate, ++}; ++ ++static const struct clk_ops omap3_dpll_ck_ops = { ++ .init = &omap2_init_clk_clkdm, ++ .enable = &omap3_noncore_dpll_enable, ++ .disable = &omap3_noncore_dpll_disable, ++ .get_parent = &omap2_init_dpll_parent, ++ .recalc_rate = &omap3_dpll_recalc, ++ .set_rate = &omap3_noncore_dpll_set_rate, ++ .round_rate = &omap2_dpll_round_rate, ++}; ++ ++static const struct clk_ops omap3_dpll_per_ck_ops = { ++ .init = &omap2_init_clk_clkdm, ++ .enable = &omap3_noncore_dpll_enable, ++ .disable = &omap3_noncore_dpll_disable, ++ .get_parent = &omap2_init_dpll_parent, ++ .recalc_rate = &omap3_dpll_recalc, ++ .set_rate = &omap3_dpll4_set_rate, ++ .round_rate = &omap2_dpll_round_rate, ++}; ++ ++static const struct clk_ops dpll_x2_ck_ops = { ++ .recalc_rate = &omap3_clkoutx2_recalc, ++}; ++ ++static struct clk *omap_clk_register_dpll(struct device *dev, const char *name, ++ const char **parent_names, int num_parents, unsigned long flags, ++ struct dpll_data *dpll_data, const char *clkdm_name, ++ const struct clk_ops *ops) ++{ ++ struct clk *clk; ++ struct clk_init_data init = { 0 }; ++ struct clk_hw_omap *clk_hw; ++ ++ /* allocate the divider */ ++ clk_hw = kzalloc(sizeof(*clk_hw), GFP_KERNEL); ++ if (!clk_hw) { ++ pr_err("%s: could not allocate clk_hw_omap\n", __func__); ++ return ERR_PTR(-ENOMEM); ++ } ++ ++ clk_hw->dpll_data = dpll_data; ++ clk_hw->ops = &clkhwops_omap3_dpll; ++ clk_hw->clkdm_name = clkdm_name; ++ clk_hw->hw.init = &init; ++ ++ init.name = name; ++ init.ops = ops; ++ init.flags = flags; ++ init.parent_names = parent_names; ++ init.num_parents = num_parents; ++ ++ /* register the clock */ ++ clk = clk_register(dev, &clk_hw->hw); ++ ++ if (IS_ERR(clk)) ++ kfree(clk_hw); ++ else ++ omap2_init_clk_hw_omap_clocks(clk); ++ ++ return clk; ++} ++ ++static struct clk *omap_clk_register_dpll_x2(struct device *dev, ++ const char *name, const char *parent_name, void __iomem *reg, ++ const struct clk_ops *ops) ++{ ++ struct clk *clk; ++ struct clk_init_data init = { 0 }; ++ struct clk_hw_omap *clk_hw; ++ ++ if (!parent_name) { ++ pr_err("%s: dpll_x2 must have parent\n", __func__); ++ return ERR_PTR(-EINVAL); ++ } ++ ++ clk_hw = kzalloc(sizeof(*clk_hw), GFP_KERNEL); ++ if (!clk_hw) { ++ pr_err("%s: could not allocate clk_hw_omap\n", __func__); ++ return ERR_PTR(-ENOMEM); ++ } ++ ++ clk_hw->ops = &clkhwops_omap4_dpllmx; ++ clk_hw->clksel_reg = reg; ++ clk_hw->hw.init = &init; ++ ++ init.name = name; ++ init.ops = ops; ++ init.parent_names = &parent_name; ++ init.num_parents = 1; ++ ++ /* register the clock */ ++ clk = clk_register(dev, &clk_hw->hw); ++ ++ if (IS_ERR(clk)) ++ kfree(clk_hw); ++ else ++ omap2_init_clk_hw_omap_clocks(clk); ++ ++ return clk; ++} ++ ++/** ++ * of_omap_dpll_setup() - Setup function for OMAP DPLL clocks ++ * ++ * @node: device node containing the DPLL info ++ * @ops: ops for the DPLL ++ * @ddt: DPLL data template to use ++ */ ++static void __init of_omap_dpll_setup(struct device_node *node, ++ const struct clk_ops *ops, ++ const struct dpll_data *ddt) ++{ ++ struct clk *clk; ++ const char *clk_name = node->name; ++ int num_parents; ++ const char **parent_names = NULL; ++ const char *clkdm_name = NULL; ++ u8 dpll_flags = 0; ++ struct dpll_data *dd; ++ int i; ++ u32 val; ++ ++ dd = kzalloc(sizeof(*dd), GFP_KERNEL); ++ if (!dd) { ++ pr_err("%s: could not allocate dpll_data\n", __func__); ++ return; ++ } ++ ++ memcpy(dd, ddt, sizeof(*dd)); ++ ++ of_property_read_string(node, "clock-output-names", &clk_name); ++ ++ num_parents = of_clk_get_parent_count(node); ++ if (num_parents < 1) { ++ pr_err("%s: omap dpll %s must have parent(s)\n", ++ __func__, node->name); ++ goto cleanup; ++ } ++ ++ parent_names = kzalloc(sizeof(char *) * num_parents, GFP_KERNEL); ++ ++ for (i = 0; i < num_parents; i++) ++ parent_names[i] = of_clk_get_parent_name(node, i); ++ ++ dd->clk_ref = of_clk_get(node, 0); ++ dd->clk_bypass = of_clk_get(node, 1); ++ ++ if (IS_ERR(dd->clk_ref)) { ++ pr_err("%s: ti,clk-ref for %s not found\n", __func__, ++ clk_name); ++ goto cleanup; ++ } ++ ++ if (IS_ERR(dd->clk_bypass)) { ++ pr_err("%s: ti,clk-bypass for %s not found\n", __func__, ++ clk_name); ++ goto cleanup; ++ } ++ ++ of_property_read_string(node, "ti,clkdm-name", &clkdm_name); ++ ++ i = of_property_match_string(node, "reg-names", "control"); ++ if (i >= 0) ++ dd->control_reg = of_iomap(node, i); ++ ++ i = of_property_match_string(node, "reg-names", "idlest"); ++ if (i >= 0) ++ dd->idlest_reg = of_iomap(node, i); ++ ++ i = of_property_match_string(node, "reg-names", "autoidle"); ++ if (i >= 0) ++ dd->autoidle_reg = of_iomap(node, i); ++ ++ i = of_property_match_string(node, "reg-names", "mult-div1"); ++ if (i >= 0) ++ dd->mult_div1_reg = of_iomap(node, i); ++ ++ if (!of_property_read_u32(node, "ti,modes", &val)) ++ dd->modes = val; ++ ++ clk = omap_clk_register_dpll(NULL, clk_name, parent_names, ++ num_parents, dpll_flags, dd, ++ clkdm_name, ops); ++ ++ if (!IS_ERR(clk)) ++ of_clk_add_provider(node, of_clk_src_simple_get, clk); ++ return; ++ ++cleanup: ++ kfree(dd); ++ kfree(parent_names); ++ return; ++} ++ ++static void __init of_omap_dpll_x2_setup(struct device_node *node) ++{ ++ struct clk *clk; ++ const char *clk_name = node->name; ++ void __iomem *reg; ++ const char *parent_name; ++ ++ of_property_read_string(node, "clock-output-names", &clk_name); ++ ++ parent_name = of_clk_get_parent_name(node, 0); ++ ++ reg = of_iomap(node, 0); ++ ++ clk = omap_clk_register_dpll_x2(NULL, clk_name, parent_name, ++ reg, &dpll_x2_ck_ops); ++ ++ if (!IS_ERR(clk)) ++ of_clk_add_provider(node, of_clk_src_simple_get, clk); ++} ++CLK_OF_DECLARE(omap_dpll_x2_clock, "ti,omap4-dpll-x2-clock", ++ of_omap_dpll_x2_setup); ++ ++static void __init of_omap3_dpll_setup(struct device_node *node) ++{ ++ const struct dpll_data dd = { ++ .idlest_mask = 0x1, ++ .enable_mask = 0x7, ++ .autoidle_mask = 0x7, ++ .mult_mask = 0x7ff << 8, ++ .div1_mask = 0x7f, ++ .max_multiplier = 2047, ++ .max_divider = 128, ++ .min_divider = 1, ++ .freqsel_mask = 0xf0, ++ .modes = (1 << DPLL_LOW_POWER_BYPASS) | (1 << DPLL_LOCKED), ++ }; ++ ++ of_omap_dpll_setup(node, &omap3_dpll_ck_ops, &dd); ++} ++CLK_OF_DECLARE(omap3_dpll_clock, "ti,omap3-dpll-clock", of_omap3_dpll_setup); ++ ++static void __init of_omap3_core_dpll_setup(struct device_node *node) ++{ ++ const struct dpll_data dd = { ++ .idlest_mask = 0x1, ++ .enable_mask = 0x7, ++ .autoidle_mask = 0x7, ++ .mult_mask = 0x7ff << 16, ++ .div1_mask = 0x7f << 8, ++ .max_multiplier = 2047, ++ .max_divider = 128, ++ .min_divider = 1, ++ .freqsel_mask = 0xf0, ++ }; ++ ++ of_omap_dpll_setup(node, &omap3_dpll_core_ck_ops, &dd); ++} ++CLK_OF_DECLARE(omap3_core_dpll_clock, "ti,omap3-dpll-core-clock", ++ of_omap3_core_dpll_setup); ++ ++static void __init of_omap3_per_dpll_setup(struct device_node *node) ++{ ++ const struct dpll_data dd = { ++ .idlest_mask = 0x1 << 1, ++ .enable_mask = 0x7 << 16, ++ .autoidle_mask = 0x7 << 3, ++ .mult_mask = 0x7ff << 8, ++ .div1_mask = 0x7f, ++ .max_multiplier = 2047, ++ .max_divider = 128, ++ .min_divider = 1, ++ .freqsel_mask = 0xf00000, ++ .modes = (1 << DPLL_LOW_POWER_STOP) | (1 << DPLL_LOCKED), ++ }; ++ ++ of_omap_dpll_setup(node, &omap3_dpll_per_ck_ops, &dd); ++} ++CLK_OF_DECLARE(omap3_per_dpll_clock, "ti,omap3-dpll-per-clock", ++ of_omap3_per_dpll_setup); ++ ++static void __init of_omap3_per_jtype_dpll_setup(struct device_node *node) ++{ ++ const struct dpll_data dd = { ++ .idlest_mask = 0x1 << 1, ++ .enable_mask = 0x7 << 16, ++ .autoidle_mask = 0x7 << 3, ++ .mult_mask = 0xfff << 8, ++ .div1_mask = 0x7f, ++ .max_multiplier = 4095, ++ .max_divider = 128, ++ .min_divider = 1, ++ .sddiv_mask = 0xff << 24, ++ .dco_mask = 0xe << 20, ++ .flags = DPLL_J_TYPE, ++ .modes = (1 << DPLL_LOW_POWER_STOP) | (1 << DPLL_LOCKED), ++ }; ++ ++ of_omap_dpll_setup(node, &omap3_dpll_per_ck_ops, &dd); ++} ++CLK_OF_DECLARE(omap3_per_jtype_dpll_clock, "ti,omap3-dpll-per-j-type-clock", ++ of_omap3_per_jtype_dpll_setup); ++ ++static void __init of_omap4_dpll_setup(struct device_node *node) ++{ ++ const struct dpll_data dd = { ++ .idlest_mask = 0x1, ++ .enable_mask = 0x7, ++ .autoidle_mask = 0x7, ++ .mult_mask = 0x7ff << 8, ++ .div1_mask = 0x7f, ++ .max_multiplier = 2047, ++ .max_divider = 128, ++ .min_divider = 1, ++ .modes = (1 << DPLL_LOW_POWER_BYPASS) | (1 << DPLL_LOCKED), ++ }; ++ ++ of_omap_dpll_setup(node, &dpll_ck_ops, &dd); ++} ++CLK_OF_DECLARE(omap4_dpll_clock, "ti,omap4-dpll-clock", of_omap4_dpll_setup); ++ ++static void __init of_omap4_core_dpll_setup(struct device_node *node) ++{ ++ const struct dpll_data dd = { ++ .idlest_mask = 0x1, ++ .enable_mask = 0x7, ++ .autoidle_mask = 0x7, ++ .mult_mask = 0x7ff << 8, ++ .div1_mask = 0x7f, ++ .max_multiplier = 2047, ++ .max_divider = 128, ++ .min_divider = 1, ++ .modes = (1 << DPLL_LOW_POWER_BYPASS) | (1 << DPLL_LOCKED), ++ }; ++ ++ of_omap_dpll_setup(node, &dpll_core_ck_ops, &dd); ++} ++CLK_OF_DECLARE(omap4_core_dpll_clock, "ti,omap4-dpll-core-clock", ++ of_omap4_core_dpll_setup); ++ ++static void __init of_omap4_m4xen_dpll_setup(struct device_node *node) ++{ ++ const struct dpll_data dd = { ++ .idlest_mask = 0x1, ++ .enable_mask = 0x7, ++ .autoidle_mask = 0x7, ++ .mult_mask = 0x7ff << 8, ++ .div1_mask = 0x7f, ++ .max_multiplier = 2047, ++ .max_divider = 128, ++ .min_divider = 1, ++ .m4xen_mask = 0x800, ++ .lpmode_mask = 1 << 10, ++ .modes = (1 << DPLL_LOW_POWER_BYPASS) | (1 << DPLL_LOCKED), ++ }; ++ ++ of_omap_dpll_setup(node, &dpll_m4xen_ck_ops, &dd); ++} ++CLK_OF_DECLARE(omap4_m4xen_dpll_clock, "ti,omap4-dpll-m4xen-clock", ++ of_omap4_m4xen_dpll_setup); ++ ++static void __init of_omap4_jtype_dpll_setup(struct device_node *node) ++{ ++ const struct dpll_data dd = { ++ .idlest_mask = 0x1, ++ .enable_mask = 0x7, ++ .autoidle_mask = 0x7, ++ .mult_mask = 0xfff << 8, ++ .div1_mask = 0xff, ++ .max_multiplier = 4095, ++ .max_divider = 256, ++ .min_divider = 1, ++ .sddiv_mask = 0xff << 24, ++ .flags = DPLL_J_TYPE, ++ .modes = (1 << DPLL_LOW_POWER_BYPASS) | (1 << DPLL_LOCKED), ++ }; ++ ++ of_omap_dpll_setup(node, &dpll_m4xen_ck_ops, &dd); ++} ++CLK_OF_DECLARE(omap4_jtype_dpll_clock, "ti,omap4-dpll-j-type-clock", ++ of_omap4_jtype_dpll_setup); ++ ++static void __init of_omap4_no_gate_dpll_setup(struct device_node *node) ++{ ++ const struct dpll_data dd = { ++ .idlest_mask = 0x1, ++ .enable_mask = 0x7, ++ .autoidle_mask = 0x7, ++ .mult_mask = 0x7ff << 8, ++ .div1_mask = 0x7f, ++ .max_multiplier = 2047, ++ .max_divider = 128, ++ .min_divider = 1, ++ .modes = (1 << DPLL_LOW_POWER_BYPASS) | (1 << DPLL_LOCKED), ++ }; ++ ++ of_omap_dpll_setup(node, &dpll_no_gate_ck_ops, &dd); ++} ++CLK_OF_DECLARE(omap4_no_gate_dpll_clock, "ti,omap4-dpll-no-gate-clock", ++ of_omap4_no_gate_dpll_setup); ++ ++static void __init of_omap4_no_gate_jtype_dpll_setup(struct device_node *node) ++{ ++ const struct dpll_data dd = { ++ .idlest_mask = 0x1, ++ .enable_mask = 0x7, ++ .autoidle_mask = 0x7, ++ .mult_mask = 0x7ff << 8, ++ .div1_mask = 0x7f, ++ .max_multiplier = 2047, ++ .max_divider = 128, ++ .min_divider = 1, ++ .flags = DPLL_J_TYPE, ++ .modes = (1 << DPLL_LOW_POWER_BYPASS) | (1 << DPLL_LOCKED), ++ }; ++ ++ of_omap_dpll_setup(node, &dpll_no_gate_ck_ops, &dd); ++} ++CLK_OF_DECLARE(omap4_no_gate_jtype_dpll_clock, ++ "ti,omap4-dpll-no-gate-j-type-clock", ++ of_omap4_no_gate_jtype_dpll_setup); +--- /dev/null ++++ b/drivers/clk/ti/gate.c +@@ -0,0 +1,174 @@ ++/* ++ * OMAP gate clock support ++ * ++ * Copyright (C) 2013 Texas Instruments, Inc. ++ * ++ * Tero Kristo <t-kristo@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-provider.h> ++#include <linux/slab.h> ++#include <linux/io.h> ++#include <linux/of.h> ++#include <linux/of_address.h> ++#include <linux/clk/ti.h> ++ ++#define to_clk_divider(_hw) container_of(_hw, struct clk_divider, hw) ++ ++static int omap36xx_gate_clk_enable_with_hsdiv_restore(struct clk_hw *clk); ++ ++static const struct clk_ops omap_gate_clkdm_clk_ops = { ++ .init = &omap2_init_clk_clkdm, ++ .enable = &omap2_clkops_enable_clkdm, ++ .disable = &omap2_clkops_disable_clkdm, ++}; ++ ++static const struct clk_ops omap_gate_clk_ops = { ++ .init = &omap2_init_clk_clkdm, ++ .enable = &omap2_dflt_clk_enable, ++ .disable = &omap2_dflt_clk_disable, ++ .is_enabled = &omap2_dflt_clk_is_enabled, ++}; ++ ++static const struct clk_ops omap_gate_clk_hsdiv_restore_ops = { ++ .init = &omap2_init_clk_clkdm, ++ .enable = &omap36xx_gate_clk_enable_with_hsdiv_restore, ++ .disable = &omap2_dflt_clk_disable, ++ .is_enabled = &omap2_dflt_clk_is_enabled, ++}; ++ ++/** ++ * omap36xx_gate_clk_enable_with_hsdiv_restore - enable clocks suffering ++ * from HSDivider PWRDN problem Implements Errata ID: i556. ++ * @clk: DPLL output struct clk ++ * ++ * 3630 only: dpll3_m3_ck, dpll4_m2_ck, dpll4_m3_ck, dpll4_m4_ck, ++ * dpll4_m5_ck & dpll4_m6_ck dividers gets loaded with reset ++ * valueafter their respective PWRDN bits are set. Any dummy write ++ * (Any other value different from the Read value) to the ++ * corresponding CM_CLKSEL register will refresh the dividers. ++ */ ++static int omap36xx_gate_clk_enable_with_hsdiv_restore(struct clk_hw *clk) ++{ ++ struct clk_divider *parent; ++ struct clk_hw *parent_hw; ++ u32 dummy_v, orig_v; ++ int ret; ++ ++ /* Clear PWRDN bit of HSDIVIDER */ ++ ret = omap2_dflt_clk_enable(clk); ++ ++ /* Parent is the x2 node, get parent of parent for the m2 div */ ++ parent_hw = __clk_get_hw(__clk_get_parent(__clk_get_parent(clk->clk))); ++ parent = to_clk_divider(parent_hw); ++ ++ /* Restore the dividers */ ++ if (!ret) { ++ orig_v = __raw_readl(parent->reg); ++ dummy_v = orig_v; ++ ++ /* Write any other value different from the Read value */ ++ dummy_v ^= (1 << parent->shift); ++ __raw_writel(dummy_v, parent->reg); ++ ++ /* Write the original divider */ ++ __raw_writel(orig_v, parent->reg); ++ } ++ ++ return ret; ++} ++ ++static void __init _of_omap_gate_clk_setup(struct device_node *node, ++ void __iomem *reg, ++ const struct clk_ops *ops, ++ const struct clk_hw_omap_ops *hw_ops) ++{ ++ struct clk *clk; ++ struct clk_init_data init = { 0 }; ++ struct clk_hw_omap *clk_hw; ++ const char *clk_name = node->name; ++ const char *parent_name; ++ u32 val; ++ ++ clk_hw = kzalloc(sizeof(*clk_hw), GFP_KERNEL); ++ if (!clk_hw) { ++ pr_err("%s: could not allocate clk_hw_omap\n", __func__); ++ return; ++ } ++ ++ clk_hw->hw.init = &init; ++ ++ of_property_read_string(node, "clock-output-names", &clk_name); ++ ++ init.name = clk_name; ++ init.ops = ops; ++ clk_hw->enable_reg = reg; ++ if (!of_property_read_u32(node, "ti,enable-bit", &val)) ++ clk_hw->enable_bit = val; ++ clk_hw->ops = hw_ops; ++ ++ parent_name = of_clk_get_parent_name(node, 0); ++ init.parent_names = &parent_name; ++ init.num_parents = 1; ++ ++ if (of_property_read_bool(node, "ti,set-rate-parent")) ++ init.flags |= CLK_SET_RATE_PARENT; ++ ++ if (of_property_read_bool(node, "ti,set-bit-to-disable")) ++ clk_hw->flags |= INVERT_ENABLE; ++ ++ clk = clk_register(NULL, &clk_hw->hw); ++ ++ if (!IS_ERR(clk)) ++ of_clk_add_provider(node, of_clk_src_simple_get, clk); ++} ++ ++static void __init of_omap_clkdm_gate_clk_setup(struct device_node *node) ++{ ++ _of_omap_gate_clk_setup(node, NULL, &omap_gate_clkdm_clk_ops, NULL); ++} ++CLK_OF_DECLARE(omap_clkdm_gate_clk, "ti,clkdm-gate-clock", ++ of_omap_clkdm_gate_clk_setup); ++ ++static void __init of_omap_hsdiv_gate_clk_setup(struct device_node *node) ++{ ++ void __iomem *reg = of_iomap(node, 0); ++ _of_omap_gate_clk_setup(node, reg, &omap_gate_clk_hsdiv_restore_ops, ++ &clkhwops_wait); ++} ++CLK_OF_DECLARE(omap_hsdiv_gate_clk, "ti,hsdiv-gate-clock", ++ of_omap_hsdiv_gate_clk_setup); ++ ++static void __init of_omap_gate_clk_setup(struct device_node *node) ++{ ++ void __iomem *reg = of_iomap(node, 0); ++ _of_omap_gate_clk_setup(node, reg, &omap_gate_clk_ops, &clkhwops_wait); ++} ++CLK_OF_DECLARE(omap_gate_clk, "ti,gate-clock", of_omap_gate_clk_setup); ++ ++static void __init of_omap_am35xx_gate_clk_setup(struct device_node *node) ++{ ++ void __iomem *reg = of_iomap(node, 0); ++ _of_omap_gate_clk_setup(node, reg, &omap_gate_clk_ops, ++ &clkhwops_am35xx_ipss_module_wait); ++} ++CLK_OF_DECLARE(omap_am35xx_gate_clk, "ti,am35xx-gate-clock", ++ of_omap_am35xx_gate_clk_setup); ++ ++static void __init of_omap_dss_gate_clk_setup(struct device_node *node) ++{ ++ void __iomem *reg = of_iomap(node, 0); ++ _of_omap_gate_clk_setup(node, reg, &omap_gate_clk_ops, ++ &clkhwops_omap3430es2_dss_usbhost_wait); ++} ++CLK_OF_DECLARE(omap_dss_gate_clk, "ti,dss-gate-clock", ++ of_omap_dss_gate_clk_setup); +--- /dev/null ++++ b/drivers/clk/ti/interface.c +@@ -0,0 +1,124 @@ ++/* ++ * OMAP interface clock support ++ * ++ * Copyright (C) 2013 Texas Instruments, Inc. ++ * ++ * Tero Kristo <t-kristo@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-provider.h> ++#include <linux/slab.h> ++#include <linux/of.h> ++#include <linux/of_address.h> ++#include <linux/clk/ti.h> ++ ++static const struct clk_ops omap_interface_clk_ops = { ++ .init = &omap2_init_clk_clkdm, ++ .enable = &omap2_dflt_clk_enable, ++ .disable = &omap2_dflt_clk_disable, ++ .is_enabled = &omap2_dflt_clk_is_enabled, ++}; ++ ++void __init _of_omap_interface_clk_setup(struct device_node *node, ++ const struct clk_hw_omap_ops *ops) ++{ ++ struct clk *clk; ++ struct clk_init_data init = { 0 }; ++ struct clk_hw_omap *clk_hw; ++ const char *clk_name = node->name; ++ const char *parent_name; ++ u32 val; ++ ++ clk_hw = kzalloc(sizeof(*clk_hw), GFP_KERNEL); ++ if (!clk_hw) { ++ pr_err("%s: could not allocate clk_hw_omap\n", __func__); ++ return; ++ } ++ ++ clk_hw->hw.init = &init; ++ clk_hw->ops = ops; ++ clk_hw->enable_reg = of_iomap(node, 0); ++ ++ if (!of_property_read_u32(node, "ti,enable-bit", &val)) ++ clk_hw->enable_bit = val; ++ ++ of_property_read_string(node, "clock-output-names", &clk_name); ++ ++ init.name = clk_name; ++ init.ops = &omap_interface_clk_ops; ++ init.flags = 0; ++ ++ parent_name = of_clk_get_parent_name(node, 0); ++ if (!parent_name) { ++ pr_err("%s: %s must have a parent\n", __func__, clk_name); ++ goto cleanup; ++ } ++ ++ init.num_parents = 1; ++ init.parent_names = &parent_name; ++ ++ clk = clk_register(NULL, &clk_hw->hw); ++ ++ if (!IS_ERR(clk)) { ++ of_clk_add_provider(node, of_clk_src_simple_get, clk); ++ omap2_init_clk_hw_omap_clocks(clk); ++ return; ++ } ++ ++cleanup: ++ kfree(clk_hw); ++} ++ ++static void __init of_omap_interface_clk_setup(struct device_node *node) ++{ ++ _of_omap_interface_clk_setup(node, &clkhwops_iclk_wait); ++} ++CLK_OF_DECLARE(omap_interface_clk, "ti,omap3-interface-clock", ++ of_omap_interface_clk_setup); ++ ++static void __init of_omap_no_wait_interface_clk_setup(struct device_node *node) ++{ ++ _of_omap_interface_clk_setup(node, &clkhwops_iclk); ++} ++CLK_OF_DECLARE(omap_no_wait_interface_clk, "ti,omap3-no-wait-interface-clock", ++ of_omap_no_wait_interface_clk_setup); ++ ++static void __init ++of_omap_hsotgusb_interface_clk_setup(struct device_node *node) ++{ ++ _of_omap_interface_clk_setup(node, ++ &clkhwops_omap3430es2_iclk_hsotgusb_wait); ++} ++CLK_OF_DECLARE(omap_hsotgusb_interface_clk, "ti,omap3-hsotgusb-interface-clock", ++ of_omap_hsotgusb_interface_clk_setup); ++ ++static void __init of_omap_dss_interface_clk_setup(struct device_node *node) ++{ ++ _of_omap_interface_clk_setup(node, ++ &clkhwops_omap3430es2_iclk_dss_usbhost_wait); ++} ++CLK_OF_DECLARE(omap_dss_interface_clk, "ti,omap3-dss-interface-clock", ++ of_omap_dss_interface_clk_setup); ++ ++static void __init of_omap_ssi_interface_clk_setup(struct device_node *node) ++{ ++ _of_omap_interface_clk_setup(node, &clkhwops_omap3430es2_iclk_ssi_wait); ++} ++CLK_OF_DECLARE(omap_ssi_interface_clk, "ti,omap3-ssi-interface-clock", ++ of_omap_ssi_interface_clk_setup); ++ ++static void __init of_omap_am35xx_interface_clk_setup(struct device_node *node) ++{ ++ _of_omap_interface_clk_setup(node, &clkhwops_am35xx_ipss_wait); ++} ++CLK_OF_DECLARE(omap_am35xx_interface_clk, "ti,am35xx-interface-clock", ++ of_omap_am35xx_interface_clk_setup); +--- /dev/null ++++ b/drivers/clk/ti/Makefile +@@ -0,0 +1,6 @@ ++ifneq ($(CONFIG_OF),) ++obj-y += clk.o dpll.o autoidle.o gate.o \ ++ clockdomain.o apll.o clk-44xx.o \ ++ clk-54xx.o clk-7xx.o clk-33xx.o \ ++ clk-43xx.o interface.o clk-3xxx.o ++endif +--- a/drivers/cpufreq/cpufreq-cpu0.c ++++ b/drivers/cpufreq/cpufreq-cpu0.c +@@ -21,6 +21,7 @@ + #include <linux/platform_device.h> + #include <linux/regulator/consumer.h> + #include <linux/slab.h> ++#include <linux/suspend.h> + + static unsigned int transition_latency; + static unsigned int voltage_tolerance; /* in percentage */ +@@ -29,6 +30,8 @@ static struct device *cpu_dev; + static struct clk *cpu_clk; + static struct regulator *cpu_reg; + static struct cpufreq_frequency_table *freq_table; ++static DEFINE_MUTEX(cpu_lock); ++static bool is_suspended; + + static int cpu0_verify_speed(struct cpufreq_policy *policy) + { +@@ -50,12 +53,19 @@ static int cpu0_set_target(struct cpufre + unsigned int index; + int ret; + ++ mutex_lock(&cpu_lock); ++ ++ if (is_suspended) { ++ ret = -EBUSY; ++ goto out; ++ } ++ + ret = cpufreq_frequency_table_target(policy, freq_table, target_freq, + relation, &index); + if (ret) { + pr_err("failed to match target freqency %d: %d\n", + target_freq, ret); +- return ret; ++ goto out; + } + + freq_Hz = clk_round_rate(cpu_clk, freq_table[index].frequency * 1000); +@@ -65,8 +75,10 @@ static int cpu0_set_target(struct cpufre + freqs.new = freq_Hz / 1000; + freqs.old = clk_get_rate(cpu_clk) / 1000; + +- if (freqs.old == freqs.new) +- return 0; ++ if (freqs.old == freqs.new) { ++ ret = 0; ++ goto out; ++ } + + cpufreq_notify_transition(policy, &freqs, CPUFREQ_PRECHANGE); + +@@ -122,9 +134,32 @@ static int cpu0_set_target(struct cpufre + post_notify: + cpufreq_notify_transition(policy, &freqs, CPUFREQ_POSTCHANGE); + ++out: ++ mutex_unlock(&cpu_lock); + return ret; + } + ++static int cpu0_pm_notify(struct notifier_block *nb, unsigned long event, ++ void *dummy) ++{ ++ mutex_lock(&cpu_lock); ++ switch (event) { ++ case PM_SUSPEND_PREPARE: ++ is_suspended = true; ++ break; ++ case PM_POST_SUSPEND: ++ is_suspended = false; ++ break; ++ } ++ mutex_unlock(&cpu_lock); ++ ++ return NOTIFY_OK; ++} ++ ++static struct notifier_block cpu_pm_notifier = { ++ .notifier_call = cpu0_pm_notify, ++}; ++ + static int cpu0_cpufreq_init(struct cpufreq_policy *policy) + { + int ret; +@@ -147,11 +182,17 @@ static int cpu0_cpufreq_init(struct cpuf + + cpufreq_frequency_table_get_attr(freq_table, policy->cpu); + ++ if (!IS_ERR(cpu_reg)) ++ register_pm_notifier(&cpu_pm_notifier); ++ + return 0; + } + + static int cpu0_cpufreq_exit(struct cpufreq_policy *policy) + { ++ if (!IS_ERR(cpu_reg)) ++ unregister_pm_notifier(&cpu_pm_notifier); ++ + cpufreq_frequency_table_put_attr(policy->cpu); + + return 0; +--- a/drivers/crypto/Kconfig ++++ b/drivers/crypto/Kconfig +@@ -263,6 +263,17 @@ config CRYPTO_DEV_OMAP_AES + OMAP processors have AES module accelerator. Select this if you + want to use the OMAP module for AES algorithms. + ++config CRYPTO_DEV_OMAP_DES ++ tristate "Support for OMAP DES3DES hw engine" ++ depends on ARCH_OMAP2PLUS ++ select CRYPTO_DES ++ select CRYPTO_BLKCIPHER2 ++ help ++ OMAP processors have DES/3DES module accelerator. Select this if you ++ want to use the OMAP module for DES and 3DES algorithms. Currently ++ the ECB and CBC modes of operation supported by the driver. Also ++ accesses made on unaligned boundaries are also supported. ++ + config CRYPTO_DEV_PICOXCELL + tristate "Support for picoXcell IPSEC and Layer2 crypto engines" + depends on ARCH_PICOXCELL && HAVE_CLK +--- a/drivers/crypto/Makefile ++++ b/drivers/crypto/Makefile +@@ -11,6 +11,7 @@ obj-$(CONFIG_CRYPTO_DEV_IXP4XX) += ixp4x + obj-$(CONFIG_CRYPTO_DEV_PPC4XX) += amcc/ + obj-$(CONFIG_CRYPTO_DEV_OMAP_SHAM) += omap-sham.o + obj-$(CONFIG_CRYPTO_DEV_OMAP_AES) += omap-aes.o ++obj-$(CONFIG_CRYPTO_DEV_OMAP_DES) += omap-des.o + obj-$(CONFIG_CRYPTO_DEV_PICOXCELL) += picoxcell_crypto.o + obj-$(CONFIG_CRYPTO_DEV_SAHARA) += sahara.o + obj-$(CONFIG_CRYPTO_DEV_DCP) += dcp.o +--- a/drivers/crypto/omap-aes.c ++++ b/drivers/crypto/omap-aes.c +@@ -275,7 +275,7 @@ static int omap_aes_write_ctrl(struct om + if (dd->flags & FLAGS_CBC) + val |= AES_REG_CTRL_CBC; + if (dd->flags & FLAGS_CTR) { +- val |= AES_REG_CTRL_CTR | AES_REG_CTRL_CTR_WIDTH_32; ++ val |= AES_REG_CTRL_CTR | AES_REG_CTRL_CTR_WIDTH_128; + mask = AES_REG_CTRL_CTR | AES_REG_CTRL_CTR_WIDTH_MASK; + } + if (dd->flags & FLAGS_ENCRYPT) +--- /dev/null ++++ b/drivers/crypto/omap-des.c +@@ -0,0 +1,1239 @@ ++/* ++ * Cryptographic API. ++ * ++ * Support for OMAP DES and Triple DES HW acceleration. ++ * ++ * Copyright (c) 2012 Texas Instruments Incorporated ++ * Author: Joel Fernandes <joelf@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. ++ * ++ */ ++ ++#define pr_fmt(fmt) "%s: " fmt, __func__ ++ ++#ifdef DEBUG ++#define prn(num) printk(#num "=%d\n", num) ++#define prx(num) printk(#num "=%x\n", num) ++#else ++#define prn(num) do { } while (0) ++#define prx(num) do { } while (0) ++#endif ++ ++#include <linux/err.h> ++#include <linux/module.h> ++#include <linux/init.h> ++#include <linux/errno.h> ++#include <linux/kernel.h> ++#include <linux/platform_device.h> ++#include <linux/scatterlist.h> ++#include <linux/dma-mapping.h> ++#include <linux/dmaengine.h> ++#include <linux/omap-dma.h> ++#include <linux/pm_runtime.h> ++#include <linux/of.h> ++#include <linux/of_device.h> ++#include <linux/of_address.h> ++#include <linux/io.h> ++#include <linux/crypto.h> ++#include <linux/interrupt.h> ++#include <crypto/scatterwalk.h> ++#include <crypto/des.h> ++ ++#define DST_MAXBURST 2 ++ ++#define DES_BLOCK_WORDS (DES_BLOCK_SIZE >> 2) ++ ++#define _calc_walked(inout) (dd->inout##_walk.offset - dd->inout##_sg->offset) ++ ++#define DES_REG_KEY(dd, x) ((dd)->pdata->key_ofs - \ ++ ((x ^ 0x01) * 0x04)) ++ ++#define DES_REG_IV(dd, x) ((dd)->pdata->iv_ofs + ((x) * 0x04)) ++ ++#define DES_REG_CTRL(dd) ((dd)->pdata->ctrl_ofs) ++#define DES_REG_CTRL_CBC (1 << 4) ++#define DES_REG_CTRL_TDES (1 << 3) ++#define DES_REG_CTRL_DIRECTION (1 << 2) ++#define DES_REG_CTRL_INPUT_READY (1 << 1) ++#define DES_REG_CTRL_OUTPUT_READY (1 << 0) ++ ++#define DES_REG_DATA_N(dd, x) ((dd)->pdata->data_ofs + ((x) * 0x04)) ++ ++#define DES_REG_REV(dd) ((dd)->pdata->rev_ofs) ++ ++#define DES_REG_MASK(dd) ((dd)->pdata->mask_ofs) ++ ++#define DES_REG_LENGTH_N(x) (0x24 + ((x) * 0x04)) ++ ++#define DES_REG_IRQ_STATUS(dd) ((dd)->pdata->irq_status_ofs) ++#define DES_REG_IRQ_ENABLE(dd) ((dd)->pdata->irq_enable_ofs) ++#define DES_REG_IRQ_DATA_IN BIT(1) ++#define DES_REG_IRQ_DATA_OUT BIT(2) ++ ++#define FLAGS_MODE_MASK 0x000f ++#define FLAGS_ENCRYPT BIT(0) ++#define FLAGS_CBC BIT(1) ++#define FLAGS_INIT BIT(4) ++#define FLAGS_BUSY BIT(6) ++ ++struct omap_des_ctx { ++ struct omap_des_dev *dd; ++ ++ int keylen; ++ u32 key[(3 * DES_KEY_SIZE) / sizeof(u32)]; ++ unsigned long flags; ++}; ++ ++struct omap_des_reqctx { ++ unsigned long mode; ++}; ++ ++#define OMAP_DES_QUEUE_LENGTH 1 ++#define OMAP_DES_CACHE_SIZE 0 ++ ++struct omap_des_algs_info { ++ struct crypto_alg *algs_list; ++ unsigned int size; ++ unsigned int registered; ++}; ++ ++struct omap_des_pdata { ++ struct omap_des_algs_info *algs_info; ++ unsigned int algs_info_size; ++ ++ void (*trigger)(struct omap_des_dev *dd, int length); ++ ++ u32 key_ofs; ++ u32 iv_ofs; ++ u32 ctrl_ofs; ++ u32 data_ofs; ++ u32 rev_ofs; ++ u32 mask_ofs; ++ u32 irq_enable_ofs; ++ u32 irq_status_ofs; ++ ++ u32 dma_enable_in; ++ u32 dma_enable_out; ++ u32 dma_start; ++ ++ u32 major_mask; ++ u32 major_shift; ++ u32 minor_mask; ++ u32 minor_shift; ++}; ++ ++struct omap_des_dev { ++ struct list_head list; ++ unsigned long phys_base; ++ void __iomem *io_base; ++ struct omap_des_ctx *ctx; ++ struct device *dev; ++ unsigned long flags; ++ int err; ++ ++ /* spinlock used for queues */ ++ spinlock_t lock; ++ struct crypto_queue queue; ++ ++ struct tasklet_struct done_task; ++ struct tasklet_struct queue_task; ++ ++ struct ablkcipher_request *req; ++ /* ++ * total is used by PIO mode for book keeping so introduce ++ * variable total_save as need it to calc page_order ++ */ ++ size_t total; ++ size_t total_save; ++ ++ struct scatterlist *in_sg; ++ struct scatterlist *out_sg; ++ ++ /* Buffers for copying for unaligned cases */ ++ struct scatterlist in_sgl; ++ struct scatterlist out_sgl; ++ struct scatterlist *orig_out; ++ int sgs_copied; ++ ++ struct scatter_walk in_walk; ++ struct scatter_walk out_walk; ++ int dma_in; ++ struct dma_chan *dma_lch_in; ++ int dma_out; ++ struct dma_chan *dma_lch_out; ++ int in_sg_len; ++ int out_sg_len; ++ int pio_only; ++ const struct omap_des_pdata *pdata; ++}; ++ ++/* keep registered devices data here */ ++static LIST_HEAD(dev_list); ++static DEFINE_SPINLOCK(list_lock); ++ ++#ifdef DEBUG ++#define omap_des_read(dd, offset) \ ++ ({ \ ++ int _read_ret; \ ++ _read_ret = __raw_readl(dd->io_base + offset); \ ++ pr_err("omap_des_read(" #offset "=%#x)= %#x\n", \ ++ offset, _read_ret); \ ++ _read_ret; \ ++ }) ++#else ++static inline u32 omap_des_read(struct omap_des_dev *dd, u32 offset) ++{ ++ return __raw_readl(dd->io_base + offset); ++} ++#endif ++ ++#ifdef DEBUG ++#define omap_des_write(dd, offset, value) \ ++ do { \ ++ pr_err("omap_des_write(" #offset "=%#x) value=%#x\n", \ ++ offset, value); \ ++ __raw_writel(value, dd->io_base + offset); \ ++ } while (0) ++#else ++static inline void omap_des_write(struct omap_des_dev *dd, u32 offset, ++ u32 value) ++{ ++ __raw_writel(value, dd->io_base + offset); ++} ++#endif ++ ++static inline void omap_des_write_mask(struct omap_des_dev *dd, u32 offset, ++ u32 value, u32 mask) ++{ ++ u32 val; ++ ++ val = omap_des_read(dd, offset); ++ val &= ~mask; ++ val |= value; ++ omap_des_write(dd, offset, val); ++} ++ ++static void omap_des_write_n(struct omap_des_dev *dd, u32 offset, ++ u32 *value, int count) ++{ ++ for (; count--; value++, offset += 4) ++ omap_des_write(dd, offset, *value); ++} ++ ++static int omap_des_hw_init(struct omap_des_dev *dd) ++{ ++ /* ++ * clocks are enabled when request starts and disabled when finished. ++ * It may be long delays between requests. ++ * Device might go to off mode to save power. ++ */ ++ pm_runtime_get_sync(dd->dev); ++ ++ if (!(dd->flags & FLAGS_INIT)) { ++ dd->flags |= FLAGS_INIT; ++ dd->err = 0; ++ } ++ ++ return 0; ++} ++ ++static int omap_des_write_ctrl(struct omap_des_dev *dd) ++{ ++ unsigned int key32; ++ int i, err; ++ u32 val = 0, mask = 0; ++ ++ err = omap_des_hw_init(dd); ++ if (err) ++ return err; ++ ++ key32 = dd->ctx->keylen / sizeof(u32); ++ ++ /* it seems a key should always be set even if it has not changed */ ++ for (i = 0; i < key32; i++) { ++ omap_des_write(dd, DES_REG_KEY(dd, i), ++ __le32_to_cpu(dd->ctx->key[i])); ++ } ++ ++ if ((dd->flags & FLAGS_CBC) && dd->req->info) ++ omap_des_write_n(dd, DES_REG_IV(dd, 0), dd->req->info, 2); ++ ++ if (dd->flags & FLAGS_CBC) ++ val |= DES_REG_CTRL_CBC; ++ if (dd->flags & FLAGS_ENCRYPT) ++ val |= DES_REG_CTRL_DIRECTION; ++ if (key32 == 6) ++ val |= DES_REG_CTRL_TDES; ++ ++ mask |= DES_REG_CTRL_CBC | DES_REG_CTRL_DIRECTION | DES_REG_CTRL_TDES; ++ ++ omap_des_write_mask(dd, DES_REG_CTRL(dd), val, mask); ++ ++ return 0; ++} ++ ++static void omap_des_dma_trigger_omap4(struct omap_des_dev *dd, int length) ++{ ++ u32 mask, val; ++ ++ omap_des_write(dd, DES_REG_LENGTH_N(0), length); ++ ++ val = dd->pdata->dma_start; ++ ++ if (dd->dma_lch_out != NULL) ++ val |= dd->pdata->dma_enable_out; ++ if (dd->dma_lch_in != NULL) ++ val |= dd->pdata->dma_enable_in; ++ ++ mask = dd->pdata->dma_enable_out | dd->pdata->dma_enable_in | ++ dd->pdata->dma_start; ++ ++ omap_des_write_mask(dd, DES_REG_MASK(dd), val, mask); ++} ++ ++static void omap_des_dma_stop(struct omap_des_dev *dd) ++{ ++ u32 mask; ++ ++ mask = dd->pdata->dma_enable_out | dd->pdata->dma_enable_in | ++ dd->pdata->dma_start; ++ ++ omap_des_write_mask(dd, DES_REG_MASK(dd), 0, mask); ++} ++ ++static struct omap_des_dev *omap_des_find_dev(struct omap_des_ctx *ctx) ++{ ++ struct omap_des_dev *dd = NULL, *tmp; ++ ++ spin_lock_bh(&list_lock); ++ if (!ctx->dd) { ++ list_for_each_entry(tmp, &dev_list, list) { ++ /* FIXME: take fist available des core */ ++ dd = tmp; ++ break; ++ } ++ ctx->dd = dd; ++ } else { ++ /* already found before */ ++ dd = ctx->dd; ++ } ++ spin_unlock_bh(&list_lock); ++ ++ return dd; ++} ++ ++static void omap_des_dma_out_callback(void *data) ++{ ++ struct omap_des_dev *dd = data; ++ ++ /* dma_lch_out - completed */ ++ tasklet_schedule(&dd->done_task); ++} ++ ++static int omap_des_dma_init(struct omap_des_dev *dd) ++{ ++ int err = -ENOMEM; ++ dma_cap_mask_t mask; ++ ++ dd->dma_lch_out = NULL; ++ dd->dma_lch_in = NULL; ++ ++ dma_cap_zero(mask); ++ dma_cap_set(DMA_SLAVE, mask); ++ ++ dd->dma_lch_in = dma_request_slave_channel_compat(mask, ++ omap_dma_filter_fn, ++ &dd->dma_in, ++ dd->dev, "rx"); ++ if (!dd->dma_lch_in) { ++ dev_err(dd->dev, "Unable to request in DMA channel\n"); ++ goto err_dma_in; ++ } ++ ++ dd->dma_lch_out = dma_request_slave_channel_compat(mask, ++ omap_dma_filter_fn, ++ &dd->dma_out, ++ dd->dev, "tx"); ++ if (!dd->dma_lch_out) { ++ dev_err(dd->dev, "Unable to request out DMA channel\n"); ++ goto err_dma_out; ++ } ++ ++ return 0; ++ ++err_dma_out: ++ dma_release_channel(dd->dma_lch_in); ++err_dma_in: ++ if (err) ++ pr_err("error: %d\n", err); ++ return err; ++} ++ ++static void omap_des_dma_cleanup(struct omap_des_dev *dd) ++{ ++ dma_release_channel(dd->dma_lch_out); ++ dma_release_channel(dd->dma_lch_in); ++} ++ ++static void sg_copy_buf(void *buf, struct scatterlist *sg, ++ unsigned int start, unsigned int nbytes, int out) ++{ ++ struct scatter_walk walk; ++ ++ if (!nbytes) ++ return; ++ ++ scatterwalk_start(&walk, sg); ++ scatterwalk_advance(&walk, start); ++ scatterwalk_copychunks(buf, &walk, nbytes, out); ++ scatterwalk_done(&walk, out, 0); ++} ++ ++static int omap_des_crypt_dma(struct crypto_tfm *tfm, ++ struct scatterlist *in_sg, struct scatterlist *out_sg, ++ int in_sg_len, int out_sg_len) ++{ ++ struct omap_des_ctx *ctx = crypto_tfm_ctx(tfm); ++ struct omap_des_dev *dd = ctx->dd; ++ struct dma_async_tx_descriptor *tx_in, *tx_out; ++ struct dma_slave_config cfg; ++ int ret; ++ ++ if (dd->pio_only) { ++ scatterwalk_start(&dd->in_walk, dd->in_sg); ++ scatterwalk_start(&dd->out_walk, dd->out_sg); ++ ++ /* Enable DATAIN interrupt and let it take ++ care of the rest */ ++ omap_des_write(dd, DES_REG_IRQ_ENABLE(dd), 0x2); ++ return 0; ++ } ++ ++ dma_sync_sg_for_device(dd->dev, dd->in_sg, in_sg_len, DMA_TO_DEVICE); ++ ++ memset(&cfg, 0, sizeof(cfg)); ++ ++ cfg.src_addr = dd->phys_base + DES_REG_DATA_N(dd, 0); ++ cfg.dst_addr = dd->phys_base + DES_REG_DATA_N(dd, 0); ++ cfg.src_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES; ++ cfg.dst_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES; ++ cfg.src_maxburst = DST_MAXBURST; ++ cfg.dst_maxburst = DST_MAXBURST; ++ ++ /* IN */ ++ ret = dmaengine_slave_config(dd->dma_lch_in, &cfg); ++ if (ret) { ++ dev_err(dd->dev, "can't configure IN dmaengine slave: %d\n", ++ ret); ++ return ret; ++ } ++ ++ tx_in = dmaengine_prep_slave_sg(dd->dma_lch_in, in_sg, in_sg_len, ++ DMA_MEM_TO_DEV, ++ DMA_PREP_INTERRUPT | DMA_CTRL_ACK); ++ if (!tx_in) { ++ dev_err(dd->dev, "IN prep_slave_sg() failed\n"); ++ return -EINVAL; ++ } ++ ++ /* No callback necessary */ ++ tx_in->callback_param = dd; ++ ++ /* OUT */ ++ ret = dmaengine_slave_config(dd->dma_lch_out, &cfg); ++ if (ret) { ++ dev_err(dd->dev, "can't configure OUT dmaengine slave: %d\n", ++ ret); ++ return ret; ++ } ++ ++ tx_out = dmaengine_prep_slave_sg(dd->dma_lch_out, out_sg, out_sg_len, ++ DMA_DEV_TO_MEM, ++ DMA_PREP_INTERRUPT | DMA_CTRL_ACK); ++ if (!tx_out) { ++ dev_err(dd->dev, "OUT prep_slave_sg() failed\n"); ++ return -EINVAL; ++ } ++ ++ tx_out->callback = omap_des_dma_out_callback; ++ tx_out->callback_param = dd; ++ ++ dmaengine_submit(tx_in); ++ dmaengine_submit(tx_out); ++ ++ dma_async_issue_pending(dd->dma_lch_in); ++ dma_async_issue_pending(dd->dma_lch_out); ++ ++ /* start DMA */ ++ dd->pdata->trigger(dd, dd->total); ++ ++ return 0; ++} ++ ++static int omap_des_crypt_dma_start(struct omap_des_dev *dd) ++{ ++ struct crypto_tfm *tfm = crypto_ablkcipher_tfm( ++ crypto_ablkcipher_reqtfm(dd->req)); ++ int err; ++ ++ pr_debug("total: %d\n", dd->total); ++ ++ if (!dd->pio_only) { ++ err = dma_map_sg(dd->dev, dd->in_sg, dd->in_sg_len, ++ DMA_TO_DEVICE); ++ if (!err) { ++ dev_err(dd->dev, "dma_map_sg() error\n"); ++ return -EINVAL; ++ } ++ ++ err = dma_map_sg(dd->dev, dd->out_sg, dd->out_sg_len, ++ DMA_FROM_DEVICE); ++ if (!err) { ++ dev_err(dd->dev, "dma_map_sg() error\n"); ++ return -EINVAL; ++ } ++ } ++ ++ err = omap_des_crypt_dma(tfm, dd->in_sg, dd->out_sg, dd->in_sg_len, ++ dd->out_sg_len); ++ if (err && !dd->pio_only) { ++ dma_unmap_sg(dd->dev, dd->in_sg, dd->in_sg_len, DMA_TO_DEVICE); ++ dma_unmap_sg(dd->dev, dd->out_sg, dd->out_sg_len, ++ DMA_FROM_DEVICE); ++ } ++ ++ return err; ++} ++ ++static void omap_des_finish_req(struct omap_des_dev *dd, int err) ++{ ++ struct ablkcipher_request *req = dd->req; ++ ++ pr_debug("err: %d\n", err); ++ ++ pm_runtime_put(dd->dev); ++ dd->flags &= ~FLAGS_BUSY; ++ ++ req->base.complete(&req->base, err); ++} ++ ++static int omap_des_crypt_dma_stop(struct omap_des_dev *dd) ++{ ++ int err = 0; ++ ++ pr_debug("total: %d\n", dd->total); ++ ++ omap_des_dma_stop(dd); ++ ++ dmaengine_terminate_all(dd->dma_lch_in); ++ dmaengine_terminate_all(dd->dma_lch_out); ++ ++ dma_unmap_sg(dd->dev, dd->in_sg, dd->in_sg_len, DMA_TO_DEVICE); ++ dma_unmap_sg(dd->dev, dd->out_sg, dd->out_sg_len, DMA_FROM_DEVICE); ++ ++ return err; ++} ++ ++int omap_des_copy_needed(struct scatterlist *sg) ++{ ++ while (sg) { ++ if (!IS_ALIGNED(sg->offset, 4)) ++ return -1; ++ if (!IS_ALIGNED(sg->length, DES_BLOCK_SIZE)) ++ return -1; ++ sg = sg_next(sg); ++ } ++ return 0; ++} ++ ++int omap_des_copy_sgs(struct omap_des_dev *dd) ++{ ++ void *buf_in, *buf_out; ++ int pages; ++ ++ pages = dd->total >> PAGE_SHIFT; ++ ++ if (dd->total & (PAGE_SIZE-1)) ++ pages++; ++ ++ BUG_ON(!pages); ++ ++ buf_in = (void *)__get_free_pages(GFP_ATOMIC, pages); ++ buf_out = (void *)__get_free_pages(GFP_ATOMIC, pages); ++ ++ if (!buf_in || !buf_out) { ++ pr_err("Couldn't allocated pages for unaligned cases.\n"); ++ return -1; ++ } ++ ++ dd->orig_out = dd->out_sg; ++ ++ sg_copy_buf(buf_in, dd->in_sg, 0, dd->total, 0); ++ ++ sg_init_table(&dd->in_sgl, 1); ++ sg_set_buf(&dd->in_sgl, buf_in, dd->total); ++ dd->in_sg = &dd->in_sgl; ++ ++ sg_init_table(&dd->out_sgl, 1); ++ sg_set_buf(&dd->out_sgl, buf_out, dd->total); ++ dd->out_sg = &dd->out_sgl; ++ ++ return 0; ++} ++ ++static int omap_des_handle_queue(struct omap_des_dev *dd, ++ struct ablkcipher_request *req) ++{ ++ struct crypto_async_request *async_req, *backlog; ++ struct omap_des_ctx *ctx; ++ struct omap_des_reqctx *rctx; ++ unsigned long flags; ++ int err, ret = 0; ++ ++ spin_lock_irqsave(&dd->lock, flags); ++ if (req) ++ ret = ablkcipher_enqueue_request(&dd->queue, req); ++ if (dd->flags & FLAGS_BUSY) { ++ spin_unlock_irqrestore(&dd->lock, flags); ++ return ret; ++ } ++ backlog = crypto_get_backlog(&dd->queue); ++ async_req = crypto_dequeue_request(&dd->queue); ++ if (async_req) ++ dd->flags |= FLAGS_BUSY; ++ spin_unlock_irqrestore(&dd->lock, flags); ++ ++ if (!async_req) ++ return ret; ++ ++ if (backlog) ++ backlog->complete(backlog, -EINPROGRESS); ++ ++ req = ablkcipher_request_cast(async_req); ++ ++ /* assign new request to device */ ++ dd->req = req; ++ dd->total = req->nbytes; ++ dd->total_save = req->nbytes; ++ dd->in_sg = req->src; ++ dd->out_sg = req->dst; ++ ++ if (omap_des_copy_needed(dd->in_sg) || ++ omap_des_copy_needed(dd->out_sg)) { ++ if (omap_des_copy_sgs(dd)) ++ pr_err("Failed to copy SGs for unaligned cases\n"); ++ dd->sgs_copied = 1; ++ } else { ++ dd->sgs_copied = 0; ++ } ++ ++ dd->in_sg_len = scatterwalk_bytes_sglen(dd->in_sg, dd->total); ++ dd->out_sg_len = scatterwalk_bytes_sglen(dd->out_sg, dd->total); ++ BUG_ON(dd->in_sg_len < 0 || dd->out_sg_len < 0); ++ ++ rctx = ablkcipher_request_ctx(req); ++ ctx = crypto_ablkcipher_ctx(crypto_ablkcipher_reqtfm(req)); ++ rctx->mode &= FLAGS_MODE_MASK; ++ dd->flags = (dd->flags & ~FLAGS_MODE_MASK) | rctx->mode; ++ ++ dd->ctx = ctx; ++ ctx->dd = dd; ++ ++ err = omap_des_write_ctrl(dd); ++ if (!err) ++ err = omap_des_crypt_dma_start(dd); ++ if (err) { ++ /* des_task will not finish it, so do it here */ ++ omap_des_finish_req(dd, err); ++ tasklet_schedule(&dd->queue_task); ++ } ++ ++ return ret; /* return ret, which is enqueue return value */ ++} ++ ++static void omap_des_done_task(unsigned long data) ++{ ++ struct omap_des_dev *dd = (struct omap_des_dev *)data; ++ void *buf_in, *buf_out; ++ int pages; ++ ++ pr_debug("enter done_task\n"); ++ ++ if (!dd->pio_only) { ++ dma_sync_sg_for_device(dd->dev, dd->out_sg, dd->out_sg_len, ++ DMA_FROM_DEVICE); ++ dma_unmap_sg(dd->dev, dd->in_sg, dd->in_sg_len, DMA_TO_DEVICE); ++ dma_unmap_sg(dd->dev, dd->out_sg, dd->out_sg_len, ++ DMA_FROM_DEVICE); ++ omap_des_crypt_dma_stop(dd); ++ } ++ ++ if (dd->sgs_copied) { ++ buf_in = sg_virt(&dd->in_sgl); ++ buf_out = sg_virt(&dd->out_sgl); ++ ++ sg_copy_buf(buf_out, dd->orig_out, 0, dd->total_save, 1); ++ ++ pages = get_order(dd->total_save); ++ free_pages((unsigned long)buf_in, pages); ++ free_pages((unsigned long)buf_out, pages); ++ } ++ ++ omap_des_finish_req(dd, 0); ++ omap_des_handle_queue(dd, NULL); ++ ++ pr_debug("exit\n"); ++} ++ ++static void omap_des_queue_task(unsigned long data) ++{ ++ struct omap_des_dev *dd = (struct omap_des_dev *)data; ++ ++ omap_des_handle_queue(dd, NULL); ++} ++ ++static int omap_des_crypt(struct ablkcipher_request *req, unsigned long mode) ++{ ++ struct omap_des_ctx *ctx = crypto_ablkcipher_ctx( ++ crypto_ablkcipher_reqtfm(req)); ++ struct omap_des_reqctx *rctx = ablkcipher_request_ctx(req); ++ struct omap_des_dev *dd; ++ ++ pr_debug("nbytes: %d, enc: %d, cbc: %d\n", req->nbytes, ++ !!(mode & FLAGS_ENCRYPT), ++ !!(mode & FLAGS_CBC)); ++ ++ if (!IS_ALIGNED(req->nbytes, DES_BLOCK_SIZE)) { ++ pr_err("request size is not exact amount of DES blocks\n"); ++ return -EINVAL; ++ } ++ ++ dd = omap_des_find_dev(ctx); ++ if (!dd) ++ return -ENODEV; ++ ++ rctx->mode = mode; ++ ++ return omap_des_handle_queue(dd, req); ++} ++ ++/* ********************** ALG API ************************************ */ ++ ++static int omap_des_setkey(struct crypto_ablkcipher *tfm, const u8 *key, ++ unsigned int keylen) ++{ ++ struct omap_des_ctx *ctx = crypto_ablkcipher_ctx(tfm); ++ ++ if (keylen != DES_KEY_SIZE && keylen != (3*DES_KEY_SIZE)) ++ return -EINVAL; ++ ++ pr_debug("enter, keylen: %d\n", keylen); ++ ++ memcpy(ctx->key, key, keylen); ++ ctx->keylen = keylen; ++ ++ return 0; ++} ++ ++static int omap_des_ecb_encrypt(struct ablkcipher_request *req) ++{ ++ return omap_des_crypt(req, FLAGS_ENCRYPT); ++} ++ ++static int omap_des_ecb_decrypt(struct ablkcipher_request *req) ++{ ++ return omap_des_crypt(req, 0); ++} ++ ++static int omap_des_cbc_encrypt(struct ablkcipher_request *req) ++{ ++ return omap_des_crypt(req, FLAGS_ENCRYPT | FLAGS_CBC); ++} ++ ++static int omap_des_cbc_decrypt(struct ablkcipher_request *req) ++{ ++ return omap_des_crypt(req, FLAGS_CBC); ++} ++ ++static int omap_des_cra_init(struct crypto_tfm *tfm) ++{ ++ pr_debug("enter\n"); ++ ++ tfm->crt_ablkcipher.reqsize = sizeof(struct omap_des_reqctx); ++ ++ return 0; ++} ++ ++static void omap_des_cra_exit(struct crypto_tfm *tfm) ++{ ++ pr_debug("enter\n"); ++} ++ ++/* ********************** ALGS ************************************ */ ++ ++static struct crypto_alg algs_ecb_cbc[] = { ++{ ++ .cra_name = "ecb(des)", ++ .cra_driver_name = "ecb-des-omap", ++ .cra_priority = 100, ++ .cra_flags = CRYPTO_ALG_TYPE_ABLKCIPHER | ++ CRYPTO_ALG_KERN_DRIVER_ONLY | ++ CRYPTO_ALG_ASYNC, ++ .cra_blocksize = DES_BLOCK_SIZE, ++ .cra_ctxsize = sizeof(struct omap_des_ctx), ++ .cra_alignmask = 0, ++ .cra_type = &crypto_ablkcipher_type, ++ .cra_module = THIS_MODULE, ++ .cra_init = omap_des_cra_init, ++ .cra_exit = omap_des_cra_exit, ++ .cra_u.ablkcipher = { ++ .min_keysize = DES_KEY_SIZE, ++ .max_keysize = DES_KEY_SIZE, ++ .setkey = omap_des_setkey, ++ .encrypt = omap_des_ecb_encrypt, ++ .decrypt = omap_des_ecb_decrypt, ++ } ++}, ++{ ++ .cra_name = "cbc(des)", ++ .cra_driver_name = "cbc-des-omap", ++ .cra_priority = 100, ++ .cra_flags = CRYPTO_ALG_TYPE_ABLKCIPHER | ++ CRYPTO_ALG_KERN_DRIVER_ONLY | ++ CRYPTO_ALG_ASYNC, ++ .cra_blocksize = DES_BLOCK_SIZE, ++ .cra_ctxsize = sizeof(struct omap_des_ctx), ++ .cra_alignmask = 0, ++ .cra_type = &crypto_ablkcipher_type, ++ .cra_module = THIS_MODULE, ++ .cra_init = omap_des_cra_init, ++ .cra_exit = omap_des_cra_exit, ++ .cra_u.ablkcipher = { ++ .min_keysize = DES_KEY_SIZE, ++ .max_keysize = DES_KEY_SIZE, ++ .ivsize = DES_BLOCK_SIZE, ++ .setkey = omap_des_setkey, ++ .encrypt = omap_des_cbc_encrypt, ++ .decrypt = omap_des_cbc_decrypt, ++ } ++}, ++{ ++ .cra_name = "ecb(des3_ede)", ++ .cra_driver_name = "ecb-des3-omap", ++ .cra_priority = 100, ++ .cra_flags = CRYPTO_ALG_TYPE_ABLKCIPHER | ++ CRYPTO_ALG_KERN_DRIVER_ONLY | ++ CRYPTO_ALG_ASYNC, ++ .cra_blocksize = DES_BLOCK_SIZE, ++ .cra_ctxsize = sizeof(struct omap_des_ctx), ++ .cra_alignmask = 0, ++ .cra_type = &crypto_ablkcipher_type, ++ .cra_module = THIS_MODULE, ++ .cra_init = omap_des_cra_init, ++ .cra_exit = omap_des_cra_exit, ++ .cra_u.ablkcipher = { ++ .min_keysize = 3*DES_KEY_SIZE, ++ .max_keysize = 3*DES_KEY_SIZE, ++ .setkey = omap_des_setkey, ++ .encrypt = omap_des_ecb_encrypt, ++ .decrypt = omap_des_ecb_decrypt, ++ } ++}, ++{ ++ .cra_name = "cbc(des3_ede)", ++ .cra_driver_name = "cbc-des3-omap", ++ .cra_priority = 100, ++ .cra_flags = CRYPTO_ALG_TYPE_ABLKCIPHER | ++ CRYPTO_ALG_KERN_DRIVER_ONLY | ++ CRYPTO_ALG_ASYNC, ++ .cra_blocksize = DES_BLOCK_SIZE, ++ .cra_ctxsize = sizeof(struct omap_des_ctx), ++ .cra_alignmask = 0, ++ .cra_type = &crypto_ablkcipher_type, ++ .cra_module = THIS_MODULE, ++ .cra_init = omap_des_cra_init, ++ .cra_exit = omap_des_cra_exit, ++ .cra_u.ablkcipher = { ++ .min_keysize = 3*DES_KEY_SIZE, ++ .max_keysize = 3*DES_KEY_SIZE, ++ .ivsize = DES_BLOCK_SIZE, ++ .setkey = omap_des_setkey, ++ .encrypt = omap_des_cbc_encrypt, ++ .decrypt = omap_des_cbc_decrypt, ++ } ++} ++}; ++ ++static struct omap_des_algs_info omap_des_algs_info_ecb_cbc[] = { ++ { ++ .algs_list = algs_ecb_cbc, ++ .size = ARRAY_SIZE(algs_ecb_cbc), ++ }, ++}; ++ ++#ifdef CONFIG_OF ++static const struct omap_des_pdata omap_des_pdata_omap4 = { ++ .algs_info = omap_des_algs_info_ecb_cbc, ++ .algs_info_size = ARRAY_SIZE(omap_des_algs_info_ecb_cbc), ++ .trigger = omap_des_dma_trigger_omap4, ++ .key_ofs = 0x14, ++ .iv_ofs = 0x18, ++ .ctrl_ofs = 0x20, ++ .data_ofs = 0x28, ++ .rev_ofs = 0x30, ++ .mask_ofs = 0x34, ++ .irq_status_ofs = 0x3c, ++ .irq_enable_ofs = 0x40, ++ .dma_enable_in = BIT(5), ++ .dma_enable_out = BIT(6), ++ .major_mask = 0x0700, ++ .major_shift = 8, ++ .minor_mask = 0x003f, ++ .minor_shift = 0, ++}; ++ ++static irqreturn_t omap_des_irq(int irq, void *dev_id) ++{ ++ struct omap_des_dev *dd = dev_id; ++ u32 status, i; ++ u32 *src, *dst; ++ ++ status = omap_des_read(dd, DES_REG_IRQ_STATUS(dd)); ++ if (status & DES_REG_IRQ_DATA_IN) { ++ omap_des_write(dd, DES_REG_IRQ_ENABLE(dd), 0x0); ++ ++ BUG_ON(!dd->in_sg); ++ ++ BUG_ON(_calc_walked(in) > dd->in_sg->length); ++ ++ src = sg_virt(dd->in_sg) + _calc_walked(in); ++ ++ for (i = 0; i < DES_BLOCK_WORDS; i++) { ++ omap_des_write(dd, DES_REG_DATA_N(dd, i), *src); ++ ++ scatterwalk_advance(&dd->in_walk, 4); ++ if (dd->in_sg->length == _calc_walked(in)) { ++ dd->in_sg = scatterwalk_sg_next(dd->in_sg); ++ if (dd->in_sg) { ++ scatterwalk_start(&dd->in_walk, ++ dd->in_sg); ++ src = sg_virt(dd->in_sg) + ++ _calc_walked(in); ++ } ++ } else { ++ src++; ++ } ++ } ++ ++ /* Clear IRQ status */ ++ status &= ~DES_REG_IRQ_DATA_IN; ++ omap_des_write(dd, DES_REG_IRQ_STATUS(dd), status); ++ ++ /* Enable DATA_OUT interrupt */ ++ omap_des_write(dd, DES_REG_IRQ_ENABLE(dd), 0x4); ++ ++ } else if (status & DES_REG_IRQ_DATA_OUT) { ++ omap_des_write(dd, DES_REG_IRQ_ENABLE(dd), 0x0); ++ ++ BUG_ON(!dd->out_sg); ++ ++ BUG_ON(_calc_walked(out) > dd->out_sg->length); ++ ++ dst = sg_virt(dd->out_sg) + _calc_walked(out); ++ ++ for (i = 0; i < DES_BLOCK_WORDS; i++) { ++ *dst = omap_des_read(dd, DES_REG_DATA_N(dd, i)); ++ scatterwalk_advance(&dd->out_walk, 4); ++ if (dd->out_sg->length == _calc_walked(out)) { ++ dd->out_sg = scatterwalk_sg_next(dd->out_sg); ++ if (dd->out_sg) { ++ scatterwalk_start(&dd->out_walk, ++ dd->out_sg); ++ dst = sg_virt(dd->out_sg) + ++ _calc_walked(out); ++ } ++ } else { ++ dst++; ++ } ++ } ++ ++ dd->total -= DES_BLOCK_SIZE; ++ ++ BUG_ON(dd->total < 0); ++ ++ /* Clear IRQ status */ ++ status &= ~DES_REG_IRQ_DATA_OUT; ++ omap_des_write(dd, DES_REG_IRQ_STATUS(dd), status); ++ ++ if (!dd->total) ++ /* All bytes read! */ ++ tasklet_schedule(&dd->done_task); ++ else ++ /* Enable DATA_IN interrupt for next block */ ++ omap_des_write(dd, DES_REG_IRQ_ENABLE(dd), 0x2); ++ } ++ ++ return IRQ_HANDLED; ++} ++ ++static const struct of_device_id omap_des_of_match[] = { ++ { ++ .compatible = "ti,omap4-des", ++ .data = &omap_des_pdata_omap4, ++ }, ++ {}, ++}; ++MODULE_DEVICE_TABLE(of, omap_des_of_match); ++ ++static int omap_des_get_res_of(struct omap_des_dev *dd, ++ struct device *dev, struct resource *res) ++{ ++ struct device_node *node = dev->of_node; ++ const struct of_device_id *match; ++ int err = 0; ++ ++ match = of_match_device(of_match_ptr(omap_des_of_match), dev); ++ if (!match) { ++ dev_err(dev, "no compatible OF match\n"); ++ err = -EINVAL; ++ goto err; ++ } ++ ++ err = of_address_to_resource(node, 0, res); ++ if (err < 0) { ++ dev_err(dev, "can't translate OF node address\n"); ++ err = -EINVAL; ++ goto err; ++ } ++ ++ dd->dma_out = -1; /* Dummy value that's unused */ ++ dd->dma_in = -1; /* Dummy value that's unused */ ++ ++ dd->pdata = match->data; ++ ++err: ++ return err; ++} ++#else ++static const struct of_device_id omap_des_of_match[] = { ++ {}, ++}; ++ ++static int omap_des_get_res_of(struct omap_des_dev *dd, ++ struct device *dev, struct resource *res) ++{ ++ return -EINVAL; ++} ++#endif ++ ++static int omap_des_get_res_pdev(struct omap_des_dev *dd, ++ struct platform_device *pdev, struct resource *res) ++{ ++ struct device *dev = &pdev->dev; ++ struct resource *r; ++ int err = 0; ++ ++ /* Get the base address */ ++ r = platform_get_resource(pdev, IORESOURCE_MEM, 0); ++ if (!r) { ++ dev_err(dev, "no MEM resource info\n"); ++ err = -ENODEV; ++ goto err; ++ } ++ memcpy(res, r, sizeof(*res)); ++ ++ /* Get the DMA out channel */ ++ r = platform_get_resource(pdev, IORESOURCE_DMA, 0); ++ if (!r) { ++ dev_err(dev, "no DMA out resource info\n"); ++ err = -ENODEV; ++ goto err; ++ } ++ dd->dma_out = r->start; ++ ++ /* Get the DMA in channel */ ++ r = platform_get_resource(pdev, IORESOURCE_DMA, 1); ++ if (!r) { ++ dev_err(dev, "no DMA in resource info\n"); ++ err = -ENODEV; ++ goto err; ++ } ++ dd->dma_in = r->start; ++ ++ /* non-DT devices get pdata from pdev */ ++ dd->pdata = pdev->dev.platform_data; ++ ++err: ++ return err; ++} ++ ++static int omap_des_probe(struct platform_device *pdev) ++{ ++ struct device *dev = &pdev->dev; ++ struct omap_des_dev *dd; ++ struct crypto_alg *algp; ++ struct resource res; ++ int err = -ENOMEM, i, j, irq = -1; ++ u32 reg; ++ ++ dd = devm_kzalloc(dev, sizeof(struct omap_des_dev), GFP_KERNEL); ++ if (dd == NULL) { ++ dev_err(dev, "unable to alloc data struct.\n"); ++ goto err_data; ++ } ++ dd->dev = dev; ++ platform_set_drvdata(pdev, dd); ++ ++ spin_lock_init(&dd->lock); ++ crypto_init_queue(&dd->queue, OMAP_DES_QUEUE_LENGTH); ++ ++ err = (dev->of_node) ? omap_des_get_res_of(dd, dev, &res) : ++ omap_des_get_res_pdev(dd, pdev, &res); ++ if (err) ++ goto err_res; ++ ++ dd->io_base = devm_request_and_ioremap(dev, &res); ++ if (!dd->io_base) { ++ dev_err(dev, "can't ioremap\n"); ++ err = -ENOMEM; ++ goto err_res; ++ } ++ dd->phys_base = res.start; ++ ++ pm_runtime_enable(dev); ++ pm_runtime_get_sync(dev); ++ ++ omap_des_dma_stop(dd); ++ ++ reg = omap_des_read(dd, DES_REG_REV(dd)); ++ ++ pm_runtime_put_sync(dev); ++ ++ dev_info(dev, "OMAP DES hw accel rev: %u.%u\n", ++ (reg & dd->pdata->major_mask) >> dd->pdata->major_shift, ++ (reg & dd->pdata->minor_mask) >> dd->pdata->minor_shift); ++ ++ tasklet_init(&dd->done_task, omap_des_done_task, (unsigned long)dd); ++ tasklet_init(&dd->queue_task, omap_des_queue_task, (unsigned long)dd); ++ ++ err = omap_des_dma_init(dd); ++ if (err && DES_REG_IRQ_STATUS(dd) && DES_REG_IRQ_ENABLE(dd)) { ++ dd->pio_only = 1; ++ ++ irq = platform_get_irq(pdev, 0); ++ if (irq < 0) { ++ dev_err(dev, "can't get IRQ resource\n"); ++ goto err_irq; ++ } ++ ++ err = devm_request_irq(dev, irq, omap_des_irq, 0, ++ dev_name(dev), dd); ++ if (err) { ++ dev_err(dev, "Unable to grab omap-des IRQ\n"); ++ goto err_irq; ++ } ++ } ++ ++ ++ INIT_LIST_HEAD(&dd->list); ++ spin_lock(&list_lock); ++ list_add_tail(&dd->list, &dev_list); ++ spin_unlock(&list_lock); ++ ++ for (i = 0; i < dd->pdata->algs_info_size; i++) { ++ for (j = 0; j < dd->pdata->algs_info[i].size; j++) { ++ algp = &dd->pdata->algs_info[i].algs_list[j]; ++ ++ pr_debug("reg alg: %s\n", algp->cra_name); ++ INIT_LIST_HEAD(&algp->cra_list); ++ ++ err = crypto_register_alg(algp); ++ if (err) ++ goto err_algs; ++ ++ dd->pdata->algs_info[i].registered++; ++ } ++ } ++ ++ return 0; ++err_algs: ++ for (i = dd->pdata->algs_info_size - 1; i >= 0; i--) ++ for (j = dd->pdata->algs_info[i].registered - 1; j >= 0; j--) ++ crypto_unregister_alg( ++ &dd->pdata->algs_info[i].algs_list[j]); ++ if (!dd->pio_only) ++ omap_des_dma_cleanup(dd); ++err_irq: ++ tasklet_kill(&dd->done_task); ++ tasklet_kill(&dd->queue_task); ++ pm_runtime_disable(dev); ++err_res: ++ dd = NULL; ++err_data: ++ dev_err(dev, "initialization failed.\n"); ++ return err; ++} ++ ++static int omap_des_remove(struct platform_device *pdev) ++{ ++ struct omap_des_dev *dd = platform_get_drvdata(pdev); ++ int i, j; ++ ++ if (!dd) ++ return -ENODEV; ++ ++ spin_lock(&list_lock); ++ list_del(&dd->list); ++ spin_unlock(&list_lock); ++ ++ for (i = dd->pdata->algs_info_size - 1; i >= 0; i--) ++ for (j = dd->pdata->algs_info[i].registered - 1; j >= 0; j--) ++ crypto_unregister_alg( ++ &dd->pdata->algs_info[i].algs_list[j]); ++ ++ tasklet_kill(&dd->done_task); ++ tasklet_kill(&dd->queue_task); ++ omap_des_dma_cleanup(dd); ++ pm_runtime_disable(dd->dev); ++ dd = NULL; ++ ++ return 0; ++} ++ ++#ifdef CONFIG_PM_SLEEP ++static int omap_des_suspend(struct device *dev) ++{ ++ pm_runtime_put_sync(dev); ++ return 0; ++} ++ ++static int omap_des_resume(struct device *dev) ++{ ++ pm_runtime_get_sync(dev); ++ return 0; ++} ++#endif ++ ++static const struct dev_pm_ops omap_des_pm_ops = { ++ SET_SYSTEM_SLEEP_PM_OPS(omap_des_suspend, omap_des_resume) ++}; ++ ++static struct platform_driver omap_des_driver = { ++ .probe = omap_des_probe, ++ .remove = omap_des_remove, ++ .driver = { ++ .name = "omap-des", ++ .owner = THIS_MODULE, ++ .pm = &omap_des_pm_ops, ++ .of_match_table = omap_des_of_match, ++ }, ++}; ++ ++module_platform_driver(omap_des_driver); ++ ++MODULE_DESCRIPTION("OMAP DES hw acceleration support."); ++MODULE_LICENSE("GPL v2"); ++MODULE_AUTHOR("Joel Fernandes <joelf@ti.com>"); +--- a/drivers/dma/amba-pl08x.c ++++ b/drivers/dma/amba-pl08x.c +@@ -2133,8 +2133,7 @@ static int pl08x_probe(struct amba_devic + writel(0x000000FF, pl08x->base + PL080_ERR_CLEAR); + writel(0x000000FF, pl08x->base + PL080_TC_CLEAR); + +- ret = request_irq(adev->irq[0], pl08x_irq, IRQF_DISABLED, +- DRIVER_NAME, pl08x); ++ ret = request_irq(adev->irq[0], pl08x_irq, 0, DRIVER_NAME, pl08x); + if (ret) { + dev_err(&adev->dev, "%s failed to request interrupt %d\n", + __func__, adev->irq[0]); +--- a/drivers/dma/coh901318.c ++++ b/drivers/dma/coh901318.c +@@ -2694,7 +2694,7 @@ static int __init coh901318_probe(struct + if (irq < 0) + return irq; + +- err = devm_request_irq(&pdev->dev, irq, dma_irq_handler, IRQF_DISABLED, ++ err = devm_request_irq(&pdev->dev, irq, dma_irq_handler, 0, + "coh901318", base); + if (err) + return err; +--- a/drivers/dma/cppi41.c ++++ b/drivers/dma/cppi41.c +@@ -141,6 +141,9 @@ struct cppi41_dd { + const struct chan_queues *queues_rx; + const struct chan_queues *queues_tx; + struct chan_queues td_queue; ++ ++ /* context for suspend/resume */ ++ unsigned int dma_tdfdq; + }; + + #define FIST_COMPLETION_QUEUE 93 +@@ -263,6 +266,15 @@ static u32 pd_trans_len(u32 val) + return val & ((1 << (DESC_LENGTH_BITS_NUM + 1)) - 1); + } + ++static u32 cppi41_pop_desc(struct cppi41_dd *cdd, unsigned queue_num) ++{ ++ u32 desc; ++ ++ desc = cppi_readl(cdd->qmgr_mem + QMGR_QUEUE_D(queue_num)); ++ desc &= ~0x1f; ++ return desc; ++} ++ + static irqreturn_t cppi41_irq(int irq, void *data) + { + struct cppi41_dd *cdd = data; +@@ -300,8 +312,7 @@ static irqreturn_t cppi41_irq(int irq, v + q_num = __fls(val); + val &= ~(1 << q_num); + q_num += 32 * i; +- desc = cppi_readl(cdd->qmgr_mem + QMGR_QUEUE_D(q_num)); +- desc &= ~0x1f; ++ desc = cppi41_pop_desc(cdd, q_num); + c = desc_to_chan(cdd, desc); + if (WARN_ON(!c)) { + pr_err("%s() q %d desc %08x\n", __func__, +@@ -517,15 +528,6 @@ static void cppi41_compute_td_desc(struc + d->pd0 = DESC_TYPE_TEARD << DESC_TYPE; + } + +-static u32 cppi41_pop_desc(struct cppi41_dd *cdd, unsigned queue_num) +-{ +- u32 desc; +- +- desc = cppi_readl(cdd->qmgr_mem + QMGR_QUEUE_D(queue_num)); +- desc &= ~0x1f; +- return desc; +-} +- + static int cppi41_tear_down_chan(struct cppi41_channel *c) + { + struct cppi41_dd *cdd = c->cdd; +@@ -561,36 +563,26 @@ static int cppi41_tear_down_chan(struct + c->td_retry = 100; + } + +- if (!c->td_seen) { +- unsigned td_comp_queue; ++ if (!c->td_seen || !c->td_desc_seen) { + +- if (c->is_tx) +- td_comp_queue = cdd->td_queue.complete; +- else +- td_comp_queue = c->q_comp_num; ++ desc_phys = cppi41_pop_desc(cdd, cdd->td_queue.complete); ++ if (!desc_phys) ++ desc_phys = cppi41_pop_desc(cdd, c->q_comp_num); + +- desc_phys = cppi41_pop_desc(cdd, td_comp_queue); +- if (desc_phys) { +- __iormb(); ++ if (desc_phys == c->desc_phys) { ++ c->td_desc_seen = 1; ++ ++ } else if (desc_phys == td_desc_phys) { ++ u32 pd0; + +- if (desc_phys == td_desc_phys) { +- u32 pd0; +- pd0 = td->pd0; +- WARN_ON((pd0 >> DESC_TYPE) != DESC_TYPE_TEARD); +- WARN_ON(!c->is_tx && !(pd0 & TD_DESC_IS_RX)); +- WARN_ON((pd0 & 0x1f) != c->port_num); +- } else { +- WARN_ON_ONCE(1); +- } +- c->td_seen = 1; +- } +- } +- if (!c->td_desc_seen) { +- desc_phys = cppi41_pop_desc(cdd, c->q_comp_num); +- if (desc_phys) { + __iormb(); +- WARN_ON(c->desc_phys != desc_phys); +- c->td_desc_seen = 1; ++ pd0 = td->pd0; ++ WARN_ON((pd0 >> DESC_TYPE) != DESC_TYPE_TEARD); ++ WARN_ON(!c->is_tx && !(pd0 & TD_DESC_IS_RX)); ++ WARN_ON((pd0 & 0x1f) != c->port_num); ++ c->td_seen = 1; ++ } else if (desc_phys) { ++ WARN_ON_ONCE(1); + } + } + c->td_retry--; +@@ -609,7 +601,7 @@ static int cppi41_tear_down_chan(struct + + WARN_ON(!c->td_retry); + if (!c->td_desc_seen) { +- desc_phys = cppi_readl(cdd->qmgr_mem + QMGR_QUEUE_D(c->q_num)); ++ desc_phys = cppi41_pop_desc(cdd, c->q_num); + WARN_ON(!desc_phys); + } + +@@ -674,14 +666,14 @@ static void cleanup_chans(struct cppi41_ + } + } + +-static int cppi41_add_chans(struct platform_device *pdev, struct cppi41_dd *cdd) ++static int cppi41_add_chans(struct device *dev, struct cppi41_dd *cdd) + { + struct cppi41_channel *cchan; + int i; + int ret; + u32 n_chans; + +- ret = of_property_read_u32(pdev->dev.of_node, "#dma-channels", ++ ret = of_property_read_u32(dev->of_node, "#dma-channels", + &n_chans); + if (ret) + return ret; +@@ -719,7 +711,7 @@ err: + return -ENOMEM; + } + +-static void purge_descs(struct platform_device *pdev, struct cppi41_dd *cdd) ++static void purge_descs(struct device *dev, struct cppi41_dd *cdd) + { + unsigned int mem_decs; + int i; +@@ -731,7 +723,7 @@ static void purge_descs(struct platform_ + cppi_writel(0, cdd->qmgr_mem + QMGR_MEMBASE(i)); + cppi_writel(0, cdd->qmgr_mem + QMGR_MEMCTRL(i)); + +- dma_free_coherent(&pdev->dev, mem_decs, cdd->cd, ++ dma_free_coherent(dev, mem_decs, cdd->cd, + cdd->descs_phys); + } + } +@@ -741,19 +733,19 @@ static void disable_sched(struct cppi41_ + cppi_writel(0, cdd->sched_mem + DMA_SCHED_CTRL); + } + +-static void deinit_cpii41(struct platform_device *pdev, struct cppi41_dd *cdd) ++static void deinit_cppi41(struct device *dev, struct cppi41_dd *cdd) + { + disable_sched(cdd); + +- purge_descs(pdev, cdd); ++ purge_descs(dev, cdd); + + cppi_writel(0, cdd->qmgr_mem + QMGR_LRAM0_BASE); + cppi_writel(0, cdd->qmgr_mem + QMGR_LRAM0_BASE); +- dma_free_coherent(&pdev->dev, QMGR_SCRATCH_SIZE, cdd->qmgr_scratch, ++ dma_free_coherent(dev, QMGR_SCRATCH_SIZE, cdd->qmgr_scratch, + cdd->scratch_phys); + } + +-static int init_descs(struct platform_device *pdev, struct cppi41_dd *cdd) ++static int init_descs(struct device *dev, struct cppi41_dd *cdd) + { + unsigned int desc_size; + unsigned int mem_decs; +@@ -777,7 +769,7 @@ static int init_descs(struct platform_de + reg |= ilog2(ALLOC_DECS_NUM) - 5; + + BUILD_BUG_ON(DESCS_AREAS != 1); +- cdd->cd = dma_alloc_coherent(&pdev->dev, mem_decs, ++ cdd->cd = dma_alloc_coherent(dev, mem_decs, + &cdd->descs_phys, GFP_KERNEL); + if (!cdd->cd) + return -ENOMEM; +@@ -813,12 +805,12 @@ static void init_sched(struct cppi41_dd + cppi_writel(reg, cdd->sched_mem + DMA_SCHED_CTRL); + } + +-static int init_cppi41(struct platform_device *pdev, struct cppi41_dd *cdd) ++static int init_cppi41(struct device *dev, struct cppi41_dd *cdd) + { + int ret; + + BUILD_BUG_ON(QMGR_SCRATCH_SIZE > ((1 << 14) - 1)); +- cdd->qmgr_scratch = dma_alloc_coherent(&pdev->dev, QMGR_SCRATCH_SIZE, ++ cdd->qmgr_scratch = dma_alloc_coherent(dev, QMGR_SCRATCH_SIZE, + &cdd->scratch_phys, GFP_KERNEL); + if (!cdd->qmgr_scratch) + return -ENOMEM; +@@ -827,7 +819,7 @@ static int init_cppi41(struct platform_d + cppi_writel(QMGR_SCRATCH_SIZE, cdd->qmgr_mem + QMGR_LRAM_SIZE); + cppi_writel(0, cdd->qmgr_mem + QMGR_LRAM1_BASE); + +- ret = init_descs(pdev, cdd); ++ ret = init_descs(dev, cdd); + if (ret) + goto err_td; + +@@ -835,7 +827,7 @@ static int init_cppi41(struct platform_d + init_sched(cdd); + return 0; + err_td: +- deinit_cpii41(pdev, cdd); ++ deinit_cppi41(dev, cdd); + return ret; + } + +@@ -914,11 +906,11 @@ static const struct of_device_id cppi41_ + }; + MODULE_DEVICE_TABLE(of, cppi41_dma_ids); + +-static const struct cppi_glue_infos *get_glue_info(struct platform_device *pdev) ++static const struct cppi_glue_infos *get_glue_info(struct device *dev) + { + const struct of_device_id *of_id; + +- of_id = of_match_node(cppi41_dma_ids, pdev->dev.of_node); ++ of_id = of_match_node(cppi41_dma_ids, dev->of_node); + if (!of_id) + return NULL; + return of_id->data; +@@ -927,11 +919,12 @@ static const struct cppi_glue_infos *get + static int cppi41_dma_probe(struct platform_device *pdev) + { + struct cppi41_dd *cdd; ++ struct device *dev = &pdev->dev; + const struct cppi_glue_infos *glue_info; + int irq; + int ret; + +- glue_info = get_glue_info(pdev); ++ glue_info = get_glue_info(dev); + if (!glue_info) + return -EINVAL; + +@@ -946,14 +939,14 @@ static int cppi41_dma_probe(struct platf + cdd->ddev.device_issue_pending = cppi41_dma_issue_pending; + cdd->ddev.device_prep_slave_sg = cppi41_dma_prep_slave_sg; + cdd->ddev.device_control = cppi41_dma_control; +- cdd->ddev.dev = &pdev->dev; ++ cdd->ddev.dev = dev; + INIT_LIST_HEAD(&cdd->ddev.channels); + cpp41_dma_info.dma_cap = cdd->ddev.cap_mask; + +- cdd->usbss_mem = of_iomap(pdev->dev.of_node, 0); +- cdd->ctrl_mem = of_iomap(pdev->dev.of_node, 1); +- cdd->sched_mem = of_iomap(pdev->dev.of_node, 2); +- cdd->qmgr_mem = of_iomap(pdev->dev.of_node, 3); ++ cdd->usbss_mem = of_iomap(dev->of_node, 0); ++ cdd->ctrl_mem = of_iomap(dev->of_node, 1); ++ cdd->sched_mem = of_iomap(dev->of_node, 2); ++ cdd->qmgr_mem = of_iomap(dev->of_node, 3); + + if (!cdd->usbss_mem || !cdd->ctrl_mem || !cdd->sched_mem || + !cdd->qmgr_mem) { +@@ -961,31 +954,31 @@ static int cppi41_dma_probe(struct platf + goto err_remap; + } + +- pm_runtime_enable(&pdev->dev); +- ret = pm_runtime_get_sync(&pdev->dev); +- if (ret) ++ pm_runtime_enable(dev); ++ ret = pm_runtime_get_sync(dev); ++ if (ret < 0) + goto err_get_sync; + + cdd->queues_rx = glue_info->queues_rx; + cdd->queues_tx = glue_info->queues_tx; + cdd->td_queue = glue_info->td_queue; + +- ret = init_cppi41(pdev, cdd); ++ ret = init_cppi41(dev, cdd); + if (ret) + goto err_init_cppi; + +- ret = cppi41_add_chans(pdev, cdd); ++ ret = cppi41_add_chans(dev, cdd); + if (ret) + goto err_chans; + +- irq = irq_of_parse_and_map(pdev->dev.of_node, 0); ++ irq = irq_of_parse_and_map(dev->of_node, 0); + if (!irq) + goto err_irq; + + cppi_writel(USBSS_IRQ_PD_COMP, cdd->usbss_mem + USBSS_IRQ_ENABLER); + + ret = request_irq(irq, glue_info->isr, IRQF_SHARED, +- dev_name(&pdev->dev), cdd); ++ dev_name(dev), cdd); + if (ret) + goto err_irq; + cdd->irq = irq; +@@ -994,7 +987,7 @@ static int cppi41_dma_probe(struct platf + if (ret) + goto err_dma_reg; + +- ret = of_dma_controller_register(pdev->dev.of_node, ++ ret = of_dma_controller_register(dev->of_node, + cppi41_dma_xlate, &cpp41_dma_info); + if (ret) + goto err_of; +@@ -1009,11 +1002,11 @@ err_irq: + cppi_writel(0, cdd->usbss_mem + USBSS_IRQ_CLEARR); + cleanup_chans(cdd); + err_chans: +- deinit_cpii41(pdev, cdd); ++ deinit_cppi41(dev, cdd); + err_init_cppi: +- pm_runtime_put(&pdev->dev); ++ pm_runtime_put(dev); + err_get_sync: +- pm_runtime_disable(&pdev->dev); ++ pm_runtime_disable(dev); + iounmap(cdd->usbss_mem); + iounmap(cdd->ctrl_mem); + iounmap(cdd->sched_mem); +@@ -1033,7 +1026,7 @@ static int cppi41_dma_remove(struct plat + cppi_writel(0, cdd->usbss_mem + USBSS_IRQ_CLEARR); + free_irq(cdd->irq, cdd); + cleanup_chans(cdd); +- deinit_cpii41(pdev, cdd); ++ deinit_cppi41(&pdev->dev, cdd); + iounmap(cdd->usbss_mem); + iounmap(cdd->ctrl_mem); + iounmap(cdd->sched_mem); +@@ -1044,12 +1037,53 @@ static int cppi41_dma_remove(struct plat + return 0; + } + ++#ifdef CONFIG_PM_SLEEP ++static int cppi41_suspend(struct device *dev) ++{ ++ struct cppi41_dd *cdd = dev_get_drvdata(dev); ++ ++ cdd->dma_tdfdq = cppi_readl(cdd->ctrl_mem + DMA_TDFDQ); ++ cppi_writel(0, cdd->usbss_mem + USBSS_IRQ_CLEARR); ++ disable_sched(cdd); ++ ++ return 0; ++} ++ ++static int cppi41_resume(struct device *dev) ++{ ++ struct cppi41_dd *cdd = dev_get_drvdata(dev); ++ struct cppi41_channel *c; ++ int i; ++ ++ for (i = 0; i < DESCS_AREAS; i++) ++ cppi_writel(cdd->descs_phys, cdd->qmgr_mem + QMGR_MEMBASE(i)); ++ ++ list_for_each_entry(c, &cdd->ddev.channels, chan.device_node) ++ if (!c->is_tx) ++ cppi_writel(c->q_num, c->gcr_reg + RXHPCRA0); ++ ++ init_sched(cdd); ++ ++ cppi_writel(cdd->dma_tdfdq, cdd->ctrl_mem + DMA_TDFDQ); ++ cppi_writel(cdd->scratch_phys, cdd->qmgr_mem + QMGR_LRAM0_BASE); ++ cppi_writel(QMGR_SCRATCH_SIZE, cdd->qmgr_mem + QMGR_LRAM_SIZE); ++ cppi_writel(0, cdd->qmgr_mem + QMGR_LRAM1_BASE); ++ ++ cppi_writel(USBSS_IRQ_PD_COMP, cdd->usbss_mem + USBSS_IRQ_ENABLER); ++ ++ return 0; ++} ++#endif ++ ++static SIMPLE_DEV_PM_OPS(cppi41_pm_ops, cppi41_suspend, cppi41_resume); ++ + static struct platform_driver cpp41_dma_driver = { + .probe = cppi41_dma_probe, + .remove = cppi41_dma_remove, + .driver = { + .name = "cppi41-dma-engine", + .owner = THIS_MODULE, ++ .pm = &cppi41_pm_ops, + .of_match_table = of_match_ptr(cppi41_dma_ids), + }, + }; +--- a/drivers/dma/edma.c ++++ b/drivers/dma/edma.c +@@ -46,8 +46,14 @@ + #define EDMA_CHANS 64 + #endif /* CONFIG_ARCH_DAVINCI_DA8XX */ + +-/* Max of 16 segments per channel to conserve PaRAM slots */ +-#define MAX_NR_SG 16 ++/* ++ * Max of 20 segments per channel to conserve PaRAM slots ++ * Also note that MAX_NR_SG should be atleast the no.of periods ++ * that are required for ASoC, otherwise DMA prep calls will ++ * fail. Today davinci-pcm is the only user of this driver and ++ * requires atleast 17 slots, so we setup the default to 20. ++ */ ++#define MAX_NR_SG 20 + #define EDMA_MAX_SLOTS MAX_NR_SG + #define EDMA_DESCRIPTORS 16 + +@@ -250,6 +256,117 @@ static int edma_control(struct dma_chan + return ret; + } + ++/* ++ * A PaRAM set configuration abstraction used by other modes ++ * @chan: Channel who's PaRAM set we're configuring ++ * @pset: PaRAM set to initialize and setup. ++ * @src_addr: Source address of the DMA ++ * @dst_addr: Destination address of the DMA ++ * @burst: In units of dev_width, how much to send ++ * @dev_width: How much is the dev_width ++ * @dma_length: Total length of the DMA transfer ++ * @direction: Direction of the transfer ++ */ ++static int edma_config_pset(struct dma_chan *chan, struct edmacc_param *pset, ++ dma_addr_t src_addr, dma_addr_t dst_addr, u32 burst, ++ enum dma_slave_buswidth dev_width, unsigned int dma_length, ++ enum dma_transfer_direction direction) ++{ ++ struct edma_chan *echan = to_edma_chan(chan); ++ struct device *dev = chan->device->dev; ++ int acnt, bcnt, ccnt, cidx; ++ int src_bidx, dst_bidx, src_cidx, dst_cidx; ++ int absync; ++ ++ acnt = dev_width; ++ /* ++ * If the maxburst is equal to the fifo width, use ++ * A-synced transfers. This allows for large contiguous ++ * buffer transfers using only one PaRAM set. ++ */ ++ if (burst == 1) { ++ /* ++ * For the A-sync case, bcnt and ccnt are the remainder ++ * and quotient respectively of the division of: ++ * (dma_length / acnt) by (SZ_64K -1). This is so ++ * that in case bcnt over flows, we have ccnt to use. ++ * Note: In A-sync tranfer only, bcntrld is used, but it ++ * only applies for sg_dma_len(sg) >= SZ_64K. ++ * In this case, the best way adopted is- bccnt for the ++ * first frame will be the remainder below. Then for ++ * every successive frame, bcnt will be SZ_64K-1. This ++ * is assured as bcntrld = 0xffff in end of function. ++ */ ++ absync = false; ++ ccnt = dma_length / acnt / (SZ_64K - 1); ++ bcnt = dma_length / acnt - ccnt * (SZ_64K - 1); ++ /* ++ * If bcnt is non-zero, we have a remainder and hence an ++ * extra frame to transfer, so increment ccnt. ++ */ ++ if (bcnt) ++ ccnt++; ++ else ++ bcnt = SZ_64K - 1; ++ cidx = acnt; ++ } else { ++ /* ++ * If maxburst is greater than the fifo address_width, ++ * use AB-synced transfers where A count is the fifo ++ * address_width and B count is the maxburst. In this ++ * case, we are limited to transfers of C count frames ++ * of (address_width * maxburst) where C count is limited ++ * to SZ_64K-1. This places an upper bound on the length ++ * of an SG segment that can be handled. ++ */ ++ absync = true; ++ bcnt = burst; ++ ccnt = dma_length / (acnt * bcnt); ++ if (ccnt > (SZ_64K - 1)) { ++ dev_err(dev, "Exceeded max SG segment size\n"); ++ return -EINVAL; ++ } ++ cidx = acnt * bcnt; ++ } ++ ++ if (direction == DMA_MEM_TO_DEV) { ++ src_bidx = acnt; ++ src_cidx = cidx; ++ dst_bidx = 0; ++ dst_cidx = 0; ++ } else if (direction == DMA_DEV_TO_MEM) { ++ src_bidx = 0; ++ src_cidx = 0; ++ dst_bidx = acnt; ++ dst_cidx = cidx; ++ } else { ++ dev_err(dev, "%s: direction not implemented yet\n", __func__); ++ return -EINVAL; ++ } ++ ++ pset->opt = EDMA_TCC(EDMA_CHAN_SLOT(echan->ch_num)); ++ /* Configure A or AB synchronized transfers */ ++ if (absync) ++ pset->opt |= SYNCDIM; ++ ++ pset->src = src_addr; ++ pset->dst = dst_addr; ++ ++ pset->src_dst_bidx = (dst_bidx << 16) | src_bidx; ++ pset->src_dst_cidx = (dst_cidx << 16) | src_cidx; ++ ++ pset->a_b_cnt = bcnt << 16 | acnt; ++ pset->ccnt = ccnt; ++ /* ++ * Only time when (bcntrld) auto reload is required is for ++ * A-sync case, and in this case, a requirement of reload value ++ * of SZ_64K-1 only is assured. 'link' is initially set to NULL ++ * and then later will be populated by edma_execute. ++ */ ++ pset->link_bcntrld = 0xffffffff; ++ return absync; ++} ++ + static struct dma_async_tx_descriptor *edma_prep_slave_sg( + struct dma_chan *chan, struct scatterlist *sgl, + unsigned int sg_len, enum dma_transfer_direction direction, +@@ -258,23 +375,21 @@ static struct dma_async_tx_descriptor *e + struct edma_chan *echan = to_edma_chan(chan); + struct device *dev = chan->device->dev; + struct edma_desc *edesc; +- dma_addr_t dev_addr; ++ dma_addr_t src_addr = 0, dst_addr = 0; + enum dma_slave_buswidth dev_width; + u32 burst; + struct scatterlist *sg; +- int acnt, bcnt, ccnt, src, dst, cidx; +- int src_bidx, dst_bidx, src_cidx, dst_cidx; +- int i, nslots; ++ int i, nslots, ret; + + if (unlikely(!echan || !sgl || !sg_len)) + return NULL; + + if (direction == DMA_DEV_TO_MEM) { +- dev_addr = echan->cfg.src_addr; ++ src_addr = echan->cfg.src_addr; + dev_width = echan->cfg.src_addr_width; + burst = echan->cfg.src_maxburst; + } else if (direction == DMA_MEM_TO_DEV) { +- dev_addr = echan->cfg.dst_addr; ++ dst_addr = echan->cfg.dst_addr; + dev_width = echan->cfg.dst_addr_width; + burst = echan->cfg.dst_maxburst; + } else { +@@ -315,64 +430,19 @@ static struct dma_async_tx_descriptor *e + + /* Configure PaRAM sets for each SG */ + for_each_sg(sgl, sg, sg_len, i) { ++ /* Get address for each SG */ ++ if (direction == DMA_DEV_TO_MEM) ++ dst_addr = sg_dma_address(sg); ++ else ++ src_addr = sg_dma_address(sg); ++ ++ ret = edma_config_pset(chan, &edesc->pset[i], src_addr, ++ dst_addr, burst, dev_width, ++ sg_dma_len(sg), direction); ++ if (ret < 0) ++ return NULL; + +- acnt = dev_width; +- +- /* +- * If the maxburst is equal to the fifo width, use +- * A-synced transfers. This allows for large contiguous +- * buffer transfers using only one PaRAM set. +- */ +- if (burst == 1) { +- edesc->absync = false; +- ccnt = sg_dma_len(sg) / acnt / (SZ_64K - 1); +- bcnt = sg_dma_len(sg) / acnt - ccnt * (SZ_64K - 1); +- if (bcnt) +- ccnt++; +- else +- bcnt = SZ_64K - 1; +- cidx = acnt; +- /* +- * If maxburst is greater than the fifo address_width, +- * use AB-synced transfers where A count is the fifo +- * address_width and B count is the maxburst. In this +- * case, we are limited to transfers of C count frames +- * of (address_width * maxburst) where C count is limited +- * to SZ_64K-1. This places an upper bound on the length +- * of an SG segment that can be handled. +- */ +- } else { +- edesc->absync = true; +- bcnt = burst; +- ccnt = sg_dma_len(sg) / (acnt * bcnt); +- if (ccnt > (SZ_64K - 1)) { +- dev_err(dev, "Exceeded max SG segment size\n"); +- kfree(edesc); +- return NULL; +- } +- cidx = acnt * bcnt; +- } +- +- if (direction == DMA_MEM_TO_DEV) { +- src = sg_dma_address(sg); +- dst = dev_addr; +- src_bidx = acnt; +- src_cidx = cidx; +- dst_bidx = 0; +- dst_cidx = 0; +- } else { +- src = dev_addr; +- dst = sg_dma_address(sg); +- src_bidx = 0; +- src_cidx = 0; +- dst_bidx = acnt; +- dst_cidx = cidx; +- } +- +- edesc->pset[i].opt = EDMA_TCC(EDMA_CHAN_SLOT(echan->ch_num)); +- /* Configure A or AB synchronized transfers */ +- if (edesc->absync) +- edesc->pset[i].opt |= SYNCDIM; ++ edesc->absync = ret; + + /* If this is the last in a current SG set of transactions, + enable interrupts so that next set is processed */ +@@ -382,17 +452,6 @@ static struct dma_async_tx_descriptor *e + /* If this is the last set, enable completion interrupt flag */ + if (i == sg_len - 1) + edesc->pset[i].opt |= TCINTEN; +- +- edesc->pset[i].src = src; +- edesc->pset[i].dst = dst; +- +- edesc->pset[i].src_dst_bidx = (dst_bidx << 16) | src_bidx; +- edesc->pset[i].src_dst_cidx = (dst_cidx << 16) | src_cidx; +- +- edesc->pset[i].a_b_cnt = bcnt << 16 | acnt; +- edesc->pset[i].ccnt = ccnt; +- edesc->pset[i].link_bcntrld = 0xffffffff; +- + } + + return vchan_tx_prep(&echan->vchan, &edesc->vdesc, tx_flags); +--- a/drivers/dma/k3dma.c ++++ b/drivers/dma/k3dma.c +@@ -693,7 +693,7 @@ static int k3_dma_probe(struct platform_ + + irq = platform_get_irq(op, 0); + ret = devm_request_irq(&op->dev, irq, +- k3_dma_int_handler, IRQF_DISABLED, DRIVER_NAME, d); ++ k3_dma_int_handler, 0, DRIVER_NAME, d); + if (ret) + return ret; + +--- a/drivers/dma/mmp_pdma.c ++++ b/drivers/dma/mmp_pdma.c +@@ -798,8 +798,7 @@ static void dma_do_tasklet(unsigned long + * move the descriptors to a temporary list so we can drop + * the lock during the entire cleanup operation + */ +- list_del(&desc->node); +- list_add(&desc->node, &chain_cleanup); ++ list_move(&desc->node, &chain_cleanup); + + /* + * Look for the first list entry which has the ENDIRQEN flag +@@ -863,7 +862,7 @@ static int mmp_pdma_chan_init(struct mmp + + if (irq) { + ret = devm_request_irq(pdev->dev, irq, +- mmp_pdma_chan_handler, IRQF_DISABLED, "pdma", phy); ++ mmp_pdma_chan_handler, 0, "pdma", phy); + if (ret) { + dev_err(pdev->dev, "channel request irq fail!\n"); + return ret; +@@ -970,7 +969,7 @@ static int mmp_pdma_probe(struct platfor + /* all chan share one irq, demux inside */ + irq = platform_get_irq(op, 0); + ret = devm_request_irq(pdev->dev, irq, +- mmp_pdma_int_handler, IRQF_DISABLED, "pdma", pdev); ++ mmp_pdma_int_handler, 0, "pdma", pdev); + if (ret) + return ret; + } +--- a/drivers/dma/mmp_tdma.c ++++ b/drivers/dma/mmp_tdma.c +@@ -62,6 +62,11 @@ + #define TDCR_BURSTSZ_16B (0x3 << 6) + #define TDCR_BURSTSZ_32B (0x6 << 6) + #define TDCR_BURSTSZ_64B (0x7 << 6) ++#define TDCR_BURSTSZ_SQU_1B (0x5 << 6) ++#define TDCR_BURSTSZ_SQU_2B (0x6 << 6) ++#define TDCR_BURSTSZ_SQU_4B (0x0 << 6) ++#define TDCR_BURSTSZ_SQU_8B (0x1 << 6) ++#define TDCR_BURSTSZ_SQU_16B (0x3 << 6) + #define TDCR_BURSTSZ_SQU_32B (0x7 << 6) + #define TDCR_BURSTSZ_128B (0x5 << 6) + #define TDCR_DSTDIR_MSK (0x3 << 4) /* Dst Direction */ +@@ -228,8 +233,31 @@ static int mmp_tdma_config_chan(struct m + return -EINVAL; + } + } else if (tdmac->type == PXA910_SQU) { +- tdcr |= TDCR_BURSTSZ_SQU_32B; + tdcr |= TDCR_SSPMOD; ++ ++ switch (tdmac->burst_sz) { ++ case 1: ++ tdcr |= TDCR_BURSTSZ_SQU_1B; ++ break; ++ case 2: ++ tdcr |= TDCR_BURSTSZ_SQU_2B; ++ break; ++ case 4: ++ tdcr |= TDCR_BURSTSZ_SQU_4B; ++ break; ++ case 8: ++ tdcr |= TDCR_BURSTSZ_SQU_8B; ++ break; ++ case 16: ++ tdcr |= TDCR_BURSTSZ_SQU_16B; ++ break; ++ case 32: ++ tdcr |= TDCR_BURSTSZ_SQU_32B; ++ break; ++ default: ++ dev_err(tdmac->dev, "mmp_tdma: unknown burst size.\n"); ++ return -EINVAL; ++ } + } + + writel(tdcr, tdmac->reg_base + TDCR); +@@ -324,7 +352,7 @@ static int mmp_tdma_alloc_chan_resources + + if (tdmac->irq) { + ret = devm_request_irq(tdmac->dev, tdmac->irq, +- mmp_tdma_chan_handler, IRQF_DISABLED, "tdma", tdmac); ++ mmp_tdma_chan_handler, 0, "tdma", tdmac); + if (ret) + return ret; + } +@@ -559,7 +587,7 @@ static int mmp_tdma_probe(struct platfor + if (irq_num != chan_num) { + irq = platform_get_irq(pdev, 0); + ret = devm_request_irq(&pdev->dev, irq, +- mmp_tdma_int_handler, IRQF_DISABLED, "tdma", tdev); ++ mmp_tdma_int_handler, 0, "tdma", tdev); + if (ret) + return ret; + } +--- a/drivers/dma/pl330.c ++++ b/drivers/dma/pl330.c +@@ -2922,16 +2922,23 @@ pl330_probe(struct amba_device *adev, co + + amba_set_drvdata(adev, pdmac); + +- irq = adev->irq[0]; +- ret = request_irq(irq, pl330_irq_handler, 0, +- dev_name(&adev->dev), pi); +- if (ret) +- return ret; ++ for (i = 0; i <= AMBA_NR_IRQS; i++) { ++ irq = adev->irq[i]; ++ if (irq) { ++ ret = devm_request_irq(&adev->dev, irq, ++ pl330_irq_handler, 0, ++ dev_name(&adev->dev), pi); ++ if (ret) ++ return ret; ++ } else { ++ break; ++ } ++ } + + pi->pcfg.periph_id = adev->periphid; + ret = pl330_add(pi); + if (ret) +- goto probe_err1; ++ return ret; + + INIT_LIST_HEAD(&pdmac->desc_pool); + spin_lock_init(&pdmac->pool_lock); +@@ -3044,8 +3051,6 @@ probe_err3: + } + probe_err2: + pl330_del(pi); +-probe_err1: +- free_irq(irq, pi); + + return ret; + } +@@ -3055,7 +3060,6 @@ static int pl330_remove(struct amba_devi + struct dma_pl330_dmac *pdmac = amba_get_drvdata(adev); + struct dma_pl330_chan *pch, *_p; + struct pl330_info *pi; +- int irq; + + if (!pdmac) + return 0; +@@ -3082,9 +3086,6 @@ static int pl330_remove(struct amba_devi + + pl330_del(pi); + +- irq = adev->irq[0]; +- free_irq(irq, pi); +- + return 0; + } + +--- a/drivers/dma/ste_dma40.c ++++ b/drivers/dma/ste_dma40.c +@@ -14,6 +14,7 @@ + #include <linux/platform_device.h> + #include <linux/clk.h> + #include <linux/delay.h> ++#include <linux/log2.h> + #include <linux/pm.h> + #include <linux/pm_runtime.h> + #include <linux/err.h> +@@ -2796,8 +2797,8 @@ static int d40_set_runtime_config(struct + src_addr_width > DMA_SLAVE_BUSWIDTH_8_BYTES || + dst_addr_width <= DMA_SLAVE_BUSWIDTH_UNDEFINED || + dst_addr_width > DMA_SLAVE_BUSWIDTH_8_BYTES || +- ((src_addr_width > 1) && (src_addr_width & 1)) || +- ((dst_addr_width > 1) && (dst_addr_width & 1))) ++ !is_power_of_2(src_addr_width) || ++ !is_power_of_2(dst_addr_width)) + return -EINVAL; + + cfg->src_info.data_width = src_addr_width; +--- /dev/null ++++ b/drivers/extcon/extcon-gpio-usbvid.c +@@ -0,0 +1,281 @@ ++/* ++ * Generic USB VBUS-ID pin detection driver ++ * ++ * Copyright (C) 2013 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; either version 2 of the License, or ++ * (at your option) any later version. ++ * ++ * Author: George Cherian <george.cherian@ti.com> ++ * ++ * Based on extcon-palmas.c ++ * ++ * Author: Kishon Vijay Abraham I <kishon@ti.com> ++ * ++ * 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/err.h> ++#include <linux/extcon.h> ++#include <linux/gpio.h> ++#include <linux/interrupt.h> ++#include <linux/module.h> ++#include <linux/of.h> ++#include <linux/of_gpio.h> ++#include <linux/of_platform.h> ++#include <linux/platform_device.h> ++ ++struct gpio_usbvid { ++ struct device *dev; ++ ++ struct extcon_dev edev; ++ ++ /* GPIO pin */ ++ int id_gpio; ++ int vbus_gpio; ++ ++ int id_irq; ++ int vbus_irq; ++ int type; ++}; ++ ++static const char *dra7xx_extcon_cable[] = { ++ [0] = "USB", ++ [1] = "USB-HOST", ++ NULL, ++}; ++ ++static const int mutually_exclusive[] = {0x3, 0x0}; ++ ++/* Two types of support are provided. ++ * Systems which has ++ * 1) VBUS and ID pin connected via GPIO ++ * 2) only ID pin connected via GPIO ++ * For Case 1 both the gpios should be provided via DT ++ * Always the first GPIO in dt is considered ID pin GPIO ++ */ ++ ++enum { ++ UNKNOWN = 0, ++ ID_DETECT, ++ VBUS_ID_DETECT, ++}; ++ ++#define ID_GND 0 ++#define ID_FLOAT 1 ++#define VBUS_OFF 0 ++#define VBUS_ON 1 ++ ++static irqreturn_t id_irq_handler(int irq, void *data) ++{ ++ struct gpio_usbvid *gpio_usbvid = (struct gpio_usbvid *)data; ++ int id_current; ++ ++ id_current = gpio_get_value_cansleep(gpio_usbvid->id_gpio); ++ if (id_current == ID_GND) { ++ if (gpio_usbvid->type == ID_DETECT) ++ extcon_set_cable_state(&gpio_usbvid->edev, ++ "USB", false); ++ extcon_set_cable_state(&gpio_usbvid->edev, "USB-HOST", true); ++ } else { ++ extcon_set_cable_state(&gpio_usbvid->edev, "USB-HOST", false); ++ if (gpio_usbvid->type == ID_DETECT) ++ extcon_set_cable_state(&gpio_usbvid->edev, ++ "USB", true); ++ } ++ ++ return IRQ_HANDLED; ++} ++ ++static irqreturn_t vbus_irq_handler(int irq, void *data) ++{ ++ struct gpio_usbvid *gpio_usbvid = (struct gpio_usbvid *)data; ++ int vbus_current; ++ ++ vbus_current = gpio_get_value_cansleep(gpio_usbvid->vbus_gpio); ++ if (vbus_current == VBUS_OFF) ++ extcon_set_cable_state(&gpio_usbvid->edev, "USB", false); ++ else ++ extcon_set_cable_state(&gpio_usbvid->edev, "USB", true); ++ ++ return IRQ_HANDLED; ++} ++ ++static void gpio_usbvid_set_initial_state(struct gpio_usbvid *gpio_usbvid) ++{ ++ int id_current, vbus_current; ++ ++ switch (gpio_usbvid->type) { ++ case ID_DETECT: ++ id_current = gpio_get_value_cansleep(gpio_usbvid->id_gpio); ++ if (!!id_current == ID_FLOAT) { ++ extcon_set_cable_state(&gpio_usbvid->edev, ++ "USB-HOST", false); ++ extcon_set_cable_state(&gpio_usbvid->edev, ++ "USB", true); ++ } else { ++ extcon_set_cable_state(&gpio_usbvid->edev, ++ "USB", false); ++ extcon_set_cable_state(&gpio_usbvid->edev, ++ "USB-HOST", true); ++ } ++ break; ++ ++ case VBUS_ID_DETECT: ++ id_current = gpio_get_value_cansleep(gpio_usbvid->id_gpio); ++ if (!!id_current == ID_FLOAT) ++ extcon_set_cable_state(&gpio_usbvid->edev, ++ "USB-HOST", false); ++ else ++ extcon_set_cable_state(&gpio_usbvid->edev, ++ "USB-HOST", true); ++ ++ vbus_current = gpio_get_value_cansleep(gpio_usbvid->vbus_gpio); ++ if (!!vbus_current == VBUS_ON) ++ extcon_set_cable_state(&gpio_usbvid->edev, ++ "USB", true); ++ else ++ extcon_set_cable_state(&gpio_usbvid->edev, ++ "USB", false); ++ break; ++ ++ default: ++ dev_err(gpio_usbvid->dev, "Unknown VBUS-ID type\n"); ++ } ++} ++ ++static int gpio_usbvid_request_irq(struct gpio_usbvid *gpio_usbvid) ++{ ++ int ret; ++ ++ ret = devm_request_threaded_irq(gpio_usbvid->dev, gpio_usbvid->id_irq, ++ NULL, id_irq_handler, ++ IRQF_ONESHOT | IRQF_TRIGGER_FALLING, ++ dev_name(gpio_usbvid->dev), ++ (void *) gpio_usbvid); ++ if (ret) { ++ dev_err(gpio_usbvid->dev, "failed to request id irq #%d\n", ++ gpio_usbvid->id_irq); ++ return ret; ++ } ++ if (gpio_usbvid->type == VBUS_ID_DETECT) { ++ ret = devm_request_threaded_irq(gpio_usbvid->dev, ++ gpio_usbvid->vbus_irq, NULL, ++ vbus_irq_handler, ++ IRQF_ONESHOT | IRQF_TRIGGER_FALLING, ++ dev_name(gpio_usbvid->dev), ++ (void *) gpio_usbvid); ++ if (ret) ++ dev_err(gpio_usbvid->dev, "failed to request vbus irq #%d\n", ++ gpio_usbvid->vbus_irq); ++ } ++ ++ return ret; ++} ++ ++static int gpio_usbvid_probe(struct platform_device *pdev) ++{ ++ struct device_node *node = pdev->dev.of_node; ++ struct gpio_usbvid *gpio_usbvid; ++ int ret, gpio; ++ ++ gpio_usbvid = devm_kzalloc(&pdev->dev, sizeof(*gpio_usbvid), ++ GFP_KERNEL); ++ if (!gpio_usbvid) ++ return -ENOMEM; ++ ++ gpio_usbvid->dev = &pdev->dev; ++ ++ platform_set_drvdata(pdev, gpio_usbvid); ++ ++ //gpio_usbvid->edev.name = dev_name(&pdev->dev); ++ gpio_usbvid->edev.supported_cable = dra7xx_extcon_cable; ++ gpio_usbvid->edev.mutually_exclusive = mutually_exclusive; ++ ++ if (of_device_is_compatible(node, "ti,gpio-usb-id")) ++ gpio_usbvid->type = ID_DETECT; ++ ++ gpio = of_get_gpio(node, 0); ++ if (gpio_is_valid(gpio)) { ++ gpio_usbvid->id_gpio = gpio; ++ ret = devm_gpio_request(&pdev->dev, gpio_usbvid->id_gpio, ++ "id_gpio"); ++ if (ret) ++ return ret; ++ ++ gpio_usbvid->id_irq = gpio_to_irq(gpio_usbvid->id_gpio); ++ } else { ++ dev_err(&pdev->dev, "failed to get id gpio\n"); ++ return -EPROBE_DEFER; ++ } ++ ++ if (of_device_is_compatible(node, "ti,gpio-usb-vid")) { ++ gpio_usbvid->type = VBUS_ID_DETECT; ++ gpio = of_get_gpio(node, 1); ++ if (gpio_is_valid(gpio)) { ++ gpio_usbvid->vbus_gpio = gpio; ++ ret = devm_gpio_request(&pdev->dev, ++ gpio_usbvid->vbus_gpio, ++ "vbus_gpio"); ++ if (ret) ++ return ret; ++ ++ gpio_usbvid->vbus_irq = ++ gpio_to_irq(gpio_usbvid->vbus_gpio); ++ } else { ++ dev_err(&pdev->dev, "failed to get vbus gpio\n"); ++ return -ENODEV; ++ } ++ } ++ ++ ret = gpio_usbvid_request_irq(gpio_usbvid); ++ if (ret) ++ return ret; ++ ++ ret = extcon_dev_register(&gpio_usbvid->edev, gpio_usbvid->dev); ++ if (ret) { ++ dev_err(&pdev->dev, "failed to register extcon device\n"); ++ return ret; ++ } ++ ++ gpio_usbvid_set_initial_state(gpio_usbvid); ++ ++ return 0; ++ ++} ++ ++static int gpio_usbvid_remove(struct platform_device *pdev) ++{ ++ struct gpio_usbvid *gpio_usbvid = platform_get_drvdata(pdev); ++ ++ extcon_dev_unregister(&gpio_usbvid->edev); ++ return 0; ++} ++ ++static struct of_device_id of_gpio_usbvid_match_tbl[] = { ++ { .compatible = "ti,gpio-usb-vid", }, ++ { .compatible = "ti,gpio-usb-id", }, ++ { /* end */ } ++}; ++ ++static struct platform_driver gpio_usbvid_driver = { ++ .probe = gpio_usbvid_probe, ++ .remove = gpio_usbvid_remove, ++ .driver = { ++ .name = "gpio-usbvid", ++ .of_match_table = of_gpio_usbvid_match_tbl, ++ .owner = THIS_MODULE, ++ }, ++}; ++ ++module_platform_driver(gpio_usbvid_driver); ++ ++MODULE_ALIAS("platform:gpio-usbvid"); ++MODULE_AUTHOR("George Cherian <george.cherian@ti.com>"); ++MODULE_DESCRIPTION("GPIO based USB Connector driver"); ++MODULE_LICENSE("GPL"); ++MODULE_DEVICE_TABLE(of, of_gpio_usbvid_match_tbl); +--- a/drivers/extcon/extcon-palmas.c ++++ b/drivers/extcon/extcon-palmas.c +@@ -78,20 +78,24 @@ static irqreturn_t palmas_vbus_irq_handl + + static irqreturn_t palmas_id_irq_handler(int irq, void *_palmas_usb) + { +- unsigned int set; ++ unsigned int set, id_src; + struct palmas_usb *palmas_usb = _palmas_usb; + + palmas_read(palmas_usb->palmas, PALMAS_USB_OTG_BASE, + PALMAS_USB_ID_INT_LATCH_SET, &set); ++ palmas_read(palmas_usb->palmas, PALMAS_USB_OTG_BASE, ++ PALMAS_USB_ID_INT_SRC, &id_src); + +- if (set & PALMAS_USB_ID_INT_SRC_ID_GND) { ++ if ((set & PALMAS_USB_ID_INT_SRC_ID_GND) && ++ (id_src & PALMAS_USB_ID_INT_SRC_ID_GND)) { + palmas_write(palmas_usb->palmas, PALMAS_USB_OTG_BASE, + PALMAS_USB_ID_INT_LATCH_CLR, + PALMAS_USB_ID_INT_EN_HI_CLR_ID_GND); + palmas_usb->linkstat = PALMAS_USB_STATE_ID; + extcon_set_cable_state(&palmas_usb->edev, "USB-HOST", true); + dev_info(palmas_usb->dev, "USB-HOST cable is attached\n"); +- } else if (set & PALMAS_USB_ID_INT_SRC_ID_FLOAT) { ++ } else if ((set & PALMAS_USB_ID_INT_SRC_ID_FLOAT) && ++ (id_src & PALMAS_USB_ID_INT_SRC_ID_FLOAT)) { + palmas_write(palmas_usb->palmas, PALMAS_USB_OTG_BASE, + PALMAS_USB_ID_INT_LATCH_CLR, + PALMAS_USB_ID_INT_EN_HI_CLR_ID_FLOAT); +@@ -103,6 +107,11 @@ static irqreturn_t palmas_id_irq_handler + palmas_usb->linkstat = PALMAS_USB_STATE_DISCONNECT; + extcon_set_cable_state(&palmas_usb->edev, "USB-HOST", false); + dev_info(palmas_usb->dev, "USB-HOST cable is detached\n"); ++ } else if ((palmas_usb->linkstat == PALMAS_USB_STATE_DISCONNECT) && ++ (id_src & PALMAS_USB_ID_INT_SRC_ID_GND)) { ++ palmas_usb->linkstat = PALMAS_USB_STATE_ID; ++ extcon_set_cable_state(&palmas_usb->edev, "USB-HOST", true); ++ dev_info(palmas_usb->dev, " USB-HOST cable is attached\n"); + } + + return IRQ_HANDLED; +@@ -268,6 +277,7 @@ static const struct dev_pm_ops palmas_pm + + static struct of_device_id of_palmas_match_tbl[] = { + { .compatible = "ti,palmas-usb", }, ++ { .compatible = "ti,palmas-usb-vid", }, + { .compatible = "ti,twl6035-usb", }, + { /* end */ } + }; +--- a/drivers/extcon/Kconfig ++++ b/drivers/extcon/Kconfig +@@ -64,4 +64,9 @@ config EXTCON_PALMAS + Say Y here to enable support for USB peripheral and USB host + detection by palmas usb. + ++config EXTCON_GPIO_USBVID ++ tristate "Generic USB VBUS/ID detection using GPIO EXTCON support" ++ help ++ Say Y here to enable support for USB VBUS/ID deetction by GPIO. ++ + endif # MULTISTATE_SWITCH +--- a/drivers/extcon/Makefile ++++ b/drivers/extcon/Makefile +@@ -11,3 +11,4 @@ obj-$(CONFIG_EXTCON_MAX77693) += extcon- + obj-$(CONFIG_EXTCON_MAX8997) += extcon-max8997.o + obj-$(CONFIG_EXTCON_ARIZONA) += extcon-arizona.o + obj-$(CONFIG_EXTCON_PALMAS) += extcon-palmas.o ++obj-$(CONFIG_EXTCON_GPIO_USBVID) += extcon-gpio-usbvid.o +--- a/drivers/gpio/gpio-pcf857x.c ++++ b/drivers/gpio/gpio-pcf857x.c +@@ -26,9 +26,10 @@ + #include <linux/irqdomain.h> + #include <linux/kernel.h> + #include <linux/module.h> ++#include <linux/of.h> ++#include <linux/of_device.h> + #include <linux/slab.h> + #include <linux/spinlock.h> +-#include <linux/workqueue.h> + + + static const struct i2c_device_id pcf857x_id[] = { +@@ -50,6 +51,27 @@ static const struct i2c_device_id pcf857 + }; + MODULE_DEVICE_TABLE(i2c, pcf857x_id); + ++#ifdef CONFIG_OF ++static const struct of_device_id pcf857x_of_table[] = { ++ { .compatible = "nxp,pcf8574" }, ++ { .compatible = "nxp,pcf8574a" }, ++ { .compatible = "nxp,pca8574" }, ++ { .compatible = "nxp,pca9670" }, ++ { .compatible = "nxp,pca9672" }, ++ { .compatible = "nxp,pca9674" }, ++ { .compatible = "nxp,pcf8575" }, ++ { .compatible = "nxp,pca8575" }, ++ { .compatible = "nxp,pca9671" }, ++ { .compatible = "nxp,pca9673" }, ++ { .compatible = "nxp,pca9675" }, ++ { .compatible = "maxim,max7328" }, ++ { .compatible = "maxim,max7329" }, ++ { .compatible = "ti,tca9554" }, ++ { } ++}; ++MODULE_DEVICE_TABLE(of, pcf857x_of_table); ++#endif ++ + /* + * The pcf857x, pca857x, and pca967x chips only expose one read and one + * write register. Writing a "one" bit (to match the reset state) lets +@@ -66,12 +88,11 @@ struct pcf857x { + struct gpio_chip chip; + struct i2c_client *client; + struct mutex lock; /* protect 'out' */ +- struct work_struct work; /* irq demux work */ + struct irq_domain *irq_domain; /* for irq demux */ + spinlock_t slock; /* protect irq demux */ + unsigned out; /* software latch */ + unsigned status; /* current status */ +- int irq; /* real irq number */ ++ unsigned irq_mapped; /* mapped gpio irqs */ + + int (*write)(struct i2c_client *client, unsigned data); + int (*read)(struct i2c_client *client); +@@ -164,48 +185,54 @@ static void pcf857x_set(struct gpio_chip + static int pcf857x_to_irq(struct gpio_chip *chip, unsigned offset) + { + struct pcf857x *gpio = container_of(chip, struct pcf857x, chip); ++ int ret; + +- return irq_create_mapping(gpio->irq_domain, offset); ++ ret = irq_create_mapping(gpio->irq_domain, offset); ++ if (ret > 0) ++ gpio->irq_mapped |= (1 << offset); ++ ++ return ret; + } + +-static void pcf857x_irq_demux_work(struct work_struct *work) ++static irqreturn_t pcf857x_irq(int irq, void *data) + { +- struct pcf857x *gpio = container_of(work, +- struct pcf857x, +- work); ++ struct pcf857x *gpio = data; + unsigned long change, i, status, flags; + + status = gpio->read(gpio->client); + + spin_lock_irqsave(&gpio->slock, flags); + +- change = gpio->status ^ status; ++ /* ++ * call the interrupt handler iff gpio is used as ++ * interrupt source, just to avoid bad irqs ++ */ ++ ++ change = ((gpio->status ^ status) & gpio->irq_mapped); + for_each_set_bit(i, &change, gpio->chip.ngpio) + generic_handle_irq(irq_find_mapping(gpio->irq_domain, i)); + gpio->status = status; + + spin_unlock_irqrestore(&gpio->slock, flags); +-} +- +-static irqreturn_t pcf857x_irq_demux(int irq, void *data) +-{ +- struct pcf857x *gpio = data; +- +- /* +- * pcf857x can't read/write data here, +- * since i2c data access might go to sleep. +- */ +- schedule_work(&gpio->work); + + return IRQ_HANDLED; + } + +-static int pcf857x_irq_domain_map(struct irq_domain *domain, unsigned int virq, ++static int pcf857x_irq_domain_map(struct irq_domain *domain, unsigned int irq, + irq_hw_number_t hw) + { +- irq_set_chip_and_handler(virq, ++ struct pcf857x *gpio = domain->host_data; ++ ++ irq_set_chip_and_handler(irq, + &dummy_irq_chip, + handle_level_irq); ++#ifdef CONFIG_ARM ++ set_irq_flags(irq, IRQF_VALID); ++#else ++ irq_set_noprobe(irq); ++#endif ++ gpio->irq_mapped |= (1 << hw); ++ + return 0; + } + +@@ -218,8 +245,6 @@ static void pcf857x_irq_domain_cleanup(s + if (gpio->irq_domain) + irq_domain_remove(gpio->irq_domain); + +- if (gpio->irq) +- free_irq(gpio->irq, gpio); + } + + static int pcf857x_irq_domain_init(struct pcf857x *gpio, +@@ -230,20 +255,21 @@ static int pcf857x_irq_domain_init(struc + gpio->irq_domain = irq_domain_add_linear(client->dev.of_node, + gpio->chip.ngpio, + &pcf857x_irq_domain_ops, +- NULL); ++ gpio); + if (!gpio->irq_domain) + goto fail; + + /* enable real irq */ +- status = request_irq(client->irq, pcf857x_irq_demux, 0, +- dev_name(&client->dev), gpio); ++ status = devm_request_threaded_irq(&client->dev, client->irq, ++ NULL, pcf857x_irq, IRQF_ONESHOT | ++ IRQF_TRIGGER_FALLING, ++ dev_name(&client->dev), gpio); ++ + if (status) + goto fail; + + /* enable gpio_to_irq() */ +- INIT_WORK(&gpio->work, pcf857x_irq_demux_work); + gpio->chip.to_irq = pcf857x_to_irq; +- gpio->irq = client->irq; + + return 0; + +@@ -257,14 +283,18 @@ fail: + static int pcf857x_probe(struct i2c_client *client, + const struct i2c_device_id *id) + { +- struct pcf857x_platform_data *pdata; ++ struct pcf857x_platform_data *pdata = dev_get_platdata(&client->dev); ++ struct device_node *np = client->dev.of_node; + struct pcf857x *gpio; ++ unsigned int n_latch = 0; + int status; + +- pdata = dev_get_platdata(&client->dev); +- if (!pdata) { ++ if (IS_ENABLED(CONFIG_OF) && np) ++ of_property_read_u32(np, "lines-initial-states", &n_latch); ++ else if (pdata) ++ n_latch = pdata->n_latch; ++ else + dev_dbg(&client->dev, "no platform data\n"); +- } + + /* Allocate, initialize, and register this gpio_chip. */ + gpio = devm_kzalloc(&client->dev, sizeof(*gpio), GFP_KERNEL); +@@ -357,11 +387,11 @@ static int pcf857x_probe(struct i2c_clie + * may cause transient glitching since it can't know the last value + * written (some pins may need to be driven low). + * +- * Using pdata->n_latch avoids that trouble. When left initialized +- * to zero, our software copy of the "latch" then matches the chip's +- * all-ones reset state. Otherwise it flags pins to be driven low. ++ * Using n_latch avoids that trouble. When left initialized to zero, ++ * our software copy of the "latch" then matches the chip's all-ones ++ * reset state. Otherwise it flags pins to be driven low. + */ +- gpio->out = pdata ? ~pdata->n_latch : ~0; ++ gpio->out = ~n_latch; + gpio->status = gpio->out; + + status = gpiochip_add(&gpio->chip); +@@ -423,6 +453,7 @@ static struct i2c_driver pcf857x_driver + .driver = { + .name = "pcf857x", + .owner = THIS_MODULE, ++ .of_match_table = of_match_ptr(pcf857x_of_table), + }, + .probe = pcf857x_probe, + .remove = pcf857x_remove, +--- a/drivers/gpu/drm/omapdrm/omap_crtc.c ++++ b/drivers/gpu/drm/omapdrm/omap_crtc.c +@@ -411,7 +411,7 @@ static void omap_crtc_error_irq(struct o + struct drm_crtc *crtc = &omap_crtc->base; + DRM_ERROR("%s: errors: %08x\n", omap_crtc->name, irqstatus); + /* avoid getting in a flood, unregister the irq until next vblank */ +- omap_irq_unregister(crtc->dev, &omap_crtc->error_irq); ++ __omap_irq_unregister(crtc->dev, &omap_crtc->error_irq); + } + + static void omap_crtc_apply_irq(struct omap_drm_irq *irq, uint32_t irqstatus) +@@ -421,13 +421,13 @@ static void omap_crtc_apply_irq(struct o + struct drm_crtc *crtc = &omap_crtc->base; + + if (!omap_crtc->error_irq.registered) +- omap_irq_register(crtc->dev, &omap_crtc->error_irq); ++ __omap_irq_register(crtc->dev, &omap_crtc->error_irq); + + if (!dispc_mgr_go_busy(omap_crtc->channel)) { + struct omap_drm_private *priv = + crtc->dev->dev_private; + DBG("%s: apply done", omap_crtc->name); +- omap_irq_unregister(crtc->dev, &omap_crtc->apply_irq); ++ __omap_irq_unregister(crtc->dev, &omap_crtc->apply_irq); + queue_work(priv->wq, &omap_crtc->apply_work); + } + } +@@ -623,6 +623,11 @@ void omap_crtc_pre_init(void) + dss_install_mgr_ops(&mgr_ops); + } + ++void omap_crtc_pre_uninit(void) ++{ ++ dss_uninstall_mgr_ops(); ++} ++ + /* initialize crtc */ + struct drm_crtc *omap_crtc_init(struct drm_device *dev, + struct drm_plane *plane, enum omap_channel channel, int id) +--- a/drivers/gpu/drm/omapdrm/omap_dmm_tiler.c ++++ b/drivers/gpu/drm/omapdrm/omap_dmm_tiler.c +@@ -968,12 +968,23 @@ static const struct dev_pm_ops omap_dmm_ + }; + #endif + ++#if defined(CONFIG_OF) ++static const struct of_device_id dmm_of_match[] = { ++ { .compatible = "ti,omap4-dmm", }, ++ { .compatible = "ti,omap5-dmm", }, ++ {}, ++}; ++#else ++#define dmm_of_match NULL ++#endif ++ + struct platform_driver omap_dmm_driver = { + .probe = omap_dmm_probe, + .remove = omap_dmm_remove, + .driver = { + .owner = THIS_MODULE, + .name = DMM_DRIVER_NAME, ++ .of_match_table = dmm_of_match, + #ifdef CONFIG_PM + .pm = &omap_dmm_pm_ops, + #endif +--- a/drivers/gpu/drm/omapdrm/omap_drv.c ++++ b/drivers/gpu/drm/omapdrm/omap_drv.c +@@ -86,6 +86,47 @@ static bool channel_used(struct drm_devi + + return false; + } ++static void omap_disconnect_dssdevs(void) ++{ ++ struct omap_dss_device *dssdev = NULL; ++ ++ for_each_dss_dev(dssdev) ++ dssdev->driver->disconnect(dssdev); ++} ++ ++static int omap_connect_dssdevs(void) ++{ ++ int r; ++ struct omap_dss_device *dssdev = NULL; ++ bool no_displays = true; ++ ++ for_each_dss_dev(dssdev) { ++ r = dssdev->driver->connect(dssdev); ++ if (r == -EPROBE_DEFER) { ++ omap_dss_put_device(dssdev); ++ goto cleanup; ++ } else if (r) { ++ dev_warn(dssdev->dev, "could not connect display: %s\n", ++ dssdev->name); ++ } else { ++ no_displays = false; ++ } ++ } ++ ++ if (no_displays) ++ return -EPROBE_DEFER; ++ ++ return 0; ++ ++cleanup: ++ /* ++ * if we are deferring probe, we disconnect the devices we previously ++ * connected ++ */ ++ omap_disconnect_dssdevs(); ++ ++ return r; ++} + + static int omap_modeset_init(struct drm_device *dev) + { +@@ -95,9 +136,6 @@ static int omap_modeset_init(struct drm_ + int num_mgrs = dss_feat_get_num_mgrs(); + int num_crtcs; + int i, id = 0; +- int r; +- +- omap_crtc_pre_init(); + + drm_mode_config_init(dev); + +@@ -119,26 +157,8 @@ static int omap_modeset_init(struct drm_ + enum omap_channel channel; + struct omap_overlay_manager *mgr; + +- if (!dssdev->driver) { +- dev_warn(dev->dev, "%s has no driver.. skipping it\n", +- dssdev->name); +- continue; +- } +- +- if (!(dssdev->driver->get_timings || +- dssdev->driver->read_edid)) { +- dev_warn(dev->dev, "%s driver does not support " +- "get_timings or read_edid.. skipping it!\n", +- dssdev->name); +- continue; +- } +- +- r = dssdev->driver->connect(dssdev); +- if (r) { +- dev_err(dev->dev, "could not connect display: %s\n", +- dssdev->name); ++ if (!omapdss_device_is_connected(dssdev)) + continue; +- } + + encoder = omap_encoder_init(dev, dssdev); + +@@ -656,9 +676,19 @@ static void pdev_shutdown(struct platfor + + static int pdev_probe(struct platform_device *device) + { ++ int r; ++ + if (omapdss_is_initialized() == false) + return -EPROBE_DEFER; + ++ omap_crtc_pre_init(); ++ ++ r = omap_connect_dssdevs(); ++ if (r) { ++ omap_crtc_pre_uninit(); ++ return r; ++ } ++ + DBG("%s", device->name); + return drm_platform_init(&omap_drm_driver, device); + } +@@ -668,6 +698,8 @@ static int pdev_remove(struct platform_d + DBG(""); + drm_platform_exit(&omap_drm_driver, device); + ++ omap_disconnect_dssdevs(); ++ + platform_driver_unregister(&omap_dmm_driver); + return 0; + } +--- a/drivers/gpu/drm/omapdrm/omap_drv.h ++++ b/drivers/gpu/drm/omapdrm/omap_drv.h +@@ -145,6 +145,8 @@ irqreturn_t omap_irq_handler(DRM_IRQ_ARG + void omap_irq_preinstall(struct drm_device *dev); + int omap_irq_postinstall(struct drm_device *dev); + void omap_irq_uninstall(struct drm_device *dev); ++void __omap_irq_register(struct drm_device *dev, struct omap_drm_irq *irq); ++void __omap_irq_unregister(struct drm_device *dev, struct omap_drm_irq *irq); + void omap_irq_register(struct drm_device *dev, struct omap_drm_irq *irq); + void omap_irq_unregister(struct drm_device *dev, struct omap_drm_irq *irq); + int omap_drm_irq_uninstall(struct drm_device *dev); +@@ -158,6 +160,7 @@ enum omap_channel omap_crtc_channel(stru + int omap_crtc_apply(struct drm_crtc *crtc, + struct omap_drm_apply *apply); + void omap_crtc_pre_init(void); ++void omap_crtc_pre_uninit(void); + struct drm_crtc *omap_crtc_init(struct drm_device *dev, + struct drm_plane *plane, enum omap_channel channel, int id); + +--- a/drivers/gpu/drm/omapdrm/omap_encoder.c ++++ b/drivers/gpu/drm/omapdrm/omap_encoder.c +@@ -51,6 +51,10 @@ struct omap_dss_device *omap_encoder_get + static void omap_encoder_destroy(struct drm_encoder *encoder) + { + struct omap_encoder *omap_encoder = to_omap_encoder(encoder); ++ struct omap_dss_device *dssdev = omap_encoder->dssdev; ++ ++ dssdev->driver->disable(dssdev); ++ + drm_encoder_cleanup(encoder); + kfree(omap_encoder); + } +--- a/drivers/gpu/drm/omapdrm/omap_irq.c ++++ b/drivers/gpu/drm/omapdrm/omap_irq.c +@@ -45,12 +45,11 @@ static void omap_irq_update(struct drm_d + dispc_read_irqenable(); /* flush posted write */ + } + +-void omap_irq_register(struct drm_device *dev, struct omap_drm_irq *irq) ++void __omap_irq_register(struct drm_device *dev, struct omap_drm_irq *irq) + { + struct omap_drm_private *priv = dev->dev_private; + unsigned long flags; + +- dispc_runtime_get(); + spin_lock_irqsave(&list_lock, flags); + + if (!WARN_ON(irq->registered)) { +@@ -60,14 +59,21 @@ void omap_irq_register(struct drm_device + } + + spin_unlock_irqrestore(&list_lock, flags); ++} ++ ++void omap_irq_register(struct drm_device *dev, struct omap_drm_irq *irq) ++{ ++ dispc_runtime_get(); ++ ++ __omap_irq_register(dev, irq); ++ + dispc_runtime_put(); + } + +-void omap_irq_unregister(struct drm_device *dev, struct omap_drm_irq *irq) ++void __omap_irq_unregister(struct drm_device *dev, struct omap_drm_irq *irq) + { + unsigned long flags; + +- dispc_runtime_get(); + spin_lock_irqsave(&list_lock, flags); + + if (!WARN_ON(!irq->registered)) { +@@ -77,6 +83,14 @@ void omap_irq_unregister(struct drm_devi + } + + spin_unlock_irqrestore(&list_lock, flags); ++} ++ ++void omap_irq_unregister(struct drm_device *dev, struct omap_drm_irq *irq) ++{ ++ dispc_runtime_get(); ++ ++ __omap_irq_unregister(dev, irq); ++ + dispc_runtime_put(); + } + +--- a/drivers/gpu/drm/omapdrm/omap_plane.c ++++ b/drivers/gpu/drm/omapdrm/omap_plane.c +@@ -122,6 +122,7 @@ static void omap_plane_pre_apply(struct + enum omap_channel channel; + bool enabled = omap_plane->enabled && crtc; + bool ilace, replication; ++ u32 low, high; + int ret; + + DBG("%s, enabled=%d", omap_plane->name, enabled); +@@ -149,6 +150,10 @@ static void omap_plane_pre_apply(struct + ilace = false; + replication = false; + ++ dispc_ovl_compute_fifo_thresholds(omap_plane->id, &low, &high, ++ false, false); ++ dispc_ovl_set_fifo_threshold(omap_plane->id, low, high); ++ + /* and finally, update omapdss: */ + ret = dispc_ovl_setup(omap_plane->id, info, + replication, omap_crtc_timings(crtc), false); +--- a/drivers/gpu/drm/tilcdc/tilcdc_drv.h ++++ b/drivers/gpu/drm/tilcdc/tilcdc_drv.h +@@ -43,7 +43,7 @@ + * with optimized DDR & EMIF settings tweaked 1920x1080@24 appears to + * be supportable + */ +-#define TILCDC_DEFAULT_MAX_BANDWIDTH (1280*1024*60) ++#define TILCDC_DEFAULT_MAX_BANDWIDTH (1680*1050*60) + + + struct tilcdc_drm_private { +--- a/drivers/iio/adc/ti_am335x_adc.c ++++ b/drivers/iio/adc/ti_am335x_adc.c +@@ -154,7 +154,7 @@ static int tiadc_read_raw(struct iio_dev + while (tiadc_readl(adc_dev, REG_ADCFSM) & SEQ_STATUS) { + if (time_after(jiffies, timeout)) + return -EAGAIN; +- } ++ } + map_val = chan->channel + TOTAL_CHANNELS; + + /* +--- a/drivers/input/touchscreen/atmel_mxt_ts.c ++++ b/drivers/input/touchscreen/atmel_mxt_ts.c +@@ -20,6 +20,8 @@ + #include <linux/input/mt.h> + #include <linux/interrupt.h> + #include <linux/slab.h> ++#include <linux/of.h> ++#include <linux/of_device.h> + + /* Version */ + #define MXT_VER_20 20 +@@ -335,6 +337,105 @@ static void mxt_dump_message(struct devi + message->reportid, 7, message->message); + } + ++static int mxt_of_get_platform_info(struct i2c_client *client, ++ struct mxt_platform_data *pdata) ++ ++{ ++ int size, index = 0; ++ u32 val; ++ const __be32 *config_be; ++ u8 *config; ++ const char *pname; ++ struct device_node *node = client->dev.of_node; ++ ++ config_be = of_get_property(node, "atmel,config", &size); ++ if (config_be && size) { ++ size /= sizeof(*config_be); ++ config = devm_kzalloc(&client->dev, size, GFP_KERNEL); ++ if (!config) { ++ dev_err(&client->dev, "Failed to allocate memory\n"); ++ return -ENOMEM; ++ } ++ ++ pdata->config = config; ++ pdata->config_length = size; ++ ++ while (index < size) { ++ config[index] = be32_to_cpup(config_be + index) & 0xFF; ++ index++; ++ } ++ } else { ++ dev_dbg(&client->dev, "%s:no config data specified\n", ++ __func__); ++ } ++ ++ pname = "atmel,x_line"; ++ if (of_property_read_u32(node, pname, &pdata->x_line)) { ++ dev_err(&client->dev, "%s: Failed to read %s property\n", ++ __func__, pname); ++ return -EINVAL; ++ } ++ ++ pname = "atmel,y_line"; ++ if (of_property_read_u32(node, pname, &pdata->y_line)) { ++ dev_err(&client->dev, "%s: Failed to read %s property\n", ++ __func__, pname); ++ return -EINVAL; ++ } ++ ++ pname = "atmel,x_size"; ++ if (of_property_read_u32(node, pname, &pdata->x_size)) { ++ dev_err(&client->dev, "%s: Failed to read %s property\n", ++ __func__, pname); ++ return -EINVAL; ++ } ++ ++ pname = "atmel,y_size"; ++ if (of_property_read_u32(node, pname, &pdata->y_size)) { ++ dev_err(&client->dev, "%s: Failed to read %s property\n", ++ __func__, pname); ++ return -EINVAL; ++ } ++ ++ pname = "atmel,blen"; ++ if (of_property_read_u32(node, pname, &pdata->blen)) { ++ dev_err(&client->dev, "%s: Failed to read %s property\n", ++ __func__, pname); ++ return -EINVAL; ++ } ++ ++ pname = "atmel,threshold"; ++ if (of_property_read_u32(node, pname, &pdata->threshold)) { ++ dev_err(&client->dev, "%s: Failed to read %s property\n", ++ __func__, pname); ++ return -EINVAL; ++ } ++ ++ pname = "atmel,voltage"; ++ if (of_property_read_u32(node, pname, &pdata->voltage)) { ++ dev_err(&client->dev, ++ "%s: Failed to read %s property\n", ++ __func__, pname); ++ return -EINVAL; ++ } ++ ++ pname = "atmel,orient"; ++ if (of_property_read_u32(node, pname, &val)) { ++ dev_err(&client->dev, "%s: Failed to read %s property\n", ++ __func__, pname); ++ return -EINVAL; ++ } ++ ++ if (val > 0xFF) { ++ dev_err(&client->dev, "%s: Bad %s property value %d\n", ++ __func__, pname, val); ++ return -EINVAL; ++ } ++ pdata->orient = val & 0xFF; ++ ++ return 0; ++} ++ + static int mxt_check_bootloader(struct i2c_client *client, + unsigned int state) + { +@@ -1127,19 +1228,43 @@ static void mxt_input_close(struct input + mxt_stop(data); + } + ++static const struct of_device_id mxt_dt_ids[] = { ++ { .compatible = "atmel,qt602240_ts", }, ++ { .compatible = "atmel,atmel_mxt_ts", }, ++ { .compatible = "atmel,mXT244", }, ++ { /* sentinel */ } ++}; ++MODULE_DEVICE_TABLE(of, mxt_dt_ids); ++ + static int mxt_probe(struct i2c_client *client, + const struct i2c_device_id *id) + { +- const struct mxt_platform_data *pdata = client->dev.platform_data; ++ struct mxt_platform_data *pdata; + struct mxt_data *data; + struct input_dev *input_dev; + int error; + unsigned int num_mt_slots; ++ const struct of_device_id *match; + +- if (!pdata) +- return -EINVAL; ++ match = of_match_device(of_match_ptr(mxt_dt_ids), &client->dev); ++ if (match) { ++ pdata = devm_kzalloc(&client->dev, ++ sizeof(struct mxt_platform_data), ++ GFP_KERNEL); ++ if (!pdata) ++ return -ENOMEM; ++ error = mxt_of_get_platform_info(client, pdata); ++ if (error) ++ return error; ++ } else { ++ pdata = client->dev.platform_data; ++ if (!pdata) { ++ dev_err(&client->dev, "Platform data not populated\n"); ++ return -EINVAL; ++ } ++ } + +- data = kzalloc(sizeof(struct mxt_data), GFP_KERNEL); ++ data = devm_kzalloc(&client->dev, sizeof(struct mxt_data), GFP_KERNEL); + input_dev = input_allocate_device(); + if (!data || !input_dev) { + dev_err(&client->dev, "Failed to allocate memory\n"); +@@ -1224,9 +1349,10 @@ static int mxt_probe(struct i2c_client * + input_set_drvdata(input_dev, data); + i2c_set_clientdata(client, data); + +- error = request_threaded_irq(client->irq, NULL, mxt_interrupt, +- pdata->irqflags | IRQF_ONESHOT, +- client->name, data); ++ error = devm_request_threaded_irq(&client->dev, client->irq, ++ NULL, mxt_interrupt, ++ IRQF_ONESHOT, ++ dev_name(&client->dev), data); + if (error) { + dev_err(&client->dev, "Failed to register interrupt\n"); + goto err_free_object; +@@ -1234,11 +1360,11 @@ static int mxt_probe(struct i2c_client * + + error = mxt_make_highchg(data); + if (error) +- goto err_free_irq; ++ goto err_free_object; + + error = input_register_device(input_dev); + if (error) +- goto err_free_irq; ++ goto err_free_object; + + error = sysfs_create_group(&client->dev.kobj, &mxt_attr_group); + if (error) +@@ -1249,13 +1375,10 @@ static int mxt_probe(struct i2c_client * + err_unregister_device: + input_unregister_device(input_dev); + input_dev = NULL; +-err_free_irq: +- free_irq(client->irq, data); + err_free_object: + kfree(data->object_table); + err_free_mem: + input_free_device(input_dev); +- kfree(data); + return error; + } + +@@ -1264,10 +1387,8 @@ static int mxt_remove(struct i2c_client + struct mxt_data *data = i2c_get_clientdata(client); + + sysfs_remove_group(&client->dev.kobj, &mxt_attr_group); +- free_irq(data->irq, data); + input_unregister_device(data->input_dev); + kfree(data->object_table); +- kfree(data); + + return 0; + } +@@ -1328,6 +1449,7 @@ static struct i2c_driver mxt_driver = { + .name = "atmel_mxt_ts", + .owner = THIS_MODULE, + .pm = &mxt_pm_ops, ++ .of_match_table = mxt_dt_ids, + }, + .probe = mxt_probe, + .remove = mxt_remove, +--- a/drivers/input/touchscreen/pixcir_i2c_ts.c ++++ b/drivers/input/touchscreen/pixcir_i2c_ts.c +@@ -23,170 +23,490 @@ + #include <linux/slab.h> + #include <linux/i2c.h> + #include <linux/input.h> ++#include <linux/input/mt.h> + #include <linux/input/pixcir_ts.h> ++#include <linux/gpio.h> ++#include <linux/of.h> ++#include <linux/of_gpio.h> ++#include <linux/of_device.h> ++ ++#define MAX_FINGERS 5 /* Maximum supported by the driver */ + + struct pixcir_i2c_ts_data { + struct i2c_client *client; + struct input_dev *input; +- const struct pixcir_ts_platform_data *chip; ++ const struct pixcir_ts_platform_data *pdata; + bool exiting; ++ u8 max_fingers; /* Maximum supported by the chip */ + }; + +-static void pixcir_ts_poscheck(struct pixcir_i2c_ts_data *data) ++static void pixcir_ts_typea_report(struct pixcir_i2c_ts_data *tsdata) + { +- struct pixcir_i2c_ts_data *tsdata = data; ++ const struct pixcir_ts_platform_data *pdata = tsdata->pdata; + u8 rdbuf[10], wrbuf[1] = { 0 }; + u8 touch; + int ret; + +- ret = i2c_master_send(tsdata->client, wrbuf, sizeof(wrbuf)); +- if (ret != sizeof(wrbuf)) { +- dev_err(&tsdata->client->dev, +- "%s: i2c_master_send failed(), ret=%d\n", +- __func__, ret); +- return; +- } +- +- ret = i2c_master_recv(tsdata->client, rdbuf, sizeof(rdbuf)); +- if (ret != sizeof(rdbuf)) { +- dev_err(&tsdata->client->dev, +- "%s: i2c_master_recv failed(), ret=%d\n", +- __func__, ret); +- return; +- } +- +- touch = rdbuf[0]; +- if (touch) { +- u16 posx1 = (rdbuf[3] << 8) | rdbuf[2]; +- u16 posy1 = (rdbuf[5] << 8) | rdbuf[4]; +- u16 posx2 = (rdbuf[7] << 8) | rdbuf[6]; +- u16 posy2 = (rdbuf[9] << 8) | rdbuf[8]; +- +- input_report_key(tsdata->input, BTN_TOUCH, 1); +- input_report_abs(tsdata->input, ABS_X, posx1); +- input_report_abs(tsdata->input, ABS_Y, posy1); +- +- input_report_abs(tsdata->input, ABS_MT_POSITION_X, posx1); +- input_report_abs(tsdata->input, ABS_MT_POSITION_Y, posy1); +- input_mt_sync(tsdata->input); +- +- if (touch == 2) { +- input_report_abs(tsdata->input, +- ABS_MT_POSITION_X, posx2); +- input_report_abs(tsdata->input, +- ABS_MT_POSITION_Y, posy2); ++ while (!tsdata->exiting) { ++ ++ ret = i2c_master_send(tsdata->client, wrbuf, sizeof(wrbuf)); ++ if (ret != sizeof(wrbuf)) { ++ dev_err(&tsdata->client->dev, ++ "%s: i2c_master_send failed(), ret=%d\n", ++ __func__, ret); ++ return; ++ } ++ ++ ret = i2c_master_recv(tsdata->client, rdbuf, sizeof(rdbuf)); ++ if (ret != sizeof(rdbuf)) { ++ dev_err(&tsdata->client->dev, ++ "%s: i2c_master_recv failed(), ret=%d\n", ++ __func__, ret); ++ return; ++ } ++ ++ touch = rdbuf[0]; ++ if (touch) { ++ u16 posx1 = (rdbuf[3] << 8) | rdbuf[2]; ++ u16 posy1 = (rdbuf[5] << 8) | rdbuf[4]; ++ u16 posx2 = (rdbuf[7] << 8) | rdbuf[6]; ++ u16 posy2 = (rdbuf[9] << 8) | rdbuf[8]; ++ ++ input_report_key(tsdata->input, BTN_TOUCH, 1); ++ input_report_abs(tsdata->input, ABS_X, posx1); ++ input_report_abs(tsdata->input, ABS_Y, posy1); ++ ++ input_report_abs(tsdata->input, ABS_MT_POSITION_X, ++ posx1); ++ input_report_abs(tsdata->input, ABS_MT_POSITION_Y, ++ posy1); + input_mt_sync(tsdata->input); ++ ++ if (touch == 2) { ++ input_report_abs(tsdata->input, ++ ABS_MT_POSITION_X, posx2); ++ input_report_abs(tsdata->input, ++ ABS_MT_POSITION_Y, posy2); ++ input_mt_sync(tsdata->input); ++ } ++ } else { ++ input_report_key(tsdata->input, BTN_TOUCH, 0); + } +- } else { +- input_report_key(tsdata->input, BTN_TOUCH, 0); ++ ++ input_sync(tsdata->input); ++ ++ if (gpio_get_value(pdata->gpio_attb)) ++ break; ++ ++ msleep(20); + } ++} ++ ++static void pixcir_ts_typeb_report(struct pixcir_i2c_ts_data *ts) ++{ ++ const struct pixcir_ts_platform_data *pdata = ts->pdata; ++ struct device *dev = &ts->client->dev; ++ u8 rdbuf[32], wrbuf[1] = { 0 }; ++ u8 *bufptr; ++ u8 num_fingers; ++ u8 unreliable; ++ int ret, i; ++ ++ while (!ts->exiting) { ++ ++ ret = i2c_master_send(ts->client, wrbuf, sizeof(wrbuf)); ++ if (ret != sizeof(wrbuf)) { ++ dev_err(dev, "%s: i2c_master_send failed(), ret=%d\n", ++ __func__, ret); ++ return; ++ } ++ ++ ret = i2c_master_recv(ts->client, rdbuf, sizeof(rdbuf)); ++ if (ret != sizeof(rdbuf)) { ++ dev_err(dev, "%s: i2c_master_recv failed(), ret=%d\n", ++ __func__, ret); ++ return; ++ } + +- input_sync(tsdata->input); ++ unreliable = rdbuf[0] & 0xe0; ++ ++ if (unreliable) ++ goto next; /* ignore unreliable data */ ++ ++ num_fingers = rdbuf[0] & 0x7; ++ bufptr = &rdbuf[2]; ++ ++ if (num_fingers > ts->max_fingers) { ++ num_fingers = ts->max_fingers; ++ dev_dbg(dev, "limiting num_fingers to %d\n", ++ num_fingers); ++ } ++ ++ for (i = 0; i < num_fingers; i++) { ++ u8 id; ++ unsigned int x, y; ++ int slot; ++ ++ id = bufptr[4]; ++ slot = input_mt_get_slot_by_key(ts->input, id); ++ if (slot < 0) { ++ dev_dbg(dev, "no free slot for id 0x%x\n", id); ++ continue; ++ } ++ ++ ++ x = bufptr[1] << 8 | bufptr[0]; ++ y = bufptr[3] << 8 | bufptr[2]; ++ ++ input_mt_slot(ts->input, slot); ++ input_mt_report_slot_state(ts->input, ++ MT_TOOL_FINGER, true); ++ ++ input_event(ts->input, EV_ABS, ABS_MT_POSITION_X, x); ++ input_event(ts->input, EV_ABS, ABS_MT_POSITION_Y, y); ++ ++ bufptr = &bufptr[5]; ++ dev_dbg(dev, "%d: id 0x%x slot %d, x %d, y %d\n", ++ i, id, slot, x, y); ++ } ++ ++ /* One frame is complete so sync it */ ++ input_mt_sync_frame(ts->input); ++ input_sync(ts->input); ++ ++next: ++ if (gpio_get_value(pdata->gpio_attb)) ++ break; ++ ++ usleep_range(2000, 5000); ++ } + } + + static irqreturn_t pixcir_ts_isr(int irq, void *dev_id) + { + struct pixcir_i2c_ts_data *tsdata = dev_id; + +- while (!tsdata->exiting) { +- pixcir_ts_poscheck(tsdata); ++ if (tsdata->input->mt) ++ pixcir_ts_typeb_report(tsdata); ++ else ++ pixcir_ts_typea_report(tsdata); + +- if (tsdata->chip->attb_read_val()) +- break; ++ return IRQ_HANDLED; ++} + +- msleep(20); ++static int pixcir_set_power_mode(struct pixcir_i2c_ts_data *ts, ++ enum pixcir_power_mode mode) ++{ ++ struct device *dev = &ts->client->dev; ++ int ret; ++ ++ ret = i2c_smbus_read_byte_data(ts->client, PIXCIR_REG_POWER_MODE); ++ if (ret < 0) { ++ dev_err(dev, "%s: can't read reg 0x%x : %d\n", ++ __func__, PIXCIR_REG_POWER_MODE, ret); ++ return ret; + } + +- return IRQ_HANDLED; ++ ret &= ~PIXCIR_POWER_MODE_MASK; ++ ret |= mode; ++ ++ /* Always AUTO_IDLE */ ++ ret |= PIXCIR_POWER_ALLOW_IDLE; ++ ++ ret = i2c_smbus_write_byte_data(ts->client, PIXCIR_REG_POWER_MODE, ret); ++ if (ret < 0) { ++ dev_err(dev, "%s: can't write reg 0x%x : %d\n", ++ __func__, PIXCIR_REG_POWER_MODE, ret); ++ return ret; ++ } ++ ++ return 0; + } + +-#ifdef CONFIG_PM_SLEEP +-static int pixcir_i2c_ts_suspend(struct device *dev) ++/* ++ * Set the interrupt mode for the device i.e. ATTB line behaviour ++ * ++ * @polarity : 1 for active high, 0 for active low. ++ */ ++static int pixcir_set_int_mode(struct pixcir_i2c_ts_data *ts, ++ enum pixcir_int_mode mode, ++ bool polarity) + { +- struct i2c_client *client = to_i2c_client(dev); ++ struct device *dev = &ts->client->dev; ++ int ret; + +- if (device_may_wakeup(&client->dev)) +- enable_irq_wake(client->irq); ++ ret = i2c_smbus_read_byte_data(ts->client, PIXCIR_REG_INT_MODE); ++ if (ret < 0) { ++ dev_err(dev, "%s: can't read reg 0x%x : %d\n", ++ __func__, PIXCIR_REG_INT_MODE, ret); ++ return ret; ++ } ++ ++ ret &= ~PIXCIR_INT_MODE_MASK; ++ ret |= mode; ++ ++ if (polarity) ++ ret |= PIXCIR_INT_POL_HIGH; ++ else ++ ret &= ~PIXCIR_INT_POL_HIGH; ++ ++ ret = i2c_smbus_write_byte_data(ts->client, PIXCIR_REG_INT_MODE, ret); ++ if (ret < 0) { ++ dev_err(dev, "%s: can't write reg 0x%x : %d\n", ++ __func__, PIXCIR_REG_INT_MODE, ret); ++ return ret; ++ } + + return 0; + } + +-static int pixcir_i2c_ts_resume(struct device *dev) ++/* ++ * Enable/disable interrupt generation ++ */ ++static int pixcir_int_enable(struct pixcir_i2c_ts_data *ts, bool enable) + { +- struct i2c_client *client = to_i2c_client(dev); ++ struct device *dev = &ts->client->dev; ++ int ret; + +- if (device_may_wakeup(&client->dev)) +- disable_irq_wake(client->irq); ++ ret = i2c_smbus_read_byte_data(ts->client, PIXCIR_REG_INT_MODE); ++ if (ret < 0) { ++ dev_err(dev, "%s: can't read reg 0x%x : %d\n", ++ __func__, PIXCIR_REG_INT_MODE, ret); ++ return ret; ++ } ++ ++ if (enable) ++ ret |= PIXCIR_INT_ENABLE; ++ else ++ ret &= ~PIXCIR_INT_ENABLE; ++ ++ ret = i2c_smbus_write_byte_data(ts->client, PIXCIR_REG_INT_MODE, ret); ++ if (ret < 0) { ++ dev_err(dev, "%s: can't write reg 0x%x : %d\n", ++ __func__, PIXCIR_REG_INT_MODE, ret); ++ return ret; ++ } + + return 0; + } +-#endif + +-static SIMPLE_DEV_PM_OPS(pixcir_dev_pm_ops, +- pixcir_i2c_ts_suspend, pixcir_i2c_ts_resume); ++static int pixcir_start(struct pixcir_i2c_ts_data *ts) ++{ ++ struct device *dev = &ts->client->dev; ++ int ret; ++ ++ /* LEVEL_TOUCH interrupt with active low polarity */ ++ ret = pixcir_set_int_mode(ts, PIXCIR_INT_LEVEL_TOUCH, 0); ++ if (ret) { ++ dev_err(dev, "Failed to set interrupt mode\n"); ++ return ret; ++ } ++ ++ enable_irq(ts->client->irq); ++ ++ /* enable interrupt generation */ ++ ret = pixcir_int_enable(ts, 1); ++ if (ret) { ++ dev_err(dev, "Failed to enable interrupt generation\n"); ++ return ret; ++ } ++ ++ return 0; ++} ++ ++static int pixcir_stop(struct pixcir_i2c_ts_data *ts) ++{ ++ struct device *dev = &ts->client->dev; ++ int ret; ++ ++ /* disable interrupt generation */ ++ ret = pixcir_int_enable(ts, 0); ++ if (ret) { ++ dev_err(dev, "Failed to disable interrupt generation\n"); ++ return ret; ++ } ++ ++ disable_irq(ts->client->irq); ++ ++ return 0; ++} ++ ++static int pixcir_input_open(struct input_dev *dev) ++{ ++ struct pixcir_i2c_ts_data *ts = input_get_drvdata(dev); ++ ++ return pixcir_start(ts); ++} ++ ++static void pixcir_input_close(struct input_dev *dev) ++{ ++ struct pixcir_i2c_ts_data *ts = input_get_drvdata(dev); ++ ++ pixcir_stop(ts); ++ ++ return; ++} ++ ++#if defined(CONFIG_OF) ++static const struct of_device_id pixcir_of_match[]; ++ ++static struct pixcir_ts_platform_data *pixcir_parse_dt(struct device *dev) ++{ ++ struct pixcir_ts_platform_data *pdata; ++ struct device_node *np = dev->of_node; ++ const struct of_device_id *match; ++ ++ match = of_match_device(of_match_ptr(pixcir_of_match), dev); ++ if (!match) ++ return ERR_PTR(-EINVAL); ++ ++ pdata = devm_kzalloc(dev, sizeof(*pdata), GFP_KERNEL); ++ if (!pdata) ++ return ERR_PTR(-ENOMEM); ++ ++ pdata->chip = *(const struct pixcir_i2c_chip_data *)match->data; ++ ++ pdata->gpio_attb = of_get_named_gpio(np, "attb-gpio", 0); ++ if (!gpio_is_valid(pdata->gpio_attb)) { ++ dev_err(dev, "Failed to get ATTB GPIO\n"); ++ return ERR_PTR(-EINVAL); ++ } ++ ++ if (of_property_read_u32(np, "x-size", &pdata->x_size)) { ++ dev_err(dev, "Failed to get x-size property\n"); ++ return ERR_PTR(-EINVAL); ++ } ++ ++ if (of_property_read_u32(np, "y-size", &pdata->y_size)) { ++ dev_err(dev, "Failed to get y-size property\n"); ++ return ERR_PTR(-EINVAL); ++ } ++ ++ dev_dbg(dev, "%s: x %d, y %d, gpio %d\n", __func__, ++ pdata->x_size, pdata->y_size, pdata->gpio_attb); ++ ++ return pdata; ++} ++#else ++static struct pixcir_ts_platform_data *pixcir_parse_dt(struct device *dev) ++{ ++ return NULL; ++} ++#endif + + static int pixcir_i2c_ts_probe(struct i2c_client *client, + const struct i2c_device_id *id) + { + const struct pixcir_ts_platform_data *pdata = client->dev.platform_data; ++ struct device *dev = &client->dev; ++ struct device_node *np = dev->of_node; + struct pixcir_i2c_ts_data *tsdata; + struct input_dev *input; + int error; + +- if (!pdata) { ++ if (np) { ++ pdata = pixcir_parse_dt(dev); ++ if (IS_ERR(pdata)) ++ return PTR_ERR(pdata); ++ ++ } else if (!pdata) { + dev_err(&client->dev, "platform data not defined\n"); + return -EINVAL; ++ } else { ++ if (!gpio_is_valid(pdata->gpio_attb)) { ++ dev_err(dev, "Invalid gpio_attb in pdata\n"); ++ return -EINVAL; ++ } + } + +- tsdata = kzalloc(sizeof(*tsdata), GFP_KERNEL); +- input = input_allocate_device(); +- if (!tsdata || !input) { +- dev_err(&client->dev, "Failed to allocate driver data!\n"); +- error = -ENOMEM; +- goto err_free_mem; ++ tsdata = devm_kzalloc(dev, sizeof(*tsdata), GFP_KERNEL); ++ if (!tsdata) ++ return -ENOMEM; ++ ++ input = devm_input_allocate_device(dev); ++ if (!input) { ++ dev_err(&client->dev, "Failed to allocate input device\n"); ++ return -ENOMEM; + } + + tsdata->client = client; + tsdata->input = input; +- tsdata->chip = pdata; ++ tsdata->pdata = pdata; + + input->name = client->name; + input->id.bustype = BUS_I2C; + input->dev.parent = &client->dev; ++ input->open = pixcir_input_open; ++ input->close = pixcir_input_close; + +- __set_bit(EV_KEY, input->evbit); + __set_bit(EV_ABS, input->evbit); + __set_bit(BTN_TOUCH, input->keybit); +- input_set_abs_params(input, ABS_X, 0, pdata->x_max, 0, 0); +- input_set_abs_params(input, ABS_Y, 0, pdata->y_max, 0, 0); +- input_set_abs_params(input, ABS_MT_POSITION_X, 0, pdata->x_max, 0, 0); +- input_set_abs_params(input, ABS_MT_POSITION_Y, 0, pdata->y_max, 0, 0); ++ ++ input_set_abs_params(input, ABS_X, ++ 0, pdata->x_size - 1, 0, 0); ++ input_set_abs_params(input, ABS_Y, ++ 0, pdata->y_size - 1, 0, 0); ++ input_set_abs_params(input, ABS_MT_POSITION_X, ++ 0, pdata->x_size - 1, 0, 0); ++ input_set_abs_params(input, ABS_MT_POSITION_Y, ++ 0, pdata->y_size - 1, 0, 0); ++ ++ /* Type-B Multi-Touch support */ ++ if (pdata->chip.num_report_ids) { ++ const struct pixcir_i2c_chip_data *chip = &pdata->chip; ++ ++ tsdata->max_fingers = chip->num_report_ids; ++ if (tsdata->max_fingers > MAX_FINGERS) { ++ dev_info(dev, "Limiting maximum fingers to %d\n", ++ MAX_FINGERS); ++ tsdata->max_fingers = MAX_FINGERS; ++ } ++ ++ error = input_mt_init_slots(input, tsdata->max_fingers, ++ INPUT_MT_DIRECT | INPUT_MT_DROP_UNUSED); ++ if (error) { ++ dev_err(dev, "Error initializing Multi-Touch slots\n"); ++ return error; ++ } ++ } + + input_set_drvdata(input, tsdata); + +- error = request_threaded_irq(client->irq, NULL, pixcir_ts_isr, ++ error = devm_gpio_request_one(dev, pdata->gpio_attb, ++ GPIOF_DIR_IN, "pixcir_i2c_attb"); ++ if (error) { ++ dev_err(dev, "Failed to request ATTB gpio\n"); ++ return error; ++ } ++ ++ error = devm_request_threaded_irq(dev, client->irq, NULL, pixcir_ts_isr, + IRQF_TRIGGER_FALLING | IRQF_ONESHOT, + client->name, tsdata); + if (error) { +- dev_err(&client->dev, "Unable to request touchscreen IRQ.\n"); +- goto err_free_mem; ++ dev_err(dev, "failed to request irq %d\n", client->irq); ++ return error; + } + ++ /* Always be in IDLE mode to save power, device supports auto wake */ ++ error = pixcir_set_power_mode(tsdata, PIXCIR_POWER_IDLE); ++ if (error) { ++ dev_err(dev, "Failed to set IDLE mode\n"); ++ return error; ++ } ++ ++ /* Stop device till opened */ ++ error = pixcir_stop(tsdata); ++ if (error) ++ return error; ++ + error = input_register_device(input); + if (error) +- goto err_free_irq; ++ return error; + + i2c_set_clientdata(client, tsdata); + device_init_wakeup(&client->dev, 1); + + return 0; +- +-err_free_irq: +- free_irq(client->irq, tsdata); +-err_free_mem: +- input_free_device(input); +- kfree(tsdata); +- return error; + } + + static int pixcir_i2c_ts_remove(struct i2c_client *client) +@@ -197,25 +517,99 @@ static int pixcir_i2c_ts_remove(struct i + + tsdata->exiting = true; + mb(); +- free_irq(client->irq, tsdata); +- +- input_unregister_device(tsdata->input); +- kfree(tsdata); + + return 0; + } + ++#ifdef CONFIG_PM_SLEEP ++static int pixcir_i2c_ts_suspend(struct device *dev) ++{ ++ struct i2c_client *client = to_i2c_client(dev); ++ struct pixcir_i2c_ts_data *ts = i2c_get_clientdata(client); ++ struct input_dev *input = ts->input; ++ int ret = 0; ++ ++ mutex_lock(&input->mutex); ++ ++ if (device_may_wakeup(&client->dev)) { ++ /* need to start device if not open, to be wakeup source */ ++ if (!input->users) { ++ ret = pixcir_start(ts); ++ if (ret) ++ goto unlock; ++ } ++ ++ enable_irq_wake(client->irq); ++ ++ } else if (input->users) { ++ ret = pixcir_stop(ts); ++ } ++ ++unlock: ++ mutex_unlock(&input->mutex); ++ ++ return ret; ++} ++ ++static int pixcir_i2c_ts_resume(struct device *dev) ++{ ++ struct i2c_client *client = to_i2c_client(dev); ++ struct pixcir_i2c_ts_data *ts = i2c_get_clientdata(client); ++ struct input_dev *input = ts->input; ++ int ret = 0; ++ ++ mutex_lock(&input->mutex); ++ ++ if (device_may_wakeup(&client->dev)) { ++ disable_irq_wake(client->irq); ++ ++ /* need to stop device if it was not open on suspend */ ++ if (!input->users) { ++ ret = pixcir_stop(ts); ++ if (ret) ++ goto unlock; ++ } ++ ++ } else if (input->users) { ++ ret = pixcir_start(ts); ++ } ++ ++unlock: ++ mutex_unlock(&input->mutex); ++ ++ return ret; ++} ++#endif ++ ++static SIMPLE_DEV_PM_OPS(pixcir_dev_pm_ops, ++ pixcir_i2c_ts_suspend, pixcir_i2c_ts_resume); ++ + static const struct i2c_device_id pixcir_i2c_ts_id[] = { + { "pixcir_ts", 0 }, ++ { "pixcir_tangoc", 0}, + { } + }; + MODULE_DEVICE_TABLE(i2c, pixcir_i2c_ts_id); + ++#if defined(CONFIG_OF) ++static const struct pixcir_i2c_chip_data tangoc_data = { ++ .num_report_ids = 5, ++}; ++ ++static const struct of_device_id pixcir_of_match[] = { ++ { .compatible = "pixcir,pixcir_ts", }, ++ { .compatible = "pixcir,pixcir_tangoc", .data = &tangoc_data, }, ++ { } ++}; ++MODULE_DEVICE_TABLE(of, pixcir_of_match); ++#endif ++ + static struct i2c_driver pixcir_i2c_ts_driver = { + .driver = { + .owner = THIS_MODULE, + .name = "pixcir_ts", + .pm = &pixcir_dev_pm_ops, ++ .of_match_table = of_match_ptr(pixcir_of_match), + }, + .probe = pixcir_i2c_ts_probe, + .remove = pixcir_i2c_ts_remove, +--- a/drivers/input/touchscreen/ti_am335x_tsc.c ++++ b/drivers/input/touchscreen/ti_am335x_tsc.c +@@ -348,9 +348,16 @@ static int titsc_parse_dt(struct platfor + if (err < 0) + return err; + +- err = of_property_read_u32(node, "ti,coordiante-readouts", ++ /* ++ * try with new binding first. If it fails, still try with ++ * bogus, miss-spelled version. ++ */ ++ err = of_property_read_u32(node, "ti,coordinate-readouts", + &ts_dev->coordinate_readouts); + if (err < 0) ++ err = of_property_read_u32(node, "ti,coordiante-readouts", ++ &ts_dev->coordinate_readouts); ++ if (err < 0) + return err; + + return of_property_read_u32_array(node, "ti,wire-config", +--- a/drivers/Kconfig ++++ b/drivers/Kconfig +@@ -166,4 +166,6 @@ source "drivers/reset/Kconfig" + + source "drivers/fmc/Kconfig" + ++source "drivers/phy/Kconfig" ++ + endmenu +--- a/drivers/mailbox/mailbox-omap1.c ++++ b/drivers/mailbox/mailbox-omap1.c +@@ -13,6 +13,7 @@ + #include <linux/interrupt.h> + #include <linux/platform_device.h> + #include <linux/io.h> ++#include <linux/delay.h> + + #include "omap-mbox.h" + +@@ -26,7 +27,7 @@ + #define MAILBOX_DSP2ARM1_Flag 0x1c + #define MAILBOX_DSP2ARM2_Flag 0x20 + +-static void __iomem *mbox_base; ++static struct omap_mbox_device omap1_mbox_device; + + struct omap_mbox1_fifo { + unsigned long cmd; +@@ -37,16 +38,17 @@ struct omap_mbox1_fifo { + struct omap_mbox1_priv { + struct omap_mbox1_fifo tx_fifo; + struct omap_mbox1_fifo rx_fifo; ++ bool empty_flag; + }; + + static inline int mbox_read_reg(size_t ofs) + { +- return __raw_readw(mbox_base + ofs); ++ return __raw_readw(omap1_mbox_device.mbox_base + ofs); + } + + static inline void mbox_write_reg(u32 val, size_t ofs) + { +- __raw_writew(val, mbox_base + ofs); ++ __raw_writew(val, omap1_mbox_device.mbox_base + ofs); + } + + /* msg */ +@@ -59,6 +61,7 @@ static mbox_msg_t omap1_mbox_fifo_read(s + msg = mbox_read_reg(fifo->data); + msg |= ((mbox_msg_t) mbox_read_reg(fifo->cmd)) << 16; + ++ (struct omap_mbox1_priv *)(mbox->priv)->empty_flag = false; + return msg; + } + +@@ -74,7 +77,9 @@ omap1_mbox_fifo_write(struct omap_mbox * + + static int omap1_mbox_fifo_empty(struct omap_mbox *mbox) + { +- return 0; ++ struct omap_mbox1_priv *priv = (struct omap_mbox1_priv *)mbox->priv; ++ ++ return priv->empty_flag ? 0 : 1; + } + + static int omap1_mbox_fifo_full(struct omap_mbox *mbox) +@@ -85,6 +90,18 @@ static int omap1_mbox_fifo_full(struct o + return mbox_read_reg(fifo->flag); + } + ++static int omap1_mbox_poll_for_space(struct omap_mbox *mbox) ++{ ++ int i = 1000; ++ ++ while (omap1_mbox_fifo_full(mbox)) { ++ if (--i == 0) ++ return -1; ++ udelay(1); ++ } ++ return 0; ++} ++ + /* irq */ + static void + omap1_mbox_enable_irq(struct omap_mbox *mbox, omap_mbox_irq_t irq) +@@ -103,17 +120,21 @@ omap1_mbox_disable_irq(struct omap_mbox + static int + omap1_mbox_is_irq(struct omap_mbox *mbox, omap_mbox_irq_t irq) + { ++ struct omap_mbox1_priv *priv = (struct omap_mbox1_priv *)mbox->priv; ++ + if (irq == IRQ_TX) + return 0; ++ if (irq == IRQ_RX) ++ priv->empty_flag = true; ++ + return 1; + } + + static struct omap_mbox_ops omap1_mbox_ops = { +- .type = OMAP_MBOX_TYPE1, + .fifo_read = omap1_mbox_fifo_read, + .fifo_write = omap1_mbox_fifo_write, + .fifo_empty = omap1_mbox_fifo_empty, +- .fifo_full = omap1_mbox_fifo_full, ++ .poll_for_space = omap1_mbox_poll_for_space, + .enable_irq = omap1_mbox_enable_irq, + .disable_irq = omap1_mbox_disable_irq, + .is_irq = omap1_mbox_is_irq, +@@ -139,6 +160,7 @@ static struct omap_mbox mbox_dsp_info = + .name = "dsp", + .ops = &omap1_mbox_ops, + .priv = &omap1_mbox_dsp_priv, ++ .parent = &omap1_mbox_device, + }; + + static struct omap_mbox *omap1_mboxes[] = { &mbox_dsp_info, NULL }; +@@ -148,6 +170,7 @@ static int omap1_mbox_probe(struct platf + struct resource *mem; + int ret; + struct omap_mbox **list; ++ struct omap_mbox_device *mdev = &omap1_mbox_device; + + list = omap1_mboxes; + list[0]->irq = platform_get_irq_byname(pdev, "dsp"); +@@ -156,13 +179,18 @@ static int omap1_mbox_probe(struct platf + if (!mem) + return -ENOENT; + +- mbox_base = ioremap(mem->start, resource_size(mem)); +- if (!mbox_base) ++ mdev->mbox_base = ioremap(mem->start, resource_size(mem)); ++ if (!mdev->mbox_base) + return -ENOMEM; ++ mutex_init(&mdev->cfg_lock); ++ mdev->dev = &pdev->dev; ++ mdev->mboxes = omap1_mboxes; ++ mdev->num_users = 2; ++ mdev->num_fifos = 4; + +- ret = omap_mbox_register(&pdev->dev, list); ++ ret = omap_mbox_register(mdev); + if (ret) { +- iounmap(mbox_base); ++ iounmap(mdev->mbox_base); + return ret; + } + +@@ -171,8 +199,14 @@ static int omap1_mbox_probe(struct platf + + static int omap1_mbox_remove(struct platform_device *pdev) + { +- omap_mbox_unregister(); +- iounmap(mbox_base); ++ struct omap_mbox_device *mdev = &omap1_mbox_device; ++ ++ omap_mbox_unregister(mdev); ++ iounmap(mdev->mbox_base); ++ mdev->mbox_base = NULL; ++ mdev->mboxes = NULL; ++ mdev->dev = NULL; ++ + return 0; + } + +--- a/drivers/mailbox/mailbox-omap2.c ++++ b/drivers/mailbox/mailbox-omap2.c +@@ -14,6 +14,7 @@ + #include <linux/slab.h> + #include <linux/clk.h> + #include <linux/err.h> ++#include <linux/of_device.h> + #include <linux/platform_device.h> + #include <linux/io.h> + #include <linux/pm_runtime.h> +@@ -35,6 +36,8 @@ + #define MAILBOX_IRQ_NEWMSG(m) (1 << (2 * (m))) + #define MAILBOX_IRQ_NOTFULL(m) (1 << (2 * (m) + 1)) + ++#define AM33X_MBOX_WKUPM3_USR 3 ++ + #define MBOX_REG_SIZE 0x120 + + #define OMAP4_MBOX_REG_SIZE 0x130 +@@ -42,8 +45,6 @@ + #define MBOX_NR_REGS (MBOX_REG_SIZE / sizeof(u32)) + #define OMAP4_MBOX_NR_REGS (OMAP4_MBOX_REG_SIZE / sizeof(u32)) + +-static void __iomem *mbox_base; +- + struct omap_mbox2_fifo { + unsigned long msg; + unsigned long fifo_stat; +@@ -62,34 +63,38 @@ struct omap_mbox2_priv { + u32 intr_type; + }; + +-static inline unsigned int mbox_read_reg(size_t ofs) ++static inline ++unsigned int mbox_read_reg(struct omap_mbox_device *mdev, size_t ofs) + { +- return __raw_readl(mbox_base + ofs); ++ return __raw_readl(mdev->mbox_base + ofs); + } + +-static inline void mbox_write_reg(u32 val, size_t ofs) ++static inline ++void mbox_write_reg(struct omap_mbox_device *mdev, u32 val, size_t ofs) + { +- __raw_writel(val, mbox_base + ofs); ++ __raw_writel(val, mdev->mbox_base + ofs); + } + + /* Mailbox H/W preparations */ + static int omap2_mbox_startup(struct omap_mbox *mbox) + { +- u32 l; +- +- pm_runtime_enable(mbox->dev->parent); +- pm_runtime_get_sync(mbox->dev->parent); ++ pm_runtime_get_sync(mbox->parent->dev); + +- l = mbox_read_reg(MAILBOX_REVISION); +- pr_debug("omap mailbox rev %d.%d\n", (l & 0xf0) >> 4, (l & 0x0f)); ++ /* ++ * just print the raw revision register, the format is not ++ * uniform across all SoCs ++ */ ++ if (!mbox->use_count) { ++ u32 l = mbox_read_reg(mbox->parent, MAILBOX_REVISION); ++ pr_debug("omap mailbox rev 0x%x\n", l); ++ } + + return 0; + } + + static void omap2_mbox_shutdown(struct omap_mbox *mbox) + { +- pm_runtime_put_sync(mbox->dev->parent); +- pm_runtime_disable(mbox->dev->parent); ++ pm_runtime_put_sync(mbox->parent->dev); + } + + /* Mailbox FIFO handle functions */ +@@ -97,28 +102,36 @@ static mbox_msg_t omap2_mbox_fifo_read(s + { + struct omap_mbox2_fifo *fifo = + &((struct omap_mbox2_priv *)mbox->priv)->rx_fifo; +- return (mbox_msg_t) mbox_read_reg(fifo->msg); ++ return (mbox_msg_t) mbox_read_reg(mbox->parent, fifo->msg); + } + + static void omap2_mbox_fifo_write(struct omap_mbox *mbox, mbox_msg_t msg) + { + struct omap_mbox2_fifo *fifo = + &((struct omap_mbox2_priv *)mbox->priv)->tx_fifo; +- mbox_write_reg(msg, fifo->msg); ++ mbox_write_reg(mbox->parent, msg, fifo->msg); + } + + static int omap2_mbox_fifo_empty(struct omap_mbox *mbox) + { + struct omap_mbox2_fifo *fifo = + &((struct omap_mbox2_priv *)mbox->priv)->rx_fifo; +- return (mbox_read_reg(fifo->msg_stat) == 0); ++ return (mbox_read_reg(mbox->parent, fifo->msg_stat) == 0); + } + + static int omap2_mbox_fifo_full(struct omap_mbox *mbox) + { + struct omap_mbox2_fifo *fifo = + &((struct omap_mbox2_priv *)mbox->priv)->tx_fifo; +- return mbox_read_reg(fifo->fifo_stat); ++ return mbox_read_reg(mbox->parent, fifo->fifo_stat); ++} ++ ++static int omap2_mbox_poll_for_space(struct omap_mbox *mbox) ++{ ++ if (omap2_mbox_fifo_full(mbox)) ++ return -1; ++ ++ return 0; + } + + /* Mailbox IRQ handle functions */ +@@ -127,9 +140,9 @@ static void omap2_mbox_enable_irq(struct + struct omap_mbox2_priv *p = mbox->priv; + u32 l, bit = (irq == IRQ_TX) ? p->notfull_bit : p->newmsg_bit; + +- l = mbox_read_reg(p->irqenable); ++ l = mbox_read_reg(mbox->parent, p->irqenable); + l |= bit; +- mbox_write_reg(l, p->irqenable); ++ mbox_write_reg(mbox->parent, l, p->irqenable); + } + + static void omap2_mbox_disable_irq(struct omap_mbox *mbox, omap_mbox_irq_t irq) +@@ -142,9 +155,9 @@ static void omap2_mbox_disable_irq(struc + * OMAP4 and later SoCs have a dedicated interrupt disabling register. + */ + if (!p->intr_type) +- bit = mbox_read_reg(p->irqdisable) & ~bit; ++ bit = mbox_read_reg(mbox->parent, p->irqdisable) & ~bit; + +- mbox_write_reg(bit, p->irqdisable); ++ mbox_write_reg(mbox->parent, bit, p->irqdisable); + } + + static void omap2_mbox_ack_irq(struct omap_mbox *mbox, omap_mbox_irq_t irq) +@@ -152,18 +165,69 @@ static void omap2_mbox_ack_irq(struct om + struct omap_mbox2_priv *p = mbox->priv; + u32 bit = (irq == IRQ_TX) ? p->notfull_bit : p->newmsg_bit; + +- mbox_write_reg(bit, p->irqstatus); ++ mbox_write_reg(mbox->parent, bit, p->irqstatus); + + /* Flush posted write for irq status to avoid spurious interrupts */ +- mbox_read_reg(p->irqstatus); ++ mbox_read_reg(mbox->parent, p->irqstatus); + } + + static int omap2_mbox_is_irq(struct omap_mbox *mbox, omap_mbox_irq_t irq) + { + struct omap_mbox2_priv *p = mbox->priv; + u32 bit = (irq == IRQ_TX) ? p->notfull_bit : p->newmsg_bit; +- u32 enable = mbox_read_reg(p->irqenable); +- u32 status = mbox_read_reg(p->irqstatus); ++ u32 enable = mbox_read_reg(mbox->parent, p->irqenable); ++ u32 status = mbox_read_reg(mbox->parent, p->irqstatus); ++ ++ return (int)(enable & status & bit); ++} ++ ++static void wkupm3_mbox_enable_irq(struct omap_mbox *mbox, omap_mbox_irq_t irq) ++{ ++ struct omap_mbox2_priv *p = mbox->priv; ++ u32 l, bit = (irq == IRQ_TX) ? p->notfull_bit : p->newmsg_bit; ++ unsigned long irqenable = ((irq == IRQ_RX) ? ++ OMAP4_MAILBOX_IRQENABLE(AM33X_MBOX_WKUPM3_USR) : p->irqenable); ++ ++ l = mbox_read_reg(mbox->parent, irqenable); ++ l |= bit; ++ mbox_write_reg(mbox->parent, l, irqenable); ++} ++ ++static void wkupm3_mbox_disable_irq(struct omap_mbox *mbox, omap_mbox_irq_t irq) ++{ ++ struct omap_mbox2_priv *p = mbox->priv; ++ u32 bit = (irq == IRQ_TX) ? p->notfull_bit : p->newmsg_bit; ++ unsigned long irqdisable = ((irq == IRQ_RX) ? ++ OMAP4_MAILBOX_IRQENABLE_CLR(AM33X_MBOX_WKUPM3_USR) : p->irqdisable); ++ ++ mbox_write_reg(mbox->parent, bit, irqdisable); ++} ++ ++static void wkupm3_mbox_ack_irq(struct omap_mbox *mbox, omap_mbox_irq_t irq) ++{ ++ struct omap_mbox2_priv *p = mbox->priv; ++ u32 bit = (irq == IRQ_TX) ? p->notfull_bit : p->newmsg_bit; ++ unsigned long irqstatus = ((irq == IRQ_RX) ? ++ OMAP4_MAILBOX_IRQSTATUS(AM33X_MBOX_WKUPM3_USR) : p->irqstatus); ++ ++ mbox_write_reg(mbox->parent, bit, irqstatus); ++ ++ /* Flush posted write for irq status to avoid spurious interrupts */ ++ mbox_read_reg(mbox->parent, irqstatus); ++} ++ ++static int wkupm3_mbox_is_irq(struct omap_mbox *mbox, omap_mbox_irq_t irq) ++{ ++ struct omap_mbox2_priv *p = mbox->priv; ++ u32 bit = (irq == IRQ_TX) ? p->notfull_bit : p->newmsg_bit; ++ u32 enable, status; ++ ++ /* WkupM3 mailbox does not use a receive queue */ ++ if (irq == IRQ_RX) ++ return 0; ++ ++ enable = mbox_read_reg(mbox->parent, p->irqenable); ++ status = mbox_read_reg(mbox->parent, p->irqstatus); + + return (int)(enable & status & bit); + } +@@ -179,7 +243,7 @@ static void omap2_mbox_save_ctx(struct o + else + nr_regs = MBOX_NR_REGS; + for (i = 0; i < nr_regs; i++) { +- p->ctx[i] = mbox_read_reg(i * sizeof(u32)); ++ p->ctx[i] = mbox_read_reg(mbox->parent, i * sizeof(u32)); + + dev_dbg(mbox->dev, "%s: [%02x] %08x\n", __func__, + i, p->ctx[i]); +@@ -197,21 +261,34 @@ static void omap2_mbox_restore_ctx(struc + else + nr_regs = MBOX_NR_REGS; + for (i = 0; i < nr_regs; i++) { +- mbox_write_reg(p->ctx[i], i * sizeof(u32)); ++ mbox_write_reg(mbox->parent, p->ctx[i], i * sizeof(u32)); + + dev_dbg(mbox->dev, "%s: [%02x] %08x\n", __func__, + i, p->ctx[i]); + } + } + ++static void wkupm3_mbox_send_data(struct omap_mbox *mbox, mbox_msg_t msg) ++{ ++ mbox_msg_t rmsg; ++ ++ /* enable the mbox Rx interrupt for WkupM3 only briefly */ ++ wkupm3_mbox_enable_irq(mbox, IRQ_RX); ++ omap2_mbox_fifo_write(mbox, msg); ++ wkupm3_mbox_disable_irq(mbox, IRQ_RX); ++ ++ /* read back the message and ack the interrupt on behalf of WkupM3 */ ++ rmsg = omap2_mbox_fifo_read(mbox); ++ wkupm3_mbox_ack_irq(mbox, IRQ_RX); ++} ++ + static struct omap_mbox_ops omap2_mbox_ops = { +- .type = OMAP_MBOX_TYPE2, + .startup = omap2_mbox_startup, + .shutdown = omap2_mbox_shutdown, + .fifo_read = omap2_mbox_fifo_read, + .fifo_write = omap2_mbox_fifo_write, + .fifo_empty = omap2_mbox_fifo_empty, +- .fifo_full = omap2_mbox_fifo_full, ++ .poll_for_space = omap2_mbox_poll_for_space, + .enable_irq = omap2_mbox_enable_irq, + .disable_irq = omap2_mbox_disable_irq, + .ack_irq = omap2_mbox_ack_irq, +@@ -220,6 +297,36 @@ static struct omap_mbox_ops omap2_mbox_o + .restore_ctx = omap2_mbox_restore_ctx, + }; + ++static struct omap_mbox_ops wkupm3_mbox_ops = { ++ .startup = omap2_mbox_startup, ++ .shutdown = omap2_mbox_shutdown, ++ .fifo_read = omap2_mbox_fifo_read, ++ .fifo_write = wkupm3_mbox_send_data, ++ .fifo_empty = omap2_mbox_fifo_empty, ++ .poll_for_space = omap2_mbox_poll_for_space, ++ .enable_irq = wkupm3_mbox_enable_irq, ++ .disable_irq = wkupm3_mbox_disable_irq, ++ .ack_irq = wkupm3_mbox_ack_irq, ++ .is_irq = wkupm3_mbox_is_irq, ++ .save_ctx = omap2_mbox_save_ctx, ++ .restore_ctx = omap2_mbox_restore_ctx, ++}; ++ ++static const struct of_device_id omap_mailbox_of_match[] = { ++ { ++ .compatible = "ti,omap2-mailbox", ++ .data = (void *) MBOX_INTR_CFG_TYPE1, ++ }, ++ { ++ .compatible = "ti,omap4-mailbox", ++ .data = (void *) MBOX_INTR_CFG_TYPE2, ++ }, ++ { ++ /* end */ ++ }, ++}; ++MODULE_DEVICE_TABLE(of, omap_mailbox_of_match); ++ + static int omap2_mbox_probe(struct platform_device *pdev) + { + struct resource *mem; +@@ -227,40 +334,127 @@ static int omap2_mbox_probe(struct platf + struct omap_mbox **list, *mbox, *mboxblk; + struct omap_mbox2_priv *priv, *privblk; + struct omap_mbox_pdata *pdata = pdev->dev.platform_data; +- struct omap_mbox_dev_info *info; +- int i; ++ struct omap_mbox_device *mdev; ++ struct omap_mbox_dev_info *info, *of_info = NULL; ++ struct device_node *node = pdev->dev.of_node; ++ int i, j; ++ u32 info_count = 0, intr_type = 0; ++ u32 num_users = 0, num_fifos = 0; ++ u32 dlen, dsize = 4; ++ u32 *tmp; ++ const __be32 *mbox_data; + +- if (!pdata || !pdata->info_cnt || !pdata->info) { ++ if (!node && (!pdata || !pdata->info_cnt || !pdata->info)) { + pr_err("%s: platform not supported\n", __func__); + return -ENODEV; + } + ++ if (node) { ++ intr_type = (u32)of_match_device(omap_mailbox_of_match, ++ &pdev->dev)->data; ++ if (intr_type != 0 && intr_type != 1) { ++ dev_err(&pdev->dev, "invalid match data value\n"); ++ return -EINVAL; ++ } ++ ++ if (of_property_read_u32(node, "ti,mbox-num-users", ++ &num_users)) { ++ dev_err(&pdev->dev, ++ "no ti,mbox-num-users configuration found\n"); ++ return -ENODEV; ++ } ++ ++ if (of_property_read_u32(node, "ti,mbox-num-fifos", ++ &num_fifos)) { ++ dev_err(&pdev->dev, ++ "no ti,mbox-num-fifos configuration found\n"); ++ return -ENODEV; ++ } ++ ++ info_count = of_property_count_strings(node, "ti,mbox-names"); ++ if (!info_count) { ++ dev_err(&pdev->dev, "no mbox devices found\n"); ++ return -ENODEV; ++ } ++ ++ mbox_data = of_get_property(node, "ti,mbox-data", &dlen); ++ if (!mbox_data) { ++ dev_err(&pdev->dev, "no mbox device data found\n"); ++ return -ENODEV; ++ } ++ dlen /= sizeof(dsize); ++ if (dlen != dsize * info_count) { ++ dev_err(&pdev->dev, "mbox device data is truncated\n"); ++ return -ENODEV; ++ } ++ ++ of_info = kzalloc(info_count * sizeof(*of_info), GFP_KERNEL); ++ if (!of_info) ++ return -ENOMEM; ++ ++ i = 0; ++ while (i < info_count) { ++ info = of_info + i; ++ if (of_property_read_string_index(node, ++ "ti,mbox-names", i, &info->name)) { ++ dev_err(&pdev->dev, ++ "mbox_name [%d] read failed\n", i); ++ ret = -ENODEV; ++ goto free_of; ++ } ++ ++ tmp = &info->tx_id; ++ for (j = 0; j < dsize; j++) { ++ tmp[j] = of_read_number( ++ mbox_data + j + (i * dsize), 1); ++ } ++ i++; ++ } ++ } ++ ++ if (!node) { /* non-DT device creation */ ++ info_count = pdata->info_cnt; ++ info = pdata->info; ++ intr_type = pdata->intr_type; ++ num_users = pdata->num_users; ++ num_fifos = pdata->num_fifos; ++ } else { ++ info = of_info; ++ } ++ ++ mdev = kzalloc(sizeof(*mdev), GFP_KERNEL); ++ if (!mdev) { ++ ret = -ENOMEM; ++ goto free_of; ++ } ++ + /* allocate one extra for marking end of list */ +- list = kzalloc((pdata->info_cnt + 1) * sizeof(*list), GFP_KERNEL); +- if (!list) +- return -ENOMEM; ++ list = kzalloc((info_count + 1) * sizeof(*list), GFP_KERNEL); ++ if (!list) { ++ ret = -ENOMEM; ++ goto free_mdev; ++ } + +- mboxblk = mbox = kzalloc(pdata->info_cnt * sizeof(*mbox), GFP_KERNEL); ++ mboxblk = mbox = kzalloc(info_count * sizeof(*mbox), GFP_KERNEL); + if (!mboxblk) { + ret = -ENOMEM; + goto free_list; + } + +- privblk = priv = kzalloc(pdata->info_cnt * sizeof(*priv), GFP_KERNEL); ++ privblk = priv = kzalloc(info_count * sizeof(*priv), GFP_KERNEL); + if (!privblk) { + ret = -ENOMEM; + goto free_mboxblk; + } + +- info = pdata->info; +- for (i = 0; i < pdata->info_cnt; i++, info++, priv++) { ++ for (i = 0; i < info_count; i++, info++, priv++) { + priv->tx_fifo.msg = MAILBOX_MESSAGE(info->tx_id); + priv->tx_fifo.fifo_stat = MAILBOX_FIFOSTATUS(info->tx_id); + priv->rx_fifo.msg = MAILBOX_MESSAGE(info->rx_id); + priv->rx_fifo.msg_stat = MAILBOX_MSGSTATUS(info->rx_id); + priv->notfull_bit = MAILBOX_IRQ_NOTFULL(info->tx_id); + priv->newmsg_bit = MAILBOX_IRQ_NEWMSG(info->rx_id); +- if (pdata->intr_type) { ++ if (intr_type) { + priv->irqenable = OMAP4_MAILBOX_IRQENABLE(info->usr_id); + priv->irqstatus = OMAP4_MAILBOX_IRQSTATUS(info->usr_id); + priv->irqdisable = +@@ -270,11 +464,15 @@ static int omap2_mbox_probe(struct platf + priv->irqstatus = MAILBOX_IRQSTATUS(info->usr_id); + priv->irqdisable = MAILBOX_IRQENABLE(info->usr_id); + } +- priv->intr_type = pdata->intr_type; ++ priv->intr_type = intr_type; + + mbox->priv = priv; ++ mbox->parent = mdev; + mbox->name = info->name; +- mbox->ops = &omap2_mbox_ops; ++ if (!strcmp(mbox->name, "wkup_m3")) ++ mbox->ops = &wkupm3_mbox_ops; ++ else ++ mbox->ops = &omap2_mbox_ops; + mbox->irq = platform_get_irq(pdev, info->irq_id); + if (mbox->irq < 0) { + ret = mbox->irq; +@@ -289,42 +487,58 @@ static int omap2_mbox_probe(struct platf + goto free_privblk; + } + +- mbox_base = ioremap(mem->start, resource_size(mem)); +- if (!mbox_base) { ++ mdev->mbox_base = ioremap(mem->start, resource_size(mem)); ++ if (!mdev->mbox_base) { + ret = -ENOMEM; + goto free_privblk; + } + +- ret = omap_mbox_register(&pdev->dev, list); ++ mutex_init(&mdev->cfg_lock); ++ mdev->dev = &pdev->dev; ++ mdev->num_users = num_users; ++ mdev->num_fifos = num_fifos; ++ mdev->mboxes = list; ++ ret = omap_mbox_register(mdev); + if (ret) + goto unmap_mbox; +- platform_set_drvdata(pdev, list); ++ platform_set_drvdata(pdev, mdev); + ++ pm_runtime_enable(mdev->dev); ++ ++ kfree(of_info); + return 0; + + unmap_mbox: +- iounmap(mbox_base); ++ iounmap(mdev->mbox_base); + free_privblk: + kfree(privblk); + free_mboxblk: + kfree(mboxblk); + free_list: + kfree(list); ++free_mdev: ++ kfree(mdev); ++free_of: ++ kfree(of_info); + return ret; + } + + static int omap2_mbox_remove(struct platform_device *pdev) + { + struct omap_mbox2_priv *privblk; +- struct omap_mbox **list = platform_get_drvdata(pdev); ++ struct omap_mbox_device *mdev = platform_get_drvdata(pdev); ++ struct omap_mbox **list = mdev->mboxes; + struct omap_mbox *mboxblk = list[0]; + ++ pm_runtime_disable(mdev->dev); ++ + privblk = mboxblk->priv; +- omap_mbox_unregister(); +- iounmap(mbox_base); ++ omap_mbox_unregister(mdev); ++ iounmap(mdev->mbox_base); + kfree(privblk); + kfree(mboxblk); + kfree(list); ++ kfree(mdev); + + return 0; + } +@@ -334,6 +548,7 @@ static struct platform_driver omap2_mbox + .remove = omap2_mbox_remove, + .driver = { + .name = "omap-mailbox", ++ .of_match_table = omap_mailbox_of_match, + }, + }; + +--- a/drivers/mailbox/omap-mailbox.c ++++ b/drivers/mailbox/omap-mailbox.c +@@ -24,7 +24,6 @@ + #include <linux/interrupt.h> + #include <linux/spinlock.h> + #include <linux/mutex.h> +-#include <linux/delay.h> + #include <linux/slab.h> + #include <linux/kfifo.h> + #include <linux/err.h> +@@ -33,16 +32,16 @@ + + #include "omap-mbox.h" + +-static struct omap_mbox **mboxes; +- +-static int mbox_configured; +-static DEFINE_MUTEX(mbox_configured_lock); ++/* global variables for the mailbox devices */ ++static DEFINE_MUTEX(omap_mbox_devices_lock); ++static LIST_HEAD(omap_mbox_devices); + ++/* default size for the fifos, configured through kernel menuconfig */ + static unsigned int mbox_kfifo_size = CONFIG_OMAP_MBOX_KFIFO_SIZE; + module_param(mbox_kfifo_size, uint, S_IRUGO); + MODULE_PARM_DESC(mbox_kfifo_size, "Size of omap's mailbox kfifo (bytes)"); + +-/* Mailbox FIFO handle functions */ ++/* mailbox h/w transport communication handler helper functions */ + static inline mbox_msg_t mbox_fifo_read(struct omap_mbox *mbox) + { + return mbox->ops->fifo_read(mbox); +@@ -55,12 +54,16 @@ static inline int mbox_fifo_empty(struct + { + return mbox->ops->fifo_empty(mbox); + } +-static inline int mbox_fifo_full(struct omap_mbox *mbox) ++/* ++ * local helper to check if the h/w transport is busy or free. ++ * Returns 0 if free, and non-zero otherwise ++ */ ++static inline int mbox_poll_for_space(struct omap_mbox *mbox) + { +- return mbox->ops->fifo_full(mbox); ++ return mbox->ops->poll_for_space(mbox); + } + +-/* Mailbox IRQ handle functions */ ++/* mailbox h/w irq handler helper functions */ + static inline void ack_mbox_irq(struct omap_mbox *mbox, omap_mbox_irq_t irq) + { + if (mbox->ops->ack_irq) +@@ -71,23 +74,21 @@ static inline int is_mbox_irq(struct oma + return mbox->ops->is_irq(mbox, irq); + } + +-/* +- * message sender ++/** ++ * omap_mbox_msg_send() - send a mailbox message ++ * @mbox: handle to the acquired mailbox on which to send the message ++ * @msg: the mailbox message to be sent ++ * ++ * This API is called by a client user to send a mailbox message on an ++ * acquired mailbox. The API transmits the message immediately on the h/w ++ * communication transport if it is available, otherwise buffers the ++ * message for transmission as soon as the h/w transport is ready. ++ * ++ * The only failure from this function is when neither the h/w transport ++ * is available nor the s/w buffer fifo is empty. ++ * ++ * Returns 0 on success, or an error otherwise + */ +-static int __mbox_poll_for_space(struct omap_mbox *mbox) +-{ +- int ret = 0, i = 1000; +- +- while (mbox_fifo_full(mbox)) { +- if (mbox->ops->type == OMAP_MBOX_TYPE2) +- return -1; +- if (--i == 0) +- return -1; +- udelay(1); +- } +- return ret; +-} +- + int omap_mbox_msg_send(struct omap_mbox *mbox, mbox_msg_t msg) + { + struct omap_mbox_queue *mq = mbox->txq; +@@ -100,7 +101,7 @@ int omap_mbox_msg_send(struct omap_mbox + goto out; + } + +- if (kfifo_is_empty(&mq->fifo) && !__mbox_poll_for_space(mbox)) { ++ if (kfifo_is_empty(&mq->fifo) && !mbox_poll_for_space(mbox)) { + mbox_fifo_write(mbox, msg); + goto out; + } +@@ -116,6 +117,17 @@ out: + } + EXPORT_SYMBOL(omap_mbox_msg_send); + ++/** ++ * omap_mbox_save_ctx: save the context of a mailbox ++ * @mbox: handle to the acquired mailbox ++ * ++ * This allows a client (controlling a remote) to request a mailbox to ++ * save its context when it is powering down the remote. ++ * ++ * NOTE: This will be eventually deprecated, new clients should not use this. ++ * The same feature can be enabled through runtime_pm enablement of ++ * mailbox. ++ */ + void omap_mbox_save_ctx(struct omap_mbox *mbox) + { + if (!mbox->ops->save_ctx) { +@@ -127,6 +139,18 @@ void omap_mbox_save_ctx(struct omap_mbox + } + EXPORT_SYMBOL(omap_mbox_save_ctx); + ++/** ++ * omap_mbox_restore_ctx: restore the context of a mailbox ++ * @mbox: handle to the acquired mailbox ++ * ++ * This allows a client (controlling a remote) to request a mailbox to ++ * restore its context after restoring the remote, so that it can ++ * communicate with the remote as it would normally. ++ * ++ * NOTE: This will be deprecated, new clients should not use this. ++ * The same feature can be enabled through runtime_pm enablement ++ * of mailbox. ++ */ + void omap_mbox_restore_ctx(struct omap_mbox *mbox) + { + if (!mbox->ops->restore_ctx) { +@@ -138,18 +162,48 @@ void omap_mbox_restore_ctx(struct omap_m + } + EXPORT_SYMBOL(omap_mbox_restore_ctx); + ++/** ++ * omap_mbox_enable_irq: enable a specific mailbox Rx or Tx interrupt source ++ * @mbox: handle to the acquired mailbox ++ * @irq: interrupt type associated with either the Rx or Tx ++ * ++ * This allows a client (having its own shared memory communication protocol ++ * with the remote) to request a mailbox to enable a particular interrupt ++ * signal source of the mailbox, as part of its communication state machine. ++ * ++ * NOTE: This will be deprecated, new clients should not use this. It is ++ * being exported for TI DSP/Bridge driver. ++ */ + void omap_mbox_enable_irq(struct omap_mbox *mbox, omap_mbox_irq_t irq) + { + mbox->ops->enable_irq(mbox, irq); + } + EXPORT_SYMBOL(omap_mbox_enable_irq); + ++/** ++ * omap_mbox_disable_irq: disable a specific mailbox Rx or Tx interrupt source ++ * @mbox: handle to the acquired mailbox ++ * @irq: interrupt type associated with either the Rx or Tx ++ * ++ * This allows a client (having its own shared memory communication protocal ++ * with the remote) to request a mailbox to disable a particular interrupt ++ * signal source of the mailbox, as part of its communication state machine. ++ * ++ * NOTE: This will be deprecated, new clients should not use this. It is ++ * being exported for TI DSP/Bridge driver. ++ */ + void omap_mbox_disable_irq(struct omap_mbox *mbox, omap_mbox_irq_t irq) + { + mbox->ops->disable_irq(mbox, irq); + } + EXPORT_SYMBOL(omap_mbox_disable_irq); + ++/* ++ * This is the tasklet function in which all the buffered messages are ++ * sent until the h/w transport is busy again. The tasklet is scheduled ++ * upon receiving an interrupt indicating the availability of the h/w ++ * transport. ++ */ + static void mbox_tx_tasklet(unsigned long tx_data) + { + struct omap_mbox *mbox = (struct omap_mbox *)tx_data; +@@ -158,7 +212,7 @@ static void mbox_tx_tasklet(unsigned lon + int ret; + + while (kfifo_len(&mq->fifo)) { +- if (__mbox_poll_for_space(mbox)) { ++ if (mbox_poll_for_space(mbox)) { + omap_mbox_enable_irq(mbox, IRQ_TX); + break; + } +@@ -172,7 +226,12 @@ static void mbox_tx_tasklet(unsigned lon + } + + /* +- * Message receiver(workqueue) ++ * This is the message receiver workqueue function, which is responsible ++ * for delivering all the received messages stored in the receive kfifo ++ * to the clients. Each message is delivered to all the registered mailbox ++ * clients. It also re-enables the receive interrupt on the mailbox (disabled ++ * when the s/w kfifo is full) after emptying atleast a message from the ++ * fifo. + */ + static void mbox_rx_work(struct work_struct *work) + { +@@ -197,7 +256,9 @@ static void mbox_rx_work(struct work_str + } + + /* +- * Mailbox interrupt handler ++ * Interrupt handler for Tx interrupt source for each of the mailboxes. ++ * This schedules the tasklet to transmit the messages buffered in the ++ * Tx fifo. + */ + static void __mbox_tx_interrupt(struct omap_mbox *mbox) + { +@@ -206,6 +267,12 @@ static void __mbox_tx_interrupt(struct o + tasklet_schedule(&mbox->txq->tasklet); + } + ++/* ++ * Interrupt handler for Rx interrupt source for each of the mailboxes. ++ * This performs the read from the h/w mailbox until the transport is ++ * free of any incoming messages, and buffers the read message. The ++ * buffers are delivered to clients by scheduling a work-queue. ++ */ + static void __mbox_rx_interrupt(struct omap_mbox *mbox) + { + struct omap_mbox_queue *mq = mbox->rxq; +@@ -223,9 +290,6 @@ static void __mbox_rx_interrupt(struct o + + len = kfifo_in(&mq->fifo, (unsigned char *)&msg, sizeof(msg)); + WARN_ON(len != sizeof(msg)); +- +- if (mbox->ops->type == OMAP_MBOX_TYPE1) +- break; + } + + /* no more messages in the fifo. clear IRQ source. */ +@@ -234,6 +298,10 @@ nomem: + schedule_work(&mbox->rxq->work); + } + ++/* ++ * The core mailbox interrupt handler function. The interrupt core would ++ * call this for each of the mailboxes the interrupt is configured. ++ */ + static irqreturn_t mbox_interrupt(int irq, void *p) + { + struct omap_mbox *mbox = p; +@@ -247,6 +315,12 @@ static irqreturn_t mbox_interrupt(int ir + return IRQ_HANDLED; + } + ++/* ++ * Helper function to allocate a mailbox queue object. This function ++ * also creates either or both of the work-queue or tasklet to ++ * deal with processing of messages on the kfifo associated with ++ * the mailbox queue object. ++ */ + static struct omap_mbox_queue *mbox_queue_alloc(struct omap_mbox *mbox, + void (*work) (struct work_struct *), + void (*tasklet)(unsigned long)) +@@ -273,24 +347,31 @@ error: + return NULL; + } + ++/* ++ * Helper function to free a mailbox queue object. ++ */ + static void mbox_queue_free(struct omap_mbox_queue *q) + { + kfifo_free(&q->fifo); + kfree(q); + } + ++/* ++ * Helper function to initialize a mailbox. This function creates ++ * the mailbox queue objects associated with the mailbox h/w channel ++ * and plugs-in the interrupt associated with the mailbox, when the ++ * mailbox h/w channel is requested for the first time. ++ */ + static int omap_mbox_startup(struct omap_mbox *mbox) + { + int ret = 0; + struct omap_mbox_queue *mq; ++ struct omap_mbox_device *mdev = mbox->parent; + +- mutex_lock(&mbox_configured_lock); +- if (!mbox_configured++) { +- if (likely(mbox->ops->startup)) { +- ret = mbox->ops->startup(mbox); +- if (unlikely(ret)) +- goto fail_startup; +- } else ++ mutex_lock(&mdev->cfg_lock); ++ if (mbox->ops->startup) { ++ ret = mbox->ops->startup(mbox); ++ if (ret) + goto fail_startup; + } + +@@ -319,7 +400,7 @@ static int omap_mbox_startup(struct omap + + omap_mbox_enable_irq(mbox, IRQ_RX); + } +- mutex_unlock(&mbox_configured_lock); ++ mutex_unlock(&mdev->cfg_lock); + return 0; + + fail_request_irq: +@@ -331,14 +412,18 @@ fail_alloc_txq: + mbox->ops->shutdown(mbox); + mbox->use_count--; + fail_startup: +- mbox_configured--; +- mutex_unlock(&mbox_configured_lock); ++ mutex_unlock(&mdev->cfg_lock); + return ret; + } + ++/* ++ * Helper function to de-initialize a mailbox ++ */ + static void omap_mbox_fini(struct omap_mbox *mbox) + { +- mutex_lock(&mbox_configured_lock); ++ struct omap_mbox_device *mdev = mbox->parent; ++ ++ mutex_lock(&mdev->cfg_lock); + + if (!--mbox->use_count) { + omap_mbox_disable_irq(mbox, IRQ_RX); +@@ -349,28 +434,66 @@ static void omap_mbox_fini(struct omap_m + mbox_queue_free(mbox->rxq); + } + +- if (likely(mbox->ops->shutdown)) { +- if (!--mbox_configured) +- mbox->ops->shutdown(mbox); +- } ++ if (mbox->ops->shutdown) ++ mbox->ops->shutdown(mbox); + +- mutex_unlock(&mbox_configured_lock); ++ mutex_unlock(&mdev->cfg_lock); + } + +-struct omap_mbox *omap_mbox_get(const char *name, struct notifier_block *nb) ++/* ++ * Helper function to find a mailbox. It is currently assumed that all the ++ * mailbox names are unique among all the mailbox devices. This can be ++ * easily extended if only a particular mailbox device is to searched. ++ */ ++static struct omap_mbox *omap_mbox_device_find(struct omap_mbox_device *mdev, ++ const char *mbox_name) + { + struct omap_mbox *_mbox, *mbox = NULL; +- int i, ret; ++ struct omap_mbox **mboxes = mdev->mboxes; ++ int i; + + if (!mboxes) +- return ERR_PTR(-EINVAL); ++ return NULL; + + for (i = 0; (_mbox = mboxes[i]); i++) { +- if (!strcmp(_mbox->name, name)) { ++ if (!strcmp(_mbox->name, mbox_name)) { + mbox = _mbox; + break; + } + } ++ return mbox; ++} ++ ++/** ++ * omap_mbox_get() - acquire a mailbox ++ * @name: name of the mailbox to acquire ++ * @nb: notifier block to be invoked on received messages ++ * ++ * This API is called by a client user to use a mailbox. The returned handle ++ * needs to be used by the client for invoking any other mailbox API. Any ++ * message received on the mailbox is delivered to the client through the ++ * 'nb' notifier. There are currently no restrictions on multiple clients ++ * acquiring the same mailbox - the same message is delivered to each of the ++ * clients through their respective notifiers. ++ * ++ * The function ensures that the mailbox is put into an operational state ++ * before the function returns. ++ * ++ * Returns a usable mailbox handle on success, or NULL otherwise ++ */ ++struct omap_mbox *omap_mbox_get(const char *name, struct notifier_block *nb) ++{ ++ struct omap_mbox *mbox = NULL; ++ struct omap_mbox_device *mdev; ++ int ret; ++ ++ mutex_lock(&omap_mbox_devices_lock); ++ list_for_each_entry(mdev, &omap_mbox_devices, elem) { ++ mbox = omap_mbox_device_find(mdev, name); ++ if (mbox) ++ break; ++ } ++ mutex_unlock(&omap_mbox_devices_lock); + + if (!mbox) + return ERR_PTR(-ENOENT); +@@ -388,6 +511,18 @@ struct omap_mbox *omap_mbox_get(const ch + } + EXPORT_SYMBOL(omap_mbox_get); + ++/** ++ * omap_mbox_put() - release a mailbox ++ * @mbox: handle to the acquired mailbox ++ * @nb: notifier block used while acquiring the mailbox ++ * ++ * This API is to be called by a client user once it is done using the ++ * mailbox. The particular user's notifier function is removed from the ++ * notifier list of received messages on this mailbox. It also undoes ++ * any h/w configuration done during the acquisition of the mailbox. ++ * ++ * No return value ++ */ + void omap_mbox_put(struct omap_mbox *mbox, struct notifier_block *nb) + { + blocking_notifier_chain_unregister(&mbox->notifier, nb); +@@ -397,19 +532,35 @@ EXPORT_SYMBOL(omap_mbox_put); + + static struct class omap_mbox_class = { .name = "mbox", }; + +-int omap_mbox_register(struct device *parent, struct omap_mbox **list) ++/** ++ * omap_mbox_register() - register the list of mailboxes ++ * @mdev: mailbox device handle containing the mailboxes that need to be ++ * with the mailbox core ++ * ++ * This API is to be called by individual mailbox driver implementations ++ * for registering the set of mailboxes contained in a h/w communication ++ * block with the mailbox core. Each of the mailbox represents a h/w ++ * communication channel, contained within the h/w communication block or ip. ++ * ++ * An associated device is also created for each of the mailboxes, and the ++ * mailbox device is added to a global list of registered mailbox devices. ++ * ++ * Return 0 on success, or a failure code otherwise ++ */ ++int omap_mbox_register(struct omap_mbox_device *mdev) + { + int ret; + int i; ++ struct omap_mbox **mboxes; + +- mboxes = list; +- if (!mboxes) ++ if (!mdev || !mdev->mboxes) + return -EINVAL; + ++ mboxes = mdev->mboxes; + for (i = 0; mboxes[i]; i++) { + struct omap_mbox *mbox = mboxes[i]; + mbox->dev = device_create(&omap_mbox_class, +- parent, 0, mbox, "%s", mbox->name); ++ mdev->dev, 0, mbox, "%s", mbox->name); + if (IS_ERR(mbox->dev)) { + ret = PTR_ERR(mbox->dev); + goto err_out; +@@ -417,6 +568,11 @@ int omap_mbox_register(struct device *pa + + BLOCKING_INIT_NOTIFIER_HEAD(&mbox->notifier); + } ++ ++ mutex_lock(&omap_mbox_devices_lock); ++ list_add(&mdev->elem, &omap_mbox_devices); ++ mutex_unlock(&omap_mbox_devices_lock); ++ + return 0; + + err_out: +@@ -426,16 +582,33 @@ err_out: + } + EXPORT_SYMBOL(omap_mbox_register); + +-int omap_mbox_unregister(void) ++/** ++ * omap_mbox_unregister() - unregister the list of mailboxes ++ * @mdev: parent mailbox device handle containing the mailboxes that need ++ * to be unregistered ++ * ++ * This API is to be called by individual mailbox driver implementations ++ * for unregistering the set of mailboxes contained in a h/w communication ++ * block. Once unregistered, these mailboxes are not available for any ++ * client users/drivers. ++ * ++ * Return 0 on success, or a failure code otherwise ++ */ ++int omap_mbox_unregister(struct omap_mbox_device *mdev) + { + int i; ++ struct omap_mbox **mboxes; + +- if (!mboxes) ++ if (!mdev || !mdev->mboxes) + return -EINVAL; + ++ mutex_lock(&omap_mbox_devices_lock); ++ list_del(&mdev->elem); ++ mutex_unlock(&omap_mbox_devices_lock); ++ ++ mboxes = mdev->mboxes; + for (i = 0; mboxes[i]; i++) + device_unregister(mboxes[i]->dev); +- mboxes = NULL; + return 0; + } + EXPORT_SYMBOL(omap_mbox_unregister); +--- a/drivers/mailbox/omap-mbox.h ++++ b/drivers/mailbox/omap-mbox.h +@@ -16,19 +16,58 @@ + #include <linux/workqueue.h> + #include <linux/omap-mailbox.h> + +-typedef int __bitwise omap_mbox_type_t; +-#define OMAP_MBOX_TYPE1 ((__force omap_mbox_type_t) 1) +-#define OMAP_MBOX_TYPE2 ((__force omap_mbox_type_t) 2) +- ++/** ++ * struct omap_mbox_ops - function ops specific to a mailbox implementation ++ * @startup: the startup function, essential for making the mailbox active. ++ * This will be called when a client acquires the mailbox. The driver ++ * implementation needs to take care of any refcounting if the same ++ * mailbox is requested by multiple clients. ++ * @shutdown: the shutdown function, essential for making the mailbox inactive ++ * after usage. This will be called when a client releases the ++ * mailbox. The driver implementation needs to take care of any ++ * refcounting if the same mailbox is requested by multiple clients. ++ * @fifo_read: read and return the h/w transport payload message. This hook ++ * provides the omap mailbox core to read all the available messages ++ * upon a Rx interrupt and buffer them. The messages are delivered ++ * to the clients in a workqueue. ++ * @fifo_write: send a mailbox message packet on the h/w transport channel. The ++ * individual drivers are responsible for configuring the h/w ++ * accordingly. ++ * @fifo_empty: check if the h/w Rx transport has more messages. The function ++ * should return 0 if there are no more messages to be read from ++ * the transport, and non-zero if there are available messages. ++ * @poll_for_space: check if the h/w Tx transport is busy. This hook should ++ * return non-zero if the h/w Tx transport is busy, and 0 when ++ * the h/w communication channel is free. ++ * @enable_irq: This hook allows the mailbox core to allow a specific Rx or Tx ++ * interrupt signal to interrupt the processor, based on its state ++ * machine. ++ * @disable_irq: This hooks allows the mailbox core to disable a specific Rx or ++ * Tx interrupt signal from interrupting the processor, based on ++ * its state machine. ++ * @ack_irq: acknowledge the Tx or Rx interrupt signal internal to the mailbox. ++ * This allows the h/w communication block to clear any internal ++ * interrupt source status registers. ++ * @is_irq: check if a particular Tx or Rx interrupt signal on the corresponding ++ * mailbox is set. This hook is used by the mailbox core to process the ++ * interrupt accordingly. ++ * @save_ctx: Called by a client or the mailbox core to allow the individual ++ * driver implementation to save the context of the mailbox registers ++ * before the domain containing the h/w communication block can be ++ * put into a low-power state. ++ * @restore_ctx: Called by a client or the mailbox core to allow the individual ++ * driver implementation to restore the context of the mailbox ++ * registers after the domain containing the h/w communication block ++ * is powered back to active state. ++ */ + struct omap_mbox_ops { +- omap_mbox_type_t type; + int (*startup)(struct omap_mbox *mbox); + void (*shutdown)(struct omap_mbox *mbox); +- /* fifo */ ++ /* mailbox access */ + mbox_msg_t (*fifo_read)(struct omap_mbox *mbox); + void (*fifo_write)(struct omap_mbox *mbox, mbox_msg_t msg); + int (*fifo_empty)(struct omap_mbox *mbox); +- int (*fifo_full)(struct omap_mbox *mbox); ++ int (*poll_for_space)(struct omap_mbox *mbox); + /* irq */ + void (*enable_irq)(struct omap_mbox *mbox, + omap_mbox_irq_t irq); +@@ -36,11 +75,28 @@ struct omap_mbox_ops { + omap_mbox_irq_t irq); + void (*ack_irq)(struct omap_mbox *mbox, omap_mbox_irq_t irq); + int (*is_irq)(struct omap_mbox *mbox, omap_mbox_irq_t irq); +- /* ctx */ ++ /* context */ + void (*save_ctx)(struct omap_mbox *mbox); + void (*restore_ctx)(struct omap_mbox *mbox); + }; + ++/** ++ * struct omap_mbox_queue - A queue object used for buffering messages ++ * @lock: a spinlock providing synchronization in atomic context ++ * @fifo: a kfifo object for buffering the messages. The size of the kfifo is ++ * is currently configured either at build time using kernel menu ++ * configuration or at runtime through a module parameter. The usage of ++ * the kfifo depends on whether the queue object is for Rx or Tx. For Tx, ++ * a message is buffered into the kfifo if the h/w transport is busy, and ++ * is taken out when the h/w signals Tx readiness. For Rx, the messages ++ * are buffered into the kfifo in the bottom-half processing of a Rx ++ * interrupt, and taken out during the top-half processing. ++ * @work: a workqueue object for scheduling top-half processing of rx messages ++ * @tasklet: a tasklet object for processing tx messages in an atomic context ++ * @mbox: reference to the containing parent mailbox ++ * full: indicates the status of the fifo, and is set to true when there is no ++ * room in the fifo. ++ */ + struct omap_mbox_queue { + spinlock_t lock; + struct kfifo fifo; +@@ -50,18 +106,65 @@ struct omap_mbox_queue { + bool full; + }; + ++/** ++ * struct omap_mbox_device - device structure for storing h/w mailbox block ++ * @dev: reference device pointer of the h/w mailbox block ++ * @cfg_lock: a configuration mutex lock used for protecting the mailbox ++ * device configuration operations ++ * @mbox_base: ioremapped base address of the h/w mailbox block ++ * @num_users: number of output interrupts from the h/w mailbox block, multiple ++ * interrupts can be routed to a particular processor sub-system ++ * @num_fifos: number of individual h/w fifo queues supported within a h/w ++ * mailbox block ++ * @mboxes: array of containing mailboxes within the h/w mailbox block ++ * @elem: list node ++ */ ++struct omap_mbox_device { ++ struct device *dev; ++ struct mutex cfg_lock; ++ void __iomem *mbox_base; ++ u32 num_users; ++ u32 num_fifos; ++ struct omap_mbox **mboxes; ++ struct list_head elem; ++}; ++ ++/** ++ * struct omap_mbox - the base object describing a h/w communication channel. ++ * there can be more than one object in a h/w communication block ++ * @name: a unique name for the mailbox object. Client users acquire a ++ * mailbox object using this name ++ * @irq: IRQ number that the mailbox uses to interrupt the host processor. ++ * the same IRQ number may be shared between different mailboxes ++ * @txq: the mailbox queue object pertaining to Tx ++ * @rxq: the mailbox queue object pertaining to Rx ++ * @ops: function ops specific to the mailbox ++ * @dev: the device pointer representing the mailbox object ++ * @parent: back reference to the containing parent mailbox device object ++ * @priv: a private structure specific to the driver implementation, this will ++ * not be touched by the mailbox core ++ * @use_count: number of current references to the mailbox, useful in ++ * controlling the mailbox state ++ * @notifier: notifier chain of clients, to which a received message is ++ * communicated ++ */ + struct omap_mbox { + const char *name; + unsigned int irq; + struct omap_mbox_queue *txq, *rxq; + struct omap_mbox_ops *ops; + struct device *dev; ++ struct omap_mbox_device *parent; + void *priv; + int use_count; + struct blocking_notifier_head notifier; + }; + +-int omap_mbox_register(struct device *parent, struct omap_mbox **); +-int omap_mbox_unregister(void); ++/* ++ * mailbox objects registration and de-registration functions with the ++ * mailbox core. ++ */ ++int omap_mbox_register(struct omap_mbox_device *device); ++int omap_mbox_unregister(struct omap_mbox_device *device); + + #endif /* OMAP_MBOX_H */ +--- a/drivers/Makefile ++++ b/drivers/Makefile +@@ -8,6 +8,8 @@ + obj-y += irqchip/ + obj-y += bus/ + ++obj-$(CONFIG_GENERIC_PHY) += phy/ ++ + # GPIO must come after pinctrl as gpios may need to mux pins etc + obj-y += pinctrl/ + obj-y += gpio/ +--- a/drivers/media/platform/Kconfig ++++ b/drivers/media/platform/Kconfig +@@ -220,6 +220,22 @@ config VIDEO_RENESAS_VSP1 + To compile this driver as a module, choose M here: the module + will be called vsp1. + ++config VIDEO_TI_VPE ++ tristate "TI VPE (Video Processing Engine) driver" ++ depends on VIDEO_DEV && VIDEO_V4L2 && SOC_DRA7XX ++ select VIDEOBUF2_DMA_CONTIG ++ select V4L2_MEM2MEM_DEV ++ default n ++ ---help--- ++ Support for the TI VPE(Video Processing Engine) block ++ found on DRA7XX SoC. ++ ++config VIDEO_TI_VPE_DEBUG ++ bool "VPE debug messages" ++ depends on VIDEO_TI_VPE ++ ---help--- ++ Enable debug messages on VPE driver. ++ + endif # V4L_MEM2MEM_DRIVERS + + menuconfig V4L_TEST_DRIVERS +--- a/drivers/media/platform/Makefile ++++ b/drivers/media/platform/Makefile +@@ -22,6 +22,8 @@ obj-$(CONFIG_VIDEO_VIVI) += vivi.o + + obj-$(CONFIG_VIDEO_MEM2MEM_TESTDEV) += mem2mem_testdev.o + ++obj-$(CONFIG_VIDEO_TI_VPE) += ti-vpe/ ++ + obj-$(CONFIG_VIDEO_MX2_EMMAPRP) += mx2_emmaprp.o + obj-$(CONFIG_VIDEO_CODA) += coda.o + +--- /dev/null ++++ b/drivers/media/platform/ti-vpe/Makefile +@@ -0,0 +1,5 @@ ++obj-$(CONFIG_VIDEO_TI_VPE) += ti-vpe.o ++ ++ti-vpe-y := vpe.o vpdma.o ++ ++ccflags-$(CONFIG_VIDEO_TI_VPE_DEBUG) += -DDEBUG +--- /dev/null ++++ b/drivers/media/platform/ti-vpe/vpdma.c +@@ -0,0 +1,846 @@ ++/* ++ * VPDMA helper library ++ * ++ * Copyright (c) 2013 Texas Instruments Inc. ++ * ++ * David Griego, <dagriego@biglakesoftware.com> ++ * Dale Farnsworth, <dale@farnsworth.org> ++ * Archit Taneja, <archit@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/delay.h> ++#include <linux/dma-mapping.h> ++#include <linux/err.h> ++#include <linux/firmware.h> ++#include <linux/io.h> ++#include <linux/module.h> ++#include <linux/platform_device.h> ++#include <linux/sched.h> ++#include <linux/slab.h> ++#include <linux/videodev2.h> ++ ++#include "vpdma.h" ++#include "vpdma_priv.h" ++ ++#define VPDMA_FIRMWARE "vpdma-1b8.bin" ++ ++const struct vpdma_data_format vpdma_yuv_fmts[] = { ++ [VPDMA_DATA_FMT_Y444] = { ++ .data_type = DATA_TYPE_Y444, ++ .depth = 8, ++ }, ++ [VPDMA_DATA_FMT_Y422] = { ++ .data_type = DATA_TYPE_Y422, ++ .depth = 8, ++ }, ++ [VPDMA_DATA_FMT_Y420] = { ++ .data_type = DATA_TYPE_Y420, ++ .depth = 8, ++ }, ++ [VPDMA_DATA_FMT_C444] = { ++ .data_type = DATA_TYPE_C444, ++ .depth = 8, ++ }, ++ [VPDMA_DATA_FMT_C422] = { ++ .data_type = DATA_TYPE_C422, ++ .depth = 8, ++ }, ++ [VPDMA_DATA_FMT_C420] = { ++ .data_type = DATA_TYPE_C420, ++ .depth = 4, ++ }, ++ [VPDMA_DATA_FMT_YC422] = { ++ .data_type = DATA_TYPE_YC422, ++ .depth = 16, ++ }, ++ [VPDMA_DATA_FMT_YC444] = { ++ .data_type = DATA_TYPE_YC444, ++ .depth = 24, ++ }, ++ [VPDMA_DATA_FMT_CY422] = { ++ .data_type = DATA_TYPE_CY422, ++ .depth = 16, ++ }, ++}; ++ ++const struct vpdma_data_format vpdma_rgb_fmts[] = { ++ [VPDMA_DATA_FMT_RGB565] = { ++ .data_type = DATA_TYPE_RGB16_565, ++ .depth = 16, ++ }, ++ [VPDMA_DATA_FMT_ARGB16_1555] = { ++ .data_type = DATA_TYPE_ARGB_1555, ++ .depth = 16, ++ }, ++ [VPDMA_DATA_FMT_ARGB16] = { ++ .data_type = DATA_TYPE_ARGB_4444, ++ .depth = 16, ++ }, ++ [VPDMA_DATA_FMT_RGBA16_5551] = { ++ .data_type = DATA_TYPE_RGBA_5551, ++ .depth = 16, ++ }, ++ [VPDMA_DATA_FMT_RGBA16] = { ++ .data_type = DATA_TYPE_RGBA_4444, ++ .depth = 16, ++ }, ++ [VPDMA_DATA_FMT_ARGB24] = { ++ .data_type = DATA_TYPE_ARGB24_6666, ++ .depth = 24, ++ }, ++ [VPDMA_DATA_FMT_RGB24] = { ++ .data_type = DATA_TYPE_RGB24_888, ++ .depth = 24, ++ }, ++ [VPDMA_DATA_FMT_ARGB32] = { ++ .data_type = DATA_TYPE_ARGB32_8888, ++ .depth = 32, ++ }, ++ [VPDMA_DATA_FMT_RGBA24] = { ++ .data_type = DATA_TYPE_RGBA24_6666, ++ .depth = 24, ++ }, ++ [VPDMA_DATA_FMT_RGBA32] = { ++ .data_type = DATA_TYPE_RGBA32_8888, ++ .depth = 32, ++ }, ++ [VPDMA_DATA_FMT_BGR565] = { ++ .data_type = DATA_TYPE_BGR16_565, ++ .depth = 16, ++ }, ++ [VPDMA_DATA_FMT_ABGR16_1555] = { ++ .data_type = DATA_TYPE_ABGR_1555, ++ .depth = 16, ++ }, ++ [VPDMA_DATA_FMT_ABGR16] = { ++ .data_type = DATA_TYPE_ABGR_4444, ++ .depth = 16, ++ }, ++ [VPDMA_DATA_FMT_BGRA16_5551] = { ++ .data_type = DATA_TYPE_BGRA_5551, ++ .depth = 16, ++ }, ++ [VPDMA_DATA_FMT_BGRA16] = { ++ .data_type = DATA_TYPE_BGRA_4444, ++ .depth = 16, ++ }, ++ [VPDMA_DATA_FMT_ABGR24] = { ++ .data_type = DATA_TYPE_ABGR24_6666, ++ .depth = 24, ++ }, ++ [VPDMA_DATA_FMT_BGR24] = { ++ .data_type = DATA_TYPE_BGR24_888, ++ .depth = 24, ++ }, ++ [VPDMA_DATA_FMT_ABGR32] = { ++ .data_type = DATA_TYPE_ABGR32_8888, ++ .depth = 32, ++ }, ++ [VPDMA_DATA_FMT_BGRA24] = { ++ .data_type = DATA_TYPE_BGRA24_6666, ++ .depth = 24, ++ }, ++ [VPDMA_DATA_FMT_BGRA32] = { ++ .data_type = DATA_TYPE_BGRA32_8888, ++ .depth = 32, ++ }, ++}; ++ ++const struct vpdma_data_format vpdma_misc_fmts[] = { ++ [VPDMA_DATA_FMT_MV] = { ++ .data_type = DATA_TYPE_MV, ++ .depth = 4, ++ }, ++}; ++ ++struct vpdma_channel_info { ++ int num; /* VPDMA channel number */ ++ int cstat_offset; /* client CSTAT register offset */ ++}; ++ ++static const struct vpdma_channel_info chan_info[] = { ++ [VPE_CHAN_LUMA1_IN] = { ++ .num = VPE_CHAN_NUM_LUMA1_IN, ++ .cstat_offset = VPDMA_DEI_LUMA1_CSTAT, ++ }, ++ [VPE_CHAN_CHROMA1_IN] = { ++ .num = VPE_CHAN_NUM_CHROMA1_IN, ++ .cstat_offset = VPDMA_DEI_CHROMA1_CSTAT, ++ }, ++ [VPE_CHAN_LUMA2_IN] = { ++ .num = VPE_CHAN_NUM_LUMA2_IN, ++ .cstat_offset = VPDMA_DEI_LUMA2_CSTAT, ++ }, ++ [VPE_CHAN_CHROMA2_IN] = { ++ .num = VPE_CHAN_NUM_CHROMA2_IN, ++ .cstat_offset = VPDMA_DEI_CHROMA2_CSTAT, ++ }, ++ [VPE_CHAN_LUMA3_IN] = { ++ .num = VPE_CHAN_NUM_LUMA3_IN, ++ .cstat_offset = VPDMA_DEI_LUMA3_CSTAT, ++ }, ++ [VPE_CHAN_CHROMA3_IN] = { ++ .num = VPE_CHAN_NUM_CHROMA3_IN, ++ .cstat_offset = VPDMA_DEI_CHROMA3_CSTAT, ++ }, ++ [VPE_CHAN_MV_IN] = { ++ .num = VPE_CHAN_NUM_MV_IN, ++ .cstat_offset = VPDMA_DEI_MV_IN_CSTAT, ++ }, ++ [VPE_CHAN_MV_OUT] = { ++ .num = VPE_CHAN_NUM_MV_OUT, ++ .cstat_offset = VPDMA_DEI_MV_OUT_CSTAT, ++ }, ++ [VPE_CHAN_LUMA_OUT] = { ++ .num = VPE_CHAN_NUM_LUMA_OUT, ++ .cstat_offset = VPDMA_VIP_UP_Y_CSTAT, ++ }, ++ [VPE_CHAN_CHROMA_OUT] = { ++ .num = VPE_CHAN_NUM_CHROMA_OUT, ++ .cstat_offset = VPDMA_VIP_UP_UV_CSTAT, ++ }, ++ [VPE_CHAN_RGB_OUT] = { ++ .num = VPE_CHAN_NUM_RGB_OUT, ++ .cstat_offset = VPDMA_VIP_UP_Y_CSTAT, ++ }, ++}; ++ ++static u32 read_reg(struct vpdma_data *vpdma, int offset) ++{ ++ return ioread32(vpdma->base + offset); ++} ++ ++static void write_reg(struct vpdma_data *vpdma, int offset, u32 value) ++{ ++ iowrite32(value, vpdma->base + offset); ++} ++ ++static int read_field_reg(struct vpdma_data *vpdma, int offset, ++ u32 mask, int shift) ++{ ++ return (read_reg(vpdma, offset) & (mask << shift)) >> shift; ++} ++ ++static void write_field_reg(struct vpdma_data *vpdma, int offset, u32 field, ++ u32 mask, int shift) ++{ ++ u32 val = read_reg(vpdma, offset); ++ ++ val &= ~(mask << shift); ++ val |= (field & mask) << shift; ++ ++ write_reg(vpdma, offset, val); ++} ++ ++void vpdma_dump_regs(struct vpdma_data *vpdma) ++{ ++ struct device *dev = &vpdma->pdev->dev; ++ ++#define DUMPREG(r) dev_dbg(dev, "%-35s %08x\n", #r, read_reg(vpdma, VPDMA_##r)) ++ ++ dev_dbg(dev, "VPDMA Registers:\n"); ++ ++ DUMPREG(PID); ++ DUMPREG(LIST_ADDR); ++ DUMPREG(LIST_ATTR); ++ DUMPREG(LIST_STAT_SYNC); ++ DUMPREG(BG_RGB); ++ DUMPREG(BG_YUV); ++ DUMPREG(SETUP); ++ DUMPREG(MAX_SIZE1); ++ DUMPREG(MAX_SIZE2); ++ DUMPREG(MAX_SIZE3); ++ ++ /* ++ * dumping registers of only group0 and group3, because VPE channels ++ * lie within group0 and group3 registers ++ */ ++ DUMPREG(INT_CHAN_STAT(0)); ++ DUMPREG(INT_CHAN_MASK(0)); ++ DUMPREG(INT_CHAN_STAT(3)); ++ DUMPREG(INT_CHAN_MASK(3)); ++ DUMPREG(INT_CLIENT0_STAT); ++ DUMPREG(INT_CLIENT0_MASK); ++ DUMPREG(INT_CLIENT1_STAT); ++ DUMPREG(INT_CLIENT1_MASK); ++ DUMPREG(INT_LIST0_STAT); ++ DUMPREG(INT_LIST0_MASK); ++ ++ /* ++ * these are registers specific to VPE clients, we can make this ++ * function dump client registers specific to VPE or VIP based on ++ * who is using it ++ */ ++ DUMPREG(DEI_CHROMA1_CSTAT); ++ DUMPREG(DEI_LUMA1_CSTAT); ++ DUMPREG(DEI_CHROMA2_CSTAT); ++ DUMPREG(DEI_LUMA2_CSTAT); ++ DUMPREG(DEI_CHROMA3_CSTAT); ++ DUMPREG(DEI_LUMA3_CSTAT); ++ DUMPREG(DEI_MV_IN_CSTAT); ++ DUMPREG(DEI_MV_OUT_CSTAT); ++ DUMPREG(VIP_UP_Y_CSTAT); ++ DUMPREG(VIP_UP_UV_CSTAT); ++ DUMPREG(VPI_CTL_CSTAT); ++} ++ ++/* ++ * Allocate a DMA buffer ++ */ ++int vpdma_alloc_desc_buf(struct vpdma_buf *buf, size_t size) ++{ ++ buf->size = size; ++ buf->mapped = false; ++ buf->addr = kzalloc(size, GFP_KERNEL); ++ if (!buf->addr) ++ return -ENOMEM; ++ ++ WARN_ON((u32) buf->addr & VPDMA_DESC_ALIGN); ++ ++ return 0; ++} ++ ++void vpdma_free_desc_buf(struct vpdma_buf *buf) ++{ ++ WARN_ON(buf->mapped); ++ kfree(buf->addr); ++ buf->addr = NULL; ++ buf->size = 0; ++} ++ ++/* ++ * map descriptor/payload DMA buffer, enabling DMA access ++ */ ++int vpdma_map_desc_buf(struct vpdma_data *vpdma, struct vpdma_buf *buf) ++{ ++ struct device *dev = &vpdma->pdev->dev; ++ ++ WARN_ON(buf->mapped); ++ buf->dma_addr = dma_map_single(dev, buf->addr, buf->size, ++ DMA_TO_DEVICE); ++ if (dma_mapping_error(dev, buf->dma_addr)) { ++ dev_err(dev, "failed to map buffer\n"); ++ return -EINVAL; ++ } ++ ++ buf->mapped = true; ++ ++ return 0; ++} ++ ++/* ++ * unmap descriptor/payload DMA buffer, disabling DMA access and ++ * allowing the main processor to acces the data ++ */ ++void vpdma_unmap_desc_buf(struct vpdma_data *vpdma, struct vpdma_buf *buf) ++{ ++ struct device *dev = &vpdma->pdev->dev; ++ ++ if (buf->mapped) ++ dma_unmap_single(dev, buf->dma_addr, buf->size, DMA_TO_DEVICE); ++ ++ buf->mapped = false; ++} ++ ++/* ++ * create a descriptor list, the user of this list will append configuration, ++ * control and data descriptors to this list, this list will be submitted to ++ * VPDMA. VPDMA's list parser will go through each descriptor and perform the ++ * required DMA operations ++ */ ++int vpdma_create_desc_list(struct vpdma_desc_list *list, size_t size, int type) ++{ ++ int r; ++ ++ r = vpdma_alloc_desc_buf(&list->buf, size); ++ if (r) ++ return r; ++ ++ list->next = list->buf.addr; ++ ++ list->type = type; ++ ++ return 0; ++} ++ ++/* ++ * once a descriptor list is parsed by VPDMA, we reset the list by emptying it, ++ * to allow new descriptors to be added to the list. ++ */ ++void vpdma_reset_desc_list(struct vpdma_desc_list *list) ++{ ++ list->next = list->buf.addr; ++} ++ ++/* ++ * free the buffer allocated fot the VPDMA descriptor list, this should be ++ * called when the user doesn't want to use VPDMA any more. ++ */ ++void vpdma_free_desc_list(struct vpdma_desc_list *list) ++{ ++ vpdma_free_desc_buf(&list->buf); ++ ++ list->next = NULL; ++} ++ ++static bool vpdma_list_busy(struct vpdma_data *vpdma, int list_num) ++{ ++ return read_reg(vpdma, VPDMA_LIST_STAT_SYNC) & BIT(list_num + 16); ++} ++ ++/* ++ * submit a list of DMA descriptors to the VPE VPDMA, do not wait for completion ++ */ ++int vpdma_submit_descs(struct vpdma_data *vpdma, struct vpdma_desc_list *list) ++{ ++ /* we always use the first list */ ++ int list_num = 0; ++ int list_size; ++ ++ if (vpdma_list_busy(vpdma, list_num)) ++ return -EBUSY; ++ ++ /* 16-byte granularity */ ++ list_size = (list->next - list->buf.addr) >> 4; ++ ++ write_reg(vpdma, VPDMA_LIST_ADDR, (u32) list->buf.dma_addr); ++ ++ write_reg(vpdma, VPDMA_LIST_ATTR, ++ (list_num << VPDMA_LIST_NUM_SHFT) | ++ (list->type << VPDMA_LIST_TYPE_SHFT) | ++ list_size); ++ ++ return 0; ++} ++ ++static void dump_cfd(struct vpdma_cfd *cfd) ++{ ++ int class; ++ ++ class = cfd_get_class(cfd); ++ ++ pr_debug("config descriptor of payload class: %s\n", ++ class == CFD_CLS_BLOCK ? "simple block" : ++ "address data block"); ++ ++ if (class == CFD_CLS_BLOCK) ++ pr_debug("word0: dst_addr_offset = 0x%08x\n", ++ cfd->dest_addr_offset); ++ ++ if (class == CFD_CLS_BLOCK) ++ pr_debug("word1: num_data_wrds = %d\n", cfd->block_len); ++ ++ pr_debug("word2: payload_addr = 0x%08x\n", cfd->payload_addr); ++ ++ pr_debug("word3: pkt_type = %d, direct = %d, class = %d, dest = %d, " ++ "payload_len = %d\n", cfd_get_pkt_type(cfd), ++ cfd_get_direct(cfd), class, cfd_get_dest(cfd), ++ cfd_get_payload_len(cfd)); ++} ++ ++/* ++ * append a configuration descriptor to the given descriptor list, where the ++ * payload is in the form of a simple data block specified in the descriptor ++ * header, this is used to upload scaler coefficients to the scaler module ++ */ ++void vpdma_add_cfd_block(struct vpdma_desc_list *list, int client, ++ struct vpdma_buf *blk, u32 dest_offset) ++{ ++ struct vpdma_cfd *cfd; ++ int len = blk->size; ++ ++ WARN_ON(blk->dma_addr & VPDMA_DESC_ALIGN); ++ ++ cfd = list->next; ++ WARN_ON((void *)(cfd + 1) > (list->buf.addr + list->buf.size)); ++ ++ cfd->dest_addr_offset = dest_offset; ++ cfd->block_len = len; ++ cfd->payload_addr = (u32) blk->dma_addr; ++ cfd->ctl_payload_len = cfd_pkt_payload_len(CFD_INDIRECT, CFD_CLS_BLOCK, ++ client, len >> 4); ++ ++ list->next = cfd + 1; ++ ++ dump_cfd(cfd); ++} ++ ++/* ++ * append a configuration descriptor to the given descriptor list, where the ++ * payload is in the address data block format, this is used to a configure a ++ * discontiguous set of MMRs ++ */ ++void vpdma_add_cfd_adb(struct vpdma_desc_list *list, int client, ++ struct vpdma_buf *adb) ++{ ++ struct vpdma_cfd *cfd; ++ unsigned int len = adb->size; ++ ++ WARN_ON(len & VPDMA_ADB_SIZE_ALIGN); ++ WARN_ON(adb->dma_addr & VPDMA_DESC_ALIGN); ++ ++ cfd = list->next; ++ BUG_ON((void *)(cfd + 1) > (list->buf.addr + list->buf.size)); ++ ++ cfd->w0 = 0; ++ cfd->w1 = 0; ++ cfd->payload_addr = (u32) adb->dma_addr; ++ cfd->ctl_payload_len = cfd_pkt_payload_len(CFD_INDIRECT, CFD_CLS_ADB, ++ client, len >> 4); ++ ++ list->next = cfd + 1; ++ ++ dump_cfd(cfd); ++}; ++ ++/* ++ * control descriptor format change based on what type of control descriptor it ++ * is, we only use 'sync on channel' control descriptors for now, so assume it's ++ * that ++ */ ++static void dump_ctd(struct vpdma_ctd *ctd) ++{ ++ pr_debug("control descriptor\n"); ++ ++ pr_debug("word3: pkt_type = %d, source = %d, ctl_type = %d\n", ++ ctd_get_pkt_type(ctd), ctd_get_source(ctd), ctd_get_ctl(ctd)); ++} ++ ++/* ++ * append a 'sync on channel' type control descriptor to the given descriptor ++ * list, this descriptor stalls the VPDMA list till the time DMA is completed ++ * on the specified channel ++ */ ++void vpdma_add_sync_on_channel_ctd(struct vpdma_desc_list *list, ++ enum vpdma_channel chan) ++{ ++ struct vpdma_ctd *ctd; ++ ++ ctd = list->next; ++ WARN_ON((void *)(ctd + 1) > (list->buf.addr + list->buf.size)); ++ ++ ctd->w0 = 0; ++ ctd->w1 = 0; ++ ctd->w2 = 0; ++ ctd->type_source_ctl = ctd_type_source_ctl(chan_info[chan].num, ++ CTD_TYPE_SYNC_ON_CHANNEL); ++ ++ list->next = ctd + 1; ++ ++ dump_ctd(ctd); ++} ++ ++static void dump_dtd(struct vpdma_dtd *dtd) ++{ ++ int dir, chan; ++ ++ dir = dtd_get_dir(dtd); ++ chan = dtd_get_chan(dtd); ++ ++ pr_debug("%s data transfer descriptor for channel %d\n", ++ dir == DTD_DIR_OUT ? "outbound" : "inbound", chan); ++ ++ pr_debug("word0: data_type = %d, notify = %d, field = %d, 1D = %d, " ++ "even_ln_skp = %d, odd_ln_skp = %d, line_stride = %d\n", ++ dtd_get_data_type(dtd), dtd_get_notify(dtd), dtd_get_field(dtd), ++ dtd_get_1d(dtd), dtd_get_even_line_skip(dtd), ++ dtd_get_odd_line_skip(dtd), dtd_get_line_stride(dtd)); ++ ++ if (dir == DTD_DIR_IN) ++ pr_debug("word1: line_length = %d, xfer_height = %d\n", ++ dtd_get_line_length(dtd), dtd_get_xfer_height(dtd)); ++ ++ pr_debug("word2: start_addr = 0x%08x\n", dtd->start_addr); ++ ++ pr_debug("word3: pkt_type = %d, mode = %d, dir = %d, chan = %d, " ++ "pri = %d, next_chan = %d\n", dtd_get_pkt_type(dtd), ++ dtd_get_mode(dtd), dir, chan, dtd_get_priority(dtd), ++ dtd_get_next_chan(dtd)); ++ ++ if (dir == DTD_DIR_IN) ++ pr_debug("word4: frame_width = %d, frame_height = %d\n", ++ dtd_get_frame_width(dtd), dtd_get_frame_height(dtd)); ++ else ++ pr_debug("word4: desc_write_addr = 0x%08x, write_desc = %d, " ++ "drp_data = %d, use_desc_reg = %d\n", ++ dtd_get_desc_write_addr(dtd), dtd_get_write_desc(dtd), ++ dtd_get_drop_data(dtd), dtd_get_use_desc(dtd)); ++ ++ if (dir == DTD_DIR_IN) ++ pr_debug("word5: hor_start = %d, ver_start = %d\n", ++ dtd_get_h_start(dtd), dtd_get_v_start(dtd)); ++ else ++ pr_debug("word5: max_width %d, max_height %d\n", ++ dtd_get_max_width(dtd), dtd_get_max_height(dtd)); ++ ++ pr_debug("word6: client specfic attr0 = 0x%08x\n", dtd->client_attr0); ++ pr_debug("word7: client specfic attr1 = 0x%08x\n", dtd->client_attr1); ++} ++ ++/* ++ * append an outbound data transfer descriptor to the given descriptor list, ++ * this sets up a 'client to memory' VPDMA transfer for the given VPDMA channel ++ */ ++void vpdma_add_out_dtd(struct vpdma_desc_list *list, struct v4l2_rect *c_rect, ++ const struct vpdma_data_format *fmt, dma_addr_t dma_addr, ++ enum vpdma_channel chan, u32 flags) ++{ ++ int priority = 0; ++ int field = 0; ++ int notify = 1; ++ int channel, next_chan; ++ int depth = fmt->depth; ++ int stride; ++ struct vpdma_dtd *dtd; ++ ++ channel = next_chan = chan_info[chan].num; ++ ++ if (fmt->data_type == DATA_TYPE_C420) ++ depth = 8; ++ ++ stride = (depth * c_rect->width) >> 3; ++ dma_addr += (c_rect->left * depth) >> 3; ++ ++ dtd = list->next; ++ WARN_ON((void *)(dtd + 1) > (list->buf.addr + list->buf.size)); ++ ++ dtd->type_ctl_stride = dtd_type_ctl_stride(fmt->data_type, ++ notify, ++ field, ++ !!(flags & VPDMA_DATA_FRAME_1D), ++ !!(flags & VPDMA_DATA_EVEN_LINE_SKIP), ++ !!(flags & VPDMA_DATA_ODD_LINE_SKIP), ++ stride); ++ dtd->w1 = 0; ++ dtd->start_addr = (u32) dma_addr; ++ dtd->pkt_ctl = dtd_pkt_ctl(!!(flags & VPDMA_DATA_MODE_TILED), ++ DTD_DIR_OUT, channel, priority, next_chan); ++ dtd->desc_write_addr = dtd_desc_write_addr(0, 0, 0, 0); ++ dtd->max_width_height = dtd_max_width_height(MAX_OUT_WIDTH_1920, ++ MAX_OUT_HEIGHT_1080); ++ dtd->client_attr0 = 0; ++ dtd->client_attr1 = 0; ++ ++ list->next = dtd + 1; ++ ++ dump_dtd(dtd); ++} ++ ++/* ++ * append an inbound data transfer descriptor to the given descriptor list, ++ * this sets up a 'memory to client' VPDMA transfer for the given VPDMA channel ++ */ ++void vpdma_add_in_dtd(struct vpdma_desc_list *list, int frame_width, ++ int frame_height, struct v4l2_rect *c_rect, ++ const struct vpdma_data_format *fmt, dma_addr_t dma_addr, ++ enum vpdma_channel chan, int field, u32 flags) ++{ ++ int priority = 0; ++ int notify = 1; ++ int depth = fmt->depth; ++ int channel, next_chan; ++ int stride; ++ int height = c_rect->height; ++ struct vpdma_dtd *dtd; ++ ++ channel = next_chan = chan_info[chan].num; ++ ++ if (fmt->data_type == DATA_TYPE_C420) { ++ height >>= 1; ++ frame_height >>= 1; ++ depth = 8; ++ } ++ ++ stride = (depth * c_rect->width) >> 3; ++ dma_addr += (c_rect->left * depth) >> 3; ++ ++ dtd = list->next; ++ WARN_ON((void *)(dtd + 1) > (list->buf.addr + list->buf.size)); ++ ++ dtd->type_ctl_stride = dtd_type_ctl_stride(fmt->data_type, ++ notify, ++ field, ++ !!(flags & VPDMA_DATA_FRAME_1D), ++ !!(flags & VPDMA_DATA_EVEN_LINE_SKIP), ++ !!(flags & VPDMA_DATA_ODD_LINE_SKIP), ++ stride); ++ ++ dtd->xfer_length_height = dtd_xfer_length_height(c_rect->width, height); ++ dtd->start_addr = (u32) dma_addr; ++ dtd->pkt_ctl = dtd_pkt_ctl(!!(flags & VPDMA_DATA_MODE_TILED), ++ DTD_DIR_IN, channel, priority, next_chan); ++ dtd->frame_width_height = dtd_frame_width_height(frame_width, ++ frame_height); ++ dtd->start_h_v = dtd_start_h_v(c_rect->left, c_rect->top); ++ dtd->client_attr0 = 0; ++ dtd->client_attr1 = 0; ++ ++ list->next = dtd + 1; ++ ++ dump_dtd(dtd); ++} ++ ++/* set or clear the mask for list complete interrupt */ ++void vpdma_enable_list_complete_irq(struct vpdma_data *vpdma, int list_num, ++ bool enable) ++{ ++ u32 val; ++ ++ val = read_reg(vpdma, VPDMA_INT_LIST0_MASK); ++ if (enable) ++ val |= (1 << (list_num * 2)); ++ else ++ val &= ~(1 << (list_num * 2)); ++ write_reg(vpdma, VPDMA_INT_LIST0_MASK, val); ++} ++ ++/* clear previosuly occured list intterupts in the LIST_STAT register */ ++void vpdma_clear_list_stat(struct vpdma_data *vpdma) ++{ ++ write_reg(vpdma, VPDMA_INT_LIST0_STAT, ++ read_reg(vpdma, VPDMA_INT_LIST0_STAT)); ++} ++ ++/* ++ * configures the output mode of the line buffer for the given client, the ++ * line buffer content can either be mirrored(each line repeated twice) or ++ * passed to the client as is ++ */ ++void vpdma_set_line_mode(struct vpdma_data *vpdma, int line_mode, ++ enum vpdma_channel chan) ++{ ++ int client_cstat = chan_info[chan].cstat_offset; ++ ++ write_field_reg(vpdma, client_cstat, line_mode, ++ VPDMA_CSTAT_LINE_MODE_MASK, VPDMA_CSTAT_LINE_MODE_SHIFT); ++} ++ ++/* ++ * configures the event which should trigger VPDMA transfer for the given ++ * client ++ */ ++void vpdma_set_frame_start_event(struct vpdma_data *vpdma, ++ enum vpdma_frame_start_event fs_event, ++ enum vpdma_channel chan) ++{ ++ int client_cstat = chan_info[chan].cstat_offset; ++ ++ write_field_reg(vpdma, client_cstat, fs_event, ++ VPDMA_CSTAT_FRAME_START_MASK, VPDMA_CSTAT_FRAME_START_SHIFT); ++} ++ ++static void vpdma_firmware_cb(const struct firmware *f, void *context) ++{ ++ struct vpdma_data *vpdma = context; ++ struct vpdma_buf fw_dma_buf; ++ int i, r; ++ ++ dev_dbg(&vpdma->pdev->dev, "firmware callback\n"); ++ ++ if (!f || !f->data) { ++ dev_err(&vpdma->pdev->dev, "couldn't get firmware\n"); ++ return; ++ } ++ ++ /* already initialized */ ++ if (read_field_reg(vpdma, VPDMA_LIST_ATTR, VPDMA_LIST_RDY_MASK, ++ VPDMA_LIST_RDY_SHFT)) { ++ vpdma->ready = true; ++ return; ++ } ++ ++ r = vpdma_alloc_desc_buf(&fw_dma_buf, f->size); ++ if (r) { ++ dev_err(&vpdma->pdev->dev, ++ "failed to allocate dma buffer for firmware\n"); ++ goto rel_fw; ++ } ++ ++ memcpy(fw_dma_buf.addr, f->data, f->size); ++ ++ vpdma_map_desc_buf(vpdma, &fw_dma_buf); ++ ++ write_reg(vpdma, VPDMA_LIST_ADDR, (u32) fw_dma_buf.dma_addr); ++ ++ for (i = 0; i < 100; i++) { /* max 1 second */ ++ msleep_interruptible(10); ++ ++ if (read_field_reg(vpdma, VPDMA_LIST_ATTR, VPDMA_LIST_RDY_MASK, ++ VPDMA_LIST_RDY_SHFT)) ++ break; ++ } ++ ++ if (i == 100) { ++ dev_err(&vpdma->pdev->dev, "firmware upload failed\n"); ++ goto free_buf; ++ } ++ ++ vpdma->ready = true; ++ ++free_buf: ++ vpdma_unmap_desc_buf(vpdma, &fw_dma_buf); ++ ++ vpdma_free_desc_buf(&fw_dma_buf); ++rel_fw: ++ release_firmware(f); ++} ++ ++static int vpdma_load_firmware(struct vpdma_data *vpdma) ++{ ++ int r; ++ struct device *dev = &vpdma->pdev->dev; ++ ++ r = request_firmware_nowait(THIS_MODULE, 1, ++ (const char *) VPDMA_FIRMWARE, dev, GFP_KERNEL, vpdma, ++ vpdma_firmware_cb); ++ if (r) { ++ dev_err(dev, "firmware not available %s\n", VPDMA_FIRMWARE); ++ return r; ++ } else { ++ dev_info(dev, "loading firmware %s\n", VPDMA_FIRMWARE); ++ } ++ ++ return 0; ++} ++ ++struct vpdma_data *vpdma_create(struct platform_device *pdev) ++{ ++ struct resource *res; ++ struct vpdma_data *vpdma; ++ int r; ++ ++ dev_dbg(&pdev->dev, "vpdma_create\n"); ++ ++ vpdma = devm_kzalloc(&pdev->dev, sizeof(*vpdma), GFP_KERNEL); ++ if (!vpdma) { ++ dev_err(&pdev->dev, "couldn't alloc vpdma_dev\n"); ++ return ERR_PTR(-ENOMEM); ++ } ++ ++ vpdma->pdev = pdev; ++ ++ res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "vpdma"); ++ if (res == NULL) { ++ dev_err(&pdev->dev, "missing platform resources data\n"); ++ return ERR_PTR(-ENODEV); ++ } ++ ++ vpdma->base = devm_ioremap(&pdev->dev, res->start, resource_size(res)); ++ if (!vpdma->base) { ++ dev_err(&pdev->dev, "failed to ioremap\n"); ++ return ERR_PTR(-ENOMEM); ++ } ++ ++ r = vpdma_load_firmware(vpdma); ++ if (r) { ++ pr_err("failed to load firmware %s\n", VPDMA_FIRMWARE); ++ return ERR_PTR(r); ++ } ++ ++ return vpdma; ++} ++MODULE_FIRMWARE(VPDMA_FIRMWARE); +--- /dev/null ++++ b/drivers/media/platform/ti-vpe/vpdma.h +@@ -0,0 +1,203 @@ ++/* ++ * Copyright (c) 2013 Texas Instruments Inc. ++ * ++ * David Griego, <dagriego@biglakesoftware.com> ++ * Dale Farnsworth, <dale@farnsworth.org> ++ * Archit Taneja, <archit@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 __TI_VPDMA_H_ ++#define __TI_VPDMA_H_ ++ ++/* ++ * A vpdma_buf tracks the size, DMA address and mapping status of each ++ * driver DMA area. ++ */ ++struct vpdma_buf { ++ void *addr; ++ dma_addr_t dma_addr; ++ size_t size; ++ bool mapped; ++}; ++ ++struct vpdma_desc_list { ++ struct vpdma_buf buf; ++ void *next; ++ int type; ++}; ++ ++struct vpdma_data { ++ void __iomem *base; ++ ++ struct platform_device *pdev; ++ ++ /* tells whether vpdma firmware is loaded or not */ ++ bool ready; ++}; ++ ++struct vpdma_data_format { ++ int data_type; ++ u8 depth; ++}; ++ ++#define VPDMA_DESC_ALIGN 16 /* 16-byte descriptor alignment */ ++ ++#define VPDMA_DTD_DESC_SIZE 32 /* 8 words */ ++#define VPDMA_CFD_CTD_DESC_SIZE 16 /* 4 words */ ++ ++#define VPDMA_LIST_TYPE_NORMAL 0 ++#define VPDMA_LIST_TYPE_SELF_MODIFYING 1 ++#define VPDMA_LIST_TYPE_DOORBELL 2 ++ ++enum vpdma_yuv_formats { ++ VPDMA_DATA_FMT_Y444 = 0, ++ VPDMA_DATA_FMT_Y422, ++ VPDMA_DATA_FMT_Y420, ++ VPDMA_DATA_FMT_C444, ++ VPDMA_DATA_FMT_C422, ++ VPDMA_DATA_FMT_C420, ++ VPDMA_DATA_FMT_YC422, ++ VPDMA_DATA_FMT_YC444, ++ VPDMA_DATA_FMT_CY422, ++}; ++ ++enum vpdma_rgb_formats { ++ VPDMA_DATA_FMT_RGB565 = 0, ++ VPDMA_DATA_FMT_ARGB16_1555, ++ VPDMA_DATA_FMT_ARGB16, ++ VPDMA_DATA_FMT_RGBA16_5551, ++ VPDMA_DATA_FMT_RGBA16, ++ VPDMA_DATA_FMT_ARGB24, ++ VPDMA_DATA_FMT_RGB24, ++ VPDMA_DATA_FMT_ARGB32, ++ VPDMA_DATA_FMT_RGBA24, ++ VPDMA_DATA_FMT_RGBA32, ++ VPDMA_DATA_FMT_BGR565, ++ VPDMA_DATA_FMT_ABGR16_1555, ++ VPDMA_DATA_FMT_ABGR16, ++ VPDMA_DATA_FMT_BGRA16_5551, ++ VPDMA_DATA_FMT_BGRA16, ++ VPDMA_DATA_FMT_ABGR24, ++ VPDMA_DATA_FMT_BGR24, ++ VPDMA_DATA_FMT_ABGR32, ++ VPDMA_DATA_FMT_BGRA24, ++ VPDMA_DATA_FMT_BGRA32, ++}; ++ ++enum vpdma_misc_formats { ++ VPDMA_DATA_FMT_MV = 0, ++}; ++ ++extern const struct vpdma_data_format vpdma_yuv_fmts[]; ++extern const struct vpdma_data_format vpdma_rgb_fmts[]; ++extern const struct vpdma_data_format vpdma_misc_fmts[]; ++ ++enum vpdma_frame_start_event { ++ VPDMA_FSEVENT_HDMI_FID = 0, ++ VPDMA_FSEVENT_DVO2_FID, ++ VPDMA_FSEVENT_HDCOMP_FID, ++ VPDMA_FSEVENT_SD_FID, ++ VPDMA_FSEVENT_LM_FID0, ++ VPDMA_FSEVENT_LM_FID1, ++ VPDMA_FSEVENT_LM_FID2, ++ VPDMA_FSEVENT_CHANNEL_ACTIVE, ++}; ++ ++/* ++ * VPDMA channel numbers ++ */ ++enum vpdma_channel { ++ VPE_CHAN_LUMA1_IN, ++ VPE_CHAN_CHROMA1_IN, ++ VPE_CHAN_LUMA2_IN, ++ VPE_CHAN_CHROMA2_IN, ++ VPE_CHAN_LUMA3_IN, ++ VPE_CHAN_CHROMA3_IN, ++ VPE_CHAN_MV_IN, ++ VPE_CHAN_MV_OUT, ++ VPE_CHAN_LUMA_OUT, ++ VPE_CHAN_CHROMA_OUT, ++ VPE_CHAN_RGB_OUT, ++}; ++ ++/* flags for VPDMA data descriptors */ ++#define VPDMA_DATA_ODD_LINE_SKIP (1 << 0) ++#define VPDMA_DATA_EVEN_LINE_SKIP (1 << 1) ++#define VPDMA_DATA_FRAME_1D (1 << 2) ++#define VPDMA_DATA_MODE_TILED (1 << 3) ++ ++/* ++ * client identifiers used for configuration descriptors ++ */ ++#define CFD_MMR_CLIENT 0 ++#define CFD_SC_CLIENT 4 ++ ++/* Address data block header format */ ++struct vpdma_adb_hdr { ++ u32 offset; ++ u32 nwords; ++ u32 reserved0; ++ u32 reserved1; ++}; ++ ++/* helpers for creating ADB headers for config descriptors MMRs as client */ ++#define ADB_ADDR(dma_buf, str, fld) ((dma_buf)->addr + offsetof(str, fld)) ++#define MMR_ADB_ADDR(buf, str, fld) ADB_ADDR(&(buf), struct str, fld) ++ ++#define VPDMA_SET_MMR_ADB_HDR(buf, str, hdr, regs, offset_a) \ ++ do { \ ++ struct vpdma_adb_hdr *h; \ ++ struct str *adb = NULL; \ ++ h = MMR_ADB_ADDR(buf, str, hdr); \ ++ h->offset = (offset_a); \ ++ h->nwords = sizeof(adb->regs) >> 2; \ ++ } while (0) ++ ++/* vpdma descriptor buffer allocation and management */ ++int vpdma_alloc_desc_buf(struct vpdma_buf *buf, size_t size); ++void vpdma_free_desc_buf(struct vpdma_buf *buf); ++int vpdma_map_desc_buf(struct vpdma_data *vpdma, struct vpdma_buf *buf); ++void vpdma_unmap_desc_buf(struct vpdma_data *vpdma, struct vpdma_buf *buf); ++ ++/* vpdma descriptor list funcs */ ++int vpdma_create_desc_list(struct vpdma_desc_list *list, size_t size, int type); ++void vpdma_reset_desc_list(struct vpdma_desc_list *list); ++void vpdma_free_desc_list(struct vpdma_desc_list *list); ++int vpdma_submit_descs(struct vpdma_data *vpdma, struct vpdma_desc_list *list); ++ ++/* helpers for creating vpdma descriptors */ ++void vpdma_add_cfd_block(struct vpdma_desc_list *list, int client, ++ struct vpdma_buf *blk, u32 dest_offset); ++void vpdma_add_cfd_adb(struct vpdma_desc_list *list, int client, ++ struct vpdma_buf *adb); ++void vpdma_add_sync_on_channel_ctd(struct vpdma_desc_list *list, ++ enum vpdma_channel chan); ++void vpdma_add_out_dtd(struct vpdma_desc_list *list, struct v4l2_rect *c_rect, ++ const struct vpdma_data_format *fmt, dma_addr_t dma_addr, ++ enum vpdma_channel chan, u32 flags); ++void vpdma_add_in_dtd(struct vpdma_desc_list *list, int frame_width, ++ int frame_height, struct v4l2_rect *c_rect, ++ const struct vpdma_data_format *fmt, dma_addr_t dma_addr, ++ enum vpdma_channel chan, int field, u32 flags); ++ ++/* vpdma list interrupt management */ ++void vpdma_enable_list_complete_irq(struct vpdma_data *vpdma, int list_num, ++ bool enable); ++void vpdma_clear_list_stat(struct vpdma_data *vpdma); ++ ++/* vpdma client configuration */ ++void vpdma_set_line_mode(struct vpdma_data *vpdma, int line_mode, ++ enum vpdma_channel chan); ++void vpdma_set_frame_start_event(struct vpdma_data *vpdma, ++ enum vpdma_frame_start_event fs_event, enum vpdma_channel chan); ++ ++void vpdma_dump_regs(struct vpdma_data *vpdma); ++ ++/* initialize vpdma, passed with VPE's platform device pointer */ ++struct vpdma_data *vpdma_create(struct platform_device *pdev); ++ ++#endif +--- /dev/null ++++ b/drivers/media/platform/ti-vpe/vpdma_priv.h +@@ -0,0 +1,641 @@ ++/* ++ * Copyright (c) 2013 Texas Instruments Inc. ++ * ++ * David Griego, <dagriego@biglakesoftware.com> ++ * Dale Farnsworth, <dale@farnsworth.org> ++ * Archit Taneja, <archit@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 _TI_VPDMA_PRIV_H_ ++#define _TI_VPDMA_PRIV_H_ ++ ++/* ++ * VPDMA Register offsets ++ */ ++ ++/* Top level */ ++#define VPDMA_PID 0x00 ++#define VPDMA_LIST_ADDR 0x04 ++#define VPDMA_LIST_ATTR 0x08 ++#define VPDMA_LIST_STAT_SYNC 0x0c ++#define VPDMA_BG_RGB 0x18 ++#define VPDMA_BG_YUV 0x1c ++#define VPDMA_SETUP 0x30 ++#define VPDMA_MAX_SIZE1 0x34 ++#define VPDMA_MAX_SIZE2 0x38 ++#define VPDMA_MAX_SIZE3 0x3c ++ ++/* Interrupts */ ++#define VPDMA_INT_CHAN_STAT(grp) (0x40 + grp * 8) ++#define VPDMA_INT_CHAN_MASK(grp) (VPDMA_INT_CHAN_STAT(grp) + 4) ++#define VPDMA_INT_CLIENT0_STAT 0x78 ++#define VPDMA_INT_CLIENT0_MASK 0x7c ++#define VPDMA_INT_CLIENT1_STAT 0x80 ++#define VPDMA_INT_CLIENT1_MASK 0x84 ++#define VPDMA_INT_LIST0_STAT 0x88 ++#define VPDMA_INT_LIST0_MASK 0x8c ++ ++#define VPDMA_PERFMON(i) (0x200 + i * 4) ++ ++/* VPE specific client registers */ ++#define VPDMA_DEI_CHROMA1_CSTAT 0x0300 ++#define VPDMA_DEI_LUMA1_CSTAT 0x0304 ++#define VPDMA_DEI_LUMA2_CSTAT 0x0308 ++#define VPDMA_DEI_CHROMA2_CSTAT 0x030c ++#define VPDMA_DEI_LUMA3_CSTAT 0x0310 ++#define VPDMA_DEI_CHROMA3_CSTAT 0x0314 ++#define VPDMA_DEI_MV_IN_CSTAT 0x0330 ++#define VPDMA_DEI_MV_OUT_CSTAT 0x033c ++#define VPDMA_VIP_UP_Y_CSTAT 0x0390 ++#define VPDMA_VIP_UP_UV_CSTAT 0x0394 ++#define VPDMA_VPI_CTL_CSTAT 0x03d0 ++ ++/* Reg field info for VPDMA_CLIENT_CSTAT registers */ ++#define VPDMA_CSTAT_LINE_MODE_MASK 0x03 ++#define VPDMA_CSTAT_LINE_MODE_SHIFT 8 ++#define VPDMA_CSTAT_FRAME_START_MASK 0xf ++#define VPDMA_CSTAT_FRAME_START_SHIFT 10 ++ ++#define VPDMA_LIST_NUM_MASK 0x07 ++#define VPDMA_LIST_NUM_SHFT 24 ++#define VPDMA_LIST_STOP_SHFT 20 ++#define VPDMA_LIST_RDY_MASK 0x01 ++#define VPDMA_LIST_RDY_SHFT 19 ++#define VPDMA_LIST_TYPE_MASK 0x03 ++#define VPDMA_LIST_TYPE_SHFT 16 ++#define VPDMA_LIST_SIZE_MASK 0xffff ++ ++/* VPDMA data type values for data formats */ ++#define DATA_TYPE_Y444 0x0 ++#define DATA_TYPE_Y422 0x1 ++#define DATA_TYPE_Y420 0x2 ++#define DATA_TYPE_C444 0x4 ++#define DATA_TYPE_C422 0x5 ++#define DATA_TYPE_C420 0x6 ++#define DATA_TYPE_YC422 0x7 ++#define DATA_TYPE_YC444 0x8 ++#define DATA_TYPE_CY422 0x23 ++ ++#define DATA_TYPE_RGB16_565 0x0 ++#define DATA_TYPE_ARGB_1555 0x1 ++#define DATA_TYPE_ARGB_4444 0x2 ++#define DATA_TYPE_RGBA_5551 0x3 ++#define DATA_TYPE_RGBA_4444 0x4 ++#define DATA_TYPE_ARGB24_6666 0x5 ++#define DATA_TYPE_RGB24_888 0x6 ++#define DATA_TYPE_ARGB32_8888 0x7 ++#define DATA_TYPE_RGBA24_6666 0x8 ++#define DATA_TYPE_RGBA32_8888 0x9 ++#define DATA_TYPE_BGR16_565 0x10 ++#define DATA_TYPE_ABGR_1555 0x11 ++#define DATA_TYPE_ABGR_4444 0x12 ++#define DATA_TYPE_BGRA_5551 0x13 ++#define DATA_TYPE_BGRA_4444 0x14 ++#define DATA_TYPE_ABGR24_6666 0x15 ++#define DATA_TYPE_BGR24_888 0x16 ++#define DATA_TYPE_ABGR32_8888 0x17 ++#define DATA_TYPE_BGRA24_6666 0x18 ++#define DATA_TYPE_BGRA32_8888 0x19 ++ ++#define DATA_TYPE_MV 0x3 ++ ++/* VPDMA channel numbers(only VPE channels for now) */ ++#define VPE_CHAN_NUM_LUMA1_IN 0 ++#define VPE_CHAN_NUM_CHROMA1_IN 1 ++#define VPE_CHAN_NUM_LUMA2_IN 2 ++#define VPE_CHAN_NUM_CHROMA2_IN 3 ++#define VPE_CHAN_NUM_LUMA3_IN 4 ++#define VPE_CHAN_NUM_CHROMA3_IN 5 ++#define VPE_CHAN_NUM_MV_IN 12 ++#define VPE_CHAN_NUM_MV_OUT 15 ++#define VPE_CHAN_NUM_LUMA_OUT 102 ++#define VPE_CHAN_NUM_CHROMA_OUT 103 ++#define VPE_CHAN_NUM_RGB_OUT 106 ++ ++/* ++ * a VPDMA address data block payload for a configuration descriptor needs to ++ * have each sub block length as a multiple of 16 bytes. Therefore, the overall ++ * size of the payload also needs to be a multiple of 16 bytes. The sub block ++ * lengths should be ensured to be aligned by the VPDMA user. ++ */ ++#define VPDMA_ADB_SIZE_ALIGN 0x0f ++ ++/* ++ * data transfer descriptor ++ */ ++struct vpdma_dtd { ++ u32 type_ctl_stride; ++ union { ++ u32 xfer_length_height; ++ u32 w1; ++ }; ++ dma_addr_t start_addr; ++ u32 pkt_ctl; ++ union { ++ u32 frame_width_height; /* inbound */ ++ dma_addr_t desc_write_addr; /* outbound */ ++ }; ++ union { ++ u32 start_h_v; /* inbound */ ++ u32 max_width_height; /* outbound */ ++ }; ++ u32 client_attr0; ++ u32 client_attr1; ++}; ++ ++/* Data Transfer Descriptor specifics */ ++#define DTD_NO_NOTIFY 0 ++#define DTD_NOTIFY 1 ++ ++#define DTD_PKT_TYPE 0xa ++#define DTD_DIR_IN 0 ++#define DTD_DIR_OUT 1 ++ ++/* type_ctl_stride */ ++#define DTD_DATA_TYPE_MASK 0x3f ++#define DTD_DATA_TYPE_SHFT 26 ++#define DTD_NOTIFY_MASK 0x01 ++#define DTD_NOTIFY_SHFT 25 ++#define DTD_FIELD_MASK 0x01 ++#define DTD_FIELD_SHFT 24 ++#define DTD_1D_MASK 0x01 ++#define DTD_1D_SHFT 23 ++#define DTD_EVEN_LINE_SKIP_MASK 0x01 ++#define DTD_EVEN_LINE_SKIP_SHFT 20 ++#define DTD_ODD_LINE_SKIP_MASK 0x01 ++#define DTD_ODD_LINE_SKIP_SHFT 16 ++#define DTD_LINE_STRIDE_MASK 0xffff ++#define DTD_LINE_STRIDE_SHFT 0 ++ ++/* xfer_length_height */ ++#define DTD_LINE_LENGTH_MASK 0xffff ++#define DTD_LINE_LENGTH_SHFT 16 ++#define DTD_XFER_HEIGHT_MASK 0xffff ++#define DTD_XFER_HEIGHT_SHFT 0 ++ ++/* pkt_ctl */ ++#define DTD_PKT_TYPE_MASK 0x1f ++#define DTD_PKT_TYPE_SHFT 27 ++#define DTD_MODE_MASK 0x01 ++#define DTD_MODE_SHFT 26 ++#define DTD_DIR_MASK 0x01 ++#define DTD_DIR_SHFT 25 ++#define DTD_CHAN_MASK 0x01ff ++#define DTD_CHAN_SHFT 16 ++#define DTD_PRI_MASK 0x0f ++#define DTD_PRI_SHFT 9 ++#define DTD_NEXT_CHAN_MASK 0x01ff ++#define DTD_NEXT_CHAN_SHFT 0 ++ ++/* frame_width_height */ ++#define DTD_FRAME_WIDTH_MASK 0xffff ++#define DTD_FRAME_WIDTH_SHFT 16 ++#define DTD_FRAME_HEIGHT_MASK 0xffff ++#define DTD_FRAME_HEIGHT_SHFT 0 ++ ++/* start_h_v */ ++#define DTD_H_START_MASK 0xffff ++#define DTD_H_START_SHFT 16 ++#define DTD_V_START_MASK 0xffff ++#define DTD_V_START_SHFT 0 ++ ++#define DTD_DESC_START_SHIFT 5 ++#define DTD_WRITE_DESC_MASK 0x01 ++#define DTD_WRITE_DESC_SHIFT 2 ++#define DTD_DROP_DATA_MASK 0x01 ++#define DTD_DROP_DATA_SHIFT 1 ++#define DTD_USE_DESC_MASK 0x01 ++#define DTD_USE_DESC_SHIFT 0 ++ ++/* max_width_height */ ++#define DTD_MAX_WIDTH_MASK 0x07 ++#define DTD_MAX_WIDTH_SHFT 4 ++#define DTD_MAX_HEIGHT_MASK 0x07 ++#define DTD_MAX_HEIGHT_SHFT 0 ++ ++/* max width configurations */ ++ /* unlimited width */ ++#define MAX_OUT_WIDTH_UNLIMITED 0 ++/* as specified in max_size1 reg */ ++#define MAX_OUT_WIDTH_REG1 1 ++/* as specified in max_size2 reg */ ++#define MAX_OUT_WIDTH_REG2 2 ++/* as specified in max_size3 reg */ ++#define MAX_OUT_WIDTH_REG3 3 ++/* maximum of 352 pixels as width */ ++#define MAX_OUT_WIDTH_352 4 ++/* maximum of 768 pixels as width */ ++#define MAX_OUT_WIDTH_768 5 ++/* maximum of 1280 pixels width */ ++#define MAX_OUT_WIDTH_1280 6 ++/* maximum of 1920 pixels as width */ ++#define MAX_OUT_WIDTH_1920 7 ++ ++/* max height configurations */ ++ /* unlimited height */ ++#define MAX_OUT_HEIGHT_UNLIMITED 0 ++/* as specified in max_size1 reg */ ++#define MAX_OUT_HEIGHT_REG1 1 ++/* as specified in max_size2 reg */ ++#define MAX_OUT_HEIGHT_REG2 2 ++/* as specified in max_size3 reg */ ++#define MAX_OUT_HEIGHT_REG3 3 ++/* maximum of 288 lines as height */ ++#define MAX_OUT_HEIGHT_288 4 ++/* maximum of 576 lines as height */ ++#define MAX_OUT_HEIGHT_576 5 ++/* maximum of 720 lines as height */ ++#define MAX_OUT_HEIGHT_720 6 ++/* maximum of 1080 lines as height */ ++#define MAX_OUT_HEIGHT_1080 7 ++ ++static inline u32 dtd_type_ctl_stride(int type, bool notify, int field, ++ bool one_d, bool even_line_skip, bool odd_line_skip, ++ int line_stride) ++{ ++ return (type << DTD_DATA_TYPE_SHFT) | (notify << DTD_NOTIFY_SHFT) | ++ (field << DTD_FIELD_SHFT) | (one_d << DTD_1D_SHFT) | ++ (even_line_skip << DTD_EVEN_LINE_SKIP_SHFT) | ++ (odd_line_skip << DTD_ODD_LINE_SKIP_SHFT) | ++ line_stride; ++} ++ ++static inline u32 dtd_xfer_length_height(int line_length, int xfer_height) ++{ ++ return (line_length << DTD_LINE_LENGTH_SHFT) | xfer_height; ++} ++ ++static inline u32 dtd_pkt_ctl(bool mode, bool dir, int chan, int pri, ++ int next_chan) ++{ ++ return (DTD_PKT_TYPE << DTD_PKT_TYPE_SHFT) | (mode << DTD_MODE_SHFT) | ++ (dir << DTD_DIR_SHFT) | (chan << DTD_CHAN_SHFT) | ++ (pri << DTD_PRI_SHFT) | next_chan; ++} ++ ++static inline u32 dtd_frame_width_height(int width, int height) ++{ ++ return (width << DTD_FRAME_WIDTH_SHFT) | height; ++} ++ ++static inline u32 dtd_desc_write_addr(unsigned int addr, bool write_desc, ++ bool drop_data, bool use_desc) ++{ ++ return (addr << DTD_DESC_START_SHIFT) | ++ (write_desc << DTD_WRITE_DESC_SHIFT) | ++ (drop_data << DTD_DROP_DATA_SHIFT) | ++ use_desc; ++} ++ ++static inline u32 dtd_start_h_v(int h_start, int v_start) ++{ ++ return (h_start << DTD_H_START_SHFT) | v_start; ++} ++ ++static inline u32 dtd_max_width_height(int max_width, int max_height) ++{ ++ return (max_width << DTD_MAX_WIDTH_SHFT) | max_height; ++} ++ ++static inline int dtd_get_data_type(struct vpdma_dtd *dtd) ++{ ++ return dtd->type_ctl_stride >> DTD_DATA_TYPE_SHFT; ++} ++ ++static inline bool dtd_get_notify(struct vpdma_dtd *dtd) ++{ ++ return (dtd->type_ctl_stride >> DTD_NOTIFY_SHFT) & DTD_NOTIFY_MASK; ++} ++ ++static inline int dtd_get_field(struct vpdma_dtd *dtd) ++{ ++ return (dtd->type_ctl_stride >> DTD_FIELD_SHFT) & DTD_FIELD_MASK; ++} ++ ++static inline bool dtd_get_1d(struct vpdma_dtd *dtd) ++{ ++ return (dtd->type_ctl_stride >> DTD_1D_SHFT) & DTD_1D_MASK; ++} ++ ++static inline bool dtd_get_even_line_skip(struct vpdma_dtd *dtd) ++{ ++ return (dtd->type_ctl_stride >> DTD_EVEN_LINE_SKIP_SHFT) ++ & DTD_EVEN_LINE_SKIP_MASK; ++} ++ ++static inline bool dtd_get_odd_line_skip(struct vpdma_dtd *dtd) ++{ ++ return (dtd->type_ctl_stride >> DTD_ODD_LINE_SKIP_SHFT) ++ & DTD_ODD_LINE_SKIP_MASK; ++} ++ ++static inline int dtd_get_line_stride(struct vpdma_dtd *dtd) ++{ ++ return dtd->type_ctl_stride & DTD_LINE_STRIDE_MASK; ++} ++ ++static inline int dtd_get_line_length(struct vpdma_dtd *dtd) ++{ ++ return dtd->xfer_length_height >> DTD_LINE_LENGTH_SHFT; ++} ++ ++static inline int dtd_get_xfer_height(struct vpdma_dtd *dtd) ++{ ++ return dtd->xfer_length_height & DTD_XFER_HEIGHT_MASK; ++} ++ ++static inline int dtd_get_pkt_type(struct vpdma_dtd *dtd) ++{ ++ return dtd->pkt_ctl >> DTD_PKT_TYPE_SHFT; ++} ++ ++static inline bool dtd_get_mode(struct vpdma_dtd *dtd) ++{ ++ return (dtd->pkt_ctl >> DTD_MODE_SHFT) & DTD_MODE_MASK; ++} ++ ++static inline bool dtd_get_dir(struct vpdma_dtd *dtd) ++{ ++ return (dtd->pkt_ctl >> DTD_DIR_SHFT) & DTD_DIR_MASK; ++} ++ ++static inline int dtd_get_chan(struct vpdma_dtd *dtd) ++{ ++ return (dtd->pkt_ctl >> DTD_CHAN_SHFT) & DTD_CHAN_MASK; ++} ++ ++static inline int dtd_get_priority(struct vpdma_dtd *dtd) ++{ ++ return (dtd->pkt_ctl >> DTD_PRI_SHFT) & DTD_PRI_MASK; ++} ++ ++static inline int dtd_get_next_chan(struct vpdma_dtd *dtd) ++{ ++ return (dtd->pkt_ctl >> DTD_NEXT_CHAN_SHFT) & DTD_NEXT_CHAN_MASK; ++} ++ ++static inline int dtd_get_frame_width(struct vpdma_dtd *dtd) ++{ ++ return dtd->frame_width_height >> DTD_FRAME_WIDTH_SHFT; ++} ++ ++static inline int dtd_get_frame_height(struct vpdma_dtd *dtd) ++{ ++ return dtd->frame_width_height & DTD_FRAME_HEIGHT_MASK; ++} ++ ++static inline int dtd_get_desc_write_addr(struct vpdma_dtd *dtd) ++{ ++ return dtd->desc_write_addr >> DTD_DESC_START_SHIFT; ++} ++ ++static inline bool dtd_get_write_desc(struct vpdma_dtd *dtd) ++{ ++ return (dtd->desc_write_addr >> DTD_WRITE_DESC_SHIFT) & ++ DTD_WRITE_DESC_MASK; ++} ++ ++static inline bool dtd_get_drop_data(struct vpdma_dtd *dtd) ++{ ++ return (dtd->desc_write_addr >> DTD_DROP_DATA_SHIFT) & ++ DTD_DROP_DATA_MASK; ++} ++ ++static inline bool dtd_get_use_desc(struct vpdma_dtd *dtd) ++{ ++ return dtd->desc_write_addr & DTD_USE_DESC_MASK; ++} ++ ++static inline int dtd_get_h_start(struct vpdma_dtd *dtd) ++{ ++ return dtd->start_h_v >> DTD_H_START_SHFT; ++} ++ ++static inline int dtd_get_v_start(struct vpdma_dtd *dtd) ++{ ++ return dtd->start_h_v & DTD_V_START_MASK; ++} ++ ++static inline int dtd_get_max_width(struct vpdma_dtd *dtd) ++{ ++ return (dtd->max_width_height >> DTD_MAX_WIDTH_SHFT) & ++ DTD_MAX_WIDTH_MASK; ++} ++ ++static inline int dtd_get_max_height(struct vpdma_dtd *dtd) ++{ ++ return (dtd->max_width_height >> DTD_MAX_HEIGHT_SHFT) & ++ DTD_MAX_HEIGHT_MASK; ++} ++ ++/* ++ * configuration descriptor ++ */ ++struct vpdma_cfd { ++ union { ++ u32 dest_addr_offset; ++ u32 w0; ++ }; ++ union { ++ u32 block_len; /* in words */ ++ u32 w1; ++ }; ++ u32 payload_addr; ++ u32 ctl_payload_len; /* in words */ ++}; ++ ++/* Configuration descriptor specifics */ ++ ++#define CFD_PKT_TYPE 0xb ++ ++#define CFD_DIRECT 1 ++#define CFD_INDIRECT 0 ++#define CFD_CLS_ADB 0 ++#define CFD_CLS_BLOCK 1 ++ ++/* block_len */ ++#define CFD__BLOCK_LEN_MASK 0xffff ++#define CFD__BLOCK_LEN_SHFT 0 ++ ++/* ctl_payload_len */ ++#define CFD_PKT_TYPE_MASK 0x1f ++#define CFD_PKT_TYPE_SHFT 27 ++#define CFD_DIRECT_MASK 0x01 ++#define CFD_DIRECT_SHFT 26 ++#define CFD_CLASS_MASK 0x03 ++#define CFD_CLASS_SHFT 24 ++#define CFD_DEST_MASK 0xff ++#define CFD_DEST_SHFT 16 ++#define CFD_PAYLOAD_LEN_MASK 0xffff ++#define CFD_PAYLOAD_LEN_SHFT 0 ++ ++static inline u32 cfd_pkt_payload_len(bool direct, int cls, int dest, ++ int payload_len) ++{ ++ return (CFD_PKT_TYPE << CFD_PKT_TYPE_SHFT) | ++ (direct << CFD_DIRECT_SHFT) | ++ (cls << CFD_CLASS_SHFT) | ++ (dest << CFD_DEST_SHFT) | ++ payload_len; ++} ++ ++static inline int cfd_get_pkt_type(struct vpdma_cfd *cfd) ++{ ++ return cfd->ctl_payload_len >> CFD_PKT_TYPE_SHFT; ++} ++ ++static inline bool cfd_get_direct(struct vpdma_cfd *cfd) ++{ ++ return (cfd->ctl_payload_len >> CFD_DIRECT_SHFT) & CFD_DIRECT_MASK; ++} ++ ++static inline bool cfd_get_class(struct vpdma_cfd *cfd) ++{ ++ return (cfd->ctl_payload_len >> CFD_CLASS_SHFT) & CFD_CLASS_MASK; ++} ++ ++static inline int cfd_get_dest(struct vpdma_cfd *cfd) ++{ ++ return (cfd->ctl_payload_len >> CFD_DEST_SHFT) & CFD_DEST_MASK; ++} ++ ++static inline int cfd_get_payload_len(struct vpdma_cfd *cfd) ++{ ++ return cfd->ctl_payload_len & CFD_PAYLOAD_LEN_MASK; ++} ++ ++/* ++ * control descriptor ++ */ ++struct vpdma_ctd { ++ union { ++ u32 timer_value; ++ u32 list_addr; ++ u32 w0; ++ }; ++ union { ++ u32 pixel_line_count; ++ u32 list_size; ++ u32 w1; ++ }; ++ union { ++ u32 event; ++ u32 fid_ctl; ++ u32 w2; ++ }; ++ u32 type_source_ctl; ++}; ++ ++/* control descriptor types */ ++#define CTD_TYPE_SYNC_ON_CLIENT 0 ++#define CTD_TYPE_SYNC_ON_LIST 1 ++#define CTD_TYPE_SYNC_ON_EXT 2 ++#define CTD_TYPE_SYNC_ON_LM_TIMER 3 ++#define CTD_TYPE_SYNC_ON_CHANNEL 4 ++#define CTD_TYPE_CHNG_CLIENT_IRQ 5 ++#define CTD_TYPE_SEND_IRQ 6 ++#define CTD_TYPE_RELOAD_LIST 7 ++#define CTD_TYPE_ABORT_CHANNEL 8 ++ ++#define CTD_PKT_TYPE 0xc ++ ++/* timer_value */ ++#define CTD_TIMER_VALUE_MASK 0xffff ++#define CTD_TIMER_VALUE_SHFT 0 ++ ++/* pixel_line_count */ ++#define CTD_PIXEL_COUNT_MASK 0xffff ++#define CTD_PIXEL_COUNT_SHFT 16 ++#define CTD_LINE_COUNT_MASK 0xffff ++#define CTD_LINE_COUNT_SHFT 0 ++ ++/* list_size */ ++#define CTD_LIST_SIZE_MASK 0xffff ++#define CTD_LIST_SIZE_SHFT 0 ++ ++/* event */ ++#define CTD_EVENT_MASK 0x0f ++#define CTD_EVENT_SHFT 0 ++ ++/* fid_ctl */ ++#define CTD_FID2_MASK 0x03 ++#define CTD_FID2_SHFT 4 ++#define CTD_FID1_MASK 0x03 ++#define CTD_FID1_SHFT 2 ++#define CTD_FID0_MASK 0x03 ++#define CTD_FID0_SHFT 0 ++ ++/* type_source_ctl */ ++#define CTD_PKT_TYPE_MASK 0x1f ++#define CTD_PKT_TYPE_SHFT 27 ++#define CTD_SOURCE_MASK 0xff ++#define CTD_SOURCE_SHFT 16 ++#define CTD_CONTROL_MASK 0x0f ++#define CTD_CONTROL_SHFT 0 ++ ++static inline u32 ctd_pixel_line_count(int pixel_count, int line_count) ++{ ++ return (pixel_count << CTD_PIXEL_COUNT_SHFT) | line_count; ++} ++ ++static inline u32 ctd_set_fid_ctl(int fid0, int fid1, int fid2) ++{ ++ return (fid2 << CTD_FID2_SHFT) | (fid1 << CTD_FID1_SHFT) | fid0; ++} ++ ++static inline u32 ctd_type_source_ctl(int source, int control) ++{ ++ return (CTD_PKT_TYPE << CTD_PKT_TYPE_SHFT) | ++ (source << CTD_SOURCE_SHFT) | control; ++} ++ ++static inline u32 ctd_get_pixel_count(struct vpdma_ctd *ctd) ++{ ++ return ctd->pixel_line_count >> CTD_PIXEL_COUNT_SHFT; ++} ++ ++static inline int ctd_get_line_count(struct vpdma_ctd *ctd) ++{ ++ return ctd->pixel_line_count & CTD_LINE_COUNT_MASK; ++} ++ ++static inline int ctd_get_event(struct vpdma_ctd *ctd) ++{ ++ return ctd->event & CTD_EVENT_MASK; ++} ++ ++static inline int ctd_get_fid2_ctl(struct vpdma_ctd *ctd) ++{ ++ return (ctd->fid_ctl >> CTD_FID2_SHFT) & CTD_FID2_MASK; ++} ++ ++static inline int ctd_get_fid1_ctl(struct vpdma_ctd *ctd) ++{ ++ return (ctd->fid_ctl >> CTD_FID1_SHFT) & CTD_FID1_MASK; ++} ++ ++static inline int ctd_get_fid0_ctl(struct vpdma_ctd *ctd) ++{ ++ return ctd->fid_ctl & CTD_FID2_MASK; ++} ++ ++static inline int ctd_get_pkt_type(struct vpdma_ctd *ctd) ++{ ++ return ctd->type_source_ctl >> CTD_PKT_TYPE_SHFT; ++} ++ ++static inline int ctd_get_source(struct vpdma_ctd *ctd) ++{ ++ return (ctd->type_source_ctl >> CTD_SOURCE_SHFT) & CTD_SOURCE_MASK; ++} ++ ++static inline int ctd_get_ctl(struct vpdma_ctd *ctd) ++{ ++ return ctd->type_source_ctl & CTD_CONTROL_MASK; ++} ++ ++#endif +--- /dev/null ++++ b/drivers/media/platform/ti-vpe/vpe.c +@@ -0,0 +1,2074 @@ ++/* ++ * TI VPE mem2mem driver, based on the virtual v4l2-mem2mem example driver ++ * ++ * Copyright (c) 2013 Texas Instruments Inc. ++ * David Griego, <dagriego@biglakesoftware.com> ++ * Dale Farnsworth, <dale@farnsworth.org> ++ * Archit Taneja, <archit@ti.com> ++ * ++ * Copyright (c) 2009-2010 Samsung Electronics Co., Ltd. ++ * Pawel Osciak, <pawel@osciak.com> ++ * Marek Szyprowski, <m.szyprowski@samsung.com> ++ * ++ * Based on the virtual v4l2-mem2mem example device ++ * ++ * 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/delay.h> ++#include <linux/dma-mapping.h> ++#include <linux/err.h> ++#include <linux/fs.h> ++#include <linux/interrupt.h> ++#include <linux/io.h> ++#include <linux/ioctl.h> ++#include <linux/module.h> ++#include <linux/platform_device.h> ++#include <linux/pm_runtime.h> ++#include <linux/sched.h> ++#include <linux/slab.h> ++#include <linux/videodev2.h> ++ ++#include <media/v4l2-common.h> ++#include <media/v4l2-ctrls.h> ++#include <media/v4l2-device.h> ++#include <media/v4l2-event.h> ++#include <media/v4l2-ioctl.h> ++#include <media/v4l2-mem2mem.h> ++#include <media/videobuf2-core.h> ++#include <media/videobuf2-dma-contig.h> ++ ++#include "vpdma.h" ++#include "vpe_regs.h" ++ ++#define VPE_MODULE_NAME "vpe" ++ ++/* minimum and maximum frame sizes */ ++#define MIN_W 128 ++#define MIN_H 128 ++#define MAX_W 1920 ++#define MAX_H 1080 ++ ++/* required alignments */ ++#define S_ALIGN 0 /* multiple of 1 */ ++#define H_ALIGN 1 /* multiple of 2 */ ++#define W_ALIGN 1 /* multiple of 2 */ ++ ++/* multiple of 128 bits, line stride, 16 bytes */ ++#define L_ALIGN 4 ++ ++/* flags that indicate a format can be used for capture/output */ ++#define VPE_FMT_TYPE_CAPTURE (1 << 0) ++#define VPE_FMT_TYPE_OUTPUT (1 << 1) ++ ++/* used as plane indices */ ++#define VPE_MAX_PLANES 2 ++#define VPE_LUMA 0 ++#define VPE_CHROMA 1 ++ ++/* per m2m context info */ ++#define VPE_MAX_SRC_BUFS 3 /* need 3 src fields to de-interlace */ ++ ++#define VPE_DEF_BUFS_PER_JOB 1 /* default one buffer per batch job */ ++ ++/* ++ * each VPE context can need up to 3 config desciptors, 7 input descriptors, ++ * 3 output descriptors, and 10 control descriptors ++ */ ++#define VPE_DESC_LIST_SIZE (10 * VPDMA_DTD_DESC_SIZE + \ ++ 13 * VPDMA_CFD_CTD_DESC_SIZE) ++ ++#define vpe_dbg(vpedev, fmt, arg...) \ ++ dev_dbg((vpedev)->v4l2_dev.dev, fmt, ##arg) ++#define vpe_err(vpedev, fmt, arg...) \ ++ dev_err((vpedev)->v4l2_dev.dev, fmt, ##arg) ++ ++struct vpe_us_coeffs { ++ unsigned short anchor_fid0_c0; ++ unsigned short anchor_fid0_c1; ++ unsigned short anchor_fid0_c2; ++ unsigned short anchor_fid0_c3; ++ unsigned short interp_fid0_c0; ++ unsigned short interp_fid0_c1; ++ unsigned short interp_fid0_c2; ++ unsigned short interp_fid0_c3; ++ unsigned short anchor_fid1_c0; ++ unsigned short anchor_fid1_c1; ++ unsigned short anchor_fid1_c2; ++ unsigned short anchor_fid1_c3; ++ unsigned short interp_fid1_c0; ++ unsigned short interp_fid1_c1; ++ unsigned short interp_fid1_c2; ++ unsigned short interp_fid1_c3; ++}; ++ ++/* ++ * Default upsampler coefficients ++ */ ++static const struct vpe_us_coeffs us_coeffs[] = { ++ { ++ /* Coefficients for progressive input */ ++ 0x00C8, 0x0348, 0x0018, 0x3FD8, 0x3FB8, 0x0378, 0x00E8, 0x3FE8, ++ 0x00C8, 0x0348, 0x0018, 0x3FD8, 0x3FB8, 0x0378, 0x00E8, 0x3FE8, ++ }, ++ { ++ /* Coefficients for Top Field Interlaced input */ ++ 0x0051, 0x03D5, 0x3FE3, 0x3FF7, 0x3FB5, 0x02E9, 0x018F, 0x3FD3, ++ /* Coefficients for Bottom Field Interlaced input */ ++ 0x016B, 0x0247, 0x00B1, 0x3F9D, 0x3FCF, 0x03DB, 0x005D, 0x3FF9, ++ }, ++}; ++ ++/* ++ * the following registers are for configuring some of the parameters of the ++ * motion and edge detection blocks inside DEI, these generally remain the same, ++ * these could be passed later via userspace if some one needs to tweak these. ++ */ ++struct vpe_dei_regs { ++ unsigned long mdt_spacial_freq_thr_reg; /* VPE_DEI_REG2 */ ++ unsigned long edi_config_reg; /* VPE_DEI_REG3 */ ++ unsigned long edi_lut_reg0; /* VPE_DEI_REG4 */ ++ unsigned long edi_lut_reg1; /* VPE_DEI_REG5 */ ++ unsigned long edi_lut_reg2; /* VPE_DEI_REG6 */ ++ unsigned long edi_lut_reg3; /* VPE_DEI_REG7 */ ++}; ++ ++/* ++ * default expert DEI register values, unlikely to be modified. ++ */ ++static const struct vpe_dei_regs dei_regs = { ++ 0x020C0804u, ++ 0x0118100Fu, ++ 0x08040200u, ++ 0x1010100Cu, ++ 0x10101010u, ++ 0x10101010u, ++}; ++ ++/* ++ * The port_data structure contains per-port data. ++ */ ++struct vpe_port_data { ++ enum vpdma_channel channel; /* VPDMA channel */ ++ u8 vb_index; /* input frame f, f-1, f-2 index */ ++ u8 vb_part; /* plane index for co-panar formats */ ++}; ++ ++/* ++ * Define indices into the port_data tables ++ */ ++#define VPE_PORT_LUMA1_IN 0 ++#define VPE_PORT_CHROMA1_IN 1 ++#define VPE_PORT_LUMA2_IN 2 ++#define VPE_PORT_CHROMA2_IN 3 ++#define VPE_PORT_LUMA3_IN 4 ++#define VPE_PORT_CHROMA3_IN 5 ++#define VPE_PORT_MV_IN 6 ++#define VPE_PORT_MV_OUT 7 ++#define VPE_PORT_LUMA_OUT 8 ++#define VPE_PORT_CHROMA_OUT 9 ++#define VPE_PORT_RGB_OUT 10 ++ ++static const struct vpe_port_data port_data[11] = { ++ [VPE_PORT_LUMA1_IN] = { ++ .channel = VPE_CHAN_LUMA1_IN, ++ .vb_index = 0, ++ .vb_part = VPE_LUMA, ++ }, ++ [VPE_PORT_CHROMA1_IN] = { ++ .channel = VPE_CHAN_CHROMA1_IN, ++ .vb_index = 0, ++ .vb_part = VPE_CHROMA, ++ }, ++ [VPE_PORT_LUMA2_IN] = { ++ .channel = VPE_CHAN_LUMA2_IN, ++ .vb_index = 1, ++ .vb_part = VPE_LUMA, ++ }, ++ [VPE_PORT_CHROMA2_IN] = { ++ .channel = VPE_CHAN_CHROMA2_IN, ++ .vb_index = 1, ++ .vb_part = VPE_CHROMA, ++ }, ++ [VPE_PORT_LUMA3_IN] = { ++ .channel = VPE_CHAN_LUMA3_IN, ++ .vb_index = 2, ++ .vb_part = VPE_LUMA, ++ }, ++ [VPE_PORT_CHROMA3_IN] = { ++ .channel = VPE_CHAN_CHROMA3_IN, ++ .vb_index = 2, ++ .vb_part = VPE_CHROMA, ++ }, ++ [VPE_PORT_MV_IN] = { ++ .channel = VPE_CHAN_MV_IN, ++ }, ++ [VPE_PORT_MV_OUT] = { ++ .channel = VPE_CHAN_MV_OUT, ++ }, ++ [VPE_PORT_LUMA_OUT] = { ++ .channel = VPE_CHAN_LUMA_OUT, ++ .vb_part = VPE_LUMA, ++ }, ++ [VPE_PORT_CHROMA_OUT] = { ++ .channel = VPE_CHAN_CHROMA_OUT, ++ .vb_part = VPE_CHROMA, ++ }, ++ [VPE_PORT_RGB_OUT] = { ++ .channel = VPE_CHAN_RGB_OUT, ++ .vb_part = VPE_LUMA, ++ }, ++}; ++ ++ ++/* driver info for each of the supported video formats */ ++struct vpe_fmt { ++ char *name; /* human-readable name */ ++ u32 fourcc; /* standard format identifier */ ++ u8 types; /* CAPTURE and/or OUTPUT */ ++ u8 coplanar; /* set for unpacked Luma and Chroma */ ++ /* vpdma format info for each plane */ ++ struct vpdma_data_format const *vpdma_fmt[VPE_MAX_PLANES]; ++}; ++ ++static struct vpe_fmt vpe_formats[] = { ++ { ++ .name = "YUV 422 co-planar", ++ .fourcc = V4L2_PIX_FMT_NV16, ++ .types = VPE_FMT_TYPE_CAPTURE | VPE_FMT_TYPE_OUTPUT, ++ .coplanar = 1, ++ .vpdma_fmt = { &vpdma_yuv_fmts[VPDMA_DATA_FMT_Y444], ++ &vpdma_yuv_fmts[VPDMA_DATA_FMT_C444], ++ }, ++ }, ++ { ++ .name = "YUV 420 co-planar", ++ .fourcc = V4L2_PIX_FMT_NV12, ++ .types = VPE_FMT_TYPE_CAPTURE | VPE_FMT_TYPE_OUTPUT, ++ .coplanar = 1, ++ .vpdma_fmt = { &vpdma_yuv_fmts[VPDMA_DATA_FMT_Y420], ++ &vpdma_yuv_fmts[VPDMA_DATA_FMT_C420], ++ }, ++ }, ++ { ++ .name = "YUYV 422 packed", ++ .fourcc = V4L2_PIX_FMT_YUYV, ++ .types = VPE_FMT_TYPE_CAPTURE | VPE_FMT_TYPE_OUTPUT, ++ .coplanar = 0, ++ .vpdma_fmt = { &vpdma_yuv_fmts[VPDMA_DATA_FMT_YC422], ++ }, ++ }, ++ { ++ .name = "UYVY 422 packed", ++ .fourcc = V4L2_PIX_FMT_UYVY, ++ .types = VPE_FMT_TYPE_CAPTURE | VPE_FMT_TYPE_OUTPUT, ++ .coplanar = 0, ++ .vpdma_fmt = { &vpdma_yuv_fmts[VPDMA_DATA_FMT_CY422], ++ }, ++ }, ++}; ++ ++/* ++ * per-queue, driver-specific private data. ++ * there is one source queue and one destination queue for each m2m context. ++ */ ++struct vpe_q_data { ++ unsigned int width; /* frame width */ ++ unsigned int height; /* frame height */ ++ unsigned int bytesperline[VPE_MAX_PLANES]; /* bytes per line in memory */ ++ enum v4l2_colorspace colorspace; ++ enum v4l2_field field; /* supported field value */ ++ unsigned int flags; ++ unsigned int sizeimage[VPE_MAX_PLANES]; /* image size in memory */ ++ struct v4l2_rect c_rect; /* crop/compose rectangle */ ++ struct vpe_fmt *fmt; /* format info */ ++}; ++ ++/* vpe_q_data flag bits */ ++#define Q_DATA_FRAME_1D (1 << 0) ++#define Q_DATA_MODE_TILED (1 << 1) ++#define Q_DATA_INTERLACED (1 << 2) ++ ++enum { ++ Q_DATA_SRC = 0, ++ Q_DATA_DST = 1, ++}; ++ ++/* find our format description corresponding to the passed v4l2_format */ ++static struct vpe_fmt *find_format(struct v4l2_format *f) ++{ ++ struct vpe_fmt *fmt; ++ unsigned int k; ++ ++ for (k = 0; k < ARRAY_SIZE(vpe_formats); k++) { ++ fmt = &vpe_formats[k]; ++ if (fmt->fourcc == f->fmt.pix.pixelformat) ++ return fmt; ++ } ++ ++ return NULL; ++} ++ ++/* ++ * there is one vpe_dev structure in the driver, it is shared by ++ * all instances. ++ */ ++struct vpe_dev { ++ struct v4l2_device v4l2_dev; ++ struct video_device vfd; ++ struct v4l2_m2m_dev *m2m_dev; ++ ++ atomic_t num_instances; /* count of driver instances */ ++ dma_addr_t loaded_mmrs; /* shadow mmrs in device */ ++ struct mutex dev_mutex; ++ spinlock_t lock; ++ ++ int irq; ++ void __iomem *base; ++ ++ struct vb2_alloc_ctx *alloc_ctx; ++ struct vpdma_data *vpdma; /* vpdma data handle */ ++}; ++ ++/* ++ * There is one vpe_ctx structure for each m2m context. ++ */ ++struct vpe_ctx { ++ struct v4l2_fh fh; ++ struct vpe_dev *dev; ++ struct v4l2_m2m_ctx *m2m_ctx; ++ struct v4l2_ctrl_handler hdl; ++ ++ unsigned int field; /* current field */ ++ unsigned int sequence; /* current frame/field seq */ ++ unsigned int aborting; /* abort after next irq */ ++ ++ unsigned int bufs_per_job; /* input buffers per batch */ ++ unsigned int bufs_completed; /* bufs done in this batch */ ++ ++ struct vpe_q_data q_data[2]; /* src & dst queue data */ ++ struct vb2_buffer *src_vbs[VPE_MAX_SRC_BUFS]; ++ struct vb2_buffer *dst_vb; ++ ++ dma_addr_t mv_buf_dma[2]; /* dma addrs of motion vector in/out bufs */ ++ void *mv_buf[2]; /* virtual addrs of motion vector bufs */ ++ size_t mv_buf_size; /* current motion vector buffer size */ ++ struct vpdma_buf mmr_adb; /* shadow reg addr/data block */ ++ struct vpdma_desc_list desc_list; /* DMA descriptor list */ ++ ++ bool deinterlacing; /* using de-interlacer */ ++ bool load_mmrs; /* have new shadow reg values */ ++ ++ unsigned int src_mv_buf_selector; ++}; ++ ++ ++/* ++ * M2M devices get 2 queues. ++ * Return the queue given the type. ++ */ ++static struct vpe_q_data *get_q_data(struct vpe_ctx *ctx, ++ enum v4l2_buf_type type) ++{ ++ switch (type) { ++ case V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE: ++ return &ctx->q_data[Q_DATA_SRC]; ++ case V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE: ++ return &ctx->q_data[Q_DATA_DST]; ++ default: ++ BUG(); ++ } ++ return NULL; ++} ++ ++static u32 read_reg(struct vpe_dev *dev, int offset) ++{ ++ return ioread32(dev->base + offset); ++} ++ ++static void write_reg(struct vpe_dev *dev, int offset, u32 value) ++{ ++ iowrite32(value, dev->base + offset); ++} ++ ++/* register field read/write helpers */ ++static int get_field(u32 value, u32 mask, int shift) ++{ ++ return (value & (mask << shift)) >> shift; ++} ++ ++static int read_field_reg(struct vpe_dev *dev, int offset, u32 mask, int shift) ++{ ++ return get_field(read_reg(dev, offset), mask, shift); ++} ++ ++static void write_field(u32 *valp, u32 field, u32 mask, int shift) ++{ ++ u32 val = *valp; ++ ++ val &= ~(mask << shift); ++ val |= (field & mask) << shift; ++ *valp = val; ++} ++ ++static void write_field_reg(struct vpe_dev *dev, int offset, u32 field, ++ u32 mask, int shift) ++{ ++ u32 val = read_reg(dev, offset); ++ ++ write_field(&val, field, mask, shift); ++ ++ write_reg(dev, offset, val); ++} ++ ++/* ++ * DMA address/data block for the shadow registers ++ */ ++struct vpe_mmr_adb { ++ struct vpdma_adb_hdr out_fmt_hdr; ++ u32 out_fmt_reg[1]; ++ u32 out_fmt_pad[3]; ++ struct vpdma_adb_hdr us1_hdr; ++ u32 us1_regs[8]; ++ struct vpdma_adb_hdr us2_hdr; ++ u32 us2_regs[8]; ++ struct vpdma_adb_hdr us3_hdr; ++ u32 us3_regs[8]; ++ struct vpdma_adb_hdr dei_hdr; ++ u32 dei_regs[8]; ++ struct vpdma_adb_hdr sc_hdr; ++ u32 sc_regs[1]; ++ u32 sc_pad[3]; ++ struct vpdma_adb_hdr csc_hdr; ++ u32 csc_regs[6]; ++ u32 csc_pad[2]; ++}; ++ ++#define VPE_SET_MMR_ADB_HDR(ctx, hdr, regs, offset_a) \ ++ VPDMA_SET_MMR_ADB_HDR(ctx->mmr_adb, vpe_mmr_adb, hdr, regs, offset_a) ++/* ++ * Set the headers for all of the address/data block structures. ++ */ ++static void init_adb_hdrs(struct vpe_ctx *ctx) ++{ ++ VPE_SET_MMR_ADB_HDR(ctx, out_fmt_hdr, out_fmt_reg, VPE_CLK_FORMAT_SELECT); ++ VPE_SET_MMR_ADB_HDR(ctx, us1_hdr, us1_regs, VPE_US1_R0); ++ VPE_SET_MMR_ADB_HDR(ctx, us2_hdr, us2_regs, VPE_US2_R0); ++ VPE_SET_MMR_ADB_HDR(ctx, us3_hdr, us3_regs, VPE_US3_R0); ++ VPE_SET_MMR_ADB_HDR(ctx, dei_hdr, dei_regs, VPE_DEI_FRAME_SIZE); ++ VPE_SET_MMR_ADB_HDR(ctx, sc_hdr, sc_regs, VPE_SC_MP_SC0); ++ VPE_SET_MMR_ADB_HDR(ctx, csc_hdr, csc_regs, VPE_CSC_CSC00); ++}; ++ ++/* ++ * Allocate or re-allocate the motion vector DMA buffers ++ * There are two buffers, one for input and one for output. ++ * However, the roles are reversed after each field is processed. ++ * In other words, after each field is processed, the previous ++ * output (dst) MV buffer becomes the new input (src) MV buffer. ++ */ ++static int realloc_mv_buffers(struct vpe_ctx *ctx, size_t size) ++{ ++ struct device *dev = ctx->dev->v4l2_dev.dev; ++ ++ if (ctx->mv_buf_size == size) ++ return 0; ++ ++ if (ctx->mv_buf[0]) ++ dma_free_coherent(dev, ctx->mv_buf_size, ctx->mv_buf[0], ++ ctx->mv_buf_dma[0]); ++ ++ if (ctx->mv_buf[1]) ++ dma_free_coherent(dev, ctx->mv_buf_size, ctx->mv_buf[1], ++ ctx->mv_buf_dma[1]); ++ ++ if (size == 0) ++ return 0; ++ ++ ctx->mv_buf[0] = dma_alloc_coherent(dev, size, &ctx->mv_buf_dma[0], ++ GFP_KERNEL); ++ if (!ctx->mv_buf[0]) { ++ vpe_err(ctx->dev, "failed to allocate motion vector buffer\n"); ++ return -ENOMEM; ++ } ++ ++ ctx->mv_buf[1] = dma_alloc_coherent(dev, size, &ctx->mv_buf_dma[1], ++ GFP_KERNEL); ++ if (!ctx->mv_buf[1]) { ++ vpe_err(ctx->dev, "failed to allocate motion vector buffer\n"); ++ dma_free_coherent(dev, size, ctx->mv_buf[0], ++ ctx->mv_buf_dma[0]); ++ ++ return -ENOMEM; ++ } ++ ++ ctx->mv_buf_size = size; ++ ctx->src_mv_buf_selector = 0; ++ ++ return 0; ++} ++ ++static void free_mv_buffers(struct vpe_ctx *ctx) ++{ ++ realloc_mv_buffers(ctx, 0); ++} ++ ++/* ++ * While de-interlacing, we keep the two most recent input buffers ++ * around. This function frees those two buffers when we have ++ * finished processing the current stream. ++ */ ++static void free_vbs(struct vpe_ctx *ctx) ++{ ++ struct vpe_dev *dev = ctx->dev; ++ unsigned long flags; ++ ++ if (ctx->src_vbs[2] == NULL) ++ return; ++ ++ spin_lock_irqsave(&dev->lock, flags); ++ if (ctx->src_vbs[2]) { ++ v4l2_m2m_buf_done(ctx->src_vbs[2], VB2_BUF_STATE_DONE); ++ v4l2_m2m_buf_done(ctx->src_vbs[1], VB2_BUF_STATE_DONE); ++ } ++ spin_unlock_irqrestore(&dev->lock, flags); ++} ++ ++/* ++ * Enable or disable the VPE clocks ++ */ ++static void vpe_set_clock_enable(struct vpe_dev *dev, bool on) ++{ ++ u32 val = 0; ++ ++ if (on) ++ val = VPE_DATA_PATH_CLK_ENABLE | VPE_VPEDMA_CLK_ENABLE; ++ write_reg(dev, VPE_CLK_ENABLE, val); ++} ++ ++static void vpe_top_reset(struct vpe_dev *dev) ++{ ++ ++ write_field_reg(dev, VPE_CLK_RESET, 1, VPE_DATA_PATH_CLK_RESET_MASK, ++ VPE_DATA_PATH_CLK_RESET_SHIFT); ++ ++ usleep_range(100, 150); ++ ++ write_field_reg(dev, VPE_CLK_RESET, 0, VPE_DATA_PATH_CLK_RESET_MASK, ++ VPE_DATA_PATH_CLK_RESET_SHIFT); ++} ++ ++static void vpe_top_vpdma_reset(struct vpe_dev *dev) ++{ ++ write_field_reg(dev, VPE_CLK_RESET, 1, VPE_VPDMA_CLK_RESET_MASK, ++ VPE_VPDMA_CLK_RESET_SHIFT); ++ ++ usleep_range(100, 150); ++ ++ write_field_reg(dev, VPE_CLK_RESET, 0, VPE_VPDMA_CLK_RESET_MASK, ++ VPE_VPDMA_CLK_RESET_SHIFT); ++} ++ ++/* ++ * Load the correct of upsampler coefficients into the shadow MMRs ++ */ ++static void set_us_coefficients(struct vpe_ctx *ctx) ++{ ++ struct vpe_mmr_adb *mmr_adb = ctx->mmr_adb.addr; ++ struct vpe_q_data *s_q_data = &ctx->q_data[Q_DATA_SRC]; ++ u32 *us1_reg = &mmr_adb->us1_regs[0]; ++ u32 *us2_reg = &mmr_adb->us2_regs[0]; ++ u32 *us3_reg = &mmr_adb->us3_regs[0]; ++ const unsigned short *cp, *end_cp; ++ ++ cp = &us_coeffs[0].anchor_fid0_c0; ++ ++ if (s_q_data->flags & Q_DATA_INTERLACED) /* interlaced */ ++ cp += sizeof(us_coeffs[0]) / sizeof(*cp); ++ ++ end_cp = cp + sizeof(us_coeffs[0]) / sizeof(*cp); ++ ++ while (cp < end_cp) { ++ write_field(us1_reg, *cp++, VPE_US_C0_MASK, VPE_US_C0_SHIFT); ++ write_field(us1_reg, *cp++, VPE_US_C1_MASK, VPE_US_C1_SHIFT); ++ *us2_reg++ = *us1_reg; ++ *us3_reg++ = *us1_reg++; ++ } ++ ctx->load_mmrs = true; ++} ++ ++/* ++ * Set the upsampler config mode and the VPDMA line mode in the shadow MMRs. ++ */ ++static void set_cfg_and_line_modes(struct vpe_ctx *ctx) ++{ ++ struct vpe_fmt *fmt = ctx->q_data[Q_DATA_SRC].fmt; ++ struct vpe_mmr_adb *mmr_adb = ctx->mmr_adb.addr; ++ u32 *us1_reg0 = &mmr_adb->us1_regs[0]; ++ u32 *us2_reg0 = &mmr_adb->us2_regs[0]; ++ u32 *us3_reg0 = &mmr_adb->us3_regs[0]; ++ int line_mode = 1; ++ int cfg_mode = 1; ++ ++ /* ++ * Cfg Mode 0: YUV420 source, enable upsampler, DEI is de-interlacing. ++ * Cfg Mode 1: YUV422 source, disable upsampler, DEI is de-interlacing. ++ */ ++ ++ if (fmt->fourcc == V4L2_PIX_FMT_NV12) { ++ cfg_mode = 0; ++ line_mode = 0; /* double lines to line buffer */ ++ } ++ ++ write_field(us1_reg0, cfg_mode, VPE_US_MODE_MASK, VPE_US_MODE_SHIFT); ++ write_field(us2_reg0, cfg_mode, VPE_US_MODE_MASK, VPE_US_MODE_SHIFT); ++ write_field(us3_reg0, cfg_mode, VPE_US_MODE_MASK, VPE_US_MODE_SHIFT); ++ ++ /* regs for now */ ++ vpdma_set_line_mode(ctx->dev->vpdma, line_mode, VPE_CHAN_CHROMA1_IN); ++ vpdma_set_line_mode(ctx->dev->vpdma, line_mode, VPE_CHAN_CHROMA2_IN); ++ vpdma_set_line_mode(ctx->dev->vpdma, line_mode, VPE_CHAN_CHROMA3_IN); ++ ++ /* frame start for input luma */ ++ vpdma_set_frame_start_event(ctx->dev->vpdma, VPDMA_FSEVENT_CHANNEL_ACTIVE, ++ VPE_CHAN_LUMA1_IN); ++ vpdma_set_frame_start_event(ctx->dev->vpdma, VPDMA_FSEVENT_CHANNEL_ACTIVE, ++ VPE_CHAN_LUMA2_IN); ++ vpdma_set_frame_start_event(ctx->dev->vpdma, VPDMA_FSEVENT_CHANNEL_ACTIVE, ++ VPE_CHAN_LUMA3_IN); ++ ++ /* frame start for input chroma */ ++ vpdma_set_frame_start_event(ctx->dev->vpdma, VPDMA_FSEVENT_CHANNEL_ACTIVE, ++ VPE_CHAN_CHROMA1_IN); ++ vpdma_set_frame_start_event(ctx->dev->vpdma, VPDMA_FSEVENT_CHANNEL_ACTIVE, ++ VPE_CHAN_CHROMA2_IN); ++ vpdma_set_frame_start_event(ctx->dev->vpdma, VPDMA_FSEVENT_CHANNEL_ACTIVE, ++ VPE_CHAN_CHROMA3_IN); ++ ++ /* frame start for MV in client */ ++ vpdma_set_frame_start_event(ctx->dev->vpdma, VPDMA_FSEVENT_CHANNEL_ACTIVE, ++ VPE_CHAN_MV_IN); ++ ++ ctx->load_mmrs = true; ++} ++ ++/* ++ * Set the shadow registers that are modified when the source ++ * format changes. ++ */ ++static void set_src_registers(struct vpe_ctx *ctx) ++{ ++ set_us_coefficients(ctx); ++} ++ ++/* ++ * Set the shadow registers that are modified when the destination ++ * format changes. ++ */ ++static void set_dst_registers(struct vpe_ctx *ctx) ++{ ++ struct vpe_mmr_adb *mmr_adb = ctx->mmr_adb.addr; ++ struct vpe_fmt *fmt = ctx->q_data[Q_DATA_DST].fmt; ++ u32 val = 0; ++ ++ /* select RGB path when color space conversion is supported in future */ ++ if (fmt->fourcc == V4L2_PIX_FMT_RGB24) ++ val |= VPE_RGB_OUT_SELECT | VPE_CSC_SRC_DEI_SCALER; ++ else if (fmt->fourcc == V4L2_PIX_FMT_NV16) ++ val |= VPE_COLOR_SEPARATE_422; ++ ++ /* The source of CHR_DS is always the scaler, whether it's used or not */ ++ val |= VPE_DS_SRC_DEI_SCALER; ++ ++ if (fmt->fourcc != V4L2_PIX_FMT_NV12) ++ val |= VPE_DS_BYPASS; ++ ++ mmr_adb->out_fmt_reg[0] = val; ++ ++ ctx->load_mmrs = true; ++} ++ ++/* ++ * Set the de-interlacer shadow register values ++ */ ++static void set_dei_regs(struct vpe_ctx *ctx) ++{ ++ struct vpe_mmr_adb *mmr_adb = ctx->mmr_adb.addr; ++ struct vpe_q_data *s_q_data = &ctx->q_data[Q_DATA_SRC]; ++ unsigned int src_h = s_q_data->c_rect.height; ++ unsigned int src_w = s_q_data->c_rect.width; ++ u32 *dei_mmr0 = &mmr_adb->dei_regs[0]; ++ bool deinterlace = true; ++ u32 val = 0; ++ ++ /* ++ * according to TRM, we should set DEI in progressive bypass mode when ++ * the input content is progressive, however, DEI is bypassed correctly ++ * for both progressive and interlace content in interlace bypass mode. ++ * It has been recommended not to use progressive bypass mode. ++ */ ++ if ((!ctx->deinterlacing && (s_q_data->flags & Q_DATA_INTERLACED)) || ++ !(s_q_data->flags & Q_DATA_INTERLACED)) { ++ deinterlace = false; ++ val = VPE_DEI_INTERLACE_BYPASS; ++ } ++ ++ src_h = deinterlace ? src_h * 2 : src_h; ++ ++ val |= (src_h << VPE_DEI_HEIGHT_SHIFT) | ++ (src_w << VPE_DEI_WIDTH_SHIFT) | ++ VPE_DEI_FIELD_FLUSH; ++ ++ *dei_mmr0 = val; ++ ++ ctx->load_mmrs = true; ++} ++ ++static void set_dei_shadow_registers(struct vpe_ctx *ctx) ++{ ++ struct vpe_mmr_adb *mmr_adb = ctx->mmr_adb.addr; ++ u32 *dei_mmr = &mmr_adb->dei_regs[0]; ++ const struct vpe_dei_regs *cur = &dei_regs; ++ ++ dei_mmr[2] = cur->mdt_spacial_freq_thr_reg; ++ dei_mmr[3] = cur->edi_config_reg; ++ dei_mmr[4] = cur->edi_lut_reg0; ++ dei_mmr[5] = cur->edi_lut_reg1; ++ dei_mmr[6] = cur->edi_lut_reg2; ++ dei_mmr[7] = cur->edi_lut_reg3; ++ ++ ctx->load_mmrs = true; ++} ++ ++static void set_csc_coeff_bypass(struct vpe_ctx *ctx) ++{ ++ struct vpe_mmr_adb *mmr_adb = ctx->mmr_adb.addr; ++ u32 *shadow_csc_reg5 = &mmr_adb->csc_regs[5]; ++ ++ *shadow_csc_reg5 |= VPE_CSC_BYPASS; ++ ++ ctx->load_mmrs = true; ++} ++ ++static void set_sc_regs_bypass(struct vpe_ctx *ctx) ++{ ++ struct vpe_mmr_adb *mmr_adb = ctx->mmr_adb.addr; ++ u32 *sc_reg0 = &mmr_adb->sc_regs[0]; ++ u32 val = 0; ++ ++ val |= VPE_SC_BYPASS; ++ *sc_reg0 = val; ++ ++ ctx->load_mmrs = true; ++} ++ ++/* ++ * Set the shadow registers whose values are modified when either the ++ * source or destination format is changed. ++ */ ++static int set_srcdst_params(struct vpe_ctx *ctx) ++{ ++ struct vpe_q_data *s_q_data = &ctx->q_data[Q_DATA_SRC]; ++ struct vpe_q_data *d_q_data = &ctx->q_data[Q_DATA_DST]; ++ size_t mv_buf_size; ++ int ret; ++ ++ ctx->sequence = 0; ++ ctx->field = V4L2_FIELD_TOP; ++ ++ if ((s_q_data->flags & Q_DATA_INTERLACED) && ++ !(d_q_data->flags & Q_DATA_INTERLACED)) { ++ const struct vpdma_data_format *mv = ++ &vpdma_misc_fmts[VPDMA_DATA_FMT_MV]; ++ ++ ctx->deinterlacing = 1; ++ mv_buf_size = ++ (s_q_data->width * s_q_data->height * mv->depth) >> 3; ++ } else { ++ ctx->deinterlacing = 0; ++ mv_buf_size = 0; ++ } ++ ++ free_vbs(ctx); ++ ++ ret = realloc_mv_buffers(ctx, mv_buf_size); ++ if (ret) ++ return ret; ++ ++ set_cfg_and_line_modes(ctx); ++ set_dei_regs(ctx); ++ set_csc_coeff_bypass(ctx); ++ set_sc_regs_bypass(ctx); ++ ++ return 0; ++} ++ ++/* ++ * Return the vpe_ctx structure for a given struct file ++ */ ++static struct vpe_ctx *file2ctx(struct file *file) ++{ ++ return container_of(file->private_data, struct vpe_ctx, fh); ++} ++ ++/* ++ * mem2mem callbacks ++ */ ++ ++/** ++ * job_ready() - check whether an instance is ready to be scheduled to run ++ */ ++static int job_ready(void *priv) ++{ ++ struct vpe_ctx *ctx = priv; ++ int needed = ctx->bufs_per_job; ++ ++ if (ctx->deinterlacing && ctx->src_vbs[2] == NULL) ++ needed += 2; /* need additional two most recent fields */ ++ ++ if (v4l2_m2m_num_src_bufs_ready(ctx->m2m_ctx) < needed) ++ return 0; ++ ++ return 1; ++} ++ ++static void job_abort(void *priv) ++{ ++ struct vpe_ctx *ctx = priv; ++ ++ /* Will cancel the transaction in the next interrupt handler */ ++ ctx->aborting = 1; ++} ++ ++/* ++ * Lock access to the device ++ */ ++static void vpe_lock(void *priv) ++{ ++ struct vpe_ctx *ctx = priv; ++ struct vpe_dev *dev = ctx->dev; ++ mutex_lock(&dev->dev_mutex); ++} ++ ++static void vpe_unlock(void *priv) ++{ ++ struct vpe_ctx *ctx = priv; ++ struct vpe_dev *dev = ctx->dev; ++ mutex_unlock(&dev->dev_mutex); ++} ++ ++static void vpe_dump_regs(struct vpe_dev *dev) ++{ ++#define DUMPREG(r) vpe_dbg(dev, "%-35s %08x\n", #r, read_reg(dev, VPE_##r)) ++ ++ vpe_dbg(dev, "VPE Registers:\n"); ++ ++ DUMPREG(PID); ++ DUMPREG(SYSCONFIG); ++ DUMPREG(INT0_STATUS0_RAW); ++ DUMPREG(INT0_STATUS0); ++ DUMPREG(INT0_ENABLE0); ++ DUMPREG(INT0_STATUS1_RAW); ++ DUMPREG(INT0_STATUS1); ++ DUMPREG(INT0_ENABLE1); ++ DUMPREG(CLK_ENABLE); ++ DUMPREG(CLK_RESET); ++ DUMPREG(CLK_FORMAT_SELECT); ++ DUMPREG(CLK_RANGE_MAP); ++ DUMPREG(US1_R0); ++ DUMPREG(US1_R1); ++ DUMPREG(US1_R2); ++ DUMPREG(US1_R3); ++ DUMPREG(US1_R4); ++ DUMPREG(US1_R5); ++ DUMPREG(US1_R6); ++ DUMPREG(US1_R7); ++ DUMPREG(US2_R0); ++ DUMPREG(US2_R1); ++ DUMPREG(US2_R2); ++ DUMPREG(US2_R3); ++ DUMPREG(US2_R4); ++ DUMPREG(US2_R5); ++ DUMPREG(US2_R6); ++ DUMPREG(US2_R7); ++ DUMPREG(US3_R0); ++ DUMPREG(US3_R1); ++ DUMPREG(US3_R2); ++ DUMPREG(US3_R3); ++ DUMPREG(US3_R4); ++ DUMPREG(US3_R5); ++ DUMPREG(US3_R6); ++ DUMPREG(US3_R7); ++ DUMPREG(DEI_FRAME_SIZE); ++ DUMPREG(MDT_BYPASS); ++ DUMPREG(MDT_SF_THRESHOLD); ++ DUMPREG(EDI_CONFIG); ++ DUMPREG(DEI_EDI_LUT_R0); ++ DUMPREG(DEI_EDI_LUT_R1); ++ DUMPREG(DEI_EDI_LUT_R2); ++ DUMPREG(DEI_EDI_LUT_R3); ++ DUMPREG(DEI_FMD_WINDOW_R0); ++ DUMPREG(DEI_FMD_WINDOW_R1); ++ DUMPREG(DEI_FMD_CONTROL_R0); ++ DUMPREG(DEI_FMD_CONTROL_R1); ++ DUMPREG(DEI_FMD_STATUS_R0); ++ DUMPREG(DEI_FMD_STATUS_R1); ++ DUMPREG(DEI_FMD_STATUS_R2); ++ DUMPREG(SC_MP_SC0); ++ DUMPREG(SC_MP_SC1); ++ DUMPREG(SC_MP_SC2); ++ DUMPREG(SC_MP_SC3); ++ DUMPREG(SC_MP_SC4); ++ DUMPREG(SC_MP_SC5); ++ DUMPREG(SC_MP_SC6); ++ DUMPREG(SC_MP_SC8); ++ DUMPREG(SC_MP_SC9); ++ DUMPREG(SC_MP_SC10); ++ DUMPREG(SC_MP_SC11); ++ DUMPREG(SC_MP_SC12); ++ DUMPREG(SC_MP_SC13); ++ DUMPREG(SC_MP_SC17); ++ DUMPREG(SC_MP_SC18); ++ DUMPREG(SC_MP_SC19); ++ DUMPREG(SC_MP_SC20); ++ DUMPREG(SC_MP_SC21); ++ DUMPREG(SC_MP_SC22); ++ DUMPREG(SC_MP_SC23); ++ DUMPREG(SC_MP_SC24); ++ DUMPREG(SC_MP_SC25); ++ DUMPREG(CSC_CSC00); ++ DUMPREG(CSC_CSC01); ++ DUMPREG(CSC_CSC02); ++ DUMPREG(CSC_CSC03); ++ DUMPREG(CSC_CSC04); ++ DUMPREG(CSC_CSC05); ++#undef DUMPREG ++} ++ ++static void add_out_dtd(struct vpe_ctx *ctx, int port) ++{ ++ struct vpe_q_data *q_data = &ctx->q_data[Q_DATA_DST]; ++ const struct vpe_port_data *p_data = &port_data[port]; ++ struct vb2_buffer *vb = ctx->dst_vb; ++ struct v4l2_rect *c_rect = &q_data->c_rect; ++ struct vpe_fmt *fmt = q_data->fmt; ++ const struct vpdma_data_format *vpdma_fmt; ++ int mv_buf_selector = !ctx->src_mv_buf_selector; ++ dma_addr_t dma_addr; ++ u32 flags = 0; ++ ++ if (port == VPE_PORT_MV_OUT) { ++ vpdma_fmt = &vpdma_misc_fmts[VPDMA_DATA_FMT_MV]; ++ dma_addr = ctx->mv_buf_dma[mv_buf_selector]; ++ } else { ++ /* to incorporate interleaved formats */ ++ int plane = fmt->coplanar ? p_data->vb_part : 0; ++ ++ vpdma_fmt = fmt->vpdma_fmt[plane]; ++ dma_addr = vb2_dma_contig_plane_dma_addr(vb, plane); ++ if (!dma_addr) { ++ vpe_err(ctx->dev, ++ "acquiring output buffer(%d) dma_addr failed\n", ++ port); ++ return; ++ } ++ } ++ ++ if (q_data->flags & Q_DATA_FRAME_1D) ++ flags |= VPDMA_DATA_FRAME_1D; ++ if (q_data->flags & Q_DATA_MODE_TILED) ++ flags |= VPDMA_DATA_MODE_TILED; ++ ++ vpdma_add_out_dtd(&ctx->desc_list, c_rect, vpdma_fmt, dma_addr, ++ p_data->channel, flags); ++} ++ ++static void add_in_dtd(struct vpe_ctx *ctx, int port) ++{ ++ struct vpe_q_data *q_data = &ctx->q_data[Q_DATA_SRC]; ++ const struct vpe_port_data *p_data = &port_data[port]; ++ struct vb2_buffer *vb = ctx->src_vbs[p_data->vb_index]; ++ struct v4l2_rect *c_rect = &q_data->c_rect; ++ struct vpe_fmt *fmt = q_data->fmt; ++ const struct vpdma_data_format *vpdma_fmt; ++ int mv_buf_selector = ctx->src_mv_buf_selector; ++ int field = vb->v4l2_buf.field == V4L2_FIELD_BOTTOM; ++ dma_addr_t dma_addr; ++ u32 flags = 0; ++ ++ if (port == VPE_PORT_MV_IN) { ++ vpdma_fmt = &vpdma_misc_fmts[VPDMA_DATA_FMT_MV]; ++ dma_addr = ctx->mv_buf_dma[mv_buf_selector]; ++ } else { ++ /* to incorporate interleaved formats */ ++ int plane = fmt->coplanar ? p_data->vb_part : 0; ++ ++ vpdma_fmt = fmt->vpdma_fmt[plane]; ++ ++ dma_addr = vb2_dma_contig_plane_dma_addr(vb, plane); ++ if (!dma_addr) { ++ vpe_err(ctx->dev, ++ "acquiring input buffer(%d) dma_addr failed\n", ++ port); ++ return; ++ } ++ } ++ ++ if (q_data->flags & Q_DATA_FRAME_1D) ++ flags |= VPDMA_DATA_FRAME_1D; ++ if (q_data->flags & Q_DATA_MODE_TILED) ++ flags |= VPDMA_DATA_MODE_TILED; ++ ++ vpdma_add_in_dtd(&ctx->desc_list, q_data->width, q_data->height, ++ c_rect, vpdma_fmt, dma_addr, p_data->channel, field, flags); ++} ++ ++/* ++ * Enable the expected IRQ sources ++ */ ++static void enable_irqs(struct vpe_ctx *ctx) ++{ ++ write_reg(ctx->dev, VPE_INT0_ENABLE0_SET, VPE_INT0_LIST0_COMPLETE); ++ write_reg(ctx->dev, VPE_INT0_ENABLE1_SET, VPE_DEI_ERROR_INT | ++ VPE_DS1_UV_ERROR_INT); ++ ++ vpdma_enable_list_complete_irq(ctx->dev->vpdma, 0, true); ++} ++ ++static void disable_irqs(struct vpe_ctx *ctx) ++{ ++ write_reg(ctx->dev, VPE_INT0_ENABLE0_CLR, 0xffffffff); ++ write_reg(ctx->dev, VPE_INT0_ENABLE1_CLR, 0xffffffff); ++ ++ vpdma_enable_list_complete_irq(ctx->dev->vpdma, 0, false); ++} ++ ++/* device_run() - prepares and starts the device ++ * ++ * This function is only called when both the source and destination ++ * buffers are in place. ++ */ ++static void device_run(void *priv) ++{ ++ struct vpe_ctx *ctx = priv; ++ struct vpe_q_data *d_q_data = &ctx->q_data[Q_DATA_DST]; ++ ++ if (ctx->deinterlacing && ctx->src_vbs[2] == NULL) { ++ ctx->src_vbs[2] = v4l2_m2m_src_buf_remove(ctx->m2m_ctx); ++ WARN_ON(ctx->src_vbs[2] == NULL); ++ ctx->src_vbs[1] = v4l2_m2m_src_buf_remove(ctx->m2m_ctx); ++ WARN_ON(ctx->src_vbs[1] == NULL); ++ } ++ ++ ctx->src_vbs[0] = v4l2_m2m_src_buf_remove(ctx->m2m_ctx); ++ WARN_ON(ctx->src_vbs[0] == NULL); ++ ctx->dst_vb = v4l2_m2m_dst_buf_remove(ctx->m2m_ctx); ++ WARN_ON(ctx->dst_vb == NULL); ++ ++ /* config descriptors */ ++ if (ctx->dev->loaded_mmrs != ctx->mmr_adb.dma_addr || ctx->load_mmrs) { ++ vpdma_map_desc_buf(ctx->dev->vpdma, &ctx->mmr_adb); ++ vpdma_add_cfd_adb(&ctx->desc_list, CFD_MMR_CLIENT, &ctx->mmr_adb); ++ ctx->dev->loaded_mmrs = ctx->mmr_adb.dma_addr; ++ ctx->load_mmrs = false; ++ } ++ ++ /* output data descriptors */ ++ if (ctx->deinterlacing) ++ add_out_dtd(ctx, VPE_PORT_MV_OUT); ++ ++ add_out_dtd(ctx, VPE_PORT_LUMA_OUT); ++ if (d_q_data->fmt->coplanar) ++ add_out_dtd(ctx, VPE_PORT_CHROMA_OUT); ++ ++ /* input data descriptors */ ++ if (ctx->deinterlacing) { ++ add_in_dtd(ctx, VPE_PORT_LUMA3_IN); ++ add_in_dtd(ctx, VPE_PORT_CHROMA3_IN); ++ ++ add_in_dtd(ctx, VPE_PORT_LUMA2_IN); ++ add_in_dtd(ctx, VPE_PORT_CHROMA2_IN); ++ } ++ ++ add_in_dtd(ctx, VPE_PORT_LUMA1_IN); ++ add_in_dtd(ctx, VPE_PORT_CHROMA1_IN); ++ ++ if (ctx->deinterlacing) ++ add_in_dtd(ctx, VPE_PORT_MV_IN); ++ ++ /* sync on channel control descriptors for input ports */ ++ vpdma_add_sync_on_channel_ctd(&ctx->desc_list, VPE_CHAN_LUMA1_IN); ++ vpdma_add_sync_on_channel_ctd(&ctx->desc_list, VPE_CHAN_CHROMA1_IN); ++ ++ if (ctx->deinterlacing) { ++ vpdma_add_sync_on_channel_ctd(&ctx->desc_list, ++ VPE_CHAN_LUMA2_IN); ++ vpdma_add_sync_on_channel_ctd(&ctx->desc_list, ++ VPE_CHAN_CHROMA2_IN); ++ ++ vpdma_add_sync_on_channel_ctd(&ctx->desc_list, ++ VPE_CHAN_LUMA3_IN); ++ vpdma_add_sync_on_channel_ctd(&ctx->desc_list, ++ VPE_CHAN_CHROMA3_IN); ++ ++ vpdma_add_sync_on_channel_ctd(&ctx->desc_list, VPE_CHAN_MV_IN); ++ } ++ ++ /* sync on channel control descriptors for output ports */ ++ vpdma_add_sync_on_channel_ctd(&ctx->desc_list, VPE_CHAN_LUMA_OUT); ++ if (d_q_data->fmt->coplanar) ++ vpdma_add_sync_on_channel_ctd(&ctx->desc_list, VPE_CHAN_CHROMA_OUT); ++ ++ if (ctx->deinterlacing) ++ vpdma_add_sync_on_channel_ctd(&ctx->desc_list, VPE_CHAN_MV_OUT); ++ ++ enable_irqs(ctx); ++ ++ vpdma_map_desc_buf(ctx->dev->vpdma, &ctx->desc_list.buf); ++ vpdma_submit_descs(ctx->dev->vpdma, &ctx->desc_list); ++} ++ ++static void dei_error(struct vpe_ctx *ctx) ++{ ++ dev_warn(ctx->dev->v4l2_dev.dev, ++ "received DEI error interrupt\n"); ++} ++ ++static void ds1_uv_error(struct vpe_ctx *ctx) ++{ ++ dev_warn(ctx->dev->v4l2_dev.dev, ++ "received downsampler error interrupt\n"); ++} ++ ++static irqreturn_t vpe_irq(int irq_vpe, void *data) ++{ ++ struct vpe_dev *dev = (struct vpe_dev *)data; ++ struct vpe_ctx *ctx; ++ struct vpe_q_data *d_q_data; ++ struct vb2_buffer *s_vb, *d_vb; ++ struct v4l2_buffer *s_buf, *d_buf; ++ unsigned long flags; ++ u32 irqst0, irqst1; ++ ++ irqst0 = read_reg(dev, VPE_INT0_STATUS0); ++ if (irqst0) { ++ write_reg(dev, VPE_INT0_STATUS0_CLR, irqst0); ++ vpe_dbg(dev, "INT0_STATUS0 = 0x%08x\n", irqst0); ++ } ++ ++ irqst1 = read_reg(dev, VPE_INT0_STATUS1); ++ if (irqst1) { ++ write_reg(dev, VPE_INT0_STATUS1_CLR, irqst1); ++ vpe_dbg(dev, "INT0_STATUS1 = 0x%08x\n", irqst1); ++ } ++ ++ ctx = v4l2_m2m_get_curr_priv(dev->m2m_dev); ++ if (!ctx) { ++ vpe_err(dev, "instance released before end of transaction\n"); ++ goto handled; ++ } ++ ++ if (irqst1) { ++ if (irqst1 & VPE_DEI_ERROR_INT) { ++ irqst1 &= ~VPE_DEI_ERROR_INT; ++ dei_error(ctx); ++ } ++ if (irqst1 & VPE_DS1_UV_ERROR_INT) { ++ irqst1 &= ~VPE_DS1_UV_ERROR_INT; ++ ds1_uv_error(ctx); ++ } ++ } ++ ++ if (irqst0) { ++ if (irqst0 & VPE_INT0_LIST0_COMPLETE) ++ vpdma_clear_list_stat(ctx->dev->vpdma); ++ ++ irqst0 &= ~(VPE_INT0_LIST0_COMPLETE); ++ } ++ ++ if (irqst0 | irqst1) { ++ dev_warn(dev->v4l2_dev.dev, "Unexpected interrupt: " ++ "INT0_STATUS0 = 0x%08x, INT0_STATUS1 = 0x%08x\n", ++ irqst0, irqst1); ++ } ++ ++ disable_irqs(ctx); ++ ++ vpdma_unmap_desc_buf(dev->vpdma, &ctx->desc_list.buf); ++ vpdma_unmap_desc_buf(dev->vpdma, &ctx->mmr_adb); ++ ++ vpdma_reset_desc_list(&ctx->desc_list); ++ ++ /* the previous dst mv buffer becomes the next src mv buffer */ ++ ctx->src_mv_buf_selector = !ctx->src_mv_buf_selector; ++ ++ if (ctx->aborting) ++ goto finished; ++ ++ s_vb = ctx->src_vbs[0]; ++ d_vb = ctx->dst_vb; ++ s_buf = &s_vb->v4l2_buf; ++ d_buf = &d_vb->v4l2_buf; ++ ++ d_buf->timestamp = s_buf->timestamp; ++ if (s_buf->flags & V4L2_BUF_FLAG_TIMECODE) { ++ d_buf->flags |= V4L2_BUF_FLAG_TIMECODE; ++ d_buf->timecode = s_buf->timecode; ++ } ++ d_buf->sequence = ctx->sequence; ++ d_buf->field = ctx->field; ++ ++ d_q_data = &ctx->q_data[Q_DATA_DST]; ++ if (d_q_data->flags & Q_DATA_INTERLACED) { ++ if (ctx->field == V4L2_FIELD_BOTTOM) { ++ ctx->sequence++; ++ ctx->field = V4L2_FIELD_TOP; ++ } else { ++ WARN_ON(ctx->field != V4L2_FIELD_TOP); ++ ctx->field = V4L2_FIELD_BOTTOM; ++ } ++ } else { ++ ctx->sequence++; ++ } ++ ++ if (ctx->deinterlacing) ++ s_vb = ctx->src_vbs[2]; ++ ++ spin_lock_irqsave(&dev->lock, flags); ++ v4l2_m2m_buf_done(s_vb, VB2_BUF_STATE_DONE); ++ v4l2_m2m_buf_done(d_vb, VB2_BUF_STATE_DONE); ++ spin_unlock_irqrestore(&dev->lock, flags); ++ ++ if (ctx->deinterlacing) { ++ ctx->src_vbs[2] = ctx->src_vbs[1]; ++ ctx->src_vbs[1] = ctx->src_vbs[0]; ++ } ++ ++ ctx->bufs_completed++; ++ if (ctx->bufs_completed < ctx->bufs_per_job) { ++ device_run(ctx); ++ goto handled; ++ } ++ ++finished: ++ vpe_dbg(ctx->dev, "finishing transaction\n"); ++ ctx->bufs_completed = 0; ++ v4l2_m2m_job_finish(dev->m2m_dev, ctx->m2m_ctx); ++handled: ++ return IRQ_HANDLED; ++} ++ ++/* ++ * video ioctls ++ */ ++static int vpe_querycap(struct file *file, void *priv, ++ struct v4l2_capability *cap) ++{ ++ strncpy(cap->driver, VPE_MODULE_NAME, sizeof(cap->driver) - 1); ++ strncpy(cap->card, VPE_MODULE_NAME, sizeof(cap->card) - 1); ++ strlcpy(cap->bus_info, VPE_MODULE_NAME, sizeof(cap->bus_info)); ++ cap->device_caps = V4L2_CAP_VIDEO_M2M | V4L2_CAP_STREAMING; ++ cap->capabilities = cap->device_caps | V4L2_CAP_DEVICE_CAPS; ++ return 0; ++} ++ ++static int __enum_fmt(struct v4l2_fmtdesc *f, u32 type) ++{ ++ int i, index; ++ struct vpe_fmt *fmt = NULL; ++ ++ index = 0; ++ for (i = 0; i < ARRAY_SIZE(vpe_formats); ++i) { ++ if (vpe_formats[i].types & type) { ++ if (index == f->index) { ++ fmt = &vpe_formats[i]; ++ break; ++ } ++ index++; ++ } ++ } ++ ++ if (!fmt) ++ return -EINVAL; ++ ++ strncpy(f->description, fmt->name, sizeof(f->description) - 1); ++ f->pixelformat = fmt->fourcc; ++ return 0; ++} ++ ++static int vpe_enum_fmt(struct file *file, void *priv, ++ struct v4l2_fmtdesc *f) ++{ ++ if (V4L2_TYPE_IS_OUTPUT(f->type)) ++ return __enum_fmt(f, VPE_FMT_TYPE_OUTPUT); ++ ++ return __enum_fmt(f, VPE_FMT_TYPE_CAPTURE); ++} ++ ++static int vpe_g_fmt(struct file *file, void *priv, struct v4l2_format *f) ++{ ++ struct v4l2_pix_format_mplane *pix = &f->fmt.pix_mp; ++ struct vpe_ctx *ctx = file2ctx(file); ++ struct vb2_queue *vq; ++ struct vpe_q_data *q_data; ++ int i; ++ ++ vq = v4l2_m2m_get_vq(ctx->m2m_ctx, f->type); ++ if (!vq) ++ return -EINVAL; ++ ++ q_data = get_q_data(ctx, f->type); ++ ++ pix->width = q_data->width; ++ pix->height = q_data->height; ++ pix->pixelformat = q_data->fmt->fourcc; ++ pix->field = q_data->field; ++ pix->colorspace = q_data->colorspace; ++ pix->num_planes = q_data->fmt->coplanar ? 2 : 1; ++ ++ for (i = 0; i < pix->num_planes; i++) { ++ pix->plane_fmt[i].bytesperline = q_data->bytesperline[i]; ++ pix->plane_fmt[i].sizeimage = q_data->sizeimage[i]; ++ } ++ ++ return 0; ++} ++ ++static int __vpe_try_fmt(struct vpe_ctx *ctx, struct v4l2_format *f, ++ struct vpe_fmt *fmt, int type) ++{ ++ struct v4l2_pix_format_mplane *pix = &f->fmt.pix_mp; ++ struct v4l2_plane_pix_format *plane_fmt; ++ int i; ++ ++ if (!fmt || !(fmt->types & type)) { ++ vpe_err(ctx->dev, "Fourcc format (0x%08x) invalid.\n", ++ pix->pixelformat); ++ return -EINVAL; ++ } ++ ++ if (pix->field != V4L2_FIELD_NONE && pix->field != V4L2_FIELD_ALTERNATE) ++ pix->field = V4L2_FIELD_NONE; ++ ++ v4l_bound_align_image(&pix->width, MIN_W, MAX_W, W_ALIGN, ++ &pix->height, MIN_H, MAX_H, H_ALIGN, ++ S_ALIGN); ++ ++ pix->num_planes = fmt->coplanar ? 2 : 1; ++ pix->pixelformat = fmt->fourcc; ++ pix->colorspace = fmt->fourcc == V4L2_PIX_FMT_RGB24 ? ++ V4L2_COLORSPACE_SRGB : V4L2_COLORSPACE_SMPTE170M; ++ ++ for (i = 0; i < pix->num_planes; i++) { ++ int depth; ++ ++ plane_fmt = &pix->plane_fmt[i]; ++ depth = fmt->vpdma_fmt[i]->depth; ++ ++ if (i == VPE_LUMA) ++ plane_fmt->bytesperline = ++ round_up((pix->width * depth) >> 3, ++ 1 << L_ALIGN); ++ else ++ plane_fmt->bytesperline = pix->width; ++ ++ plane_fmt->sizeimage = ++ (pix->height * pix->width * depth) >> 3; ++ } ++ ++ return 0; ++} ++ ++static int vpe_try_fmt(struct file *file, void *priv, struct v4l2_format *f) ++{ ++ struct vpe_ctx *ctx = file2ctx(file); ++ struct vpe_fmt *fmt = find_format(f); ++ ++ if (V4L2_TYPE_IS_OUTPUT(f->type)) ++ return __vpe_try_fmt(ctx, f, fmt, VPE_FMT_TYPE_OUTPUT); ++ else ++ return __vpe_try_fmt(ctx, f, fmt, VPE_FMT_TYPE_CAPTURE); ++} ++ ++static int __vpe_s_fmt(struct vpe_ctx *ctx, struct v4l2_format *f) ++{ ++ struct v4l2_pix_format_mplane *pix = &f->fmt.pix_mp; ++ struct v4l2_plane_pix_format *plane_fmt; ++ struct vpe_q_data *q_data; ++ struct vb2_queue *vq; ++ int i; ++ ++ vq = v4l2_m2m_get_vq(ctx->m2m_ctx, f->type); ++ if (!vq) ++ return -EINVAL; ++ ++ if (vb2_is_busy(vq)) { ++ vpe_err(ctx->dev, "queue busy\n"); ++ return -EBUSY; ++ } ++ ++ q_data = get_q_data(ctx, f->type); ++ if (!q_data) ++ return -EINVAL; ++ ++ q_data->fmt = find_format(f); ++ q_data->width = pix->width; ++ q_data->height = pix->height; ++ q_data->colorspace = pix->colorspace; ++ q_data->field = pix->field; ++ ++ for (i = 0; i < pix->num_planes; i++) { ++ plane_fmt = &pix->plane_fmt[i]; ++ ++ q_data->bytesperline[i] = plane_fmt->bytesperline; ++ q_data->sizeimage[i] = plane_fmt->sizeimage; ++ } ++ ++ q_data->c_rect.left = 0; ++ q_data->c_rect.top = 0; ++ q_data->c_rect.width = q_data->width; ++ q_data->c_rect.height = q_data->height; ++ ++ if (q_data->field == V4L2_FIELD_ALTERNATE) ++ q_data->flags |= Q_DATA_INTERLACED; ++ else ++ q_data->flags &= ~Q_DATA_INTERLACED; ++ ++ vpe_dbg(ctx->dev, "Setting format for type %d, wxh: %dx%d, fmt: %d bpl_y %d", ++ f->type, q_data->width, q_data->height, q_data->fmt->fourcc, ++ q_data->bytesperline[VPE_LUMA]); ++ if (q_data->fmt->coplanar) ++ vpe_dbg(ctx->dev, " bpl_uv %d\n", ++ q_data->bytesperline[VPE_CHROMA]); ++ ++ return 0; ++} ++ ++static int vpe_s_fmt(struct file *file, void *priv, struct v4l2_format *f) ++{ ++ int ret; ++ struct vpe_ctx *ctx = file2ctx(file); ++ ++ ret = vpe_try_fmt(file, priv, f); ++ if (ret) ++ return ret; ++ ++ ret = __vpe_s_fmt(ctx, f); ++ if (ret) ++ return ret; ++ ++ if (V4L2_TYPE_IS_OUTPUT(f->type)) ++ set_src_registers(ctx); ++ else ++ set_dst_registers(ctx); ++ ++ return set_srcdst_params(ctx); ++} ++ ++static int vpe_reqbufs(struct file *file, void *priv, ++ struct v4l2_requestbuffers *reqbufs) ++{ ++ struct vpe_ctx *ctx = file2ctx(file); ++ ++ return v4l2_m2m_reqbufs(file, ctx->m2m_ctx, reqbufs); ++} ++ ++static int vpe_querybuf(struct file *file, void *priv, struct v4l2_buffer *buf) ++{ ++ struct vpe_ctx *ctx = file2ctx(file); ++ ++ return v4l2_m2m_querybuf(file, ctx->m2m_ctx, buf); ++} ++ ++static int vpe_qbuf(struct file *file, void *priv, struct v4l2_buffer *buf) ++{ ++ struct vpe_ctx *ctx = file2ctx(file); ++ ++ return v4l2_m2m_qbuf(file, ctx->m2m_ctx, buf); ++} ++ ++static int vpe_dqbuf(struct file *file, void *priv, struct v4l2_buffer *buf) ++{ ++ struct vpe_ctx *ctx = file2ctx(file); ++ ++ return v4l2_m2m_dqbuf(file, ctx->m2m_ctx, buf); ++} ++ ++static int vpe_streamon(struct file *file, void *priv, enum v4l2_buf_type type) ++{ ++ struct vpe_ctx *ctx = file2ctx(file); ++ ++ return v4l2_m2m_streamon(file, ctx->m2m_ctx, type); ++} ++ ++static int vpe_streamoff(struct file *file, void *priv, enum v4l2_buf_type type) ++{ ++ struct vpe_ctx *ctx = file2ctx(file); ++ ++ vpe_dump_regs(ctx->dev); ++ vpdma_dump_regs(ctx->dev->vpdma); ++ ++ return v4l2_m2m_streamoff(file, ctx->m2m_ctx, type); ++} ++ ++#define V4L2_CID_VPE_BUFS_PER_JOB (V4L2_CID_USER_TI_VPE_BASE + 0) ++ ++static int vpe_s_ctrl(struct v4l2_ctrl *ctrl) ++{ ++ struct vpe_ctx *ctx = ++ container_of(ctrl->handler, struct vpe_ctx, hdl); ++ ++ switch (ctrl->id) { ++ case V4L2_CID_VPE_BUFS_PER_JOB: ++ ctx->bufs_per_job = ctrl->val; ++ break; ++ ++ default: ++ vpe_err(ctx->dev, "Invalid control\n"); ++ return -EINVAL; ++ } ++ ++ return 0; ++} ++ ++static const struct v4l2_ctrl_ops vpe_ctrl_ops = { ++ .s_ctrl = vpe_s_ctrl, ++}; ++ ++static const struct v4l2_ioctl_ops vpe_ioctl_ops = { ++ .vidioc_querycap = vpe_querycap, ++ ++ .vidioc_enum_fmt_vid_cap_mplane = vpe_enum_fmt, ++ .vidioc_g_fmt_vid_cap_mplane = vpe_g_fmt, ++ .vidioc_try_fmt_vid_cap_mplane = vpe_try_fmt, ++ .vidioc_s_fmt_vid_cap_mplane = vpe_s_fmt, ++ ++ .vidioc_enum_fmt_vid_out_mplane = vpe_enum_fmt, ++ .vidioc_g_fmt_vid_out_mplane = vpe_g_fmt, ++ .vidioc_try_fmt_vid_out_mplane = vpe_try_fmt, ++ .vidioc_s_fmt_vid_out_mplane = vpe_s_fmt, ++ ++ .vidioc_reqbufs = vpe_reqbufs, ++ .vidioc_querybuf = vpe_querybuf, ++ ++ .vidioc_qbuf = vpe_qbuf, ++ .vidioc_dqbuf = vpe_dqbuf, ++ ++ .vidioc_streamon = vpe_streamon, ++ .vidioc_streamoff = vpe_streamoff, ++ .vidioc_subscribe_event = v4l2_ctrl_subscribe_event, ++ .vidioc_unsubscribe_event = v4l2_event_unsubscribe, ++}; ++ ++/* ++ * Queue operations ++ */ ++static int vpe_queue_setup(struct vb2_queue *vq, ++ const struct v4l2_format *fmt, ++ unsigned int *nbuffers, unsigned int *nplanes, ++ unsigned int sizes[], void *alloc_ctxs[]) ++{ ++ int i; ++ struct vpe_ctx *ctx = vb2_get_drv_priv(vq); ++ struct vpe_q_data *q_data; ++ ++ q_data = get_q_data(ctx, vq->type); ++ ++ *nplanes = q_data->fmt->coplanar ? 2 : 1; ++ ++ for (i = 0; i < *nplanes; i++) { ++ sizes[i] = q_data->sizeimage[i]; ++ alloc_ctxs[i] = ctx->dev->alloc_ctx; ++ } ++ ++ vpe_dbg(ctx->dev, "get %d buffer(s) of size %d", *nbuffers, ++ sizes[VPE_LUMA]); ++ if (q_data->fmt->coplanar) ++ vpe_dbg(ctx->dev, " and %d\n", sizes[VPE_CHROMA]); ++ ++ return 0; ++} ++ ++static int vpe_buf_prepare(struct vb2_buffer *vb) ++{ ++ struct vpe_ctx *ctx = vb2_get_drv_priv(vb->vb2_queue); ++ struct vpe_q_data *q_data; ++ int i, num_planes; ++ ++ vpe_dbg(ctx->dev, "type: %d\n", vb->vb2_queue->type); ++ ++ q_data = get_q_data(ctx, vb->vb2_queue->type); ++ num_planes = q_data->fmt->coplanar ? 2 : 1; ++ ++ for (i = 0; i < num_planes; i++) { ++ if (vb2_plane_size(vb, i) < q_data->sizeimage[i]) { ++ vpe_err(ctx->dev, ++ "data will not fit into plane (%lu < %lu)\n", ++ vb2_plane_size(vb, i), ++ (long) q_data->sizeimage[i]); ++ return -EINVAL; ++ } ++ } ++ ++ for (i = 0; i < num_planes; i++) ++ vb2_set_plane_payload(vb, i, q_data->sizeimage[i]); ++ ++ return 0; ++} ++ ++static void vpe_buf_queue(struct vb2_buffer *vb) ++{ ++ struct vpe_ctx *ctx = vb2_get_drv_priv(vb->vb2_queue); ++ v4l2_m2m_buf_queue(ctx->m2m_ctx, vb); ++} ++ ++static void vpe_wait_prepare(struct vb2_queue *q) ++{ ++ struct vpe_ctx *ctx = vb2_get_drv_priv(q); ++ vpe_unlock(ctx); ++} ++ ++static void vpe_wait_finish(struct vb2_queue *q) ++{ ++ struct vpe_ctx *ctx = vb2_get_drv_priv(q); ++ vpe_lock(ctx); ++} ++ ++static struct vb2_ops vpe_qops = { ++ .queue_setup = vpe_queue_setup, ++ .buf_prepare = vpe_buf_prepare, ++ .buf_queue = vpe_buf_queue, ++ .wait_prepare = vpe_wait_prepare, ++ .wait_finish = vpe_wait_finish, ++}; ++ ++static int queue_init(void *priv, struct vb2_queue *src_vq, ++ struct vb2_queue *dst_vq) ++{ ++ struct vpe_ctx *ctx = priv; ++ int ret; ++ ++ memset(src_vq, 0, sizeof(*src_vq)); ++ src_vq->type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE; ++ src_vq->io_modes = VB2_MMAP; ++ src_vq->drv_priv = ctx; ++ src_vq->buf_struct_size = sizeof(struct v4l2_m2m_buffer); ++ src_vq->ops = &vpe_qops; ++ src_vq->mem_ops = &vb2_dma_contig_memops; ++ src_vq->timestamp_type = V4L2_BUF_FLAG_TIMESTAMP_COPY; ++ ++ ret = vb2_queue_init(src_vq); ++ if (ret) ++ return ret; ++ ++ memset(dst_vq, 0, sizeof(*dst_vq)); ++ dst_vq->type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE; ++ dst_vq->io_modes = VB2_MMAP; ++ dst_vq->drv_priv = ctx; ++ dst_vq->buf_struct_size = sizeof(struct v4l2_m2m_buffer); ++ dst_vq->ops = &vpe_qops; ++ dst_vq->mem_ops = &vb2_dma_contig_memops; ++ dst_vq->timestamp_type = V4L2_BUF_FLAG_TIMESTAMP_COPY; ++ ++ return vb2_queue_init(dst_vq); ++} ++ ++static const struct v4l2_ctrl_config vpe_bufs_per_job = { ++ .ops = &vpe_ctrl_ops, ++ .id = V4L2_CID_VPE_BUFS_PER_JOB, ++ .name = "Buffers Per Transaction", ++ .type = V4L2_CTRL_TYPE_INTEGER, ++ .def = VPE_DEF_BUFS_PER_JOB, ++ .min = 1, ++ .max = VIDEO_MAX_FRAME, ++ .step = 1, ++}; ++ ++/* ++ * File operations ++ */ ++static int vpe_open(struct file *file) ++{ ++ struct vpe_dev *dev = video_drvdata(file); ++ struct vpe_ctx *ctx = NULL; ++ struct vpe_q_data *s_q_data; ++ struct v4l2_ctrl_handler *hdl; ++ int ret; ++ ++ vpe_dbg(dev, "vpe_open\n"); ++ ++ if (!dev->vpdma->ready) { ++ vpe_err(dev, "vpdma firmware not loaded\n"); ++ return -ENODEV; ++ } ++ ++ ctx = kzalloc(sizeof(*ctx), GFP_KERNEL); ++ if (!ctx) ++ return -ENOMEM; ++ ++ ctx->dev = dev; ++ ++ if (mutex_lock_interruptible(&dev->dev_mutex)) { ++ ret = -ERESTARTSYS; ++ goto free_ctx; ++ } ++ ++ ret = vpdma_create_desc_list(&ctx->desc_list, VPE_DESC_LIST_SIZE, ++ VPDMA_LIST_TYPE_NORMAL); ++ if (ret != 0) ++ goto unlock; ++ ++ ret = vpdma_alloc_desc_buf(&ctx->mmr_adb, sizeof(struct vpe_mmr_adb)); ++ if (ret != 0) ++ goto free_desc_list; ++ ++ init_adb_hdrs(ctx); ++ ++ v4l2_fh_init(&ctx->fh, video_devdata(file)); ++ file->private_data = &ctx->fh; ++ ++ hdl = &ctx->hdl; ++ v4l2_ctrl_handler_init(hdl, 1); ++ v4l2_ctrl_new_custom(hdl, &vpe_bufs_per_job, NULL); ++ if (hdl->error) { ++ ret = hdl->error; ++ goto exit_fh; ++ } ++ ctx->fh.ctrl_handler = hdl; ++ v4l2_ctrl_handler_setup(hdl); ++ ++ s_q_data = &ctx->q_data[Q_DATA_SRC]; ++ s_q_data->fmt = &vpe_formats[2]; ++ s_q_data->width = 1920; ++ s_q_data->height = 1080; ++ s_q_data->sizeimage[VPE_LUMA] = (s_q_data->width * s_q_data->height * ++ s_q_data->fmt->vpdma_fmt[VPE_LUMA]->depth) >> 3; ++ s_q_data->colorspace = V4L2_COLORSPACE_SMPTE240M; ++ s_q_data->field = V4L2_FIELD_NONE; ++ s_q_data->c_rect.left = 0; ++ s_q_data->c_rect.top = 0; ++ s_q_data->c_rect.width = s_q_data->width; ++ s_q_data->c_rect.height = s_q_data->height; ++ s_q_data->flags = 0; ++ ++ ctx->q_data[Q_DATA_DST] = *s_q_data; ++ ++ set_dei_shadow_registers(ctx); ++ set_src_registers(ctx); ++ set_dst_registers(ctx); ++ ret = set_srcdst_params(ctx); ++ if (ret) ++ goto exit_fh; ++ ++ ctx->m2m_ctx = v4l2_m2m_ctx_init(dev->m2m_dev, ctx, &queue_init); ++ ++ if (IS_ERR(ctx->m2m_ctx)) { ++ ret = PTR_ERR(ctx->m2m_ctx); ++ goto exit_fh; ++ } ++ ++ v4l2_fh_add(&ctx->fh); ++ ++ /* ++ * for now, just report the creation of the first instance, we can later ++ * optimize the driver to enable or disable clocks when the first ++ * instance is created or the last instance released ++ */ ++ if (atomic_inc_return(&dev->num_instances) == 1) ++ vpe_dbg(dev, "first instance created\n"); ++ ++ ctx->bufs_per_job = VPE_DEF_BUFS_PER_JOB; ++ ++ ctx->load_mmrs = true; ++ ++ vpe_dbg(dev, "created instance %p, m2m_ctx: %p\n", ++ ctx, ctx->m2m_ctx); ++ ++ mutex_unlock(&dev->dev_mutex); ++ ++ return 0; ++exit_fh: ++ v4l2_ctrl_handler_free(hdl); ++ v4l2_fh_exit(&ctx->fh); ++ vpdma_free_desc_buf(&ctx->mmr_adb); ++free_desc_list: ++ vpdma_free_desc_list(&ctx->desc_list); ++unlock: ++ mutex_unlock(&dev->dev_mutex); ++free_ctx: ++ kfree(ctx); ++ return ret; ++} ++ ++static int vpe_release(struct file *file) ++{ ++ struct vpe_dev *dev = video_drvdata(file); ++ struct vpe_ctx *ctx = file2ctx(file); ++ ++ vpe_dbg(dev, "releasing instance %p\n", ctx); ++ ++ mutex_lock(&dev->dev_mutex); ++ free_vbs(ctx); ++ free_mv_buffers(ctx); ++ vpdma_free_desc_list(&ctx->desc_list); ++ vpdma_free_desc_buf(&ctx->mmr_adb); ++ ++ v4l2_fh_del(&ctx->fh); ++ v4l2_fh_exit(&ctx->fh); ++ v4l2_ctrl_handler_free(&ctx->hdl); ++ v4l2_m2m_ctx_release(ctx->m2m_ctx); ++ ++ kfree(ctx); ++ ++ /* ++ * for now, just report the release of the last instance, we can later ++ * optimize the driver to enable or disable clocks when the first ++ * instance is created or the last instance released ++ */ ++ if (atomic_dec_return(&dev->num_instances) == 0) ++ vpe_dbg(dev, "last instance released\n"); ++ ++ mutex_unlock(&dev->dev_mutex); ++ ++ return 0; ++} ++ ++static unsigned int vpe_poll(struct file *file, ++ struct poll_table_struct *wait) ++{ ++ struct vpe_ctx *ctx = file2ctx(file); ++ struct vpe_dev *dev = ctx->dev; ++ int ret; ++ ++ mutex_lock(&dev->dev_mutex); ++ ret = v4l2_m2m_poll(file, ctx->m2m_ctx, wait); ++ mutex_unlock(&dev->dev_mutex); ++ return ret; ++} ++ ++static int vpe_mmap(struct file *file, struct vm_area_struct *vma) ++{ ++ struct vpe_ctx *ctx = file2ctx(file); ++ struct vpe_dev *dev = ctx->dev; ++ int ret; ++ ++ if (mutex_lock_interruptible(&dev->dev_mutex)) ++ return -ERESTARTSYS; ++ ret = v4l2_m2m_mmap(file, ctx->m2m_ctx, vma); ++ mutex_unlock(&dev->dev_mutex); ++ return ret; ++} ++ ++static const struct v4l2_file_operations vpe_fops = { ++ .owner = THIS_MODULE, ++ .open = vpe_open, ++ .release = vpe_release, ++ .poll = vpe_poll, ++ .unlocked_ioctl = video_ioctl2, ++ .mmap = vpe_mmap, ++}; ++ ++static struct video_device vpe_videodev = { ++ .name = VPE_MODULE_NAME, ++ .fops = &vpe_fops, ++ .ioctl_ops = &vpe_ioctl_ops, ++ .minor = -1, ++ .release = video_device_release, ++ .vfl_dir = VFL_DIR_M2M, ++}; ++ ++static struct v4l2_m2m_ops m2m_ops = { ++ .device_run = device_run, ++ .job_ready = job_ready, ++ .job_abort = job_abort, ++ .lock = vpe_lock, ++ .unlock = vpe_unlock, ++}; ++ ++static int vpe_runtime_get(struct platform_device *pdev) ++{ ++ int r; ++ ++ dev_dbg(&pdev->dev, "vpe_runtime_get\n"); ++ ++ r = pm_runtime_get_sync(&pdev->dev); ++ WARN_ON(r < 0); ++ return r < 0 ? r : 0; ++} ++ ++static void vpe_runtime_put(struct platform_device *pdev) ++{ ++ ++ int r; ++ ++ dev_dbg(&pdev->dev, "vpe_runtime_put\n"); ++ ++ r = pm_runtime_put_sync(&pdev->dev); ++ WARN_ON(r < 0 && r != -ENOSYS); ++} ++ ++static int vpe_probe(struct platform_device *pdev) ++{ ++ struct vpe_dev *dev; ++ struct video_device *vfd; ++ struct resource *res; ++ int ret, irq, func; ++ ++ dev = devm_kzalloc(&pdev->dev, sizeof(*dev), GFP_KERNEL); ++ if (IS_ERR(dev)) ++ return PTR_ERR(dev); ++ ++ spin_lock_init(&dev->lock); ++ ++ ret = v4l2_device_register(&pdev->dev, &dev->v4l2_dev); ++ if (ret) ++ return ret; ++ ++ atomic_set(&dev->num_instances, 0); ++ mutex_init(&dev->dev_mutex); ++ ++ res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "vpe_top"); ++ /* ++ * HACK: we get resource info from device tree in the form of a list of ++ * VPE sub blocks, the driver currently uses only the base of vpe_top ++ * for register access, the driver should be changed later to access ++ * registers based on the sub block base addresses ++ */ ++ dev->base = devm_ioremap(&pdev->dev, res->start, SZ_32K); ++ if (IS_ERR(dev->base)) { ++ ret = PTR_ERR(dev->base); ++ goto v4l2_dev_unreg; ++ } ++ ++ irq = platform_get_irq(pdev, 0); ++ ret = devm_request_irq(&pdev->dev, irq, vpe_irq, 0, VPE_MODULE_NAME, ++ dev); ++ if (ret) ++ goto v4l2_dev_unreg; ++ ++ platform_set_drvdata(pdev, dev); ++ ++ dev->alloc_ctx = vb2_dma_contig_init_ctx(&pdev->dev); ++ if (IS_ERR(dev->alloc_ctx)) { ++ vpe_err(dev, "Failed to alloc vb2 context\n"); ++ ret = PTR_ERR(dev->alloc_ctx); ++ goto v4l2_dev_unreg; ++ } ++ ++ dev->m2m_dev = v4l2_m2m_init(&m2m_ops); ++ if (IS_ERR(dev->m2m_dev)) { ++ vpe_err(dev, "Failed to init mem2mem device\n"); ++ ret = PTR_ERR(dev->m2m_dev); ++ goto rel_ctx; ++ } ++ ++ pm_runtime_enable(&pdev->dev); ++ ++ ret = vpe_runtime_get(pdev); ++ if (ret) ++ goto rel_m2m; ++ ++ /* Perform clk enable followed by reset */ ++ vpe_set_clock_enable(dev, 1); ++ ++ vpe_top_reset(dev); ++ ++ func = read_field_reg(dev, VPE_PID, VPE_PID_FUNC_MASK, ++ VPE_PID_FUNC_SHIFT); ++ vpe_dbg(dev, "VPE PID function %x\n", func); ++ ++ vpe_top_vpdma_reset(dev); ++ ++ dev->vpdma = vpdma_create(pdev); ++ if (IS_ERR(dev->vpdma)) ++ goto runtime_put; ++ ++ vfd = &dev->vfd; ++ *vfd = vpe_videodev; ++ vfd->lock = &dev->dev_mutex; ++ vfd->v4l2_dev = &dev->v4l2_dev; ++ ++ ret = video_register_device(vfd, VFL_TYPE_GRABBER, 0); ++ if (ret) { ++ vpe_err(dev, "Failed to register video device\n"); ++ goto runtime_put; ++ } ++ ++ video_set_drvdata(vfd, dev); ++ snprintf(vfd->name, sizeof(vfd->name), "%s", vpe_videodev.name); ++ dev_info(dev->v4l2_dev.dev, "Device registered as /dev/video%d\n", ++ vfd->num); ++ ++ return 0; ++ ++runtime_put: ++ vpe_runtime_put(pdev); ++rel_m2m: ++ pm_runtime_disable(&pdev->dev); ++ v4l2_m2m_release(dev->m2m_dev); ++rel_ctx: ++ vb2_dma_contig_cleanup_ctx(dev->alloc_ctx); ++v4l2_dev_unreg: ++ v4l2_device_unregister(&dev->v4l2_dev); ++ ++ return ret; ++} ++ ++static int vpe_remove(struct platform_device *pdev) ++{ ++ struct vpe_dev *dev = ++ (struct vpe_dev *) platform_get_drvdata(pdev); ++ ++ v4l2_info(&dev->v4l2_dev, "Removing " VPE_MODULE_NAME); ++ ++ v4l2_m2m_release(dev->m2m_dev); ++ video_unregister_device(&dev->vfd); ++ v4l2_device_unregister(&dev->v4l2_dev); ++ vb2_dma_contig_cleanup_ctx(dev->alloc_ctx); ++ ++ vpe_set_clock_enable(dev, 0); ++ vpe_runtime_put(pdev); ++ pm_runtime_disable(&pdev->dev); ++ ++ return 0; ++} ++ ++#if defined(CONFIG_OF) ++static const struct of_device_id vpe_of_match[] = { ++ { ++ .compatible = "ti,vpe", ++ }, ++ {}, ++}; ++#else ++#define vpe_of_match NULL ++#endif ++ ++static struct platform_driver vpe_pdrv = { ++ .probe = vpe_probe, ++ .remove = vpe_remove, ++ .driver = { ++ .name = VPE_MODULE_NAME, ++ .owner = THIS_MODULE, ++ .of_match_table = vpe_of_match, ++ }, ++}; ++ ++static void __exit vpe_exit(void) ++{ ++ platform_driver_unregister(&vpe_pdrv); ++} ++ ++static int __init vpe_init(void) ++{ ++ return platform_driver_register(&vpe_pdrv); ++} ++ ++module_init(vpe_init); ++module_exit(vpe_exit); ++ ++MODULE_DESCRIPTION("TI VPE driver"); ++MODULE_AUTHOR("Dale Farnsworth, <dale@farnsworth.org>"); ++MODULE_LICENSE("GPL"); +--- /dev/null ++++ b/drivers/media/platform/ti-vpe/vpe_regs.h +@@ -0,0 +1,496 @@ ++/* ++ * Copyright (c) 2013 Texas Instruments Inc. ++ * ++ * David Griego, <dagriego@biglakesoftware.com> ++ * Dale Farnsworth, <dale@farnsworth.org> ++ * Archit Taneja, <archit@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 __TI_VPE_REGS_H ++#define __TI_VPE_REGS_H ++ ++/* VPE register offsets and field selectors */ ++ ++/* VPE top level regs */ ++#define VPE_PID 0x0000 ++#define VPE_PID_MINOR_MASK 0x3f ++#define VPE_PID_MINOR_SHIFT 0 ++#define VPE_PID_CUSTOM_MASK 0x03 ++#define VPE_PID_CUSTOM_SHIFT 6 ++#define VPE_PID_MAJOR_MASK 0x07 ++#define VPE_PID_MAJOR_SHIFT 8 ++#define VPE_PID_RTL_MASK 0x1f ++#define VPE_PID_RTL_SHIFT 11 ++#define VPE_PID_FUNC_MASK 0xfff ++#define VPE_PID_FUNC_SHIFT 16 ++#define VPE_PID_SCHEME_MASK 0x03 ++#define VPE_PID_SCHEME_SHIFT 30 ++ ++#define VPE_SYSCONFIG 0x0010 ++#define VPE_SYSCONFIG_IDLE_MASK 0x03 ++#define VPE_SYSCONFIG_IDLE_SHIFT 2 ++#define VPE_SYSCONFIG_STANDBY_MASK 0x03 ++#define VPE_SYSCONFIG_STANDBY_SHIFT 4 ++#define VPE_FORCE_IDLE_MODE 0 ++#define VPE_NO_IDLE_MODE 1 ++#define VPE_SMART_IDLE_MODE 2 ++#define VPE_SMART_IDLE_WAKEUP_MODE 3 ++#define VPE_FORCE_STANDBY_MODE 0 ++#define VPE_NO_STANDBY_MODE 1 ++#define VPE_SMART_STANDBY_MODE 2 ++#define VPE_SMART_STANDBY_WAKEUP_MODE 3 ++ ++#define VPE_INT0_STATUS0_RAW_SET 0x0020 ++#define VPE_INT0_STATUS0_RAW VPE_INT0_STATUS0_RAW_SET ++#define VPE_INT0_STATUS0_CLR 0x0028 ++#define VPE_INT0_STATUS0 VPE_INT0_STATUS0_CLR ++#define VPE_INT0_ENABLE0_SET 0x0030 ++#define VPE_INT0_ENABLE0 VPE_INT0_ENABLE0_SET ++#define VPE_INT0_ENABLE0_CLR 0x0038 ++#define VPE_INT0_LIST0_COMPLETE (1 << 0) ++#define VPE_INT0_LIST0_NOTIFY (1 << 1) ++#define VPE_INT0_LIST1_COMPLETE (1 << 2) ++#define VPE_INT0_LIST1_NOTIFY (1 << 3) ++#define VPE_INT0_LIST2_COMPLETE (1 << 4) ++#define VPE_INT0_LIST2_NOTIFY (1 << 5) ++#define VPE_INT0_LIST3_COMPLETE (1 << 6) ++#define VPE_INT0_LIST3_NOTIFY (1 << 7) ++#define VPE_INT0_LIST4_COMPLETE (1 << 8) ++#define VPE_INT0_LIST4_NOTIFY (1 << 9) ++#define VPE_INT0_LIST5_COMPLETE (1 << 10) ++#define VPE_INT0_LIST5_NOTIFY (1 << 11) ++#define VPE_INT0_LIST6_COMPLETE (1 << 12) ++#define VPE_INT0_LIST6_NOTIFY (1 << 13) ++#define VPE_INT0_LIST7_COMPLETE (1 << 14) ++#define VPE_INT0_LIST7_NOTIFY (1 << 15) ++#define VPE_INT0_DESCRIPTOR (1 << 16) ++#define VPE_DEI_FMD_INT (1 << 18) ++ ++#define VPE_INT0_STATUS1_RAW_SET 0x0024 ++#define VPE_INT0_STATUS1_RAW VPE_INT0_STATUS1_RAW_SET ++#define VPE_INT0_STATUS1_CLR 0x002c ++#define VPE_INT0_STATUS1 VPE_INT0_STATUS1_CLR ++#define VPE_INT0_ENABLE1_SET 0x0034 ++#define VPE_INT0_ENABLE1 VPE_INT0_ENABLE1_SET ++#define VPE_INT0_ENABLE1_CLR 0x003c ++#define VPE_INT0_CHANNEL_GROUP0 (1 << 0) ++#define VPE_INT0_CHANNEL_GROUP1 (1 << 1) ++#define VPE_INT0_CHANNEL_GROUP2 (1 << 2) ++#define VPE_INT0_CHANNEL_GROUP3 (1 << 3) ++#define VPE_INT0_CHANNEL_GROUP4 (1 << 4) ++#define VPE_INT0_CHANNEL_GROUP5 (1 << 5) ++#define VPE_INT0_CLIENT (1 << 7) ++#define VPE_DEI_ERROR_INT (1 << 16) ++#define VPE_DS1_UV_ERROR_INT (1 << 22) ++ ++#define VPE_INTC_EOI 0x00a0 ++ ++#define VPE_CLK_ENABLE 0x0100 ++#define VPE_VPEDMA_CLK_ENABLE (1 << 0) ++#define VPE_DATA_PATH_CLK_ENABLE (1 << 1) ++ ++#define VPE_CLK_RESET 0x0104 ++#define VPE_VPDMA_CLK_RESET_MASK 0x1 ++#define VPE_VPDMA_CLK_RESET_SHIFT 0 ++#define VPE_DATA_PATH_CLK_RESET_MASK 0x1 ++#define VPE_DATA_PATH_CLK_RESET_SHIFT 1 ++#define VPE_MAIN_RESET_MASK 0x1 ++#define VPE_MAIN_RESET_SHIFT 31 ++ ++#define VPE_CLK_FORMAT_SELECT 0x010c ++#define VPE_CSC_SRC_SELECT_MASK 0x03 ++#define VPE_CSC_SRC_SELECT_SHIFT 0 ++#define VPE_RGB_OUT_SELECT (1 << 8) ++#define VPE_DS_SRC_SELECT_MASK 0x07 ++#define VPE_DS_SRC_SELECT_SHIFT 9 ++#define VPE_DS_BYPASS (1 << 16) ++#define VPE_COLOR_SEPARATE_422 (1 << 18) ++ ++#define VPE_DS_SRC_DEI_SCALER (5 << VPE_DS_SRC_SELECT_SHIFT) ++#define VPE_CSC_SRC_DEI_SCALER (3 << VPE_CSC_SRC_SELECT_SHIFT) ++ ++#define VPE_CLK_RANGE_MAP 0x011c ++#define VPE_RANGE_RANGE_MAP_Y_MASK 0x07 ++#define VPE_RANGE_RANGE_MAP_Y_SHIFT 0 ++#define VPE_RANGE_RANGE_MAP_UV_MASK 0x07 ++#define VPE_RANGE_RANGE_MAP_UV_SHIFT 3 ++#define VPE_RANGE_MAP_ON (1 << 6) ++#define VPE_RANGE_REDUCTION_ON (1 << 28) ++ ++/* VPE chrominance upsampler regs */ ++#define VPE_US1_R0 0x0304 ++#define VPE_US2_R0 0x0404 ++#define VPE_US3_R0 0x0504 ++#define VPE_US_C1_MASK 0x3fff ++#define VPE_US_C1_SHIFT 2 ++#define VPE_US_C0_MASK 0x3fff ++#define VPE_US_C0_SHIFT 18 ++#define VPE_US_MODE_MASK 0x03 ++#define VPE_US_MODE_SHIFT 16 ++#define VPE_ANCHOR_FID0_C1_MASK 0x3fff ++#define VPE_ANCHOR_FID0_C1_SHIFT 2 ++#define VPE_ANCHOR_FID0_C0_MASK 0x3fff ++#define VPE_ANCHOR_FID0_C0_SHIFT 18 ++ ++#define VPE_US1_R1 0x0308 ++#define VPE_US2_R1 0x0408 ++#define VPE_US3_R1 0x0508 ++#define VPE_ANCHOR_FID0_C3_MASK 0x3fff ++#define VPE_ANCHOR_FID0_C3_SHIFT 2 ++#define VPE_ANCHOR_FID0_C2_MASK 0x3fff ++#define VPE_ANCHOR_FID0_C2_SHIFT 18 ++ ++#define VPE_US1_R2 0x030c ++#define VPE_US2_R2 0x040c ++#define VPE_US3_R2 0x050c ++#define VPE_INTERP_FID0_C1_MASK 0x3fff ++#define VPE_INTERP_FID0_C1_SHIFT 2 ++#define VPE_INTERP_FID0_C0_MASK 0x3fff ++#define VPE_INTERP_FID0_C0_SHIFT 18 ++ ++#define VPE_US1_R3 0x0310 ++#define VPE_US2_R3 0x0410 ++#define VPE_US3_R3 0x0510 ++#define VPE_INTERP_FID0_C3_MASK 0x3fff ++#define VPE_INTERP_FID0_C3_SHIFT 2 ++#define VPE_INTERP_FID0_C2_MASK 0x3fff ++#define VPE_INTERP_FID0_C2_SHIFT 18 ++ ++#define VPE_US1_R4 0x0314 ++#define VPE_US2_R4 0x0414 ++#define VPE_US3_R4 0x0514 ++#define VPE_ANCHOR_FID1_C1_MASK 0x3fff ++#define VPE_ANCHOR_FID1_C1_SHIFT 2 ++#define VPE_ANCHOR_FID1_C0_MASK 0x3fff ++#define VPE_ANCHOR_FID1_C0_SHIFT 18 ++ ++#define VPE_US1_R5 0x0318 ++#define VPE_US2_R5 0x0418 ++#define VPE_US3_R5 0x0518 ++#define VPE_ANCHOR_FID1_C3_MASK 0x3fff ++#define VPE_ANCHOR_FID1_C3_SHIFT 2 ++#define VPE_ANCHOR_FID1_C2_MASK 0x3fff ++#define VPE_ANCHOR_FID1_C2_SHIFT 18 ++ ++#define VPE_US1_R6 0x031c ++#define VPE_US2_R6 0x041c ++#define VPE_US3_R6 0x051c ++#define VPE_INTERP_FID1_C1_MASK 0x3fff ++#define VPE_INTERP_FID1_C1_SHIFT 2 ++#define VPE_INTERP_FID1_C0_MASK 0x3fff ++#define VPE_INTERP_FID1_C0_SHIFT 18 ++ ++#define VPE_US1_R7 0x0320 ++#define VPE_US2_R7 0x0420 ++#define VPE_US3_R7 0x0520 ++#define VPE_INTERP_FID0_C3_MASK 0x3fff ++#define VPE_INTERP_FID0_C3_SHIFT 2 ++#define VPE_INTERP_FID0_C2_MASK 0x3fff ++#define VPE_INTERP_FID0_C2_SHIFT 18 ++ ++/* VPE de-interlacer regs */ ++#define VPE_DEI_FRAME_SIZE 0x0600 ++#define VPE_DEI_WIDTH_MASK 0x07ff ++#define VPE_DEI_WIDTH_SHIFT 0 ++#define VPE_DEI_HEIGHT_MASK 0x07ff ++#define VPE_DEI_HEIGHT_SHIFT 16 ++#define VPE_DEI_INTERLACE_BYPASS (1 << 29) ++#define VPE_DEI_FIELD_FLUSH (1 << 30) ++#define VPE_DEI_PROGRESSIVE (1 << 31) ++ ++#define VPE_MDT_BYPASS 0x0604 ++#define VPE_MDT_TEMPMAX_BYPASS (1 << 0) ++#define VPE_MDT_SPATMAX_BYPASS (1 << 1) ++ ++#define VPE_MDT_SF_THRESHOLD 0x0608 ++#define VPE_MDT_SF_SC_THR1_MASK 0xff ++#define VPE_MDT_SF_SC_THR1_SHIFT 0 ++#define VPE_MDT_SF_SC_THR2_MASK 0xff ++#define VPE_MDT_SF_SC_THR2_SHIFT 0 ++#define VPE_MDT_SF_SC_THR3_MASK 0xff ++#define VPE_MDT_SF_SC_THR3_SHIFT 0 ++ ++#define VPE_EDI_CONFIG 0x060c ++#define VPE_EDI_INP_MODE_MASK 0x03 ++#define VPE_EDI_INP_MODE_SHIFT 0 ++#define VPE_EDI_ENABLE_3D (1 << 2) ++#define VPE_EDI_ENABLE_CHROMA_3D (1 << 3) ++#define VPE_EDI_CHROMA3D_COR_THR_MASK 0xff ++#define VPE_EDI_CHROMA3D_COR_THR_SHIFT 8 ++#define VPE_EDI_DIR_COR_LOWER_THR_MASK 0xff ++#define VPE_EDI_DIR_COR_LOWER_THR_SHIFT 16 ++#define VPE_EDI_COR_SCALE_FACTOR_MASK 0xff ++#define VPE_EDI_COR_SCALE_FACTOR_SHIFT 23 ++ ++#define VPE_DEI_EDI_LUT_R0 0x0610 ++#define VPE_EDI_LUT0_MASK 0x1f ++#define VPE_EDI_LUT0_SHIFT 0 ++#define VPE_EDI_LUT1_MASK 0x1f ++#define VPE_EDI_LUT1_SHIFT 8 ++#define VPE_EDI_LUT2_MASK 0x1f ++#define VPE_EDI_LUT2_SHIFT 16 ++#define VPE_EDI_LUT3_MASK 0x1f ++#define VPE_EDI_LUT3_SHIFT 24 ++ ++#define VPE_DEI_EDI_LUT_R1 0x0614 ++#define VPE_EDI_LUT0_MASK 0x1f ++#define VPE_EDI_LUT0_SHIFT 0 ++#define VPE_EDI_LUT1_MASK 0x1f ++#define VPE_EDI_LUT1_SHIFT 8 ++#define VPE_EDI_LUT2_MASK 0x1f ++#define VPE_EDI_LUT2_SHIFT 16 ++#define VPE_EDI_LUT3_MASK 0x1f ++#define VPE_EDI_LUT3_SHIFT 24 ++ ++#define VPE_DEI_EDI_LUT_R2 0x0618 ++#define VPE_EDI_LUT4_MASK 0x1f ++#define VPE_EDI_LUT4_SHIFT 0 ++#define VPE_EDI_LUT5_MASK 0x1f ++#define VPE_EDI_LUT5_SHIFT 8 ++#define VPE_EDI_LUT6_MASK 0x1f ++#define VPE_EDI_LUT6_SHIFT 16 ++#define VPE_EDI_LUT7_MASK 0x1f ++#define VPE_EDI_LUT7_SHIFT 24 ++ ++#define VPE_DEI_EDI_LUT_R3 0x061c ++#define VPE_EDI_LUT8_MASK 0x1f ++#define VPE_EDI_LUT8_SHIFT 0 ++#define VPE_EDI_LUT9_MASK 0x1f ++#define VPE_EDI_LUT9_SHIFT 8 ++#define VPE_EDI_LUT10_MASK 0x1f ++#define VPE_EDI_LUT10_SHIFT 16 ++#define VPE_EDI_LUT11_MASK 0x1f ++#define VPE_EDI_LUT11_SHIFT 24 ++ ++#define VPE_DEI_FMD_WINDOW_R0 0x0620 ++#define VPE_FMD_WINDOW_MINX_MASK 0x07ff ++#define VPE_FMD_WINDOW_MINX_SHIFT 0 ++#define VPE_FMD_WINDOW_MAXX_MASK 0x07ff ++#define VPE_FMD_WINDOW_MAXX_SHIFT 16 ++#define VPE_FMD_WINDOW_ENABLE (1 << 31) ++ ++#define VPE_DEI_FMD_WINDOW_R1 0x0624 ++#define VPE_FMD_WINDOW_MINY_MASK 0x07ff ++#define VPE_FMD_WINDOW_MINY_SHIFT 0 ++#define VPE_FMD_WINDOW_MAXY_MASK 0x07ff ++#define VPE_FMD_WINDOW_MAXY_SHIFT 16 ++ ++#define VPE_DEI_FMD_CONTROL_R0 0x0628 ++#define VPE_FMD_ENABLE (1 << 0) ++#define VPE_FMD_LOCK (1 << 1) ++#define VPE_FMD_JAM_DIR (1 << 2) ++#define VPE_FMD_BED_ENABLE (1 << 3) ++#define VPE_FMD_CAF_FIELD_THR_MASK 0xff ++#define VPE_FMD_CAF_FIELD_THR_SHIFT 16 ++#define VPE_FMD_CAF_LINE_THR_MASK 0xff ++#define VPE_FMD_CAF_LINE_THR_SHIFT 24 ++ ++#define VPE_DEI_FMD_CONTROL_R1 0x062c ++#define VPE_FMD_CAF_THR_MASK 0x000fffff ++#define VPE_FMD_CAF_THR_SHIFT 0 ++ ++#define VPE_DEI_FMD_STATUS_R0 0x0630 ++#define VPE_FMD_CAF_MASK 0x000fffff ++#define VPE_FMD_CAF_SHIFT 0 ++#define VPE_FMD_RESET (1 << 24) ++ ++#define VPE_DEI_FMD_STATUS_R1 0x0634 ++#define VPE_FMD_FIELD_DIFF_MASK 0x0fffffff ++#define VPE_FMD_FIELD_DIFF_SHIFT 0 ++ ++#define VPE_DEI_FMD_STATUS_R2 0x0638 ++#define VPE_FMD_FRAME_DIFF_MASK 0x000fffff ++#define VPE_FMD_FRAME_DIFF_SHIFT 0 ++ ++/* VPE scaler regs */ ++#define VPE_SC_MP_SC0 0x0700 ++#define VPE_INTERLACE_O (1 << 0) ++#define VPE_LINEAR (1 << 1) ++#define VPE_SC_BYPASS (1 << 2) ++#define VPE_INVT_FID (1 << 3) ++#define VPE_USE_RAV (1 << 4) ++#define VPE_ENABLE_EV (1 << 5) ++#define VPE_AUTO_HS (1 << 6) ++#define VPE_DCM_2X (1 << 7) ++#define VPE_DCM_4X (1 << 8) ++#define VPE_HP_BYPASS (1 << 9) ++#define VPE_INTERLACE_I (1 << 10) ++#define VPE_ENABLE_SIN2_VER_INTP (1 << 11) ++#define VPE_Y_PK_EN (1 << 14) ++#define VPE_TRIM (1 << 15) ++#define VPE_SELFGEN_FID (1 << 16) ++ ++#define VPE_SC_MP_SC1 0x0704 ++#define VPE_ROW_ACC_INC_MASK 0x07ffffff ++#define VPE_ROW_ACC_INC_SHIFT 0 ++ ++#define VPE_SC_MP_SC2 0x0708 ++#define VPE_ROW_ACC_OFFSET_MASK 0x0fffffff ++#define VPE_ROW_ACC_OFFSET_SHIFT 0 ++ ++#define VPE_SC_MP_SC3 0x070c ++#define VPE_ROW_ACC_OFFSET_B_MASK 0x0fffffff ++#define VPE_ROW_ACC_OFFSET_B_SHIFT 0 ++ ++#define VPE_SC_MP_SC4 0x0710 ++#define VPE_TAR_H_MASK 0x07ff ++#define VPE_TAR_H_SHIFT 0 ++#define VPE_TAR_W_MASK 0x07ff ++#define VPE_TAR_W_SHIFT 12 ++#define VPE_LIN_ACC_INC_U_MASK 0x07 ++#define VPE_LIN_ACC_INC_U_SHIFT 24 ++#define VPE_NLIN_ACC_INIT_U_MASK 0x07 ++#define VPE_NLIN_ACC_INIT_U_SHIFT 28 ++ ++#define VPE_SC_MP_SC5 0x0714 ++#define VPE_SRC_H_MASK 0x07ff ++#define VPE_SRC_H_SHIFT 0 ++#define VPE_SRC_W_MASK 0x07ff ++#define VPE_SRC_W_SHIFT 12 ++#define VPE_NLIN_ACC_INC_U_MASK 0x07 ++#define VPE_NLIN_ACC_INC_U_SHIFT 24 ++ ++#define VPE_SC_MP_SC6 0x0718 ++#define VPE_ROW_ACC_INIT_RAV_MASK 0x03ff ++#define VPE_ROW_ACC_INIT_RAV_SHIFT 0 ++#define VPE_ROW_ACC_INIT_RAV_B_MASK 0x03ff ++#define VPE_ROW_ACC_INIT_RAV_B_SHIFT 10 ++ ++#define VPE_SC_MP_SC8 0x0720 ++#define VPE_NLIN_LEFT_MASK 0x07ff ++#define VPE_NLIN_LEFT_SHIFT 0 ++#define VPE_NLIN_RIGHT_MASK 0x07ff ++#define VPE_NLIN_RIGHT_SHIFT 12 ++ ++#define VPE_SC_MP_SC9 0x0724 ++#define VPE_LIN_ACC_INC VPE_SC_MP_SC9 ++ ++#define VPE_SC_MP_SC10 0x0728 ++#define VPE_NLIN_ACC_INIT VPE_SC_MP_SC10 ++ ++#define VPE_SC_MP_SC11 0x072c ++#define VPE_NLIN_ACC_INC VPE_SC_MP_SC11 ++ ++#define VPE_SC_MP_SC12 0x0730 ++#define VPE_COL_ACC_OFFSET_MASK 0x01ffffff ++#define VPE_COL_ACC_OFFSET_SHIFT 0 ++ ++#define VPE_SC_MP_SC13 0x0734 ++#define VPE_SC_FACTOR_RAV_MASK 0x03ff ++#define VPE_SC_FACTOR_RAV_SHIFT 0 ++#define VPE_CHROMA_INTP_THR_MASK 0x03ff ++#define VPE_CHROMA_INTP_THR_SHIFT 12 ++#define VPE_DELTA_CHROMA_THR_MASK 0x0f ++#define VPE_DELTA_CHROMA_THR_SHIFT 24 ++ ++#define VPE_SC_MP_SC17 0x0744 ++#define VPE_EV_THR_MASK 0x03ff ++#define VPE_EV_THR_SHIFT 12 ++#define VPE_DELTA_LUMA_THR_MASK 0x0f ++#define VPE_DELTA_LUMA_THR_SHIFT 24 ++#define VPE_DELTA_EV_THR_MASK 0x0f ++#define VPE_DELTA_EV_THR_SHIFT 28 ++ ++#define VPE_SC_MP_SC18 0x0748 ++#define VPE_HS_FACTOR_MASK 0x03ff ++#define VPE_HS_FACTOR_SHIFT 0 ++#define VPE_CONF_DEFAULT_MASK 0x01ff ++#define VPE_CONF_DEFAULT_SHIFT 16 ++ ++#define VPE_SC_MP_SC19 0x074c ++#define VPE_HPF_COEFF0_MASK 0xff ++#define VPE_HPF_COEFF0_SHIFT 0 ++#define VPE_HPF_COEFF1_MASK 0xff ++#define VPE_HPF_COEFF1_SHIFT 8 ++#define VPE_HPF_COEFF2_MASK 0xff ++#define VPE_HPF_COEFF2_SHIFT 16 ++#define VPE_HPF_COEFF3_MASK 0xff ++#define VPE_HPF_COEFF3_SHIFT 23 ++ ++#define VPE_SC_MP_SC20 0x0750 ++#define VPE_HPF_COEFF4_MASK 0xff ++#define VPE_HPF_COEFF4_SHIFT 0 ++#define VPE_HPF_COEFF5_MASK 0xff ++#define VPE_HPF_COEFF5_SHIFT 8 ++#define VPE_HPF_NORM_SHIFT_MASK 0x07 ++#define VPE_HPF_NORM_SHIFT_SHIFT 16 ++#define VPE_NL_LIMIT_MASK 0x1ff ++#define VPE_NL_LIMIT_SHIFT 20 ++ ++#define VPE_SC_MP_SC21 0x0754 ++#define VPE_NL_LO_THR_MASK 0x01ff ++#define VPE_NL_LO_THR_SHIFT 0 ++#define VPE_NL_LO_SLOPE_MASK 0xff ++#define VPE_NL_LO_SLOPE_SHIFT 16 ++ ++#define VPE_SC_MP_SC22 0x0758 ++#define VPE_NL_HI_THR_MASK 0x01ff ++#define VPE_NL_HI_THR_SHIFT 0 ++#define VPE_NL_HI_SLOPE_SH_MASK 0x07 ++#define VPE_NL_HI_SLOPE_SH_SHIFT 16 ++ ++#define VPE_SC_MP_SC23 0x075c ++#define VPE_GRADIENT_THR_MASK 0x07ff ++#define VPE_GRADIENT_THR_SHIFT 0 ++#define VPE_GRADIENT_THR_RANGE_MASK 0x0f ++#define VPE_GRADIENT_THR_RANGE_SHIFT 12 ++#define VPE_MIN_GY_THR_MASK 0xff ++#define VPE_MIN_GY_THR_SHIFT 16 ++#define VPE_MIN_GY_THR_RANGE_MASK 0x0f ++#define VPE_MIN_GY_THR_RANGE_SHIFT 28 ++ ++#define VPE_SC_MP_SC24 0x0760 ++#define VPE_ORG_H_MASK 0x07ff ++#define VPE_ORG_H_SHIFT 0 ++#define VPE_ORG_W_MASK 0x07ff ++#define VPE_ORG_W_SHIFT 16 ++ ++#define VPE_SC_MP_SC25 0x0764 ++#define VPE_OFF_H_MASK 0x07ff ++#define VPE_OFF_H_SHIFT 0 ++#define VPE_OFF_W_MASK 0x07ff ++#define VPE_OFF_W_SHIFT 16 ++ ++/* VPE color space converter regs */ ++#define VPE_CSC_CSC00 0x5700 ++#define VPE_CSC_A0_MASK 0x1fff ++#define VPE_CSC_A0_SHIFT 0 ++#define VPE_CSC_B0_MASK 0x1fff ++#define VPE_CSC_B0_SHIFT 16 ++ ++#define VPE_CSC_CSC01 0x5704 ++#define VPE_CSC_C0_MASK 0x1fff ++#define VPE_CSC_C0_SHIFT 0 ++#define VPE_CSC_A1_MASK 0x1fff ++#define VPE_CSC_A1_SHIFT 16 ++ ++#define VPE_CSC_CSC02 0x5708 ++#define VPE_CSC_B1_MASK 0x1fff ++#define VPE_CSC_B1_SHIFT 0 ++#define VPE_CSC_C1_MASK 0x1fff ++#define VPE_CSC_C1_SHIFT 16 ++ ++#define VPE_CSC_CSC03 0x570c ++#define VPE_CSC_A2_MASK 0x1fff ++#define VPE_CSC_A2_SHIFT 0 ++#define VPE_CSC_B2_MASK 0x1fff ++#define VPE_CSC_B2_SHIFT 16 ++ ++#define VPE_CSC_CSC04 0x5710 ++#define VPE_CSC_C2_MASK 0x1fff ++#define VPE_CSC_C2_SHIFT 0 ++#define VPE_CSC_D0_MASK 0x0fff ++#define VPE_CSC_D0_SHIFT 16 ++ ++#define VPE_CSC_CSC05 0x5714 ++#define VPE_CSC_D1_MASK 0x0fff ++#define VPE_CSC_D1_SHIFT 0 ++#define VPE_CSC_D2_MASK 0x0fff ++#define VPE_CSC_D2_SHIFT 16 ++#define VPE_CSC_BYPASS (1 << 28) ++ ++#endif +--- a/drivers/memory/emif.h ++++ b/drivers/memory/emif.h +@@ -12,548 +12,7 @@ + #ifndef __EMIF_H + #define __EMIF_H + +-/* +- * 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 +- +-/* State of the core voltage */ +-#define DDR_VOLTAGE_STABLE 0 +-#define DDR_VOLTAGE_RAMPING 1 +- +-/* Defines for timing De-rating */ +-#define EMIF_NORMAL_TIMINGS 0 +-#define EMIF_DERATED_TIMINGS 1 +- +-/* Length of the forced read idle period in terms of cycles */ +-#define EMIF_READ_IDLE_LEN_VAL 5 +- +-/* +- * forced read idle interval to be used when voltage +- * is changed as part of DVFS/DPS - 1ms +- */ +-#define READ_IDLE_INTERVAL_DVFS (1*1000000) +- +-/* +- * Forced read idle interval to be used when voltage is stable +- * 50us - or maximum value will do +- */ +-#define READ_IDLE_INTERVAL_NORMAL (50*1000000) +- +-/* DLL calibration interval when voltage is NOT stable - 1us */ +-#define DLL_CALIB_INTERVAL_DVFS (1*1000000) +- +-#define DLL_CALIB_ACK_WAIT_VAL 5 +- +-/* Interval between ZQCS commands - hw team recommended value */ +-#define EMIF_ZQCS_INTERVAL_US (50*1000) +-/* Enable ZQ Calibration on exiting Self-refresh */ +-#define ZQ_SFEXITEN_ENABLE 1 +-/* +- * ZQ Calibration simultaneously on both chip-selects: +- * Needs one calibration resistor per CS +- */ +-#define ZQ_DUALCALEN_DISABLE 0 +-#define ZQ_DUALCALEN_ENABLE 1 +- +-#define T_ZQCS_DEFAULT_NS 90 +-#define T_ZQCL_DEFAULT_NS 360 +-#define T_ZQINIT_DEFAULT_NS 1000 +- +-/* DPD_EN */ +-#define DPD_DISABLE 0 +-#define DPD_ENABLE 1 +- +-/* +- * Default values for the low-power entry to be used if not provided by user. +- * OMAP4/5 has a hw bug(i735) due to which this value can not be less than 512 +- * Timeout values are in DDR clock 'cycles' and frequency threshold in Hz +- */ +-#define EMIF_LP_MODE_TIMEOUT_PERFORMANCE 2048 +-#define EMIF_LP_MODE_TIMEOUT_POWER 512 +-#define EMIF_LP_MODE_FREQ_THRESHOLD 400000000 +- +-/* DDR_PHY_CTRL_1 values for EMIF4D - ATTILA PHY combination */ +-#define EMIF_DDR_PHY_CTRL_1_BASE_VAL_ATTILAPHY 0x049FF000 +-#define EMIF_DLL_SLAVE_DLY_CTRL_400_MHZ_ATTILAPHY 0x41 +-#define EMIF_DLL_SLAVE_DLY_CTRL_200_MHZ_ATTILAPHY 0x80 +-#define EMIF_DLL_SLAVE_DLY_CTRL_100_MHZ_AND_LESS_ATTILAPHY 0xFF +- +-/* DDR_PHY_CTRL_1 values for EMIF4D5 INTELLIPHY combination */ +-#define EMIF_DDR_PHY_CTRL_1_BASE_VAL_INTELLIPHY 0x0E084200 +-#define EMIF_PHY_TOTAL_READ_LATENCY_INTELLIPHY_PS 10000 +- +-/* TEMP_ALERT_CONFIG - corresponding to temp gradient 5 C/s */ +-#define TEMP_ALERT_POLL_INTERVAL_DEFAULT_MS 360 +- +-#define EMIF_T_CSTA 3 +-#define EMIF_T_PDLL_UL 128 +- +-/* External PHY control registers magic values */ +-#define EMIF_EXT_PHY_CTRL_1_VAL 0x04020080 +-#define EMIF_EXT_PHY_CTRL_5_VAL 0x04010040 +-#define EMIF_EXT_PHY_CTRL_6_VAL 0x01004010 +-#define EMIF_EXT_PHY_CTRL_7_VAL 0x00001004 +-#define EMIF_EXT_PHY_CTRL_8_VAL 0x04010040 +-#define EMIF_EXT_PHY_CTRL_9_VAL 0x01004010 +-#define EMIF_EXT_PHY_CTRL_10_VAL 0x00001004 +-#define EMIF_EXT_PHY_CTRL_11_VAL 0x00000000 +-#define EMIF_EXT_PHY_CTRL_12_VAL 0x00000000 +-#define EMIF_EXT_PHY_CTRL_13_VAL 0x00000000 +-#define EMIF_EXT_PHY_CTRL_14_VAL 0x80080080 +-#define EMIF_EXT_PHY_CTRL_15_VAL 0x00800800 +-#define EMIF_EXT_PHY_CTRL_16_VAL 0x08102040 +-#define EMIF_EXT_PHY_CTRL_17_VAL 0x00000001 +-#define EMIF_EXT_PHY_CTRL_18_VAL 0x540A8150 +-#define EMIF_EXT_PHY_CTRL_19_VAL 0xA81502A0 +-#define EMIF_EXT_PHY_CTRL_20_VAL 0x002A0540 +-#define EMIF_EXT_PHY_CTRL_21_VAL 0x00000000 +-#define EMIF_EXT_PHY_CTRL_22_VAL 0x00000000 +-#define EMIF_EXT_PHY_CTRL_23_VAL 0x00000000 +-#define EMIF_EXT_PHY_CTRL_24_VAL 0x00000077 +- +-#define EMIF_INTELLI_PHY_DQS_GATE_OPENING_DELAY_PS 1200 +- +-/* Registers offset */ +-#define EMIF_MODULE_ID_AND_REVISION 0x0000 +-#define EMIF_STATUS 0x0004 +-#define EMIF_SDRAM_CONFIG 0x0008 +-#define EMIF_SDRAM_CONFIG_2 0x000c +-#define EMIF_SDRAM_REFRESH_CONTROL 0x0010 +-#define EMIF_SDRAM_REFRESH_CTRL_SHDW 0x0014 +-#define EMIF_SDRAM_TIMING_1 0x0018 +-#define EMIF_SDRAM_TIMING_1_SHDW 0x001c +-#define EMIF_SDRAM_TIMING_2 0x0020 +-#define EMIF_SDRAM_TIMING_2_SHDW 0x0024 +-#define EMIF_SDRAM_TIMING_3 0x0028 +-#define EMIF_SDRAM_TIMING_3_SHDW 0x002c +-#define EMIF_LPDDR2_NVM_TIMING 0x0030 +-#define EMIF_LPDDR2_NVM_TIMING_SHDW 0x0034 +-#define EMIF_POWER_MANAGEMENT_CONTROL 0x0038 +-#define EMIF_POWER_MANAGEMENT_CTRL_SHDW 0x003c +-#define EMIF_LPDDR2_MODE_REG_DATA 0x0040 +-#define EMIF_LPDDR2_MODE_REG_CONFIG 0x0050 +-#define EMIF_OCP_CONFIG 0x0054 +-#define EMIF_OCP_CONFIG_VALUE_1 0x0058 +-#define EMIF_OCP_CONFIG_VALUE_2 0x005c +-#define EMIF_IODFT_TEST_LOGIC_GLOBAL_CONTROL 0x0060 +-#define EMIF_IODFT_TEST_LOGIC_CTRL_MISR_RESULT 0x0064 +-#define EMIF_IODFT_TEST_LOGIC_ADDRESS_MISR_RESULT 0x0068 +-#define EMIF_IODFT_TEST_LOGIC_DATA_MISR_RESULT_1 0x006c +-#define EMIF_IODFT_TEST_LOGIC_DATA_MISR_RESULT_2 0x0070 +-#define EMIF_IODFT_TEST_LOGIC_DATA_MISR_RESULT_3 0x0074 +-#define EMIF_PERFORMANCE_COUNTER_1 0x0080 +-#define EMIF_PERFORMANCE_COUNTER_2 0x0084 +-#define EMIF_PERFORMANCE_COUNTER_CONFIG 0x0088 +-#define EMIF_PERFORMANCE_COUNTER_MASTER_REGION_SELECT 0x008c +-#define EMIF_PERFORMANCE_COUNTER_TIME 0x0090 +-#define EMIF_MISC_REG 0x0094 +-#define EMIF_DLL_CALIB_CTRL 0x0098 +-#define EMIF_DLL_CALIB_CTRL_SHDW 0x009c +-#define EMIF_END_OF_INTERRUPT 0x00a0 +-#define EMIF_SYSTEM_OCP_INTERRUPT_RAW_STATUS 0x00a4 +-#define EMIF_LL_OCP_INTERRUPT_RAW_STATUS 0x00a8 +-#define EMIF_SYSTEM_OCP_INTERRUPT_STATUS 0x00ac +-#define EMIF_LL_OCP_INTERRUPT_STATUS 0x00b0 +-#define EMIF_SYSTEM_OCP_INTERRUPT_ENABLE_SET 0x00b4 +-#define EMIF_LL_OCP_INTERRUPT_ENABLE_SET 0x00b8 +-#define EMIF_SYSTEM_OCP_INTERRUPT_ENABLE_CLEAR 0x00bc +-#define EMIF_LL_OCP_INTERRUPT_ENABLE_CLEAR 0x00c0 +-#define EMIF_SDRAM_OUTPUT_IMPEDANCE_CALIBRATION_CONFIG 0x00c8 +-#define EMIF_TEMPERATURE_ALERT_CONFIG 0x00cc +-#define EMIF_OCP_ERROR_LOG 0x00d0 +-#define EMIF_READ_WRITE_LEVELING_RAMP_WINDOW 0x00d4 +-#define EMIF_READ_WRITE_LEVELING_RAMP_CONTROL 0x00d8 +-#define EMIF_READ_WRITE_LEVELING_CONTROL 0x00dc +-#define EMIF_DDR_PHY_CTRL_1 0x00e4 +-#define EMIF_DDR_PHY_CTRL_1_SHDW 0x00e8 +-#define EMIF_DDR_PHY_CTRL_2 0x00ec +-#define EMIF_PRIORITY_TO_CLASS_OF_SERVICE_MAPPING 0x0100 +-#define EMIF_CONNECTION_ID_TO_CLASS_OF_SERVICE_1_MAPPING 0x0104 +-#define EMIF_CONNECTION_ID_TO_CLASS_OF_SERVICE_2_MAPPING 0x0108 +-#define EMIF_READ_WRITE_EXECUTION_THRESHOLD 0x0120 +-#define EMIF_COS_CONFIG 0x0124 +-#define EMIF_PHY_STATUS_1 0x0140 +-#define EMIF_PHY_STATUS_2 0x0144 +-#define EMIF_PHY_STATUS_3 0x0148 +-#define EMIF_PHY_STATUS_4 0x014c +-#define EMIF_PHY_STATUS_5 0x0150 +-#define EMIF_PHY_STATUS_6 0x0154 +-#define EMIF_PHY_STATUS_7 0x0158 +-#define EMIF_PHY_STATUS_8 0x015c +-#define EMIF_PHY_STATUS_9 0x0160 +-#define EMIF_PHY_STATUS_10 0x0164 +-#define EMIF_PHY_STATUS_11 0x0168 +-#define EMIF_PHY_STATUS_12 0x016c +-#define EMIF_PHY_STATUS_13 0x0170 +-#define EMIF_PHY_STATUS_14 0x0174 +-#define EMIF_PHY_STATUS_15 0x0178 +-#define EMIF_PHY_STATUS_16 0x017c +-#define EMIF_PHY_STATUS_17 0x0180 +-#define EMIF_PHY_STATUS_18 0x0184 +-#define EMIF_PHY_STATUS_19 0x0188 +-#define EMIF_PHY_STATUS_20 0x018c +-#define EMIF_PHY_STATUS_21 0x0190 +-#define EMIF_EXT_PHY_CTRL_1 0x0200 +-#define EMIF_EXT_PHY_CTRL_1_SHDW 0x0204 +-#define EMIF_EXT_PHY_CTRL_2 0x0208 +-#define EMIF_EXT_PHY_CTRL_2_SHDW 0x020c +-#define EMIF_EXT_PHY_CTRL_3 0x0210 +-#define EMIF_EXT_PHY_CTRL_3_SHDW 0x0214 +-#define EMIF_EXT_PHY_CTRL_4 0x0218 +-#define EMIF_EXT_PHY_CTRL_4_SHDW 0x021c +-#define EMIF_EXT_PHY_CTRL_5 0x0220 +-#define EMIF_EXT_PHY_CTRL_5_SHDW 0x0224 +-#define EMIF_EXT_PHY_CTRL_6 0x0228 +-#define EMIF_EXT_PHY_CTRL_6_SHDW 0x022c +-#define EMIF_EXT_PHY_CTRL_7 0x0230 +-#define EMIF_EXT_PHY_CTRL_7_SHDW 0x0234 +-#define EMIF_EXT_PHY_CTRL_8 0x0238 +-#define EMIF_EXT_PHY_CTRL_8_SHDW 0x023c +-#define EMIF_EXT_PHY_CTRL_9 0x0240 +-#define EMIF_EXT_PHY_CTRL_9_SHDW 0x0244 +-#define EMIF_EXT_PHY_CTRL_10 0x0248 +-#define EMIF_EXT_PHY_CTRL_10_SHDW 0x024c +-#define EMIF_EXT_PHY_CTRL_11 0x0250 +-#define EMIF_EXT_PHY_CTRL_11_SHDW 0x0254 +-#define EMIF_EXT_PHY_CTRL_12 0x0258 +-#define EMIF_EXT_PHY_CTRL_12_SHDW 0x025c +-#define EMIF_EXT_PHY_CTRL_13 0x0260 +-#define EMIF_EXT_PHY_CTRL_13_SHDW 0x0264 +-#define EMIF_EXT_PHY_CTRL_14 0x0268 +-#define EMIF_EXT_PHY_CTRL_14_SHDW 0x026c +-#define EMIF_EXT_PHY_CTRL_15 0x0270 +-#define EMIF_EXT_PHY_CTRL_15_SHDW 0x0274 +-#define EMIF_EXT_PHY_CTRL_16 0x0278 +-#define EMIF_EXT_PHY_CTRL_16_SHDW 0x027c +-#define EMIF_EXT_PHY_CTRL_17 0x0280 +-#define EMIF_EXT_PHY_CTRL_17_SHDW 0x0284 +-#define EMIF_EXT_PHY_CTRL_18 0x0288 +-#define EMIF_EXT_PHY_CTRL_18_SHDW 0x028c +-#define EMIF_EXT_PHY_CTRL_19 0x0290 +-#define EMIF_EXT_PHY_CTRL_19_SHDW 0x0294 +-#define EMIF_EXT_PHY_CTRL_20 0x0298 +-#define EMIF_EXT_PHY_CTRL_20_SHDW 0x029c +-#define EMIF_EXT_PHY_CTRL_21 0x02a0 +-#define EMIF_EXT_PHY_CTRL_21_SHDW 0x02a4 +-#define EMIF_EXT_PHY_CTRL_22 0x02a8 +-#define EMIF_EXT_PHY_CTRL_22_SHDW 0x02ac +-#define EMIF_EXT_PHY_CTRL_23 0x02b0 +-#define EMIF_EXT_PHY_CTRL_23_SHDW 0x02b4 +-#define EMIF_EXT_PHY_CTRL_24 0x02b8 +-#define EMIF_EXT_PHY_CTRL_24_SHDW 0x02bc +-#define EMIF_EXT_PHY_CTRL_25 0x02c0 +-#define EMIF_EXT_PHY_CTRL_25_SHDW 0x02c4 +-#define EMIF_EXT_PHY_CTRL_26 0x02c8 +-#define EMIF_EXT_PHY_CTRL_26_SHDW 0x02cc +-#define EMIF_EXT_PHY_CTRL_27 0x02d0 +-#define EMIF_EXT_PHY_CTRL_27_SHDW 0x02d4 +-#define EMIF_EXT_PHY_CTRL_28 0x02d8 +-#define EMIF_EXT_PHY_CTRL_28_SHDW 0x02dc +-#define EMIF_EXT_PHY_CTRL_29 0x02e0 +-#define EMIF_EXT_PHY_CTRL_29_SHDW 0x02e4 +-#define EMIF_EXT_PHY_CTRL_30 0x02e8 +-#define EMIF_EXT_PHY_CTRL_30_SHDW 0x02ec +- +-/* Registers shifts and masks */ +- +-/* EMIF_MODULE_ID_AND_REVISION */ +-#define SCHEME_SHIFT 30 +-#define SCHEME_MASK (0x3 << 30) +-#define MODULE_ID_SHIFT 16 +-#define MODULE_ID_MASK (0xfff << 16) +-#define RTL_VERSION_SHIFT 11 +-#define RTL_VERSION_MASK (0x1f << 11) +-#define MAJOR_REVISION_SHIFT 8 +-#define MAJOR_REVISION_MASK (0x7 << 8) +-#define MINOR_REVISION_SHIFT 0 +-#define MINOR_REVISION_MASK (0x3f << 0) +- +-/* STATUS */ +-#define BE_SHIFT 31 +-#define BE_MASK (1 << 31) +-#define DUAL_CLK_MODE_SHIFT 30 +-#define DUAL_CLK_MODE_MASK (1 << 30) +-#define FAST_INIT_SHIFT 29 +-#define FAST_INIT_MASK (1 << 29) +-#define RDLVLGATETO_SHIFT 6 +-#define RDLVLGATETO_MASK (1 << 6) +-#define RDLVLTO_SHIFT 5 +-#define RDLVLTO_MASK (1 << 5) +-#define WRLVLTO_SHIFT 4 +-#define WRLVLTO_MASK (1 << 4) +-#define PHY_DLL_READY_SHIFT 2 +-#define PHY_DLL_READY_MASK (1 << 2) +- +-/* SDRAM_CONFIG */ +-#define SDRAM_TYPE_SHIFT 29 +-#define SDRAM_TYPE_MASK (0x7 << 29) +-#define IBANK_POS_SHIFT 27 +-#define IBANK_POS_MASK (0x3 << 27) +-#define DDR_TERM_SHIFT 24 +-#define DDR_TERM_MASK (0x7 << 24) +-#define DDR2_DDQS_SHIFT 23 +-#define DDR2_DDQS_MASK (1 << 23) +-#define DYN_ODT_SHIFT 21 +-#define DYN_ODT_MASK (0x3 << 21) +-#define DDR_DISABLE_DLL_SHIFT 20 +-#define DDR_DISABLE_DLL_MASK (1 << 20) +-#define SDRAM_DRIVE_SHIFT 18 +-#define SDRAM_DRIVE_MASK (0x3 << 18) +-#define CWL_SHIFT 16 +-#define CWL_MASK (0x3 << 16) +-#define NARROW_MODE_SHIFT 14 +-#define NARROW_MODE_MASK (0x3 << 14) +-#define CL_SHIFT 10 +-#define CL_MASK (0xf << 10) +-#define ROWSIZE_SHIFT 7 +-#define ROWSIZE_MASK (0x7 << 7) +-#define IBANK_SHIFT 4 +-#define IBANK_MASK (0x7 << 4) +-#define EBANK_SHIFT 3 +-#define EBANK_MASK (1 << 3) +-#define PAGESIZE_SHIFT 0 +-#define PAGESIZE_MASK (0x7 << 0) +- +-/* SDRAM_CONFIG_2 */ +-#define CS1NVMEN_SHIFT 30 +-#define CS1NVMEN_MASK (1 << 30) +-#define EBANK_POS_SHIFT 27 +-#define EBANK_POS_MASK (1 << 27) +-#define RDBNUM_SHIFT 4 +-#define RDBNUM_MASK (0x3 << 4) +-#define RDBSIZE_SHIFT 0 +-#define RDBSIZE_MASK (0x7 << 0) +- +-/* SDRAM_REFRESH_CONTROL */ +-#define INITREF_DIS_SHIFT 31 +-#define INITREF_DIS_MASK (1 << 31) +-#define SRT_SHIFT 29 +-#define SRT_MASK (1 << 29) +-#define ASR_SHIFT 28 +-#define ASR_MASK (1 << 28) +-#define PASR_SHIFT 24 +-#define PASR_MASK (0x7 << 24) +-#define REFRESH_RATE_SHIFT 0 +-#define REFRESH_RATE_MASK (0xffff << 0) +- +-/* SDRAM_TIMING_1 */ +-#define T_RTW_SHIFT 29 +-#define T_RTW_MASK (0x7 << 29) +-#define T_RP_SHIFT 25 +-#define T_RP_MASK (0xf << 25) +-#define T_RCD_SHIFT 21 +-#define T_RCD_MASK (0xf << 21) +-#define T_WR_SHIFT 17 +-#define T_WR_MASK (0xf << 17) +-#define T_RAS_SHIFT 12 +-#define T_RAS_MASK (0x1f << 12) +-#define T_RC_SHIFT 6 +-#define T_RC_MASK (0x3f << 6) +-#define T_RRD_SHIFT 3 +-#define T_RRD_MASK (0x7 << 3) +-#define T_WTR_SHIFT 0 +-#define T_WTR_MASK (0x7 << 0) +- +-/* SDRAM_TIMING_2 */ +-#define T_XP_SHIFT 28 +-#define T_XP_MASK (0x7 << 28) +-#define T_ODT_SHIFT 25 +-#define T_ODT_MASK (0x7 << 25) +-#define T_XSNR_SHIFT 16 +-#define T_XSNR_MASK (0x1ff << 16) +-#define T_XSRD_SHIFT 6 +-#define T_XSRD_MASK (0x3ff << 6) +-#define T_RTP_SHIFT 3 +-#define T_RTP_MASK (0x7 << 3) +-#define T_CKE_SHIFT 0 +-#define T_CKE_MASK (0x7 << 0) +- +-/* SDRAM_TIMING_3 */ +-#define T_PDLL_UL_SHIFT 28 +-#define T_PDLL_UL_MASK (0xf << 28) +-#define T_CSTA_SHIFT 24 +-#define T_CSTA_MASK (0xf << 24) +-#define T_CKESR_SHIFT 21 +-#define T_CKESR_MASK (0x7 << 21) +-#define ZQ_ZQCS_SHIFT 15 +-#define ZQ_ZQCS_MASK (0x3f << 15) +-#define T_TDQSCKMAX_SHIFT 13 +-#define T_TDQSCKMAX_MASK (0x3 << 13) +-#define T_RFC_SHIFT 4 +-#define T_RFC_MASK (0x1ff << 4) +-#define T_RAS_MAX_SHIFT 0 +-#define T_RAS_MAX_MASK (0xf << 0) +- +-/* POWER_MANAGEMENT_CONTROL */ +-#define PD_TIM_SHIFT 12 +-#define PD_TIM_MASK (0xf << 12) +-#define DPD_EN_SHIFT 11 +-#define DPD_EN_MASK (1 << 11) +-#define LP_MODE_SHIFT 8 +-#define LP_MODE_MASK (0x7 << 8) +-#define SR_TIM_SHIFT 4 +-#define SR_TIM_MASK (0xf << 4) +-#define CS_TIM_SHIFT 0 +-#define CS_TIM_MASK (0xf << 0) +- +-/* LPDDR2_MODE_REG_DATA */ +-#define VALUE_0_SHIFT 0 +-#define VALUE_0_MASK (0x7f << 0) +- +-/* LPDDR2_MODE_REG_CONFIG */ +-#define CS_SHIFT 31 +-#define CS_MASK (1 << 31) +-#define REFRESH_EN_SHIFT 30 +-#define REFRESH_EN_MASK (1 << 30) +-#define ADDRESS_SHIFT 0 +-#define ADDRESS_MASK (0xff << 0) +- +-/* OCP_CONFIG */ +-#define SYS_THRESH_MAX_SHIFT 24 +-#define SYS_THRESH_MAX_MASK (0xf << 24) +-#define MPU_THRESH_MAX_SHIFT 20 +-#define MPU_THRESH_MAX_MASK (0xf << 20) +-#define LL_THRESH_MAX_SHIFT 16 +-#define LL_THRESH_MAX_MASK (0xf << 16) +- +-/* PERFORMANCE_COUNTER_1 */ +-#define COUNTER1_SHIFT 0 +-#define COUNTER1_MASK (0xffffffff << 0) +- +-/* PERFORMANCE_COUNTER_2 */ +-#define COUNTER2_SHIFT 0 +-#define COUNTER2_MASK (0xffffffff << 0) +- +-/* PERFORMANCE_COUNTER_CONFIG */ +-#define CNTR2_MCONNID_EN_SHIFT 31 +-#define CNTR2_MCONNID_EN_MASK (1 << 31) +-#define CNTR2_REGION_EN_SHIFT 30 +-#define CNTR2_REGION_EN_MASK (1 << 30) +-#define CNTR2_CFG_SHIFT 16 +-#define CNTR2_CFG_MASK (0xf << 16) +-#define CNTR1_MCONNID_EN_SHIFT 15 +-#define CNTR1_MCONNID_EN_MASK (1 << 15) +-#define CNTR1_REGION_EN_SHIFT 14 +-#define CNTR1_REGION_EN_MASK (1 << 14) +-#define CNTR1_CFG_SHIFT 0 +-#define CNTR1_CFG_MASK (0xf << 0) +- +-/* PERFORMANCE_COUNTER_MASTER_REGION_SELECT */ +-#define MCONNID2_SHIFT 24 +-#define MCONNID2_MASK (0xff << 24) +-#define REGION_SEL2_SHIFT 16 +-#define REGION_SEL2_MASK (0x3 << 16) +-#define MCONNID1_SHIFT 8 +-#define MCONNID1_MASK (0xff << 8) +-#define REGION_SEL1_SHIFT 0 +-#define REGION_SEL1_MASK (0x3 << 0) +- +-/* PERFORMANCE_COUNTER_TIME */ +-#define TOTAL_TIME_SHIFT 0 +-#define TOTAL_TIME_MASK (0xffffffff << 0) +- +-/* DLL_CALIB_CTRL */ +-#define ACK_WAIT_SHIFT 16 +-#define ACK_WAIT_MASK (0xf << 16) +-#define DLL_CALIB_INTERVAL_SHIFT 0 +-#define DLL_CALIB_INTERVAL_MASK (0x1ff << 0) +- +-/* END_OF_INTERRUPT */ +-#define EOI_SHIFT 0 +-#define EOI_MASK (1 << 0) +- +-/* SYSTEM_OCP_INTERRUPT_RAW_STATUS */ +-#define DNV_SYS_SHIFT 2 +-#define DNV_SYS_MASK (1 << 2) +-#define TA_SYS_SHIFT 1 +-#define TA_SYS_MASK (1 << 1) +-#define ERR_SYS_SHIFT 0 +-#define ERR_SYS_MASK (1 << 0) +- +-/* LOW_LATENCY_OCP_INTERRUPT_RAW_STATUS */ +-#define DNV_LL_SHIFT 2 +-#define DNV_LL_MASK (1 << 2) +-#define TA_LL_SHIFT 1 +-#define TA_LL_MASK (1 << 1) +-#define ERR_LL_SHIFT 0 +-#define ERR_LL_MASK (1 << 0) +- +-/* SYSTEM_OCP_INTERRUPT_ENABLE_SET */ +-#define EN_DNV_SYS_SHIFT 2 +-#define EN_DNV_SYS_MASK (1 << 2) +-#define EN_TA_SYS_SHIFT 1 +-#define EN_TA_SYS_MASK (1 << 1) +-#define EN_ERR_SYS_SHIFT 0 +-#define EN_ERR_SYS_MASK (1 << 0) +- +-/* LOW_LATENCY_OCP_INTERRUPT_ENABLE_SET */ +-#define EN_DNV_LL_SHIFT 2 +-#define EN_DNV_LL_MASK (1 << 2) +-#define EN_TA_LL_SHIFT 1 +-#define EN_TA_LL_MASK (1 << 1) +-#define EN_ERR_LL_SHIFT 0 +-#define EN_ERR_LL_MASK (1 << 0) +- +-/* SDRAM_OUTPUT_IMPEDANCE_CALIBRATION_CONFIG */ +-#define ZQ_CS1EN_SHIFT 31 +-#define ZQ_CS1EN_MASK (1 << 31) +-#define ZQ_CS0EN_SHIFT 30 +-#define ZQ_CS0EN_MASK (1 << 30) +-#define ZQ_DUALCALEN_SHIFT 29 +-#define ZQ_DUALCALEN_MASK (1 << 29) +-#define ZQ_SFEXITEN_SHIFT 28 +-#define ZQ_SFEXITEN_MASK (1 << 28) +-#define ZQ_ZQINIT_MULT_SHIFT 18 +-#define ZQ_ZQINIT_MULT_MASK (0x3 << 18) +-#define ZQ_ZQCL_MULT_SHIFT 16 +-#define ZQ_ZQCL_MULT_MASK (0x3 << 16) +-#define ZQ_REFINTERVAL_SHIFT 0 +-#define ZQ_REFINTERVAL_MASK (0xffff << 0) +- +-/* TEMPERATURE_ALERT_CONFIG */ +-#define TA_CS1EN_SHIFT 31 +-#define TA_CS1EN_MASK (1 << 31) +-#define TA_CS0EN_SHIFT 30 +-#define TA_CS0EN_MASK (1 << 30) +-#define TA_SFEXITEN_SHIFT 28 +-#define TA_SFEXITEN_MASK (1 << 28) +-#define TA_DEVWDT_SHIFT 26 +-#define TA_DEVWDT_MASK (0x3 << 26) +-#define TA_DEVCNT_SHIFT 24 +-#define TA_DEVCNT_MASK (0x3 << 24) +-#define TA_REFINTERVAL_SHIFT 0 +-#define TA_REFINTERVAL_MASK (0x3fffff << 0) +- +-/* OCP_ERROR_LOG */ +-#define MADDRSPACE_SHIFT 14 +-#define MADDRSPACE_MASK (0x3 << 14) +-#define MBURSTSEQ_SHIFT 11 +-#define MBURSTSEQ_MASK (0x7 << 11) +-#define MCMD_SHIFT 8 +-#define MCMD_MASK (0x7 << 8) +-#define MCONNID_SHIFT 0 +-#define MCONNID_MASK (0xff << 0) +- +-/* DDR_PHY_CTRL_1 - EMIF4D */ +-#define DLL_SLAVE_DLY_CTRL_SHIFT_4D 4 +-#define DLL_SLAVE_DLY_CTRL_MASK_4D (0xFF << 4) +-#define READ_LATENCY_SHIFT_4D 0 +-#define READ_LATENCY_MASK_4D (0xf << 0) +- +-/* DDR_PHY_CTRL_1 - EMIF4D5 */ +-#define DLL_HALF_DELAY_SHIFT_4D5 21 +-#define DLL_HALF_DELAY_MASK_4D5 (1 << 21) +-#define READ_LATENCY_SHIFT_4D5 0 +-#define READ_LATENCY_MASK_4D5 (0x1f << 0) +- +-/* DDR_PHY_CTRL_1_SHDW */ +-#define DDR_PHY_CTRL_1_SHDW_SHIFT 5 +-#define DDR_PHY_CTRL_1_SHDW_MASK (0x7ffffff << 5) +-#define READ_LATENCY_SHDW_SHIFT 0 +-#define READ_LATENCY_SHDW_MASK (0x1f << 0) ++#include <linux/ti_emif.h> + + #ifndef __ASSEMBLY__ + /* +--- a/drivers/mfd/Kconfig ++++ b/drivers/mfd/Kconfig +@@ -821,6 +821,17 @@ config MFD_TPS65217 + This driver can also be built as a module. If so, the module + will be called tps65217. + ++config MFD_TPS65218 ++ bool "TI TPS65218 Power Management chips" ++ depends on I2C ++ select MFD_CORE ++ select REGMAP_I2C ++ help ++ If you say yes here you get support for the TPS65218 series of ++ Power Management chips. ++ These include voltage regulators, gpio and other features ++ that are often used in portable devices. ++ + config MFD_TPS6586X + bool "TI TPS6586x Power Management chips" + depends on I2C=y +--- a/drivers/mfd/Makefile ++++ b/drivers/mfd/Makefile +@@ -62,6 +62,7 @@ obj-$(CONFIG_TPS6105X) += tps6105x.o + obj-$(CONFIG_TPS65010) += tps65010.o + obj-$(CONFIG_TPS6507X) += tps6507x.o + obj-$(CONFIG_MFD_TPS65217) += tps65217.o ++obj-$(CONFIG_MFD_TPS65218) += tps65218.o + obj-$(CONFIG_MFD_TPS65910) += tps65910.o + tps65912-objs := tps65912-core.o tps65912-irq.o + obj-$(CONFIG_MFD_TPS65912) += tps65912.o +--- a/drivers/mfd/omap-usb-host.c ++++ b/drivers/mfd/omap-usb-host.c +@@ -328,13 +328,13 @@ static int usbhs_runtime_resume(struct d + omap_tll_enable(pdata); + + if (!IS_ERR(omap->ehci_logic_fck)) +- clk_enable(omap->ehci_logic_fck); ++ clk_prepare_enable(omap->ehci_logic_fck); + + for (i = 0; i < omap->nports; i++) { + switch (pdata->port_mode[i]) { + case OMAP_EHCI_PORT_MODE_HSIC: + if (!IS_ERR(omap->hsic60m_clk[i])) { +- r = clk_enable(omap->hsic60m_clk[i]); ++ r = clk_prepare_enable(omap->hsic60m_clk[i]); + if (r) { + dev_err(dev, + "Can't enable port %d hsic60m clk:%d\n", +@@ -343,7 +343,7 @@ static int usbhs_runtime_resume(struct d + } + + if (!IS_ERR(omap->hsic480m_clk[i])) { +- r = clk_enable(omap->hsic480m_clk[i]); ++ r = clk_prepare_enable(omap->hsic480m_clk[i]); + if (r) { + dev_err(dev, + "Can't enable port %d hsic480m clk:%d\n", +@@ -354,7 +354,7 @@ static int usbhs_runtime_resume(struct d + + case OMAP_EHCI_PORT_MODE_TLL: + if (!IS_ERR(omap->utmi_clk[i])) { +- r = clk_enable(omap->utmi_clk[i]); ++ r = clk_prepare_enable(omap->utmi_clk[i]); + if (r) { + dev_err(dev, + "Can't enable port %d clk : %d\n", +@@ -382,15 +382,15 @@ static int usbhs_runtime_suspend(struct + switch (pdata->port_mode[i]) { + case OMAP_EHCI_PORT_MODE_HSIC: + if (!IS_ERR(omap->hsic60m_clk[i])) +- clk_disable(omap->hsic60m_clk[i]); ++ clk_disable_unprepare(omap->hsic60m_clk[i]); + + if (!IS_ERR(omap->hsic480m_clk[i])) +- clk_disable(omap->hsic480m_clk[i]); ++ clk_disable_unprepare(omap->hsic480m_clk[i]); + /* Fall through as utmi_clks were used in HSIC mode */ + + case OMAP_EHCI_PORT_MODE_TLL: + if (!IS_ERR(omap->utmi_clk[i])) +- clk_disable(omap->utmi_clk[i]); ++ clk_disable_unprepare(omap->utmi_clk[i]); + break; + default: + break; +@@ -398,7 +398,7 @@ static int usbhs_runtime_suspend(struct + } + + if (!IS_ERR(omap->ehci_logic_fck)) +- clk_disable(omap->ehci_logic_fck); ++ clk_disable_unprepare(omap->ehci_logic_fck); + + omap_tll_disable(pdata); + +--- a/drivers/mfd/omap-usb-tll.c ++++ b/drivers/mfd/omap-usb-tll.c +@@ -429,7 +429,7 @@ int omap_tll_enable(struct usbhs_omap_pl + if (IS_ERR(tll->ch_clk[i])) + continue; + +- r = clk_enable(tll->ch_clk[i]); ++ r = clk_prepare_enable(tll->ch_clk[i]); + if (r) { + dev_err(tll_dev, + "Error enabling ch %d clock: %d\n", i, r); +@@ -460,7 +460,7 @@ int omap_tll_disable(struct usbhs_omap_p + for (i = 0; i < tll->nch; i++) { + if (omap_usb_mode_needs_tll(pdata->port_mode[i])) { + if (!IS_ERR(tll->ch_clk[i])) +- clk_disable(tll->ch_clk[i]); ++ clk_disable_unprepare(tll->ch_clk[i]); + } + } + +--- a/drivers/mfd/ti_am335x_tscadc.c ++++ b/drivers/mfd/ti_am335x_tscadc.c +@@ -56,21 +56,25 @@ EXPORT_SYMBOL_GPL(am335x_tsc_se_update); + + void am335x_tsc_se_set(struct ti_tscadc_dev *tsadc, u32 val) + { +- spin_lock(&tsadc->reg_lock); ++ unsigned long flags; ++ ++ spin_lock_irqsave(&tsadc->reg_lock, flags); + tsadc->reg_se_cache = tscadc_readl(tsadc, REG_SE); + tsadc->reg_se_cache |= val; + am335x_tsc_se_update(tsadc); +- spin_unlock(&tsadc->reg_lock); ++ spin_unlock_irqrestore(&tsadc->reg_lock, flags); + } + EXPORT_SYMBOL_GPL(am335x_tsc_se_set); + + void am335x_tsc_se_clr(struct ti_tscadc_dev *tsadc, u32 val) + { +- spin_lock(&tsadc->reg_lock); ++ unsigned long flags; ++ ++ spin_lock_irqsave(&tsadc->reg_lock, flags); + tsadc->reg_se_cache = tscadc_readl(tsadc, REG_SE); + tsadc->reg_se_cache &= ~val; + am335x_tsc_se_update(tsadc); +- spin_unlock(&tsadc->reg_lock); ++ spin_unlock_irqrestore(&tsadc->reg_lock, flags); + } + EXPORT_SYMBOL_GPL(am335x_tsc_se_clr); + +--- /dev/null ++++ b/drivers/mfd/tps65218.c +@@ -0,0 +1,275 @@ ++/* ++ * TPS65218 chip family multi-function driver ++ * ++ * Copyright (C) 2013 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 version 2 as ++ * published by the Free Software Foundation. ++ * ++ * This program is distributed "as is" WITHOUT ANY WARRANTY of any ++ * kind, whether expressed or implied; without even the implied warranty ++ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License version 2 for more details. ++ */ ++ ++#include <linux/kernel.h> ++#include <linux/device.h> ++#include <linux/module.h> ++#include <linux/platform_device.h> ++#include <linux/init.h> ++#include <linux/i2c.h> ++#include <linux/slab.h> ++#include <linux/regmap.h> ++#include <linux/err.h> ++#include <linux/of.h> ++#include <linux/of_device.h> ++#include <linux/irq.h> ++#include <linux/interrupt.h> ++#include <linux/mutex.h> ++ ++#include <linux/mfd/core.h> ++#include <linux/mfd/tps65218.h> ++ ++#define TPS65218_PASSWORD_REGS_UNLOCK 0x7D ++ ++/** ++ * tps65218_reg_read: Read a single tps65218 register. ++ * ++ * @tps: Device to read from. ++ * @reg: Register to read. ++ * @val: Contians the value ++ */ ++int tps65218_reg_read(struct tps65218 *tps, unsigned int reg, ++ unsigned int *val) ++{ ++ return regmap_read(tps->regmap, reg, val); ++} ++EXPORT_SYMBOL_GPL(tps65218_reg_read); ++ ++/** ++ * tps65218_reg_write: Write a single tps65218 register. ++ * ++ * @tps65218: Device to write to. ++ * @reg: Register to write to. ++ * @val: Value to write. ++ * @level: Password protected level ++ */ ++int tps65218_reg_write(struct tps65218 *tps, unsigned int reg, ++ unsigned int val, unsigned int level) ++{ ++ int ret; ++ unsigned int xor_reg_val; ++ ++ switch (level) { ++ case TPS65218_PROTECT_NONE: ++ return regmap_write(tps->regmap, reg, val); ++ case TPS65218_PROTECT_L1: ++ xor_reg_val = reg ^ TPS65218_PASSWORD_REGS_UNLOCK; ++ ret = regmap_write(tps->regmap, TPS65218_REG_PASSWORD, ++ xor_reg_val); ++ if (ret < 0) ++ return ret; ++ ++ return regmap_write(tps->regmap, reg, val); ++ default: ++ return -EINVAL; ++ } ++} ++EXPORT_SYMBOL_GPL(tps65218_reg_write); ++ ++/** ++ * tps65218_update_bits: Modify bits w.r.t mask, val and level. ++ * ++ * @tps65218: Device to write to. ++ * @reg: Register to read-write to. ++ * @mask: Mask. ++ * @val: Value to write. ++ * @level: Password protected level ++ */ ++static int tps65218_update_bits(struct tps65218 *tps, unsigned int reg, ++ unsigned int mask, unsigned int val, unsigned int level) ++{ ++ int ret; ++ unsigned int data; ++ ++ ret = tps65218_reg_read(tps, reg, &data); ++ if (ret) { ++ dev_err(tps->dev, "Read from reg 0x%x failed\n", reg); ++ return ret; ++ } ++ ++ data &= ~mask; ++ data |= val & mask; ++ ++ mutex_lock(&tps->tps_lock); ++ ret = tps65218_reg_write(tps, reg, data, level); ++ if (ret) ++ dev_err(tps->dev, "Write for reg 0x%x failed\n", reg); ++ mutex_unlock(&tps->tps_lock); ++ ++ return ret; ++} ++ ++int tps65218_set_bits(struct tps65218 *tps, unsigned int reg, ++ unsigned int mask, unsigned int val, unsigned int level) ++{ ++ return tps65218_update_bits(tps, reg, mask, val, level); ++} ++EXPORT_SYMBOL_GPL(tps65218_set_bits); ++ ++int tps65218_clear_bits(struct tps65218 *tps, unsigned int reg, ++ unsigned int mask, unsigned int level) ++{ ++ return tps65218_update_bits(tps, reg, mask, 0, level); ++} ++EXPORT_SYMBOL_GPL(tps65218_clear_bits); ++ ++static struct regmap_config tps65218_regmap_config = { ++ .reg_bits = 8, ++ .val_bits = 8, ++}; ++ ++static const struct regmap_irq tps65218_irqs[] = { ++ /* INT1 IRQs */ ++ [TPS65218_PRGC_IRQ] = { ++ .mask = TPS65218_INT1_PRGC, ++ }, ++ [TPS65218_CC_AQC_IRQ] = { ++ .mask = TPS65218_INT1_CC_AQC, ++ }, ++ [TPS65218_HOT_IRQ] = { ++ .mask = TPS65218_INT1_HOT, ++ }, ++ [TPS65218_PB_IRQ] = { ++ .mask = TPS65218_INT1_PB, ++ }, ++ [TPS65218_AC_IRQ] = { ++ .mask = TPS65218_INT1_AC, ++ }, ++ [TPS65218_VPRG_IRQ] = { ++ .mask = TPS65218_INT1_VPRG, ++ }, ++ [TPS65218_INVALID1_IRQ] = { ++ }, ++ [TPS65218_INVALID2_IRQ] = { ++ }, ++ /* INT2 IRQs*/ ++ [TPS65218_LS1_I_IRQ] = { ++ .mask = TPS65218_INT2_LS1_I, ++ .reg_offset = 1, ++ }, ++ [TPS65218_LS2_I_IRQ] = { ++ .mask = TPS65218_INT2_LS2_I, ++ .reg_offset = 1, ++ }, ++ [TPS65218_LS3_I_IRQ] = { ++ .mask = TPS65218_INT2_LS3_I, ++ .reg_offset = 1, ++ }, ++ [TPS65218_LS1_F_IRQ] = { ++ .mask = TPS65218_INT2_LS1_F, ++ .reg_offset = 1, ++ }, ++ [TPS65218_LS2_F_IRQ] = { ++ .mask = TPS65218_INT2_LS2_F, ++ .reg_offset = 1, ++ }, ++ [TPS65218_LS3_F_IRQ] = { ++ .mask = TPS65218_INT2_LS3_F, ++ .reg_offset = 1, ++ }, ++ [TPS65218_INVALID3_IRQ] = { ++ }, ++ [TPS65218_INVALID4_IRQ] = { ++ }, ++}; ++ ++static struct regmap_irq_chip tps65218_irq_chip = { ++ .name = "tps65218", ++ .irqs = tps65218_irqs, ++ .num_irqs = ARRAY_SIZE(tps65218_irqs), ++ ++ .num_regs = 2, ++ .mask_base = TPS65218_REG_INT_MASK1, ++}; ++ ++static const struct of_device_id of_tps65218_match_table[] = { ++ { .compatible = "ti,tps65218", }, ++ { /* end */ } ++}; ++ ++static int tps65218_probe(struct i2c_client *client, ++ const struct i2c_device_id *ids) ++{ ++ struct tps65218 *tps; ++ const struct of_device_id *match; ++ int ret; ++ ++ match = of_match_device(of_tps65218_match_table, &client->dev); ++ if (!match) { ++ dev_err(&client->dev, ++ "Failed to find matching dt id\n"); ++ return -EINVAL; ++ } ++ ++ tps = devm_kzalloc(&client->dev, sizeof(*tps), GFP_KERNEL); ++ if (!tps) ++ return -ENOMEM; ++ ++ i2c_set_clientdata(client, tps); ++ tps->dev = &client->dev; ++ ++ tps->regmap = devm_regmap_init_i2c(client, &tps65218_regmap_config); ++ if (IS_ERR(tps->regmap)) { ++ ret = PTR_ERR(tps->regmap); ++ dev_err(tps->dev, "Failed to allocate register map: %d\n", ++ ret); ++ return ret; ++ } ++ ++ mutex_init(&tps->tps_lock); ++ ++ ret = regmap_add_irq_chip(tps->regmap, tps->irq, ++ IRQF_ONESHOT, 0, &tps65218_irq_chip, ++ &tps->irq_data); ++ if (ret < 0) ++ return ret; ++ ++ ret = of_platform_populate(client->dev.of_node, NULL, NULL, ++ &client->dev); ++ if (ret < 0) ++ goto err_irq; ++ ++ return 0; ++ ++err_irq: ++ regmap_del_irq_chip(tps->irq, tps->irq_data); ++ ++ return ret; ++} ++ ++static int tps65218_remove(struct i2c_client *client) ++{ ++ struct tps65218 *tps = i2c_get_clientdata(client); ++ ++ regmap_del_irq_chip(tps->irq, tps->irq_data); ++ ++ return 0; ++} ++ ++static struct i2c_driver tps65218_driver = { ++ .driver = { ++ .name = "tps65218", ++ .owner = THIS_MODULE, ++ .of_match_table = of_tps65218_match_table, ++ }, ++ .probe = tps65218_probe, ++ .remove = tps65218_remove, ++}; ++ ++module_i2c_driver(tps65218_driver); ++ ++MODULE_AUTHOR("J Keerthy <j-keerthy@ti.com>"); ++MODULE_DESCRIPTION("TPS65218 chip family multi-function driver"); ++MODULE_LICENSE("GPL v2"); +--- a/drivers/mfd/twl6040.c ++++ b/drivers/mfd/twl6040.c +@@ -238,6 +238,8 @@ int twl6040_power(struct twl6040 *twl604 + if (twl6040->power_count++) + goto out; + ++ clk_prepare_enable(twl6040->clk32k); ++ + if (gpio_is_valid(twl6040->audpwron)) { + /* use automatic power-up sequence */ + ret = twl6040_power_up_automatic(twl6040); +@@ -281,6 +283,8 @@ int twl6040_power(struct twl6040 *twl604 + } + twl6040->sysclk = 0; + twl6040->mclk = 0; ++ ++ clk_disable_unprepare(twl6040->clk32k); + } + + out: +@@ -559,6 +563,12 @@ static int twl6040_probe(struct i2c_clie + + i2c_set_clientdata(client, twl6040); + ++ twl6040->clk32k = devm_clk_get(&client->dev, "clk32k"); ++ if (IS_ERR(twl6040->clk32k)) { ++ dev_info(&client->dev, "clk32k is not handled\n"); ++ twl6040->clk32k = NULL; ++ } ++ + twl6040->supplies[0].supply = "vio"; + twl6040->supplies[1].supply = "v2v1"; + ret = devm_regulator_bulk_get(&client->dev, TWL6040_NUM_SUPPLIES, +--- /dev/null ++++ b/drivers/misc/crossbar.c +@@ -0,0 +1,258 @@ ++/* ++ * IRQ/DMA CROSSBAR DRIVER ++ * ++ * Copyright (C) 2013 Texas Instruments Incorporated - http://www.ti.com/ ++ * Sricharan R <r.sricharan@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; either version 2 of the License, or ++ * (at your option) any later version. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this program; if not, write to the Free Software ++ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 ++ * USA ++ */ ++#include <linux/crossbar.h> ++#include <linux/regmap.h> ++ ++static LIST_HEAD(cb_devlist); ++ ++static struct regmap_config cb_regmap_config = { ++ .reg_bits = 32, ++}; ++ ++static unsigned cb_entry_read(struct cb_line *tmp, const void *cbs) ++{ ++ unsigned index = 0; ++ ++ tmp->cb_name = cbs; ++ index = strlen(tmp->cb_name) + 1; ++ ++ tmp->dev_name = cbs + index; ++ index += strlen(tmp->dev_name) + 1; ++ ++ tmp->int_no = be32_to_cpup(cbs + index); ++ index += sizeof(tmp->int_no); ++ ++ tmp->cb_no = be32_to_cpup(cbs + index); ++ index += sizeof(tmp->cb_no); ++ ++ tmp->offset = be32_to_cpup(cbs + index); ++ index += sizeof(tmp->offset); ++ ++ return index; ++} ++ ++int crossbar_unmap(struct device_node *cbdev_node, unsigned index) ++{ ++ const void *cbs; ++ unsigned size = 0, i = 0; ++ struct cb_line tmp; ++ struct cb_device *cbdev; ++ struct cb_entry *cbentry, *p; ++ ++ cbs = of_get_property(cbdev_node, "crossbar-lines", &size); ++ if (!cbs) ++ return -ENOENT; ++ ++ size = 0; ++ ++ while (i++ < index) ++ size += cb_entry_read(&tmp, cbs + size); ++ ++ cb_entry_read(&tmp, cbs + size); ++ ++ list_for_each_entry(cbdev, &cb_devlist, node) { ++ if (strcmp(cbdev->name, tmp.cb_name)) ++ continue; ++ ++ mutex_lock(&cbdev->cb_lock); ++ list_for_each_entry_safe(cbentry, p, &cbdev->cb_entries, ++ cb_list) { ++ if ((cbentry->line.cb_no == tmp.cb_no) && ++ (cbentry->line.int_no == tmp.int_no)) { ++ list_del(&cbentry->cb_list); ++ mutex_unlock(&cbdev->cb_lock); ++ dev_warn(cbdev->dev, ++ "unmapped int_no %x mapped to cb %x\n", ++ tmp.int_no, tmp.cb_no); ++ return 0; ++ } ++ } ++ mutex_unlock(&cbdev->cb_lock); ++ break; ++ } ++ ++ dev_warn(cbdev->dev, "%s cb entry %d not found\n", ++ __func__, tmp.cb_no); ++ return -ENOENT; ++} ++EXPORT_SYMBOL(crossbar_unmap); ++ ++const int cb_map(struct cb_line cbl) ++{ ++ struct cb_device *cbdev; ++ struct cb_entry *cbentry, *tmp; ++ unsigned val; ++ ++ /* Get corresponding device pointer */ ++ list_for_each_entry(cbdev, &cb_devlist, node) { ++ if (strcmp(cbdev->name, cbl.cb_name)) ++ continue; ++ ++ mutex_lock(&cbdev->cb_lock); ++ ++ /* Check for invalid and duplicate mapping */ ++ list_for_each_entry_safe(cbentry, tmp, &cbdev->cb_entries, ++ cb_list) { ++ if ((cbentry->line.cb_no == cbl.cb_no) && ++ (cbentry->line.int_no != cbl.int_no)) { ++ dev_warn(cbdev->dev, ++ "%s irq already mapped to irq no %d", ++ cbentry->line.dev_name, ++ cbentry->line.int_no); ++ mutex_unlock(&cbdev->cb_lock); ++ return -EINVAL; ++ } ++ if ((cbentry->line.cb_no == cbl.cb_no) && ++ (cbentry->line.int_no == cbl.int_no)) { ++ mutex_unlock(&cbdev->cb_lock); ++ return 0; ++ } ++ if ((cbentry->line.int_no == cbl.int_no) && ++ (cbentry->line.cb_no != cbl.cb_no)) { ++ dev_warn(cbdev->dev, ++ "%s irq replaced by %s irq\n", ++ cbentry->line.dev_name, ++ cbl.dev_name); ++ list_del(&(cbentry->cb_list)); ++ break; ++ } ++ } ++ ++ cbentry = devm_kzalloc(cbdev->dev, sizeof(struct cb_entry), ++ GFP_KERNEL); ++ cbentry->line = cbl; ++ list_add_tail(&(cbentry->cb_list), &cbdev->cb_entries); ++ ++ regmap_read(cbdev->cb_regmap, cbl.offset, &val); ++ ++ /* Print the replaced entry and map the new one */ ++ dev_warn(cbdev->dev, ++ "replacing irq %d mapped to cb input %d with cb input %d\n", ++ cbl.int_no, val, cbl.cb_no); ++ ++ regmap_write(cbdev->cb_regmap, cbl.offset, cbl.cb_no); ++ mutex_unlock(&cbdev->cb_lock); ++ return 0; ++ } ++ ++ dev_warn(cbdev->dev, "crossbar device %s not found", cbl.cb_name); ++ return -ENODEV; ++} ++ ++int crossbar_map(struct device_node *cbdev_node) ++{ ++ const void *cbs; ++ unsigned size = 0, index = 0; ++ int err; ++ ++ cbs = of_get_property(cbdev_node, "crossbar-lines", &size); ++ if (!cbs) ++ return -ENOENT; ++ ++ while (index < size) { ++ struct cb_line tmp; ++ ++ index += cb_entry_read(&tmp, cbs + index); ++ ++ err = cb_map(tmp); ++ if (IS_ERR_VALUE(err)) ++ return err; ++ } ++ ++ return 0; ++} ++EXPORT_SYMBOL(crossbar_map); ++ ++static int crossbar_probe(struct platform_device *pdev) ++{ ++ struct cb_device *cbdev; ++ unsigned width; ++ struct device_node *cbdev_node = pdev->dev.of_node; ++ int err; ++ struct resource *res; ++ ++ cbdev = devm_kzalloc(&pdev->dev, sizeof(struct cb_device), GFP_KERNEL); ++ if (!cbdev) ++ return -ENOMEM; ++ ++ /* Get the device resources */ ++ of_property_read_string(cbdev_node, "crossbar-name", &(cbdev->name)); ++ ++ res = platform_get_resource(pdev, IORESOURCE_MEM, 0); ++ if (res == NULL) ++ return -ENOENT; ++ ++ cbdev->base = devm_ioremap_resource(&pdev->dev, res); ++ if (!cbdev->base) ++ return -ENOMEM; ++ ++ cbdev->dev = &pdev->dev; ++ ++ of_property_read_u32(cbdev_node, "reg-width", &width); ++ ++ cb_regmap_config.val_bits = width; ++ cb_regmap_config.reg_stride = width >> 3; ++ ++ cbdev->cb_regmap = devm_regmap_init_mmio(cbdev->dev, cbdev->base, ++ &cb_regmap_config); ++ ++ if (IS_ERR(cbdev->cb_regmap)) { ++ dev_err(&pdev->dev, "regmap init failed\n"); ++ err = PTR_ERR(cbdev->cb_regmap); ++ return err; ++ } ++ ++ platform_set_drvdata(pdev, cbdev); ++ list_add_tail(&cbdev->node, &cb_devlist); ++ ++ /* INIT LIST HEAD */ ++ INIT_LIST_HEAD(&cbdev->cb_entries); ++ ++ mutex_init(&cbdev->cb_lock); ++ ++ /* map the cross bar entries passed as default from DT */ ++ err = crossbar_map(cbdev_node); ++ ++ return err; ++} ++ ++#ifdef CONFIG_OF ++static const struct of_device_id crossbar_match[] = { ++ {.compatible = "crossbar", }, ++ {}, ++}; ++#endif ++ ++static struct platform_driver crossbar_driver = { ++ .probe = crossbar_probe, ++ .driver = { ++ .name = "crossbar", ++ .owner = THIS_MODULE, ++ .of_match_table = crossbar_match, ++ }, ++}; ++ ++static int __init crossbar_init(void) ++{ ++ return platform_driver_register(&crossbar_driver); ++} ++postcore_initcall(crossbar_init); +--- a/drivers/misc/Kconfig ++++ b/drivers/misc/Kconfig +@@ -528,6 +528,14 @@ config SRAM + the genalloc API. It is supposed to be used for small on-chip SRAM + areas found on many SoCs. + ++config CROSSBAR ++ bool "on-chip crossbar driver" ++ select REGMAP_MMIO ++ help ++ This driver is for IRQ/DMA crossbar devices which is responsible for ++ muxing the irq/dma requests from external peripherals to the corresponding ++ controller's inputs. ++ + source "drivers/misc/c2port/Kconfig" + source "drivers/misc/eeprom/Kconfig" + source "drivers/misc/cb710/Kconfig" +--- a/drivers/misc/Makefile ++++ b/drivers/misc/Makefile +@@ -53,3 +53,4 @@ obj-$(CONFIG_INTEL_MEI) += mei/ + obj-$(CONFIG_VMWARE_VMCI) += vmw_vmci/ + obj-$(CONFIG_LATTICE_ECP3_CONFIG) += lattice-ecp3-config.o + obj-$(CONFIG_SRAM) += sram.o ++obj-$(CONFIG_CROSSBAR) += crossbar.o +--- a/drivers/mmc/core/mmc.c ++++ b/drivers/mmc/core/mmc.c +@@ -1512,14 +1512,6 @@ static int mmc_suspend(struct mmc_host * + } + + /* +- * Shutdown callback +- */ +-static int mmc_shutdown(struct mmc_host *host) +-{ +- return _mmc_suspend(host, false); +-} +- +-/* + * Resume callback from host. + * + * This function tries to determine if the same card is still present +@@ -1608,7 +1600,6 @@ static const struct mmc_bus_ops mmc_ops + .resume = NULL, + .power_restore = mmc_power_restore, + .alive = mmc_alive, +- .shutdown = mmc_shutdown, + }; + + static const struct mmc_bus_ops mmc_ops_unsafe = { +@@ -1620,7 +1611,6 @@ static const struct mmc_bus_ops mmc_ops_ + .runtime_resume = mmc_runtime_resume, + .power_restore = mmc_power_restore, + .alive = mmc_alive, +- .shutdown = mmc_shutdown, + }; + + static void mmc_attach_bus_ops(struct mmc_host *host) +--- a/drivers/mmc/core/sd.c ++++ b/drivers/mmc/core/sd.c +@@ -1173,7 +1173,6 @@ static const struct mmc_bus_ops mmc_sd_o + .resume = NULL, + .power_restore = mmc_sd_power_restore, + .alive = mmc_sd_alive, +- .shutdown = mmc_sd_suspend, + }; + + static const struct mmc_bus_ops mmc_sd_ops_unsafe = { +@@ -1185,7 +1184,6 @@ static const struct mmc_bus_ops mmc_sd_o + .resume = mmc_sd_resume, + .power_restore = mmc_sd_power_restore, + .alive = mmc_sd_alive, +- .shutdown = mmc_sd_suspend, + }; + + static void mmc_sd_attach_bus_ops(struct mmc_host *host) +--- a/drivers/mmc/host/omap_hsmmc.c ++++ b/drivers/mmc/host/omap_hsmmc.c +@@ -45,6 +45,7 @@ + /* OMAP HSMMC Host Controller Registers */ + #define OMAP_HSMMC_SYSSTATUS 0x0014 + #define OMAP_HSMMC_CON 0x002C ++#define OMAP_HSMMC_SDMASA 0x0100 + #define OMAP_HSMMC_BLK 0x0104 + #define OMAP_HSMMC_ARG 0x0108 + #define OMAP_HSMMC_CMD 0x010C +@@ -58,7 +59,9 @@ + #define OMAP_HSMMC_STAT 0x0130 + #define OMAP_HSMMC_IE 0x0134 + #define OMAP_HSMMC_ISE 0x0138 ++#define OMAP_HSMMC_AC12 0x013C + #define OMAP_HSMMC_CAPA 0x0140 ++#define OMAP_HSMMC_REV 0x01FC + + #define VS18 (1 << 26) + #define VS30 (1 << 25) +@@ -75,11 +78,14 @@ + #define ICE 0x1 + #define ICS 0x2 + #define CEN (1 << 2) ++#define CLKD_MAX 0x3FF /* max clock divisor: 1023 */ + #define CLKD_MASK 0x0000FFC0 + #define CLKD_SHIFT 6 + #define DTO_MASK 0x000F0000 + #define DTO_SHIFT 16 + #define INIT_STREAM (1 << 1) ++#define ACEN_ACMD12 (1 << 2) ++#define ACEN_ACMD23 (2 << 2) + #define DP_SELECT (1 << 21) + #define DDIR (1 << 4) + #define DMAE 0x1 +@@ -111,6 +117,7 @@ + #define DTO_EN (1 << 20) + #define DCRC_EN (1 << 21) + #define DEB_EN (1 << 22) ++#define ACE_EN (1 << 24) + #define CERR_EN (1 << 28) + #define BADA_EN (1 << 29) + +@@ -118,12 +125,27 @@ + DTO_EN | CIE_EN | CEB_EN | CCRC_EN | CTO_EN | \ + BRR_EN | BWR_EN | TC_EN | CC_EN) + ++#define CNI (1 << 7) ++#define ACIE (1 << 4) ++#define ACEB (1 << 3) ++#define ACCE (1 << 2) ++#define ACTO (1 << 1) ++#define ACNE (1 << 0) ++ + #define MMC_AUTOSUSPEND_DELAY 100 + #define MMC_TIMEOUT_MS 20 ++#define MMC_TIMEOUT_US 20000 + #define OMAP_MMC_MIN_CLOCK 400000 + #define OMAP_MMC_MAX_CLOCK 52000000 + #define DRIVER_NAME "omap_hsmmc" + ++#define AUTO_CMD12 (1 << 0) /* Auto CMD12 support */ ++#define AUTO_CMD23 (1 << 1) /* Auto CMD23 support */ ++ ++#define OMAP_HSMMC_REV_SHIFT 24 ++/* HSMMC controller revision on OMAP5, DRA7 */ ++#define OMAP_HSMMC_REV_33 0x33 ++ + /* + * One controller can have multiple slots, like on some omap boards using + * omap.c controller driver. Luckily this is not currently done on any known +@@ -171,6 +193,10 @@ struct omap_hsmmc_host { + unsigned char bus_mode; + unsigned char power_mode; + int suspended; ++ u32 con; ++ u32 hctl; ++ u32 sysctl; ++ u32 capa; + int irq; + int use_dma, dma_ch; + struct dma_chan *tx_chan; +@@ -182,11 +208,19 @@ struct omap_hsmmc_host { + int reqs_blocked; + int use_reg; + int req_in_progress; ++ unsigned long clk_rate; ++ unsigned int flags; + struct omap_hsmmc_next next_data; +- + struct omap_mmc_platform_data *pdata; + }; + ++static int ++omap_hsmmc_prepare_data(struct omap_hsmmc_host *host, struct mmc_request *req); ++ ++static void set_data_timeout(struct omap_hsmmc_host *host, ++ unsigned int timeout_ns, ++ unsigned int timeout_clks); ++ + static int omap_hsmmc_card_detect(struct device *dev, int slot) + { + struct omap_hsmmc_host *host = dev_get_drvdata(dev); +@@ -407,6 +441,9 @@ static int omap_hsmmc_gpio_init(struct o + ret = gpio_direction_input(pdata->slots[0].switch_pin); + if (ret) + goto err_free_sp; ++ ret = gpio_set_debounce(pdata->slots[0].switch_pin, 50000); ++ if (ret) ++ goto err_free_sp; + } else + pdata->slots[0].switch_pin = -EINVAL; + +@@ -493,8 +530,8 @@ static u16 calc_divisor(struct omap_hsmm + + if (ios->clock) { + dsor = DIV_ROUND_UP(clk_get_rate(host->fclk), ios->clock); +- if (dsor > 250) +- dsor = 250; ++ if (dsor > CLKD_MAX) ++ dsor = CLKD_MAX; + } + + return dsor; +@@ -597,25 +634,20 @@ static void omap_hsmmc_set_bus_mode(stru + static int omap_hsmmc_context_restore(struct omap_hsmmc_host *host) + { + struct mmc_ios *ios = &host->mmc->ios; +- struct omap_mmc_platform_data *pdata = host->pdata; +- int context_loss = 0; + u32 hctl, capa; + unsigned long timeout; + +- if (pdata->get_context_loss_count) { +- context_loss = pdata->get_context_loss_count(host->dev); +- if (context_loss < 0) +- return 1; +- } +- +- dev_dbg(mmc_dev(host->mmc), "context was %slost\n", +- context_loss == host->context_loss ? "not " : ""); +- if (host->context_loss == context_loss) +- return 1; +- + if (!OMAP_HSMMC_READ(host->base, SYSSTATUS) & RESETDONE) + return 1; + ++ if (host->con == OMAP_HSMMC_READ(host->base, CON) && ++ host->hctl == OMAP_HSMMC_READ(host->base, HCTL) && ++ host->sysctl == OMAP_HSMMC_READ(host->base, SYSCTL) && ++ host->capa == OMAP_HSMMC_READ(host->base, CAPA)) ++ return 0; ++ ++ host->context_loss++; ++ + if (host->pdata->controller_flags & OMAP_HSMMC_SUPPORTS_DUAL_VOLT) { + if (host->power_mode != MMC_POWER_OFF && + (1 << ios->vdd) <= MMC_VDD_23_24) +@@ -655,9 +687,8 @@ static int omap_hsmmc_context_restore(st + omap_hsmmc_set_bus_mode(host); + + out: +- host->context_loss = context_loss; +- +- dev_dbg(mmc_dev(host->mmc), "context is restored\n"); ++ dev_dbg(mmc_dev(host->mmc), "context is restored: restore count %d\n", ++ host->context_loss); + return 0; + } + +@@ -666,15 +697,10 @@ out: + */ + static void omap_hsmmc_context_save(struct omap_hsmmc_host *host) + { +- struct omap_mmc_platform_data *pdata = host->pdata; +- int context_loss; +- +- if (pdata->get_context_loss_count) { +- context_loss = pdata->get_context_loss_count(host->dev); +- if (context_loss < 0) +- return; +- host->context_loss = context_loss; +- } ++ host->con = OMAP_HSMMC_READ(host->base, CON); ++ host->hctl = OMAP_HSMMC_READ(host->base, HCTL); ++ host->sysctl = OMAP_HSMMC_READ(host->base, SYSCTL); ++ host->capa = OMAP_HSMMC_READ(host->base, CAPA); + } + + #else +@@ -762,7 +788,7 @@ static DEVICE_ATTR(slot_name, S_IRUGO, o + */ + static void + omap_hsmmc_start_command(struct omap_hsmmc_host *host, struct mmc_command *cmd, +- struct mmc_data *data) ++ struct mmc_data *data, bool autocmd12) + { + int cmdreg = 0, resptype = 0, cmdtype = 0; + +@@ -792,6 +818,13 @@ omap_hsmmc_start_command(struct omap_hsm + cmdtype = 0x3; + + cmdreg = (cmd->opcode << 24) | (resptype << 16) | (cmdtype << 22); ++ if ((host->flags & AUTO_CMD23) && mmc_op_multi(cmd->opcode) && ++ host->mrq->sbc) { ++ cmdreg |= ACEN_ACMD23; ++ OMAP_HSMMC_WRITE(host->base, SDMASA, host->mrq->sbc->arg); ++ } else if ((host->flags & AUTO_CMD12) && mmc_op_multi(cmd->opcode) && ++ autocmd12) ++ cmdreg |= ACEN_ACMD12; + + if (data) { + cmdreg |= DP_SELECT | MSBS | BCE; +@@ -870,11 +903,38 @@ omap_hsmmc_xfer_done(struct omap_hsmmc_h + else + data->bytes_xfered = 0; + +- if (!data->stop) { ++ if (data->stop && (data->error || (!(host->flags & AUTO_CMD12) && ++ !host->mrq->sbc))) { ++ /* ++ * If there is any error or open-end read/write with autocmd12 ++ * disabled ++ */ ++ omap_hsmmc_start_command(host, data->stop, NULL, 0); ++ } else { ++ /* status update for autocmd12 of open-end read/write */ ++ if (data->stop && !host->mrq->sbc) ++ data->stop->resp[0] = OMAP_HSMMC_READ(host->base, ++ RSP76); + omap_hsmmc_request_done(host, data->mrq); +- return; + } +- omap_hsmmc_start_command(host, data->stop, NULL); ++ ++ return; ++} ++ ++static void omap_hsmmc_start_dma_transfer(struct omap_hsmmc_host *host) ++{ ++ struct mmc_request *req; ++ struct dma_chan *chan; ++ req = host->mrq; ++ ++ if (!req->data) ++ return; ++ OMAP_HSMMC_WRITE(host->base, BLK, (req->data->blksz) ++ | (req->data->blocks << 16)); ++ set_data_timeout(host, req->data->timeout_ns, ++ req->data->timeout_clks); ++ chan = omap_hsmmc_get_dma_chan(host, req->data); ++ dma_async_issue_pending(chan); + } + + /* +@@ -883,6 +943,18 @@ omap_hsmmc_xfer_done(struct omap_hsmmc_h + static void + omap_hsmmc_cmd_done(struct omap_hsmmc_host *host, struct mmc_command *cmd) + { ++ struct mmc_request *req; ++ req = host->mrq; ++ ++ if (host->mrq->sbc && (host->cmd == host->mrq->sbc) && ++ !host->mrq->sbc->error && !(host->flags & AUTO_CMD23)) { ++ host->cmd = NULL; ++ omap_hsmmc_start_dma_transfer(host); ++ omap_hsmmc_start_command(host, host->mrq->cmd, ++ host->mrq->data, 0); ++ return; ++ } ++ + host->cmd = NULL; + + if (cmd->flags & MMC_RSP_PRESENT) { +@@ -975,8 +1047,7 @@ static inline void omap_hsmmc_reset_cont + unsigned long bit) + { + unsigned long i = 0; +- unsigned long limit = (loops_per_jiffy * +- msecs_to_jiffies(MMC_TIMEOUT_MS)); ++ unsigned long limit = MMC_TIMEOUT_US; + + OMAP_HSMMC_WRITE(host->base, SYSCTL, + OMAP_HSMMC_READ(host->base, SYSCTL) | bit); +@@ -988,13 +1059,14 @@ static inline void omap_hsmmc_reset_cont + if (mmc_slot(host).features & HSMMC_HAS_UPDATED_RESET) { + while ((!(OMAP_HSMMC_READ(host->base, SYSCTL) & bit)) + && (i++ < limit)) +- cpu_relax(); ++ udelay(1); + } ++ + i = 0; + + while ((OMAP_HSMMC_READ(host->base, SYSCTL) & bit) && + (i++ < limit)) +- cpu_relax(); ++ udelay(1); + + if (OMAP_HSMMC_READ(host->base, SYSCTL) & bit) + dev_err(mmc_dev(host->mmc), +@@ -1022,6 +1094,7 @@ static void omap_hsmmc_do_irq(struct oma + { + struct mmc_data *data; + int end_cmd = 0, end_trans = 0; ++ int error = 0; + + data = host->data; + dev_vdbg(mmc_dev(host->mmc), "IRQ Status is %x\n", status); +@@ -1036,6 +1109,29 @@ static void omap_hsmmc_do_irq(struct oma + else if (status & (CCRC_EN | DCRC_EN)) + hsmmc_command_incomplete(host, -EILSEQ, end_cmd); + ++ if (status & ACE_EN) { ++ u32 ac12; ++ ac12 = OMAP_HSMMC_READ(host->base, AC12); ++ if (!(ac12 & ACNE) && host->mrq->sbc) { ++ end_cmd = 1; ++ if (ac12 & ACTO) ++ error = -ETIMEDOUT; ++ else if (ac12 & (ACCE | ACEB | ACIE)) ++ error = -EILSEQ; ++ host->mrq->sbc->error = error; ++ hsmmc_command_incomplete(host, error, end_cmd); ++ } ++ if (!(ac12 & ACNE) && !host->mrq->sbc && ++ host->mrq->data) { ++ end_trans = 1; ++ if (ac12 & ACTO) ++ host->mrq->data->error = -ETIMEDOUT; ++ else if (ac12 & (ACCE | ACEB | ACIE)) ++ host->mrq->data->error = -EILSEQ; ++ omap_hsmmc_reset_controller_fsm(host, SRC); ++ } ++ dev_dbg(mmc_dev(host->mmc), "AC12 err: 0x%x\n", ac12); ++ } + if (host->data || host->response_busy) { + end_trans = !end_cmd; + host->response_busy = 0; +@@ -1272,7 +1368,7 @@ static int omap_hsmmc_pre_dma_transfer(s + /* + * Routine to configure and start DMA for the MMC card + */ +-static int omap_hsmmc_start_dma_transfer(struct omap_hsmmc_host *host, ++static int omap_hsmmc_setup_dma_transfer(struct omap_hsmmc_host *host, + struct mmc_request *req) + { + struct dma_slave_config cfg; +@@ -1331,8 +1427,6 @@ static int omap_hsmmc_start_dma_transfer + + host->dma_ch = 1; + +- dma_async_issue_pending(chan); +- + return 0; + } + +@@ -1348,7 +1442,7 @@ static void set_data_timeout(struct omap + if (clkd == 0) + clkd = 1; + +- cycle_ns = 1000000000 / (clk_get_rate(host->fclk) / clkd); ++ cycle_ns = 1000000000 / (host->clk_rate / clkd); + timeout = timeout_ns / cycle_ns; + timeout += timeout_clks; + if (timeout) { +@@ -1393,12 +1487,8 @@ omap_hsmmc_prepare_data(struct omap_hsmm + return 0; + } + +- OMAP_HSMMC_WRITE(host->base, BLK, (req->data->blksz) +- | (req->data->blocks << 16)); +- set_data_timeout(host, req->data->timeout_ns, req->data->timeout_clks); +- + if (host->use_dma) { +- ret = omap_hsmmc_start_dma_transfer(host, req); ++ ret = omap_hsmmc_setup_dma_transfer(host, req); + if (ret != 0) { + dev_err(mmc_dev(host->mmc), "MMC start dma failure\n"); + return ret; +@@ -1472,6 +1562,7 @@ static void omap_hsmmc_request(struct mm + host->reqs_blocked = 0; + WARN_ON(host->mrq != NULL); + host->mrq = req; ++ host->clk_rate = clk_get_rate(host->fclk); + err = omap_hsmmc_prepare_data(host, req); + if (err) { + req->cmd->error = err; +@@ -1481,8 +1572,12 @@ static void omap_hsmmc_request(struct mm + mmc_request_done(mmc, req); + return; + } +- +- omap_hsmmc_start_command(host, req->cmd, req->data); ++ if (req->sbc && !(host->flags & AUTO_CMD23)) { ++ omap_hsmmc_start_command(host, req->sbc, NULL, 0); ++ return; ++ } ++ omap_hsmmc_start_dma_transfer(host); ++ omap_hsmmc_start_command(host, req->cmd, req->data, 1); + } + + /* Routine to configure clock values. Exposed API to core */ +@@ -1635,13 +1730,9 @@ static int omap_hsmmc_regs_show(struct s + { + struct mmc_host *mmc = s->private; + struct omap_hsmmc_host *host = mmc_priv(mmc); +- int context_loss = 0; + +- if (host->pdata->get_context_loss_count) +- context_loss = host->pdata->get_context_loss_count(host->dev); +- +- seq_printf(s, "mmc%d:\n ctx_loss:\t%d:%d\n\nregs:\n", +- mmc->index, host->context_loss, context_loss); ++ seq_printf(s, "mmc%d:\n ctx_loss:\t%d\n\nregs:\n", ++ mmc->index, host->context_loss); + + if (host->suspended) { + seq_printf(s, "host suspended, can't read registers\n"); +@@ -1778,6 +1869,7 @@ static int omap_hsmmc_probe(struct platf + dma_cap_mask_t mask; + unsigned tx_req, rx_req; + struct pinctrl *pinctrl; ++ u32 revision; + + match = of_match_device(of_match_ptr(omap_mmc_of_match), &pdev->dev); + if (match) { +@@ -1874,7 +1966,7 @@ static int omap_hsmmc_probe(struct platf + omap_hsmmc_context_save(host); + + /* This can be removed once we support PBIAS with DT */ +- if (host->dev->of_node && host->mapbase == 0x4809c000) ++ if (host->dev->of_node && res->start == 0x4809c000) + host->pbias_disable = 1; + + host->dbclk = clk_get(&pdev->dev, "mmchsdb_fck"); +@@ -1976,6 +2068,12 @@ static int omap_hsmmc_probe(struct platf + host->use_reg = 1; + } + ++ revision = OMAP_HSMMC_READ(host->base, REV); ++ if ((revision >> OMAP_HSMMC_REV_SHIFT) >= OMAP_HSMMC_REV_33) { ++ mmc->caps |= MMC_CAP_CMD23; ++ host->flags |= AUTO_CMD23; ++ } ++ + mmc->ocr_avail = mmc_slot(host).ocr_mask; + + /* Request IRQ for card detect */ +--- a/drivers/mtd/devices/elm.c ++++ b/drivers/mtd/devices/elm.c +@@ -22,8 +22,11 @@ + #include <linux/of.h> + #include <linux/sched.h> + #include <linux/pm_runtime.h> ++#include <linux/mtd/mtd.h> ++#include <linux/mtd/nand.h> + #include <linux/platform_data/elm.h> + ++#define DRIVER_NAME "omap-elm" + #define ELM_SYSCONFIG 0x010 + #define ELM_IRQSTATUS 0x018 + #define ELM_IRQENABLE 0x01c +@@ -82,8 +85,10 @@ struct elm_info { + void __iomem *elm_base; + struct completion elm_completion; + struct list_head list; ++ struct mtd_info *mtd; + enum bch_ecc bch_type; + struct elm_registers elm_regs; ++ int eccsteps; + }; + + static LIST_HEAD(elm_devices); +@@ -103,19 +108,42 @@ static u32 elm_read_reg(struct elm_info + * @dev: ELM device + * @bch_type: Type of BCH ecc + */ +-int elm_config(struct device *dev, enum bch_ecc bch_type) ++int elm_config(struct device *dev, struct mtd_info *mtd, ++ enum bch_ecc bch_type) + { + u32 reg_val; +- struct elm_info *info = dev_get_drvdata(dev); +- ++ struct elm_info *info; ++ struct nand_chip *chip; ++ if (!dev) { ++ pr_err("%s: ELM device not found\n", DRIVER_NAME); ++ return -ENODEV; ++ } ++ info = dev_get_drvdata(dev); + if (!info) { +- dev_err(dev, "Unable to configure elm - device not probed?\n"); ++ pr_err("%s: ELM device data not found\n", DRIVER_NAME); + return -ENODEV; + } +- ++ if (!mtd) { ++ pr_err("%s: MTD device not found\n", DRIVER_NAME); ++ return -ENODEV; ++ } ++ chip = mtd->priv; ++ /* ELM supports error correction in chunks of 512bytes of data only ++ * where each 512bytes of data has its own ECC syndrome */ ++ if (chip->ecc.size != 512) { ++ pr_err("%s: invalid ecc_size configuration", DRIVER_NAME); ++ return -EINVAL; ++ } ++ if (mtd->writesize > 4096) { ++ pr_err("%s: page-size > 4096 is not supported", DRIVER_NAME); ++ return -EINVAL; ++ } ++ /* ELM eccsteps required to decode complete NAND page */ ++ info->mtd = mtd; ++ info->bch_type = bch_type; ++ info->eccsteps = mtd->writesize / chip->ecc.size; + reg_val = (bch_type & ECC_BCH_LEVEL_MASK) | (ELM_ECC_SIZE << 16); + elm_write_reg(info, ELM_LOCATION_CONFIG, reg_val); +- info->bch_type = bch_type; + + return 0; + } +@@ -152,55 +180,80 @@ static void elm_configure_page_mode(stru + * Load syndrome fragment registers with calculated ecc in reverse order. + */ + static void elm_load_syndrome(struct elm_info *info, +- struct elm_errorvec *err_vec, u8 *ecc) ++ struct elm_errorvec *err_vec, u8 *ecc_calc) + { ++ struct nand_chip *chip = info->mtd->priv; ++ unsigned int eccbytes = chip->ecc.bytes; ++ u8 *ecc = ecc_calc; + int i, offset; + u32 val; + +- for (i = 0; i < ERROR_VECTOR_MAX; i++) { +- ++ for (i = 0; i < info->eccsteps; i++) { + /* Check error reported */ + if (err_vec[i].error_reported) { + elm_configure_page_mode(info, i, true); +- offset = ELM_SYNDROME_FRAGMENT_0 + +- SYNDROME_FRAGMENT_REG_SIZE * i; +- +- /* BCH8 */ +- if (info->bch_type) { +- +- /* syndrome fragment 0 = ecc[9-12B] */ +- val = cpu_to_be32(*(u32 *) &ecc[9]); +- elm_write_reg(info, offset, val); +- +- /* syndrome fragment 1 = ecc[5-8B] */ +- offset += 4; +- val = cpu_to_be32(*(u32 *) &ecc[5]); +- elm_write_reg(info, offset, val); +- +- /* syndrome fragment 2 = ecc[1-4B] */ +- offset += 4; +- val = cpu_to_be32(*(u32 *) &ecc[1]); +- elm_write_reg(info, offset, val); +- +- /* syndrome fragment 3 = ecc[0B] */ +- offset += 4; +- val = ecc[0]; +- elm_write_reg(info, offset, val); +- } else { +- /* syndrome fragment 0 = ecc[20-52b] bits */ +- val = (cpu_to_be32(*(u32 *) &ecc[3]) >> 4) | +- ((ecc[2] & 0xf) << 28); +- elm_write_reg(info, offset, val); +- +- /* syndrome fragment 1 = ecc[0-20b] bits */ +- offset += 4; +- val = cpu_to_be32(*(u32 *) &ecc[0]) >> 12; +- elm_write_reg(info, offset, val); ++ offset = SYNDROME_FRAGMENT_REG_SIZE * i; ++ ecc = ecc_calc + (i * eccbytes); ++ switch (info->bch_type) { ++ case BCH4_ECC: ++ val = ((*(ecc + 6) >> 4) & 0x0F) | ++ *(ecc + 5) << 4 | *(ecc + 4) << 12 | ++ *(ecc + 3) << 20 | *(ecc + 2) << 28; ++ elm_write_reg(info, (ELM_SYNDROME_FRAGMENT_0 + ++ offset), cpu_to_le32(val)); ++ val = ((*(ecc + 2) >> 4) & 0x0F) | ++ *(ecc + 1) << 4 | *(ecc + 0) << 12; ++ elm_write_reg(info, (ELM_SYNDROME_FRAGMENT_1 + ++ offset), cpu_to_le32(val)); ++ break; ++ case BCH8_ECC: ++ val = *(ecc + 12) << 0 | *(ecc + 11) << 8 | ++ *(ecc + 10) << 16 | *(ecc + 9) << 24; ++ elm_write_reg(info, (ELM_SYNDROME_FRAGMENT_0 + ++ offset), cpu_to_le32(val)); ++ val = *(ecc + 8) << 0 | *(ecc + 7) << 8 | ++ *(ecc + 6) << 16 | *(ecc + 5) << 24; ++ elm_write_reg(info, (ELM_SYNDROME_FRAGMENT_1 + ++ offset), cpu_to_le32(val)); ++ val = *(ecc + 4) << 0 | *(ecc + 3) << 8 | ++ *(ecc + 2) << 16 | *(ecc + 1) << 24; ++ elm_write_reg(info, (ELM_SYNDROME_FRAGMENT_2 + ++ offset), cpu_to_le32(val)); ++ val = *(ecc + 0) << 0 & 0x000000FF; ++ elm_write_reg(info, (ELM_SYNDROME_FRAGMENT_3 + ++ offset), cpu_to_le32(val)); ++ break; ++ case BCH16_ECC: ++ val = *(ecc + 25) << 0 | *(ecc + 24) << 8 | ++ *(ecc + 23) << 16 | *(ecc + 22) << 24; ++ elm_write_reg(info, (ELM_SYNDROME_FRAGMENT_0 + ++ offset), cpu_to_le32(val)); ++ val = *(ecc + 21) << 0 | *(ecc + 20) << 8 | ++ *(ecc + 19) << 16 | *(ecc + 18) << 24; ++ elm_write_reg(info, (ELM_SYNDROME_FRAGMENT_1 + ++ offset), cpu_to_le32(val)); ++ val = *(ecc + 17) << 0 | *(ecc + 16) << 8 | ++ *(ecc + 15) << 16 | *(ecc + 14) << 24; ++ elm_write_reg(info, (ELM_SYNDROME_FRAGMENT_2 + ++ offset), cpu_to_le32(val)); ++ val = *(ecc + 13) << 0 | *(ecc + 12) << 8 | ++ *(ecc + 11) << 16 | *(ecc + 10) << 24; ++ elm_write_reg(info, (ELM_SYNDROME_FRAGMENT_3 + ++ offset), cpu_to_le32(val)); ++ val = *(ecc + 9) << 0 | *(ecc + 8) << 8 | ++ *(ecc + 7) << 16 | *(ecc + 6) << 24; ++ elm_write_reg(info, (ELM_SYNDROME_FRAGMENT_4 + ++ offset), cpu_to_le32(val)); ++ val = *(ecc + 5) << 0 | *(ecc + 4) << 8 | ++ *(ecc + 3) << 16 | *(ecc + 2) << 24; ++ elm_write_reg(info, (ELM_SYNDROME_FRAGMENT_5 + ++ offset), cpu_to_le32(val)); ++ val = *(ecc + 1) << 0 | *(ecc + 0) << 8; ++ elm_write_reg(info, (ELM_SYNDROME_FRAGMENT_6 + ++ offset), cpu_to_le32(val)); ++ break; + } + } +- +- /* Update ecc pointer with ecc byte size */ +- ecc += info->bch_type ? BCH8_SIZE : BCH4_SIZE; + } + } + +@@ -223,7 +276,7 @@ static void elm_start_processing(struct + * Set syndrome vector valid, so that ELM module + * will process it for vectors error is reported + */ +- for (i = 0; i < ERROR_VECTOR_MAX; i++) { ++ for (i = 0; i < info->eccsteps; i++) { + if (err_vec[i].error_reported) { + offset = ELM_SYNDROME_FRAGMENT_6 + + SYNDROME_FRAGMENT_REG_SIZE * i; +@@ -252,7 +305,7 @@ static void elm_error_correction(struct + int offset; + u32 reg_val; + +- for (i = 0; i < ERROR_VECTOR_MAX; i++) { ++ for (i = 0; i < info->eccsteps; i++) { + + /* Check error reported */ + if (err_vec[i].error_reported) { +@@ -263,14 +316,12 @@ static void elm_error_correction(struct + if (reg_val & ECC_CORRECTABLE_MASK) { + offset = ELM_ERROR_LOCATION_0 + + ERROR_LOCATION_SIZE * i; +- + /* Read count of correctable errors */ + err_vec[i].error_count = reg_val & + ECC_NB_ERRORS_MASK; + + /* Update the error locations in error vector */ + for (j = 0; j < err_vec[i].error_count; j++) { +- + reg_val = elm_read_reg(info, offset); + err_vec[i].error_loc[j] = reg_val & + ECC_ERROR_LOCATION_MASK; +--- a/drivers/mtd/devices/Kconfig ++++ b/drivers/mtd/devices/Kconfig +@@ -95,13 +95,6 @@ config MTD_M25P80 + if you want to specify device partitioning or to use a device which + doesn't support the JEDEC ID instruction. + +-config M25PXX_USE_FAST_READ +- bool "Use FAST_READ OPCode allowing SPI CLK >= 50MHz" +- depends on MTD_M25P80 +- default y +- help +- This option enables FAST_READ access supported by ST M25Pxx. +- + config MTD_SPEAR_SMI + tristate "SPEAR MTD NOR Support through SMI controller" + depends on PLAT_SPEAR +--- a/drivers/mtd/devices/m25p80.c ++++ b/drivers/mtd/devices/m25p80.c +@@ -41,6 +41,7 @@ + #define OPCODE_WRSR 0x01 /* Write status register 1 byte */ + #define OPCODE_NORM_READ 0x03 /* Read data bytes (low frequency) */ + #define OPCODE_FAST_READ 0x0b /* Read data bytes (high frequency) */ ++#define OPCODE_QUAD_READ 0x6b /* QUAD READ */ + #define OPCODE_PP 0x02 /* Page program (up to 256 bytes) */ + #define OPCODE_BE_4K 0x20 /* Erase 4KiB block */ + #define OPCODE_BE_4K_PMC 0xd7 /* Erase 4KiB block on PMC chips */ +@@ -48,10 +49,12 @@ + #define OPCODE_CHIP_ERASE 0xc7 /* Erase whole flash chip */ + #define OPCODE_SE 0xd8 /* Sector erase (usually 64KiB) */ + #define OPCODE_RDID 0x9f /* Read JEDEC ID */ ++#define OPCODE_RDCR 0x35 /* Read configuration register */ + + /* 4-byte address opcodes - used on Spansion and some Macronix flashes. */ + #define OPCODE_NORM_READ_4B 0x13 /* Read data bytes (low frequency) */ + #define OPCODE_FAST_READ_4B 0x0c /* Read data bytes (high frequency) */ ++#define OPCODE_QUAD_READ_4B 0x6c /* Read data bytes */ + #define OPCODE_PP_4B 0x12 /* Page program (up to 256 bytes) */ + #define OPCODE_SE_4B 0xdc /* Sector erase (usually 64KiB) */ + +@@ -76,9 +79,13 @@ + #define SR_BP2 0x10 /* Block protect 2 */ + #define SR_SRWD 0x80 /* SR write protect */ + ++/* Configuration Register bits. */ ++#define CR_QUAD_EN_SPAN 0x2 /* Spansion Quad I/O */ ++#define SR_QUAD_EN_MX 0x40 /* Macronix Quad I/O */ ++ + /* Define max times to check status register before we give up. */ + #define MAX_READY_WAIT_JIFFIES (40 * HZ) /* M25P16 specs 40s max chip erase */ +-#define MAX_CMD_SIZE 5 ++#define MAX_CMD_SIZE 6 + + #define JEDEC_MFR(_jedec_id) ((_jedec_id) >> 16) + +@@ -101,6 +108,8 @@ struct m25p { + u8 program_opcode; + u8 *command; + bool fast_read; ++ bool quad_read; ++ bool mmap; + }; + + static inline struct m25p *mtd_to_m25p(struct mtd_info *mtd) +@@ -137,6 +146,26 @@ static int read_sr(struct m25p *flash) + } + + /* ++ * Read the configuration register, returning its value in the location ++ * Return the configuration register value. ++ * Returns negative if error occurred. ++ */ ++static int read_cr(struct m25p *flash) ++{ ++ u8 code = OPCODE_RDCR; ++ int ret; ++ u8 val; ++ ++ ret = spi_write_then_read(flash->spi, &code, 1, &val, 1); ++ if (ret < 0) { ++ dev_err(&flash->spi->dev, "error %d reading CR\n", ret); ++ return ret; ++ } ++ ++ return val; ++} ++ ++/* + * Write status register 1 byte + * Returns negative if error occurred. + */ +@@ -226,6 +255,93 @@ static int wait_till_ready(struct m25p * + } + + /* ++ * It should be something like this. Note the asterisk alignment. You ++ * also could wrap the right edge neatly to nearly 80 characters. ++ */ ++static int write_sr_cr(struct m25p *flash, u16 val) ++{ ++ flash->command[0] = OPCODE_WRSR; ++ flash->command[1] = val & 0xff; ++ flash->command[2] = (val >> 8); ++ ++ return spi_write(flash->spi, flash->command, 3); ++} ++ ++static int macronix_quad_enable(struct m25p *flash) ++{ ++ int ret, val; ++ u8 cmd[2]; ++ cmd[0] = OPCODE_WRSR; ++ ++ val = read_sr(flash); ++ cmd[1] = val | SR_QUAD_EN_MX; ++ write_enable(flash); ++ ++ spi_write(flash->spi, &cmd, 2); ++ ++ if (wait_till_ready(flash)) ++ return 1; ++ ++ ret = read_sr(flash); ++ if (!(ret > 0 && (ret & SR_QUAD_EN_MX))) { ++ dev_err(&flash->spi->dev, ++ "Macronix Quad bit not set"); ++ return -EINVAL; ++ } ++ ++ return 0; ++} ++ ++static int spansion_quad_enable(struct m25p *flash) ++{ ++ int ret; ++ int quad_en = CR_QUAD_EN_SPAN << 8; ++ ++ write_enable(flash); ++ ++ ret = write_sr_cr(flash, quad_en); ++ if (ret < 0) { ++ dev_err(&flash->spi->dev, ++ "error while writing configuration register"); ++ return -EINVAL; ++ } ++ ++ /* read back and check it */ ++ ret = read_cr(flash); ++ if (!(ret > 0 && (ret & CR_QUAD_EN_SPAN))) { ++ dev_err(&flash->spi->dev, ++ "Spansion Quad bit not set"); ++ return -EINVAL; ++ } ++ ++ return 0; ++} ++ ++static inline int set_quad_mode(struct m25p *flash, u32 jedec_id, int enable) ++{ ++ int status; ++ ++ switch (JEDEC_MFR(jedec_id)) { ++ case CFI_MFR_MACRONIX: ++ status = macronix_quad_enable(flash); ++ if (status) { ++ dev_err(&flash->spi->dev, ++ "Macronix quad not enable"); ++ return -EINVAL; ++ } ++ return status; ++ default: ++ status = spansion_quad_enable(flash); ++ if (status) { ++ dev_err(&flash->spi->dev, ++ "Spansion quad not enable"); ++ return -EINVAL; ++ } ++ return status; ++ } ++} ++ ++/* + * Erase the whole flash memory + * + * Returns 0 if successful, non-zero otherwise. +@@ -355,6 +471,13 @@ static int m25p80_erase(struct mtd_info + return 0; + } + ++static inline int m25p80_dummy_cycles_read(struct m25p *flash) ++{ ++ if (flash->quad_read || flash->fast_read) ++ return 1; ++ return 0; ++} ++ + /* + * Read an address range from the flash chip. The address range + * may be any size provided it is within the physical boundaries. +@@ -373,14 +496,14 @@ static int m25p80_read(struct mtd_info * + spi_message_init(&m); + memset(t, 0, (sizeof t)); + +- /* NOTE: +- * OPCODE_FAST_READ (if available) is faster. +- * Should add 1 byte DUMMY_BYTE. +- */ ++ t[0].memory_map = 1; + t[0].tx_buf = flash->command; +- t[0].len = m25p_cmdsz(flash) + (flash->fast_read ? 1 : 0); ++ t[0].len = flash->mmap ? from : m25p_cmdsz(flash) + ++ m25p80_dummy_cycles_read(flash); + spi_message_add_tail(&t[0], &m); + ++ t[1].memory_map = 1; ++ t[1].rx_nbits = flash->quad_read ? SPI_NBITS_QUAD : 1; + t[1].rx_buf = buf; + t[1].len = len; + spi_message_add_tail(&t[1], &m); +@@ -394,11 +517,6 @@ static int m25p80_read(struct mtd_info * + return 1; + } + +- /* FIXME switch to OPCODE_FAST_READ. It's required for higher +- * clocks; and at this writing, every chip this driver handles +- * supports that opcode. +- */ +- + /* Set up the write data buffer. */ + opcode = flash->read_opcode; + flash->command[0] = opcode; +@@ -406,8 +524,8 @@ static int m25p80_read(struct mtd_info * + + spi_sync(flash->spi, &m); + +- *retlen = m.actual_length - m25p_cmdsz(flash) - +- (flash->fast_read ? 1 : 0); ++ *retlen = flash->mmap ? len : m.actual_length - m25p_cmdsz(flash) - ++ m25p80_dummy_cycles_read(flash); + + mutex_unlock(&flash->lock); + +@@ -713,6 +831,7 @@ struct flash_info { + #define SST_WRITE 0x04 /* use SST byte programming */ + #define M25P_NO_FR 0x08 /* Can't do fastread */ + #define SECT_4K_PMC 0x10 /* OPCODE_BE_4K_PMC works uniformly */ ++#define M25P80_QUAD_READ 0x20 /* Flash supports Quad Read */ + }; + + #define INFO(_jedec_id, _ext_id, _sector_size, _n_sectors, _flags) \ +@@ -789,7 +908,7 @@ static const struct spi_device_id m25p_i + { "mx25l12855e", INFO(0xc22618, 0, 64 * 1024, 256, 0) }, + { "mx25l25635e", INFO(0xc22019, 0, 64 * 1024, 512, 0) }, + { "mx25l25655e", INFO(0xc22619, 0, 64 * 1024, 512, 0) }, +- { "mx66l51235l", INFO(0xc2201a, 0, 64 * 1024, 1024, 0) }, ++ { "mx66l51235l", INFO(0xc2201a, 0, 64 * 1024, 1024, M25P80_QUAD_READ) }, + + /* Micron */ + { "n25q064", INFO(0x20ba17, 0, 64 * 1024, 128, 0) }, +@@ -808,7 +927,7 @@ static const struct spi_device_id m25p_i + { "s25sl032p", INFO(0x010215, 0x4d00, 64 * 1024, 64, 0) }, + { "s25sl064p", INFO(0x010216, 0x4d00, 64 * 1024, 128, 0) }, + { "s25fl256s0", INFO(0x010219, 0x4d00, 256 * 1024, 128, 0) }, +- { "s25fl256s1", INFO(0x010219, 0x4d01, 64 * 1024, 512, 0) }, ++ { "s25fl256s1", INFO(0x010219, 0x4d01, 64 * 1024, 512, M25P80_QUAD_READ) }, + { "s25fl512s", INFO(0x010220, 0x4d00, 256 * 1024, 256, 0) }, + { "s70fl01gs", INFO(0x010221, 0x4d00, 256 * 1024, 256, 0) }, + { "s25sl12800", INFO(0x012018, 0x0300, 256 * 1024, 64, 0) }, +@@ -821,7 +940,7 @@ static const struct spi_device_id m25p_i + { "s25sl032a", INFO(0x010215, 0, 64 * 1024, 64, 0) }, + { "s25sl064a", INFO(0x010216, 0, 64 * 1024, 128, 0) }, + { "s25fl016k", INFO(0xef4015, 0, 64 * 1024, 32, SECT_4K) }, +- { "s25fl064k", INFO(0xef4017, 0, 64 * 1024, 128, SECT_4K) }, ++ { "s25fl064k", INFO(0xef4017, 0x4d01, 64 * 1024, 128, SECT_4K) }, + + /* SST -- large erase sizes are "overlays", "sectors" are 4K */ + { "sst25vf040b", INFO(0xbf258d, 0, 64 * 1024, 8, SECT_4K | SST_WRITE) }, +@@ -949,12 +1068,8 @@ static int m25p_probe(struct spi_device + struct flash_info *info; + unsigned i; + struct mtd_part_parser_data ppdata; +- struct device_node __maybe_unused *np = spi->dev.of_node; +- +-#ifdef CONFIG_MTD_OF_PARTS +- if (!of_device_is_available(np)) +- return -ENODEV; +-#endif ++ struct device_node *np = spi->dev.of_node; ++ int ret; + + /* Platform data helps sort out which chip type we have, as + * well as how this board partitions it. If we don't have +@@ -1001,15 +1116,14 @@ static int m25p_probe(struct spi_device + } + } + +- flash = kzalloc(sizeof *flash, GFP_KERNEL); ++ flash = devm_kzalloc(&spi->dev, sizeof(*flash), GFP_KERNEL); + if (!flash) + return -ENOMEM; +- flash->command = kmalloc(MAX_CMD_SIZE + (flash->fast_read ? 1 : 0), +- GFP_KERNEL); +- if (!flash->command) { +- kfree(flash); ++ ++ ++ flash->command = devm_kzalloc(&spi->dev, MAX_CMD_SIZE, GFP_KERNEL); ++ if (!flash->command) + return -ENOMEM; +- } + + flash->spi = spi; + mutex_init(&flash->lock); +@@ -1039,6 +1153,15 @@ static int m25p_probe(struct spi_device + flash->mtd._erase = m25p80_erase; + flash->mtd._read = m25p80_read; + ++ if (spi->mode & SPI_RX_QUAD && info->flags & M25P80_QUAD_READ) { ++ ret = set_quad_mode(flash, info->jedec_id, 1); ++ if (ret) { ++ dev_err(&flash->spi->dev, "quad mode not supported\n"); ++ return ret; ++ } ++ flash->quad_read = true; ++ } ++ + /* flash protection support for STmicro chips */ + if (JEDEC_MFR(info->jedec_id) == CFI_MFR_ST) { + flash->mtd._lock = m25p80_lock; +@@ -1071,18 +1194,21 @@ static int m25p_probe(struct spi_device + flash->page_size = info->page_size; + flash->mtd.writebufsize = flash->page_size; + +- flash->fast_read = false; +- if (np && of_property_read_bool(np, "m25p,fast-read")) ++ if (np) ++ /* If we were instantiated by DT, use it */ ++ flash->fast_read = of_property_read_bool(np, "m25p,fast-read"); ++ else ++ /* If we weren't instantiated by DT, default to fast-read */ + flash->fast_read = true; + +-#ifdef CONFIG_M25PXX_USE_FAST_READ +- flash->fast_read = true; +-#endif ++ /* Some devices cannot do fast-read, no matter what DT tells us */ + if (info->flags & M25P_NO_FR) + flash->fast_read = false; + + /* Default commands */ +- if (flash->fast_read) ++ if (flash->quad_read) ++ flash->read_opcode = OPCODE_QUAD_READ; ++ else if (flash->fast_read) + flash->read_opcode = OPCODE_FAST_READ; + else + flash->read_opcode = OPCODE_NORM_READ; +@@ -1094,21 +1220,14 @@ static int m25p_probe(struct spi_device + else if (flash->mtd.size > 0x1000000) { + /* enable 4-byte addressing if the device exceeds 16MiB */ + flash->addr_width = 4; +- if (JEDEC_MFR(info->jedec_id) == CFI_MFR_AMD) { +- /* Dedicated 4-byte command set */ +- flash->read_opcode = flash->fast_read ? +- OPCODE_FAST_READ_4B : +- OPCODE_NORM_READ_4B; +- flash->program_opcode = OPCODE_PP_4B; +- /* No small sector erase for 4-byte command set */ +- flash->erase_opcode = OPCODE_SE_4B; +- flash->mtd.erasesize = info->sector_size; +- } else +- set_4byte(flash, info->jedec_id, 1); ++ set_4byte(flash, info->jedec_id, 1); + } else { + flash->addr_width = 3; + } + ++ if (spi->mode & SPI_RX_MMAP) ++ flash->mmap = true; ++ + dev_info(&spi->dev, "%s (%lld Kbytes)\n", id->name, + (long long)flash->mtd.size >> 10); + +@@ -1142,14 +1261,10 @@ static int m25p_probe(struct spi_device + static int m25p_remove(struct spi_device *spi) + { + struct m25p *flash = spi_get_drvdata(spi); +- int status; + + /* Clean up MTD stuff. */ +- status = mtd_device_unregister(&flash->mtd); +- if (status == 0) { +- kfree(flash->command); +- kfree(flash); +- } ++ mtd_device_unregister(&flash->mtd); ++ + return 0; + } + +--- a/drivers/mtd/nand/Kconfig ++++ b/drivers/mtd/nand/Kconfig +@@ -96,35 +96,13 @@ config MTD_NAND_OMAP2 + + config MTD_NAND_OMAP_BCH + depends on MTD_NAND && MTD_NAND_OMAP2 && ARCH_OMAP3 +- tristate "Enable support for hardware BCH error correction" ++ tristate "Support hardware based BCH error correction" + default n + select BCH +- select BCH_CONST_PARAMS + help +- Support for hardware BCH error correction. +- +-choice +- prompt "BCH error correction capability" +- depends on MTD_NAND_OMAP_BCH +- +-config MTD_NAND_OMAP_BCH8 +- bool "8 bits / 512 bytes (recommended)" +- help +- Support correcting up to 8 bitflips per 512-byte block. +- This will use 13 bytes of spare area per 512 bytes of page data. +- This is the recommended mode, as 4-bit mode does not work +- on some OMAP3 revisions, due to a hardware bug. +- +-config MTD_NAND_OMAP_BCH4 +- bool "4 bits / 512 bytes" +- help +- Support correcting up to 4 bitflips per 512-byte block. +- This will use 7 bytes of spare area per 512 bytes of page data. +- Note that this mode does not work on some OMAP3 revisions, due to a +- hardware bug. Please check your OMAP datasheet before selecting this +- mode. +- +-endchoice ++ Some devices have built-in ELM hardware engine, which can be used to ++ locate and correct errors when using BCH ECC scheme. This enables the ++ driver support for same. + + if MTD_NAND_OMAP_BCH + config BCH_CONST_M +--- a/drivers/mtd/nand/omap2.c ++++ b/drivers/mtd/nand/omap2.c +@@ -25,8 +25,11 @@ + #include <linux/of.h> + #include <linux/of_device.h> + +-#ifdef CONFIG_MTD_NAND_OMAP_BCH ++#ifdef CONFIG_MTD_NAND_ECC_BCH + #include <linux/bch.h> ++#include <linux/mtd/nand_bch.h> ++#endif ++#ifdef CONFIG_MTD_NAND_OMAP_BCH + #include <linux/platform_data/elm.h> + #endif + +@@ -35,6 +38,10 @@ + #define DRIVER_NAME "omap2-nand" + #define OMAP_NAND_TIMEOUT_MS 5000 + ++#define GPMC_ECC_READ 0 /* Reset Hardware ECC for read */ ++#define GPMC_ECC_WRITE 1 /* Reset Hardware ECC for write */ ++#define GPMC_ECC_READSYN 2 /* Reset before syndrom is read back */ ++ + #define NAND_Ecc_P1e (1 << 0) + #define NAND_Ecc_P2e (1 << 1) + #define NAND_Ecc_P4e (1 << 2) +@@ -103,13 +110,9 @@ + #define P4o_s(a) (TF(a & NAND_Ecc_P4o) << 1) + + #define PREFETCH_CONFIG1_CS_SHIFT 24 +-#define ECC_CONFIG_CS_SHIFT 1 + #define CS_MASK 0x7 + #define ENABLE_PREFETCH (0x1 << 7) + #define DMA_MPU_MODE_SHIFT 2 +-#define ECCSIZE0_SHIFT 12 +-#define ECCSIZE1_SHIFT 22 +-#define ECC1RESULTSIZE 0x1 + #define ECCCLEAR 0x100 + #define ECC1 0x1 + #define PREFETCH_FIFOTHRESHOLD_MAX 0x40 +@@ -120,33 +123,24 @@ + + #define OMAP24XX_DMA_GPMC 4 + +-#define BCH8_MAX_ERROR 8 /* upto 8 bit correctable */ +-#define BCH4_MAX_ERROR 4 /* upto 4 bit correctable */ +- + #define SECTOR_BYTES 512 + /* 4 bit padding to make byte aligned, 56 = 52 + 4 */ + #define BCH4_BIT_PAD 4 +-#define BCH8_ECC_MAX ((SECTOR_BYTES + BCH8_ECC_OOB_BYTES) * 8) +-#define BCH4_ECC_MAX ((SECTOR_BYTES + BCH4_ECC_OOB_BYTES) * 8) + +-/* GPMC ecc engine settings for read */ +-#define BCH_WRAPMODE_1 1 /* BCH wrap mode 1 */ +-#define BCH8R_ECC_SIZE0 0x1a /* ecc_size0 = 26 */ +-#define BCH8R_ECC_SIZE1 0x2 /* ecc_size1 = 2 */ +-#define BCH4R_ECC_SIZE0 0xd /* ecc_size0 = 13 */ +-#define BCH4R_ECC_SIZE1 0x3 /* ecc_size1 = 3 */ +- +-/* GPMC ecc engine settings for write */ +-#define BCH_WRAPMODE_6 6 /* BCH wrap mode 6 */ +-#define BCH_ECC_SIZE0 0x0 /* ecc_size0 = 0, no oob protection */ +-#define BCH_ECC_SIZE1 0x20 /* ecc_size1 = 32 */ ++#define BADBLOCK_MARKER_LENGTH 0x2 + + #ifdef CONFIG_MTD_NAND_OMAP_BCH +-static u_char bch8_vector[] = {0xf3, 0xdb, 0x14, 0x16, 0x8b, 0xd2, 0xbe, 0xcc, +- 0xac, 0x6b, 0xff, 0x99, 0x7b}; +-static u_char bch4_vector[] = {0x00, 0x6b, 0x31, 0xdd, 0x41, 0xbc, 0x10}; ++static u_char bch4_vector[] = {0x00, 0x6b, 0x31, 0xdd, 0x41, 0xbc, 0x10}; ++static u_char bch8_vector[] = {0xf3, 0xdb, 0x14, 0x16, 0x8b, 0xd2, 0xbe, 0xcc, ++ 0xac, 0x6b, 0xff, 0x99, 0x7b}; ++static u_char bch16_vector[] = {0xf5, 0x24, 0x1c, 0xd0, 0x61, 0xb3, 0xf1, 0x55, ++ 0x2e, 0x2c, 0x86, 0xa3, 0xed, 0x36, 0x1b, 0x78, ++ 0x48, 0x76, 0xa9, 0x3b, 0x97, 0xd1, 0x7a, 0x93, ++ 0x07, 0x0e}; + #endif +- ++static u8 bch4_polynomial[] = {0x28, 0x13, 0xcc, 0x39, 0x96, 0xac, 0x7f}; ++static u8 bch8_polynomial[] = {0xef, 0x51, 0x2e, 0x09, 0xed, 0x93, 0x9a, 0xc2, ++ 0x97, 0x79, 0xe5, 0x24, 0xb5}; + /* oob info generated runtime depending on ecc algorithm and layout selected */ + static struct nand_ecclayout omap_oobinfo; + /* Define some generic bad / good block scan pattern which are used +@@ -171,6 +165,7 @@ struct omap_nand_info { + int gpmc_cs; + unsigned long phys_base; + unsigned long mem_size; ++ enum omap_ecc ecc_opt; + struct completion comp; + struct dma_chan *dma; + int gpmc_irq_fifo; +@@ -180,16 +175,11 @@ struct omap_nand_info { + OMAP_NAND_IO_WRITE, /* write */ + } iomode; + u_char *buf; +- int buf_len; ++ int buf_len; + struct gpmc_nand_regs reg; +- +-#ifdef CONFIG_MTD_NAND_OMAP_BCH +- struct bch_control *bch; +- struct nand_ecclayout ecclayout; +- bool is_elm_used; ++ /* fields specific for BCHx_HW ECC scheme */ + struct device *elm_dev; + struct device_node *of_node; +-#endif + }; + + /** +@@ -948,9 +938,11 @@ static int omap_calculate_ecc(struct mtd + u32 val; + + val = readl(info->reg.gpmc_ecc_config); +- if (((val >> ECC_CONFIG_CS_SHIFT) & ~CS_MASK) != info->gpmc_cs) ++ if (((val >> 1) & 0x7) != info->gpmc_cs) { ++ pr_err("%s: invalid ECC configuration for chip-select=%d", ++ DRIVER_NAME, info->gpmc_cs); + return -EINVAL; +- ++ } + /* read ecc result */ + val = readl(info->reg.gpmc_ecc1_result); + *ecc_code++ = val; /* P128e, ..., P1e */ +@@ -962,47 +954,6 @@ static int omap_calculate_ecc(struct mtd + } + + /** +- * omap_enable_hwecc - This function enables the hardware ecc functionality +- * @mtd: MTD device structure +- * @mode: Read/Write mode +- */ +-static void omap_enable_hwecc(struct mtd_info *mtd, int mode) +-{ +- struct omap_nand_info *info = container_of(mtd, struct omap_nand_info, +- mtd); +- struct nand_chip *chip = mtd->priv; +- unsigned int dev_width = (chip->options & NAND_BUSWIDTH_16) ? 1 : 0; +- u32 val; +- +- /* clear ecc and enable bits */ +- val = ECCCLEAR | ECC1; +- writel(val, info->reg.gpmc_ecc_control); +- +- /* program ecc and result sizes */ +- val = ((((info->nand.ecc.size >> 1) - 1) << ECCSIZE1_SHIFT) | +- ECC1RESULTSIZE); +- writel(val, info->reg.gpmc_ecc_size_config); +- +- switch (mode) { +- case NAND_ECC_READ: +- case NAND_ECC_WRITE: +- writel(ECCCLEAR | ECC1, info->reg.gpmc_ecc_control); +- break; +- case NAND_ECC_READSYN: +- writel(ECCCLEAR, info->reg.gpmc_ecc_control); +- break; +- default: +- dev_info(&info->pdev->dev, +- "error: unrecognized Mode[%d]!\n", mode); +- break; +- } +- +- /* (ECC 16 or 8 bit col) | ( CS ) | ECC Enable */ +- val = (dev_width << 7) | (info->gpmc_cs << 1) | (0x1); +- writel(val, info->reg.gpmc_ecc_config); +-} +- +-/** + * omap_wait - wait until the command is done + * @mtd: MTD device structure + * @chip: NAND Chip structure +@@ -1058,496 +1009,357 @@ static int omap_dev_ready(struct mtd_inf + } + } + +-#ifdef CONFIG_MTD_NAND_OMAP_BCH +- + /** +- * omap3_enable_hwecc_bch - Program OMAP3 GPMC to perform BCH ECC correction ++ * omap_enable_hwecc - Configure OMAP GPMC to perform ECC calculation + * @mtd: MTD device structure + * @mode: Read/Write mode +- * +- * When using BCH, sector size is hardcoded to 512 bytes. +- * Using wrapping mode 6 both for reading and writing if ELM module not uses +- * for error correction. +- * On writing, +- * eccsize0 = 0 (no additional protected byte in spare area) +- * eccsize1 = 32 (skip 32 nibbles = 16 bytes per sector in spare area) ++ * Configurations for eccsize0, eccsize1, and bch_wrapmode are based on ++ * GPMC function spec: ++ * Section 4.6.3.2.3: Supported NAND page mappings and ECC schemes + */ +-static void omap3_enable_hwecc_bch(struct mtd_info *mtd, int mode) ++static void omap_enable_hwecc(struct mtd_info *mtd, int mode) + { +- int nerrors; +- unsigned int dev_width, nsectors; + struct omap_nand_info *info = container_of(mtd, struct omap_nand_info, + mtd); + struct nand_chip *chip = mtd->priv; +- u32 val, wr_mode; +- unsigned int ecc_size1, ecc_size0; +- +- /* Using wrapping mode 6 for writing */ +- wr_mode = BCH_WRAPMODE_6; +- +- /* +- * ECC engine enabled for valid ecc_size0 nibbles +- * and disabled for ecc_size1 nibbles. +- */ +- ecc_size0 = BCH_ECC_SIZE0; +- ecc_size1 = BCH_ECC_SIZE1; +- +- /* Perform ecc calculation on 512-byte sector */ +- nsectors = 1; +- +- /* Update number of error correction */ +- nerrors = info->nand.ecc.strength; +- +- /* Multi sector reading/writing for NAND flash with page size < 4096 */ +- if (info->is_elm_used && (mtd->writesize <= 4096)) { +- if (mode == NAND_ECC_READ) { +- /* Using wrapping mode 1 for reading */ +- wr_mode = BCH_WRAPMODE_1; +- +- /* +- * ECC engine enabled for ecc_size0 nibbles +- * and disabled for ecc_size1 nibbles. +- */ +- ecc_size0 = (nerrors == 8) ? +- BCH8R_ECC_SIZE0 : BCH4R_ECC_SIZE0; +- ecc_size1 = (nerrors == 8) ? +- BCH8R_ECC_SIZE1 : BCH4R_ECC_SIZE1; ++ unsigned int dev_width = (chip->options & NAND_BUSWIDTH_16) ? 1 : 0; ++ unsigned int nsectors = (mtd->writesize / SECTOR_BYTES); ++ unsigned int ecc_algo = 0; ++ unsigned int bch_type = 0; ++ unsigned int eccsize1 = 0x00, eccsize0 = 0x00, bch_wrapmode = 0x00; ++ u32 ecc_size_config_val = 0; ++ u32 ecc_config_val = 0; ++ ++ switch (info->ecc_opt) { ++ case OMAP_ECC_HAMMING_CODE_HW: ++ ecc_algo = 0x0; ++ bch_wrapmode = 0x00; ++ eccsize0 = (chip->ecc.size >> 1) - 1; ++ eccsize1 = 0; ++ nsectors = 0; ++ break; ++ case OMAP_ECC_BCH4_CODE_HW_DETECTION_SW: ++ case OMAP_ECC_BCH4_CODE_HW: ++ ecc_algo = 0x1; ++ bch_type = 0x0; ++ if (mode == GPMC_ECC_READ) { ++ bch_wrapmode = 0x01; ++ eccsize0 = 13; /* ECC bits in nibbles per sector */ ++ eccsize1 = 3; /* non-ECC bits in nibbles per sector */ ++ } else if (mode == GPMC_ECC_WRITE) { ++ eccsize0 = 0; /* extra bits in nibbles per sector */ ++ eccsize1 = 32; /* OOB bits in nibbles per sector */ ++ bch_wrapmode = 0x06; + } +- +- /* Perform ecc calculation for one page (< 4096) */ +- nsectors = info->nand.ecc.steps; ++ break; ++ case OMAP_ECC_BCH8_CODE_HW_DETECTION_SW: ++ case OMAP_ECC_BCH8_CODE_HW: ++ ecc_algo = 0x1; ++ bch_type = 0x1; ++ if (mode == GPMC_ECC_READ) { ++ bch_wrapmode = 0x01; ++ eccsize0 = 26; /* ECC bits in nibbles per sector */ ++ eccsize1 = 2; /* non-ECC bits in nibbles per sector */ ++ } else if (mode == GPMC_ECC_WRITE) { ++ bch_wrapmode = 0x01; ++ eccsize0 = 0; /* extra bits in nibbles per sector */ ++ eccsize1 = 28; /* OOB bits in nibbles per sector */ ++ } ++ break; ++ case OMAP_ECC_BCH16_CODE_HW: ++ ecc_algo = 0x1; ++ bch_type = 0x2; ++ if (mode == GPMC_ECC_READ) { ++ bch_wrapmode = 0x01; ++ eccsize0 = 52; /* ECC bits in nibbles per sector */ ++ eccsize1 = 0; /* non-ECC bits in nibbles per sector */ ++ } else if (mode == GPMC_ECC_WRITE) { ++ bch_wrapmode = 0x01; ++ eccsize0 = 0; /* extra bits in nibbles per sector */ ++ eccsize1 = 52; /* OOB bits in nibbles per sector */ ++ } ++ break; ++ default: ++ pr_err("selected ECC scheme not supported or not enabled\n"); + } +- +- writel(ECC1, info->reg.gpmc_ecc_control); +- +- /* Configure ecc size for BCH */ +- val = (ecc_size1 << ECCSIZE1_SHIFT) | (ecc_size0 << ECCSIZE0_SHIFT); +- writel(val, info->reg.gpmc_ecc_size_config); +- +- dev_width = (chip->options & NAND_BUSWIDTH_16) ? 1 : 0; +- +- /* BCH configuration */ +- val = ((1 << 16) | /* enable BCH */ +- (((nerrors == 8) ? 1 : 0) << 12) | /* 8 or 4 bits */ +- (wr_mode << 8) | /* wrap mode */ +- (dev_width << 7) | /* bus width */ +- (((nsectors-1) & 0x7) << 4) | /* number of sectors */ +- (info->gpmc_cs << 1) | /* ECC CS */ +- (0x1)); /* enable ECC */ +- +- writel(val, info->reg.gpmc_ecc_config); +- + /* Clear ecc and enable bits */ + writel(ECCCLEAR | ECC1, info->reg.gpmc_ecc_control); ++ /* Configure ecc size for BCH */ ++ ecc_size_config_val = (eccsize1 << 22) | (eccsize0 << 12); ++ writel(ecc_size_config_val, info->reg.gpmc_ecc_size_config); ++ /* Configure device details for BCH engine */ ++ ecc_config_val = ((ecc_algo << 16) | /* HAM1 | BCHx */ ++ (bch_type << 12) | /* BCH4/BCH8/BCH16 */ ++ (bch_wrapmode << 8) | /* wrap mode */ ++ (dev_width << 7) | /* bus width */ ++ (((nsectors-1) & 0x7) << 4) | /* number of sectors */ ++ (info->gpmc_cs << 1) | /* ECC CS */ ++ (0x0)); /* disable ECC */ ++ writel(ecc_config_val, info->reg.gpmc_ecc_config); ++ /* enable ECC engine */ ++ writel(ecc_config_val | 0x1, info->reg.gpmc_ecc_config); ++ /* Clear ECC and enable bits */ ++ writel(ECCCLEAR | ECC1, info->reg.gpmc_ecc_control); + } + ++#if defined(CONFIG_MTD_NAND_ECC_BCH) || defined(CONFIG_MTD_NAND_OMAP_BCH) + /** +- * omap3_calculate_ecc_bch4 - Generate 7 bytes of ECC bytes +- * @mtd: MTD device structure +- * @dat: The pointer to data on which ecc is computed +- * @ecc_code: The ecc_code buffer +- */ +-static int omap3_calculate_ecc_bch4(struct mtd_info *mtd, const u_char *dat, +- u_char *ecc_code) +-{ +- struct omap_nand_info *info = container_of(mtd, struct omap_nand_info, +- mtd); +- unsigned long nsectors, val1, val2; +- int i; +- +- nsectors = ((readl(info->reg.gpmc_ecc_config) >> 4) & 0x7) + 1; +- +- for (i = 0; i < nsectors; i++) { +- +- /* Read hw-computed remainder */ +- val1 = readl(info->reg.gpmc_bch_result0[i]); +- val2 = readl(info->reg.gpmc_bch_result1[i]); +- +- /* +- * Add constant polynomial to remainder, in order to get an ecc +- * sequence of 0xFFs for a buffer filled with 0xFFs; and +- * left-justify the resulting polynomial. +- */ +- *ecc_code++ = 0x28 ^ ((val2 >> 12) & 0xFF); +- *ecc_code++ = 0x13 ^ ((val2 >> 4) & 0xFF); +- *ecc_code++ = 0xcc ^ (((val2 & 0xF) << 4)|((val1 >> 28) & 0xF)); +- *ecc_code++ = 0x39 ^ ((val1 >> 20) & 0xFF); +- *ecc_code++ = 0x96 ^ ((val1 >> 12) & 0xFF); +- *ecc_code++ = 0xac ^ ((val1 >> 4) & 0xFF); +- *ecc_code++ = 0x7f ^ ((val1 & 0xF) << 4); +- } +- +- return 0; +-} +- +-/** +- * omap3_calculate_ecc_bch8 - Generate 13 bytes of ECC bytes +- * @mtd: MTD device structure +- * @dat: The pointer to data on which ecc is computed +- * @ecc_code: The ecc_code buffer +- */ +-static int omap3_calculate_ecc_bch8(struct mtd_info *mtd, const u_char *dat, +- u_char *ecc_code) +-{ +- struct omap_nand_info *info = container_of(mtd, struct omap_nand_info, +- mtd); +- unsigned long nsectors, val1, val2, val3, val4; +- int i; +- +- nsectors = ((readl(info->reg.gpmc_ecc_config) >> 4) & 0x7) + 1; +- +- for (i = 0; i < nsectors; i++) { +- +- /* Read hw-computed remainder */ +- val1 = readl(info->reg.gpmc_bch_result0[i]); +- val2 = readl(info->reg.gpmc_bch_result1[i]); +- val3 = readl(info->reg.gpmc_bch_result2[i]); +- val4 = readl(info->reg.gpmc_bch_result3[i]); +- +- /* +- * Add constant polynomial to remainder, in order to get an ecc +- * sequence of 0xFFs for a buffer filled with 0xFFs. +- */ +- *ecc_code++ = 0xef ^ (val4 & 0xFF); +- *ecc_code++ = 0x51 ^ ((val3 >> 24) & 0xFF); +- *ecc_code++ = 0x2e ^ ((val3 >> 16) & 0xFF); +- *ecc_code++ = 0x09 ^ ((val3 >> 8) & 0xFF); +- *ecc_code++ = 0xed ^ (val3 & 0xFF); +- *ecc_code++ = 0x93 ^ ((val2 >> 24) & 0xFF); +- *ecc_code++ = 0x9a ^ ((val2 >> 16) & 0xFF); +- *ecc_code++ = 0xc2 ^ ((val2 >> 8) & 0xFF); +- *ecc_code++ = 0x97 ^ (val2 & 0xFF); +- *ecc_code++ = 0x79 ^ ((val1 >> 24) & 0xFF); +- *ecc_code++ = 0xe5 ^ ((val1 >> 16) & 0xFF); +- *ecc_code++ = 0x24 ^ ((val1 >> 8) & 0xFF); +- *ecc_code++ = 0xb5 ^ (val1 & 0xFF); +- } +- +- return 0; +-} +- +-/** +- * omap3_calculate_ecc_bch - Generate bytes of ECC bytes ++ * omap_calculate_ecc_bch - Generate bytes of ECC bytes + * @mtd: MTD device structure + * @dat: The pointer to data on which ecc is computed + * @ecc_code: The ecc_code buffer + * + * Support calculating of BCH4/8 ecc vectors for the page + */ +-static int omap3_calculate_ecc_bch(struct mtd_info *mtd, const u_char *dat, +- u_char *ecc_code) ++static int omap_calculate_ecc_bch(struct mtd_info *mtd, const u_char *dat, ++ u_char *ecc_calc) + { + struct omap_nand_info *info = container_of(mtd, struct omap_nand_info, + mtd); +- unsigned long nsectors, bch_val1, bch_val2, bch_val3, bch_val4; +- int i, eccbchtsel; ++ struct nand_chip *chip = mtd->priv; ++ enum omap_ecc ecc_opt = info->ecc_opt; ++ struct gpmc_nand_regs *gpmc_regs = &info->reg; ++ u32 eccbytes = chip->ecc.bytes; ++ u_char *ecc_ptr; ++ u32 nsectors; ++ int i, val; + +- nsectors = ((readl(info->reg.gpmc_ecc_config) >> 4) & 0x7) + 1; +- /* +- * find BCH scheme used +- * 0 -> BCH4 +- * 1 -> BCH8 +- */ +- eccbchtsel = ((readl(info->reg.gpmc_ecc_config) >> 12) & 0x3); ++ val = readl(info->reg.gpmc_ecc_config); ++ if (((val >> 1) & 0x07) != info->gpmc_cs) { ++ pr_err("%s: invalid ECC configuration for chip-select=%d", ++ DRIVER_NAME, info->gpmc_cs); ++ return -EINVAL; ++ } ++ nsectors = ((readl(gpmc_regs->gpmc_ecc_config) >> 4) & 0x7) + 1; + + for (i = 0; i < nsectors; i++) { +- +- /* Read hw-computed remainder */ +- bch_val1 = readl(info->reg.gpmc_bch_result0[i]); +- bch_val2 = readl(info->reg.gpmc_bch_result1[i]); +- if (eccbchtsel) { +- bch_val3 = readl(info->reg.gpmc_bch_result2[i]); +- bch_val4 = readl(info->reg.gpmc_bch_result3[i]); +- } +- +- if (eccbchtsel) { +- /* BCH8 ecc scheme */ +- *ecc_code++ = (bch_val4 & 0xFF); +- *ecc_code++ = ((bch_val3 >> 24) & 0xFF); +- *ecc_code++ = ((bch_val3 >> 16) & 0xFF); +- *ecc_code++ = ((bch_val3 >> 8) & 0xFF); +- *ecc_code++ = (bch_val3 & 0xFF); +- *ecc_code++ = ((bch_val2 >> 24) & 0xFF); +- *ecc_code++ = ((bch_val2 >> 16) & 0xFF); +- *ecc_code++ = ((bch_val2 >> 8) & 0xFF); +- *ecc_code++ = (bch_val2 & 0xFF); +- *ecc_code++ = ((bch_val1 >> 24) & 0xFF); +- *ecc_code++ = ((bch_val1 >> 16) & 0xFF); +- *ecc_code++ = ((bch_val1 >> 8) & 0xFF); +- *ecc_code++ = (bch_val1 & 0xFF); +- /* +- * Setting 14th byte to zero to handle +- * erased page & maintain compatibility +- * with RBL +- */ +- *ecc_code++ = 0x0; +- } else { +- /* BCH4 ecc scheme */ +- *ecc_code++ = ((bch_val2 >> 12) & 0xFF); +- *ecc_code++ = ((bch_val2 >> 4) & 0xFF); +- *ecc_code++ = ((bch_val2 & 0xF) << 4) | +- ((bch_val1 >> 28) & 0xF); +- *ecc_code++ = ((bch_val1 >> 20) & 0xFF); +- *ecc_code++ = ((bch_val1 >> 12) & 0xFF); +- *ecc_code++ = ((bch_val1 >> 4) & 0xFF); +- *ecc_code++ = ((bch_val1 & 0xF) << 4); +- /* +- * Setting 8th byte to zero to handle +- * erased page +- */ +- *ecc_code++ = 0x0; ++ ecc_ptr = ecc_calc; ++ switch (ecc_opt) { ++ case OMAP_ECC_HAMMING_CODE_HW: ++ return -EINVAL; ++ case OMAP_ECC_BCH4_CODE_HW_DETECTION_SW: ++ case OMAP_ECC_BCH4_CODE_HW: ++ val = readl(gpmc_regs->gpmc_bch_result1[i]); ++ *(ecc_ptr++) = ((val >> 12) & 0xFF); ++ *(ecc_ptr++) = ((val >> 4) & 0xFF); ++ *(ecc_ptr) = ((val >> 0) << 4) & 0xF0; ++ val = readl(gpmc_regs->gpmc_bch_result0[i]); ++ *(ecc_ptr) = ((val >> 28) & 0x0F) | *(ecc_ptr); ++ ecc_ptr++; ++ *(ecc_ptr++) = ((val >> 20) & 0xFF); ++ *(ecc_ptr++) = ((val >> 12) & 0xFF); ++ *(ecc_ptr++) = ((val >> 4) & 0xFF); ++ *(ecc_ptr++) = ((val >> 0) << 4) & 0xF0; ++ break; ++ case OMAP_ECC_BCH8_CODE_HW_DETECTION_SW: ++ case OMAP_ECC_BCH8_CODE_HW: ++ val = readl(gpmc_regs->gpmc_bch_result3[i]); ++ *(ecc_ptr++) = ((val >> 0) & 0xFF); ++ val = readl(gpmc_regs->gpmc_bch_result2[i]); ++ *(ecc_ptr++) = ((val >> 24) & 0xFF); ++ *(ecc_ptr++) = ((val >> 16) & 0xFF); ++ *(ecc_ptr++) = ((val >> 8) & 0xFF); ++ *(ecc_ptr++) = ((val >> 0) & 0xFF); ++ val = readl(gpmc_regs->gpmc_bch_result1[i]); ++ *(ecc_ptr++) = ((val >> 24) & 0xFF); ++ *(ecc_ptr++) = ((val >> 16) & 0xFF); ++ *(ecc_ptr++) = ((val >> 8) & 0xFF); ++ *(ecc_ptr++) = ((val >> 0) & 0xFF); ++ val = readl(gpmc_regs->gpmc_bch_result0[i]); ++ *(ecc_ptr++) = ((val >> 24) & 0xFF); ++ *(ecc_ptr++) = ((val >> 16) & 0xFF); ++ *(ecc_ptr++) = ((val >> 8) & 0xFF); ++ *(ecc_ptr++) = ((val >> 0) & 0xFF); ++ break; ++ case OMAP_ECC_BCH16_CODE_HW: ++ val = readl(gpmc_regs->gpmc_bch_result6[i]); ++ *(ecc_ptr++) = ((val >> 8) & 0xFF); ++ *(ecc_ptr++) = ((val >> 0) & 0xFF); ++ val = readl(gpmc_regs->gpmc_bch_result5[i]); ++ *(ecc_ptr++) = ((val >> 24) & 0xFF); ++ *(ecc_ptr++) = ((val >> 16) & 0xFF); ++ *(ecc_ptr++) = ((val >> 8) & 0xFF); ++ *(ecc_ptr++) = ((val >> 0) & 0xFF); ++ val = readl(gpmc_regs->gpmc_bch_result4[i]); ++ *(ecc_ptr++) = ((val >> 24) & 0xFF); ++ *(ecc_ptr++) = ((val >> 16) & 0xFF); ++ *(ecc_ptr++) = ((val >> 8) & 0xFF); ++ *(ecc_ptr++) = ((val >> 0) & 0xFF); ++ val = readl(gpmc_regs->gpmc_bch_result3[i]); ++ *(ecc_ptr++) = ((val >> 24) & 0xFF); ++ *(ecc_ptr++) = ((val >> 16) & 0xFF); ++ *(ecc_ptr++) = ((val >> 8) & 0xFF); ++ *(ecc_ptr++) = ((val >> 0) & 0xFF); ++ val = readl(gpmc_regs->gpmc_bch_result2[i]); ++ *(ecc_ptr++) = ((val >> 24) & 0xFF); ++ *(ecc_ptr++) = ((val >> 16) & 0xFF); ++ *(ecc_ptr++) = ((val >> 8) & 0xFF); ++ *(ecc_ptr++) = ((val >> 0) & 0xFF); ++ val = readl(gpmc_regs->gpmc_bch_result1[i]); ++ *(ecc_ptr++) = ((val >> 24) & 0xFF); ++ *(ecc_ptr++) = ((val >> 16) & 0xFF); ++ *(ecc_ptr++) = ((val >> 8) & 0xFF); ++ *(ecc_ptr++) = ((val >> 0) & 0xFF); ++ val = readl(gpmc_regs->gpmc_bch_result0[i]); ++ *(ecc_ptr++) = ((val >> 24) & 0xFF); ++ *(ecc_ptr++) = ((val >> 16) & 0xFF); ++ *(ecc_ptr++) = ((val >> 8) & 0xFF); ++ *(ecc_ptr++) = ((val >> 0) & 0xFF); ++ break; ++ default: ++ return -EINVAL; + } ++ /* ECC scheme specific syndrome customizations */ ++ switch (ecc_opt) { ++ case OMAP_ECC_HAMMING_CODE_HW: ++ return -EINVAL; ++ case OMAP_ECC_BCH4_CODE_HW_DETECTION_SW: ++ for (i = 0; i < eccbytes; i++) ++ *(ecc_calc + i) = *(ecc_calc + i) ^ ++ bch4_polynomial[i]; ++ break; ++ case OMAP_ECC_BCH4_CODE_HW: ++ *(ecc_ptr++) = 0x00; ++ break; ++ case OMAP_ECC_BCH8_CODE_HW_DETECTION_SW: ++ for (i = 0; i < eccbytes; i++) ++ *(ecc_calc + i) = *(ecc_calc + i) ^ ++ bch8_polynomial[i]; ++ break; ++ case OMAP_ECC_BCH8_CODE_HW: ++ *(ecc_ptr++) = 0x00; ++ break; ++ case OMAP_ECC_BCH16_CODE_HW: ++ break; ++ } ++ /* update pointer to next sector */ ++ ecc_calc += eccbytes; + } +- + return 0; + } ++#endif /*defined(CONFIG_MTD_NAND_ECC_BCH) || defined(CONFIG_MTD_NAND_OMAP_BCH)*/ + +-/** +- * erased_sector_bitflips - count bit flips +- * @data: data sector buffer +- * @oob: oob buffer +- * @info: omap_nand_info +- * +- * Check the bit flips in erased page falls below correctable level. +- * If falls below, report the page as erased with correctable bit +- * flip, else report as uncorrectable page. +- */ +-static int erased_sector_bitflips(u_char *data, u_char *oob, +- struct omap_nand_info *info) +-{ +- int flip_bits = 0, i; +- +- for (i = 0; i < info->nand.ecc.size; i++) { +- flip_bits += hweight8(~data[i]); +- if (flip_bits > info->nand.ecc.strength) +- return 0; +- } +- +- for (i = 0; i < info->nand.ecc.bytes - 1; i++) { +- flip_bits += hweight8(~oob[i]); +- if (flip_bits > info->nand.ecc.strength) +- return 0; +- } +- +- /* +- * Bit flips falls in correctable level. +- * Fill data area with 0xFF +- */ +- if (flip_bits) { +- memset(data, 0xFF, info->nand.ecc.size); +- memset(oob, 0xFF, info->nand.ecc.bytes); +- } +- +- return flip_bits; +-} +- ++#ifdef CONFIG_MTD_NAND_OMAP_BCH + /** + * omap_elm_correct_data - corrects page data area in case error reported + * @mtd: MTD device structure + * @data: page data + * @read_ecc: ecc read from nand flash +- * @calc_ecc: ecc read from HW ECC registers +- * +- * Calculated ecc vector reported as zero in case of non-error pages. +- * In case of error/erased pages non-zero error vector is reported. +- * In case of non-zero ecc vector, check read_ecc at fixed offset +- * (x = 13/7 in case of BCH8/4 == 0) to find page programmed or not. +- * To handle bit flips in this data, count the number of 0's in +- * read_ecc[x] and check if it greater than 4. If it is less, it is +- * programmed page, else erased page. +- * +- * 1. If page is erased, check with standard ecc vector (ecc vector +- * for erased page to find any bit flip). If check fails, bit flip +- * is present in erased page. Count the bit flips in erased page and +- * if it falls under correctable level, report page with 0xFF and +- * update the correctable bit information. +- * 2. If error is reported on programmed page, update elm error +- * vector and correct the page with ELM error correction routine. +- * ++ * @calc_ecc: ecc calculated after reading Data and OOB regions from flash ++ * As calc_ecc is calculated over both main & oob, so calc_ecc would be ++ * non-zero only in following cases: ++ * - bit-flips in data or oob region ++ * - erase page, where no ECC is written in OOB area ++ * However, erased_pages can be differentiated from corrupted pages ++ * by comparing the calculated ECC with pre-defined syndrome ECC_of_ALL(0xFF) ++ * Bit-flips in erased-pages would also be caught by comparing, calc_ecc ++ * with ECC_of_ALL(0xFF) + */ + static int omap_elm_correct_data(struct mtd_info *mtd, u_char *data, + u_char *read_ecc, u_char *calc_ecc) + { + struct omap_nand_info *info = container_of(mtd, struct omap_nand_info, + mtd); +- int eccsteps = info->nand.ecc.steps; +- int i , j, stat = 0; +- int eccsize, eccflag, ecc_vector_size; ++ enum omap_ecc ecc_opt = info->ecc_opt; ++ struct nand_chip *chip = mtd->priv; ++ int eccsteps = chip->ecc.steps; ++ int eccsize = chip->ecc.size; ++ int eccbytes = chip->ecc.bytes; ++ int i , j, stat = 0, ret = 0, flag_read_ecc; + struct elm_errorvec err_vec[ERROR_VECTOR_MAX]; +- u_char *ecc_vec = calc_ecc; +- u_char *spare_ecc = read_ecc; +- u_char *erased_ecc_vec; +- enum bch_ecc type; ++ u_char *ecc; + bool is_error_reported = false; ++ u32 bit_pos, byte_pos, error_max, pos; + + /* Initialize elm error vector to zero */ + memset(err_vec, 0, sizeof(err_vec)); +- +- if (info->nand.ecc.strength == BCH8_MAX_ERROR) { +- type = BCH8_ECC; +- erased_ecc_vec = bch8_vector; +- } else { +- type = BCH4_ECC; +- erased_ecc_vec = bch4_vector; +- } +- +- ecc_vector_size = info->nand.ecc.bytes; +- +- /* +- * Remove extra byte padding for BCH8 RBL +- * compatibility and erased page handling +- */ +- eccsize = ecc_vector_size - 1; +- + for (i = 0; i < eccsteps ; i++) { +- eccflag = 0; /* initialize eccflag */ +- +- /* +- * Check any error reported, +- * In case of error, non zero ecc reported. +- */ +- +- for (j = 0; (j < eccsize); j++) { +- if (calc_ecc[j] != 0) { +- eccflag = 1; /* non zero ecc, error present */ ++ flag_read_ecc = 0; ++ ecc = calc_ecc + (i * eccbytes); ++ /* check calc_ecc */ ++ for (j = 0; j < eccbytes; j++) { ++ if (*(ecc + j) != 0x00) { ++ flag_read_ecc = 1; + break; + } + } +- +- if (eccflag == 1) { +- /* +- * Set threshold to minimum of 4, half of ecc.strength/2 +- * to allow max bit flip in byte to 4 +- */ +- unsigned int threshold = min_t(unsigned int, 4, +- info->nand.ecc.strength / 2); +- +- /* +- * Check data area is programmed by counting +- * number of 0's at fixed offset in spare area. +- * Checking count of 0's against threshold. +- * In case programmed page expects at least threshold +- * zeros in byte. +- * If zeros are less than threshold for programmed page/ +- * zeros are more than threshold erased page, either +- * case page reported as uncorrectable. +- */ +- if (hweight8(~read_ecc[eccsize]) >= threshold) { +- /* +- * Update elm error vector as +- * data area is programmed +- */ +- err_vec[i].error_reported = true; +- is_error_reported = true; +- } else { +- /* Error reported in erased page */ +- int bitflip_count; +- u_char *buf = &data[info->nand.ecc.size * i]; +- +- if (memcmp(calc_ecc, erased_ecc_vec, eccsize)) { +- bitflip_count = erased_sector_bitflips( +- buf, read_ecc, info); +- +- if (bitflip_count) +- stat += bitflip_count; +- else +- return -EINVAL; +- } ++ /* check if its a erased-page */ ++ if (flag_read_ecc) { ++ switch (ecc_opt) { ++ case OMAP_ECC_BCH4_CODE_HW: ++ if (memcmp(ecc, bch4_vector, eccbytes)) ++ err_vec[i].error_reported = true; ++ break; ++ case OMAP_ECC_BCH8_CODE_HW: ++ if (memcmp(ecc, bch8_vector, eccbytes)) ++ err_vec[i].error_reported = true; ++ break; ++ case OMAP_ECC_BCH16_CODE_HW: ++ if (memcmp(ecc, bch16_vector, eccbytes)) ++ err_vec[i].error_reported = true; ++ break; ++ default: ++ pr_err("%s: invalid configuration", ++ DRIVER_NAME); ++ return -EINVAL; + } + } +- +- /* Update the ecc vector */ +- calc_ecc += ecc_vector_size; +- read_ecc += ecc_vector_size; ++ /* page definitely has bit-flips */ ++ if (err_vec[i].error_reported) ++ is_error_reported = true; + } + +- /* Check if any error reported */ + if (!is_error_reported) + return 0; ++ /* detect bit-flips using ELM module */ ++ elm_decode_bch_error_page(info->elm_dev, calc_ecc, err_vec); + +- /* Decode BCH error using ELM module */ +- elm_decode_bch_error_page(info->elm_dev, ecc_vec, err_vec); +- ++ /* correct bit-flip */ + for (i = 0; i < eccsteps; i++) { +- if (err_vec[i].error_reported) { ++ if (err_vec[i].error_uncorrectable) { ++ ret = -EBADMSG; ++ } else if (err_vec[i].error_reported) { + for (j = 0; j < err_vec[i].error_count; j++) { +- u32 bit_pos, byte_pos, error_max, pos; +- +- if (type == BCH8_ECC) +- error_max = BCH8_ECC_MAX; +- else +- error_max = BCH4_ECC_MAX; +- +- if (info->nand.ecc.strength == BCH8_MAX_ERROR) +- pos = err_vec[i].error_loc[j]; +- else ++ switch (ecc_opt) { ++ case OMAP_ECC_BCH4_CODE_HW: ++ error_max = SECTOR_BYTES + ++ (eccbytes - 1); + /* Add 4 to take care 4 bit padding */ + pos = err_vec[i].error_loc[j] + +- BCH4_BIT_PAD; +- +- /* Calculate bit position of error */ ++ BCH4_BIT_PAD; ++ break; ++ case OMAP_ECC_BCH8_CODE_HW: ++ error_max = SECTOR_BYTES + ++ (eccbytes - 1); ++ pos = err_vec[i].error_loc[j]; ++ break; ++ case OMAP_ECC_BCH16_CODE_HW: ++ error_max = SECTOR_BYTES + eccbytes; ++ pos = err_vec[i].error_loc[j]; ++ break; ++ default: ++ return -EINVAL; ++ } ++ /* Calculate bit & byte bit-flip position */ + bit_pos = pos % 8; +- +- /* Calculate byte position of error */ +- byte_pos = (error_max - pos - 1) / 8; +- +- if (pos < error_max) { +- if (byte_pos < 512) +- data[byte_pos] ^= 1 << bit_pos; +- else +- spare_ecc[byte_pos - 512] ^= ++ byte_pos = error_max - (pos / 8) - 1; ++ if (byte_pos < SECTOR_BYTES) ++ data[byte_pos] ^= 1 << bit_pos; ++ else if (byte_pos < error_max) ++ read_ecc[byte_pos - SECTOR_BYTES] ^= + 1 << bit_pos; +- } +- /* else, not interested to correct ecc */ ++ else ++ ret = -EBADMSG; + } + } +- + /* Update number of correctable errors */ + stat += err_vec[i].error_count; +- + /* Update page data with sector size */ +- data += info->nand.ecc.size; +- spare_ecc += ecc_vector_size; ++ data += eccsize; ++ read_ecc += eccbytes; + } + +- for (i = 0; i < eccsteps; i++) +- /* Return error if uncorrectable error present */ +- if (err_vec[i].error_uncorrectable) +- return -EINVAL; +- +- return stat; +-} +- +-/** +- * omap3_correct_data_bch - Decode received data and correct errors +- * @mtd: MTD device structure +- * @data: page data +- * @read_ecc: ecc read from nand flash +- * @calc_ecc: ecc read from HW ECC registers +- */ +-static int omap3_correct_data_bch(struct mtd_info *mtd, u_char *data, +- u_char *read_ecc, u_char *calc_ecc) +-{ +- int i, count; +- /* cannot correct more than 8 errors */ +- unsigned int errloc[8]; +- struct omap_nand_info *info = container_of(mtd, struct omap_nand_info, +- mtd); +- +- count = decode_bch(info->bch, NULL, 512, read_ecc, calc_ecc, NULL, +- errloc); +- if (count > 0) { +- /* correct errors */ +- for (i = 0; i < count; i++) { +- /* correct data only, not ecc bytes */ +- if (errloc[i] < 8*512) +- data[errloc[i]/8] ^= 1 << (errloc[i] & 7); +- pr_debug("corrected bitflip %u\n", errloc[i]); +- } +- } else if (count < 0) { +- pr_err("ecc unrecoverable error\n"); +- } +- return count; ++ return (ret < 0) ? ret : stat; + } + + /** +@@ -1637,186 +1449,30 @@ static int omap_read_page_bch(struct mtd + } + + /** +- * omap3_free_bch - Release BCH ecc resources +- * @mtd: MTD device structure +- */ +-static void omap3_free_bch(struct mtd_info *mtd) +-{ +- struct omap_nand_info *info = container_of(mtd, struct omap_nand_info, +- mtd); +- if (info->bch) { +- free_bch(info->bch); +- info->bch = NULL; +- } +-} +- +-/** +- * omap3_init_bch - Initialize BCH ECC +- * @mtd: MTD device structure +- * @ecc_opt: OMAP ECC mode (OMAP_ECC_BCH4_CODE_HW or OMAP_ECC_BCH8_CODE_HW) +- */ +-static int omap3_init_bch(struct mtd_info *mtd, int ecc_opt) +-{ +- int max_errors; +- struct omap_nand_info *info = container_of(mtd, struct omap_nand_info, +- mtd); +-#ifdef CONFIG_MTD_NAND_OMAP_BCH8 +- const int hw_errors = BCH8_MAX_ERROR; +-#else +- const int hw_errors = BCH4_MAX_ERROR; +-#endif +- enum bch_ecc bch_type; +- const __be32 *parp; +- int lenp; +- struct device_node *elm_node; +- +- info->bch = NULL; +- +- max_errors = (ecc_opt == OMAP_ECC_BCH8_CODE_HW) ? +- BCH8_MAX_ERROR : BCH4_MAX_ERROR; +- if (max_errors != hw_errors) { +- pr_err("cannot configure %d-bit BCH ecc, only %d-bit supported", +- max_errors, hw_errors); +- goto fail; +- } +- +- info->nand.ecc.size = 512; +- info->nand.ecc.hwctl = omap3_enable_hwecc_bch; +- info->nand.ecc.mode = NAND_ECC_HW; +- info->nand.ecc.strength = max_errors; +- +- if (hw_errors == BCH8_MAX_ERROR) +- bch_type = BCH8_ECC; +- else +- bch_type = BCH4_ECC; +- +- /* Detect availability of ELM module */ +- parp = of_get_property(info->of_node, "elm_id", &lenp); +- if ((parp == NULL) && (lenp != (sizeof(void *) * 2))) { +- pr_err("Missing elm_id property, fall back to Software BCH\n"); +- info->is_elm_used = false; +- } else { +- struct platform_device *pdev; +- +- elm_node = of_find_node_by_phandle(be32_to_cpup(parp)); +- pdev = of_find_device_by_node(elm_node); +- info->elm_dev = &pdev->dev; +- +- if (elm_config(info->elm_dev, bch_type) == 0) +- info->is_elm_used = true; +- } +- +- if (info->is_elm_used && (mtd->writesize <= 4096)) { +- +- if (hw_errors == BCH8_MAX_ERROR) +- info->nand.ecc.bytes = BCH8_SIZE; +- else +- info->nand.ecc.bytes = BCH4_SIZE; +- +- info->nand.ecc.correct = omap_elm_correct_data; +- info->nand.ecc.calculate = omap3_calculate_ecc_bch; +- info->nand.ecc.read_page = omap_read_page_bch; +- info->nand.ecc.write_page = omap_write_page_bch; +- } else { +- /* +- * software bch library is only used to detect and +- * locate errors +- */ +- info->bch = init_bch(13, max_errors, +- 0x201b /* hw polynomial */); +- if (!info->bch) +- goto fail; +- +- info->nand.ecc.correct = omap3_correct_data_bch; +- +- /* +- * The number of corrected errors in an ecc block that will +- * trigger block scrubbing defaults to the ecc strength (4 or 8) +- * Set mtd->bitflip_threshold here to define a custom threshold. +- */ +- +- if (max_errors == 8) { +- info->nand.ecc.bytes = 13; +- info->nand.ecc.calculate = omap3_calculate_ecc_bch8; +- } else { +- info->nand.ecc.bytes = 7; +- info->nand.ecc.calculate = omap3_calculate_ecc_bch4; +- } +- } +- +- pr_info("enabling NAND BCH ecc with %d-bit correction\n", max_errors); +- return 0; +-fail: +- omap3_free_bch(mtd); +- return -1; +-} +- +-/** +- * omap3_init_bch_tail - Build an oob layout for BCH ECC correction. +- * @mtd: MTD device structure +- */ +-static int omap3_init_bch_tail(struct mtd_info *mtd) +-{ +- int i, steps, offset; +- struct omap_nand_info *info = container_of(mtd, struct omap_nand_info, +- mtd); +- struct nand_ecclayout *layout = &info->ecclayout; +- +- /* build oob layout */ +- steps = mtd->writesize/info->nand.ecc.size; +- layout->eccbytes = steps*info->nand.ecc.bytes; +- +- /* do not bother creating special oob layouts for small page devices */ +- if (mtd->oobsize < 64) { +- pr_err("BCH ecc is not supported on small page devices\n"); +- goto fail; ++ * is_elm_present - checks for presence of ELM module by scanning DT nodes ++ * @omap_nand_info: NAND device structure containing platform data ++ * @bch_type: 0x0=BCH4, 0x1=BCH8, 0x2=BCH16 ++ */ ++static int is_elm_present(struct omap_nand_info *info, ++ struct device_node *elm_node, enum bch_ecc bch_type) ++{ ++ struct platform_device *pdev; ++ /* check whether elm-id is passed via DT */ ++ if (!elm_node) { ++ pr_err("nand: error: ELM DT node not found\n"); ++ return -ENODEV; + } +- +- /* reserve 2 bytes for bad block marker */ +- if (layout->eccbytes+2 > mtd->oobsize) { +- pr_err("no oob layout available for oobsize %d eccbytes %u\n", +- mtd->oobsize, layout->eccbytes); +- goto fail; ++ pdev = of_find_device_by_node(elm_node); ++ /* check whether ELM device is registered */ ++ if (!pdev) { ++ pr_err("nand: error: ELM device not found\n"); ++ return -ENODEV; + } +- +- /* ECC layout compatible with RBL for BCH8 */ +- if (info->is_elm_used && (info->nand.ecc.bytes == BCH8_SIZE)) +- offset = 2; +- else +- offset = mtd->oobsize - layout->eccbytes; +- +- /* put ecc bytes at oob tail */ +- for (i = 0; i < layout->eccbytes; i++) +- layout->eccpos[i] = offset + i; +- +- if (info->is_elm_used && (info->nand.ecc.bytes == BCH8_SIZE)) +- layout->oobfree[0].offset = 2 + layout->eccbytes * steps; +- else +- layout->oobfree[0].offset = 2; +- +- layout->oobfree[0].length = mtd->oobsize-2-layout->eccbytes; +- info->nand.ecc.layout = layout; +- +- if (!(info->nand.options & NAND_BUSWIDTH_16)) +- info->nand.badblock_pattern = &bb_descrip_flashbased; ++ /* ELM module available, now configure it */ ++ info->elm_dev = &pdev->dev; ++ if (elm_config(info->elm_dev, &info->mtd, bch_type)) ++ return -ENODEV; + return 0; +-fail: +- omap3_free_bch(mtd); +- return -1; +-} +- +-#else +-static int omap3_init_bch(struct mtd_info *mtd, int ecc_opt) +-{ +- pr_err("CONFIG_MTD_NAND_OMAP_BCH is not enabled\n"); +- return -1; +-} +-static int omap3_init_bch_tail(struct mtd_info *mtd) +-{ +- return -1; +-} +-static void omap3_free_bch(struct mtd_info *mtd) +-{ + } + #endif /* CONFIG_MTD_NAND_OMAP_BCH */ + +@@ -1824,10 +1480,13 @@ static int omap_nand_probe(struct platfo + { + struct omap_nand_info *info; + struct omap_nand_platform_data *pdata; ++ struct mtd_info *mtd; ++ struct nand_chip *chip; ++ struct nand_ecclayout *ecclayout; + int err; +- int i, offset; +- dma_cap_mask_t mask; +- unsigned sig; ++ int i; ++ dma_cap_mask_t mask; ++ unsigned sig; + struct resource *res; + struct mtd_part_parser_data ppdata = {}; + +@@ -1846,20 +1505,22 @@ static int omap_nand_probe(struct platfo + spin_lock_init(&info->controller.lock); + init_waitqueue_head(&info->controller.wq); + +- info->pdev = pdev; ++ mtd = &info->mtd; ++ mtd->name = dev_name(&pdev->dev); ++ mtd->owner = THIS_MODULE; ++ mtd->priv = &info->nand; ++ chip = mtd->priv; ++ chip->ecc.priv = NULL; + ++ info->pdev = pdev; + info->gpmc_cs = pdata->cs; + info->reg = pdata->reg; ++ info->ecc_opt = pdata->ecc_opt; + +- info->mtd.priv = &info->nand; +- info->mtd.name = dev_name(&pdev->dev); +- info->mtd.owner = THIS_MODULE; +- +- info->nand.options = pdata->devsize; ++ info->nand.options = NAND_BUSWIDTH_AUTO; + info->nand.options |= NAND_SKIP_BBTSCAN; +-#ifdef CONFIG_MTD_NAND_OMAP_BCH + info->of_node = pdata->of_node; +-#endif ++ + + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + if (res == NULL) { +@@ -1903,6 +1564,30 @@ static int omap_nand_probe(struct platfo + info->nand.chip_delay = 50; + } + ++ /* scan NAND device conncted to controller */ ++ if (nand_scan_ident(mtd, 1, NULL)) { ++ err = -ENXIO; ++ goto out_release_mem_region; ++ } ++ pr_info("%s: detected %s NAND flash\n", DRIVER_NAME, ++ (info->nand.options & NAND_BUSWIDTH_16) ? "x16" : "x8"); ++ if ((info->nand.options & NAND_BUSWIDTH_16) != ++ (pdata->devsize & NAND_BUSWIDTH_16)) { ++ pr_err("%s: but incorrectly configured as %s", DRIVER_NAME, ++ (pdata->devsize & NAND_BUSWIDTH_16) ? "x16" : "x8"); ++ err = -EINVAL; ++ goto out_release_mem_region; ++ } ++ ++ /* check for small page devices */ ++ if ((mtd->oobsize < 64) && ++ (pdata->ecc_opt != OMAP_ECC_HAMMING_CODE_HW)) { ++ pr_err("small page devices are not supported\n"); ++ err = -EINVAL; ++ goto out_release_mem_region; ++ } ++ ++ /* populate read & write API based on xfer_type selected */ + switch (pdata->xfer_type) { + case NAND_OMAP_PREFETCH_POLLED: + info->nand.read_buf = omap_read_buf_pref; +@@ -1992,64 +1677,218 @@ static int omap_nand_probe(struct platfo + goto out_release_mem_region; + } + +- /* select the ecc type */ +- if (pdata->ecc_opt == OMAP_ECC_HAMMING_CODE_DEFAULT) +- info->nand.ecc.mode = NAND_ECC_SOFT; +- else if ((pdata->ecc_opt == OMAP_ECC_HAMMING_CODE_HW) || +- (pdata->ecc_opt == OMAP_ECC_HAMMING_CODE_HW_ROMCODE)) { ++ /* populate MTD interface based on ECC scheme */ ++ chip->ecclayout = &omap_oobinfo; ++ chip->ecc.layout = &omap_oobinfo; ++ ecclayout = &omap_oobinfo; ++ switch (pdata->ecc_opt) { ++ case OMAP_ECC_HAMMING_CODE_HW: ++ pr_info("nand: using OMAP_ECC_HAMMING_CODE_HW\n"); ++ info->nand.ecc.mode = NAND_ECC_HW; + info->nand.ecc.bytes = 3; + info->nand.ecc.size = 512; + info->nand.ecc.strength = 1; + info->nand.ecc.calculate = omap_calculate_ecc; + info->nand.ecc.hwctl = omap_enable_hwecc; + info->nand.ecc.correct = omap_correct_data; +- info->nand.ecc.mode = NAND_ECC_HW; +- } else if ((pdata->ecc_opt == OMAP_ECC_BCH4_CODE_HW) || +- (pdata->ecc_opt == OMAP_ECC_BCH8_CODE_HW)) { +- err = omap3_init_bch(&info->mtd, pdata->ecc_opt); +- if (err) { ++ /* define custom ECC layout */ ++ ecclayout->eccbytes = info->nand.ecc.bytes * ++ (mtd->writesize / ++ info->nand.ecc.size); ++ if (info->nand.options & NAND_BUSWIDTH_16) ++ ecclayout->eccpos[0] = BADBLOCK_MARKER_LENGTH; ++ else ++ ecclayout->eccpos[0] = 1; ++ ecclayout->oobfree->offset = ecclayout->eccpos[0] + ++ ecclayout->eccbytes; ++ goto custom_ecc_layout; ++ break; ++ case OMAP_ECC_BCH4_CODE_HW_DETECTION_SW: ++#ifdef CONFIG_MTD_NAND_ECC_BCH ++ pr_info("nand: using OMAP_ECC_BCH4_CODE_HW_DETECTION_SW\n"); ++ info->nand.ecc.mode = NAND_ECC_HW; ++ info->nand.ecc.size = 512; ++ info->nand.ecc.bytes = 7; ++ info->nand.ecc.strength = 4; ++ info->nand.ecc.hwctl = omap_enable_hwecc; ++ info->nand.ecc.correct = nand_bch_correct_data; ++ info->nand.ecc.calculate = omap_calculate_ecc_bch; ++ /* define custom ECC layout */ ++ ecclayout->eccbytes = info->nand.ecc.bytes * ++ (mtd->writesize / ++ info->nand.ecc.size); ++ ecclayout->eccpos[0] = info->mtd.oobsize - ++ ecclayout->eccbytes; ++ ecclayout->oobfree->offset = BADBLOCK_MARKER_LENGTH; ++ /* software bch library is used for locating errors */ ++ info->nand.ecc.priv = nand_bch_init(mtd, ++ info->nand.ecc.size, ++ info->nand.ecc.bytes, ++ &info->nand.ecc.layout); ++ if (!info->nand.ecc.priv) { ++ pr_err("nand: error: unable to use s/w BCH library\n"); + err = -EINVAL; + goto out_release_mem_region; + } +- } +- +- /* DIP switches on some boards change between 8 and 16 bit +- * bus widths for flash. Try the other width if the first try fails. +- */ +- if (nand_scan_ident(&info->mtd, 1, NULL)) { +- info->nand.options ^= NAND_BUSWIDTH_16; +- if (nand_scan_ident(&info->mtd, 1, NULL)) { +- err = -ENXIO; ++ goto custom_ecc_layout; ++#else ++ pr_err("nand: error: CONFIG_MTD_NAND_ECC_BCH not enabled\n"); ++ err = -EINVAL; ++ goto out_release_mem_region; ++#endif ++ break; ++ case OMAP_ECC_BCH4_CODE_HW: ++#ifdef CONFIG_MTD_NAND_OMAP_BCH ++ pr_info("nand: using OMAP_ECC_BCH4_CODE_HW ECC scheme\n"); ++ info->nand.ecc.mode = NAND_ECC_HW; ++ info->nand.ecc.size = 512; ++ /* 14th bit is kept reserved for ROM-code compatibility */ ++ info->nand.ecc.bytes = 7 + 1; ++ info->nand.ecc.strength = 4; ++ info->nand.ecc.hwctl = omap_enable_hwecc; ++ info->nand.ecc.correct = omap_elm_correct_data; ++ info->nand.ecc.calculate = omap_calculate_ecc_bch; ++ info->nand.ecc.read_page = omap_read_page_bch; ++ info->nand.ecc.write_page = omap_write_page_bch; ++ /* This ECC scheme requires ELM H/W block */ ++ if (is_elm_present(info, pdata->elm_of_node, BCH4_ECC) < 0) { ++ pr_err("nand: error: could not initialize ELM\n"); ++ err = -ENODEV; + goto out_release_mem_region; + } +- } +- +- /* rom code layout */ +- if (pdata->ecc_opt == OMAP_ECC_HAMMING_CODE_HW_ROMCODE) { +- +- if (info->nand.options & NAND_BUSWIDTH_16) +- offset = 2; +- else { +- offset = 1; +- info->nand.badblock_pattern = &bb_descrip_flashbased; +- } +- omap_oobinfo.eccbytes = 3 * (info->mtd.oobsize/16); +- for (i = 0; i < omap_oobinfo.eccbytes; i++) +- omap_oobinfo.eccpos[i] = i+offset; +- +- omap_oobinfo.oobfree->offset = offset + omap_oobinfo.eccbytes; +- omap_oobinfo.oobfree->length = info->mtd.oobsize - +- (offset + omap_oobinfo.eccbytes); +- +- info->nand.ecc.layout = &omap_oobinfo; +- } else if ((pdata->ecc_opt == OMAP_ECC_BCH4_CODE_HW) || +- (pdata->ecc_opt == OMAP_ECC_BCH8_CODE_HW)) { +- /* build OOB layout for BCH ECC correction */ +- err = omap3_init_bch_tail(&info->mtd); +- if (err) { ++ /* define custom ECC layout */ ++ ecclayout->eccbytes = info->nand.ecc.bytes * ++ (mtd->writesize / ++ info->nand.ecc.size); ++ ecclayout->eccpos[0] = BADBLOCK_MARKER_LENGTH; ++ ecclayout->oobfree->offset = ecclayout->eccpos[0] + ++ ecclayout->eccbytes; ++ goto custom_ecc_layout; ++#else ++ pr_err("nand: error: CONFIG_MTD_NAND_OMAP_BCH not enabled\n"); ++ err = -EINVAL; ++ goto out_release_mem_region; ++#endif ++ break; ++ case OMAP_ECC_BCH8_CODE_HW_DETECTION_SW: ++#ifdef CONFIG_MTD_NAND_ECC_BCH ++ pr_info("nand: using OMAP_ECC_BCH8_CODE_HW_DETECTION_SW\n"); ++ info->nand.ecc.mode = NAND_ECC_HW; ++ info->nand.ecc.size = 512; ++ info->nand.ecc.bytes = 13; ++ info->nand.ecc.strength = 8; ++ info->nand.ecc.hwctl = omap_enable_hwecc; ++ info->nand.ecc.correct = nand_bch_correct_data; ++ info->nand.ecc.calculate = omap_calculate_ecc_bch; ++ /* define custom ECC layout */ ++ ecclayout->eccbytes = info->nand.ecc.bytes * ++ (mtd->writesize / ++ info->nand.ecc.size); ++ ecclayout->eccpos[0] = info->mtd.oobsize - ++ ecclayout->eccbytes; ++ ecclayout->oobfree->offset = BADBLOCK_MARKER_LENGTH; ++ /* software bch library is used for locating errors */ ++ info->nand.ecc.priv = nand_bch_init(mtd, ++ info->nand.ecc.size, ++ info->nand.ecc.bytes, ++ &info->nand.ecc.layout); ++ if (!info->nand.ecc.priv) { ++ pr_err("nand: error: unable to use s/w BCH library\n"); + err = -EINVAL; + goto out_release_mem_region; + } ++ goto custom_ecc_layout; ++#else ++ pr_err("nand: error: CONFIG_MTD_NAND_ECC_BCH not enabled\n"); ++ err = -EINVAL; ++ goto out_release_mem_region; ++#endif ++ break; ++ case OMAP_ECC_BCH8_CODE_HW: ++#ifdef CONFIG_MTD_NAND_OMAP_BCH ++ pr_info("nand: using OMAP_ECC_BCH8_CODE_HW ECC scheme\n"); ++ info->nand.ecc.mode = NAND_ECC_HW; ++ info->nand.ecc.size = 512; ++ /* 14th bit is kept reserved for ROM-code compatibility */ ++ info->nand.ecc.bytes = 13 + 1; ++ info->nand.ecc.strength = 8; ++ info->nand.ecc.hwctl = omap_enable_hwecc; ++ info->nand.ecc.correct = omap_elm_correct_data; ++ info->nand.ecc.calculate = omap_calculate_ecc_bch; ++ info->nand.ecc.read_page = omap_read_page_bch; ++ info->nand.ecc.write_page = omap_write_page_bch; ++ /* This ECC scheme requires ELM H/W block */ ++ if (is_elm_present(info, pdata->elm_of_node, BCH8_ECC) < 0) { ++ pr_err("nand: error: could not initialize ELM\n"); ++ err = -ENODEV; ++ goto out_release_mem_region; ++ } ++ /* define custom ECC layout */ ++ ecclayout->eccbytes = info->nand.ecc.bytes * ++ (mtd->writesize / ++ info->nand.ecc.size); ++ ecclayout->eccpos[0] = BADBLOCK_MARKER_LENGTH; ++ ecclayout->oobfree->offset = ecclayout->eccpos[0] + ++ ecclayout->eccbytes; ++ goto custom_ecc_layout; ++#else ++ pr_err("nand: error: CONFIG_MTD_NAND_OMAP_BCH not enabled\n"); ++ err = -EINVAL; ++ goto out_release_mem_region; ++#endif ++ break; ++ case OMAP_ECC_BCH16_CODE_HW: ++#ifdef CONFIG_MTD_NAND_OMAP_BCH ++ pr_info("using OMAP_ECC_BCH16_CODE_HW ECC scheme\n"); ++ chip->ecc.mode = NAND_ECC_HW; ++ chip->ecc.size = 512; ++ /* 14th bit is kept reserved for ROM-code compatibility */ ++ chip->ecc.bytes = 26; ++ chip->ecc.strength = 16; ++ chip->ecc.hwctl = omap_enable_hwecc; ++ chip->ecc.correct = omap_elm_correct_data; ++ chip->ecc.calculate = omap_calculate_ecc_bch; ++ chip->ecc.read_page = omap_read_page_bch; ++ chip->ecc.write_page = omap_write_page_bch; ++ /* ELM H/W engine is used for locating errors */ ++ if (is_elm_present(info, pdata->elm_of_node, BCH16_ECC) < 0) { ++ pr_err("ELM module not detected, required for ECC\n"); ++ err = -EINVAL; ++ goto out_release_mem_region; ++ } ++ /* define custom ECC layout */ ++ omap_oobinfo.eccbytes = chip->ecc.bytes * ++ (mtd->writesize / chip->ecc.size); ++ omap_oobinfo.eccpos[0] = BADBLOCK_MARKER_LENGTH; ++ omap_oobinfo.oobfree->offset = omap_oobinfo.eccpos[0] + ++ omap_oobinfo.eccbytes; ++ goto custom_ecc_layout; ++#else ++ pr_err("nand: error: CONFIG_MTD_NAND_OMAP_BCH not enabled\n"); ++ err = -EINVAL; ++ goto out_release_mem_region; ++#endif ++ default: ++ pr_err("nand: error: invalid or unsupported ECC scheme\n"); ++ err = -EINVAL; ++ goto out_release_mem_region; ++ } ++ ++custom_ecc_layout: ++ /* populate remaining info for custom ecc layout */ ++ pr_info("%s: using custom ecc layout\n", DRIVER_NAME); ++ ecclayout->oobfree->length = mtd->oobsize - BADBLOCK_MARKER_LENGTH ++ - ecclayout->eccbytes; ++ if (!(info->nand.options & NAND_BUSWIDTH_16)) ++ info->nand.badblock_pattern = &bb_descrip_flashbased; ++ for (i = 1; i < ecclayout->eccbytes; i++) ++ ecclayout->eccpos[i] = ecclayout->eccpos[0] + i; ++ /* check if NAND OOBSIZE meets ECC scheme requirement */ ++ if (mtd->oobsize < (ecclayout->eccbytes + BADBLOCK_MARKER_LENGTH)) { ++ pr_err("not enough OOB bytes required = %d, available=%d\n", ++ ecclayout->eccbytes, mtd->oobsize); ++ err = -EINVAL; ++ goto out_release_mem_region; + } + + /* second phase scan */ +@@ -2074,7 +1913,14 @@ out_release_mem_region: + if (info->gpmc_irq_fifo > 0) + free_irq(info->gpmc_irq_fifo, info); + release_mem_region(info->phys_base, info->mem_size); ++ + out_free_info: ++#ifdef CONFIG_MTD_NAND_ECC_BCH ++ if (info->nand.ecc.priv) { ++ nand_bch_free(info->nand.ecc.priv); ++ info->nand.ecc.priv = NULL; ++ } ++#endif + kfree(info); + + return err; +@@ -2085,8 +1931,12 @@ static int omap_nand_remove(struct platf + struct mtd_info *mtd = platform_get_drvdata(pdev); + struct omap_nand_info *info = container_of(mtd, struct omap_nand_info, + mtd); +- omap3_free_bch(&info->mtd); +- ++#ifdef CONFIG_MTD_NAND_ECC_BCH ++ if (info->nand.ecc.priv) { ++ nand_bch_free(info->nand.ecc.priv); ++ info->nand.ecc.priv = NULL; ++ } ++#endif + if (info->dma) + dma_release_channel(info->dma); + +--- a/drivers/mtd/tests/oobtest.c ++++ b/drivers/mtd/tests/oobtest.c +@@ -210,11 +210,29 @@ static int verify_eraseblock(int ebnum) + static int verify_eraseblock_in_one_go(int ebnum) + { + struct mtd_oob_ops ops; +- int err = 0; ++ int i, err = 0; + loff_t addr = ebnum * mtd->erasesize; + size_t len = mtd->ecclayout->oobavail * pgcnt; + +- prandom_bytes_state(&rnd_state, writebuf, len); ++ /* ++ * if mtd->ecclayout->oobavail is not a multiple of 4 then ++ * while generating psuedo random numbers to write to flash ++ * prandom_bytes_state () generates the extra random bytes ++ * which wont be done if we do for the whole length. So check ++ * for mtd->ecclayout->oobavail if its multiple of 4 then ++ * generate for full len (mtd->ecclayout->oobavail * pgcnt) ++ * else generate prandom of mtd->ecclayout->oobavail bytes ++ * pgcnt times. ++ */ ++ ++ if (mtd->ecclayout->oobavail % sizeof(u32)) { ++ for (i = 0; i < len; i += mtd->ecclayout->oobavail) ++ prandom_bytes_state(&rnd_state, writebuf + i, ++ mtd->ecclayout->oobavail); ++ } else { ++ prandom_bytes_state(&rnd_state, writebuf, len); ++ } ++ + ops.mode = MTD_OPS_AUTO_OOB; + ops.len = 0; + ops.retlen = 0; +@@ -266,7 +284,7 @@ static int verify_all_eraseblocks(void) + static int __init mtd_oobtest_init(void) + { + int err = 0; +- unsigned int i; ++ unsigned int i, j; + uint64_t tmp; + struct mtd_oob_ops ops; + loff_t addr = 0, addr0; +@@ -341,7 +359,6 @@ static int __init mtd_oobtest_init(void) + err = verify_all_eraseblocks(); + if (err) + goto out; +- + /* + * Second test: write all OOB, a block at a time, read it back and + * verify. +@@ -591,10 +608,26 @@ static int __init mtd_oobtest_init(void) + prandom_seed_state(&rnd_state, 11); + pr_info("verifying all eraseblocks\n"); + for (i = 0; i < ebcnt - 1; ++i) { ++ size_t sz = mtd->ecclayout->oobavail; + if (bbt[i] || bbt[i + 1]) + continue; +- prandom_bytes_state(&rnd_state, writebuf, +- mtd->ecclayout->oobavail * 2); ++ /* ++ * if mtd->ecclayout->oobavail is not a multiple of 4 then ++ * while generating psuedo random numbers to write to flash ++ * prandom_bytes_state () generates the extra random bytes ++ * which wont be done if we do for the whole length. So check ++ * for mtd->ecclayout->oobavail if its multiple of 4 then ++ * generate for full len (mtd->ecclayout->oobavail * pgcnt) ++ * else generate prandom of mtd->ecclayout->oobavail bytes ++ * pgcnt times. ++ */ ++ if (sz % sizeof(u32)) { ++ for (j = 0; j < sz * 2; j += sz) ++ prandom_bytes_state(&rnd_state, ++ writebuf + j , sz); ++ } else { ++ prandom_bytes_state(&rnd_state, writebuf, sz * 2); ++ } + addr = (i + 1) * mtd->erasesize - mtd->writesize; + ops.mode = MTD_OPS_AUTO_OOB; + ops.len = 0; +--- a/drivers/net/ethernet/ti/cpsw.c ++++ b/drivers/net/ethernet/ti/cpsw.c +@@ -367,8 +367,6 @@ struct cpsw_priv { + spinlock_t lock; + struct platform_device *pdev; + struct net_device *ndev; +- struct resource *cpsw_res; +- struct resource *cpsw_wr_res; + struct napi_struct napi; + struct device *dev; + struct cpsw_platform_data data; +@@ -1016,6 +1014,10 @@ static void cpsw_slave_open(struct cpsw_ + dev_info(priv->dev, "phy found : id is : 0x%x\n", + slave->phy->phy_id); + phy_start(slave->phy); ++ ++ /* Configure GMII_SEL register */ ++ cpsw_phy_sel(&priv->pdev->dev, slave->phy->interface, ++ slave->slave_num); + } + } + +@@ -1705,62 +1707,55 @@ static int cpsw_probe_dt(struct cpsw_pla + + if (of_property_read_u32(node, "active_slave", &prop)) { + pr_err("Missing active_slave property in the DT.\n"); +- ret = -EINVAL; +- goto error_ret; ++ return -EINVAL; + } + data->active_slave = prop; + + if (of_property_read_u32(node, "cpts_clock_mult", &prop)) { + pr_err("Missing cpts_clock_mult property in the DT.\n"); +- ret = -EINVAL; +- goto error_ret; ++ return -EINVAL; + } + data->cpts_clock_mult = prop; + + if (of_property_read_u32(node, "cpts_clock_shift", &prop)) { + pr_err("Missing cpts_clock_shift property in the DT.\n"); +- ret = -EINVAL; +- goto error_ret; ++ return -EINVAL; + } + data->cpts_clock_shift = prop; + +- data->slave_data = kcalloc(data->slaves, sizeof(struct cpsw_slave_data), +- GFP_KERNEL); ++ data->slave_data = devm_kzalloc(&pdev->dev, data->slaves ++ * sizeof(struct cpsw_slave_data), ++ GFP_KERNEL); + if (!data->slave_data) +- return -EINVAL; ++ return -ENOMEM; + + if (of_property_read_u32(node, "cpdma_channels", &prop)) { + pr_err("Missing cpdma_channels property in the DT.\n"); +- ret = -EINVAL; +- goto error_ret; ++ return -EINVAL; + } + data->channels = prop; + + if (of_property_read_u32(node, "ale_entries", &prop)) { + pr_err("Missing ale_entries property in the DT.\n"); +- ret = -EINVAL; +- goto error_ret; ++ return -EINVAL; + } + data->ale_entries = prop; + + if (of_property_read_u32(node, "bd_ram_size", &prop)) { + pr_err("Missing bd_ram_size property in the DT.\n"); +- ret = -EINVAL; +- goto error_ret; ++ return -EINVAL; + } + data->bd_ram_size = prop; + + if (of_property_read_u32(node, "rx_descs", &prop)) { + pr_err("Missing rx_descs property in the DT.\n"); +- ret = -EINVAL; +- goto error_ret; ++ return -EINVAL; + } + data->rx_descs = prop; + + if (of_property_read_u32(node, "mac_control", &prop)) { + pr_err("Missing mac_control property in the DT.\n"); +- ret = -EINVAL; +- goto error_ret; ++ return -EINVAL; + } + data->mac_control = prop; + +@@ -1791,8 +1786,7 @@ static int cpsw_probe_dt(struct cpsw_pla + parp = of_get_property(slave_node, "phy_id", &lenp); + if ((parp == NULL) || (lenp != (sizeof(void *) * 2))) { + pr_err("Missing slave[%d] phy_id property\n", i); +- ret = -EINVAL; +- goto error_ret; ++ return -EINVAL; + } + mdio_node = of_find_node_by_phandle(be32_to_cpup(parp)); + phyid = be32_to_cpup(parp+1); +@@ -1822,10 +1816,6 @@ static int cpsw_probe_dt(struct cpsw_pla + } + + return 0; +- +-error_ret: +- kfree(data->slave_data); +- return ret; + } + + static int cpsw_probe_dual_emac(struct platform_device *pdev, +@@ -1867,7 +1857,6 @@ static int cpsw_probe_dual_emac(struct p + priv_sl2->coal_intvl = 0; + priv_sl2->bus_freq_mhz = priv->bus_freq_mhz; + +- priv_sl2->cpsw_res = priv->cpsw_res; + priv_sl2->regs = priv->regs; + priv_sl2->host_port = priv->host_port; + priv_sl2->host_port_regs = priv->host_port_regs; +@@ -1911,8 +1900,8 @@ static int cpsw_probe(struct platform_de + struct cpsw_priv *priv; + struct cpdma_params dma_params; + struct cpsw_ale_params ale_params; +- void __iomem *ss_regs, *wr_regs; +- struct resource *res; ++ void __iomem *ss_regs; ++ struct resource *res, *ss_res; + u32 slave_offset, sliver_offset, slave_size; + int ret = 0, i, k = 0; + +@@ -1948,7 +1937,7 @@ static int cpsw_probe(struct platform_de + if (cpsw_probe_dt(&priv->data, pdev)) { + pr_err("cpsw: platform data missing\n"); + ret = -ENODEV; +- goto clean_ndev_ret; ++ goto clean_runtime_disable_ret; + } + data = &priv->data; + +@@ -1962,11 +1951,12 @@ static int cpsw_probe(struct platform_de + + memcpy(ndev->dev_addr, priv->mac_addr, ETH_ALEN); + +- priv->slaves = kzalloc(sizeof(struct cpsw_slave) * data->slaves, +- GFP_KERNEL); ++ priv->slaves = devm_kzalloc(&pdev->dev, ++ sizeof(struct cpsw_slave) * data->slaves, ++ GFP_KERNEL); + if (!priv->slaves) { +- ret = -EBUSY; +- goto clean_ndev_ret; ++ ret = -ENOMEM; ++ goto clean_runtime_disable_ret; + } + for (i = 0; i < data->slaves; i++) + priv->slaves[i].slave_num = i; +@@ -1974,55 +1964,31 @@ static int cpsw_probe(struct platform_de + priv->slaves[0].ndev = ndev; + priv->emac_port = 0; + +- priv->clk = clk_get(&pdev->dev, "fck"); ++ priv->clk = devm_clk_get(&pdev->dev, "fck"); + if (IS_ERR(priv->clk)) { +- dev_err(&pdev->dev, "fck is not found\n"); ++ dev_err(priv->dev, "fck is not found\n"); + ret = -ENODEV; +- goto clean_slave_ret; ++ goto clean_runtime_disable_ret; + } + priv->coal_intvl = 0; + priv->bus_freq_mhz = clk_get_rate(priv->clk) / 1000000; + +- priv->cpsw_res = platform_get_resource(pdev, IORESOURCE_MEM, 0); +- if (!priv->cpsw_res) { +- dev_err(priv->dev, "error getting i/o resource\n"); +- ret = -ENOENT; +- goto clean_clk_ret; +- } +- if (!request_mem_region(priv->cpsw_res->start, +- resource_size(priv->cpsw_res), ndev->name)) { +- dev_err(priv->dev, "failed request i/o region\n"); +- ret = -ENXIO; +- goto clean_clk_ret; +- } +- ss_regs = ioremap(priv->cpsw_res->start, resource_size(priv->cpsw_res)); +- if (!ss_regs) { +- dev_err(priv->dev, "unable to map i/o region\n"); +- goto clean_cpsw_iores_ret; ++ ss_res = platform_get_resource(pdev, IORESOURCE_MEM, 0); ++ ss_regs = devm_ioremap_resource(&pdev->dev, ss_res); ++ if (IS_ERR(ss_regs)) { ++ ret = PTR_ERR(ss_regs); ++ goto clean_runtime_disable_ret; + } + priv->regs = ss_regs; + priv->version = __raw_readl(&priv->regs->id_ver); + priv->host_port = HOST_PORT_NUM; + +- priv->cpsw_wr_res = platform_get_resource(pdev, IORESOURCE_MEM, 1); +- if (!priv->cpsw_wr_res) { +- dev_err(priv->dev, "error getting i/o resource\n"); +- ret = -ENOENT; +- goto clean_iomap_ret; +- } +- if (!request_mem_region(priv->cpsw_wr_res->start, +- resource_size(priv->cpsw_wr_res), ndev->name)) { +- dev_err(priv->dev, "failed request i/o region\n"); +- ret = -ENXIO; +- goto clean_iomap_ret; +- } +- wr_regs = ioremap(priv->cpsw_wr_res->start, +- resource_size(priv->cpsw_wr_res)); +- if (!wr_regs) { +- dev_err(priv->dev, "unable to map i/o region\n"); +- goto clean_cpsw_wr_iores_ret; ++ res = platform_get_resource(pdev, IORESOURCE_MEM, 1); ++ priv->wr_regs = devm_ioremap_resource(&pdev->dev, res); ++ if (IS_ERR(priv->wr_regs)) { ++ ret = PTR_ERR(priv->wr_regs); ++ goto clean_runtime_disable_ret; + } +- priv->wr_regs = wr_regs; + + memset(&dma_params, 0, sizeof(dma_params)); + memset(&ale_params, 0, sizeof(ale_params)); +@@ -2053,12 +2019,12 @@ static int cpsw_probe(struct platform_de + slave_size = CPSW2_SLAVE_SIZE; + sliver_offset = CPSW2_SLIVER_OFFSET; + dma_params.desc_mem_phys = +- (u32 __force) priv->cpsw_res->start + CPSW2_BD_OFFSET; ++ (u32 __force) ss_res->start + CPSW2_BD_OFFSET; + break; + default: + dev_err(priv->dev, "unknown version 0x%08x\n", priv->version); + ret = -ENODEV; +- goto clean_cpsw_wr_iores_ret; ++ goto clean_runtime_disable_ret; + } + for (i = 0; i < priv->data.slaves; i++) { + struct cpsw_slave *slave = &priv->slaves[i]; +@@ -2086,7 +2052,7 @@ static int cpsw_probe(struct platform_de + if (!priv->dma) { + dev_err(priv->dev, "error initializing dma\n"); + ret = -ENOMEM; +- goto clean_wr_iomap_ret; ++ goto clean_runtime_disable_ret; + } + + priv->txch = cpdma_chan_create(priv->dma, tx_chan_num(0), +@@ -2121,8 +2087,8 @@ static int cpsw_probe(struct platform_de + + while ((res = platform_get_resource(priv->pdev, IORESOURCE_IRQ, k))) { + for (i = res->start; i <= res->end; i++) { +- if (request_irq(i, cpsw_interrupt, 0, +- dev_name(&pdev->dev), priv)) { ++ if (devm_request_irq(&pdev->dev, i, cpsw_interrupt, 0, ++ dev_name(priv->dev), priv)) { + dev_err(priv->dev, "error attaching irq\n"); + goto clean_ale_ret; + } +@@ -2144,7 +2110,7 @@ static int cpsw_probe(struct platform_de + if (ret) { + dev_err(priv->dev, "error registering net device\n"); + ret = -ENODEV; +- goto clean_irq_ret; ++ goto clean_ale_ret; + } + + if (cpts_register(&pdev->dev, priv->cpts, +@@ -2152,44 +2118,27 @@ static int cpsw_probe(struct platform_de + dev_err(priv->dev, "error registering cpts device\n"); + + cpsw_notice(priv, probe, "initialized device (regs %x, irq %d)\n", +- priv->cpsw_res->start, ndev->irq); ++ ss_res->start, ndev->irq); + + if (priv->data.dual_emac) { + ret = cpsw_probe_dual_emac(pdev, priv); + if (ret) { + cpsw_err(priv, probe, "error probe slave 2 emac interface\n"); +- goto clean_irq_ret; ++ goto clean_ale_ret; + } + } + + return 0; + +-clean_irq_ret: +- for (i = 0; i < priv->num_irqs; i++) +- free_irq(priv->irqs_table[i], priv); + clean_ale_ret: + cpsw_ale_destroy(priv->ale); + clean_dma_ret: + cpdma_chan_destroy(priv->txch); + cpdma_chan_destroy(priv->rxch); + cpdma_ctlr_destroy(priv->dma); +-clean_wr_iomap_ret: +- iounmap(priv->wr_regs); +-clean_cpsw_wr_iores_ret: +- release_mem_region(priv->cpsw_wr_res->start, +- resource_size(priv->cpsw_wr_res)); +-clean_iomap_ret: +- iounmap(priv->regs); +-clean_cpsw_iores_ret: +- release_mem_region(priv->cpsw_res->start, +- resource_size(priv->cpsw_res)); +-clean_clk_ret: +- clk_put(priv->clk); +-clean_slave_ret: ++clean_runtime_disable_ret: + pm_runtime_disable(&pdev->dev); +- kfree(priv->slaves); + clean_ndev_ret: +- kfree(priv->data.slave_data); + free_netdev(priv->ndev); + return ret; + } +@@ -2198,30 +2147,18 @@ static int cpsw_remove(struct platform_d + { + struct net_device *ndev = platform_get_drvdata(pdev); + struct cpsw_priv *priv = netdev_priv(ndev); +- int i; + + if (priv->data.dual_emac) + unregister_netdev(cpsw_get_slave_ndev(priv, 1)); + unregister_netdev(ndev); + + cpts_unregister(priv->cpts); +- for (i = 0; i < priv->num_irqs; i++) +- free_irq(priv->irqs_table[i], priv); + + cpsw_ale_destroy(priv->ale); + cpdma_chan_destroy(priv->txch); + cpdma_chan_destroy(priv->rxch); + cpdma_ctlr_destroy(priv->dma); +- iounmap(priv->regs); +- release_mem_region(priv->cpsw_res->start, +- resource_size(priv->cpsw_res)); +- iounmap(priv->wr_regs); +- release_mem_region(priv->cpsw_wr_res->start, +- resource_size(priv->cpsw_wr_res)); + pm_runtime_disable(&pdev->dev); +- clk_put(priv->clk); +- kfree(priv->slaves); +- kfree(priv->data.slave_data); + if (priv->data.dual_emac) + free_netdev(cpsw_get_slave_ndev(priv, 1)); + free_netdev(ndev); +--- a/drivers/net/ethernet/ti/cpsw.h ++++ b/drivers/net/ethernet/ti/cpsw.h +@@ -39,4 +39,6 @@ struct cpsw_platform_data { + bool dual_emac; /* Enable Dual EMAC mode */ + }; + ++void cpsw_phy_sel(struct device *dev, phy_interface_t phy_mode, int slave); ++ + #endif /* __CPSW_H__ */ +--- /dev/null ++++ b/drivers/net/ethernet/ti/cpsw-phy-sel.c +@@ -0,0 +1,161 @@ ++/* Texas Instruments Ethernet Switch Driver ++ * ++ * Copyright (C) 2013 Texas Instruments ++ * ++ * 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/platform_device.h> ++#include <linux/module.h> ++#include <linux/netdevice.h> ++#include <linux/phy.h> ++#include <linux/of.h> ++#include <linux/of_device.h> ++ ++#include "cpsw.h" ++ ++/* AM33xx SoC specific definitions for the CONTROL port */ ++#define AM33XX_GMII_SEL_MODE_MII 0 ++#define AM33XX_GMII_SEL_MODE_RMII 1 ++#define AM33XX_GMII_SEL_MODE_RGMII 2 ++ ++#define AM33XX_GMII_SEL_RMII2_IO_CLK_EN BIT(7) ++#define AM33XX_GMII_SEL_RMII1_IO_CLK_EN BIT(6) ++ ++struct cpsw_phy_sel_priv { ++ struct device *dev; ++ u32 __iomem *gmii_sel; ++ bool rmii_clock_external; ++ void (*cpsw_phy_sel)(struct cpsw_phy_sel_priv *priv, ++ phy_interface_t phy_mode, int slave); ++}; ++ ++ ++static void cpsw_gmii_sel_am3352(struct cpsw_phy_sel_priv *priv, ++ phy_interface_t phy_mode, int slave) ++{ ++ u32 reg; ++ u32 mask; ++ u32 mode = 0; ++ ++ reg = readl(priv->gmii_sel); ++ ++ switch (phy_mode) { ++ case PHY_INTERFACE_MODE_RMII: ++ mode = AM33XX_GMII_SEL_MODE_RMII; ++ break; ++ ++ case PHY_INTERFACE_MODE_RGMII: ++ case PHY_INTERFACE_MODE_RGMII_ID: ++ case PHY_INTERFACE_MODE_RGMII_RXID: ++ case PHY_INTERFACE_MODE_RGMII_TXID: ++ mode = AM33XX_GMII_SEL_MODE_RGMII; ++ break; ++ ++ case PHY_INTERFACE_MODE_MII: ++ default: ++ mode = AM33XX_GMII_SEL_MODE_MII; ++ break; ++ }; ++ ++ mask = 0x3 << (slave * 2) | BIT(slave + 6); ++ mode <<= slave * 2; ++ ++ if (priv->rmii_clock_external) { ++ if (slave == 0) ++ mode |= AM33XX_GMII_SEL_RMII1_IO_CLK_EN; ++ else ++ mode |= AM33XX_GMII_SEL_RMII2_IO_CLK_EN; ++ } ++ ++ reg &= ~mask; ++ reg |= mode; ++ ++ writel(reg, priv->gmii_sel); ++} ++ ++static struct platform_driver cpsw_phy_sel_driver; ++static int match(struct device *dev, void *data) ++{ ++ struct device_node *node = (struct device_node *)data; ++ return dev->of_node == node && ++ dev->driver == &cpsw_phy_sel_driver.driver; ++} ++ ++void cpsw_phy_sel(struct device *dev, phy_interface_t phy_mode, int slave) ++{ ++ struct device_node *node; ++ struct cpsw_phy_sel_priv *priv; ++ ++ node = of_get_child_by_name(dev->of_node, "cpsw-phy-sel"); ++ if (!node) { ++ dev_err(dev, "Phy mode driver DT not found\n"); ++ return; ++ } ++ ++ dev = bus_find_device(&platform_bus_type, NULL, node, match); ++ priv = dev_get_drvdata(dev); ++ ++ priv->cpsw_phy_sel(priv, phy_mode, slave); ++} ++EXPORT_SYMBOL_GPL(cpsw_phy_sel); ++ ++static const struct of_device_id cpsw_phy_sel_id_table[] = { ++ { ++ .compatible = "ti,am3352-cpsw-phy-sel", ++ .data = &cpsw_gmii_sel_am3352, ++ }, ++ {} ++}; ++MODULE_DEVICE_TABLE(of, cpsw_phy_sel_id_table); ++ ++static int cpsw_phy_sel_probe(struct platform_device *pdev) ++{ ++ struct resource *res; ++ const struct of_device_id *of_id; ++ struct cpsw_phy_sel_priv *priv; ++ ++ of_id = of_match_node(cpsw_phy_sel_id_table, pdev->dev.of_node); ++ if (!of_id) ++ return -EINVAL; ++ ++ priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL); ++ if (!priv) { ++ dev_err(&pdev->dev, "unable to alloc memory for cpsw phy sel\n"); ++ return -ENOMEM; ++ } ++ ++ priv->cpsw_phy_sel = of_id->data; ++ ++ res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "gmii-sel"); ++ priv->gmii_sel = devm_ioremap_resource(&pdev->dev, res); ++ if (IS_ERR(priv->gmii_sel)) ++ return PTR_ERR(priv->gmii_sel); ++ ++ if (of_find_property(pdev->dev.of_node, "rmii-clock-ext", NULL)) ++ priv->rmii_clock_external = true; ++ ++ dev_set_drvdata(&pdev->dev, priv); ++ ++ return 0; ++} ++ ++static struct platform_driver cpsw_phy_sel_driver = { ++ .probe = cpsw_phy_sel_probe, ++ .driver = { ++ .name = "cpsw-phy-sel", ++ .owner = THIS_MODULE, ++ .of_match_table = of_match_ptr(cpsw_phy_sel_id_table), ++ }, ++}; ++ ++module_platform_driver(cpsw_phy_sel_driver); ++MODULE_AUTHOR("Mugunthan V N <mugunthanvnm@ti.com>"); ++MODULE_LICENSE("GPL v2"); +--- a/drivers/net/ethernet/ti/Kconfig ++++ b/drivers/net/ethernet/ti/Kconfig +@@ -49,11 +49,19 @@ config TI_DAVINCI_CPDMA + To compile this driver as a module, choose M here: the module + will be called davinci_cpdma. This is recommended. + ++config TI_CPSW_PHY_SEL ++ boolean "TI CPSW Switch Phy sel Support" ++ depends on TI_CPSW ++ ---help--- ++ This driver supports configuring of the phy mode connected to ++ the CPSW. ++ + config TI_CPSW + tristate "TI CPSW Switch Support" + depends on ARM && (ARCH_DAVINCI || SOC_AM33XX) + select TI_DAVINCI_CPDMA + select TI_DAVINCI_MDIO ++ select TI_CPSW_PHY_SEL + ---help--- + This driver supports TI's CPSW Ethernet Switch. + +--- a/drivers/net/ethernet/ti/Makefile ++++ b/drivers/net/ethernet/ti/Makefile +@@ -7,5 +7,6 @@ obj-$(CONFIG_CPMAC) += cpmac.o + obj-$(CONFIG_TI_DAVINCI_EMAC) += davinci_emac.o + obj-$(CONFIG_TI_DAVINCI_MDIO) += davinci_mdio.o + obj-$(CONFIG_TI_DAVINCI_CPDMA) += davinci_cpdma.o ++obj-$(CONFIG_TI_CPSW_PHY_SEL) += cpsw-phy-sel.o + obj-$(CONFIG_TI_CPSW) += ti_cpsw.o + ti_cpsw-y := cpsw_ale.o cpsw.o cpts.o +--- a/drivers/net/usb/smsc95xx.c ++++ b/drivers/net/usb/smsc95xx.c +@@ -31,6 +31,9 @@ + #include <linux/crc32.h> + #include <linux/usb/usbnet.h> + #include <linux/slab.h> ++#include <linux/of.h> ++#include <linux/of_net.h> ++ + #include "smsc95xx.h" + + #define SMSC_CHIPNAME "smsc95xx" +@@ -62,6 +65,8 @@ + #define SUSPEND_ALLMODES (SUSPEND_SUSPEND0 | SUSPEND_SUSPEND1 | \ + SUSPEND_SUSPEND2 | SUSPEND_SUSPEND3) + ++#define SMSC95XX_OF_NAME "/smsc95xx@" ++ + struct smsc95xx_priv { + u32 mac_cr; + u32 hash_hi; +@@ -767,6 +772,10 @@ static int smsc95xx_ioctl(struct net_dev + + static void smsc95xx_init_mac_address(struct usbnet *dev) + { ++ struct device_node *ap = NULL; ++ const char *mac = NULL; ++ char *of_name = SMSC95XX_OF_NAME; ++ + /* try reading mac address from EEPROM */ + if (smsc95xx_read_eeprom(dev, EEPROM_MAC_OFFSET, ETH_ALEN, + dev->net->dev_addr) == 0) { +@@ -777,6 +786,20 @@ static void smsc95xx_init_mac_address(st + } + } + ++#ifdef CONFIG_OF ++ sprintf(of_name, "%s%i", SMSC95XX_OF_NAME, dev->udev->dev.id); ++ ap = of_find_node_by_path(of_name); ++ if (ap) { ++ mac = of_get_mac_address(ap); ++ if ((mac != NULL) && (is_valid_ether_addr(mac))) { ++ /* Device tree has a mac for this so use that */ ++ memcpy(dev->net->dev_addr, mac, ETH_ALEN); ++ netif_dbg(dev, ifup, dev->net, "MAC address read from DTB\n"); ++ return; ++ } ++ } ++#endif ++ + /* no eeprom, or eeprom values are invalid. generate random MAC */ + eth_hw_addr_random(dev->net); + netif_dbg(dev, ifup, dev->net, "MAC address set to eth_random_addr\n"); +--- /dev/null ++++ b/drivers/phy/Kconfig +@@ -0,0 +1,63 @@ ++# ++# PHY ++# ++ ++menu "PHY Subsystem" ++ ++config GENERIC_PHY ++ tristate "PHY Core" ++ help ++ Generic PHY support. ++ ++ This framework is designed to provide a generic interface for PHY ++ devices present in the kernel. This layer will have the generic ++ API by which phy drivers can create PHY using the phy framework and ++ phy users can obtain reference to the PHY. All the users of this ++ framework should select this config. ++ ++config OMAP_CONTROL_PHY ++ tristate "OMAP CONTROL PHY Driver" ++ help ++ Enable this to add support for the PHY part present in the control ++ module. This driver has API to power on the USB2 PHY and to write to ++ the mailbox. The mailbox is present only in omap4 and the register to ++ power on the USB2 PHY is present in OMAP4 and OMAP5. OMAP5 has an ++ additional register to power on USB3 PHY/SATA PHY/PCIE PHY ++ (PIPE3 PHY). ++ ++config OMAP_USB2 ++ tristate "OMAP USB2 PHY Driver" ++ depends on ARCH_OMAP2PLUS ++ depends on USB_SUPPORT ++ select GENERIC_PHY ++ select USB_PHY ++ select OMAP_CONTROL_PHY ++ help ++ Enable this to support the transceiver that is part of SOC. This ++ driver takes care of all the PHY functionality apart from comparator. ++ The USB OTG controller communicates with the comparator using this ++ driver. ++ ++config OMAP_PIPE3 ++ tristate "OMAP PIPE3 PHY Driver" ++ select GENERIC_PHY ++ select OMAP_CONTROL_PHY ++ help ++ Enable this to support the PIPE3 PHY that is part of SOC. This ++ driver takes care of all the PHY functionality apart from comparator. ++ This driver interacts with the "OMAP Control PHY Driver" to power ++ on/off the PHY. ++ ++config TWL4030_USB ++ tristate "TWL4030 USB Transceiver Driver" ++ depends on TWL4030_CORE && REGULATOR_TWL4030 && USB_MUSB_OMAP2PLUS ++ depends on USB_SUPPORT ++ select GENERIC_PHY ++ select USB_PHY ++ help ++ Enable this to support the USB OTG transceiver on TWL4030 ++ family chips (including the TWL5030 and TPS659x0 devices). ++ This transceiver supports high and full speed devices plus, ++ in host mode, low speed. ++ ++endmenu +--- /dev/null ++++ b/drivers/phy/Makefile +@@ -0,0 +1,9 @@ ++# ++# Makefile for the phy drivers. ++# ++ ++obj-$(CONFIG_GENERIC_PHY) += phy-core.o ++obj-$(CONFIG_OMAP_CONTROL_PHY) += phy-omap-control.o ++obj-$(CONFIG_OMAP_USB2) += phy-omap-usb2.o ++obj-$(CONFIG_OMAP_PIPE3) += phy-omap-pipe3.o ++obj-$(CONFIG_TWL4030_USB) += phy-twl4030-usb.o +--- /dev/null ++++ b/drivers/phy/phy-core.c +@@ -0,0 +1,698 @@ ++/* ++ * phy-core.c -- Generic Phy framework. ++ * ++ * Copyright (C) 2013 Texas Instruments Incorporated - http://www.ti.com ++ * ++ * Author: Kishon Vijay Abraham I <kishon@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; either version 2 of the License, or (at your ++ * option) any later version. ++ */ ++ ++#include <linux/kernel.h> ++#include <linux/export.h> ++#include <linux/module.h> ++#include <linux/err.h> ++#include <linux/device.h> ++#include <linux/slab.h> ++#include <linux/of.h> ++#include <linux/phy/phy.h> ++#include <linux/idr.h> ++#include <linux/pm_runtime.h> ++ ++static struct class *phy_class; ++static DEFINE_MUTEX(phy_provider_mutex); ++static LIST_HEAD(phy_provider_list); ++static DEFINE_IDA(phy_ida); ++ ++static void devm_phy_release(struct device *dev, void *res) ++{ ++ struct phy *phy = *(struct phy **)res; ++ ++ phy_put(phy); ++} ++ ++static void devm_phy_provider_release(struct device *dev, void *res) ++{ ++ struct phy_provider *phy_provider = *(struct phy_provider **)res; ++ ++ of_phy_provider_unregister(phy_provider); ++} ++ ++static void devm_phy_consume(struct device *dev, void *res) ++{ ++ struct phy *phy = *(struct phy **)res; ++ ++ phy_destroy(phy); ++} ++ ++static int devm_phy_match(struct device *dev, void *res, void *match_data) ++{ ++ return res == match_data; ++} ++ ++static struct phy *phy_lookup(struct device *device, const char *port) ++{ ++ unsigned int count; ++ struct phy *phy; ++ struct device *dev; ++ struct phy_consumer *consumers; ++ struct class_dev_iter iter; ++ ++ class_dev_iter_init(&iter, phy_class, NULL, NULL); ++ while ((dev = class_dev_iter_next(&iter))) { ++ phy = to_phy(dev); ++ count = phy->init_data->num_consumers; ++ consumers = phy->init_data->consumers; ++ while (count--) { ++ if (!strcmp(consumers->dev_name, dev_name(device)) && ++ !strcmp(consumers->port, port)) { ++ class_dev_iter_exit(&iter); ++ return phy; ++ } ++ consumers++; ++ } ++ } ++ ++ class_dev_iter_exit(&iter); ++ return ERR_PTR(-ENODEV); ++} ++ ++static struct phy_provider *of_phy_provider_lookup(struct device_node *node) ++{ ++ struct phy_provider *phy_provider; ++ ++ list_for_each_entry(phy_provider, &phy_provider_list, list) { ++ if (phy_provider->dev->of_node == node) ++ return phy_provider; ++ } ++ ++ return ERR_PTR(-EPROBE_DEFER); ++} ++ ++int phy_pm_runtime_get(struct phy *phy) ++{ ++ if (!pm_runtime_enabled(&phy->dev)) ++ return -ENOTSUPP; ++ ++ return pm_runtime_get(&phy->dev); ++} ++EXPORT_SYMBOL_GPL(phy_pm_runtime_get); ++ ++int phy_pm_runtime_get_sync(struct phy *phy) ++{ ++ if (!pm_runtime_enabled(&phy->dev)) ++ return -ENOTSUPP; ++ ++ return pm_runtime_get_sync(&phy->dev); ++} ++EXPORT_SYMBOL_GPL(phy_pm_runtime_get_sync); ++ ++int phy_pm_runtime_put(struct phy *phy) ++{ ++ if (!pm_runtime_enabled(&phy->dev)) ++ return -ENOTSUPP; ++ ++ return pm_runtime_put(&phy->dev); ++} ++EXPORT_SYMBOL_GPL(phy_pm_runtime_put); ++ ++int phy_pm_runtime_put_sync(struct phy *phy) ++{ ++ if (!pm_runtime_enabled(&phy->dev)) ++ return -ENOTSUPP; ++ ++ return pm_runtime_put_sync(&phy->dev); ++} ++EXPORT_SYMBOL_GPL(phy_pm_runtime_put_sync); ++ ++void phy_pm_runtime_allow(struct phy *phy) ++{ ++ if (!pm_runtime_enabled(&phy->dev)) ++ return; ++ ++ pm_runtime_allow(&phy->dev); ++} ++EXPORT_SYMBOL_GPL(phy_pm_runtime_allow); ++ ++void phy_pm_runtime_forbid(struct phy *phy) ++{ ++ if (!pm_runtime_enabled(&phy->dev)) ++ return; ++ ++ pm_runtime_forbid(&phy->dev); ++} ++EXPORT_SYMBOL_GPL(phy_pm_runtime_forbid); ++ ++int phy_init(struct phy *phy) ++{ ++ int ret; ++ ++ ret = phy_pm_runtime_get_sync(phy); ++ if (ret < 0 && ret != -ENOTSUPP) ++ return ret; ++ ++ mutex_lock(&phy->mutex); ++ if (phy->init_count++ == 0 && phy->ops->init) { ++ ret = phy->ops->init(phy); ++ if (ret < 0) { ++ dev_err(&phy->dev, "phy init failed --> %d\n", ret); ++ goto out; ++ } ++ } ++ ++out: ++ mutex_unlock(&phy->mutex); ++ phy_pm_runtime_put(phy); ++ return ret; ++} ++EXPORT_SYMBOL_GPL(phy_init); ++ ++int phy_exit(struct phy *phy) ++{ ++ int ret; ++ ++ ret = phy_pm_runtime_get_sync(phy); ++ if (ret < 0 && ret != -ENOTSUPP) ++ return ret; ++ ++ mutex_lock(&phy->mutex); ++ if (--phy->init_count == 0 && phy->ops->exit) { ++ ret = phy->ops->exit(phy); ++ if (ret < 0) { ++ dev_err(&phy->dev, "phy exit failed --> %d\n", ret); ++ goto out; ++ } ++ } ++ ++out: ++ mutex_unlock(&phy->mutex); ++ phy_pm_runtime_put(phy); ++ return ret; ++} ++EXPORT_SYMBOL_GPL(phy_exit); ++ ++int phy_power_on(struct phy *phy) ++{ ++ int ret = -ENOTSUPP; ++ ++ ret = phy_pm_runtime_get_sync(phy); ++ if (ret < 0 && ret != -ENOTSUPP) ++ return ret; ++ ++ mutex_lock(&phy->mutex); ++ if (phy->power_count++ == 0 && phy->ops->power_on) { ++ ret = phy->ops->power_on(phy); ++ if (ret < 0) { ++ dev_err(&phy->dev, "phy poweron failed --> %d\n", ret); ++ goto out; ++ } ++ } ++ ++out: ++ mutex_unlock(&phy->mutex); ++ ++ return ret; ++} ++EXPORT_SYMBOL_GPL(phy_power_on); ++ ++int phy_power_off(struct phy *phy) ++{ ++ int ret = -ENOTSUPP; ++ ++ mutex_lock(&phy->mutex); ++ if (--phy->power_count == 0 && phy->ops->power_off) { ++ ret = phy->ops->power_off(phy); ++ if (ret < 0) { ++ dev_err(&phy->dev, "phy poweroff failed --> %d\n", ret); ++ goto out; ++ } ++ } ++ ++out: ++ mutex_unlock(&phy->mutex); ++ phy_pm_runtime_put(phy); ++ ++ return ret; ++} ++EXPORT_SYMBOL_GPL(phy_power_off); ++ ++/** ++ * of_phy_get() - lookup and obtain a reference to a phy by phandle ++ * @dev: device that requests this phy ++ * @index: the index of the phy ++ * ++ * Returns the phy associated with the given phandle value, ++ * after getting a refcount to it or -ENODEV if there is no such phy or ++ * -EPROBE_DEFER if there is a phandle to the phy, but the device is ++ * not yet loaded. This function uses of_xlate call back function provided ++ * while registering the phy_provider to find the phy instance. ++ */ ++static struct phy *of_phy_get(struct device *dev, int index) ++{ ++ int ret; ++ struct phy_provider *phy_provider; ++ struct phy *phy = NULL; ++ struct of_phandle_args args; ++ ++ ret = of_parse_phandle_with_args(dev->of_node, "phys", "#phy-cells", ++ index, &args); ++ if (ret) { ++ dev_dbg(dev, "failed to get phy in %s node\n", ++ dev->of_node->full_name); ++ return ERR_PTR(-ENODEV); ++ } ++ ++ mutex_lock(&phy_provider_mutex); ++ phy_provider = of_phy_provider_lookup(args.np); ++ if (IS_ERR(phy_provider) || !try_module_get(phy_provider->owner)) { ++ phy = ERR_PTR(-EPROBE_DEFER); ++ goto err0; ++ } ++ ++ phy = phy_provider->of_xlate(phy_provider->dev, &args); ++ module_put(phy_provider->owner); ++ ++err0: ++ mutex_unlock(&phy_provider_mutex); ++ of_node_put(args.np); ++ ++ return phy; ++} ++ ++/** ++ * phy_put() - release the PHY ++ * @phy: the phy returned by phy_get() ++ * ++ * Releases a refcount the caller received from phy_get(). ++ */ ++void phy_put(struct phy *phy) ++{ ++ if (IS_ERR(phy)) ++ return; ++ ++ module_put(phy->ops->owner); ++ put_device(&phy->dev); ++} ++EXPORT_SYMBOL_GPL(phy_put); ++ ++/** ++ * devm_phy_put() - release the PHY ++ * @dev: device that wants to release this phy ++ * @phy: the phy returned by devm_phy_get() ++ * ++ * destroys the devres associated with this phy and invokes phy_put ++ * to release the phy. ++ */ ++void devm_phy_put(struct device *dev, struct phy *phy) ++{ ++ int r; ++ ++ r = devres_destroy(dev, devm_phy_release, devm_phy_match, phy); ++ dev_WARN_ONCE(dev, r, "couldn't find PHY resource\n"); ++} ++EXPORT_SYMBOL_GPL(devm_phy_put); ++ ++/** ++ * of_phy_simple_xlate() - returns the phy instance from phy provider ++ * @dev: the PHY provider device ++ * @args: of_phandle_args (not used here) ++ * ++ * Intended to be used by phy provider for the common case where #phy-cells is ++ * 0. For other cases where #phy-cells is greater than '0', the phy provider ++ * should provide a custom of_xlate function that reads the *args* and returns ++ * the appropriate phy. ++ */ ++struct phy *of_phy_simple_xlate(struct device *dev, struct of_phandle_args ++ *args) ++{ ++ struct phy *phy; ++ struct class_dev_iter iter; ++ struct device_node *node = dev->of_node; ++ ++ class_dev_iter_init(&iter, phy_class, NULL, NULL); ++ while ((dev = class_dev_iter_next(&iter))) { ++ phy = to_phy(dev); ++ if (node != phy->dev.of_node) ++ continue; ++ ++ class_dev_iter_exit(&iter); ++ return phy; ++ } ++ ++ class_dev_iter_exit(&iter); ++ return ERR_PTR(-ENODEV); ++} ++EXPORT_SYMBOL_GPL(of_phy_simple_xlate); ++ ++/** ++ * phy_get() - lookup and obtain a reference to a phy. ++ * @dev: device that requests this phy ++ * @string: the phy name as given in the dt data or the name of the controller ++ * port for non-dt case ++ * ++ * Returns the phy driver, after getting a refcount to it; or ++ * -ENODEV if there is no such phy. The caller is responsible for ++ * calling phy_put() to release that count. ++ */ ++struct phy *phy_get(struct device *dev, const char *string) ++{ ++ int index = 0; ++ struct phy *phy = NULL; ++ ++ if (string == NULL) { ++ dev_WARN(dev, "missing string\n"); ++ return ERR_PTR(-EINVAL); ++ } ++ ++ if (dev->of_node) { ++ index = of_property_match_string(dev->of_node, "phy-names", ++ string); ++ phy = of_phy_get(dev, index); ++ if (IS_ERR(phy)) { ++ dev_err(dev, "unable to find phy\n"); ++ return phy; ++ } ++ } else { ++ phy = phy_lookup(dev, string); ++ if (IS_ERR(phy)) { ++ dev_err(dev, "unable to find phy\n"); ++ return phy; ++ } ++ } ++ ++ if (!try_module_get(phy->ops->owner)) ++ return ERR_PTR(-EPROBE_DEFER); ++ ++ get_device(&phy->dev); ++ ++ return phy; ++} ++EXPORT_SYMBOL_GPL(phy_get); ++ ++/** ++ * devm_phy_get() - lookup and obtain a reference to a phy. ++ * @dev: device that requests this phy ++ * @string: the phy name as given in the dt data or phy device name ++ * for non-dt case ++ * ++ * Gets the phy using phy_get(), and associates a device with it using ++ * devres. On driver detach, release function is invoked on the devres data, ++ * then, devres data is freed. ++ */ ++struct phy *devm_phy_get(struct device *dev, const char *string) ++{ ++ struct phy **ptr, *phy; ++ ++ ptr = devres_alloc(devm_phy_release, sizeof(*ptr), GFP_KERNEL); ++ if (!ptr) ++ return ERR_PTR(-ENOMEM); ++ ++ phy = phy_get(dev, string); ++ if (!IS_ERR(phy)) { ++ *ptr = phy; ++ devres_add(dev, ptr); ++ } else { ++ devres_free(ptr); ++ } ++ ++ return phy; ++} ++EXPORT_SYMBOL_GPL(devm_phy_get); ++ ++/** ++ * phy_create() - create a new phy ++ * @dev: device that is creating the new phy ++ * @ops: function pointers for performing phy operations ++ * @init_data: contains the list of PHY consumers or NULL ++ * ++ * Called to create a phy using phy framework. ++ */ ++struct phy *phy_create(struct device *dev, const struct phy_ops *ops, ++ struct phy_init_data *init_data) ++{ ++ int ret; ++ int id; ++ struct phy *phy; ++ ++ if (!dev) { ++ dev_WARN(dev, "no device provided for PHY\n"); ++ ret = -EINVAL; ++ goto err0; ++ } ++ ++ phy = kzalloc(sizeof(*phy), GFP_KERNEL); ++ if (!phy) { ++ ret = -ENOMEM; ++ goto err0; ++ } ++ ++ id = ida_simple_get(&phy_ida, 0, 0, GFP_KERNEL); ++ if (id < 0) { ++ dev_err(dev, "unable to get id\n"); ++ ret = id; ++ goto err0; ++ } ++ ++ device_initialize(&phy->dev); ++ mutex_init(&phy->mutex); ++ ++ phy->dev.class = phy_class; ++ phy->dev.parent = dev; ++ phy->dev.of_node = dev->of_node; ++ phy->id = id; ++ phy->ops = ops; ++ phy->init_data = init_data; ++ ++ ret = dev_set_name(&phy->dev, "phy-%s.%d", dev_name(dev), id); ++ if (ret) ++ goto err1; ++ ++ ret = device_add(&phy->dev); ++ if (ret) ++ goto err1; ++ ++ if (pm_runtime_enabled(dev)) { ++ pm_runtime_enable(&phy->dev); ++ pm_runtime_no_callbacks(&phy->dev); ++ } ++ ++ return phy; ++ ++err1: ++ ida_remove(&phy_ida, phy->id); ++ put_device(&phy->dev); ++ kfree(phy); ++ ++err0: ++ return ERR_PTR(ret); ++} ++EXPORT_SYMBOL_GPL(phy_create); ++ ++/** ++ * devm_phy_create() - create a new phy ++ * @dev: device that is creating the new phy ++ * @ops: function pointers for performing phy operations ++ * @init_data: contains the list of PHY consumers or NULL ++ * ++ * Creates a new PHY device adding it to the PHY class. ++ * While at that, it also associates the device with the phy using devres. ++ * On driver detach, release function is invoked on the devres data, ++ * then, devres data is freed. ++ */ ++struct phy *devm_phy_create(struct device *dev, const struct phy_ops *ops, ++ struct phy_init_data *init_data) ++{ ++ struct phy **ptr, *phy; ++ ++ ptr = devres_alloc(devm_phy_consume, sizeof(*ptr), GFP_KERNEL); ++ if (!ptr) ++ return ERR_PTR(-ENOMEM); ++ ++ phy = phy_create(dev, ops, init_data); ++ if (!IS_ERR(phy)) { ++ *ptr = phy; ++ devres_add(dev, ptr); ++ } else { ++ devres_free(ptr); ++ } ++ ++ return phy; ++} ++EXPORT_SYMBOL_GPL(devm_phy_create); ++ ++/** ++ * phy_destroy() - destroy the phy ++ * @phy: the phy to be destroyed ++ * ++ * Called to destroy the phy. ++ */ ++void phy_destroy(struct phy *phy) ++{ ++ pm_runtime_disable(&phy->dev); ++ device_unregister(&phy->dev); ++} ++EXPORT_SYMBOL_GPL(phy_destroy); ++ ++/** ++ * devm_phy_destroy() - destroy the PHY ++ * @dev: device that wants to release this phy ++ * @phy: the phy returned by devm_phy_get() ++ * ++ * destroys the devres associated with this phy and invokes phy_destroy ++ * to destroy the phy. ++ */ ++void devm_phy_destroy(struct device *dev, struct phy *phy) ++{ ++ int r; ++ ++ r = devres_destroy(dev, devm_phy_consume, devm_phy_match, phy); ++ dev_WARN_ONCE(dev, r, "couldn't find PHY resource\n"); ++} ++EXPORT_SYMBOL_GPL(devm_phy_destroy); ++ ++/** ++ * __of_phy_provider_register() - create/register phy provider with the framework ++ * @dev: struct device of the phy provider ++ * @owner: the module owner containing of_xlate ++ * @of_xlate: function pointer to obtain phy instance from phy provider ++ * ++ * Creates struct phy_provider from dev and of_xlate function pointer. ++ * This is used in the case of dt boot for finding the phy instance from ++ * phy provider. ++ */ ++struct phy_provider *__of_phy_provider_register(struct device *dev, ++ struct module *owner, struct phy * (*of_xlate)(struct device *dev, ++ struct of_phandle_args *args)) ++{ ++ struct phy_provider *phy_provider; ++ ++ phy_provider = kzalloc(sizeof(*phy_provider), GFP_KERNEL); ++ if (!phy_provider) ++ return ERR_PTR(-ENOMEM); ++ ++ phy_provider->dev = dev; ++ phy_provider->owner = owner; ++ phy_provider->of_xlate = of_xlate; ++ ++ mutex_lock(&phy_provider_mutex); ++ list_add_tail(&phy_provider->list, &phy_provider_list); ++ mutex_unlock(&phy_provider_mutex); ++ ++ return phy_provider; ++} ++EXPORT_SYMBOL_GPL(__of_phy_provider_register); ++ ++/** ++ * __devm_of_phy_provider_register() - create/register phy provider with the ++ * framework ++ * @dev: struct device of the phy provider ++ * @owner: the module owner containing of_xlate ++ * @of_xlate: function pointer to obtain phy instance from phy provider ++ * ++ * Creates struct phy_provider from dev and of_xlate function pointer. ++ * This is used in the case of dt boot for finding the phy instance from ++ * phy provider. While at that, it also associates the device with the ++ * phy provider using devres. On driver detach, release function is invoked ++ * on the devres data, then, devres data is freed. ++ */ ++struct phy_provider *__devm_of_phy_provider_register(struct device *dev, ++ struct module *owner, struct phy * (*of_xlate)(struct device *dev, ++ struct of_phandle_args *args)) ++{ ++ struct phy_provider **ptr, *phy_provider; ++ ++ ptr = devres_alloc(devm_phy_provider_release, sizeof(*ptr), GFP_KERNEL); ++ if (!ptr) ++ return ERR_PTR(-ENOMEM); ++ ++ phy_provider = __of_phy_provider_register(dev, owner, of_xlate); ++ if (!IS_ERR(phy_provider)) { ++ *ptr = phy_provider; ++ devres_add(dev, ptr); ++ } else { ++ devres_free(ptr); ++ } ++ ++ return phy_provider; ++} ++EXPORT_SYMBOL_GPL(__devm_of_phy_provider_register); ++ ++/** ++ * of_phy_provider_unregister() - unregister phy provider from the framework ++ * @phy_provider: phy provider returned by of_phy_provider_register() ++ * ++ * Removes the phy_provider created using of_phy_provider_register(). ++ */ ++void of_phy_provider_unregister(struct phy_provider *phy_provider) ++{ ++ if (IS_ERR(phy_provider)) ++ return; ++ ++ mutex_lock(&phy_provider_mutex); ++ list_del(&phy_provider->list); ++ kfree(phy_provider); ++ mutex_unlock(&phy_provider_mutex); ++} ++EXPORT_SYMBOL_GPL(of_phy_provider_unregister); ++ ++/** ++ * devm_of_phy_provider_unregister() - remove phy provider from the framework ++ * @dev: struct device of the phy provider ++ * ++ * destroys the devres associated with this phy provider and invokes ++ * of_phy_provider_unregister to unregister the phy provider. ++ */ ++void devm_of_phy_provider_unregister(struct device *dev, ++ struct phy_provider *phy_provider) { ++ int r; ++ ++ r = devres_destroy(dev, devm_phy_provider_release, devm_phy_match, ++ phy_provider); ++ dev_WARN_ONCE(dev, r, "couldn't find PHY provider device resource\n"); ++} ++EXPORT_SYMBOL_GPL(devm_of_phy_provider_unregister); ++ ++/** ++ * phy_release() - release the phy ++ * @dev: the dev member within phy ++ * ++ * When the last reference to the device is removed, it is called ++ * from the embedded kobject as release method. ++ */ ++static void phy_release(struct device *dev) ++{ ++ struct phy *phy; ++ ++ phy = to_phy(dev); ++ dev_vdbg(dev, "releasing '%s'\n", dev_name(dev)); ++ ida_remove(&phy_ida, phy->id); ++ kfree(phy); ++} ++ ++static int __init phy_core_init(void) ++{ ++ phy_class = class_create(THIS_MODULE, "phy"); ++ if (IS_ERR(phy_class)) { ++ pr_err("failed to create phy class --> %ld\n", ++ PTR_ERR(phy_class)); ++ return PTR_ERR(phy_class); ++ } ++ ++ phy_class->dev_release = phy_release; ++ ++ return 0; ++} ++module_init(phy_core_init); ++ ++static void __exit phy_core_exit(void) ++{ ++ class_destroy(phy_class); ++} ++module_exit(phy_core_exit); ++ ++MODULE_DESCRIPTION("Generic PHY Framework"); ++MODULE_AUTHOR("Kishon Vijay Abraham I <kishon@ti.com>"); ++MODULE_LICENSE("GPL v2"); +--- /dev/null ++++ b/drivers/phy/phy-omap-control.c +@@ -0,0 +1,319 @@ ++/* ++ * omap-control-phy.c - The PHY part of control module. ++ * ++ * Copyright (C) 2013 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; either version 2 of the License, or ++ * (at your option) any later version. ++ * ++ * Author: Kishon Vijay Abraham I <kishon@ti.com> ++ * ++ * 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/module.h> ++#include <linux/platform_device.h> ++#include <linux/slab.h> ++#include <linux/of.h> ++#include <linux/of_device.h> ++#include <linux/err.h> ++#include <linux/io.h> ++#include <linux/clk.h> ++#include <linux/phy/omap_control_phy.h> ++ ++/** ++ * omap_control_phy_power - power on/off the phy using control module reg ++ * @dev: the control module device ++ * @on: 0 or 1, based on powering on or off the PHY ++ */ ++void omap_control_phy_power(struct device *dev, int on) ++{ ++ u32 val; ++ unsigned long rate; ++ struct omap_control_phy *control_phy; ++ ++ if (IS_ERR(dev) || !dev) { ++ pr_err("%s: invalid device\n", __func__); ++ return; ++ } ++ ++ control_phy = dev_get_drvdata(dev); ++ if (!control_phy) { ++ dev_err(dev, "%s: invalid control phy device\n", __func__); ++ return; ++ } ++ ++ if (control_phy->type == OMAP_CTRL_TYPE_OTGHS) ++ return; ++ ++ val = readl(control_phy->power); ++ ++ switch (control_phy->type) { ++ case OMAP_CTRL_TYPE_USB2: ++ if (on) ++ val &= ~OMAP_CTRL_DEV_PHY_PD; ++ else ++ val |= OMAP_CTRL_DEV_PHY_PD; ++ break; ++ ++ case OMAP_CTRL_TYPE_PIPE3: ++ rate = clk_get_rate(control_phy->sys_clk); ++ rate = rate/1000000; ++ ++ if (on) { ++ val &= ~(OMAP_CTRL_PIPE3_PHY_PWRCTL_CLK_CMD_MASK | ++ OMAP_CTRL_PIPE3_PHY_PWRCTL_CLK_FREQ_MASK); ++ val |= OMAP_CTRL_PIPE3_PHY_TX_RX_POWERON << ++ OMAP_CTRL_PIPE3_PHY_PWRCTL_CLK_CMD_SHIFT; ++ val |= rate << ++ OMAP_CTRL_PIPE3_PHY_PWRCTL_CLK_FREQ_SHIFT; ++ } else { ++ val &= ~OMAP_CTRL_PIPE3_PHY_PWRCTL_CLK_CMD_MASK; ++ val |= OMAP_CTRL_PIPE3_PHY_TX_RX_POWEROFF << ++ OMAP_CTRL_PIPE3_PHY_PWRCTL_CLK_CMD_SHIFT; ++ } ++ break; ++ ++ case OMAP_CTRL_TYPE_DRA7USB2: ++ if (on) ++ val &= ~OMAP_CTRL_USB2_PHY_PD; ++ else ++ val |= OMAP_CTRL_USB2_PHY_PD; ++ break; ++ ++ case OMAP_CTRL_TYPE_AM437USB2: ++ if (on) { ++ val &= ~(AM437X_CTRL_USB2_PHY_PD | ++ AM437X_CTRL_USB2_OTG_PD); ++ val |= (AM437X_CTRL_USB2_OTGVDET_EN | ++ AM437X_CTRL_USB2_OTGSESSEND_EN); ++ } else { ++ val &= ~(AM437X_CTRL_USB2_OTGVDET_EN | ++ AM437X_CTRL_USB2_OTGSESSEND_EN); ++ val |= (AM437X_CTRL_USB2_PHY_PD | ++ AM437X_CTRL_USB2_OTG_PD); ++ } ++ break; ++ default: ++ dev_err(dev, "%s: type %d not recognized\n", ++ __func__, control_phy->type); ++ break; ++ } ++ ++ writel(val, control_phy->power); ++} ++EXPORT_SYMBOL_GPL(omap_control_phy_power); ++ ++/** ++ * omap_control_usb_host_mode - set AVALID, VBUSVALID and ID pin in grounded ++ * @ctrl_phy: struct omap_control_phy * ++ * ++ * Writes to the mailbox register to notify the usb core that a usb ++ * device has been connected. ++ */ ++static void omap_control_usb_host_mode(struct omap_control_phy *ctrl_phy) ++{ ++ u32 val; ++ ++ val = readl(ctrl_phy->otghs_control); ++ val &= ~(OMAP_CTRL_DEV_IDDIG | OMAP_CTRL_DEV_SESSEND); ++ val |= OMAP_CTRL_DEV_AVALID | OMAP_CTRL_DEV_VBUSVALID; ++ writel(val, ctrl_phy->otghs_control); ++} ++ ++/** ++ * omap_control_usb_device_mode - set AVALID, VBUSVALID and ID pin in high ++ * impedance ++ * @ctrl_phy: struct omap_control_phy * ++ * ++ * Writes to the mailbox register to notify the usb core that it has been ++ * connected to a usb host. ++ */ ++static void omap_control_usb_device_mode(struct omap_control_phy *ctrl_phy) ++{ ++ u32 val; ++ ++ val = readl(ctrl_phy->otghs_control); ++ val &= ~OMAP_CTRL_DEV_SESSEND; ++ val |= OMAP_CTRL_DEV_IDDIG | OMAP_CTRL_DEV_AVALID | ++ OMAP_CTRL_DEV_VBUSVALID; ++ writel(val, ctrl_phy->otghs_control); ++} ++ ++/** ++ * omap_control_usb_set_sessionend - Enable SESSIONEND and IDIG to high ++ * impedance ++ * @ctrl_phy: struct omap_control_phy * ++ * ++ * Writes to the mailbox register to notify the usb core it's now in ++ * disconnected state. ++ */ ++static void omap_control_usb_set_sessionend(struct omap_control_phy *ctrl_phy) ++{ ++ u32 val; ++ ++ val = readl(ctrl_phy->otghs_control); ++ val &= ~(OMAP_CTRL_DEV_AVALID | OMAP_CTRL_DEV_VBUSVALID); ++ val |= OMAP_CTRL_DEV_IDDIG | OMAP_CTRL_DEV_SESSEND; ++ writel(val, ctrl_phy->otghs_control); ++} ++ ++/** ++ * omap_control_usb_set_mode - Calls to functions to set USB in one of host mode ++ * or device mode or to denote disconnected state ++ * @dev: the control module device ++ * @mode: The mode to which usb should be configured ++ * ++ * This is an API to write to the mailbox register to notify the usb core that ++ * a usb device has been connected. ++ */ ++void omap_control_usb_set_mode(struct device *dev, ++ enum omap_control_usb_mode mode) ++{ ++ struct omap_control_phy *ctrl_phy; ++ ++ if (IS_ERR(dev) || !dev) ++ return; ++ ++ ctrl_phy = dev_get_drvdata(dev); ++ ++ if (!ctrl_phy) { ++ dev_err(dev, "Invalid control phy device\n"); ++ return; ++ } ++ ++ if (ctrl_phy->type != OMAP_CTRL_TYPE_OTGHS) ++ return; ++ ++ switch (mode) { ++ case USB_MODE_HOST: ++ omap_control_usb_host_mode(ctrl_phy); ++ break; ++ case USB_MODE_DEVICE: ++ omap_control_usb_device_mode(ctrl_phy); ++ break; ++ case USB_MODE_DISCONNECT: ++ omap_control_usb_set_sessionend(ctrl_phy); ++ break; ++ default: ++ dev_vdbg(dev, "invalid omap control usb mode\n"); ++ } ++} ++EXPORT_SYMBOL_GPL(omap_control_usb_set_mode); ++ ++#ifdef CONFIG_OF ++ ++static const enum omap_control_phy_type otghs_data = OMAP_CTRL_TYPE_OTGHS; ++static const enum omap_control_phy_type usb2_data = OMAP_CTRL_TYPE_USB2; ++static const enum omap_control_phy_type pipe3_data = OMAP_CTRL_TYPE_PIPE3; ++static const enum omap_control_phy_type dra7usb2_data = OMAP_CTRL_TYPE_DRA7USB2; ++static const enum omap_control_phy_type am437usb2_data = OMAP_CTRL_TYPE_AM437USB2; ++ ++static const struct of_device_id omap_control_phy_id_table[] = { ++ { ++ .compatible = "ti,control-phy-otghs", ++ .data = &otghs_data, ++ }, ++ { ++ .compatible = "ti,control-phy-usb2", ++ .data = &usb2_data, ++ }, ++ { ++ .compatible = "ti,control-phy-pipe3", ++ .data = &pipe3_data, ++ }, ++ { ++ .compatible = "ti,control-phy-dra7usb2", ++ .data = &dra7usb2_data, ++ }, ++ { ++ .compatible = "ti,control-phy-am437usb2", ++ .data = &am437usb2_data, ++ }, ++ {}, ++}; ++MODULE_DEVICE_TABLE(of, omap_control_phy_id_table); ++#endif ++ ++static int omap_control_phy_probe(struct platform_device *pdev) ++{ ++ struct resource *res; ++ const struct of_device_id *of_id; ++ struct omap_control_phy *control_phy; ++ ++ of_id = of_match_device(of_match_ptr(omap_control_phy_id_table), ++ &pdev->dev); ++ if (!of_id) ++ return -EINVAL; ++ ++ control_phy = devm_kzalloc(&pdev->dev, sizeof(*control_phy), ++ GFP_KERNEL); ++ if (!control_phy) { ++ dev_err(&pdev->dev, "unable to alloc memory for control phy\n"); ++ return -ENOMEM; ++ } ++ ++ control_phy->dev = &pdev->dev; ++ control_phy->type = *(enum omap_control_phy_type *)of_id->data; ++ ++ if (control_phy->type == OMAP_CTRL_TYPE_OTGHS) { ++ res = platform_get_resource_byname(pdev, IORESOURCE_MEM, ++ "otghs_control"); ++ control_phy->otghs_control = devm_ioremap_resource( ++ &pdev->dev, res); ++ if (IS_ERR(control_phy->otghs_control)) ++ return PTR_ERR(control_phy->otghs_control); ++ } else { ++ res = platform_get_resource_byname(pdev, IORESOURCE_MEM, ++ "power"); ++ control_phy->power = devm_ioremap_resource(&pdev->dev, res); ++ if (IS_ERR(control_phy->power)) { ++ dev_err(&pdev->dev, "Couldn't get power register\n"); ++ return PTR_ERR(control_phy->power); ++ } ++ } ++ ++ if (control_phy->type == OMAP_CTRL_TYPE_PIPE3) { ++ control_phy->sys_clk = devm_clk_get(control_phy->dev, ++ "sys_clkin"); ++ if (IS_ERR(control_phy->sys_clk)) { ++ pr_err("%s: unable to get sys_clkin\n", __func__); ++ return -EINVAL; ++ } ++ } ++ ++ dev_set_drvdata(control_phy->dev, control_phy); ++ ++ return 0; ++} ++ ++static struct platform_driver omap_control_phy_driver = { ++ .probe = omap_control_phy_probe, ++ .driver = { ++ .name = "omap-control-phy", ++ .owner = THIS_MODULE, ++ .of_match_table = of_match_ptr(omap_control_phy_id_table), ++ }, ++}; ++ ++static int __init omap_control_phy_init(void) ++{ ++ return platform_driver_register(&omap_control_phy_driver); ++} ++subsys_initcall(omap_control_phy_init); ++ ++static void __exit omap_control_phy_exit(void) ++{ ++ platform_driver_unregister(&omap_control_phy_driver); ++} ++module_exit(omap_control_phy_exit); ++ ++MODULE_ALIAS("platform: omap_control_phy"); ++MODULE_AUTHOR("Texas Instruments Inc."); ++MODULE_DESCRIPTION("OMAP Control Module PHY Driver"); ++MODULE_LICENSE("GPL v2"); +--- /dev/null ++++ b/drivers/phy/phy-omap-pipe3.c +@@ -0,0 +1,430 @@ ++/* ++ * omap-pipe3 - PHY driver for SATA, USB and PCIE in OMAP platforms ++ * ++ * Copyright (C) 2013 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; either version 2 of the License, or ++ * (at your option) any later version. ++ * ++ * Author: Kishon Vijay Abraham I <kishon@ti.com> ++ * ++ * 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/module.h> ++#include <linux/platform_device.h> ++#include <linux/slab.h> ++#include <linux/phy/omap_pipe3.h> ++#include <linux/phy/phy.h> ++#include <linux/of.h> ++#include <linux/clk.h> ++#include <linux/err.h> ++#include <linux/pm_runtime.h> ++#include <linux/delay.h> ++#include <linux/phy/omap_control_phy.h> ++#include <linux/of_platform.h> ++ ++#define PLL_STATUS 0x00000004 ++#define PLL_GO 0x00000008 ++#define PLL_CONFIGURATION1 0x0000000C ++#define PLL_CONFIGURATION2 0x00000010 ++#define PLL_CONFIGURATION3 0x00000014 ++#define PLL_CONFIGURATION4 0x00000020 ++ ++#define PLL_REGM_MASK 0x001FFE00 ++#define PLL_REGM_SHIFT 9 ++#define PLL_REGM_F_MASK 0x0003FFFF ++#define PLL_REGM_F_SHIFT 0 ++#define PLL_REGN_MASK 0x000001FE ++#define PLL_REGN_SHIFT 1 ++#define PLL_SELFREQDCO_MASK 0x0000000E ++#define PLL_SELFREQDCO_SHIFT 1 ++#define PLL_SD_MASK 0x0003FC00 ++#define PLL_SD_SHIFT 10 ++#define SET_PLL_GO 0x1 ++#define PLL_TICOPWDN 0x10000 ++#define PLL_LOCK 0x2 ++#define PLL_IDLE 0x1 ++ ++/* ++ * This is an Empirical value that works, need to confirm the actual ++ * value required for the PIPE3PHY_PLL_CONFIGURATION2.PLL_IDLE status ++ * to be correctly reflected in the PIPE3PHY_PLL_STATUS register. ++ */ ++# define PLL_IDLE_TIME 100; ++ ++static struct pipe3_dpll_map dpll_map_usb[] = { ++ {12000000, {1250, 5, 4, 20, 0} }, /* 12 MHz */ ++ {16800000, {3125, 20, 4, 20, 0} }, /* 16.8 MHz */ ++ {19200000, {1172, 8, 4, 20, 65537} }, /* 19.2 MHz */ ++ {20000000, {1000, 7, 4, 10, 0} }, /* 20 MHz */ ++ {26000000, {1250, 12, 4, 20, 0} }, /* 26 MHz */ ++ {38400000, {3125, 47, 4, 20, 92843} }, /* 38.4 MHz */ ++ { }, /* Terminator */ ++}; ++ ++static struct pipe3_dpll_map dpll_map_sata[] = { ++ {12000000, {1000, 7, 4, 6, 0} }, /* 12 MHz */ ++ {16800000, {714, 7, 4, 6, 0} }, /* 16.8 MHz */ ++ {19200000, {625, 7, 4, 6, 0} }, /* 19.2 MHz */ ++ {20000000, {600, 7, 4, 6, 0} }, /* 20 MHz */ ++ {26000000, {461, 7, 4, 6, 0} }, /* 26 MHz */ ++ {38400000, {312, 7, 4, 6, 0} }, /* 38.4 MHz */ ++ { }, /* Terminator */ ++}; ++ ++static struct pipe3_dpll_params *omap_pipe3_get_dpll_params(struct omap_pipe3 ++ *pipe3) ++{ ++ unsigned long rate; ++ struct pipe3_dpll_map *dpll_map = pipe3->dpll_map; ++ ++ rate = clk_get_rate(pipe3->sys_clk); ++ ++ for (; dpll_map->rate; dpll_map++) { ++ if (rate == dpll_map->rate) ++ return &dpll_map->params; ++ } ++ ++ dev_err(pipe3->dev, ++ "No DPLL configuration for %lu Hz SYS CLK\n", rate); ++ return 0; ++} ++ ++static int omap_pipe3_power_off(struct phy *x) ++{ ++ struct omap_pipe3 *phy = phy_get_drvdata(x); ++ int val; ++ int timeout = PLL_IDLE_TIME; ++ ++ val = omap_pipe3_readl(phy->pll_ctrl_base, PLL_CONFIGURATION2); ++ val |= PLL_IDLE; ++ omap_pipe3_writel(phy->pll_ctrl_base, PLL_CONFIGURATION2, val); ++ ++ do { ++ val = omap_pipe3_readl(phy->pll_ctrl_base, PLL_STATUS); ++ if (val & PLL_TICOPWDN) ++ break; ++ udelay(1); ++ } while (--timeout); ++ ++ omap_control_phy_power(phy->control_dev, 0); ++ ++ return 0; ++} ++ ++static int omap_pipe3_power_on(struct phy *x) ++{ ++ struct omap_pipe3 *phy = phy_get_drvdata(x); ++ int val; ++ int timeout = PLL_IDLE_TIME; ++ ++ val = omap_pipe3_readl(phy->pll_ctrl_base, PLL_CONFIGURATION2); ++ val &= ~PLL_IDLE; ++ omap_pipe3_writel(phy->pll_ctrl_base, PLL_CONFIGURATION2, val); ++ ++ do { ++ val = omap_pipe3_readl(phy->pll_ctrl_base, PLL_STATUS); ++ if (!(val & PLL_TICOPWDN)) ++ break; ++ udelay(1); ++ } while (--timeout); ++ ++ msleep(100); ++ ++ return 0; ++} ++ ++static void omap_pipe3_dpll_relock(struct omap_pipe3 *phy) ++{ ++ u32 val; ++ unsigned long timeout; ++ ++ omap_pipe3_writel(phy->pll_ctrl_base, PLL_GO, SET_PLL_GO); ++ ++ timeout = jiffies + msecs_to_jiffies(20); ++ do { ++ val = omap_pipe3_readl(phy->pll_ctrl_base, PLL_STATUS); ++ if (val & PLL_LOCK) ++ break; ++ } while (!WARN_ON(time_after(jiffies, timeout))); ++} ++ ++static int omap_pipe3_dpll_lock(struct omap_pipe3 *phy) ++{ ++ u32 val; ++ unsigned long rate; ++ struct pipe3_dpll_params *dpll_params; ++ ++ rate = clk_get_rate(phy->sys_clk); ++ dpll_params = omap_pipe3_get_dpll_params(phy); ++ if (!dpll_params) { ++ return -EINVAL; ++ } ++ ++ val = omap_pipe3_readl(phy->pll_ctrl_base, PLL_CONFIGURATION1); ++ val &= ~PLL_REGN_MASK; ++ val |= dpll_params->n << PLL_REGN_SHIFT; ++ omap_pipe3_writel(phy->pll_ctrl_base, PLL_CONFIGURATION1, val); ++ ++ val = omap_pipe3_readl(phy->pll_ctrl_base, PLL_CONFIGURATION2); ++ val &= ~PLL_SELFREQDCO_MASK; ++ val |= dpll_params->freq << PLL_SELFREQDCO_SHIFT; ++ omap_pipe3_writel(phy->pll_ctrl_base, PLL_CONFIGURATION2, val); ++ ++ val = omap_pipe3_readl(phy->pll_ctrl_base, PLL_CONFIGURATION1); ++ val &= ~PLL_REGM_MASK; ++ val |= dpll_params->m << PLL_REGM_SHIFT; ++ omap_pipe3_writel(phy->pll_ctrl_base, PLL_CONFIGURATION1, val); ++ ++ val = omap_pipe3_readl(phy->pll_ctrl_base, PLL_CONFIGURATION4); ++ val &= ~PLL_REGM_F_MASK; ++ val |= dpll_params->mf << PLL_REGM_F_SHIFT; ++ omap_pipe3_writel(phy->pll_ctrl_base, PLL_CONFIGURATION4, val); ++ ++ val = omap_pipe3_readl(phy->pll_ctrl_base, PLL_CONFIGURATION3); ++ val &= ~PLL_SD_MASK; ++ val |= dpll_params->sd << PLL_SD_SHIFT; ++ omap_pipe3_writel(phy->pll_ctrl_base, PLL_CONFIGURATION3, val); ++ ++ omap_pipe3_dpll_relock(phy); ++ ++ return 0; ++} ++ ++static int omap_pipe3_init(struct phy *x) ++{ ++ struct omap_pipe3 *phy = phy_get_drvdata(x); ++ int ret; ++ ++ ret = omap_pipe3_dpll_lock(phy); ++ if (ret) ++ return ret; ++ ++ omap_control_phy_power(phy->control_dev, 1); ++ ++ return 0; ++} ++ ++static struct phy_ops ops = { ++ .init = omap_pipe3_init, ++ .power_on = omap_pipe3_power_on, ++ .power_off = omap_pipe3_power_off, ++ .owner = THIS_MODULE, ++}; ++ ++#ifdef CONFIG_OF ++static const struct of_device_id omap_pipe3_id_table[] = { ++ { ++ .compatible = "ti,phy-pipe3-usb3", ++ .data = dpll_map_usb, ++ }, ++ { ++ .compatible = "ti,phy-pipe3-sata", ++ .data = dpll_map_sata, ++ }, ++ {}, ++}; ++MODULE_DEVICE_TABLE(of, omap_pipe3_id_table); ++#endif ++ ++static int omap_pipe3_probe(struct platform_device *pdev) ++{ ++ struct omap_pipe3 *phy; ++ struct phy *generic_phy; ++ struct phy_provider *phy_provider; ++ struct resource *res; ++ struct device_node *node = pdev->dev.of_node; ++ struct device_node *control_node; ++ struct platform_device *control_pdev; ++ const struct of_device_id *match; ++ ++ match = of_match_device(of_match_ptr(omap_pipe3_id_table), &pdev->dev); ++ if (!match) ++ return -EINVAL; ++ ++ phy = devm_kzalloc(&pdev->dev, sizeof(*phy), GFP_KERNEL); ++ if (!phy) { ++ dev_err(&pdev->dev, "unable to alloc mem for OMAP PIPE3 PHY\n"); ++ return -ENOMEM; ++ } ++ ++ phy->dpll_map = (struct pipe3_dpll_map *)match->data; ++ if (!phy->dpll_map) { ++ dev_err(&pdev->dev, "no dpll data\n"); ++ return -EINVAL; ++ } ++ ++ res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "pll_ctrl"); ++ phy->pll_ctrl_base = devm_ioremap_resource(&pdev->dev, res); ++ if (IS_ERR(phy->pll_ctrl_base)) ++ return PTR_ERR(phy->pll_ctrl_base); ++ ++ phy->dev = &pdev->dev; ++ ++ phy->wkupclk = devm_clk_get(phy->dev, "wkupclk"); ++ if (IS_ERR(phy->wkupclk)) ++ dev_dbg(&pdev->dev, "unable to get wkupclk\n"); ++ else ++ clk_prepare(phy->wkupclk); ++ ++ phy->optclk = devm_clk_get(phy->dev, "refclk"); ++ if (IS_ERR(phy->optclk)) ++ dev_dbg(&pdev->dev, "unable to get refclk\n"); ++ else ++ clk_prepare(phy->optclk); ++ ++ phy->optclk2 = devm_clk_get(phy->dev, "refclk2"); ++ if (IS_ERR(phy->optclk2)) ++ dev_dbg(&pdev->dev, "unable to get refclk2\n"); ++ else ++ clk_prepare(phy->optclk2); ++ ++ phy->sys_clk = devm_clk_get(phy->dev, "sys_clkin"); ++ if (IS_ERR(phy->sys_clk)) { ++ pr_err("%s: unable to get sys_clkin\n", __func__); ++ return -EINVAL; ++ } ++ ++ control_node = of_parse_phandle(node, "ctrl-module", 0); ++ if (!control_node) { ++ dev_err(&pdev->dev, "Failed to get control device phandle\n"); ++ return -EINVAL; ++ } ++ ++ phy_provider = devm_of_phy_provider_register(phy->dev, ++ of_phy_simple_xlate); ++ if (IS_ERR(phy_provider)) ++ return PTR_ERR(phy_provider); ++ ++ control_pdev = of_find_device_by_node(control_node); ++ if (!control_pdev) { ++ dev_err(&pdev->dev, "Failed to get control device\n"); ++ return -EINVAL; ++ } ++ ++ phy->control_dev = &control_pdev->dev; ++ ++ omap_control_phy_power(phy->control_dev, 0); ++ ++ platform_set_drvdata(pdev, phy); ++ pm_runtime_enable(phy->dev); ++ ++ generic_phy = devm_phy_create(phy->dev, &ops, NULL); ++ if (IS_ERR(generic_phy)) ++ return PTR_ERR(generic_phy); ++ ++ phy_set_drvdata(generic_phy, phy); ++ ++ pm_runtime_get(&pdev->dev); ++ ++ return 0; ++} ++ ++static int omap_pipe3_remove(struct platform_device *pdev) ++{ ++ struct omap_pipe3 *phy = platform_get_drvdata(pdev); ++ ++ if (!IS_ERR(phy->wkupclk)) ++ clk_unprepare(phy->wkupclk); ++ if (!IS_ERR(phy->optclk)) ++ clk_unprepare(phy->optclk); ++ if (!IS_ERR(phy->optclk2)) ++ clk_unprepare(phy->optclk2); ++ if (!pm_runtime_suspended(&pdev->dev)) ++ pm_runtime_put(&pdev->dev); ++ pm_runtime_disable(&pdev->dev); ++ ++ return 0; ++} ++ ++#ifdef CONFIG_PM_RUNTIME ++ ++static int omap_pipe3_runtime_suspend(struct device *dev) ++{ ++ struct omap_pipe3 *phy = dev_get_drvdata(dev); ++ ++ if (!IS_ERR(phy->wkupclk)) ++ clk_disable(phy->wkupclk); ++ if (!IS_ERR(phy->optclk)) ++ clk_disable(phy->optclk); ++ if (!IS_ERR(phy->optclk2)) ++ clk_disable(phy->optclk2); ++ ++ return 0; ++} ++ ++static int omap_pipe3_runtime_resume(struct device *dev) ++{ ++ u32 ret = 0; ++ struct omap_pipe3 *phy = dev_get_drvdata(dev); ++ ++ if (!IS_ERR(phy->optclk)) { ++ ret = clk_enable(phy->optclk); ++ if (ret) { ++ dev_err(phy->dev, "Failed to enable optclk %d\n", ret); ++ goto err1; ++ } ++ } ++ ++ if (!IS_ERR(phy->wkupclk)) { ++ ret = clk_enable(phy->wkupclk); ++ if (ret) { ++ dev_err(phy->dev, "Failed to enable wkupclk %d\n", ret); ++ goto err2; ++ } ++ } ++ ++ if (!IS_ERR(phy->optclk2)) { ++ ret = clk_enable(phy->optclk2); ++ if (ret) { ++ dev_err(phy->dev, "Failed to enable optclk2 %d\n", ret); ++ goto err3; ++ } ++ } ++ ++ return 0; ++ ++err3: ++ if (!IS_ERR(phy->wkupclk)) ++ clk_disable(phy->wkupclk); ++err2: ++ if (!IS_ERR(phy->optclk)) ++ clk_disable(phy->optclk); ++ ++err1: ++ return ret; ++} ++ ++static const struct dev_pm_ops omap_pipe3_pm_ops = { ++ SET_RUNTIME_PM_OPS(omap_pipe3_runtime_suspend, ++ omap_pipe3_runtime_resume, NULL) ++}; ++ ++#define DEV_PM_OPS (&omap_pipe3_pm_ops) ++#else ++#define DEV_PM_OPS NULL ++#endif ++ ++static struct platform_driver omap_pipe3_driver = { ++ .probe = omap_pipe3_probe, ++ .remove = omap_pipe3_remove, ++ .driver = { ++ .name = "omap-pipe3", ++ .owner = THIS_MODULE, ++ .pm = DEV_PM_OPS, ++ .of_match_table = of_match_ptr(omap_pipe3_id_table), ++ }, ++}; ++ ++module_platform_driver(omap_pipe3_driver); ++ ++MODULE_ALIAS("platform: omap_pipe3"); ++MODULE_AUTHOR("Texas Instruments Inc."); ++MODULE_DESCRIPTION("OMAP PIPE3 phy driver"); ++MODULE_LICENSE("GPL v2"); +--- /dev/null ++++ b/drivers/phy/phy-omap-usb2.c +@@ -0,0 +1,326 @@ ++/* ++ * omap-usb2.c - USB PHY, talking to musb controller in OMAP. ++ * ++ * Copyright (C) 2012 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; either version 2 of the License, or ++ * (at your option) any later version. ++ * ++ * Author: Kishon Vijay Abraham I <kishon@ti.com> ++ * ++ * 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/module.h> ++#include <linux/platform_device.h> ++#include <linux/slab.h> ++#include <linux/of.h> ++#include <linux/io.h> ++#include <linux/phy/omap_usb.h> ++#include <linux/usb/phy_companion.h> ++#include <linux/clk.h> ++#include <linux/err.h> ++#include <linux/pm_runtime.h> ++#include <linux/delay.h> ++#include <linux/phy/omap_control_phy.h> ++#include <linux/phy/phy.h> ++#include <linux/of_platform.h> ++#include <linux/phy/phy.h> ++#include <linux/of_platform.h> ++ ++/** ++ * omap_usb2_set_comparator - links the comparator present in the sytem with ++ * this phy ++ * @comparator - the companion phy(comparator) for this phy ++ * ++ * The phy companion driver should call this API passing the phy_companion ++ * filled with set_vbus and start_srp to be used by usb phy. ++ * ++ * For use by phy companion driver ++ */ ++int omap_usb2_set_comparator(struct phy_companion *comparator) ++{ ++ struct omap_usb *phy; ++ struct usb_phy *x = usb_get_phy(USB_PHY_TYPE_USB2); ++ ++ if (IS_ERR(x)) ++ return -ENODEV; ++ ++ phy = phy_to_omapusb(x); ++ phy->comparator = comparator; ++ return 0; ++} ++EXPORT_SYMBOL_GPL(omap_usb2_set_comparator); ++ ++static int omap_usb_set_vbus(struct usb_otg *otg, bool enabled) ++{ ++ struct omap_usb *phy = phy_to_omapusb(otg->phy); ++ ++ if (!phy->comparator) ++ return -ENODEV; ++ ++ return phy->comparator->set_vbus(phy->comparator, enabled); ++} ++ ++static int omap_usb_start_srp(struct usb_otg *otg) ++{ ++ struct omap_usb *phy = phy_to_omapusb(otg->phy); ++ ++ if (!phy->comparator) ++ return -ENODEV; ++ ++ return phy->comparator->start_srp(phy->comparator); ++} ++ ++static int omap_usb_set_host(struct usb_otg *otg, struct usb_bus *host) ++{ ++ struct usb_phy *phy = otg->phy; ++ ++ otg->host = host; ++ if (!host) ++ phy->state = OTG_STATE_UNDEFINED; ++ ++ return 0; ++} ++ ++static int omap_usb_set_peripheral(struct usb_otg *otg, ++ struct usb_gadget *gadget) ++{ ++ struct usb_phy *phy = otg->phy; ++ ++ otg->gadget = gadget; ++ if (!gadget) ++ phy->state = OTG_STATE_UNDEFINED; ++ ++ return 0; ++} ++ ++static int omap_usb_power_off(struct phy *x) ++{ ++ struct omap_usb *phy = phy_get_drvdata(x); ++ ++ omap_control_phy_power(phy->control_dev, 0); ++ ++ return 0; ++} ++ ++static int omap_usb_power_on(struct phy *x) ++{ ++ struct omap_usb *phy = phy_get_drvdata(x); ++ ++ omap_control_phy_power(phy->control_dev, 1); ++ ++ return 0; ++} ++ ++static struct phy_ops ops = { ++ .power_on = omap_usb_power_on, ++ .power_off = omap_usb_power_off, ++ .owner = THIS_MODULE, ++}; ++ ++#ifdef CONFIG_OF ++static const struct usb_phy_data omap_usb2_data = { ++ .label = "omap_usb2", ++ .flags = OMAP_USB2_HAS_START_SRP | OMAP_USB2_HAS_SET_VBUS, ++}; ++ ++static const struct usb_phy_data am437x_usb2_data = { ++ .label = "am437x_usb2", ++ .flags = 0, ++}; ++ ++static const struct of_device_id omap_usb2_id_table[] = { ++ { ++ .compatible = "ti,omap-usb2", ++ .data = &omap_usb2_data, ++ }, ++ { ++ .compatible = "ti,am437x-usb2", ++ .data = &am437x_usb2_data, ++ }, ++ {}, ++}; ++MODULE_DEVICE_TABLE(of, omap_usb2_id_table); ++#endif ++ ++static int omap_usb2_probe(struct platform_device *pdev) ++{ ++ struct omap_usb *phy; ++ struct usb_otg *otg; ++ struct device_node *node = pdev->dev.of_node; ++ struct device_node *control_node; ++ struct platform_device *control_pdev; ++ struct phy *generic_phy; ++ struct phy_provider *phy_provider; ++ const struct of_device_id *of_id; ++ struct usb_phy_data *phy_data; ++ ++ of_id = of_match_device(of_match_ptr(omap_usb2_id_table), &pdev->dev); ++ ++ if (!of_id) ++ return -EINVAL; ++ phy_data = (struct usb_phy_data *)of_id->data; ++ ++ phy = devm_kzalloc(&pdev->dev, sizeof(*phy), GFP_KERNEL); ++ if (!phy) { ++ dev_err(&pdev->dev, "unable to allocate memory for USB2 PHY\n"); ++ return -ENOMEM; ++ } ++ ++ otg = devm_kzalloc(&pdev->dev, sizeof(*otg), GFP_KERNEL); ++ if (!otg) { ++ dev_err(&pdev->dev, "unable to allocate memory for USB OTG\n"); ++ return -ENOMEM; ++ } ++ ++ phy->dev = &pdev->dev; ++ ++ phy->phy.dev = phy->dev; ++ phy->phy.label = phy_data->label; ++ phy->phy.otg = otg; ++ phy->phy.type = USB_PHY_TYPE_USB2; ++ ++ phy_provider = devm_of_phy_provider_register(phy->dev, ++ of_phy_simple_xlate); ++ if (IS_ERR(phy_provider)) ++ return PTR_ERR(phy_provider); ++ ++ control_node = of_parse_phandle(node, "ctrl-module", 0); ++ if (!control_node) { ++ dev_err(&pdev->dev, "Failed to get control device phandle\n"); ++ return -EINVAL; ++ } ++ ++ control_pdev = of_find_device_by_node(control_node); ++ if (!control_pdev) { ++ dev_err(&pdev->dev, "Failed to get control device\n"); ++ return -EINVAL; ++ } ++ ++ phy->control_dev = &control_pdev->dev; ++ ++ omap_control_phy_power(phy->control_dev, 0); ++ ++ otg->set_host = omap_usb_set_host; ++ otg->set_peripheral = omap_usb_set_peripheral; ++ if (phy_data->flags & OMAP_USB2_HAS_SET_VBUS) ++ otg->set_vbus = omap_usb_set_vbus; ++ if (phy_data->flags & OMAP_USB2_HAS_START_SRP) ++ otg->start_srp = omap_usb_start_srp; ++ otg->phy = &phy->phy; ++ ++ platform_set_drvdata(pdev, phy); ++ pm_runtime_enable(phy->dev); ++ ++ generic_phy = devm_phy_create(phy->dev, &ops, NULL); ++ if (IS_ERR(generic_phy)) ++ return PTR_ERR(generic_phy); ++ ++ phy_set_drvdata(generic_phy, phy); ++ ++ phy->wkupclk = devm_clk_get(phy->dev, "wkupclk"); ++ if (IS_ERR(phy->wkupclk)) { ++ dev_err(&pdev->dev, "unable to get wkupclk\n"); ++ return PTR_ERR(phy->wkupclk); ++ } ++ clk_prepare(phy->wkupclk); ++ ++ phy->optclk = devm_clk_get(phy->dev, "refclk"); ++ if (IS_ERR(phy->optclk)) ++ dev_dbg(&pdev->dev, "unable to get refclk\n"); ++ else ++ clk_prepare(phy->optclk); ++ ++ usb_add_phy_dev(&phy->phy); ++ ++ return 0; ++} ++ ++static int omap_usb2_remove(struct platform_device *pdev) ++{ ++ struct omap_usb *phy = platform_get_drvdata(pdev); ++ ++ clk_unprepare(phy->wkupclk); ++ if (!IS_ERR(phy->optclk)) ++ clk_unprepare(phy->optclk); ++ usb_remove_phy(&phy->phy); ++ ++ return 0; ++} ++ ++#ifdef CONFIG_PM_RUNTIME ++ ++static int omap_usb2_runtime_suspend(struct device *dev) ++{ ++ struct platform_device *pdev = to_platform_device(dev); ++ struct omap_usb *phy = platform_get_drvdata(pdev); ++ ++ clk_disable(phy->wkupclk); ++ if (!IS_ERR(phy->optclk)) ++ clk_disable(phy->optclk); ++ ++ return 0; ++} ++ ++static int omap_usb2_runtime_resume(struct device *dev) ++{ ++ struct platform_device *pdev = to_platform_device(dev); ++ struct omap_usb *phy = platform_get_drvdata(pdev); ++ int ret; ++ ++ ret = clk_enable(phy->wkupclk); ++ if (ret < 0) { ++ dev_err(phy->dev, "Failed to enable wkupclk %d\n", ret); ++ goto err0; ++ } ++ ++ if (!IS_ERR(phy->optclk)) { ++ ret = clk_enable(phy->optclk); ++ if (ret < 0) { ++ dev_err(phy->dev, "Failed to enable optclk %d\n", ret); ++ goto err1; ++ } ++ } ++ ++ return 0; ++ ++err1: ++ clk_disable(phy->wkupclk); ++ ++err0: ++ return ret; ++} ++ ++static const struct dev_pm_ops omap_usb2_pm_ops = { ++ SET_RUNTIME_PM_OPS(omap_usb2_runtime_suspend, omap_usb2_runtime_resume, ++ NULL) ++}; ++ ++#define DEV_PM_OPS (&omap_usb2_pm_ops) ++#else ++#define DEV_PM_OPS NULL ++#endif ++ ++static struct platform_driver omap_usb2_driver = { ++ .probe = omap_usb2_probe, ++ .remove = omap_usb2_remove, ++ .driver = { ++ .name = "omap-usb2", ++ .owner = THIS_MODULE, ++ .pm = DEV_PM_OPS, ++ .of_match_table = of_match_ptr(omap_usb2_id_table), ++ }, ++}; ++ ++module_platform_driver(omap_usb2_driver); ++ ++MODULE_ALIAS("platform: omap_usb2"); ++MODULE_AUTHOR("Texas Instruments Inc."); ++MODULE_DESCRIPTION("OMAP USB2 phy driver"); ++MODULE_LICENSE("GPL v2"); +--- /dev/null ++++ b/drivers/phy/phy-twl4030-usb.c +@@ -0,0 +1,815 @@ ++/* ++ * twl4030_usb - TWL4030 USB transceiver, talking to OMAP OTG controller ++ * ++ * Copyright (C) 2004-2007 Texas Instruments ++ * Copyright (C) 2008 Nokia Corporation ++ * Contact: Felipe Balbi <felipe.balbi@nokia.com> ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation; either version 2 of the License, or ++ * (at your option) any later version. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this program; if not, write to the Free Software ++ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. ++ * ++ * Current status: ++ * - HS USB ULPI mode works. ++ * - 3-pin mode support may be added in future. ++ */ ++ ++#include <linux/module.h> ++#include <linux/init.h> ++#include <linux/interrupt.h> ++#include <linux/platform_device.h> ++#include <linux/spinlock.h> ++#include <linux/workqueue.h> ++#include <linux/io.h> ++#include <linux/delay.h> ++#include <linux/usb/otg.h> ++#include <linux/phy/phy.h> ++#include <linux/usb/musb-omap.h> ++#include <linux/usb/ulpi.h> ++#include <linux/i2c/twl.h> ++#include <linux/regulator/consumer.h> ++#include <linux/err.h> ++#include <linux/slab.h> ++ ++/* Register defines */ ++ ++#define MCPC_CTRL 0x30 ++#define MCPC_CTRL_RTSOL (1 << 7) ++#define MCPC_CTRL_EXTSWR (1 << 6) ++#define MCPC_CTRL_EXTSWC (1 << 5) ++#define MCPC_CTRL_VOICESW (1 << 4) ++#define MCPC_CTRL_OUT64K (1 << 3) ++#define MCPC_CTRL_RTSCTSSW (1 << 2) ++#define MCPC_CTRL_HS_UART (1 << 0) ++ ++#define MCPC_IO_CTRL 0x33 ++#define MCPC_IO_CTRL_MICBIASEN (1 << 5) ++#define MCPC_IO_CTRL_CTS_NPU (1 << 4) ++#define MCPC_IO_CTRL_RXD_PU (1 << 3) ++#define MCPC_IO_CTRL_TXDTYP (1 << 2) ++#define MCPC_IO_CTRL_CTSTYP (1 << 1) ++#define MCPC_IO_CTRL_RTSTYP (1 << 0) ++ ++#define MCPC_CTRL2 0x36 ++#define MCPC_CTRL2_MCPC_CK_EN (1 << 0) ++ ++#define OTHER_FUNC_CTRL 0x80 ++#define OTHER_FUNC_CTRL_BDIS_ACON_EN (1 << 4) ++#define OTHER_FUNC_CTRL_FIVEWIRE_MODE (1 << 2) ++ ++#define OTHER_IFC_CTRL 0x83 ++#define OTHER_IFC_CTRL_OE_INT_EN (1 << 6) ++#define OTHER_IFC_CTRL_CEA2011_MODE (1 << 5) ++#define OTHER_IFC_CTRL_FSLSSERIALMODE_4PIN (1 << 4) ++#define OTHER_IFC_CTRL_HIZ_ULPI_60MHZ_OUT (1 << 3) ++#define OTHER_IFC_CTRL_HIZ_ULPI (1 << 2) ++#define OTHER_IFC_CTRL_ALT_INT_REROUTE (1 << 0) ++ ++#define OTHER_INT_EN_RISE 0x86 ++#define OTHER_INT_EN_FALL 0x89 ++#define OTHER_INT_STS 0x8C ++#define OTHER_INT_LATCH 0x8D ++#define OTHER_INT_VB_SESS_VLD (1 << 7) ++#define OTHER_INT_DM_HI (1 << 6) /* not valid for "latch" reg */ ++#define OTHER_INT_DP_HI (1 << 5) /* not valid for "latch" reg */ ++#define OTHER_INT_BDIS_ACON (1 << 3) /* not valid for "fall" regs */ ++#define OTHER_INT_MANU (1 << 1) ++#define OTHER_INT_ABNORMAL_STRESS (1 << 0) ++ ++#define ID_STATUS 0x96 ++#define ID_RES_FLOAT (1 << 4) ++#define ID_RES_440K (1 << 3) ++#define ID_RES_200K (1 << 2) ++#define ID_RES_102K (1 << 1) ++#define ID_RES_GND (1 << 0) ++ ++#define POWER_CTRL 0xAC ++#define POWER_CTRL_OTG_ENAB (1 << 5) ++ ++#define OTHER_IFC_CTRL2 0xAF ++#define OTHER_IFC_CTRL2_ULPI_STP_LOW (1 << 4) ++#define OTHER_IFC_CTRL2_ULPI_TXEN_POL (1 << 3) ++#define OTHER_IFC_CTRL2_ULPI_4PIN_2430 (1 << 2) ++#define OTHER_IFC_CTRL2_USB_INT_OUTSEL_MASK (3 << 0) /* bits 0 and 1 */ ++#define OTHER_IFC_CTRL2_USB_INT_OUTSEL_INT1N (0 << 0) ++#define OTHER_IFC_CTRL2_USB_INT_OUTSEL_INT2N (1 << 0) ++ ++#define REG_CTRL_EN 0xB2 ++#define REG_CTRL_ERROR 0xB5 ++#define ULPI_I2C_CONFLICT_INTEN (1 << 0) ++ ++#define OTHER_FUNC_CTRL2 0xB8 ++#define OTHER_FUNC_CTRL2_VBAT_TIMER_EN (1 << 0) ++ ++/* following registers do not have separate _clr and _set registers */ ++#define VBUS_DEBOUNCE 0xC0 ++#define ID_DEBOUNCE 0xC1 ++#define VBAT_TIMER 0xD3 ++#define PHY_PWR_CTRL 0xFD ++#define PHY_PWR_PHYPWD (1 << 0) ++#define PHY_CLK_CTRL 0xFE ++#define PHY_CLK_CTRL_CLOCKGATING_EN (1 << 2) ++#define PHY_CLK_CTRL_CLK32K_EN (1 << 1) ++#define REQ_PHY_DPLL_CLK (1 << 0) ++#define PHY_CLK_CTRL_STS 0xFF ++#define PHY_DPLL_CLK (1 << 0) ++ ++/* In module TWL_MODULE_PM_MASTER */ ++#define STS_HW_CONDITIONS 0x0F ++ ++/* In module TWL_MODULE_PM_RECEIVER */ ++#define VUSB_DEDICATED1 0x7D ++#define VUSB_DEDICATED2 0x7E ++#define VUSB1V5_DEV_GRP 0x71 ++#define VUSB1V5_TYPE 0x72 ++#define VUSB1V5_REMAP 0x73 ++#define VUSB1V8_DEV_GRP 0x74 ++#define VUSB1V8_TYPE 0x75 ++#define VUSB1V8_REMAP 0x76 ++#define VUSB3V1_DEV_GRP 0x77 ++#define VUSB3V1_TYPE 0x78 ++#define VUSB3V1_REMAP 0x79 ++ ++/* In module TWL4030_MODULE_INTBR */ ++#define PMBR1 0x0D ++#define GPIO_USB_4PIN_ULPI_2430C (3 << 0) ++ ++struct twl4030_usb { ++ struct usb_phy phy; ++ struct device *dev; ++ ++ /* TWL4030 internal USB regulator supplies */ ++ struct regulator *usb1v5; ++ struct regulator *usb1v8; ++ struct regulator *usb3v1; ++ ++ /* for vbus reporting with irqs disabled */ ++ spinlock_t lock; ++ ++ /* pin configuration */ ++ enum twl4030_usb_mode usb_mode; ++ ++ int irq; ++ enum omap_musb_vbus_id_status linkstat; ++ bool vbus_supplied; ++ u8 asleep; ++ bool irq_enabled; ++ ++ struct delayed_work id_workaround_work; ++}; ++ ++/* internal define on top of container_of */ ++#define phy_to_twl(x) container_of((x), struct twl4030_usb, phy) ++ ++/*-------------------------------------------------------------------------*/ ++ ++static int twl4030_i2c_write_u8_verify(struct twl4030_usb *twl, ++ u8 module, u8 data, u8 address) ++{ ++ u8 check; ++ ++ if ((twl_i2c_write_u8(module, data, address) >= 0) && ++ (twl_i2c_read_u8(module, &check, address) >= 0) && ++ (check == data)) ++ return 0; ++ dev_dbg(twl->dev, "Write%d[%d,0x%x] wrote %02x but read %02x\n", ++ 1, module, address, check, data); ++ ++ /* Failed once: Try again */ ++ if ((twl_i2c_write_u8(module, data, address) >= 0) && ++ (twl_i2c_read_u8(module, &check, address) >= 0) && ++ (check == data)) ++ return 0; ++ dev_dbg(twl->dev, "Write%d[%d,0x%x] wrote %02x but read %02x\n", ++ 2, module, address, check, data); ++ ++ /* Failed again: Return error */ ++ return -EBUSY; ++} ++ ++#define twl4030_usb_write_verify(twl, address, data) \ ++ twl4030_i2c_write_u8_verify(twl, TWL_MODULE_USB, (data), (address)) ++ ++static inline int twl4030_usb_write(struct twl4030_usb *twl, ++ u8 address, u8 data) ++{ ++ int ret = 0; ++ ++ ret = twl_i2c_write_u8(TWL_MODULE_USB, data, address); ++ if (ret < 0) ++ dev_dbg(twl->dev, ++ "TWL4030:USB:Write[0x%x] Error %d\n", address, ret); ++ return ret; ++} ++ ++static inline int twl4030_readb(struct twl4030_usb *twl, u8 module, u8 address) ++{ ++ u8 data; ++ int ret = 0; ++ ++ ret = twl_i2c_read_u8(module, &data, address); ++ if (ret >= 0) ++ ret = data; ++ else ++ dev_dbg(twl->dev, ++ "TWL4030:readb[0x%x,0x%x] Error %d\n", ++ module, address, ret); ++ ++ return ret; ++} ++ ++static inline int twl4030_usb_read(struct twl4030_usb *twl, u8 address) ++{ ++ return twl4030_readb(twl, TWL_MODULE_USB, address); ++} ++ ++/*-------------------------------------------------------------------------*/ ++ ++static inline int ++twl4030_usb_set_bits(struct twl4030_usb *twl, u8 reg, u8 bits) ++{ ++ return twl4030_usb_write(twl, ULPI_SET(reg), bits); ++} ++ ++static inline int ++twl4030_usb_clear_bits(struct twl4030_usb *twl, u8 reg, u8 bits) ++{ ++ return twl4030_usb_write(twl, ULPI_CLR(reg), bits); ++} ++ ++/*-------------------------------------------------------------------------*/ ++ ++static bool twl4030_is_driving_vbus(struct twl4030_usb *twl) ++{ ++ int ret; ++ ++ ret = twl4030_usb_read(twl, PHY_CLK_CTRL_STS); ++ if (ret < 0 || !(ret & PHY_DPLL_CLK)) ++ /* ++ * if clocks are off, registers are not updated, ++ * but we can assume we don't drive VBUS in this case ++ */ ++ return false; ++ ++ ret = twl4030_usb_read(twl, ULPI_OTG_CTRL); ++ if (ret < 0) ++ return false; ++ ++ return (ret & (ULPI_OTG_DRVVBUS | ULPI_OTG_CHRGVBUS)) ? true : false; ++} ++ ++static enum omap_musb_vbus_id_status ++ twl4030_usb_linkstat(struct twl4030_usb *twl) ++{ ++ int status; ++ enum omap_musb_vbus_id_status linkstat = OMAP_MUSB_UNKNOWN; ++ ++ twl->vbus_supplied = false; ++ ++ /* ++ * For ID/VBUS sensing, see manual section 15.4.8 ... ++ * except when using only battery backup power, two ++ * comparators produce VBUS_PRES and ID_PRES signals, ++ * which don't match docs elsewhere. But ... BIT(7) ++ * and BIT(2) of STS_HW_CONDITIONS, respectively, do ++ * seem to match up. If either is true the USB_PRES ++ * signal is active, the OTG module is activated, and ++ * its interrupt may be raised (may wake the system). ++ */ ++ status = twl4030_readb(twl, TWL_MODULE_PM_MASTER, STS_HW_CONDITIONS); ++ if (status < 0) ++ dev_err(twl->dev, "USB link status err %d\n", status); ++ else if (status & (BIT(7) | BIT(2))) { ++ if (status & BIT(7)) { ++ if (twl4030_is_driving_vbus(twl)) ++ status &= ~BIT(7); ++ else ++ twl->vbus_supplied = true; ++ } ++ ++ if (status & BIT(2)) ++ linkstat = OMAP_MUSB_ID_GROUND; ++ else if (status & BIT(7)) ++ linkstat = OMAP_MUSB_VBUS_VALID; ++ else ++ linkstat = OMAP_MUSB_VBUS_OFF; ++ } else { ++ if (twl->linkstat != OMAP_MUSB_UNKNOWN) ++ linkstat = OMAP_MUSB_VBUS_OFF; ++ } ++ ++ dev_dbg(twl->dev, "HW_CONDITIONS 0x%02x/%d; link %d\n", ++ status, status, linkstat); ++ ++ /* REVISIT this assumes host and peripheral controllers ++ * are registered, and that both are active... ++ */ ++ ++ return linkstat; ++} ++ ++static void twl4030_usb_set_mode(struct twl4030_usb *twl, int mode) ++{ ++ twl->usb_mode = mode; ++ ++ switch (mode) { ++ case T2_USB_MODE_ULPI: ++ twl4030_usb_clear_bits(twl, ULPI_IFC_CTRL, ++ ULPI_IFC_CTRL_CARKITMODE); ++ twl4030_usb_set_bits(twl, POWER_CTRL, POWER_CTRL_OTG_ENAB); ++ twl4030_usb_clear_bits(twl, ULPI_FUNC_CTRL, ++ ULPI_FUNC_CTRL_XCVRSEL_MASK | ++ ULPI_FUNC_CTRL_OPMODE_MASK); ++ break; ++ case -1: ++ /* FIXME: power on defaults */ ++ break; ++ default: ++ dev_err(twl->dev, "unsupported T2 transceiver mode %d\n", ++ mode); ++ break; ++ }; ++} ++ ++static void twl4030_i2c_access(struct twl4030_usb *twl, int on) ++{ ++ unsigned long timeout; ++ int val = twl4030_usb_read(twl, PHY_CLK_CTRL); ++ ++ if (val >= 0) { ++ if (on) { ++ /* enable DPLL to access PHY registers over I2C */ ++ val |= REQ_PHY_DPLL_CLK; ++ WARN_ON(twl4030_usb_write_verify(twl, PHY_CLK_CTRL, ++ (u8)val) < 0); ++ ++ timeout = jiffies + HZ; ++ while (!(twl4030_usb_read(twl, PHY_CLK_CTRL_STS) & ++ PHY_DPLL_CLK) ++ && time_before(jiffies, timeout)) ++ udelay(10); ++ if (!(twl4030_usb_read(twl, PHY_CLK_CTRL_STS) & ++ PHY_DPLL_CLK)) ++ dev_err(twl->dev, "Timeout setting T2 HSUSB " ++ "PHY DPLL clock\n"); ++ } else { ++ /* let ULPI control the DPLL clock */ ++ val &= ~REQ_PHY_DPLL_CLK; ++ WARN_ON(twl4030_usb_write_verify(twl, PHY_CLK_CTRL, ++ (u8)val) < 0); ++ } ++ } ++} ++ ++static void __twl4030_phy_power(struct twl4030_usb *twl, int on) ++{ ++ u8 pwr = twl4030_usb_read(twl, PHY_PWR_CTRL); ++ ++ if (on) ++ pwr &= ~PHY_PWR_PHYPWD; ++ else ++ pwr |= PHY_PWR_PHYPWD; ++ ++ WARN_ON(twl4030_usb_write_verify(twl, PHY_PWR_CTRL, pwr) < 0); ++} ++ ++static void twl4030_phy_power(struct twl4030_usb *twl, int on) ++{ ++ int ret; ++ ++ if (on) { ++ ret = regulator_enable(twl->usb3v1); ++ if (ret) ++ dev_err(twl->dev, "Failed to enable usb3v1\n"); ++ ++ ret = regulator_enable(twl->usb1v8); ++ if (ret) ++ dev_err(twl->dev, "Failed to enable usb1v8\n"); ++ ++ /* ++ * Disabling usb3v1 regulator (= writing 0 to VUSB3V1_DEV_GRP ++ * in twl4030) resets the VUSB_DEDICATED2 register. This reset ++ * enables VUSB3V1_SLEEP bit that remaps usb3v1 ACTIVE state to ++ * SLEEP. We work around this by clearing the bit after usv3v1 ++ * is re-activated. This ensures that VUSB3V1 is really active. ++ */ ++ twl_i2c_write_u8(TWL_MODULE_PM_RECEIVER, 0, VUSB_DEDICATED2); ++ ++ ret = regulator_enable(twl->usb1v5); ++ if (ret) ++ dev_err(twl->dev, "Failed to enable usb1v5\n"); ++ ++ __twl4030_phy_power(twl, 1); ++ twl4030_usb_write(twl, PHY_CLK_CTRL, ++ twl4030_usb_read(twl, PHY_CLK_CTRL) | ++ (PHY_CLK_CTRL_CLOCKGATING_EN | ++ PHY_CLK_CTRL_CLK32K_EN)); ++ } else { ++ __twl4030_phy_power(twl, 0); ++ regulator_disable(twl->usb1v5); ++ regulator_disable(twl->usb1v8); ++ regulator_disable(twl->usb3v1); ++ } ++} ++ ++static int twl4030_phy_power_off(struct phy *phy) ++{ ++ struct twl4030_usb *twl = phy_get_drvdata(phy); ++ ++ if (twl->asleep) ++ return 0; ++ ++ twl4030_phy_power(twl, 0); ++ twl->asleep = 1; ++ dev_dbg(twl->dev, "%s\n", __func__); ++ return 0; ++} ++ ++static void __twl4030_phy_power_on(struct twl4030_usb *twl) ++{ ++ twl4030_phy_power(twl, 1); ++ twl4030_i2c_access(twl, 1); ++ twl4030_usb_set_mode(twl, twl->usb_mode); ++ if (twl->usb_mode == T2_USB_MODE_ULPI) ++ twl4030_i2c_access(twl, 0); ++} ++ ++static int twl4030_phy_power_on(struct phy *phy) ++{ ++ struct twl4030_usb *twl = phy_get_drvdata(phy); ++ ++ if (!twl->asleep) ++ return 0; ++ __twl4030_phy_power_on(twl); ++ twl->asleep = 0; ++ dev_dbg(twl->dev, "%s\n", __func__); ++ ++ /* ++ * XXX When VBUS gets driven after musb goes to A mode, ++ * ID_PRES related interrupts no longer arrive, why? ++ * Register itself is updated fine though, so we must poll. ++ */ ++ if (twl->linkstat == OMAP_MUSB_ID_GROUND) { ++ cancel_delayed_work(&twl->id_workaround_work); ++ schedule_delayed_work(&twl->id_workaround_work, HZ); ++ } ++ return 0; ++} ++ ++static int twl4030_usb_ldo_init(struct twl4030_usb *twl) ++{ ++ /* Enable writing to power configuration registers */ ++ twl_i2c_write_u8(TWL_MODULE_PM_MASTER, TWL4030_PM_MASTER_KEY_CFG1, ++ TWL4030_PM_MASTER_PROTECT_KEY); ++ ++ twl_i2c_write_u8(TWL_MODULE_PM_MASTER, TWL4030_PM_MASTER_KEY_CFG2, ++ TWL4030_PM_MASTER_PROTECT_KEY); ++ ++ /* Keep VUSB3V1 LDO in sleep state until VBUS/ID change detected*/ ++ /*twl_i2c_write_u8(TWL_MODULE_PM_RECEIVER, 0, VUSB_DEDICATED2);*/ ++ ++ /* input to VUSB3V1 LDO is from VBAT, not VBUS */ ++ twl_i2c_write_u8(TWL_MODULE_PM_RECEIVER, 0x14, VUSB_DEDICATED1); ++ ++ /* Initialize 3.1V regulator */ ++ twl_i2c_write_u8(TWL_MODULE_PM_RECEIVER, 0, VUSB3V1_DEV_GRP); ++ ++ twl->usb3v1 = devm_regulator_get(twl->dev, "usb3v1"); ++ if (IS_ERR(twl->usb3v1)) ++ return -ENODEV; ++ ++ twl_i2c_write_u8(TWL_MODULE_PM_RECEIVER, 0, VUSB3V1_TYPE); ++ ++ /* Initialize 1.5V regulator */ ++ twl_i2c_write_u8(TWL_MODULE_PM_RECEIVER, 0, VUSB1V5_DEV_GRP); ++ ++ twl->usb1v5 = devm_regulator_get(twl->dev, "usb1v5"); ++ if (IS_ERR(twl->usb1v5)) ++ return -ENODEV; ++ ++ twl_i2c_write_u8(TWL_MODULE_PM_RECEIVER, 0, VUSB1V5_TYPE); ++ ++ /* Initialize 1.8V regulator */ ++ twl_i2c_write_u8(TWL_MODULE_PM_RECEIVER, 0, VUSB1V8_DEV_GRP); ++ ++ twl->usb1v8 = devm_regulator_get(twl->dev, "usb1v8"); ++ if (IS_ERR(twl->usb1v8)) ++ return -ENODEV; ++ ++ twl_i2c_write_u8(TWL_MODULE_PM_RECEIVER, 0, VUSB1V8_TYPE); ++ ++ /* disable access to power configuration registers */ ++ twl_i2c_write_u8(TWL_MODULE_PM_MASTER, 0, ++ TWL4030_PM_MASTER_PROTECT_KEY); ++ ++ return 0; ++} ++ ++static ssize_t twl4030_usb_vbus_show(struct device *dev, ++ struct device_attribute *attr, char *buf) ++{ ++ struct twl4030_usb *twl = dev_get_drvdata(dev); ++ unsigned long flags; ++ int ret = -EINVAL; ++ ++ spin_lock_irqsave(&twl->lock, flags); ++ ret = sprintf(buf, "%s\n", ++ twl->vbus_supplied ? "on" : "off"); ++ spin_unlock_irqrestore(&twl->lock, flags); ++ ++ return ret; ++} ++static DEVICE_ATTR(vbus, 0444, twl4030_usb_vbus_show, NULL); ++ ++static irqreturn_t twl4030_usb_irq(int irq, void *_twl) ++{ ++ struct twl4030_usb *twl = _twl; ++ enum omap_musb_vbus_id_status status; ++ bool status_changed = false; ++ ++ status = twl4030_usb_linkstat(twl); ++ ++ spin_lock_irq(&twl->lock); ++ if (status >= 0 && status != twl->linkstat) { ++ twl->linkstat = status; ++ status_changed = true; ++ } ++ spin_unlock_irq(&twl->lock); ++ ++ if (status_changed) { ++ /* FIXME add a set_power() method so that B-devices can ++ * configure the charger appropriately. It's not always ++ * correct to consume VBUS power, and how much current to ++ * consume is a function of the USB configuration chosen ++ * by the host. ++ * ++ * REVISIT usb_gadget_vbus_connect(...) as needed, ditto ++ * its disconnect() sibling, when changing to/from the ++ * USB_LINK_VBUS state. musb_hdrc won't care until it ++ * starts to handle softconnect right. ++ */ ++ omap_musb_mailbox(status); ++ } ++ sysfs_notify(&twl->dev->kobj, NULL, "vbus"); ++ ++ return IRQ_HANDLED; ++} ++ ++static void twl4030_id_workaround_work(struct work_struct *work) ++{ ++ struct twl4030_usb *twl = container_of(work, struct twl4030_usb, ++ id_workaround_work.work); ++ enum omap_musb_vbus_id_status status; ++ bool status_changed = false; ++ ++ status = twl4030_usb_linkstat(twl); ++ ++ spin_lock_irq(&twl->lock); ++ if (status >= 0 && status != twl->linkstat) { ++ twl->linkstat = status; ++ status_changed = true; ++ } ++ spin_unlock_irq(&twl->lock); ++ ++ if (status_changed) { ++ dev_dbg(twl->dev, "handle missing status change to %d\n", ++ status); ++ omap_musb_mailbox(status); ++ } ++ ++ /* don't schedule during sleep - irq works right then */ ++ if (status == OMAP_MUSB_ID_GROUND && !twl->asleep) { ++ cancel_delayed_work(&twl->id_workaround_work); ++ schedule_delayed_work(&twl->id_workaround_work, HZ); ++ } ++} ++ ++static int twl4030_phy_init(struct phy *phy) ++{ ++ struct twl4030_usb *twl = phy_get_drvdata(phy); ++ enum omap_musb_vbus_id_status status; ++ ++ /* ++ * Start in sleep state, we'll get called through set_suspend() ++ * callback when musb is runtime resumed and it's time to start. ++ */ ++ __twl4030_phy_power(twl, 0); ++ twl->asleep = 1; ++ ++ status = twl4030_usb_linkstat(twl); ++ twl->linkstat = status; ++ ++ if (status == OMAP_MUSB_ID_GROUND || status == OMAP_MUSB_VBUS_VALID) { ++ omap_musb_mailbox(twl->linkstat); ++ twl4030_phy_power_on(phy); ++ } ++ ++ sysfs_notify(&twl->dev->kobj, NULL, "vbus"); ++ return 0; ++} ++ ++static int twl4030_set_peripheral(struct usb_otg *otg, ++ struct usb_gadget *gadget) ++{ ++ if (!otg) ++ return -ENODEV; ++ ++ otg->gadget = gadget; ++ if (!gadget) ++ otg->phy->state = OTG_STATE_UNDEFINED; ++ ++ return 0; ++} ++ ++static int twl4030_set_host(struct usb_otg *otg, struct usb_bus *host) ++{ ++ if (!otg) ++ return -ENODEV; ++ ++ otg->host = host; ++ if (!host) ++ otg->phy->state = OTG_STATE_UNDEFINED; ++ ++ return 0; ++} ++ ++static const struct phy_ops ops = { ++ .init = twl4030_phy_init, ++ .power_on = twl4030_phy_power_on, ++ .power_off = twl4030_phy_power_off, ++ .owner = THIS_MODULE, ++}; ++ ++static int twl4030_usb_probe(struct platform_device *pdev) ++{ ++ struct twl4030_usb_data *pdata = dev_get_platdata(&pdev->dev); ++ struct twl4030_usb *twl; ++ struct phy *phy; ++ int status, err; ++ struct usb_otg *otg; ++ struct device_node *np = pdev->dev.of_node; ++ struct phy_provider *phy_provider; ++ struct phy_init_data *init_data = NULL; ++ ++ twl = devm_kzalloc(&pdev->dev, sizeof *twl, GFP_KERNEL); ++ if (!twl) ++ return -ENOMEM; ++ ++ if (np) ++ of_property_read_u32(np, "usb_mode", ++ (enum twl4030_usb_mode *)&twl->usb_mode); ++ else if (pdata) { ++ twl->usb_mode = pdata->usb_mode; ++ init_data = pdata->init_data; ++ } else { ++ dev_err(&pdev->dev, "twl4030 initialized without pdata\n"); ++ return -EINVAL; ++ } ++ ++ otg = devm_kzalloc(&pdev->dev, sizeof *otg, GFP_KERNEL); ++ if (!otg) ++ return -ENOMEM; ++ ++ twl->dev = &pdev->dev; ++ twl->irq = platform_get_irq(pdev, 0); ++ twl->vbus_supplied = false; ++ twl->asleep = 1; ++ twl->linkstat = OMAP_MUSB_UNKNOWN; ++ ++ twl->phy.dev = twl->dev; ++ twl->phy.label = "twl4030"; ++ twl->phy.otg = otg; ++ twl->phy.type = USB_PHY_TYPE_USB2; ++ ++ otg->phy = &twl->phy; ++ otg->set_host = twl4030_set_host; ++ otg->set_peripheral = twl4030_set_peripheral; ++ ++ phy_provider = devm_of_phy_provider_register(twl->dev, ++ of_phy_simple_xlate); ++ if (IS_ERR(phy_provider)) ++ return PTR_ERR(phy_provider); ++ ++ phy = devm_phy_create(twl->dev, &ops, init_data); ++ if (IS_ERR(phy)) { ++ dev_dbg(&pdev->dev, "Failed to create PHY\n"); ++ return PTR_ERR(phy); ++ } ++ ++ phy_set_drvdata(phy, twl); ++ ++ /* init spinlock for workqueue */ ++ spin_lock_init(&twl->lock); ++ ++ INIT_DELAYED_WORK(&twl->id_workaround_work, twl4030_id_workaround_work); ++ ++ err = twl4030_usb_ldo_init(twl); ++ if (err) { ++ dev_err(&pdev->dev, "ldo init failed\n"); ++ return err; ++ } ++ usb_add_phy_dev(&twl->phy); ++ ++ platform_set_drvdata(pdev, twl); ++ if (device_create_file(&pdev->dev, &dev_attr_vbus)) ++ dev_warn(&pdev->dev, "could not create sysfs file\n"); ++ ++ ATOMIC_INIT_NOTIFIER_HEAD(&twl->phy.notifier); ++ ++ /* Our job is to use irqs and status from the power module ++ * to keep the transceiver disabled when nothing's connected. ++ * ++ * FIXME we actually shouldn't start enabling it until the ++ * USB controller drivers have said they're ready, by calling ++ * set_host() and/or set_peripheral() ... OTG_capable boards ++ * need both handles, otherwise just one suffices. ++ */ ++ twl->irq_enabled = true; ++ status = devm_request_threaded_irq(twl->dev, twl->irq, NULL, ++ twl4030_usb_irq, IRQF_TRIGGER_FALLING | ++ IRQF_TRIGGER_RISING | IRQF_ONESHOT, "twl4030_usb", twl); ++ if (status < 0) { ++ dev_dbg(&pdev->dev, "can't get IRQ %d, err %d\n", ++ twl->irq, status); ++ return status; ++ } ++ ++ dev_info(&pdev->dev, "Initialized TWL4030 USB module\n"); ++ return 0; ++} ++ ++static int twl4030_usb_remove(struct platform_device *pdev) ++{ ++ struct twl4030_usb *twl = platform_get_drvdata(pdev); ++ int val; ++ ++ cancel_delayed_work(&twl->id_workaround_work); ++ device_remove_file(twl->dev, &dev_attr_vbus); ++ ++ /* set transceiver mode to power on defaults */ ++ twl4030_usb_set_mode(twl, -1); ++ ++ /* autogate 60MHz ULPI clock, ++ * clear dpll clock request for i2c access, ++ * disable 32KHz ++ */ ++ val = twl4030_usb_read(twl, PHY_CLK_CTRL); ++ if (val >= 0) { ++ val |= PHY_CLK_CTRL_CLOCKGATING_EN; ++ val &= ~(PHY_CLK_CTRL_CLK32K_EN | REQ_PHY_DPLL_CLK); ++ twl4030_usb_write(twl, PHY_CLK_CTRL, (u8)val); ++ } ++ ++ /* disable complete OTG block */ ++ twl4030_usb_clear_bits(twl, POWER_CTRL, POWER_CTRL_OTG_ENAB); ++ ++ if (!twl->asleep) ++ twl4030_phy_power(twl, 0); ++ ++ return 0; ++} ++ ++#ifdef CONFIG_OF ++static const struct of_device_id twl4030_usb_id_table[] = { ++ { .compatible = "ti,twl4030-usb" }, ++ {} ++}; ++MODULE_DEVICE_TABLE(of, twl4030_usb_id_table); ++#endif ++ ++static struct platform_driver twl4030_usb_driver = { ++ .probe = twl4030_usb_probe, ++ .remove = twl4030_usb_remove, ++ .driver = { ++ .name = "twl4030_usb", ++ .owner = THIS_MODULE, ++ .of_match_table = of_match_ptr(twl4030_usb_id_table), ++ }, ++}; ++ ++static int __init twl4030_usb_init(void) ++{ ++ return platform_driver_register(&twl4030_usb_driver); ++} ++subsys_initcall(twl4030_usb_init); ++ ++static void __exit twl4030_usb_exit(void) ++{ ++ platform_driver_unregister(&twl4030_usb_driver); ++} ++module_exit(twl4030_usb_exit); ++ ++MODULE_ALIAS("platform:twl4030_usb"); ++MODULE_AUTHOR("Texas Instruments, Inc, Nokia Corporation"); ++MODULE_DESCRIPTION("TWL4030 USB transceiver driver"); ++MODULE_LICENSE("GPL"); +--- a/drivers/regulator/core.c ++++ b/drivers/regulator/core.c +@@ -124,6 +124,51 @@ static const char *rdev_get_name(struct + return ""; + } + ++static void regulator_lock(struct regulator_dev *rdev) ++{ ++ struct regulator_dev *locking_rdev = rdev; ++ ++ while (locking_rdev->supply) ++ locking_rdev = locking_rdev->supply->rdev; ++ ++ if (!mutex_trylock(&locking_rdev->mutex)) { ++ if (locking_rdev->lock_owner == current) { ++ locking_rdev->lock_count++; ++ dev_dbg(&locking_rdev->dev, ++ "Is locked. locking %s (ref=%u)\n", ++ rdev_get_name(rdev), ++ locking_rdev->lock_count); ++ return; ++ } ++ mutex_lock(&locking_rdev->mutex); ++ } ++ ++ WARN_ON_ONCE(locking_rdev->lock_owner != NULL); ++ WARN_ON_ONCE(locking_rdev->lock_count != 0); ++ ++ locking_rdev->lock_count = 1; ++ locking_rdev->lock_owner = current; ++ dev_dbg(&locking_rdev->dev, "Is locked. locking %s\n", ++ rdev_get_name(rdev)); ++} ++ ++static void regulator_unlock(struct regulator_dev *rdev) ++{ ++ struct regulator_dev *locking_rdev = rdev; ++ ++ while (locking_rdev->supply) ++ locking_rdev = locking_rdev->supply->rdev; ++ ++ dev_dbg(&locking_rdev->dev, "Is unlocked. unlocking %s (ref=%u)\n", ++ rdev_get_name(rdev), locking_rdev->lock_count); ++ ++ if (--locking_rdev->lock_count) ++ return; ++ ++ locking_rdev->lock_owner = NULL; ++ mutex_unlock(&locking_rdev->mutex); ++} ++ + /** + * of_get_regulator - get a regulator device node based on supply name + * @dev: Device pointer for the consumer (of regulator) device +@@ -306,9 +351,9 @@ static ssize_t regulator_uV_show(struct + struct regulator_dev *rdev = dev_get_drvdata(dev); + ssize_t ret; + +- mutex_lock(&rdev->mutex); ++ regulator_lock(rdev); + ret = sprintf(buf, "%d\n", _regulator_get_voltage(rdev)); +- mutex_unlock(&rdev->mutex); ++ regulator_unlock(rdev); + + return ret; + } +@@ -372,9 +417,9 @@ static ssize_t regulator_state_show(stru + struct regulator_dev *rdev = dev_get_drvdata(dev); + ssize_t ret; + +- mutex_lock(&rdev->mutex); ++ regulator_lock(rdev); + ret = regulator_print_state(buf, _regulator_is_enabled(rdev)); +- mutex_unlock(&rdev->mutex); ++ regulator_unlock(rdev); + + return ret; + } +@@ -482,10 +527,10 @@ static ssize_t regulator_total_uA_show(s + struct regulator *regulator; + int uA = 0; + +- mutex_lock(&rdev->mutex); ++ regulator_lock(rdev); + list_for_each_entry(regulator, &rdev->consumer_list, list) + uA += regulator->uA_load; +- mutex_unlock(&rdev->mutex); ++ regulator_unlock(rdev); + return sprintf(buf, "%d\n", uA); + } + static DEVICE_ATTR(requested_microamps, 0444, regulator_total_uA_show, NULL); +@@ -1123,7 +1168,7 @@ static struct regulator *create_regulato + if (regulator == NULL) + return NULL; + +- mutex_lock(&rdev->mutex); ++ regulator_lock(rdev); + regulator->rdev = rdev; + list_add(®ulator->list, &rdev->consumer_list); + +@@ -1175,12 +1220,12 @@ static struct regulator *create_regulato + _regulator_is_enabled(rdev)) + regulator->always_on = true; + +- mutex_unlock(&rdev->mutex); ++ regulator_unlock(rdev); + return regulator; + overflow_err: + list_del(®ulator->list); + kfree(regulator); +- mutex_unlock(&rdev->mutex); ++ regulator_unlock(rdev); + return NULL; + } + +@@ -1774,9 +1819,9 @@ int regulator_enable(struct regulator *r + return ret; + } + +- mutex_lock(&rdev->mutex); ++ regulator_lock(rdev); + ret = _regulator_enable(rdev); +- mutex_unlock(&rdev->mutex); ++ regulator_unlock(rdev); + + if (ret != 0 && rdev->supply) + regulator_disable(rdev->supply); +@@ -1866,9 +1911,9 @@ int regulator_disable(struct regulator * + if (regulator->always_on) + return 0; + +- mutex_lock(&rdev->mutex); ++ regulator_lock(rdev); + ret = _regulator_disable(rdev); +- mutex_unlock(&rdev->mutex); ++ regulator_unlock(rdev); + + if (ret == 0 && rdev->supply) + regulator_disable(rdev->supply); +@@ -1912,10 +1957,10 @@ int regulator_force_disable(struct regul + struct regulator_dev *rdev = regulator->rdev; + int ret; + +- mutex_lock(&rdev->mutex); ++ regulator_lock(rdev); + regulator->uA_load = 0; + ret = _regulator_force_disable(regulator->rdev); +- mutex_unlock(&rdev->mutex); ++ regulator_unlock(rdev); + + if (rdev->supply) + while (rdev->open_count--) +@@ -1931,7 +1976,7 @@ static void regulator_disable_work(struc + disable_work.work); + int count, i, ret; + +- mutex_lock(&rdev->mutex); ++ regulator_lock(rdev); + + BUG_ON(!rdev->deferred_disables); + +@@ -1944,7 +1989,7 @@ static void regulator_disable_work(struc + rdev_err(rdev, "Deferred disable failed: %d\n", ret); + } + +- mutex_unlock(&rdev->mutex); ++ regulator_unlock(rdev); + + if (rdev->supply) { + for (i = 0; i < count; i++) { +@@ -1980,9 +2025,9 @@ int regulator_disable_deferred(struct re + if (!ms) + return regulator_disable(regulator); + +- mutex_lock(&rdev->mutex); ++ regulator_lock(rdev); + rdev->deferred_disables++; +- mutex_unlock(&rdev->mutex); ++ regulator_unlock(rdev); + + ret = queue_delayed_work(system_power_efficient_wq, + &rdev->disable_work, +@@ -2026,9 +2071,9 @@ int regulator_is_enabled(struct regulato + if (regulator->always_on) + return 1; + +- mutex_lock(®ulator->rdev->mutex); ++ regulator_lock(regulator->rdev); + ret = _regulator_is_enabled(regulator->rdev); +- mutex_unlock(®ulator->rdev->mutex); ++ regulator_unlock(regulator->rdev); + + return ret; + } +@@ -2097,9 +2142,9 @@ int regulator_list_voltage(struct regula + if (!ops->list_voltage || selector >= rdev->desc->n_voltages) + return -EINVAL; + +- mutex_lock(&rdev->mutex); ++ regulator_lock(rdev); + ret = ops->list_voltage(rdev, selector); +- mutex_unlock(&rdev->mutex); ++ regulator_unlock(rdev); + + if (ret > 0) { + if (ret < rdev->constraints->min_uV) +@@ -2298,7 +2343,7 @@ int regulator_set_voltage(struct regulat + int ret = 0; + int old_min_uV, old_max_uV; + +- mutex_lock(&rdev->mutex); ++ regulator_lock(rdev); + + /* If we're setting the same range as last time the change + * should be a noop (some cpufreq implementations use the same +@@ -2334,12 +2379,12 @@ int regulator_set_voltage(struct regulat + goto out2; + + out: +- mutex_unlock(&rdev->mutex); ++ regulator_unlock(rdev); + return ret; + out2: + regulator->min_uV = old_min_uV; + regulator->max_uV = old_max_uV; +- mutex_unlock(&rdev->mutex); ++ regulator_unlock(rdev); + return ret; + } + EXPORT_SYMBOL_GPL(regulator_set_voltage); +@@ -2442,7 +2487,7 @@ int regulator_sync_voltage(struct regula + struct regulator_dev *rdev = regulator->rdev; + int ret, min_uV, max_uV; + +- mutex_lock(&rdev->mutex); ++ regulator_lock(rdev); + + if (!rdev->desc->ops->set_voltage && + !rdev->desc->ops->set_voltage_sel) { +@@ -2471,7 +2516,7 @@ int regulator_sync_voltage(struct regula + ret = _regulator_do_set_voltage(rdev, min_uV, max_uV); + + out: +- mutex_unlock(&rdev->mutex); ++ regulator_unlock(rdev); + return ret; + } + EXPORT_SYMBOL_GPL(regulator_sync_voltage); +@@ -2511,11 +2556,11 @@ int regulator_get_voltage(struct regulat + { + int ret; + +- mutex_lock(®ulator->rdev->mutex); ++ regulator_lock(regulator->rdev); + + ret = _regulator_get_voltage(regulator->rdev); + +- mutex_unlock(®ulator->rdev->mutex); ++ regulator_unlock(regulator->rdev); + + return ret; + } +@@ -2543,7 +2588,7 @@ int regulator_set_current_limit(struct r + struct regulator_dev *rdev = regulator->rdev; + int ret; + +- mutex_lock(&rdev->mutex); ++ regulator_lock(rdev); + + /* sanity check */ + if (!rdev->desc->ops->set_current_limit) { +@@ -2558,7 +2603,7 @@ int regulator_set_current_limit(struct r + + ret = rdev->desc->ops->set_current_limit(rdev, min_uA, max_uA); + out: +- mutex_unlock(&rdev->mutex); ++ regulator_unlock(rdev); + return ret; + } + EXPORT_SYMBOL_GPL(regulator_set_current_limit); +@@ -2567,7 +2612,7 @@ static int _regulator_get_current_limit( + { + int ret; + +- mutex_lock(&rdev->mutex); ++ regulator_lock(rdev); + + /* sanity check */ + if (!rdev->desc->ops->get_current_limit) { +@@ -2577,7 +2622,7 @@ static int _regulator_get_current_limit( + + ret = rdev->desc->ops->get_current_limit(rdev); + out: +- mutex_unlock(&rdev->mutex); ++ regulator_unlock(rdev); + return ret; + } + +@@ -2613,7 +2658,7 @@ int regulator_set_mode(struct regulator + int ret; + int regulator_curr_mode; + +- mutex_lock(&rdev->mutex); ++ regulator_lock(rdev); + + /* sanity check */ + if (!rdev->desc->ops->set_mode) { +@@ -2637,7 +2682,7 @@ int regulator_set_mode(struct regulator + + ret = rdev->desc->ops->set_mode(rdev, mode); + out: +- mutex_unlock(&rdev->mutex); ++ regulator_unlock(rdev); + return ret; + } + EXPORT_SYMBOL_GPL(regulator_set_mode); +@@ -2646,7 +2691,7 @@ static unsigned int _regulator_get_mode( + { + int ret; + +- mutex_lock(&rdev->mutex); ++ regulator_lock(rdev); + + /* sanity check */ + if (!rdev->desc->ops->get_mode) { +@@ -2656,7 +2701,7 @@ static unsigned int _regulator_get_mode( + + ret = rdev->desc->ops->get_mode(rdev); + out: +- mutex_unlock(&rdev->mutex); ++ regulator_unlock(rdev); + return ret; + } + +@@ -2708,7 +2753,7 @@ int regulator_set_optimum_mode(struct re + if (rdev->supply) + input_uV = regulator_get_voltage(rdev->supply); + +- mutex_lock(&rdev->mutex); ++ regulator_lock(rdev); + + /* + * first check to see if we can set modes at all, otherwise just +@@ -2769,7 +2814,7 @@ int regulator_set_optimum_mode(struct re + } + ret = mode; + out: +- mutex_unlock(&rdev->mutex); ++ regulator_unlock(rdev); + return ret; + } + EXPORT_SYMBOL_GPL(regulator_set_optimum_mode); +@@ -2797,7 +2842,7 @@ int regulator_allow_bypass(struct regula + !(rdev->constraints->valid_ops_mask & REGULATOR_CHANGE_BYPASS)) + return 0; + +- mutex_lock(&rdev->mutex); ++ regulator_lock(rdev); + + if (enable && !regulator->bypass) { + rdev->bypass_count++; +@@ -2821,7 +2866,7 @@ int regulator_allow_bypass(struct regula + if (ret == 0) + regulator->bypass = enable; + +- mutex_unlock(&rdev->mutex); ++ regulator_unlock(rdev); + + return ret; + } +@@ -3540,9 +3585,9 @@ int regulator_suspend_prepare(suspend_st + mutex_lock(®ulator_list_mutex); + list_for_each_entry(rdev, ®ulator_list, list) { + +- mutex_lock(&rdev->mutex); ++ regulator_lock(rdev); + ret = suspend_prepare(rdev, state); +- mutex_unlock(&rdev->mutex); ++ regulator_unlock(rdev); + + if (ret < 0) { + rdev_err(rdev, "failed to prepare\n"); +@@ -3570,7 +3615,7 @@ int regulator_suspend_finish(void) + list_for_each_entry(rdev, ®ulator_list, list) { + struct regulator_ops *ops = rdev->desc->ops; + +- mutex_lock(&rdev->mutex); ++ regulator_lock(rdev); + if ((rdev->use_count > 0 || rdev->constraints->always_on) && + ops->enable) { + error = ops->enable(rdev); +@@ -3589,7 +3634,7 @@ int regulator_suspend_finish(void) + ret = error; + } + unlock: +- mutex_unlock(&rdev->mutex); ++ regulator_unlock(rdev); + } + mutex_unlock(®ulator_list_mutex); + return ret; +@@ -3777,7 +3822,7 @@ static int __init regulator_init_complet + if (!ops->disable || (c && c->always_on)) + continue; + +- mutex_lock(&rdev->mutex); ++ regulator_lock(rdev); + + if (rdev->use_count) + goto unlock; +@@ -3809,7 +3854,7 @@ static int __init regulator_init_complet + } + + unlock: +- mutex_unlock(&rdev->mutex); ++ regulator_unlock(rdev); + } + + mutex_unlock(®ulator_list_mutex); +--- a/drivers/regulator/Kconfig ++++ b/drivers/regulator/Kconfig +@@ -492,6 +492,15 @@ config REGULATOR_TPS65217 + voltage regulators. It supports software based voltage control + for different voltage domains + ++config REGULATOR_TPS65218 ++ tristate "TI TPS65218 Power regulators" ++ depends on MFD_TPS65218 ++ help ++ This driver supports TPS65218 voltage regulator chips. TPS65218 ++ provides six step-down converters and one general-purpose LDO ++ voltage regulators. It supports software based voltage control ++ for different voltage domains ++ + config REGULATOR_TPS6524X + tristate "TI TPS6524X Power regulators" + depends on SPI +@@ -571,5 +580,19 @@ config REGULATOR_WM8994 + This driver provides support for the voltage regulators on the + WM8994 CODEC. + ++config REGULATOR_TIAVSCLASS0 ++ tristate "Adaptive Voltage Scaling class 0 support for TI SoCs" ++ depends on ARCH_OMAP2PLUS ++ help ++ AVS is a power management technique which finely controls the ++ operating voltage of a device in order to optimize (i.e. reduce) ++ its power consumption. ++ At a given operating point, the voltage is adapted depending on ++ static factors (chip manufacturing process) and this adapted ++ voltage is made available in an efuse offset. ++ AVS is also called SmartReflex on OMAP devices. ++ ++ Say Y here to enable Adaptive Voltage Scaling class 0 support. ++ + endif + +--- a/drivers/regulator/Makefile ++++ b/drivers/regulator/Makefile +@@ -63,6 +63,7 @@ obj-$(CONFIG_REGULATOR_TPS65023) += tps6 + obj-$(CONFIG_REGULATOR_TPS6507X) += tps6507x-regulator.o + obj-$(CONFIG_REGULATOR_TPS65090) += tps65090-regulator.o + obj-$(CONFIG_REGULATOR_TPS65217) += tps65217-regulator.o ++obj-$(CONFIG_REGULATOR_TPS65218) += tps65218-regulator.o + obj-$(CONFIG_REGULATOR_TPS6524X) += tps6524x-regulator.o + obj-$(CONFIG_REGULATOR_TPS6586X) += tps6586x-regulator.o + obj-$(CONFIG_REGULATOR_TPS65910) += tps65910-regulator.o +@@ -76,6 +77,7 @@ obj-$(CONFIG_REGULATOR_WM831X) += wm831x + obj-$(CONFIG_REGULATOR_WM8350) += wm8350-regulator.o + obj-$(CONFIG_REGULATOR_WM8400) += wm8400-regulator.o + obj-$(CONFIG_REGULATOR_WM8994) += wm8994-regulator.o ++obj-$(CONFIG_REGULATOR_TIAVSCLASS0) += ti-avs-class0-regulator.o + + + ccflags-$(CONFIG_REGULATOR_DEBUG) += -DDEBUG +--- /dev/null ++++ b/drivers/regulator/ti-avs-class0-regulator.c +@@ -0,0 +1,349 @@ ++/* ++ * Texas Instrument SmartReflex AVS Class 0 driver ++ * ++ * Copyright (C) 2013 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. ++ * ++ * 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. ++ */ ++#define pr_fmt(fmt) KBUILD_MODNAME ": %s(): " fmt, __func__ ++ ++#include <linux/err.h> ++#include <linux/init.h> ++#include <linux/io.h> ++#include <linux/module.h> ++#include <linux/of_device.h> ++#include <linux/of.h> ++#include <linux/platform_device.h> ++#include <linux/regulator/consumer.h> ++#include <linux/regulator/driver.h> ++#include <linux/regulator/machine.h> ++#include <linux/regulator/of_regulator.h> ++#include <linux/slab.h> ++#include <linux/string.h> ++ ++/** ++ * struct tiavs_class0_data - class data for the regulator instance ++ * @desc: regulator descriptor ++ * @reg: regulator that will actually set the voltage ++ * @volt_set_table: voltage to set data table ++ * @current_idx: current index ++ * @voltage_tolerance: % tolerance for voltage(optional) ++ */ ++struct tiavs_class0_data { ++ struct regulator_desc desc; ++ struct regulator *reg; ++ unsigned int *volt_set_table; ++ int current_idx; ++ u32 voltage_tolerance; ++}; ++ ++/** ++ * tiavs_class0_set_voltage_sel() - set voltage ++ * @rdev: regulator device ++ * @sel: set voltage corresponding to selector ++ * ++ * This searches for a best case match and uses the child regulator to set ++ * appropriate voltage ++ * ++ * Return: -ENODEV if no proper regulator data/-EINVAL if no match,bad efuse ++ * else returns regulator set result ++ */ ++static int tiavs_class0_set_voltage_sel(struct regulator_dev *rdev, ++ unsigned sel) ++{ ++ struct tiavs_class0_data *data = rdev_get_drvdata(rdev); ++ const struct regulator_desc *desc = rdev->desc; ++ struct regulator *reg; ++ int vset, ret, tol; ++ ++ if (!data) { ++ pr_err("No regulator drvdata\n"); ++ return -ENODEV; ++ } ++ ++ reg = data->reg; ++ if (!reg) { ++ pr_err("No regulator\n"); ++ return -ENODEV; ++ } ++ ++ if (!desc->n_voltages || !data->volt_set_table) { ++ pr_err("No valid voltage table entries?\n"); ++ return -EINVAL; ++ } ++ ++ if (sel >= desc->n_voltages) { ++ pr_err("sel(%d) > max voltage table entries(%d)\n", sel, ++ desc->n_voltages); ++ return -EINVAL; ++ } ++ ++ vset = data->volt_set_table[sel]; ++ ++ /* Adjust for % tolerance needed */ ++ tol = DIV_ROUND_UP(vset * data->voltage_tolerance, 100); ++ ret = regulator_set_voltage_tol(reg, vset, tol); ++ if (!ret) ++ data->current_idx = sel; ++ ++ return ret; ++} ++ ++/** ++ * tiavs_class0_get_voltage_sel() - Get voltage selector ++ * @rdev: regulator device ++ * ++ * Return: -ENODEV if no proper regulator data/-EINVAL if no data, ++ * else returns current index. ++ */ ++static int tiavs_class0_get_voltage_sel(struct regulator_dev *rdev) ++{ ++ const struct regulator_desc *desc = rdev->desc; ++ struct tiavs_class0_data *data = rdev_get_drvdata(rdev); ++ ++ if (!data) { ++ pr_err("No regulator drvdata\n"); ++ return -ENODEV; ++ } ++ ++ if (!desc->n_voltages || !data->volt_set_table) { ++ pr_err("No valid voltage table entries?\n"); ++ return -EINVAL; ++ } ++ ++ if (data->current_idx > desc->n_voltages) { ++ pr_err("Corrupted data structure?? idx(%d) > n_voltages(%d)\n", ++ data->current_idx, desc->n_voltages); ++ return -EINVAL; ++ } ++ ++ return data->current_idx; ++} ++ ++static struct regulator_ops tiavs_class0_ops = { ++ .list_voltage = regulator_list_voltage_table, ++ ++ .set_voltage_sel = tiavs_class0_set_voltage_sel, ++ .get_voltage_sel = tiavs_class0_get_voltage_sel, ++ ++}; ++ ++static const struct of_device_id tiavs_class0_of_match[] = { ++ {.compatible = "ti,avsclass0",}, ++ {}, ++}; ++ ++MODULE_DEVICE_TABLE(of, tiavs_class0_of_match); ++ ++/** ++ * tiavs_class0_probe() - AVS class 0 probe ++ * @pdev: matching platform device ++ * ++ * We support only device tree provided data here. Once we find a regulator, ++ * efuse offsets, we pick up the efuse register voltages store them per ++ * instance. ++ * ++ * Return: if everything goes through, we return 0, else corresponding error ++ * value is returned. ++ */ ++static int tiavs_class0_probe(struct platform_device *pdev) ++{ ++ const struct of_device_id *match; ++ struct device_node *np = pdev->dev.of_node; ++ struct property *prop; ++ struct resource *res; ++ struct regulator *reg; ++ struct regulator_init_data *initdata = NULL; ++ struct regulator_config config = { }; ++ struct regulation_constraints *c; ++ struct regulator_dev *rdev; ++ struct regulator_desc *desc; ++ struct tiavs_class0_data *data; ++ void __iomem *base; ++ const __be32 *val; ++ unsigned int *volt_table; ++ bool efuse_is_uV = false; ++ int proplen, i, ret; ++ int reg_v, min_uV = INT_MAX, max_uV = 0; ++ int best_val = INT_MAX, choice = -EINVAL; ++ ++ match = of_match_device(tiavs_class0_of_match, &pdev->dev); ++ if (match) ++ initdata = of_get_regulator_init_data(&pdev->dev, np); ++ if (!initdata) { ++ dev_err(&pdev->dev, "No proper OF?\n"); ++ return -ENODEV; ++ } ++ ++ /* look for avs-supply */ ++ reg = devm_regulator_get(&pdev->dev, "avs"); ++ if (IS_ERR(reg)) { ++ ret = PTR_ERR(reg); ++ reg = NULL; ++ dev_err(&pdev->dev, "avs_class0 regulator not available(%d)\n", ++ ret); ++ return ret; ++ } ++ ++ data = devm_kzalloc(&pdev->dev, sizeof(*data), GFP_KERNEL); ++ if (!data) { ++ dev_err(&pdev->dev, "No memory to alloc data!\n"); ++ return -ENOMEM; ++ } ++ data->reg = reg; ++ ++ desc = &data->desc; ++ desc->name = dev_name(&pdev->dev); ++ desc->owner = THIS_MODULE; ++ desc->type = REGULATOR_VOLTAGE; ++ desc->ops = &tiavs_class0_ops; ++ ++ /* pick up optional properties */ ++ of_property_read_u32(np, "voltage-tolerance", &data->voltage_tolerance); ++ efuse_is_uV = of_property_read_bool(np, ++ "ti,avsclass0-microvolt-values"); ++ ++ /* pick up Efuse based voltages */ ++ res = platform_get_resource(pdev, IORESOURCE_MEM, 0); ++ if (!res) { ++ dev_err(&pdev->dev, "Unable to get IO resource\n"); ++ return -ENODEV; ++ } ++ ++ base = devm_ioremap_nocache(&pdev->dev, res->start, resource_size(res)); ++ if (!base) { ++ dev_err(&pdev->dev, "Unable to map Efuse registers\n"); ++ return -ENOMEM; ++ } ++ ++ /* Fetch efuse-settings. */ ++ prop = of_find_property(np, "efuse-settings", NULL); ++ if (!prop) { ++ dev_err(&pdev->dev, "No 'efuse-settings' property found\n"); ++ return -EINVAL; ++ } ++ ++ proplen = prop->length / sizeof(int); ++ ++ data->volt_set_table = ++ devm_kzalloc(&pdev->dev, sizeof(unsigned int) * (proplen / 2), ++ GFP_KERNEL); ++ if (!data->volt_set_table) { ++ dev_err(&pdev->dev, "Unable to Allocate voltage set table\n"); ++ return -ENOMEM; ++ } ++ ++ volt_table = ++ devm_kzalloc(&pdev->dev, sizeof(unsigned int) * (proplen / 2), ++ GFP_KERNEL); ++ if (!volt_table) { ++ dev_err(&pdev->dev, ++ "Unable to Allocate voltage lookup table\n"); ++ return -ENOMEM; ++ } ++ ++ val = prop->value; ++ for (i = 0; i < proplen / 2; i++) { ++ u32 efuse_offset; ++ ++ volt_table[i] = be32_to_cpup(val++); ++ efuse_offset = be32_to_cpup(val++); ++ ++ data->volt_set_table[i] = efuse_is_uV ? ++ readl(base + efuse_offset) : ++ readw(base + efuse_offset) * 1000; ++ ++ /* Find min/max for the voltage sets */ ++ if (min_uV > volt_table[i]) ++ min_uV = volt_table[i]; ++ if (max_uV < volt_table[i]) ++ max_uV = volt_table[i]; ++ ++ dev_dbg(&pdev->dev, "[%d] efuse=0x%08x volt_table=%d vset=%d\n", ++ i, efuse_offset, volt_table[i], ++ data->volt_set_table[i]); ++ } ++ desc->n_voltages = i; ++ desc->volt_table = volt_table; ++ ++ /* Search for a best match voltage */ ++ reg_v = regulator_get_voltage(reg); ++ if (reg_v < 0) { ++ dev_err(&pdev->dev, "Regulator error %d for get_voltage!\n", ++ reg_v); ++ return reg_v; ++ } ++ ++ for (i = 0; i < desc->n_voltages; i++) ++ if (data->volt_set_table[i] < best_val && ++ data->volt_set_table[i] >= reg_v) { ++ best_val = data->volt_set_table[i]; ++ choice = i; ++ } ++ ++ if (choice == -EINVAL) { ++ dev_err(&pdev->dev, "No match regulator V=%d\n", reg_v); ++ return -EINVAL; ++ } ++ data->current_idx = choice; ++ ++ /* ++ * Constrain board-specific capabilities according to what ++ * this driver can actually do. ++ */ ++ c = &initdata->constraints; ++ if (desc->n_voltages > 1) ++ c->valid_ops_mask |= REGULATOR_CHANGE_VOLTAGE; ++ c->always_on = true; ++ ++ c->min_uV = min_uV; ++ c->max_uV = max_uV; ++ ++ config.dev = &pdev->dev; ++ config.init_data = initdata; ++ config.driver_data = data; ++ config.of_node = pdev->dev.of_node; ++ ++ rdev = regulator_register(desc, &config); ++ if (IS_ERR(rdev)) { ++ dev_err(&pdev->dev, "can't register %s, %ld\n", ++ desc->name, PTR_ERR(rdev)); ++ return PTR_ERR(rdev); ++ } ++ platform_set_drvdata(pdev, rdev); ++ ++ return 0; ++} ++ ++static int tiavs_class0_remove(struct platform_device *pdev) ++{ ++ struct regulator_dev *rdev = platform_get_drvdata(pdev); ++ ++ regulator_unregister(rdev); ++ return 0; ++} ++ ++MODULE_ALIAS("platform:tiavs_class0"); ++ ++static struct platform_driver tiavs_class0_driver = { ++ .probe = tiavs_class0_probe, ++ .remove = tiavs_class0_remove, ++ .driver = { ++ .name = "tiavs_class0", ++ .owner = THIS_MODULE, ++ .of_match_table = of_match_ptr(tiavs_class0_of_match), ++ }, ++}; ++module_platform_driver(tiavs_class0_driver); ++ ++MODULE_DESCRIPTION("TI SmartReflex AVS class 0 regulator driver"); ++MODULE_AUTHOR("Texas Instruments Inc."); ++MODULE_LICENSE("GPL v2"); +--- /dev/null ++++ b/drivers/regulator/tps65218-regulator.c +@@ -0,0 +1,392 @@ ++/* ++ * tps65218-regulator.c ++ * ++ * Regulator driver for TPS65218 PMIC ++ * ++ * Copyright (C) 2013 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 version 2 as ++ * published by the Free Software Foundation. ++ * ++ * This program is distributed "as is" WITHOUT ANY WARRANTY of any ++ * kind, whether expressed or implied; without even the implied warranty ++ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License version 2 for more details. ++ */ ++ ++#include <linux/kernel.h> ++#include <linux/module.h> ++#include <linux/device.h> ++#include <linux/init.h> ++#include <linux/err.h> ++#include <linux/platform_device.h> ++#include <linux/of_device.h> ++#include <linux/regulator/of_regulator.h> ++#include <linux/regulator/driver.h> ++#include <linux/regulator/machine.h> ++#include <linux/mfd/tps65218.h> ++ ++static unsigned int tps65218_ramp_delay = 4000; ++ ++#define TPS65218_REGULATOR(_name, _id, _ops, _n, _vr, _vm, _er, _em, _t) \ ++ { \ ++ .name = _name, \ ++ .id = _id, \ ++ .ops = &_ops, \ ++ .n_voltages = _n, \ ++ .type = REGULATOR_VOLTAGE, \ ++ .owner = THIS_MODULE, \ ++ .vsel_reg = _vr, \ ++ .vsel_mask = _vm, \ ++ .enable_reg = _er, \ ++ .enable_mask = _em, \ ++ .volt_table = _t, \ ++ } \ ++ ++#define TPS65218_INFO(_id, _nm, _min, _max, _f1, _f2) \ ++ { \ ++ .id = _id, \ ++ .name = _nm, \ ++ .min_uV = _min, \ ++ .max_uV = _max, \ ++ .vsel_to_uv = _f1, \ ++ .uv_to_vsel = _f2, \ ++ } ++ ++static int tps65218_ldo1_dcdc3_vsel_to_uv(unsigned int vsel) ++{ ++ int uV = 0; ++ ++ if (vsel <= 26) ++ uV = vsel * 25000 + 900000; ++ else ++ uV = (vsel - 26) * 50000 + 1550000; ++ ++ return uV; ++} ++ ++static int tps65218_ldo1_dcdc3_uv_to_vsel(int uV, unsigned int *vsel) ++{ ++ if (uV <= 15500000) ++ *vsel = DIV_ROUND_UP(uV - 900000, 25000); ++ else ++ *vsel = 26 + DIV_ROUND_UP(uV - 1550000, 50000); ++ ++ return 0; ++} ++ ++static int tps65218_dcdc1_2_vsel_to_uv(unsigned int vsel) ++{ ++ int uV = 0; ++ ++ if (vsel <= 50) ++ uV = vsel * 10000 + 850000; ++ else ++ uV = (vsel - 50) * 25000 + 1350000; ++ ++ return uV; ++} ++ ++static int tps65218_dcdc1_2_uv_to_vsel(int uV, unsigned int *vsel) ++{ ++ if (uV <= 13500000) ++ *vsel = DIV_ROUND_UP(uV - 850000, 10000); ++ else ++ *vsel = 50 + DIV_ROUND_UP(uV - 1350000, 25000); ++ ++ return 0; ++} ++ ++static int tps65218_dcd4_vsel_to_uv(unsigned int vsel) ++{ ++ int uV = 0; ++ ++ if (vsel <= 15) ++ uV = vsel * 25000 + 1175000; ++ else ++ uV = (vsel - 15) * 50000 + 1550000; ++ ++ return uV; ++} ++ ++static int tps65218_dcdc4_uv_to_vsel(int uV, unsigned int *vsel) ++{ ++ if (uV <= 15500000) ++ *vsel = DIV_ROUND_UP(uV - 1175000, 25000); ++ else ++ *vsel = 15 + DIV_ROUND_UP(uV - 1550000, 50000); ++ ++ return 0; ++} ++ ++static struct tps_info tps65218_pmic_regs[] = { ++ TPS65218_INFO(0, "DCDC1", 850000, 1675000, tps65218_dcdc1_2_vsel_to_uv, ++ tps65218_dcdc1_2_uv_to_vsel), ++ TPS65218_INFO(1, "DCDC2", 850000, 1675000, tps65218_dcdc1_2_vsel_to_uv, ++ tps65218_dcdc1_2_uv_to_vsel), ++ TPS65218_INFO(2, "DCDC3", 900000, 3400000, ++ tps65218_ldo1_dcdc3_vsel_to_uv, ++ tps65218_ldo1_dcdc3_uv_to_vsel), ++ TPS65218_INFO(3, "DCDC4", 1175000, 3400000, tps65218_dcd4_vsel_to_uv, ++ tps65218_dcdc4_uv_to_vsel), ++ TPS65218_INFO(4, "DCDC5", 1000000, 1000000, NULL, NULL), ++ TPS65218_INFO(5, "DCDC6", 1800000, 1800000, NULL, NULL), ++ TPS65218_INFO(6, "LDO1", 900000, 3400000, ++ tps65218_ldo1_dcdc3_vsel_to_uv, ++ tps65218_ldo1_dcdc3_uv_to_vsel), ++}; ++ ++#define TPS65218_OF_MATCH(comp, label) \ ++ { \ ++ .compatible = comp, \ ++ .data = &label, \ ++ } ++ ++static const struct of_device_id tps65218_of_match[] = { ++ TPS65218_OF_MATCH("ti,tps65218-dcdc1", tps65218_pmic_regs[0]), ++ TPS65218_OF_MATCH("ti,tps65218-dcdc2", tps65218_pmic_regs[1]), ++ TPS65218_OF_MATCH("ti,tps65218-dcdc3", tps65218_pmic_regs[2]), ++ TPS65218_OF_MATCH("ti,tps65218-dcdc4", tps65218_pmic_regs[3]), ++ TPS65218_OF_MATCH("ti,tps65218-dcdc5", tps65218_pmic_regs[4]), ++ TPS65218_OF_MATCH("ti,tps65218-dcdc6", tps65218_pmic_regs[5]), ++ TPS65218_OF_MATCH("ti,tps65218-ldo1", tps65218_pmic_regs[6]), ++}; ++MODULE_DEVICE_TABLE(of, tps65218_of_match); ++ ++static int tps65218_pmic_set_voltage_sel(struct regulator_dev *dev, ++ unsigned selector) ++{ ++ int ret; ++ struct tps65218 *tps = rdev_get_drvdata(dev); ++ unsigned int rid = rdev_get_id(dev); ++ ++ /* Set the voltage based on vsel value and write protect level is 2 */ ++ ret = tps65218_set_bits(tps, dev->desc->vsel_reg, dev->desc->vsel_mask, ++ selector, TPS65218_PROTECT_L1); ++ ++ /* Set GO bit for DCDC1/2 to initiate voltage transistion */ ++ switch (rid) { ++ case TPS65218_DCDC_1: ++ case TPS65218_DCDC_2: ++ ret = tps65218_set_bits(tps, TPS65218_REG_CONTRL_SLEW_RATE, ++ TPS65218_SLEW_RATE_GO, ++ TPS65218_SLEW_RATE_GO, ++ TPS65218_PROTECT_L1); ++ break; ++ } ++ ++ return ret; ++} ++ ++static int tps65218_pmic_map_voltage(struct regulator_dev *dev, ++ int min_uV, int max_uV) ++{ ++ struct tps65218 *tps = rdev_get_drvdata(dev); ++ unsigned int sel, rid = rdev_get_id(dev); ++ int ret; ++ ++ if (rid < TPS65218_DCDC_1 || rid > TPS65218_LDO_1) ++ return -EINVAL; ++ ++ if (min_uV < tps->info[rid]->min_uV) ++ min_uV = tps->info[rid]->min_uV; ++ ++ if (max_uV < tps->info[rid]->min_uV || min_uV > tps->info[rid]->max_uV) ++ return -EINVAL; ++ ++ ret = tps->info[rid]->uv_to_vsel(min_uV, &sel); ++ if (ret) ++ return ret; ++ ++ return sel; ++} ++ ++static int tps65218_pmic_list_voltage(struct regulator_dev *dev, ++ unsigned selector) ++{ ++ struct tps65218 *tps = rdev_get_drvdata(dev); ++ unsigned int rid = rdev_get_id(dev); ++ ++ if (rid < TPS65218_DCDC_1 || rid > TPS65218_LDO_1) ++ return -EINVAL; ++ ++ if (selector >= dev->desc->n_voltages) ++ return -EINVAL; ++ ++ return tps->info[rid]->vsel_to_uv(selector); ++} ++ ++static int tps65218_pmic_enable(struct regulator_dev *dev) ++{ ++ struct tps65218 *tps = rdev_get_drvdata(dev); ++ unsigned int rid = rdev_get_id(dev); ++ ++ if (rid < TPS65218_DCDC_1 || rid > TPS65218_LDO_1) ++ return -EINVAL; ++ ++ /* Enable the regulator and password protection is level 1 */ ++ return tps65218_set_bits(tps, dev->desc->enable_reg, ++ dev->desc->enable_mask, dev->desc->enable_mask, ++ TPS65218_PROTECT_L1); ++} ++ ++static int tps65218_pmic_disable(struct regulator_dev *dev) ++{ ++ struct tps65218 *tps = rdev_get_drvdata(dev); ++ unsigned int rid = rdev_get_id(dev); ++ ++ if (rid < TPS65218_DCDC_1 || rid > TPS65218_LDO_1) ++ return -EINVAL; ++ ++ /* Disable the regulator and password protection is level 1 */ ++ return tps65218_clear_bits(tps, dev->desc->enable_reg, ++ dev->desc->enable_mask, TPS65218_PROTECT_L1); ++} ++ ++static int tps65218_set_voltage_time_sel(struct regulator_dev *rdev, ++ unsigned int old_selector, unsigned int new_selector) ++{ ++ int old_uv, new_uv; ++ ++ old_uv = tps65218_pmic_list_voltage(rdev, old_selector); ++ if (old_uv < 0) ++ return old_uv; ++ ++ new_uv = tps65218_pmic_list_voltage(rdev, new_selector); ++ if (new_uv < 0) ++ return new_uv; ++ ++ return DIV_ROUND_UP(abs(old_uv - new_uv), tps65218_ramp_delay); ++} ++ ++/* Operations permitted on DCDC1, DCDC2 */ ++static struct regulator_ops tps65218_dcdc12_ops = { ++ .is_enabled = regulator_is_enabled_regmap, ++ .enable = tps65218_pmic_enable, ++ .disable = tps65218_pmic_disable, ++ .get_voltage_sel = regulator_get_voltage_sel_regmap, ++ .set_voltage_sel = tps65218_pmic_set_voltage_sel, ++ .list_voltage = tps65218_pmic_list_voltage, ++ .map_voltage = tps65218_pmic_map_voltage, ++ .set_voltage_time_sel = tps65218_set_voltage_time_sel, ++}; ++ ++/* Operations permitted on DCDC3, DCDC4 and LDO1 */ ++static struct regulator_ops tps65218_ldo1_dcdc34_ops = { ++ .is_enabled = regulator_is_enabled_regmap, ++ .enable = tps65218_pmic_enable, ++ .disable = tps65218_pmic_disable, ++ .get_voltage_sel = regulator_get_voltage_sel_regmap, ++ .set_voltage_sel = tps65218_pmic_set_voltage_sel, ++ .list_voltage = tps65218_pmic_list_voltage, ++ .map_voltage = tps65218_pmic_map_voltage, ++}; ++ ++/* Operations permitted on DCDC5, DCDC6 */ ++static struct regulator_ops tps65218_dcdc56_pmic_ops = { ++ .is_enabled = regulator_is_enabled_regmap, ++ .enable = tps65218_pmic_enable, ++ .disable = tps65218_pmic_disable, ++}; ++ ++static const struct regulator_desc regulators[] = { ++ TPS65218_REGULATOR("DCDC1", TPS65218_DCDC_1, tps65218_dcdc12_ops, 64, ++ TPS65218_REG_CONTROL_DCDC1, ++ TPS65218_CONTROL_DCDC1_MASK, ++ TPS65218_REG_ENABLE1, TPS65218_ENABLE1_DC1_EN, NULL), ++ TPS65218_REGULATOR("DCDC2", TPS65218_DCDC_2, tps65218_dcdc12_ops, 64, ++ TPS65218_REG_CONTROL_DCDC2, ++ TPS65218_CONTROL_DCDC2_MASK, ++ TPS65218_REG_ENABLE1, TPS65218_ENABLE1_DC2_EN, NULL), ++ TPS65218_REGULATOR("DCDC3", TPS65218_DCDC_3, tps65218_ldo1_dcdc34_ops, ++ 64, TPS65218_REG_CONTROL_DCDC3, ++ TPS65218_CONTROL_DCDC3_MASK, TPS65218_REG_ENABLE1, ++ TPS65218_ENABLE1_DC3_EN, NULL), ++ TPS65218_REGULATOR("DCDC4", TPS65218_DCDC_4, tps65218_ldo1_dcdc34_ops, ++ 53, TPS65218_REG_CONTROL_DCDC4, ++ TPS65218_CONTROL_DCDC4_MASK, ++ TPS65218_REG_ENABLE1, TPS65218_ENABLE1_DC4_EN, NULL), ++ TPS65218_REGULATOR("DCDC5", TPS65218_DCDC_5, tps65218_dcdc56_pmic_ops, ++ 1, -1, -1, TPS65218_REG_ENABLE1, ++ TPS65218_ENABLE1_DC5_EN, NULL), ++ TPS65218_REGULATOR("DCDC6", TPS65218_DCDC_6, tps65218_dcdc56_pmic_ops, ++ 1, -1, -1, TPS65218_REG_ENABLE1, ++ TPS65218_ENABLE1_DC6_EN, NULL), ++ TPS65218_REGULATOR("LDO1", TPS65218_LDO_1, tps65218_ldo1_dcdc34_ops, 64, ++ TPS65218_REG_CONTROL_DCDC4, ++ TPS65218_CONTROL_LDO1_MASK, TPS65218_REG_ENABLE2, ++ TPS65218_ENABLE2_LDO1_EN, NULL), ++}; ++ ++static int tps65218_regulator_probe(struct platform_device *pdev) ++{ ++ struct tps65218 *tps = dev_get_drvdata(pdev->dev.parent); ++ struct regulator_init_data *init_data; ++ const struct tps_info *template; ++ struct regulator_dev *rdev; ++ const struct of_device_id *match; ++ struct regulator_config config = { }; ++ int id; ++ ++ match = of_match_device(tps65218_of_match, &pdev->dev); ++ if (match) { ++ template = match->data; ++ id = template->id; ++ init_data = of_get_regulator_init_data(&pdev->dev, ++ pdev->dev.of_node); ++ } else { ++ return -ENODEV; ++ } ++ ++ platform_set_drvdata(pdev, tps); ++ ++ tps->info[id] = &tps65218_pmic_regs[id]; ++ config.dev = &pdev->dev; ++ config.init_data = init_data; ++ config.driver_data = tps; ++ config.regmap = tps->regmap; ++ ++ rdev = regulator_register(®ulators[id], &config); ++ if (IS_ERR(rdev)) { ++ dev_err(tps->dev, "failed to register %s regulator\n", ++ pdev->name); ++ return PTR_ERR(rdev); ++ } ++ ++ /* Save regulator */ ++ tps->rdev[id] = rdev; ++ ++ return 0; ++} ++ ++static int tps65218_regulator_remove(struct platform_device *pdev) ++{ ++ struct tps65218 *tps = platform_get_drvdata(pdev); ++ const struct of_device_id *match; ++ const struct tps_info *template; ++ ++ match = of_match_device(tps65218_of_match, &pdev->dev); ++ template = match->data; ++ regulator_unregister(tps->rdev[template->id]); ++ platform_set_drvdata(pdev, NULL); ++ ++ return 0; ++} ++ ++static struct platform_driver tps65218_regulator_driver = { ++ .driver = { ++ .name = "tps65218-pmic", ++ .owner = THIS_MODULE, ++ .of_match_table = of_match_ptr(tps65218_of_match), ++ }, ++ .probe = tps65218_regulator_probe, ++ .remove = tps65218_regulator_remove, ++}; ++ ++module_platform_driver(tps65218_regulator_driver); ++ ++MODULE_AUTHOR("J Keerthy <j-keerthy@ti.com>"); ++MODULE_DESCRIPTION("TPS65218 voltage regulator driver"); ++MODULE_ALIAS("platform:tps65218-pmic"); ++MODULE_LICENSE("GPL v2"); +--- a/drivers/reset/core.c ++++ b/drivers/reset/core.c +@@ -127,6 +127,38 @@ int reset_control_deassert(struct reset_ + EXPORT_SYMBOL_GPL(reset_control_deassert); + + /** ++ * reset_control_is_reset - check reset status ++ * @rstc: reset controller ++ * ++ * Returns a boolean or negative error code ++ * ++ */ ++int reset_control_is_reset(struct reset_control *rstc) ++{ ++ if (rstc->rcdev->ops->is_reset) ++ return rstc->rcdev->ops->is_reset(rstc->rcdev, rstc->id); ++ ++ return -ENOSYS; ++} ++EXPORT_SYMBOL_GPL(reset_control_is_reset); ++ ++/** ++ * reset_control_clear_reset - clear the reset ++ * @rstc: reset controller ++ * ++ * Returns zero on success or negative error code ++ * ++ */ ++int reset_control_clear_reset(struct reset_control *rstc) ++{ ++ if (rstc->rcdev->ops->clear_reset) ++ return rstc->rcdev->ops->clear_reset(rstc->rcdev, rstc->id); ++ ++ return -ENOSYS; ++} ++EXPORT_SYMBOL_GPL(reset_control_clear_reset); ++ ++/** + * reset_control_get - Lookup and obtain a reference to a reset controller. + * @dev: device to be reset by the controller + * @id: reset line name +--- a/drivers/reset/Kconfig ++++ b/drivers/reset/Kconfig +@@ -11,3 +11,17 @@ menuconfig RESET_CONTROLLER + via GPIOs or SoC-internal reset controller modules. + + If unsure, say no. ++ ++if RESET_CONTROLLER ++ ++config RESET_TI ++ bool "TI reset controller" ++ help ++ Reset controller support for TI SoC's ++ ++ Reset controller found in TI's AM series of SoC's like ++ AM335x and AM43x and OMAP SoC's like OMAP5 and DRA7 ++ ++ If unsure, say no. ++ ++endif +--- a/drivers/reset/Makefile ++++ b/drivers/reset/Makefile +@@ -1 +1,2 @@ + obj-$(CONFIG_RESET_CONTROLLER) += core.o ++obj-$(CONFIG_RESET_TI) += ti_reset.o +--- /dev/null ++++ b/drivers/reset/ti_reset.c +@@ -0,0 +1,172 @@ ++/* ++ * PRCM reset driver for TI SoC's ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation; either version 2 of the License, or ++ * (at your option) any later version. ++ */ ++#include <linux/device.h> ++#include <linux/err.h> ++#include <linux/kernel.h> ++#include <linux/module.h> ++#include <linux/of_device.h> ++#include <linux/reset.h> ++#include <linux/reset-controller.h> ++#include <linux/platform_device.h> ++#include <linux/io.h> ++ ++#define DRIVER_NAME "ti_reset" ++ ++struct ti_reset_reg_data { ++ u32 rstctrl_offs; ++ u32 rstst_offs; ++ u8 rstctrl_bit; ++ u8 rstst_bit; ++}; ++ ++struct ti_reset_data { ++ struct ti_reset_reg_data *reg_data; ++ u8 nr_resets; ++}; ++ ++static void __iomem *reg_base; ++static const struct ti_reset_data *reset_data; ++ ++static struct ti_reset_reg_data am335x_reset_reg_data[] = { ++ { ++ .rstctrl_offs = 0x1104, ++ .rstst_offs = 0x1114, ++ .rstctrl_bit = 0, ++ .rstst_bit = 0, ++ }, ++}; ++ ++static struct ti_reset_data am335x_reset_data = { ++ .reg_data = am335x_reset_reg_data, ++ .nr_resets = ARRAY_SIZE(am335x_reset_reg_data), ++}; ++ ++static struct ti_reset_reg_data am43x_reset_reg_data[] = { ++ { ++ .rstctrl_offs = 0x410, ++ .rstst_offs = 0x414, ++ .rstctrl_bit = 0, ++ .rstst_bit = 0, ++ }, ++}; ++ ++static struct ti_reset_data am43x_reset_data = { ++ .reg_data = am43x_reset_reg_data, ++ .nr_resets = ARRAY_SIZE(am43x_reset_reg_data), ++}; ++ ++static struct ti_reset_reg_data dra7_reset_reg_data[] = { ++ { ++ .rstctrl_offs = 0x1310, ++ .rstst_offs = 0x1314, ++ .rstctrl_bit = 0, ++ .rstst_bit = 0, ++ }, ++}; ++ ++static struct ti_reset_data dra7_reset_data = { ++ .reg_data = dra7_reset_reg_data, ++ .nr_resets = ARRAY_SIZE(dra7_reset_reg_data), ++}; ++ ++static int ti_reset_clear_reset(struct reset_controller_dev *rcdev, ++ unsigned long id) ++{ ++ void __iomem *reg = reset_data->reg_data[id].rstst_offs + reg_base; ++ u8 bit = reset_data->reg_data[id].rstst_bit; ++ u32 val = readl(reg); ++ ++ val &= ~(1 << bit); ++ val |= 1 << bit; ++ writel(val, reg); ++ return 0; ++} ++ ++static int ti_reset_is_reset(struct reset_controller_dev *rcdev, ++ unsigned long id) ++{ ++ void __iomem *reg = reset_data->reg_data[id].rstst_offs + reg_base; ++ u8 bit = reset_data->reg_data[id].rstst_bit; ++ u32 val = readl(reg); ++ ++ val &= (1 << bit); ++ return !!val; ++} ++ ++static int ti_reset_deassert(struct reset_controller_dev *rcdev, ++ unsigned long id) ++{ ++ void __iomem *reg = reset_data->reg_data[id].rstctrl_offs + ++ reg_base; ++ u8 bit = reset_data->reg_data[id].rstctrl_bit; ++ u32 val = readl(reg); ++ ++ val &= ~(1 << bit); ++ writel(val, reg); ++ return 0; ++} ++ ++static struct reset_control_ops ti_reset_ops = { ++ .deassert = ti_reset_deassert, ++ .is_reset = ti_reset_is_reset, ++ .clear_reset = ti_reset_clear_reset, ++}; ++ ++static struct reset_controller_dev ti_reset_controller = { ++ .ops = &ti_reset_ops, ++}; ++ ++static const struct of_device_id ti_reset_of_match[] = { ++ { .compatible = "ti,am3352-prcm", .data = &am335x_reset_data,}, ++ { .compatible = "ti,am4372-prcm", .data = &am43x_reset_data,}, ++ { .compatible = "ti,dra7-prcm", .data = &dra7_reset_data,}, ++ {}, ++}; ++ ++static int ti_reset_probe(struct platform_device *pdev) ++{ ++ struct resource *res; ++ const struct of_device_id *id; ++ ++ res = platform_get_resource(pdev, IORESOURCE_MEM, 0); ++ reg_base = devm_ioremap_resource(&pdev->dev, res); ++ if (IS_ERR(reg_base)) ++ return PTR_ERR(reg_base); ++ ++ ti_reset_controller.of_node = pdev->dev.of_node; ++ id = of_match_device(ti_reset_of_match, &pdev->dev); ++ reset_data = id->data; ++ ti_reset_controller.nr_resets = reset_data->nr_resets; ++ ++ reset_controller_register(&ti_reset_controller); ++ ++ return 0; ++} ++ ++static int ti_reset_remove(struct platform_device *pdev) ++{ ++ reset_controller_unregister(&ti_reset_controller); ++ ++ return 0; ++} ++ ++static struct platform_driver ti_reset_driver = { ++ .probe = ti_reset_probe, ++ .remove = ti_reset_remove, ++ .driver = { ++ .name = DRIVER_NAME, ++ .owner = THIS_MODULE, ++ .of_match_table = of_match_ptr(ti_reset_of_match), ++ }, ++}; ++module_platform_driver(ti_reset_driver); ++ ++MODULE_DESCRIPTION("PRCM reset driver for TI SoC's"); ++MODULE_LICENSE("GPL v2"); ++MODULE_ALIAS("platform:" DRIVER_NAME); +--- a/drivers/rtc/rtc-omap.c ++++ b/drivers/rtc/rtc-omap.c +@@ -393,6 +393,10 @@ static int __init omap_rtc_probe(struct + */ + rtc_write(0, OMAP_RTC_INTERRUPTS_REG); + ++ /* Selecting CLK cource for RTC */ ++ rtc_writel((1 << 3) | (1 << 6), OMAP_RTC_OSC_REG); ++ rtc_writel(0x3, OMAP_RTC_IRQWAKEEN); ++ + /* clear old status */ + reg = rtc_read(OMAP_RTC_STATUS_REG); + if (reg & (u8) OMAP_RTC_STATUS_POWER_UP) { +--- a/drivers/spi/spi-ti-qspi.c ++++ b/drivers/spi/spi-ti-qspi.c +@@ -41,14 +41,13 @@ struct ti_qspi_regs { + struct ti_qspi { + struct completion transfer_complete; + +- /* IRQ synchronization */ +- spinlock_t lock; +- + /* list synchronization */ + struct mutex list_lock; + + struct spi_master *master; + void __iomem *base; ++ void __iomem *ctrl_base; ++ void __iomem *mmap_base; + struct clk *fclk; + struct device *dev; + +@@ -57,7 +56,9 @@ struct ti_qspi { + u32 spi_max_frequency; + u32 cmd; + u32 dc; +- u32 stat; ++ ++ bool memory_mapped; ++ bool ctrl_mod; + }; + + #define QSPI_PID (0x0) +@@ -113,6 +114,23 @@ struct ti_qspi { + #define QSPI_CSPOL(n) (1 << (1 + n * 8)) + #define QSPI_CKPOL(n) (1 << (n * 8)) + ++#define MM_SWITCH 0x01 ++#define MEM_CS 0x100 ++#define MEM_CS_DIS 0xfffff0ff ++ ++#define QSPI_CMD_RD (0x3 << 0) ++#define QSPI_CMD_DUAL_RD (0x3b << 0) ++#define QSPI_CMD_QUAD_RD (0x6b << 0) ++#define QSPI_CMD_READ_FAST (0x0b << 0) ++#define QSPI_SETUP0_A_BYTES (0x3 << 8) ++#define QSPI_SETUP0_NO_BITS (0x0 << 10) ++#define QSPI_SETUP0_8_BITS (0x1 << 10) ++#define QSPI_SETUP0_RD_NORMAL (0x0 << 12) ++#define QSPI_SETUP0_RD_DUAL (0x1 << 12) ++#define QSPI_SETUP0_RD_QUAD (0x3 << 12) ++#define QSPI_CMD_WRITE (0x2 << 16) ++#define QSPI_NUM_DUMMY_BITS (0x0 << 24) ++ + #define QSPI_FRAME 4096 + + #define QSPI_AUTOSUSPEND_TIMEOUT 2000 +@@ -129,12 +147,37 @@ static inline void ti_qspi_write(struct + writel(val, qspi->base + reg); + } + ++void enable_qspi_memory_mapped(struct ti_qspi *qspi) ++{ ++ u32 val; ++ ++ ti_qspi_write(qspi, MM_SWITCH, QSPI_SPI_SWITCH_REG); ++ if (qspi->ctrl_mod) { ++ val = readl(qspi->ctrl_base); ++ val |= MEM_CS; ++ writel(val, qspi->ctrl_base); ++ } ++} ++ ++void disable_qspi_memory_mapped(struct ti_qspi *qspi) ++{ ++ u32 val; ++ ++ ti_qspi_write(qspi, ~MM_SWITCH, QSPI_SPI_SWITCH_REG); ++ if (qspi->ctrl_mod) { ++ val = readl(qspi->ctrl_base); ++ val |= MEM_CS_DIS; ++ writel(val, qspi->ctrl_base); ++ } ++} ++ + static int ti_qspi_setup(struct spi_device *spi) + { + struct ti_qspi *qspi = spi_master_get_devdata(spi->master); + struct ti_qspi_regs *ctx_reg = &qspi->ctx_reg; + int clk_div = 0, ret; +- u32 clk_ctrl_reg, clk_rate, clk_mask; ++ u32 clk_ctrl_reg, clk_rate, clk_mask, memval = 0; ++ qspi->dc = 0; + + if (spi->master->busy) { + dev_dbg(qspi->dev, "master busy doing other trasnfers\n"); +@@ -182,6 +225,37 @@ static int ti_qspi_setup(struct spi_devi + ti_qspi_write(qspi, clk_mask, QSPI_SPI_CLOCK_CNTRL_REG); + ctx_reg->clkctrl = clk_mask; + ++ if (spi->mode & SPI_CPHA) ++ qspi->dc |= QSPI_CKPHA(spi->chip_select); ++ if (spi->mode & SPI_CPOL) ++ qspi->dc |= QSPI_CKPOL(spi->chip_select); ++ if (spi->mode & SPI_CS_HIGH) ++ qspi->dc |= QSPI_CSPOL(spi->chip_select); ++ ++ ti_qspi_write(qspi, qspi->dc, QSPI_SPI_DC_REG); ++ ++ if (qspi->memory_mapped) { ++ switch (spi->mode) { ++ case SPI_TX_DUAL: ++ memval |= (QSPI_CMD_DUAL_RD | QSPI_SETUP0_A_BYTES | ++ QSPI_SETUP0_8_BITS | QSPI_SETUP0_RD_DUAL | ++ QSPI_CMD_WRITE | QSPI_NUM_DUMMY_BITS); ++ break; ++ case SPI_TX_QUAD: ++ memval |= (QSPI_CMD_QUAD_RD | QSPI_SETUP0_A_BYTES | ++ QSPI_SETUP0_8_BITS | QSPI_SETUP0_RD_QUAD | ++ QSPI_CMD_WRITE | QSPI_NUM_DUMMY_BITS); ++ break; ++ default: ++ memval |= (QSPI_CMD_RD | QSPI_SETUP0_A_BYTES | ++ QSPI_SETUP0_NO_BITS | QSPI_SETUP0_RD_NORMAL | ++ QSPI_CMD_WRITE | QSPI_NUM_DUMMY_BITS); ++ break; ++ } ++ ti_qspi_write(qspi, memval, QSPI_SPI_SETUP0_REG); ++ spi->mode |= SPI_RX_MMAP; ++ } ++ + pm_runtime_mark_last_busy(qspi->dev); + ret = pm_runtime_put_autosuspend(qspi->dev); + if (ret < 0) { +@@ -344,16 +418,7 @@ static int ti_qspi_start_transfer_one(st + struct spi_transfer *t; + int status = 0, ret; + int frame_length; +- +- /* setup device control reg */ +- qspi->dc = 0; +- +- if (spi->mode & SPI_CPHA) +- qspi->dc |= QSPI_CKPHA(spi->chip_select); +- if (spi->mode & SPI_CPOL) +- qspi->dc |= QSPI_CKPOL(spi->chip_select); +- if (spi->mode & SPI_CS_HIGH) +- qspi->dc |= QSPI_CSPOL(spi->chip_select); ++ size_t from = 0; + + frame_length = (m->frame_length << 3) / spi->bits_per_word; + +@@ -366,11 +431,20 @@ static int ti_qspi_start_transfer_one(st + qspi->cmd |= QSPI_WC_CMD_INT_EN; + + ti_qspi_write(qspi, QSPI_WC_INT_EN, QSPI_INTR_ENABLE_SET_REG); +- ti_qspi_write(qspi, qspi->dc, QSPI_SPI_DC_REG); + + mutex_lock(&qspi->list_lock); + + list_for_each_entry(t, &m->transfers, transfer_list) { ++ if (t->memory_map) { ++ if (t->tx_buf) { ++ from = t->len; ++ continue; ++ } ++ enable_qspi_memory_mapped(qspi); ++ memcpy(t->rx_buf, qspi->mmap_base + from, t->len); ++ disable_qspi_memory_mapped(qspi); ++ goto out; ++ } + qspi->cmd |= QSPI_WLEN(t->bits_per_word); + + ret = qspi_transfer_msg(qspi, t); +@@ -383,6 +457,7 @@ static int ti_qspi_start_transfer_one(st + m->actual_length += t->len; + } + ++out: + mutex_unlock(&qspi->list_lock); + + m->status = status; +@@ -397,13 +472,12 @@ static irqreturn_t ti_qspi_isr(int irq, + { + struct ti_qspi *qspi = dev_id; + u16 int_stat; ++ u32 stat; + + irqreturn_t ret = IRQ_HANDLED; + +- spin_lock(&qspi->lock); +- + int_stat = ti_qspi_read(qspi, QSPI_INTR_STATUS_ENABLED_CLEAR); +- qspi->stat = ti_qspi_read(qspi, QSPI_SPI_STATUS_REG); ++ stat = ti_qspi_read(qspi, QSPI_SPI_STATUS_REG); + + if (!int_stat) { + dev_dbg(qspi->dev, "No IRQ triggered\n"); +@@ -411,35 +485,14 @@ static irqreturn_t ti_qspi_isr(int irq, + goto out; + } + +- ret = IRQ_WAKE_THREAD; +- +- ti_qspi_write(qspi, QSPI_WC_INT_DISABLE, QSPI_INTR_ENABLE_CLEAR_REG); + ti_qspi_write(qspi, QSPI_WC_INT_DISABLE, + QSPI_INTR_STATUS_ENABLED_CLEAR); +- ++ if (stat & WC) ++ complete(&qspi->transfer_complete); + out: +- spin_unlock(&qspi->lock); +- + return ret; + } + +-static irqreturn_t ti_qspi_threaded_isr(int this_irq, void *dev_id) +-{ +- struct ti_qspi *qspi = dev_id; +- unsigned long flags; +- +- spin_lock_irqsave(&qspi->lock, flags); +- +- if (qspi->stat & WC) +- complete(&qspi->transfer_complete); +- +- spin_unlock_irqrestore(&qspi->lock, flags); +- +- ti_qspi_write(qspi, QSPI_WC_INT_EN, QSPI_INTR_ENABLE_SET_REG); +- +- return IRQ_HANDLED; +-} +- + static int ti_qspi_runtime_resume(struct device *dev) + { + struct ti_qspi *qspi; +@@ -463,7 +516,7 @@ static int ti_qspi_probe(struct platform + { + struct ti_qspi *qspi; + struct spi_master *master; +- struct resource *r; ++ struct resource *r, *res_ctrl, *res_mmap; + struct device_node *np = pdev->dev.of_node; + u32 max_freq; + int ret = 0, num_cs, irq; +@@ -472,7 +525,7 @@ static int ti_qspi_probe(struct platform + if (!master) + return -ENOMEM; + +- master->mode_bits = SPI_CPOL | SPI_CPHA; ++ master->mode_bits = SPI_CPOL | SPI_CPHA | SPI_RX_QUAD | SPI_RX_MMAP; + + master->bus_num = -1; + master->flags = SPI_MASTER_HALF_DUPLEX; +@@ -491,7 +544,16 @@ static int ti_qspi_probe(struct platform + qspi->master = master; + qspi->dev = &pdev->dev; + +- r = platform_get_resource(pdev, IORESOURCE_MEM, 0); ++ r = platform_get_resource_byname(pdev, IORESOURCE_MEM, "qspi_base"); ++ if (r == NULL) { ++ dev_err(&pdev->dev, "missing platform resources data\n"); ++ return -ENODEV; ++ } ++ ++ res_mmap = platform_get_resource_byname(pdev, ++ IORESOURCE_MEM, "qspi_mmap"); ++ res_ctrl = platform_get_resource_byname(pdev, ++ IORESOURCE_MEM, "qspi_ctrlmod"); + + irq = platform_get_irq(pdev, 0); + if (irq < 0) { +@@ -499,7 +561,6 @@ static int ti_qspi_probe(struct platform + return irq; + } + +- spin_lock_init(&qspi->lock); + mutex_init(&qspi->list_lock); + + qspi->base = devm_ioremap_resource(&pdev->dev, r); +@@ -508,8 +569,24 @@ static int ti_qspi_probe(struct platform + goto free_master; + } + +- ret = devm_request_threaded_irq(&pdev->dev, irq, ti_qspi_isr, +- ti_qspi_threaded_isr, 0, ++ if (res_ctrl) { ++ qspi->ctrl_mod = true; ++ qspi->ctrl_base = devm_ioremap_resource(&pdev->dev, res_ctrl); ++ if (IS_ERR(qspi->ctrl_base)) { ++ ret = PTR_ERR(qspi->ctrl_base); ++ goto free_master; ++ } ++ } ++ ++ if (res_mmap) { ++ qspi->mmap_base = devm_ioremap_resource(&pdev->dev, res_mmap); ++ if (IS_ERR(qspi->mmap_base)) { ++ ret = PTR_ERR(qspi->mmap_base); ++ goto free_master; ++ } ++ } ++ ++ ret = devm_request_irq(&pdev->dev, irq, ti_qspi_isr, 0, + dev_name(&pdev->dev), qspi); + if (ret < 0) { + dev_err(&pdev->dev, "Failed to register ISR for IRQ %d\n", +@@ -532,6 +609,9 @@ static int ti_qspi_probe(struct platform + if (!of_property_read_u32(np, "spi-max-frequency", &max_freq)) + qspi->spi_max_frequency = max_freq; + ++ if (of_property_read_bool(np, "mmap_read")) ++ qspi->memory_mapped = true; ++ + ret = spi_register_master(master); + if (ret) + goto free_master; +@@ -547,6 +627,7 @@ static int ti_qspi_remove(struct platfor + { + struct ti_qspi *qspi = platform_get_drvdata(pdev); + ++ ti_qspi_write(qspi, QSPI_WC_INT_DISABLE, QSPI_INTR_ENABLE_CLEAR_REG); + spi_unregister_master(qspi->master); + + return 0; +--- a/drivers/tty/serial/omap-serial.c ++++ b/drivers/tty/serial/omap-serial.c +@@ -240,8 +240,8 @@ serial_omap_baud_is_mode16(struct uart_p + { + unsigned int n13 = port->uartclk / (13 * baud); + unsigned int n16 = port->uartclk / (16 * baud); +- int baudAbsDiff13 = baud - (port->uartclk / (13 * n13)); +- int baudAbsDiff16 = baud - (port->uartclk / (16 * n16)); ++ int baudAbsDiff13 = n13 ? (baud - (port->uartclk / (13 * n13))) : INT_MAX; ++ int baudAbsDiff16 = n16 ? (baud - (port->uartclk / (16 * n16))) : INT_MAX; + if(baudAbsDiff13 < 0) + baudAbsDiff13 = -baudAbsDiff13; + if(baudAbsDiff16 < 0) +--- a/drivers/usb/dwc3/core.c ++++ b/drivers/usb/dwc3/core.c +@@ -80,8 +80,6 @@ static void dwc3_core_soft_reset(struct + reg |= DWC3_GUSB2PHYCFG_PHYSOFTRST; + dwc3_writel(dwc->regs, DWC3_GUSB2PHYCFG(0), reg); + +- usb_phy_init(dwc->usb2_phy); +- usb_phy_init(dwc->usb3_phy); + mdelay(100); + + /* Clear USB3 PHY reset */ +@@ -343,6 +341,11 @@ static void dwc3_core_exit(struct dwc3 * + { + usb_phy_shutdown(dwc->usb2_phy); + usb_phy_shutdown(dwc->usb3_phy); ++ ++ if (dwc->usb2_generic_phy) ++ phy_power_off(dwc->usb2_generic_phy); ++ if (dwc->usb3_generic_phy) ++ phy_power_off(dwc->usb3_generic_phy); + } + + #define DWC3_ALIGN_MASK (16 - 1) +@@ -387,16 +390,102 @@ static int dwc3_probe(struct platform_de + if (node) { + dwc->maximum_speed = of_usb_get_maximum_speed(node); + +- dwc->usb2_phy = devm_usb_get_phy_by_phandle(dev, "usb-phy", 0); +- dwc->usb3_phy = devm_usb_get_phy_by_phandle(dev, "usb-phy", 1); ++ switch (dwc->maximum_speed) { ++ case USB_SPEED_SUPER: ++ if (of_property_read_bool(node, "usb-phy")) { ++ dwc->usb2_phy = devm_usb_get_phy_by_phandle(dev, ++ "usb-phy", 0); ++ if (IS_ERR(dwc->usb2_phy)) ++ return PTR_ERR(dwc->usb2_phy); ++ dwc->usb3_phy = devm_usb_get_phy_by_phandle(dev, ++ "usb-phy", 1); ++ if (IS_ERR(dwc->usb3_phy)) ++ return PTR_ERR(dwc->usb3_phy); ++ } else { ++ dwc->usb2_phy = NULL; ++ dwc->usb3_phy = NULL; ++ } ++ ++ if (of_property_read_bool(node, "phys")) { ++ dwc->usb2_generic_phy = devm_phy_get(dev, ++ "usb2-phy"); ++ if (IS_ERR(dwc->usb2_generic_phy)) { ++ dev_err(dev, "no usb2 phy configured"); ++ return PTR_ERR(dwc->usb2_generic_phy); ++ } ++ ++ dwc->usb3_generic_phy = devm_phy_get(dev, ++ "usb3-phy"); ++ if (IS_ERR(dwc->usb3_generic_phy)) { ++ dev_err(dev, "no usb3 phy configured"); ++ return PTR_ERR(dwc->usb3_generic_phy); ++ } ++ } else { ++ dwc->usb2_generic_phy = NULL; ++ dwc->usb3_generic_phy = NULL; ++ } ++ break; ++ case USB_SPEED_HIGH: ++ case USB_SPEED_FULL: ++ case USB_SPEED_LOW: ++ dwc->usb3_phy = NULL; ++ dwc->usb3_generic_phy = NULL; ++ if (of_property_read_bool(node, "usb-phy")) { ++ dwc->usb2_phy = devm_usb_get_phy_by_phandle(dev, ++ "usb-phy", 0); ++ if (IS_ERR(dwc->usb2_phy)) ++ return PTR_ERR(dwc->usb2_phy); ++ } else { ++ dwc->usb2_phy = NULL; ++ } ++ if (of_property_read_bool(node, "phys")) { ++ dwc->usb2_generic_phy = devm_phy_get(dev, ++ "usb2-phy"); ++ if (IS_ERR(dwc->usb2_generic_phy)) { ++ dev_err(dev, "no usb2 phy configured"); ++ return PTR_ERR(dwc->usb2_generic_phy); ++ } ++ } else { ++ dwc->usb2_generic_phy = NULL; ++ } ++ break; ++ } + + dwc->needs_fifo_resize = of_property_read_bool(node, "tx-fifo-resize"); + dwc->dr_mode = of_usb_get_dr_mode(node); + } else if (pdata) { + dwc->maximum_speed = pdata->maximum_speed; + +- dwc->usb2_phy = devm_usb_get_phy(dev, USB_PHY_TYPE_USB2); +- dwc->usb3_phy = devm_usb_get_phy(dev, USB_PHY_TYPE_USB3); ++ switch (dwc->maximum_speed) { ++ case USB_SPEED_SUPER: ++ if (pdata->has_phy) { ++ dwc->usb2_phy = devm_usb_get_phy(dev, ++ USB_PHY_TYPE_USB2); ++ if (IS_ERR(dwc->usb2_phy)) ++ return PTR_ERR(dwc->usb2_phy); ++ dwc->usb3_phy = devm_usb_get_phy(dev, ++ USB_PHY_TYPE_USB3); ++ if (IS_ERR(dwc->usb3_phy)) ++ return PTR_ERR(dwc->usb3_phy); ++ } else { ++ dwc->usb2_phy = NULL; ++ dwc->usb3_phy = NULL; ++ } ++ break; ++ case USB_SPEED_HIGH: ++ case USB_SPEED_FULL: ++ case USB_SPEED_LOW: ++ dwc->usb3_phy = NULL; ++ if (pdata->has_phy) { ++ dwc->usb2_phy = devm_usb_get_phy(dev, ++ USB_PHY_TYPE_USB2); ++ if (IS_ERR(dwc->usb2_phy)) ++ return PTR_ERR(dwc->usb2_phy); ++ } else { ++ dwc->usb2_phy = NULL; ++ } ++ break; ++ } + + dwc->needs_fifo_resize = pdata->tx_fifo_resize; + dwc->dr_mode = pdata->dr_mode; +@@ -409,36 +498,6 @@ static int dwc3_probe(struct platform_de + if (dwc->maximum_speed == USB_SPEED_UNKNOWN) + dwc->maximum_speed = USB_SPEED_SUPER; + +- if (IS_ERR(dwc->usb2_phy)) { +- ret = PTR_ERR(dwc->usb2_phy); +- +- /* +- * if -ENXIO is returned, it means PHY layer wasn't +- * enabled, so it makes no sense to return -EPROBE_DEFER +- * in that case, since no PHY driver will ever probe. +- */ +- if (ret == -ENXIO) +- return ret; +- +- dev_err(dev, "no usb2 phy configured\n"); +- return -EPROBE_DEFER; +- } +- +- if (IS_ERR(dwc->usb3_phy)) { +- ret = PTR_ERR(dwc->usb3_phy); +- +- /* +- * if -ENXIO is returned, it means PHY layer wasn't +- * enabled, so it makes no sense to return -EPROBE_DEFER +- * in that case, since no PHY driver will ever probe. +- */ +- if (ret == -ENXIO) +- return ret; +- +- dev_err(dev, "no usb3 phy configured\n"); +- return -EPROBE_DEFER; +- } +- + dwc->xhci_resources[0].start = res->start; + dwc->xhci_resources[0].end = dwc->xhci_resources[0].start + + DWC3_XHCI_REGS_END; +@@ -455,9 +514,20 @@ static int dwc3_probe(struct platform_de + if (IS_ERR(regs)) + return PTR_ERR(regs); + ++ usb_phy_init(dwc->usb2_phy); ++ usb_phy_init(dwc->usb3_phy); + usb_phy_set_suspend(dwc->usb2_phy, 0); + usb_phy_set_suspend(dwc->usb3_phy, 0); + ++ if (dwc->usb2_generic_phy) { ++ phy_init(dwc->usb2_generic_phy); ++ phy_power_on(dwc->usb2_generic_phy); ++ } ++ if (dwc->usb3_generic_phy) { ++ phy_init(dwc->usb3_generic_phy); ++ phy_power_on(dwc->usb3_generic_phy); ++ } ++ + spin_lock_init(&dwc->lock); + platform_set_drvdata(pdev, dwc); + +@@ -584,7 +654,12 @@ static int dwc3_remove(struct platform_d + usb_phy_set_suspend(dwc->usb2_phy, 1); + usb_phy_set_suspend(dwc->usb3_phy, 1); + +- pm_runtime_put(&pdev->dev); ++ if (dwc->usb2_generic_phy) ++ phy_power_off(dwc->usb2_generic_phy); ++ if (dwc->usb3_generic_phy) ++ phy_power_off(dwc->usb3_generic_phy); ++ ++ pm_runtime_put_sync(&pdev->dev); + pm_runtime_disable(&pdev->dev); + + dwc3_debugfs_exit(dwc); +@@ -681,6 +756,11 @@ static int dwc3_suspend(struct device *d + usb_phy_shutdown(dwc->usb3_phy); + usb_phy_shutdown(dwc->usb2_phy); + ++ if (dwc->usb2_generic_phy) ++ phy_exit(dwc->usb2_generic_phy); ++ if (dwc->usb3_generic_phy) ++ phy_exit(dwc->usb3_generic_phy); ++ + return 0; + } + +@@ -691,6 +771,12 @@ static int dwc3_resume(struct device *de + + usb_phy_init(dwc->usb3_phy); + usb_phy_init(dwc->usb2_phy); ++ ++ if (dwc->usb2_generic_phy) ++ phy_init(dwc->usb2_generic_phy); ++ if (dwc->usb3_generic_phy) ++ phy_init(dwc->usb3_generic_phy); ++ + msleep(100); + + spin_lock_irqsave(&dwc->lock, flags); +--- a/drivers/usb/dwc3/core.h ++++ b/drivers/usb/dwc3/core.h +@@ -31,6 +31,8 @@ + #include <linux/usb/gadget.h> + #include <linux/usb/otg.h> + ++#include <linux/phy/phy.h> ++ + /* Global constants */ + #define DWC3_EP0_BOUNCE_SIZE 512 + #define DWC3_ENDPOINTS_NUM 32 +@@ -613,6 +615,8 @@ struct dwc3_scratchpad_array { + * @dr_mode: requested mode of operation + * @usb2_phy: pointer to USB2 PHY + * @usb3_phy: pointer to USB3 PHY ++ * @usb2_generic_phy: pointer to USB2 PHY ++ * @usb3_generic_phy: pointer to USB3 PHY + * @dcfg: saved contents of DCFG register + * @gctl: saved contents of GCTL register + * @is_selfpowered: true when we are selfpowered +@@ -665,6 +669,9 @@ struct dwc3 { + struct usb_phy *usb2_phy; + struct usb_phy *usb3_phy; + ++ struct phy *usb2_generic_phy; ++ struct phy *usb3_generic_phy; ++ + void __iomem *regs; + size_t regs_size; + +--- a/drivers/usb/dwc3/dwc3-omap.c ++++ b/drivers/usb/dwc3/dwc3-omap.c +@@ -535,7 +535,7 @@ static int dwc3_omap_probe(struct platfo + edev = of_extcon_get_extcon_dev(dev, 0); + if (IS_ERR(edev)) { + dev_vdbg(dev, "couldn't get extcon device\n"); +- ret = PTR_ERR(edev); ++ ret = -EPROBE_DEFER; + goto err2; + } + +--- a/drivers/usb/dwc3/dwc3-pci.c ++++ b/drivers/usb/dwc3/dwc3-pci.c +@@ -165,7 +165,6 @@ static int dwc3_pci_probe(struct pci_dev + return 0; + + err3: +- pci_set_drvdata(pci, NULL); + platform_device_put(dwc3); + err1: + pci_disable_device(pci); +@@ -180,7 +179,6 @@ static void dwc3_pci_remove(struct pci_d + platform_device_unregister(glue->dwc3); + platform_device_unregister(glue->usb2_phy); + platform_device_unregister(glue->usb3_phy); +- pci_set_drvdata(pci, NULL); + pci_disable_device(pci); + } + +--- a/drivers/usb/dwc3/Kconfig ++++ b/drivers/usb/dwc3/Kconfig +@@ -1,6 +1,9 @@ + config USB_DWC3 + tristate "DesignWare USB3 DRD Core Support" + depends on (USB || USB_GADGET) && HAS_DMA ++ depends on EXTCON ++ select USB_PHY ++ select GENERIC_PHY + select USB_XHCI_PLATFORM if USB_SUPPORT && USB_XHCI_HCD + help + Say Y or M here if your system has a Dual Role SuperSpeed +--- a/drivers/usb/dwc3/platform_data.h ++++ b/drivers/usb/dwc3/platform_data.h +@@ -24,4 +24,5 @@ struct dwc3_platform_data { + enum usb_device_speed maximum_speed; + enum usb_dr_mode dr_mode; + bool tx_fifo_resize; ++ bool has_phy; + }; +--- a/drivers/usb/gadget/acm_ms.c ++++ b/drivers/usb/gadget/acm_ms.c +@@ -31,16 +31,7 @@ + #define ACM_MS_VENDOR_NUM 0x1d6b /* Linux Foundation */ + #define ACM_MS_PRODUCT_NUM 0x0106 /* Composite Gadget: ACM + MS*/ + +-/*-------------------------------------------------------------------------*/ +- +-/* +- * Kbuild is not very cooperative with respect to linking separately +- * compiled library objects into one module. So for now we won't use +- * separate compilation ... ensuring init/exit sections work to shrink +- * the runtime footprint, and giving us at least some parts of what +- * a "gcc --combine ... part1.c part2.c part3.c ... " build would. +- */ +-#include "f_mass_storage.c" ++#include "f_mass_storage.h" + + /*-------------------------------------------------------------------------*/ + USB_GADGET_COMPOSITE_OPTIONS(); +@@ -104,18 +95,35 @@ static struct usb_gadget_strings *dev_st + /****************************** Configurations ******************************/ + + static struct fsg_module_parameters fsg_mod_data = { .stall = 1 }; +-FSG_MODULE_PARAMETERS(/* no prefix */, fsg_mod_data); ++#ifdef CONFIG_USB_GADGET_DEBUG_FILES ++ ++static unsigned int fsg_num_buffers = CONFIG_USB_GADGET_STORAGE_NUM_BUFFERS; + +-static struct fsg_common fsg_common; ++#else ++ ++/* ++ * Number of buffers we will use. ++ * 2 is usually enough for good buffering pipeline ++ */ ++#define fsg_num_buffers CONFIG_USB_GADGET_STORAGE_NUM_BUFFERS ++ ++#endif /* CONFIG_USB_DEBUG */ ++ ++FSG_MODULE_PARAMETERS(/* no prefix */, fsg_mod_data); + + /*-------------------------------------------------------------------------*/ + static struct usb_function *f_acm; + static struct usb_function_instance *f_acm_inst; ++ ++static struct usb_function_instance *fi_msg; ++static struct usb_function *f_msg; ++ + /* + * We _always_ have both ACM and mass storage functions. + */ + static int __init acm_ms_do_config(struct usb_configuration *c) + { ++ struct fsg_opts *opts; + int status; + + if (gadget_is_otg(c->cdev->gadget)) { +@@ -123,31 +131,37 @@ static int __init acm_ms_do_config(struc + c->bmAttributes |= USB_CONFIG_ATT_WAKEUP; + } + +- f_acm_inst = usb_get_function_instance("acm"); +- if (IS_ERR(f_acm_inst)) +- return PTR_ERR(f_acm_inst); ++ opts = fsg_opts_from_func_inst(fi_msg); + + f_acm = usb_get_function(f_acm_inst); +- if (IS_ERR(f_acm)) { +- status = PTR_ERR(f_acm); +- goto err_func; ++ if (IS_ERR(f_acm)) ++ return PTR_ERR(f_acm); ++ ++ f_msg = usb_get_function(fi_msg); ++ if (IS_ERR(f_msg)) { ++ status = PTR_ERR(f_msg); ++ goto put_acm; + } + + status = usb_add_function(c, f_acm); + if (status < 0) +- goto err_conf; ++ goto put_msg; + +- status = fsg_bind_config(c->cdev, c, &fsg_common); +- if (status < 0) +- goto err_fsg; ++ status = fsg_common_run_thread(opts->common); ++ if (status) ++ goto remove_acm; ++ ++ status = usb_add_function(c, f_msg); ++ if (status) ++ goto remove_acm; + + return 0; +-err_fsg: ++remove_acm: + usb_remove_function(c, f_acm); +-err_conf: ++put_msg: ++ usb_put_function(f_msg); ++put_acm: + usb_put_function(f_acm); +-err_func: +- usb_put_function_instance(f_acm_inst); + return status; + } + +@@ -163,45 +177,82 @@ static struct usb_configuration acm_ms_c + static int __init acm_ms_bind(struct usb_composite_dev *cdev) + { + struct usb_gadget *gadget = cdev->gadget; ++ struct fsg_opts *opts; ++ struct fsg_config config; + int status; +- void *retp; + +- /* set up mass storage function */ +- retp = fsg_common_from_params(&fsg_common, cdev, &fsg_mod_data); +- if (IS_ERR(retp)) { +- status = PTR_ERR(retp); +- return PTR_ERR(retp); ++ f_acm_inst = usb_get_function_instance("acm"); ++ if (IS_ERR(f_acm_inst)) ++ return PTR_ERR(f_acm_inst); ++ ++ fi_msg = usb_get_function_instance("mass_storage"); ++ if (IS_ERR(fi_msg)) { ++ status = PTR_ERR(fi_msg); ++ goto fail_get_msg; + } + ++ /* set up mass storage function */ ++ fsg_config_from_params(&config, &fsg_mod_data, fsg_num_buffers); ++ opts = fsg_opts_from_func_inst(fi_msg); ++ ++ opts->no_configfs = true; ++ status = fsg_common_set_num_buffers(opts->common, fsg_num_buffers); ++ if (status) ++ goto fail; ++ ++ status = fsg_common_set_nluns(opts->common, config.nluns); ++ if (status) ++ goto fail_set_nluns; ++ ++ status = fsg_common_set_cdev(opts->common, cdev, config.can_stall); ++ if (status) ++ goto fail_set_cdev; ++ ++ fsg_common_set_sysfs(opts->common, true); ++ status = fsg_common_create_luns(opts->common, &config); ++ if (status) ++ goto fail_set_cdev; ++ ++ fsg_common_set_inquiry_string(opts->common, config.vendor_name, ++ config.product_name); + /* + * Allocate string descriptor numbers ... note that string + * contents can be overridden by the composite_dev glue. + */ + status = usb_string_ids_tab(cdev, strings_dev); + if (status < 0) +- goto fail1; ++ goto fail_string_ids; + device_desc.iManufacturer = strings_dev[USB_GADGET_MANUFACTURER_IDX].id; + device_desc.iProduct = strings_dev[USB_GADGET_PRODUCT_IDX].id; + + /* register our configuration */ + status = usb_add_config(cdev, &acm_ms_config_driver, acm_ms_do_config); + if (status < 0) +- goto fail1; ++ goto fail_string_ids; + + usb_composite_overwrite_options(cdev, &coverwrite); + dev_info(&gadget->dev, "%s, version: " DRIVER_VERSION "\n", + DRIVER_DESC); +- fsg_common_put(&fsg_common); + return 0; + + /* error recovery */ +-fail1: +- fsg_common_put(&fsg_common); ++fail_string_ids: ++ fsg_common_remove_luns(opts->common); ++fail_set_cdev: ++ fsg_common_free_luns(opts->common); ++fail_set_nluns: ++ fsg_common_free_buffers(opts->common); ++fail: ++ usb_put_function_instance(fi_msg); ++fail_get_msg: ++ usb_put_function_instance(f_acm_inst); + return status; + } + + static int __exit acm_ms_unbind(struct usb_composite_dev *cdev) + { ++ usb_put_function(f_msg); ++ usb_put_function_instance(fi_msg); + usb_put_function(f_acm); + usb_put_function_instance(f_acm_inst); + return 0; +--- a/drivers/usb/gadget/amd5536udc.c ++++ b/drivers/usb/gadget/amd5536udc.c +@@ -3078,8 +3078,6 @@ static void udc_pci_remove(struct pci_de + if (dev->active) + pci_disable_device(pdev); + +- pci_set_drvdata(pdev, NULL); +- + udc_remove(dev); + } + +--- a/drivers/usb/gadget/configfs.c ++++ b/drivers/usb/gadget/configfs.c +@@ -557,7 +557,7 @@ static struct config_group *function_mak + + fi = usb_get_function_instance(func_name); + if (IS_ERR(fi)) +- return ERR_PTR(PTR_ERR(fi)); ++ return ERR_CAST(fi); + + ret = config_item_set_name(&fi->group.cg_item, name); + if (ret) { +@@ -991,6 +991,14 @@ static struct configfs_subsystem gadget_ + .su_mutex = __MUTEX_INITIALIZER(gadget_subsys.su_mutex), + }; + ++void unregister_gadget_item(struct config_item *item) ++{ ++ struct gadget_info *gi = to_gadget_info(item); ++ ++ unregister_gadget(gi); ++} ++EXPORT_SYMBOL(unregister_gadget_item); ++ + static int __init gadget_cfs_init(void) + { + int ret; +--- /dev/null ++++ b/drivers/usb/gadget/configfs.h +@@ -0,0 +1,6 @@ ++#ifndef USB__GADGET__CONFIGFS__H ++#define USB__GADGET__CONFIGFS__H ++ ++void unregister_gadget_item(struct config_item *item); ++ ++#endif /* USB__GADGET__CONFIGFS__H */ +--- a/drivers/usb/gadget/f_mass_storage.c ++++ b/drivers/usb/gadget/f_mass_storage.c +@@ -213,12 +213,14 @@ + #include <linux/spinlock.h> + #include <linux/string.h> + #include <linux/freezer.h> ++#include <linux/module.h> + + #include <linux/usb/ch9.h> + #include <linux/usb/gadget.h> + #include <linux/usb/composite.h> + + #include "gadget_chips.h" ++#include "configfs.h" + + + /*------------------------------------------------------------------------*/ +@@ -228,26 +230,30 @@ + + static const char fsg_string_interface[] = "Mass Storage"; + +-#include "storage_common.c" ++#include "storage_common.h" ++#include "f_mass_storage.h" + ++/* Static strings, in UTF-8 (for simplicity we use only ASCII characters) */ ++static struct usb_string fsg_strings[] = { ++ {FSG_STRING_INTERFACE, fsg_string_interface}, ++ {} ++}; ++ ++static struct usb_gadget_strings fsg_stringtab = { ++ .language = 0x0409, /* en-us */ ++ .strings = fsg_strings, ++}; ++ ++static struct usb_gadget_strings *fsg_strings_array[] = { ++ &fsg_stringtab, ++ NULL, ++}; + + /*-------------------------------------------------------------------------*/ + + struct fsg_dev; + struct fsg_common; + +-/* FSF callback functions */ +-struct fsg_operations { +- /* +- * Callback function to call when thread exits. If no +- * callback is set or it returns value lower then zero MSF +- * will force eject all LUNs it operates on (including those +- * marked as non-removable or with prevent_medium_removal flag +- * set). +- */ +- int (*thread_exits)(struct fsg_common *common); +-}; +- + /* Data shared by all the FSG instances. */ + struct fsg_common { + struct usb_gadget *gadget; +@@ -268,13 +274,14 @@ struct fsg_common { + struct fsg_buffhd *next_buffhd_to_fill; + struct fsg_buffhd *next_buffhd_to_drain; + struct fsg_buffhd *buffhds; ++ unsigned int fsg_num_buffers; + + int cmnd_size; + u8 cmnd[MAX_COMMAND_SIZE]; + + unsigned int nluns; + unsigned int lun; +- struct fsg_lun *luns; ++ struct fsg_lun **luns; + struct fsg_lun *curlun; + + unsigned int bulk_out_maxpacket; +@@ -294,6 +301,7 @@ struct fsg_common { + unsigned int short_packet_received:1; + unsigned int bad_lun_okay:1; + unsigned int running:1; ++ unsigned int sysfs:1; + + int thread_wakeup_needed; + struct completion thread_notifier; +@@ -313,27 +321,6 @@ struct fsg_common { + struct kref ref; + }; + +-struct fsg_config { +- unsigned nluns; +- struct fsg_lun_config { +- const char *filename; +- char ro; +- char removable; +- char cdrom; +- char nofua; +- } luns[FSG_MAX_LUNS]; +- +- /* Callback functions. */ +- const struct fsg_operations *ops; +- /* Gadget's private data. */ +- void *private_data; +- +- const char *vendor_name; /* 8 characters or less */ +- const char *product_name; /* 16 characters or less */ +- +- char can_stall; +-}; +- + struct fsg_dev { + struct usb_function function; + struct usb_gadget *gadget; /* Copy of cdev->gadget */ +@@ -615,13 +602,14 @@ static bool start_out_transfer(struct fs + return true; + } + +-static int sleep_thread(struct fsg_common *common) ++static int sleep_thread(struct fsg_common *common, bool can_freeze) + { + int rc = 0; + + /* Wait until a signal arrives or we are woken up */ + for (;;) { +- try_to_freeze(); ++ if (can_freeze) ++ try_to_freeze(); + set_current_state(TASK_INTERRUPTIBLE); + if (signal_pending(current)) { + rc = -EINTR; +@@ -695,7 +683,7 @@ static int do_read(struct fsg_common *co + /* Wait for the next buffer to become available */ + bh = common->next_buffhd_to_fill; + while (bh->state != BUF_STATE_EMPTY) { +- rc = sleep_thread(common); ++ rc = sleep_thread(common, false); + if (rc) + return rc; + } +@@ -950,7 +938,7 @@ static int do_write(struct fsg_common *c + } + + /* Wait for something to happen */ +- rc = sleep_thread(common); ++ rc = sleep_thread(common, false); + if (rc) + return rc; + } +@@ -1517,7 +1505,7 @@ static int throw_away_data(struct fsg_co + } + + /* Otherwise wait for something to happen */ +- rc = sleep_thread(common); ++ rc = sleep_thread(common, true); + if (rc) + return rc; + } +@@ -1638,7 +1626,7 @@ static int send_status(struct fsg_common + /* Wait for the next buffer to become available */ + bh = common->next_buffhd_to_fill; + while (bh->state != BUF_STATE_EMPTY) { +- rc = sleep_thread(common); ++ rc = sleep_thread(common, true); + if (rc) + return rc; + } +@@ -1841,7 +1829,7 @@ static int do_scsi_command(struct fsg_co + bh = common->next_buffhd_to_fill; + common->next_buffhd_to_drain = bh; + while (bh->state != BUF_STATE_EMPTY) { +- rc = sleep_thread(common); ++ rc = sleep_thread(common, true); + if (rc) + return rc; + } +@@ -2172,7 +2160,7 @@ static int received_cbw(struct fsg_dev * + common->data_dir = DATA_DIR_NONE; + common->lun = cbw->Lun; + if (common->lun < common->nluns) +- common->curlun = &common->luns[common->lun]; ++ common->curlun = common->luns[common->lun]; + else + common->curlun = NULL; + common->tag = cbw->Tag; +@@ -2187,7 +2175,7 @@ static int get_next_command(struct fsg_c + /* Wait for the next buffer to become available */ + bh = common->next_buffhd_to_fill; + while (bh->state != BUF_STATE_EMPTY) { +- rc = sleep_thread(common); ++ rc = sleep_thread(common, true); + if (rc) + return rc; + } +@@ -2206,7 +2194,7 @@ static int get_next_command(struct fsg_c + + /* Wait for the CBW to arrive */ + while (bh->state != BUF_STATE_FULL) { +- rc = sleep_thread(common); ++ rc = sleep_thread(common, true); + if (rc) + return rc; + } +@@ -2244,7 +2232,7 @@ reset: + if (common->fsg) { + fsg = common->fsg; + +- for (i = 0; i < fsg_num_buffers; ++i) { ++ for (i = 0; i < common->fsg_num_buffers; ++i) { + struct fsg_buffhd *bh = &common->buffhds[i]; + + if (bh->inreq) { +@@ -2303,7 +2291,7 @@ reset: + clear_bit(IGNORE_BULK_OUT, &fsg->atomic_bitflags); + + /* Allocate the requests */ +- for (i = 0; i < fsg_num_buffers; ++i) { ++ for (i = 0; i < common->fsg_num_buffers; ++i) { + struct fsg_buffhd *bh = &common->buffhds[i]; + + rc = alloc_request(common, fsg->bulk_in, &bh->inreq); +@@ -2320,7 +2308,9 @@ reset: + + common->running = 1; + for (i = 0; i < common->nluns; ++i) +- common->luns[i].unit_attention_data = SS_RESET_OCCURRED; ++ if (common->luns[i]) ++ common->luns[i]->unit_attention_data = ++ SS_RESET_OCCURRED; + return rc; + } + +@@ -2372,7 +2362,7 @@ static void handle_exception(struct fsg_ + + /* Cancel all the pending transfers */ + if (likely(common->fsg)) { +- for (i = 0; i < fsg_num_buffers; ++i) { ++ for (i = 0; i < common->fsg_num_buffers; ++i) { + bh = &common->buffhds[i]; + if (bh->inreq_busy) + usb_ep_dequeue(common->fsg->bulk_in, bh->inreq); +@@ -2384,13 +2374,13 @@ static void handle_exception(struct fsg_ + /* Wait until everything is idle */ + for (;;) { + int num_active = 0; +- for (i = 0; i < fsg_num_buffers; ++i) { ++ for (i = 0; i < common->fsg_num_buffers; ++i) { + bh = &common->buffhds[i]; + num_active += bh->inreq_busy + bh->outreq_busy; + } + if (num_active == 0) + break; +- if (sleep_thread(common)) ++ if (sleep_thread(common, true)) + return; + } + +@@ -2407,7 +2397,7 @@ static void handle_exception(struct fsg_ + */ + spin_lock_irq(&common->lock); + +- for (i = 0; i < fsg_num_buffers; ++i) { ++ for (i = 0; i < common->fsg_num_buffers; ++i) { + bh = &common->buffhds[i]; + bh->state = BUF_STATE_EMPTY; + } +@@ -2420,7 +2410,9 @@ static void handle_exception(struct fsg_ + common->state = FSG_STATE_STATUS_PHASE; + else { + for (i = 0; i < common->nluns; ++i) { +- curlun = &common->luns[i]; ++ curlun = common->luns[i]; ++ if (!curlun) ++ continue; + curlun->prevent_medium_removal = 0; + curlun->sense_data = SS_NO_SENSE; + curlun->unit_attention_data = SS_NO_SENSE; +@@ -2462,8 +2454,9 @@ static void handle_exception(struct fsg_ + * CONFIG_CHANGE cases. + */ + /* for (i = 0; i < common->nluns; ++i) */ +- /* common->luns[i].unit_attention_data = */ +- /* SS_RESET_OCCURRED; */ ++ /* if (common->luns[i]) */ ++ /* common->luns[i]->unit_attention_data = */ ++ /* SS_RESET_OCCURRED; */ + break; + + case FSG_STATE_CONFIG_CHANGE: +@@ -2524,7 +2517,7 @@ static int fsg_main_thread(void *common_ + } + + if (!common->running) { +- sleep_thread(common); ++ sleep_thread(common, true); + continue; + } + +@@ -2559,12 +2552,13 @@ static int fsg_main_thread(void *common_ + + if (!common->ops || !common->ops->thread_exits + || common->ops->thread_exits(common) < 0) { +- struct fsg_lun *curlun = common->luns; ++ struct fsg_lun **curlun_it = common->luns; + unsigned i = common->nluns; + + down_write(&common->filesem); +- for (; i--; ++curlun) { +- if (!fsg_lun_is_open(curlun)) ++ for (; i--; ++curlun_it) { ++ struct fsg_lun *curlun = *curlun_it; ++ if (!curlun || !fsg_lun_is_open(curlun)) + continue; + + fsg_lun_close(curlun); +@@ -2580,6 +2574,56 @@ static int fsg_main_thread(void *common_ + + /*************************** DEVICE ATTRIBUTES ***************************/ + ++static ssize_t ro_show(struct device *dev, struct device_attribute *attr, char *buf) ++{ ++ struct fsg_lun *curlun = fsg_lun_from_dev(dev); ++ ++ return fsg_show_ro(curlun, buf); ++} ++ ++static ssize_t nofua_show(struct device *dev, struct device_attribute *attr, ++ char *buf) ++{ ++ struct fsg_lun *curlun = fsg_lun_from_dev(dev); ++ ++ return fsg_show_nofua(curlun, buf); ++} ++ ++static ssize_t file_show(struct device *dev, struct device_attribute *attr, ++ char *buf) ++{ ++ struct fsg_lun *curlun = fsg_lun_from_dev(dev); ++ struct rw_semaphore *filesem = dev_get_drvdata(dev); ++ ++ return fsg_show_file(curlun, filesem, buf); ++} ++ ++static ssize_t ro_store(struct device *dev, struct device_attribute *attr, ++ const char *buf, size_t count) ++{ ++ struct fsg_lun *curlun = fsg_lun_from_dev(dev); ++ struct rw_semaphore *filesem = dev_get_drvdata(dev); ++ ++ return fsg_store_ro(curlun, filesem, buf, count); ++} ++ ++static ssize_t nofua_store(struct device *dev, struct device_attribute *attr, ++ const char *buf, size_t count) ++{ ++ struct fsg_lun *curlun = fsg_lun_from_dev(dev); ++ ++ return fsg_store_nofua(curlun, buf, count); ++} ++ ++static ssize_t file_store(struct device *dev, struct device_attribute *attr, ++ const char *buf, size_t count) ++{ ++ struct fsg_lun *curlun = fsg_lun_from_dev(dev); ++ struct rw_semaphore *filesem = dev_get_drvdata(dev); ++ ++ return fsg_store_file(curlun, filesem, buf, count); ++} ++ + static DEVICE_ATTR_RW(ro); + static DEVICE_ATTR_RW(nofua); + static DEVICE_ATTR_RW(file); +@@ -2597,221 +2641,422 @@ static void fsg_lun_release(struct devic + /* Nothing needs to be done */ + } + +-static inline void fsg_common_get(struct fsg_common *common) ++void fsg_common_get(struct fsg_common *common) + { + kref_get(&common->ref); + } ++EXPORT_SYMBOL_GPL(fsg_common_get); + +-static inline void fsg_common_put(struct fsg_common *common) ++void fsg_common_put(struct fsg_common *common) + { + kref_put(&common->ref, fsg_common_release); + } ++EXPORT_SYMBOL_GPL(fsg_common_put); + +-static struct fsg_common *fsg_common_init(struct fsg_common *common, +- struct usb_composite_dev *cdev, +- struct fsg_config *cfg) +-{ +- struct usb_gadget *gadget = cdev->gadget; +- struct fsg_buffhd *bh; +- struct fsg_lun *curlun; +- struct fsg_lun_config *lcfg; +- int nluns, i, rc; +- char *pathbuf; +- +- rc = fsg_num_buffers_validate(); +- if (rc != 0) +- return ERR_PTR(rc); +- +- /* Find out how many LUNs there should be */ +- nluns = cfg->nluns; +- if (nluns < 1 || nluns > FSG_MAX_LUNS) { +- dev_err(&gadget->dev, "invalid number of LUNs: %u\n", nluns); +- return ERR_PTR(-EINVAL); +- } ++/* check if fsg_num_buffers is within a valid range */ ++static inline int fsg_num_buffers_validate(unsigned int fsg_num_buffers) ++{ ++ if (fsg_num_buffers >= 2 && fsg_num_buffers <= 4) ++ return 0; ++ pr_err("fsg_num_buffers %u is out of range (%d to %d)\n", ++ fsg_num_buffers, 2, 4); ++ return -EINVAL; ++} + +- /* Allocate? */ ++static struct fsg_common *fsg_common_setup(struct fsg_common *common) ++{ + if (!common) { +- common = kzalloc(sizeof *common, GFP_KERNEL); ++ common = kzalloc(sizeof(*common), GFP_KERNEL); + if (!common) + return ERR_PTR(-ENOMEM); + common->free_storage_on_release = 1; + } else { +- memset(common, 0, sizeof *common); + common->free_storage_on_release = 0; + } ++ init_rwsem(&common->filesem); ++ spin_lock_init(&common->lock); ++ kref_init(&common->ref); ++ init_completion(&common->thread_notifier); ++ init_waitqueue_head(&common->fsg_wait); ++ common->state = FSG_STATE_TERMINATED; + +- common->buffhds = kcalloc(fsg_num_buffers, +- sizeof *(common->buffhds), GFP_KERNEL); +- if (!common->buffhds) { +- if (common->free_storage_on_release) +- kfree(common); +- return ERR_PTR(-ENOMEM); ++ return common; ++} ++ ++void fsg_common_set_sysfs(struct fsg_common *common, bool sysfs) ++{ ++ common->sysfs = sysfs; ++} ++EXPORT_SYMBOL_GPL(fsg_common_set_sysfs); ++ ++static void _fsg_common_free_buffers(struct fsg_buffhd *buffhds, unsigned n) ++{ ++ if (buffhds) { ++ struct fsg_buffhd *bh = buffhds; ++ while (n--) { ++ kfree(bh->buf); ++ ++bh; ++ } ++ kfree(buffhds); + } ++} + +- common->ops = cfg->ops; +- common->private_data = cfg->private_data; ++int fsg_common_set_num_buffers(struct fsg_common *common, unsigned int n) ++{ ++ struct fsg_buffhd *bh, *buffhds; ++ int i, rc; + +- common->gadget = gadget; +- common->ep0 = gadget->ep0; +- common->ep0req = cdev->req; +- common->cdev = cdev; ++ rc = fsg_num_buffers_validate(n); ++ if (rc != 0) ++ return rc; + +- /* Maybe allocate device-global string IDs, and patch descriptors */ +- if (fsg_strings[FSG_STRING_INTERFACE].id == 0) { +- rc = usb_string_id(cdev); +- if (unlikely(rc < 0)) ++ buffhds = kcalloc(n, sizeof(*buffhds), GFP_KERNEL); ++ if (!buffhds) ++ return -ENOMEM; ++ ++ /* Data buffers cyclic list */ ++ bh = buffhds; ++ i = n; ++ goto buffhds_first_it; ++ do { ++ bh->next = bh + 1; ++ ++bh; ++buffhds_first_it: ++ bh->buf = kmalloc(FSG_BUFLEN, GFP_KERNEL); ++ if (unlikely(!bh->buf)) + goto error_release; +- fsg_strings[FSG_STRING_INTERFACE].id = rc; +- fsg_intf_desc.iInterface = rc; +- } ++ } while (--i); ++ bh->next = buffhds; ++ ++ _fsg_common_free_buffers(common->buffhds, common->fsg_num_buffers); ++ common->fsg_num_buffers = n; ++ common->buffhds = buffhds; ++ ++ return 0; + ++error_release: + /* +- * Create the LUNs, open their backing files, and register the +- * LUN devices in sysfs. ++ * "buf"s pointed to by heads after n - i are NULL ++ * so releasing them won't hurt + */ +- curlun = kcalloc(nluns, sizeof(*curlun), GFP_KERNEL); +- if (unlikely(!curlun)) { +- rc = -ENOMEM; +- goto error_release; +- } +- common->luns = curlun; ++ _fsg_common_free_buffers(buffhds, n); + +- init_rwsem(&common->filesem); ++ return -ENOMEM; ++} ++EXPORT_SYMBOL_GPL(fsg_common_set_num_buffers); + +- for (i = 0, lcfg = cfg->luns; i < nluns; ++i, ++curlun, ++lcfg) { +- curlun->cdrom = !!lcfg->cdrom; +- curlun->ro = lcfg->cdrom || lcfg->ro; +- curlun->initially_ro = curlun->ro; +- curlun->removable = lcfg->removable; +- curlun->dev.release = fsg_lun_release; +- curlun->dev.parent = &gadget->dev; +- /* curlun->dev.driver = &fsg_driver.driver; XXX */ +- dev_set_drvdata(&curlun->dev, &common->filesem); +- dev_set_name(&curlun->dev, "lun%d", i); ++static inline void fsg_common_remove_sysfs(struct fsg_lun *lun) ++{ ++ device_remove_file(&lun->dev, &dev_attr_nofua); ++ /* ++ * device_remove_file() => ++ * ++ * here the attr (e.g. dev_attr_ro) is only used to be passed to: ++ * ++ * sysfs_remove_file() => ++ * ++ * here e.g. both dev_attr_ro_cdrom and dev_attr_ro are in ++ * the same namespace and ++ * from here only attr->name is passed to: ++ * ++ * sysfs_hash_and_remove() ++ * ++ * attr->name is the same for dev_attr_ro_cdrom and ++ * dev_attr_ro ++ * attr->name is the same for dev_attr_file and ++ * dev_attr_file_nonremovable ++ * ++ * so we don't differentiate between removing e.g. dev_attr_ro_cdrom ++ * and dev_attr_ro ++ */ ++ device_remove_file(&lun->dev, &dev_attr_ro); ++ device_remove_file(&lun->dev, &dev_attr_file); ++} + +- rc = device_register(&curlun->dev); +- if (rc) { +- INFO(common, "failed to register LUN%d: %d\n", i, rc); +- common->nluns = i; +- put_device(&curlun->dev); +- goto error_release; +- } ++void fsg_common_remove_lun(struct fsg_lun *lun, bool sysfs) ++{ ++ if (sysfs) { ++ fsg_common_remove_sysfs(lun); ++ device_unregister(&lun->dev); ++ } ++ fsg_lun_close(lun); ++ kfree(lun); ++} ++EXPORT_SYMBOL_GPL(fsg_common_remove_lun); + +- rc = device_create_file(&curlun->dev, +- curlun->cdrom +- ? &dev_attr_ro_cdrom +- : &dev_attr_ro); +- if (rc) +- goto error_luns; +- rc = device_create_file(&curlun->dev, +- curlun->removable +- ? &dev_attr_file +- : &dev_attr_file_nonremovable); +- if (rc) +- goto error_luns; +- rc = device_create_file(&curlun->dev, &dev_attr_nofua); +- if (rc) +- goto error_luns; ++static void _fsg_common_remove_luns(struct fsg_common *common, int n) ++{ ++ int i; + +- if (lcfg->filename) { +- rc = fsg_lun_open(curlun, lcfg->filename); +- if (rc) +- goto error_luns; +- } else if (!curlun->removable) { +- ERROR(common, "no file given for LUN%d\n", i); +- rc = -EINVAL; +- goto error_luns; ++ for (i = 0; i < n; ++i) ++ if (common->luns[i]) { ++ fsg_common_remove_lun(common->luns[i], common->sysfs); ++ common->luns[i] = NULL; + } ++} ++EXPORT_SYMBOL_GPL(fsg_common_remove_luns); ++ ++void fsg_common_remove_luns(struct fsg_common *common) ++{ ++ _fsg_common_remove_luns(common, common->nluns); ++} ++ ++void fsg_common_free_luns(struct fsg_common *common) ++{ ++ fsg_common_remove_luns(common); ++ kfree(common->luns); ++ common->luns = NULL; ++} ++EXPORT_SYMBOL_GPL(fsg_common_free_luns); ++ ++int fsg_common_set_nluns(struct fsg_common *common, int nluns) ++{ ++ struct fsg_lun **curlun; ++ ++ /* Find out how many LUNs there should be */ ++ if (nluns < 1 || nluns > FSG_MAX_LUNS) { ++ pr_err("invalid number of LUNs: %u\n", nluns); ++ return -EINVAL; + } ++ ++ curlun = kcalloc(nluns, sizeof(*curlun), GFP_KERNEL); ++ if (unlikely(!curlun)) ++ return -ENOMEM; ++ ++ if (common->luns) ++ fsg_common_free_luns(common); ++ ++ common->luns = curlun; + common->nluns = nluns; + +- /* Data buffers cyclic list */ +- bh = common->buffhds; +- i = fsg_num_buffers; +- goto buffhds_first_it; +- do { +- bh->next = bh + 1; +- ++bh; +-buffhds_first_it: +- bh->buf = kmalloc(FSG_BUFLEN, GFP_KERNEL); +- if (unlikely(!bh->buf)) { +- rc = -ENOMEM; +- goto error_release; +- } +- } while (--i); +- bh->next = common->buffhds; ++ pr_info("Number of LUNs=%d\n", common->nluns); + +- /* Prepare inquiryString */ +- i = get_default_bcdDevice(); +- snprintf(common->inquiry_string, sizeof common->inquiry_string, +- "%-8s%-16s%04x", cfg->vendor_name ?: "Linux", +- /* Assume product name dependent on the first LUN */ +- cfg->product_name ?: (common->luns->cdrom +- ? "File-CD Gadget" +- : "File-Stor Gadget"), +- i); ++ return 0; ++} ++EXPORT_SYMBOL_GPL(fsg_common_set_nluns); ++ ++void fsg_common_set_ops(struct fsg_common *common, ++ const struct fsg_operations *ops) ++{ ++ common->ops = ops; ++} ++EXPORT_SYMBOL_GPL(fsg_common_set_ops); ++ ++void fsg_common_free_buffers(struct fsg_common *common) ++{ ++ _fsg_common_free_buffers(common->buffhds, common->fsg_num_buffers); ++ common->buffhds = NULL; ++} ++EXPORT_SYMBOL_GPL(fsg_common_free_buffers); ++ ++int fsg_common_set_cdev(struct fsg_common *common, ++ struct usb_composite_dev *cdev, bool can_stall) ++{ ++ struct usb_string *us; ++ ++ common->gadget = cdev->gadget; ++ common->ep0 = cdev->gadget->ep0; ++ common->ep0req = cdev->req; ++ common->cdev = cdev; ++ ++ us = usb_gstrings_attach(cdev, fsg_strings_array, ++ ARRAY_SIZE(fsg_strings)); ++ if (IS_ERR(us)) ++ return PTR_ERR(us); ++ ++ fsg_intf_desc.iInterface = us[FSG_STRING_INTERFACE].id; + + /* + * Some peripheral controllers are known not to be able to + * halt bulk endpoints correctly. If one of them is present, + * disable stalls. + */ +- common->can_stall = cfg->can_stall && +- !(gadget_is_at91(common->gadget)); ++ common->can_stall = can_stall && !(gadget_is_at91(common->gadget)); + +- spin_lock_init(&common->lock); +- kref_init(&common->ref); ++ return 0; ++} ++EXPORT_SYMBOL_GPL(fsg_common_set_cdev); + +- /* Tell the thread to start working */ +- common->thread_task = +- kthread_create(fsg_main_thread, common, "file-storage"); +- if (IS_ERR(common->thread_task)) { +- rc = PTR_ERR(common->thread_task); +- goto error_release; ++static inline int fsg_common_add_sysfs(struct fsg_common *common, ++ struct fsg_lun *lun) ++{ ++ int rc; ++ ++ rc = device_register(&lun->dev); ++ if (rc) { ++ put_device(&lun->dev); ++ return rc; + } +- init_completion(&common->thread_notifier); +- init_waitqueue_head(&common->fsg_wait); + +- /* Information */ +- INFO(common, FSG_DRIVER_DESC ", version: " FSG_DRIVER_VERSION "\n"); +- INFO(common, "Number of LUNs=%d\n", common->nluns); ++ rc = device_create_file(&lun->dev, ++ lun->cdrom ++ ? &dev_attr_ro_cdrom ++ : &dev_attr_ro); ++ if (rc) ++ goto error; ++ rc = device_create_file(&lun->dev, ++ lun->removable ++ ? &dev_attr_file ++ : &dev_attr_file_nonremovable); ++ if (rc) ++ goto error; ++ rc = device_create_file(&lun->dev, &dev_attr_nofua); ++ if (rc) ++ goto error; ++ ++ return 0; ++ ++error: ++ /* removing nonexistent files is a no-op */ ++ fsg_common_remove_sysfs(lun); ++ device_unregister(&lun->dev); ++ return rc; ++} ++ ++int fsg_common_create_lun(struct fsg_common *common, struct fsg_lun_config *cfg, ++ unsigned int id, const char *name, ++ const char **name_pfx) ++{ ++ struct fsg_lun *lun; ++ char *pathbuf, *p; ++ int rc = -ENOMEM; ++ ++ if (!common->nluns || !common->luns) ++ return -ENODEV; ++ ++ if (common->luns[id]) ++ return -EBUSY; ++ ++ if (!cfg->filename && !cfg->removable) { ++ pr_err("no file given for LUN%d\n", id); ++ return -EINVAL; ++ } ++ ++ lun = kzalloc(sizeof(*lun), GFP_KERNEL); ++ if (!lun) ++ return -ENOMEM; ++ ++ lun->name_pfx = name_pfx; ++ ++ lun->cdrom = !!cfg->cdrom; ++ lun->ro = cfg->cdrom || cfg->ro; ++ lun->initially_ro = lun->ro; ++ lun->removable = !!cfg->removable; ++ ++ if (!common->sysfs) { ++ /* we DON'T own the name!*/ ++ lun->name = name; ++ } else { ++ lun->dev.release = fsg_lun_release; ++ lun->dev.parent = &common->gadget->dev; ++ dev_set_drvdata(&lun->dev, &common->filesem); ++ dev_set_name(&lun->dev, name); ++ lun->name = dev_name(&lun->dev); ++ ++ rc = fsg_common_add_sysfs(common, lun); ++ if (rc) { ++ pr_info("failed to register LUN%d: %d\n", id, rc); ++ goto error_sysfs; ++ } ++ } ++ ++ common->luns[id] = lun; ++ ++ if (cfg->filename) { ++ rc = fsg_lun_open(lun, cfg->filename); ++ if (rc) ++ goto error_lun; ++ } + + pathbuf = kmalloc(PATH_MAX, GFP_KERNEL); +- for (i = 0, nluns = common->nluns, curlun = common->luns; +- i < nluns; +- ++curlun, ++i) { +- char *p = "(no medium)"; +- if (fsg_lun_is_open(curlun)) { +- p = "(error)"; +- if (pathbuf) { +- p = d_path(&curlun->filp->f_path, +- pathbuf, PATH_MAX); +- if (IS_ERR(p)) +- p = "(error)"; +- } ++ p = "(no medium)"; ++ if (fsg_lun_is_open(lun)) { ++ p = "(error)"; ++ if (pathbuf) { ++ p = d_path(&lun->filp->f_path, pathbuf, PATH_MAX); ++ if (IS_ERR(p)) ++ p = "(error)"; + } +- LINFO(curlun, "LUN: %s%s%sfile: %s\n", +- curlun->removable ? "removable " : "", +- curlun->ro ? "read only " : "", +- curlun->cdrom ? "CD-ROM " : "", +- p); + } ++ pr_info("LUN: %s%s%sfile: %s\n", ++ lun->removable ? "removable " : "", ++ lun->ro ? "read only " : "", ++ lun->cdrom ? "CD-ROM " : "", ++ p); + kfree(pathbuf); + ++ return 0; ++ ++error_lun: ++ if (common->sysfs) { ++ fsg_common_remove_sysfs(lun); ++ device_unregister(&lun->dev); ++ } ++ fsg_lun_close(lun); ++ common->luns[id] = NULL; ++error_sysfs: ++ kfree(lun); ++ return rc; ++} ++EXPORT_SYMBOL_GPL(fsg_common_create_lun); ++ ++int fsg_common_create_luns(struct fsg_common *common, struct fsg_config *cfg) ++{ ++ char buf[8]; /* enough for 100000000 different numbers, decimal */ ++ int i, rc; ++ ++ for (i = 0; i < common->nluns; ++i) { ++ snprintf(buf, sizeof(buf), "lun%d", i); ++ rc = fsg_common_create_lun(common, &cfg->luns[i], i, buf, NULL); ++ if (rc) ++ goto fail; ++ } ++ ++ pr_info("Number of LUNs=%d\n", common->nluns); ++ ++ return 0; ++ ++fail: ++ _fsg_common_remove_luns(common, i); ++ return rc; ++} ++EXPORT_SYMBOL_GPL(fsg_common_create_luns); ++ ++void fsg_common_set_inquiry_string(struct fsg_common *common, const char *vn, ++ const char *pn) ++{ ++ int i; ++ ++ /* Prepare inquiryString */ ++ i = get_default_bcdDevice(); ++ snprintf(common->inquiry_string, sizeof(common->inquiry_string), ++ "%-8s%-16s%04x", vn ?: "Linux", ++ /* Assume product name dependent on the first LUN */ ++ pn ?: ((*common->luns)->cdrom ++ ? "File-CD Gadget" ++ : "File-Stor Gadget"), ++ i); ++} ++EXPORT_SYMBOL_GPL(fsg_common_set_inquiry_string); ++ ++int fsg_common_run_thread(struct fsg_common *common) ++{ ++ common->state = FSG_STATE_IDLE; ++ /* Tell the thread to start working */ ++ common->thread_task = ++ kthread_create(fsg_main_thread, common, "file-storage"); ++ if (IS_ERR(common->thread_task)) { ++ common->state = FSG_STATE_TERMINATED; ++ return PTR_ERR(common->thread_task); ++ } ++ + DBG(common, "I/O thread pid: %d\n", task_pid_nr(common->thread_task)); + + wake_up_process(common->thread_task); + +- return common; +- +-error_luns: +- common->nluns = i + 1; +-error_release: +- common->state = FSG_STATE_TERMINATED; /* The thread is dead */ +- /* Call fsg_common_release() directly, ref might be not initialised. */ +- fsg_common_release(&common->ref); +- return ERR_PTR(rc); ++ return 0; + } ++EXPORT_SYMBOL_GPL(fsg_common_run_thread); + + static void fsg_common_release(struct kref *ref) + { +@@ -2824,36 +3069,26 @@ static void fsg_common_release(struct kr + } + + if (likely(common->luns)) { +- struct fsg_lun *lun = common->luns; ++ struct fsg_lun **lun_it = common->luns; + unsigned i = common->nluns; + + /* In error recovery common->nluns may be zero. */ +- for (; i; --i, ++lun) { +- device_remove_file(&lun->dev, &dev_attr_nofua); +- device_remove_file(&lun->dev, +- lun->cdrom +- ? &dev_attr_ro_cdrom +- : &dev_attr_ro); +- device_remove_file(&lun->dev, +- lun->removable +- ? &dev_attr_file +- : &dev_attr_file_nonremovable); ++ for (; i; --i, ++lun_it) { ++ struct fsg_lun *lun = *lun_it; ++ if (!lun) ++ continue; ++ if (common->sysfs) ++ fsg_common_remove_sysfs(lun); + fsg_lun_close(lun); +- device_unregister(&lun->dev); ++ if (common->sysfs) ++ device_unregister(&lun->dev); ++ kfree(lun); + } + + kfree(common->luns); + } + +- { +- struct fsg_buffhd *bh = common->buffhds; +- unsigned i = fsg_num_buffers; +- do { +- kfree(bh->buf); +- } while (++bh, --i); +- } +- +- kfree(common->buffhds); ++ _fsg_common_free_buffers(common->buffhds, common->fsg_num_buffers); + if (common->free_storage_on_release) + kfree(common); + } +@@ -2861,24 +3096,6 @@ static void fsg_common_release(struct kr + + /*-------------------------------------------------------------------------*/ + +-static void fsg_unbind(struct usb_configuration *c, struct usb_function *f) +-{ +- struct fsg_dev *fsg = fsg_from_func(f); +- struct fsg_common *common = fsg->common; +- +- DBG(fsg, "unbind\n"); +- if (fsg->common->fsg == fsg) { +- fsg->common->new_fsg = NULL; +- raise_exception(fsg->common, FSG_STATE_CONFIG_CHANGE); +- /* FIXME: make interruptible or killable somehow? */ +- wait_event(common->fsg_wait, common->fsg != fsg); +- } +- +- fsg_common_put(common); +- usb_free_all_descriptors(&fsg->function); +- kfree(fsg); +-} +- + static int fsg_bind(struct usb_configuration *c, struct usb_function *f) + { + struct fsg_dev *fsg = fsg_from_func(f); +@@ -2887,6 +3104,19 @@ static int fsg_bind(struct usb_configura + struct usb_ep *ep; + unsigned max_burst; + int ret; ++ struct fsg_opts *opts; ++ ++ opts = fsg_opts_from_func_inst(f->fi); ++ if (!opts->no_configfs) { ++ ret = fsg_common_set_cdev(fsg->common, c->cdev, ++ fsg->common->can_stall); ++ if (ret) ++ return ret; ++ fsg_common_set_inquiry_string(fsg->common, 0, 0); ++ ret = fsg_common_run_thread(fsg->common); ++ if (ret) ++ return ret; ++ } + + fsg->gadget = gadget; + +@@ -2939,95 +3169,472 @@ autoconf_fail: + return -ENOTSUPP; + } + +-/****************************** ADD FUNCTION ******************************/ ++/****************************** ALLOCATE FUNCTION *************************/ + +-static struct usb_gadget_strings *fsg_strings_array[] = { +- &fsg_stringtab, ++static void fsg_unbind(struct usb_configuration *c, struct usb_function *f) ++{ ++ struct fsg_dev *fsg = fsg_from_func(f); ++ struct fsg_common *common = fsg->common; ++ ++ DBG(fsg, "unbind\n"); ++ if (fsg->common->fsg == fsg) { ++ fsg->common->new_fsg = NULL; ++ raise_exception(fsg->common, FSG_STATE_CONFIG_CHANGE); ++ /* FIXME: make interruptible or killable somehow? */ ++ wait_event(common->fsg_wait, common->fsg != fsg); ++ } ++ ++ usb_free_all_descriptors(&fsg->function); ++} ++ ++static inline struct fsg_lun_opts *to_fsg_lun_opts(struct config_item *item) ++{ ++ return container_of(to_config_group(item), struct fsg_lun_opts, group); ++} ++ ++static inline struct fsg_opts *to_fsg_opts(struct config_item *item) ++{ ++ return container_of(to_config_group(item), struct fsg_opts, ++ func_inst.group); ++} ++ ++CONFIGFS_ATTR_STRUCT(fsg_lun_opts); ++CONFIGFS_ATTR_OPS(fsg_lun_opts); ++ ++static void fsg_lun_attr_release(struct config_item *item) ++{ ++ struct fsg_lun_opts *lun_opts; ++ ++ lun_opts = to_fsg_lun_opts(item); ++ kfree(lun_opts); ++} ++ ++static struct configfs_item_operations fsg_lun_item_ops = { ++ .release = fsg_lun_attr_release, ++ .show_attribute = fsg_lun_opts_attr_show, ++ .store_attribute = fsg_lun_opts_attr_store, ++}; ++ ++static ssize_t fsg_lun_opts_file_show(struct fsg_lun_opts *opts, char *page) ++{ ++ struct fsg_opts *fsg_opts; ++ ++ fsg_opts = to_fsg_opts(opts->group.cg_item.ci_parent); ++ ++ return fsg_show_file(opts->lun, &fsg_opts->common->filesem, page); ++} ++ ++static ssize_t fsg_lun_opts_file_store(struct fsg_lun_opts *opts, ++ const char *page, size_t len) ++{ ++ struct fsg_opts *fsg_opts; ++ ++ fsg_opts = to_fsg_opts(opts->group.cg_item.ci_parent); ++ ++ return fsg_store_file(opts->lun, &fsg_opts->common->filesem, page, len); ++} ++ ++static struct fsg_lun_opts_attribute fsg_lun_opts_file = ++ __CONFIGFS_ATTR(file, S_IRUGO | S_IWUSR, fsg_lun_opts_file_show, ++ fsg_lun_opts_file_store); ++ ++static ssize_t fsg_lun_opts_ro_show(struct fsg_lun_opts *opts, char *page) ++{ ++ return fsg_show_ro(opts->lun, page); ++} ++ ++static ssize_t fsg_lun_opts_ro_store(struct fsg_lun_opts *opts, ++ const char *page, size_t len) ++{ ++ struct fsg_opts *fsg_opts; ++ ++ fsg_opts = to_fsg_opts(opts->group.cg_item.ci_parent); ++ ++ return fsg_store_ro(opts->lun, &fsg_opts->common->filesem, page, len); ++} ++ ++static struct fsg_lun_opts_attribute fsg_lun_opts_ro = ++ __CONFIGFS_ATTR(ro, S_IRUGO | S_IWUSR, fsg_lun_opts_ro_show, ++ fsg_lun_opts_ro_store); ++ ++static ssize_t fsg_lun_opts_removable_show(struct fsg_lun_opts *opts, ++ char *page) ++{ ++ return fsg_show_removable(opts->lun, page); ++} ++ ++static ssize_t fsg_lun_opts_removable_store(struct fsg_lun_opts *opts, ++ const char *page, size_t len) ++{ ++ return fsg_store_removable(opts->lun, page, len); ++} ++ ++static struct fsg_lun_opts_attribute fsg_lun_opts_removable = ++ __CONFIGFS_ATTR(removable, S_IRUGO | S_IWUSR, ++ fsg_lun_opts_removable_show, ++ fsg_lun_opts_removable_store); ++ ++static ssize_t fsg_lun_opts_cdrom_show(struct fsg_lun_opts *opts, char *page) ++{ ++ return fsg_show_cdrom(opts->lun, page); ++} ++ ++static ssize_t fsg_lun_opts_cdrom_store(struct fsg_lun_opts *opts, ++ const char *page, size_t len) ++{ ++ struct fsg_opts *fsg_opts; ++ ++ fsg_opts = to_fsg_opts(opts->group.cg_item.ci_parent); ++ ++ return fsg_store_cdrom(opts->lun, &fsg_opts->common->filesem, page, ++ len); ++} ++ ++static struct fsg_lun_opts_attribute fsg_lun_opts_cdrom = ++ __CONFIGFS_ATTR(cdrom, S_IRUGO | S_IWUSR, fsg_lun_opts_cdrom_show, ++ fsg_lun_opts_cdrom_store); ++ ++static ssize_t fsg_lun_opts_nofua_show(struct fsg_lun_opts *opts, char *page) ++{ ++ return fsg_show_nofua(opts->lun, page); ++} ++ ++static ssize_t fsg_lun_opts_nofua_store(struct fsg_lun_opts *opts, ++ const char *page, size_t len) ++{ ++ return fsg_store_nofua(opts->lun, page, len); ++} ++ ++static struct fsg_lun_opts_attribute fsg_lun_opts_nofua = ++ __CONFIGFS_ATTR(nofua, S_IRUGO | S_IWUSR, fsg_lun_opts_nofua_show, ++ fsg_lun_opts_nofua_store); ++ ++static struct configfs_attribute *fsg_lun_attrs[] = { ++ &fsg_lun_opts_file.attr, ++ &fsg_lun_opts_ro.attr, ++ &fsg_lun_opts_removable.attr, ++ &fsg_lun_opts_cdrom.attr, ++ &fsg_lun_opts_nofua.attr, + NULL, + }; + +-static int fsg_bind_config(struct usb_composite_dev *cdev, +- struct usb_configuration *c, +- struct fsg_common *common) ++static struct config_item_type fsg_lun_type = { ++ .ct_item_ops = &fsg_lun_item_ops, ++ .ct_attrs = fsg_lun_attrs, ++ .ct_owner = THIS_MODULE, ++}; ++ ++static struct config_group *fsg_lun_make(struct config_group *group, ++ const char *name) + { +- struct fsg_dev *fsg; ++ struct fsg_lun_opts *opts; ++ struct fsg_opts *fsg_opts; ++ struct fsg_lun_config config; ++ char *num_str; ++ u8 num; ++ int ret; ++ ++ num_str = strchr(name, '.'); ++ if (!num_str) { ++ pr_err("Unable to locate . in LUN.NUMBER\n"); ++ return ERR_PTR(-EINVAL); ++ } ++ num_str++; ++ ++ ret = kstrtou8(num_str, 0, &num); ++ if (ret) ++ return ERR_PTR(ret); ++ ++ fsg_opts = to_fsg_opts(&group->cg_item); ++ if (num >= FSG_MAX_LUNS) ++ return ERR_PTR(-ERANGE); ++ ++ mutex_lock(&fsg_opts->lock); ++ if (fsg_opts->refcnt || fsg_opts->common->luns[num]) { ++ ret = -EBUSY; ++ goto out; ++ } ++ ++ opts = kzalloc(sizeof(*opts), GFP_KERNEL); ++ if (!opts) { ++ ret = -ENOMEM; ++ goto out; ++ } ++ ++ memset(&config, 0, sizeof(config)); ++ config.removable = true; ++ ++ ret = fsg_common_create_lun(fsg_opts->common, &config, num, name, ++ (const char **)&group->cg_item.ci_name); ++ if (ret) { ++ kfree(opts); ++ goto out; ++ } ++ opts->lun = fsg_opts->common->luns[num]; ++ opts->lun_id = num; ++ mutex_unlock(&fsg_opts->lock); ++ ++ config_group_init_type_name(&opts->group, name, &fsg_lun_type); ++ ++ return &opts->group; ++out: ++ mutex_unlock(&fsg_opts->lock); ++ return ERR_PTR(ret); ++} ++ ++static void fsg_lun_drop(struct config_group *group, struct config_item *item) ++{ ++ struct fsg_lun_opts *lun_opts; ++ struct fsg_opts *fsg_opts; ++ ++ lun_opts = to_fsg_lun_opts(item); ++ fsg_opts = to_fsg_opts(&group->cg_item); ++ ++ mutex_lock(&fsg_opts->lock); ++ if (fsg_opts->refcnt) { ++ struct config_item *gadget; ++ ++ gadget = group->cg_item.ci_parent->ci_parent; ++ unregister_gadget_item(gadget); ++ } ++ ++ fsg_common_remove_lun(lun_opts->lun, fsg_opts->common->sysfs); ++ fsg_opts->common->luns[lun_opts->lun_id] = NULL; ++ lun_opts->lun_id = 0; ++ mutex_unlock(&fsg_opts->lock); ++ ++ config_item_put(item); ++} ++ ++CONFIGFS_ATTR_STRUCT(fsg_opts); ++CONFIGFS_ATTR_OPS(fsg_opts); ++ ++static void fsg_attr_release(struct config_item *item) ++{ ++ struct fsg_opts *opts = to_fsg_opts(item); ++ ++ usb_put_function_instance(&opts->func_inst); ++} ++ ++static struct configfs_item_operations fsg_item_ops = { ++ .release = fsg_attr_release, ++ .show_attribute = fsg_opts_attr_show, ++ .store_attribute = fsg_opts_attr_store, ++}; ++ ++static ssize_t fsg_opts_stall_show(struct fsg_opts *opts, char *page) ++{ ++ int result; ++ ++ mutex_lock(&opts->lock); ++ result = sprintf(page, "%d", opts->common->can_stall); ++ mutex_unlock(&opts->lock); ++ ++ return result; ++} ++ ++static ssize_t fsg_opts_stall_store(struct fsg_opts *opts, const char *page, ++ size_t len) ++{ ++ int ret; ++ bool stall; ++ ++ mutex_lock(&opts->lock); ++ ++ if (opts->refcnt) { ++ mutex_unlock(&opts->lock); ++ return -EBUSY; ++ } ++ ++ ret = strtobool(page, &stall); ++ if (!ret) { ++ opts->common->can_stall = stall; ++ ret = len; ++ } ++ ++ mutex_unlock(&opts->lock); ++ ++ return ret; ++} ++ ++static struct fsg_opts_attribute fsg_opts_stall = ++ __CONFIGFS_ATTR(stall, S_IRUGO | S_IWUSR, fsg_opts_stall_show, ++ fsg_opts_stall_store); ++ ++#ifdef CONFIG_USB_GADGET_DEBUG_FILES ++static ssize_t fsg_opts_num_buffers_show(struct fsg_opts *opts, char *page) ++{ ++ int result; ++ ++ mutex_lock(&opts->lock); ++ result = sprintf(page, "%d", opts->common->fsg_num_buffers); ++ mutex_unlock(&opts->lock); ++ ++ return result; ++} ++ ++static ssize_t fsg_opts_num_buffers_store(struct fsg_opts *opts, ++ const char *page, size_t len) ++{ ++ int ret; ++ u8 num; ++ ++ mutex_lock(&opts->lock); ++ if (opts->refcnt) { ++ ret = -EBUSY; ++ goto end; ++ } ++ ret = kstrtou8(page, 0, &num); ++ if (ret) ++ goto end; ++ ++ ret = fsg_num_buffers_validate(num); ++ if (ret) ++ goto end; ++ ++ fsg_common_set_num_buffers(opts->common, num); ++ ret = len; ++ ++end: ++ mutex_unlock(&opts->lock); ++ return ret; ++} ++ ++static struct fsg_opts_attribute fsg_opts_num_buffers = ++ __CONFIGFS_ATTR(num_buffers, S_IRUGO | S_IWUSR, ++ fsg_opts_num_buffers_show, ++ fsg_opts_num_buffers_store); ++ ++#endif ++ ++static struct configfs_attribute *fsg_attrs[] = { ++ &fsg_opts_stall.attr, ++#ifdef CONFIG_USB_GADGET_DEBUG_FILES ++ &fsg_opts_num_buffers.attr, ++#endif ++ NULL, ++}; ++ ++static struct configfs_group_operations fsg_group_ops = { ++ .make_group = fsg_lun_make, ++ .drop_item = fsg_lun_drop, ++}; ++ ++static struct config_item_type fsg_func_type = { ++ .ct_item_ops = &fsg_item_ops, ++ .ct_group_ops = &fsg_group_ops, ++ .ct_attrs = fsg_attrs, ++ .ct_owner = THIS_MODULE, ++}; ++ ++static void fsg_free_inst(struct usb_function_instance *fi) ++{ ++ struct fsg_opts *opts; ++ ++ opts = fsg_opts_from_func_inst(fi); ++ fsg_common_put(opts->common); ++ kfree(opts); ++} ++ ++static struct usb_function_instance *fsg_alloc_inst(void) ++{ ++ struct fsg_opts *opts; ++ struct fsg_lun_config config; + int rc; + +- fsg = kzalloc(sizeof *fsg, GFP_KERNEL); ++ opts = kzalloc(sizeof(*opts), GFP_KERNEL); ++ if (!opts) ++ return ERR_PTR(-ENOMEM); ++ mutex_init(&opts->lock); ++ opts->func_inst.free_func_inst = fsg_free_inst; ++ opts->common = fsg_common_setup(opts->common); ++ if (IS_ERR(opts->common)) { ++ rc = PTR_ERR(opts->common); ++ goto release_opts; ++ } ++ rc = fsg_common_set_nluns(opts->common, FSG_MAX_LUNS); ++ if (rc) ++ goto release_opts; ++ ++ rc = fsg_common_set_num_buffers(opts->common, ++ CONFIG_USB_GADGET_STORAGE_NUM_BUFFERS); ++ if (rc) ++ goto release_luns; ++ ++ pr_info(FSG_DRIVER_DESC ", version: " FSG_DRIVER_VERSION "\n"); ++ ++ memset(&config, 0, sizeof(config)); ++ config.removable = true; ++ rc = fsg_common_create_lun(opts->common, &config, 0, "lun.0", ++ (const char **)&opts->func_inst.group.cg_item.ci_name); ++ opts->lun0.lun = opts->common->luns[0]; ++ opts->lun0.lun_id = 0; ++ config_group_init_type_name(&opts->lun0.group, "lun.0", &fsg_lun_type); ++ opts->default_groups[0] = &opts->lun0.group; ++ opts->func_inst.group.default_groups = opts->default_groups; ++ ++ config_group_init_type_name(&opts->func_inst.group, "", &fsg_func_type); ++ ++ return &opts->func_inst; ++ ++release_luns: ++ kfree(opts->common->luns); ++release_opts: ++ kfree(opts); ++ return ERR_PTR(rc); ++} ++ ++static void fsg_free(struct usb_function *f) ++{ ++ struct fsg_dev *fsg; ++ struct fsg_opts *opts; ++ ++ fsg = container_of(f, struct fsg_dev, function); ++ opts = container_of(f->fi, struct fsg_opts, func_inst); ++ ++ mutex_lock(&opts->lock); ++ opts->refcnt--; ++ mutex_unlock(&opts->lock); ++ ++ kfree(fsg); ++} ++ ++static struct usb_function *fsg_alloc(struct usb_function_instance *fi) ++{ ++ struct fsg_opts *opts = fsg_opts_from_func_inst(fi); ++ struct fsg_common *common = opts->common; ++ struct fsg_dev *fsg; ++ ++ fsg = kzalloc(sizeof(*fsg), GFP_KERNEL); + if (unlikely(!fsg)) +- return -ENOMEM; ++ return ERR_PTR(-ENOMEM); + +- fsg->function.name = FSG_DRIVER_DESC; +- fsg->function.strings = fsg_strings_array; +- fsg->function.bind = fsg_bind; +- fsg->function.unbind = fsg_unbind; +- fsg->function.setup = fsg_setup; +- fsg->function.set_alt = fsg_set_alt; +- fsg->function.disable = fsg_disable; ++ mutex_lock(&opts->lock); ++ opts->refcnt++; ++ mutex_unlock(&opts->lock); ++ fsg->function.name = FSG_DRIVER_DESC; ++ fsg->function.bind = fsg_bind; ++ fsg->function.unbind = fsg_unbind; ++ fsg->function.setup = fsg_setup; ++ fsg->function.set_alt = fsg_set_alt; ++ fsg->function.disable = fsg_disable; ++ fsg->function.free_func = fsg_free; + + fsg->common = common; +- /* +- * Our caller holds a reference to common structure so we +- * don't have to be worry about it being freed until we return +- * from this function. So instead of incrementing counter now +- * and decrement in error recovery we increment it only when +- * call to usb_add_function() was successful. +- */ + +- rc = usb_add_function(c, &fsg->function); +- if (unlikely(rc)) +- kfree(fsg); +- else +- fsg_common_get(fsg->common); +- return rc; ++ return &fsg->function; + } + ++DECLARE_USB_FUNCTION_INIT(mass_storage, fsg_alloc_inst, fsg_alloc); ++MODULE_LICENSE("GPL"); ++MODULE_AUTHOR("Michal Nazarewicz"); + + /************************* Module parameters *************************/ + +-struct fsg_module_parameters { +- char *file[FSG_MAX_LUNS]; +- bool ro[FSG_MAX_LUNS]; +- bool removable[FSG_MAX_LUNS]; +- bool cdrom[FSG_MAX_LUNS]; +- bool nofua[FSG_MAX_LUNS]; +- +- unsigned int file_count, ro_count, removable_count, cdrom_count; +- unsigned int nofua_count; +- unsigned int luns; /* nluns */ +- bool stall; /* can_stall */ +-}; + +-#define _FSG_MODULE_PARAM_ARRAY(prefix, params, name, type, desc) \ +- module_param_array_named(prefix ## name, params.name, type, \ +- &prefix ## params.name ## _count, \ +- S_IRUGO); \ +- MODULE_PARM_DESC(prefix ## name, desc) +- +-#define _FSG_MODULE_PARAM(prefix, params, name, type, desc) \ +- module_param_named(prefix ## name, params.name, type, \ +- S_IRUGO); \ +- MODULE_PARM_DESC(prefix ## name, desc) +- +-#define FSG_MODULE_PARAMETERS(prefix, params) \ +- _FSG_MODULE_PARAM_ARRAY(prefix, params, file, charp, \ +- "names of backing files or devices"); \ +- _FSG_MODULE_PARAM_ARRAY(prefix, params, ro, bool, \ +- "true to force read-only"); \ +- _FSG_MODULE_PARAM_ARRAY(prefix, params, removable, bool, \ +- "true to simulate removable media"); \ +- _FSG_MODULE_PARAM_ARRAY(prefix, params, cdrom, bool, \ +- "true to simulate CD-ROM instead of disk"); \ +- _FSG_MODULE_PARAM_ARRAY(prefix, params, nofua, bool, \ +- "true to ignore SCSI WRITE(10,12) FUA bit"); \ +- _FSG_MODULE_PARAM(prefix, params, luns, uint, \ +- "number of LUNs"); \ +- _FSG_MODULE_PARAM(prefix, params, stall, bool, \ +- "false to prevent bulk stalls") +- +-static void +-fsg_config_from_params(struct fsg_config *cfg, +- const struct fsg_module_parameters *params) ++void fsg_config_from_params(struct fsg_config *cfg, ++ const struct fsg_module_parameters *params, ++ unsigned int fsg_num_buffers) + { + struct fsg_lun_config *lun; + unsigned i; +@@ -3055,19 +3662,7 @@ fsg_config_from_params(struct fsg_config + + /* Finalise */ + cfg->can_stall = params->stall; ++ cfg->fsg_num_buffers = fsg_num_buffers; + } ++EXPORT_SYMBOL_GPL(fsg_config_from_params); + +-static inline struct fsg_common * +-fsg_common_from_params(struct fsg_common *common, +- struct usb_composite_dev *cdev, +- const struct fsg_module_parameters *params) +- __attribute__((unused)); +-static inline struct fsg_common * +-fsg_common_from_params(struct fsg_common *common, +- struct usb_composite_dev *cdev, +- const struct fsg_module_parameters *params) +-{ +- struct fsg_config cfg; +- fsg_config_from_params(&cfg, params); +- return fsg_common_init(common, cdev, &cfg); +-} +--- /dev/null ++++ b/drivers/usb/gadget/f_mass_storage.h +@@ -0,0 +1,166 @@ ++#ifndef USB_F_MASS_STORAGE_H ++#define USB_F_MASS_STORAGE_H ++ ++#include <linux/usb/composite.h> ++#include "storage_common.h" ++ ++struct fsg_module_parameters { ++ char *file[FSG_MAX_LUNS]; ++ bool ro[FSG_MAX_LUNS]; ++ bool removable[FSG_MAX_LUNS]; ++ bool cdrom[FSG_MAX_LUNS]; ++ bool nofua[FSG_MAX_LUNS]; ++ ++ unsigned int file_count, ro_count, removable_count, cdrom_count; ++ unsigned int nofua_count; ++ unsigned int luns; /* nluns */ ++ bool stall; /* can_stall */ ++}; ++ ++#define _FSG_MODULE_PARAM_ARRAY(prefix, params, name, type, desc) \ ++ module_param_array_named(prefix ## name, params.name, type, \ ++ &prefix ## params.name ## _count, \ ++ S_IRUGO); \ ++ MODULE_PARM_DESC(prefix ## name, desc) ++ ++#define _FSG_MODULE_PARAM(prefix, params, name, type, desc) \ ++ module_param_named(prefix ## name, params.name, type, \ ++ S_IRUGO); \ ++ MODULE_PARM_DESC(prefix ## name, desc) ++ ++#define __FSG_MODULE_PARAMETERS(prefix, params) \ ++ _FSG_MODULE_PARAM_ARRAY(prefix, params, file, charp, \ ++ "names of backing files or devices"); \ ++ _FSG_MODULE_PARAM_ARRAY(prefix, params, ro, bool, \ ++ "true to force read-only"); \ ++ _FSG_MODULE_PARAM_ARRAY(prefix, params, removable, bool, \ ++ "true to simulate removable media"); \ ++ _FSG_MODULE_PARAM_ARRAY(prefix, params, cdrom, bool, \ ++ "true to simulate CD-ROM instead of disk"); \ ++ _FSG_MODULE_PARAM_ARRAY(prefix, params, nofua, bool, \ ++ "true to ignore SCSI WRITE(10,12) FUA bit"); \ ++ _FSG_MODULE_PARAM(prefix, params, luns, uint, \ ++ "number of LUNs"); \ ++ _FSG_MODULE_PARAM(prefix, params, stall, bool, \ ++ "false to prevent bulk stalls") ++ ++#ifdef CONFIG_USB_GADGET_DEBUG_FILES ++ ++#define FSG_MODULE_PARAMETERS(prefix, params) \ ++ __FSG_MODULE_PARAMETERS(prefix, params); \ ++ module_param_named(num_buffers, fsg_num_buffers, uint, S_IRUGO);\ ++ MODULE_PARM_DESC(num_buffers, "Number of pipeline buffers") ++#else ++ ++#define FSG_MODULE_PARAMETERS(prefix, params) \ ++ __FSG_MODULE_PARAMETERS(prefix, params) ++ ++#endif ++ ++struct fsg_common; ++ ++/* FSF callback functions */ ++struct fsg_operations { ++ /* ++ * Callback function to call when thread exits. If no ++ * callback is set or it returns value lower then zero MSF ++ * will force eject all LUNs it operates on (including those ++ * marked as non-removable or with prevent_medium_removal flag ++ * set). ++ */ ++ int (*thread_exits)(struct fsg_common *common); ++}; ++ ++struct fsg_lun_opts { ++ struct config_group group; ++ struct fsg_lun *lun; ++ int lun_id; ++}; ++ ++struct fsg_opts { ++ struct fsg_common *common; ++ struct usb_function_instance func_inst; ++ struct fsg_lun_opts lun0; ++ struct config_group *default_groups[2]; ++ bool no_configfs; /* for legacy gadgets */ ++ ++ /* ++ * Read/write access to configfs attributes is handled by configfs. ++ * ++ * This is to protect the data from concurrent access by read/write ++ * and create symlink/remove symlink. ++ */ ++ struct mutex lock; ++ int refcnt; ++}; ++ ++struct fsg_lun_config { ++ const char *filename; ++ char ro; ++ char removable; ++ char cdrom; ++ char nofua; ++}; ++ ++struct fsg_config { ++ unsigned nluns; ++ struct fsg_lun_config luns[FSG_MAX_LUNS]; ++ ++ /* Callback functions. */ ++ const struct fsg_operations *ops; ++ /* Gadget's private data. */ ++ void *private_data; ++ ++ const char *vendor_name; /* 8 characters or less */ ++ const char *product_name; /* 16 characters or less */ ++ ++ char can_stall; ++ unsigned int fsg_num_buffers; ++}; ++ ++static inline struct fsg_opts * ++fsg_opts_from_func_inst(const struct usb_function_instance *fi) ++{ ++ return container_of(fi, struct fsg_opts, func_inst); ++} ++ ++void fsg_common_get(struct fsg_common *common); ++ ++void fsg_common_put(struct fsg_common *common); ++ ++void fsg_common_set_sysfs(struct fsg_common *common, bool sysfs); ++ ++int fsg_common_set_num_buffers(struct fsg_common *common, unsigned int n); ++ ++void fsg_common_free_buffers(struct fsg_common *common); ++ ++int fsg_common_set_cdev(struct fsg_common *common, ++ struct usb_composite_dev *cdev, bool can_stall); ++ ++void fsg_common_remove_lun(struct fsg_lun *lun, bool sysfs); ++ ++void fsg_common_remove_luns(struct fsg_common *common); ++ ++void fsg_common_free_luns(struct fsg_common *common); ++ ++int fsg_common_set_nluns(struct fsg_common *common, int nluns); ++ ++void fsg_common_set_ops(struct fsg_common *common, ++ const struct fsg_operations *ops); ++ ++int fsg_common_create_lun(struct fsg_common *common, struct fsg_lun_config *cfg, ++ unsigned int id, const char *name, ++ const char **name_pfx); ++ ++int fsg_common_create_luns(struct fsg_common *common, struct fsg_config *cfg); ++ ++void fsg_common_set_inquiry_string(struct fsg_common *common, const char *vn, ++ const char *pn); ++ ++int fsg_common_run_thread(struct fsg_common *common); ++ ++void fsg_config_from_params(struct fsg_config *cfg, ++ const struct fsg_module_parameters *params, ++ unsigned int fsg_num_buffers); ++ ++#endif /* USB_F_MASS_STORAGE_H */ +--- a/drivers/usb/gadget/g_ffs.c ++++ b/drivers/usb/gadget/g_ffs.c +@@ -76,7 +76,9 @@ struct gfs_ffs_obj { + + USB_GADGET_COMPOSITE_OPTIONS(); + ++#if defined CONFIG_USB_FUNCTIONFS_ETH || defined CONFIG_USB_FUNCTIONFS_RNDIS + USB_ETHERNET_MODULE_PARAMETERS(); ++#endif + + static struct usb_device_descriptor gfs_dev_desc = { + .bLength = sizeof gfs_dev_desc, +--- a/drivers/usb/gadget/goku_udc.c ++++ b/drivers/usb/gadget/goku_udc.c +@@ -1701,7 +1701,6 @@ static void goku_remove(struct pci_dev * + if (dev->enabled) + pci_disable_device(pdev); + +- pci_set_drvdata(pdev, NULL); + dev->regs = NULL; + + INFO(dev, "unbind\n"); +--- a/drivers/usb/gadget/Kconfig ++++ b/drivers/usb/gadget/Kconfig +@@ -58,6 +58,20 @@ config USB_GADGET_DEBUG + trying to track down. Never enable these messages for a + production build. + ++config USB_GADGET_VERBOSE ++ bool "Verbose debugging Messages (DEVELOPMENT)" ++ depends on USB_GADGET_DEBUG ++ help ++ Many controller and gadget drivers will print verbose debugging ++ messages if you use this option to ask for those messages. ++ ++ Avoid enabling these messages, even if you're actively ++ debugging such a driver. Many drivers will emit so many ++ messages that the driver timings are affected, which will ++ either create new failure modes or remove the one you're ++ trying to track down. Never enable these messages for a ++ production build. ++ + config USB_GADGET_DEBUG_FILES + boolean "Debugging information files (DEVELOPMENT)" + depends on PROC_FS +@@ -525,6 +539,9 @@ config USB_F_SUBSET + config USB_F_RNDIS + tristate + ++config USB_F_MASS_STORAGE ++ tristate ++ + choice + tristate "USB Gadget Drivers" + default USB_ETH +@@ -662,6 +679,16 @@ config USB_CONFIGFS_PHONET + help + The Phonet protocol implementation for USB device. + ++config USB_CONFIGFS_MASS_STORAGE ++ boolean "Mass storage" ++ depends on USB_CONFIGFS ++ select USB_F_MASS_STORAGE ++ help ++ The Mass Storage Gadget acts as a USB Mass Storage disk drive. ++ As its storage repository it can use a regular file or a block ++ device (in much the same way as the "loop" device driver), ++ specified as a module parameter or sysfs option. ++ + config USB_ZERO + tristate "Gadget Zero (DEVELOPMENT)" + select USB_LIBCOMPOSITE +@@ -878,6 +905,7 @@ config USB_MASS_STORAGE + tristate "Mass Storage Gadget" + depends on BLOCK + select USB_LIBCOMPOSITE ++ select USB_F_MASS_STORAGE + help + The Mass Storage Gadget acts as a USB Mass Storage disk drive. + As its storage repository it can use a regular file or a block +@@ -1001,6 +1029,7 @@ config USB_G_ACM_MS + select USB_LIBCOMPOSITE + select USB_U_SERIAL + select USB_F_ACM ++ select USB_F_MASS_STORAGE + help + This driver provides two functions in one configuration: + a mass storage, and a CDC ACM (serial port) link. +@@ -1015,8 +1044,8 @@ config USB_G_MULTI + select USB_LIBCOMPOSITE + select USB_U_SERIAL + select USB_U_ETHER +- select USB_U_RNDIS + select USB_F_ACM ++ select USB_F_MASS_STORAGE + help + The Multifunction Composite Gadget provides Ethernet (RNDIS + and/or CDC Ethernet), mass storage and ACM serial link +@@ -1035,6 +1064,8 @@ config USB_G_MULTI + config USB_G_MULTI_RNDIS + bool "RNDIS + CDC Serial + Storage configuration" + depends on USB_G_MULTI ++ select USB_U_RNDIS ++ select USB_F_RNDIS + default y + help + This option enables a configuration with RNDIS, CDC Serial and +@@ -1048,6 +1079,7 @@ config USB_G_MULTI_CDC + bool "CDC Ethernet + CDC Serial + Storage configuration" + depends on USB_G_MULTI + default n ++ select USB_F_ECM + help + This option enables a configuration with CDC Ethernet (ECM), CDC + Serial and Mass Storage functions available in the Multifunction +--- a/drivers/usb/gadget/Makefile ++++ b/drivers/usb/gadget/Makefile +@@ -1,7 +1,8 @@ + # + # USB peripheral controller drivers + # +-ccflags-$(CONFIG_USB_GADGET_DEBUG) := -DDEBUG ++ccflags-$(CONFIG_USB_GADGET_DEBUG) := -DDEBUG ++ccflags-$(CONFIG_USB_GADGET_VERBOSE) += -DVERBOSE_DEBUG + + obj-$(CONFIG_USB_GADGET) += udc-core.o + obj-$(CONFIG_USB_LIBCOMPOSITE) += libcomposite.o +@@ -60,6 +61,8 @@ usb_f_ecm_subset-y := f_subset.o + obj-$(CONFIG_USB_F_SUBSET) += usb_f_ecm_subset.o + usb_f_rndis-y := f_rndis.o + obj-$(CONFIG_USB_F_RNDIS) += usb_f_rndis.o ++usb_f_mass_storage-y := f_mass_storage.o storage_common.o ++obj-$(CONFIG_USB_F_MASS_STORAGE)+= usb_f_mass_storage.o + + # + # USB gadget drivers +--- a/drivers/usb/gadget/mass_storage.c ++++ b/drivers/usb/gadget/mass_storage.c +@@ -37,16 +37,16 @@ + #define DRIVER_DESC "Mass Storage Gadget" + #define DRIVER_VERSION "2009/09/11" + +-/*-------------------------------------------------------------------------*/ +- + /* +- * kbuild is not very cooperative with respect to linking separately +- * compiled library objects into one module. So for now we won't use +- * separate compilation ... ensuring init/exit sections work to shrink +- * the runtime footprint, and giving us at least some parts of what +- * a "gcc --combine ... part1.c part2.c part3.c ... " build would. ++ * Thanks to NetChip Technologies for donating this product ID. ++ * ++ * DO NOT REUSE THESE IDs with any other driver!! Ever!! ++ * Instead: allocate your own, using normal USB-IF procedures. + */ +-#include "f_mass_storage.c" ++#define FSG_VENDOR_ID 0x0525 /* NetChip */ ++#define FSG_PRODUCT_ID 0xa4a5 /* Linux-USB File-backed Storage Gadget */ ++ ++#include "f_mass_storage.h" + + /*-------------------------------------------------------------------------*/ + USB_GADGET_COMPOSITE_OPTIONS(); +@@ -97,11 +97,28 @@ static struct usb_gadget_strings *dev_st + NULL, + }; + ++static struct usb_function_instance *fi_msg; ++static struct usb_function *f_msg; ++ + /****************************** Configurations ******************************/ + + static struct fsg_module_parameters mod_data = { + .stall = 1 + }; ++#ifdef CONFIG_USB_GADGET_DEBUG_FILES ++ ++static unsigned int fsg_num_buffers = CONFIG_USB_GADGET_STORAGE_NUM_BUFFERS; ++ ++#else ++ ++/* ++ * Number of buffers we will use. ++ * 2 is usually enough for good buffering pipeline ++ */ ++#define fsg_num_buffers CONFIG_USB_GADGET_STORAGE_NUM_BUFFERS ++ ++#endif /* CONFIG_USB_GADGET_DEBUG_FILES */ ++ + FSG_MODULE_PARAMETERS(/* no prefix */, mod_data); + + static unsigned long msg_registered; +@@ -115,13 +132,7 @@ static int msg_thread_exits(struct fsg_c + + static int __init msg_do_config(struct usb_configuration *c) + { +- static const struct fsg_operations ops = { +- .thread_exits = msg_thread_exits, +- }; +- static struct fsg_common common; +- +- struct fsg_common *retp; +- struct fsg_config config; ++ struct fsg_opts *opts; + int ret; + + if (gadget_is_otg(c->cdev->gadget)) { +@@ -129,15 +140,24 @@ static int __init msg_do_config(struct u + c->bmAttributes |= USB_CONFIG_ATT_WAKEUP; + } + +- fsg_config_from_params(&config, &mod_data); +- config.ops = &ops; ++ opts = fsg_opts_from_func_inst(fi_msg); + +- retp = fsg_common_init(&common, c->cdev, &config); +- if (IS_ERR(retp)) +- return PTR_ERR(retp); ++ f_msg = usb_get_function(fi_msg); ++ if (IS_ERR(f_msg)) ++ return PTR_ERR(f_msg); ++ ++ ret = fsg_common_run_thread(opts->common); ++ if (ret) ++ goto put_func; ++ ++ ret = usb_add_function(c, f_msg); ++ if (ret) ++ goto put_func; + +- ret = fsg_bind_config(c->cdev, c, &common); +- fsg_common_put(&common); ++ return 0; ++ ++put_func: ++ usb_put_function(f_msg); + return ret; + } + +@@ -152,23 +172,79 @@ static struct usb_configuration msg_conf + + static int __init msg_bind(struct usb_composite_dev *cdev) + { ++ static const struct fsg_operations ops = { ++ .thread_exits = msg_thread_exits, ++ }; ++ struct fsg_opts *opts; ++ struct fsg_config config; + int status; + ++ fi_msg = usb_get_function_instance("mass_storage"); ++ if (IS_ERR(fi_msg)) ++ return PTR_ERR(fi_msg); ++ ++ fsg_config_from_params(&config, &mod_data, fsg_num_buffers); ++ opts = fsg_opts_from_func_inst(fi_msg); ++ ++ opts->no_configfs = true; ++ status = fsg_common_set_num_buffers(opts->common, fsg_num_buffers); ++ if (status) ++ goto fail; ++ ++ status = fsg_common_set_nluns(opts->common, config.nluns); ++ if (status) ++ goto fail_set_nluns; ++ ++ fsg_common_set_ops(opts->common, &ops); ++ ++ status = fsg_common_set_cdev(opts->common, cdev, config.can_stall); ++ if (status) ++ goto fail_set_cdev; ++ ++ fsg_common_set_sysfs(opts->common, true); ++ status = fsg_common_create_luns(opts->common, &config); ++ if (status) ++ goto fail_set_cdev; ++ ++ fsg_common_set_inquiry_string(opts->common, config.vendor_name, ++ config.product_name); ++ + status = usb_string_ids_tab(cdev, strings_dev); + if (status < 0) +- return status; ++ goto fail_string_ids; + msg_device_desc.iProduct = strings_dev[USB_GADGET_PRODUCT_IDX].id; + + status = usb_add_config(cdev, &msg_config_driver, msg_do_config); + if (status < 0) +- return status; ++ goto fail_string_ids; ++ + usb_composite_overwrite_options(cdev, &coverwrite); + dev_info(&cdev->gadget->dev, + DRIVER_DESC ", version: " DRIVER_VERSION "\n"); + set_bit(0, &msg_registered); + return 0; ++ ++fail_string_ids: ++ fsg_common_remove_luns(opts->common); ++fail_set_cdev: ++ fsg_common_free_luns(opts->common); ++fail_set_nluns: ++ fsg_common_free_buffers(opts->common); ++fail: ++ usb_put_function_instance(fi_msg); ++ return status; + } + ++static int msg_unbind(struct usb_composite_dev *cdev) ++{ ++ if (!IS_ERR(f_msg)) ++ usb_put_function(f_msg); ++ ++ if (!IS_ERR(fi_msg)) ++ usb_put_function_instance(fi_msg); ++ ++ return 0; ++} + + /****************************** Some noise ******************************/ + +@@ -179,6 +255,7 @@ static __refdata struct usb_composite_dr + .needs_serial = 1, + .strings = dev_strings, + .bind = msg_bind, ++ .unbind = msg_unbind, + }; + + MODULE_DESCRIPTION(DRIVER_DESC); +--- a/drivers/usb/gadget/multi.c ++++ b/drivers/usb/gadget/multi.c +@@ -15,6 +15,7 @@ + + #include <linux/kernel.h> + #include <linux/module.h> ++#include <linux/netdevice.h> + + #include "u_serial.h" + #if defined USB_ETH_RNDIS +@@ -32,22 +33,11 @@ MODULE_AUTHOR("Michal Nazarewicz"); + MODULE_LICENSE("GPL"); + + +-/***************************** All the files... *****************************/ ++#include "f_mass_storage.h" + +-/* +- * kbuild is not very cooperative with respect to linking separately +- * compiled library objects into one module. So for now we won't use +- * separate compilation ... ensuring init/exit sections work to shrink +- * the runtime footprint, and giving us at least some parts of what +- * a "gcc --combine ... part1.c part2.c part3.c ... " build would. +- */ +-#include "f_mass_storage.c" +- +-#define USBF_ECM_INCLUDED +-#include "f_ecm.c" ++#include "u_ecm.h" + #ifdef USB_ETH_RNDIS +-# define USB_FRNDIS_INCLUDED +-# include "f_rndis.c" ++# include "u_rndis.h" + # include "rndis.h" + #endif + #include "u_ether.h" +@@ -132,22 +122,36 @@ static struct usb_gadget_strings *dev_st + /****************************** Configurations ******************************/ + + static struct fsg_module_parameters fsg_mod_data = { .stall = 1 }; +-FSG_MODULE_PARAMETERS(/* no prefix */, fsg_mod_data); ++#ifdef CONFIG_USB_GADGET_DEBUG_FILES ++ ++static unsigned int fsg_num_buffers = CONFIG_USB_GADGET_STORAGE_NUM_BUFFERS; ++ ++#else ++ ++/* ++ * Number of buffers we will use. ++ * 2 is usually enough for good buffering pipeline ++ */ ++#define fsg_num_buffers CONFIG_USB_GADGET_STORAGE_NUM_BUFFERS + +-static struct fsg_common fsg_common; ++#endif /* CONFIG_USB_DEBUG */ + +-static u8 host_mac[ETH_ALEN]; ++FSG_MODULE_PARAMETERS(/* no prefix */, fsg_mod_data); + + static struct usb_function_instance *fi_acm; +-static struct eth_dev *the_dev; ++static struct usb_function_instance *fi_msg; + + /********** RNDIS **********/ + + #ifdef USB_ETH_RNDIS ++static struct usb_function_instance *fi_rndis; + static struct usb_function *f_acm_rndis; ++static struct usb_function *f_rndis; ++static struct usb_function *f_msg_rndis; + + static __init int rndis_do_config(struct usb_configuration *c) + { ++ struct fsg_opts *fsg_opts; + int ret; + + if (gadget_is_otg(c->cdev->gadget)) { +@@ -155,27 +159,50 @@ static __init int rndis_do_config(struct + c->bmAttributes |= USB_CONFIG_ATT_WAKEUP; + } + +- ret = rndis_bind_config(c, host_mac, the_dev); ++ f_rndis = usb_get_function(fi_rndis); ++ if (IS_ERR(f_rndis)) ++ return PTR_ERR(f_rndis); ++ ++ ret = usb_add_function(c, f_rndis); + if (ret < 0) +- return ret; ++ goto err_func_rndis; + + f_acm_rndis = usb_get_function(fi_acm); +- if (IS_ERR(f_acm_rndis)) +- return PTR_ERR(f_acm_rndis); ++ if (IS_ERR(f_acm_rndis)) { ++ ret = PTR_ERR(f_acm_rndis); ++ goto err_func_acm; ++ } + + ret = usb_add_function(c, f_acm_rndis); + if (ret) + goto err_conf; + +- ret = fsg_bind_config(c->cdev, c, &fsg_common); +- if (ret < 0) ++ f_msg_rndis = usb_get_function(fi_msg); ++ if (IS_ERR(f_msg_rndis)) { ++ ret = PTR_ERR(f_msg_rndis); + goto err_fsg; ++ } ++ ++ fsg_opts = fsg_opts_from_func_inst(fi_msg); ++ ret = fsg_common_run_thread(fsg_opts->common); ++ if (ret) ++ goto err_run; ++ ++ ret = usb_add_function(c, f_msg_rndis); ++ if (ret) ++ goto err_run; + + return 0; ++err_run: ++ usb_put_function(f_msg_rndis); + err_fsg: + usb_remove_function(c, f_acm_rndis); + err_conf: + usb_put_function(f_acm_rndis); ++err_func_acm: ++ usb_remove_function(c, f_rndis); ++err_func_rndis: ++ usb_put_function(f_rndis); + return ret; + } + +@@ -205,10 +232,14 @@ static __ref int rndis_config_register(s + /********** CDC ECM **********/ + + #ifdef CONFIG_USB_G_MULTI_CDC ++static struct usb_function_instance *fi_ecm; + static struct usb_function *f_acm_multi; ++static struct usb_function *f_ecm; ++static struct usb_function *f_msg_multi; + + static __init int cdc_do_config(struct usb_configuration *c) + { ++ struct fsg_opts *fsg_opts; + int ret; + + if (gadget_is_otg(c->cdev->gadget)) { +@@ -216,28 +247,51 @@ static __init int cdc_do_config(struct u + c->bmAttributes |= USB_CONFIG_ATT_WAKEUP; + } + +- ret = ecm_bind_config(c, host_mac, the_dev); ++ f_ecm = usb_get_function(fi_ecm); ++ if (IS_ERR(f_ecm)) ++ return PTR_ERR(f_ecm); ++ ++ ret = usb_add_function(c, f_ecm); + if (ret < 0) +- return ret; ++ goto err_func_ecm; + + /* implicit port_num is zero */ + f_acm_multi = usb_get_function(fi_acm); +- if (IS_ERR(f_acm_multi)) +- return PTR_ERR(f_acm_multi); ++ if (IS_ERR(f_acm_multi)) { ++ ret = PTR_ERR(f_acm_multi); ++ goto err_func_acm; ++ } + + ret = usb_add_function(c, f_acm_multi); + if (ret) + goto err_conf; + +- ret = fsg_bind_config(c->cdev, c, &fsg_common); +- if (ret < 0) ++ f_msg_multi = usb_get_function(fi_msg); ++ if (IS_ERR(f_msg_multi)) { ++ ret = PTR_ERR(f_msg_multi); + goto err_fsg; ++ } ++ ++ fsg_opts = fsg_opts_from_func_inst(fi_msg); ++ ret = fsg_common_run_thread(fsg_opts->common); ++ if (ret) ++ goto err_run; ++ ++ ret = usb_add_function(c, f_msg_multi); ++ if (ret) ++ goto err_run; + + return 0; ++err_run: ++ usb_put_function(f_msg_multi); + err_fsg: + usb_remove_function(c, f_acm_multi); + err_conf: + usb_put_function(f_acm_multi); ++err_func_acm: ++ usb_remove_function(c, f_ecm); ++err_func_ecm: ++ usb_put_function(f_ecm); + return ret; + } + +@@ -270,19 +324,67 @@ static __ref int cdc_config_register(str + static int __ref multi_bind(struct usb_composite_dev *cdev) + { + struct usb_gadget *gadget = cdev->gadget; ++#ifdef CONFIG_USB_G_MULTI_CDC ++ struct f_ecm_opts *ecm_opts; ++#endif ++#ifdef USB_ETH_RNDIS ++ struct f_rndis_opts *rndis_opts; ++#endif ++ struct fsg_opts *fsg_opts; ++ struct fsg_config config; + int status; + + if (!can_support_ecm(cdev->gadget)) { + dev_err(&gadget->dev, "controller '%s' not usable\n", +- gadget->name); ++ gadget->name); + return -EINVAL; + } + +- /* set up network link layer */ +- the_dev = gether_setup(cdev->gadget, dev_addr, host_addr, host_mac, +- qmult); +- if (IS_ERR(the_dev)) +- return PTR_ERR(the_dev); ++#ifdef CONFIG_USB_G_MULTI_CDC ++ fi_ecm = usb_get_function_instance("ecm"); ++ if (IS_ERR(fi_ecm)) ++ return PTR_ERR(fi_ecm); ++ ++ ecm_opts = container_of(fi_ecm, struct f_ecm_opts, func_inst); ++ ++ gether_set_qmult(ecm_opts->net, qmult); ++ if (!gether_set_host_addr(ecm_opts->net, host_addr)) ++ pr_info("using host ethernet address: %s", host_addr); ++ if (!gether_set_dev_addr(ecm_opts->net, dev_addr)) ++ pr_info("using self ethernet address: %s", dev_addr); ++#endif ++ ++#ifdef USB_ETH_RNDIS ++ fi_rndis = usb_get_function_instance("rndis"); ++ if (IS_ERR(fi_rndis)) { ++ status = PTR_ERR(fi_rndis); ++ goto fail; ++ } ++ ++ rndis_opts = container_of(fi_rndis, struct f_rndis_opts, func_inst); ++ ++ gether_set_qmult(rndis_opts->net, qmult); ++ if (!gether_set_host_addr(rndis_opts->net, host_addr)) ++ pr_info("using host ethernet address: %s", host_addr); ++ if (!gether_set_dev_addr(rndis_opts->net, dev_addr)) ++ pr_info("using self ethernet address: %s", dev_addr); ++#endif ++ ++#if (defined CONFIG_USB_G_MULTI_CDC && defined USB_ETH_RNDIS) ++ /* ++ * If both ecm and rndis are selected then: ++ * 1) rndis borrows the net interface from ecm ++ * 2) since the interface is shared it must not be bound ++ * twice - in ecm's _and_ rndis' binds, so do it here. ++ */ ++ gether_set_gadget(ecm_opts->net, cdev->gadget); ++ status = gether_register_netdev(ecm_opts->net); ++ if (status) ++ goto fail0; ++ ++ rndis_borrow_net(fi_rndis, ecm_opts->net); ++ ecm_opts->bound = true; ++#endif + + /* set up serial link layer */ + fi_acm = usb_get_function_instance("acm"); +@@ -292,57 +394,102 @@ static int __ref multi_bind(struct usb_c + } + + /* set up mass storage function */ +- { +- void *retp; +- retp = fsg_common_from_params(&fsg_common, cdev, &fsg_mod_data); +- if (IS_ERR(retp)) { +- status = PTR_ERR(retp); +- goto fail1; +- } ++ fi_msg = usb_get_function_instance("mass_storage"); ++ if (IS_ERR(fi_msg)) { ++ status = PTR_ERR(fi_msg); ++ goto fail1; + } ++ fsg_config_from_params(&config, &fsg_mod_data, fsg_num_buffers); ++ fsg_opts = fsg_opts_from_func_inst(fi_msg); ++ ++ fsg_opts->no_configfs = true; ++ status = fsg_common_set_num_buffers(fsg_opts->common, fsg_num_buffers); ++ if (status) ++ goto fail2; ++ ++ status = fsg_common_set_nluns(fsg_opts->common, config.nluns); ++ if (status) ++ goto fail_set_nluns; ++ ++ status = fsg_common_set_cdev(fsg_opts->common, cdev, config.can_stall); ++ if (status) ++ goto fail_set_cdev; ++ ++ fsg_common_set_sysfs(fsg_opts->common, true); ++ status = fsg_common_create_luns(fsg_opts->common, &config); ++ if (status) ++ goto fail_set_cdev; ++ ++ fsg_common_set_inquiry_string(fsg_opts->common, config.vendor_name, ++ config.product_name); + + /* allocate string IDs */ + status = usb_string_ids_tab(cdev, strings_dev); + if (unlikely(status < 0)) +- goto fail2; ++ goto fail_string_ids; + device_desc.iProduct = strings_dev[USB_GADGET_PRODUCT_IDX].id; + + /* register configurations */ + status = rndis_config_register(cdev); + if (unlikely(status < 0)) +- goto fail2; ++ goto fail_string_ids; + + status = cdc_config_register(cdev); + if (unlikely(status < 0)) +- goto fail2; ++ goto fail_string_ids; + usb_composite_overwrite_options(cdev, &coverwrite); + + /* we're done */ + dev_info(&gadget->dev, DRIVER_DESC "\n"); +- fsg_common_put(&fsg_common); + return 0; + + + /* error recovery */ ++fail_string_ids: ++ fsg_common_remove_luns(fsg_opts->common); ++fail_set_cdev: ++ fsg_common_free_luns(fsg_opts->common); ++fail_set_nluns: ++ fsg_common_free_buffers(fsg_opts->common); + fail2: +- fsg_common_put(&fsg_common); ++ usb_put_function_instance(fi_msg); + fail1: + usb_put_function_instance(fi_acm); + fail0: +- gether_cleanup(the_dev); ++#ifdef USB_ETH_RNDIS ++ usb_put_function_instance(fi_rndis); ++fail: ++#endif ++#ifdef CONFIG_USB_G_MULTI_CDC ++ usb_put_function_instance(fi_ecm); ++#endif + return status; + } + + static int __exit multi_unbind(struct usb_composite_dev *cdev) + { + #ifdef CONFIG_USB_G_MULTI_CDC ++ usb_put_function(f_msg_multi); ++#endif ++#ifdef USB_ETH_RNDIS ++ usb_put_function(f_msg_rndis); ++#endif ++ usb_put_function_instance(fi_msg); ++#ifdef CONFIG_USB_G_MULTI_CDC + usb_put_function(f_acm_multi); + #endif + #ifdef USB_ETH_RNDIS + usb_put_function(f_acm_rndis); + #endif + usb_put_function_instance(fi_acm); +- gether_cleanup(the_dev); ++#ifdef USB_ETH_RNDIS ++ usb_put_function(f_rndis); ++ usb_put_function_instance(fi_rndis); ++#endif ++#ifdef CONFIG_USB_G_MULTI_CDC ++ usb_put_function(f_ecm); ++ usb_put_function_instance(fi_ecm); ++#endif + return 0; + } + +--- a/drivers/usb/gadget/mv_u3d_core.c ++++ b/drivers/usb/gadget/mv_u3d_core.c +@@ -310,6 +310,7 @@ static struct mv_u3d_trb *mv_u3d_build_t + */ + trb_hw = dma_pool_alloc(u3d->trb_pool, GFP_ATOMIC, dma); + if (!trb_hw) { ++ kfree(trb); + dev_err(u3d->dev, + "%s, dma_pool_alloc fail\n", __func__); + return NULL; +@@ -454,6 +455,7 @@ static int mv_u3d_req_to_trb(struct mv_u + + trb_hw = kcalloc(trb_num, sizeof(*trb_hw), GFP_ATOMIC); + if (!trb_hw) { ++ kfree(trb); + dev_err(u3d->dev, + "%s, trb_hw alloc fail\n", __func__); + return -ENOMEM; +@@ -1936,7 +1938,7 @@ static int mv_u3d_probe(struct platform_ + } + u3d->irq = r->start; + if (request_irq(u3d->irq, mv_u3d_irq, +- IRQF_DISABLED | IRQF_SHARED, driver_name, u3d)) { ++ IRQF_SHARED, driver_name, u3d)) { + u3d->irq = 0; + dev_err(&dev->dev, "Request irq %d for u3d failed\n", + u3d->irq); +--- a/drivers/usb/gadget/net2280.c ++++ b/drivers/usb/gadget/net2280.c +@@ -2680,7 +2680,6 @@ static void net2280_remove (struct pci_d + if (dev->enabled) + pci_disable_device (pdev); + device_remove_file (&pdev->dev, &dev_attr_registers); +- pci_set_drvdata (pdev, NULL); + + INFO (dev, "unbind\n"); + } +--- a/drivers/usb/gadget/pch_udc.c ++++ b/drivers/usb/gadget/pch_udc.c +@@ -3080,7 +3080,6 @@ static void pch_udc_remove(struct pci_de + if (dev->active) + pci_disable_device(pdev); + kfree(dev); +- pci_set_drvdata(pdev, NULL); + } + + #ifdef CONFIG_PM +--- a/drivers/usb/gadget/s3c-hsotg.c ++++ b/drivers/usb/gadget/s3c-hsotg.c +@@ -83,9 +83,12 @@ struct s3c_hsotg_req; + * @dir_in: Set to true if this endpoint is of the IN direction, which + * means that it is sending data to the Host. + * @index: The index for the endpoint registers. ++ * @mc: Multi Count - number of transactions per microframe ++ * @interval - Interval for periodic endpoints + * @name: The name array passed to the USB core. + * @halted: Set if the endpoint has been halted. + * @periodic: Set if this is a periodic ep, such as Interrupt ++ * @isochronous: Set if this is a isochronous ep + * @sent_zlp: Set if we've sent a zero-length packet. + * @total_data: The total number of data bytes done. + * @fifo_size: The size of the FIFO (for periodic IN endpoints) +@@ -121,9 +124,12 @@ struct s3c_hsotg_ep { + + unsigned char dir_in; + unsigned char index; ++ unsigned char mc; ++ unsigned char interval; + + unsigned int halted:1; + unsigned int periodic:1; ++ unsigned int isochronous:1; + unsigned int sent_zlp:1; + + char name[10]; +@@ -468,6 +474,7 @@ static int s3c_hsotg_write_fifo(struct s + void *data; + int can_write; + int pkt_round; ++ int max_transfer; + + to_write -= (buf_pos - hs_ep->last_load); + +@@ -535,8 +542,10 @@ static int s3c_hsotg_write_fifo(struct s + can_write *= 4; /* fifo size is in 32bit quantities. */ + } + +- dev_dbg(hsotg->dev, "%s: GNPTXSTS=%08x, can=%d, to=%d, mps %d\n", +- __func__, gnptxsts, can_write, to_write, hs_ep->ep.maxpacket); ++ max_transfer = hs_ep->ep.maxpacket * hs_ep->mc; ++ ++ dev_dbg(hsotg->dev, "%s: GNPTXSTS=%08x, can=%d, to=%d, max_transfer %d\n", ++ __func__, gnptxsts, can_write, to_write, max_transfer); + + /* + * limit to 512 bytes of data, it seems at least on the non-periodic +@@ -551,19 +560,21 @@ static int s3c_hsotg_write_fifo(struct s + * the transfer to return that it did not run out of fifo space + * doing it. + */ +- if (to_write > hs_ep->ep.maxpacket) { +- to_write = hs_ep->ep.maxpacket; ++ if (to_write > max_transfer) { ++ to_write = max_transfer; + +- s3c_hsotg_en_gsint(hsotg, +- periodic ? GINTSTS_PTxFEmp : +- GINTSTS_NPTxFEmp); ++ /* it's needed only when we do not use dedicated fifos */ ++ if (!hsotg->dedicated_fifos) ++ s3c_hsotg_en_gsint(hsotg, ++ periodic ? GINTSTS_PTxFEmp : ++ GINTSTS_NPTxFEmp); + } + + /* see if we can write data */ + + if (to_write > can_write) { + to_write = can_write; +- pkt_round = to_write % hs_ep->ep.maxpacket; ++ pkt_round = to_write % max_transfer; + + /* + * Round the write down to an +@@ -581,9 +592,11 @@ static int s3c_hsotg_write_fifo(struct s + * is more room left. + */ + +- s3c_hsotg_en_gsint(hsotg, +- periodic ? GINTSTS_PTxFEmp : +- GINTSTS_NPTxFEmp); ++ /* it's needed only when we do not use dedicated fifos */ ++ if (!hsotg->dedicated_fifos) ++ s3c_hsotg_en_gsint(hsotg, ++ periodic ? GINTSTS_PTxFEmp : ++ GINTSTS_NPTxFEmp); + } + + dev_dbg(hsotg->dev, "write %d/%d, can_write %d, done %d\n", +@@ -727,8 +740,16 @@ static void s3c_hsotg_start_req(struct s + else + packets = 1; /* send one packet if length is zero. */ + ++ if (hs_ep->isochronous && length > (hs_ep->mc * hs_ep->ep.maxpacket)) { ++ dev_err(hsotg->dev, "req length > maxpacket*mc\n"); ++ return; ++ } ++ + if (dir_in && index != 0) +- epsize = DxEPTSIZ_MC(1); ++ if (hs_ep->isochronous) ++ epsize = DxEPTSIZ_MC(packets); ++ else ++ epsize = DxEPTSIZ_MC(1); + else + epsize = 0; + +@@ -820,6 +841,9 @@ static void s3c_hsotg_start_req(struct s + + dev_dbg(hsotg->dev, "%s: DxEPCTL=0x%08x\n", + __func__, readl(hsotg->regs + epctrl_reg)); ++ ++ /* enable ep interrupts */ ++ s3c_hsotg_ctrl_epint(hsotg, hs_ep->index, hs_ep->dir_in, 1); + } + + /** +@@ -1091,6 +1115,7 @@ static int s3c_hsotg_process_req_feature + bool set = (ctrl->bRequest == USB_REQ_SET_FEATURE); + struct s3c_hsotg_ep *ep; + int ret; ++ bool halted; + + dev_dbg(hsotg->dev, "%s: %s_FEATURE\n", + __func__, set ? "SET" : "CLEAR"); +@@ -1105,6 +1130,8 @@ static int s3c_hsotg_process_req_feature + + switch (le16_to_cpu(ctrl->wValue)) { + case USB_ENDPOINT_HALT: ++ halted = ep->halted; ++ + s3c_hsotg_ep_sethalt(&ep->ep, set); + + ret = s3c_hsotg_send_reply(hsotg, ep0, NULL, 0); +@@ -1114,7 +1141,12 @@ static int s3c_hsotg_process_req_feature + return ret; + } + +- if (!set) { ++ /* ++ * we have to complete all requests for ep if it was ++ * halted, and the halt was cleared by CLEAR_FEATURE ++ */ ++ ++ if (!set && halted) { + /* + * If we have request in progress, + * then complete it +@@ -1147,6 +1179,8 @@ static int s3c_hsotg_process_req_feature + return 1; + } + ++static void s3c_hsotg_enqueue_setup(struct s3c_hsotg *hsotg); ++ + /** + * s3c_hsotg_process_control - process a control request + * @hsotg: The device state +@@ -1246,11 +1280,15 @@ static void s3c_hsotg_process_control(st + * don't believe we need to anything more to get the EP + * to reply with a STALL packet + */ ++ ++ /* ++ * complete won't be called, so we enqueue ++ * setup request here ++ */ ++ s3c_hsotg_enqueue_setup(hsotg); + } + } + +-static void s3c_hsotg_enqueue_setup(struct s3c_hsotg *hsotg); +- + /** + * s3c_hsotg_complete_setup - completion of a setup transfer + * @ep: The endpoint the request was on. +@@ -1698,6 +1736,7 @@ static void s3c_hsotg_set_ep_maxpacket(s + struct s3c_hsotg_ep *hs_ep = &hsotg->eps[ep]; + void __iomem *regs = hsotg->regs; + u32 mpsval; ++ u32 mcval; + u32 reg; + + if (ep == 0) { +@@ -1705,15 +1744,19 @@ static void s3c_hsotg_set_ep_maxpacket(s + mpsval = s3c_hsotg_ep0_mps(mps); + if (mpsval > 3) + goto bad_mps; ++ hs_ep->ep.maxpacket = mps; ++ hs_ep->mc = 1; + } else { +- if (mps >= DxEPCTL_MPS_LIMIT+1) ++ mpsval = mps & DxEPCTL_MPS_MASK; ++ if (mpsval > 1024) + goto bad_mps; +- +- mpsval = mps; ++ mcval = ((mps >> 11) & 0x3) + 1; ++ hs_ep->mc = mcval; ++ if (mcval > 3) ++ goto bad_mps; ++ hs_ep->ep.maxpacket = mpsval; + } + +- hs_ep->ep.maxpacket = mps; +- + /* + * update both the in and out endpoint controldir_ registers, even + * if one of the directions may not be in use. +@@ -1782,8 +1825,16 @@ static int s3c_hsotg_trytx(struct s3c_hs + { + struct s3c_hsotg_req *hs_req = hs_ep->req; + +- if (!hs_ep->dir_in || !hs_req) ++ if (!hs_ep->dir_in || !hs_req) { ++ /** ++ * if request is not enqueued, we disable interrupts ++ * for endpoints, excepting ep0 ++ */ ++ if (hs_ep->index != 0) ++ s3c_hsotg_ctrl_epint(hsotg, hs_ep->index, ++ hs_ep->dir_in, 0); + return 0; ++ } + + if (hs_req->req.actual < hs_req->req.length) { + dev_dbg(hsotg->dev, "trying to write more for ep%d\n", +@@ -1887,8 +1938,10 @@ static void s3c_hsotg_epint(struct s3c_h + u32 epctl_reg = dir_in ? DIEPCTL(idx) : DOEPCTL(idx); + u32 epsiz_reg = dir_in ? DIEPTSIZ(idx) : DOEPTSIZ(idx); + u32 ints; ++ u32 ctrl; + + ints = readl(hsotg->regs + epint_reg); ++ ctrl = readl(hsotg->regs + epctl_reg); + + /* Clear endpoint interrupts */ + writel(ints, hsotg->regs + epint_reg); +@@ -1897,6 +1950,14 @@ static void s3c_hsotg_epint(struct s3c_h + __func__, idx, dir_in ? "in" : "out", ints); + + if (ints & DxEPINT_XferCompl) { ++ if (hs_ep->isochronous && hs_ep->interval == 1) { ++ if (ctrl & DxEPCTL_EOFrNum) ++ ctrl |= DxEPCTL_SetEvenFr; ++ else ++ ctrl |= DxEPCTL_SetOddFr; ++ writel(ctrl, hsotg->regs + epctl_reg); ++ } ++ + dev_dbg(hsotg->dev, + "%s: XferCompl: DxEPCTL=0x%08x, DxEPTSIZ=%08x\n", + __func__, readl(hsotg->regs + epctl_reg), +@@ -1963,7 +2024,7 @@ static void s3c_hsotg_epint(struct s3c_h + if (ints & DxEPINT_Back2BackSetup) + dev_dbg(hsotg->dev, "%s: B2BSetup/INEPNakEff\n", __func__); + +- if (dir_in) { ++ if (dir_in && !hs_ep->isochronous) { + /* not sure if this is important, but we'll clear it anyway */ + if (ints & DIEPMSK_INTknTXFEmpMsk) { + dev_dbg(hsotg->dev, "%s: ep%d: INTknTXFEmpMsk\n", +@@ -2092,12 +2153,14 @@ static void kill_all_requests(struct s3c + } + + #define call_gadget(_hs, _entry) \ ++do { \ + if ((_hs)->gadget.speed != USB_SPEED_UNKNOWN && \ + (_hs)->driver && (_hs)->driver->_entry) { \ + spin_unlock(&_hs->lock); \ + (_hs)->driver->_entry(&(_hs)->gadget); \ + spin_lock(&_hs->lock); \ +- } ++ } \ ++} while (0) + + /** + * s3c_hsotg_disconnect - disconnect service +@@ -2241,15 +2304,19 @@ static void s3c_hsotg_core_init(struct s + GAHBCFG_HBstLen_Incr4, + hsotg->regs + GAHBCFG); + else +- writel(GAHBCFG_GlblIntrEn, hsotg->regs + GAHBCFG); ++ writel(((hsotg->dedicated_fifos) ? (GAHBCFG_NPTxFEmpLvl | ++ GAHBCFG_PTxFEmpLvl) : 0) | ++ GAHBCFG_GlblIntrEn, ++ hsotg->regs + GAHBCFG); + + /* +- * Enabling INTknTXFEmpMsk here seems to be a big mistake, we end +- * up being flooded with interrupts if the host is polling the +- * endpoint to try and read data. ++ * If INTknTXFEmpMsk is enabled, it's important to disable ep interrupts ++ * when we have no data to transfer. Otherwise we get being flooded by ++ * interrupts. + */ + +- writel(((hsotg->dedicated_fifos) ? DIEPMSK_TxFIFOEmpty : 0) | ++ writel(((hsotg->dedicated_fifos) ? DIEPMSK_TxFIFOEmpty | ++ DIEPMSK_INTknTXFEmpMsk : 0) | + DIEPMSK_EPDisbldMsk | DIEPMSK_XferComplMsk | + DIEPMSK_TimeOUTMsk | DIEPMSK_AHBErrMsk | + DIEPMSK_INTknEPMisMsk, +@@ -2378,10 +2445,14 @@ irq_retry: + + if (gintsts & (GINTSTS_OEPInt | GINTSTS_IEPInt)) { + u32 daint = readl(hsotg->regs + DAINT); +- u32 daint_out = daint >> DAINT_OutEP_SHIFT; +- u32 daint_in = daint & ~(daint_out << DAINT_OutEP_SHIFT); ++ u32 daintmsk = readl(hsotg->regs + DAINTMSK); ++ u32 daint_out, daint_in; + int ep; + ++ daint &= daintmsk; ++ daint_out = daint >> DAINT_OutEP_SHIFT; ++ daint_in = daint & ~(daint_out << DAINT_OutEP_SHIFT); ++ + dev_dbg(hsotg->dev, "%s: daint=%08x\n", __func__, daint); + + for (ep = 0; ep < 15 && daint_out; ep++, daint_out >>= 1) { +@@ -2577,16 +2648,25 @@ static int s3c_hsotg_ep_enable(struct us + epctrl |= DxEPCTL_SNAK; + + /* update the endpoint state */ +- hs_ep->ep.maxpacket = mps; ++ s3c_hsotg_set_ep_maxpacket(hsotg, hs_ep->index, mps); + + /* default, set to non-periodic */ ++ hs_ep->isochronous = 0; + hs_ep->periodic = 0; ++ hs_ep->halted = 0; ++ hs_ep->interval = desc->bInterval; ++ ++ if (hs_ep->interval > 1 && hs_ep->mc > 1) ++ dev_err(hsotg->dev, "MC > 1 when interval is not 1\n"); + + switch (desc->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) { + case USB_ENDPOINT_XFER_ISOC: +- dev_err(hsotg->dev, "no current ISOC support\n"); +- ret = -EINVAL; +- goto out; ++ epctrl |= DxEPCTL_EPType_Iso; ++ epctrl |= DxEPCTL_SetEvenFr; ++ hs_ep->isochronous = 1; ++ if (dir_in) ++ hs_ep->periodic = 1; ++ break; + + case USB_ENDPOINT_XFER_BULK: + epctrl |= DxEPCTL_EPType_Bulk; +@@ -2634,7 +2714,6 @@ static int s3c_hsotg_ep_enable(struct us + /* enable the endpoint interrupt */ + s3c_hsotg_ctrl_epint(hsotg, index, dir_in, 1); + +-out: + spin_unlock_irqrestore(&hsotg->lock, flags); + return ret; + } +@@ -2776,6 +2855,8 @@ static int s3c_hsotg_ep_sethalt(struct u + + writel(epctl, hs->regs + epreg); + ++ hs_ep->halted = value; ++ + return 0; + } + +@@ -2903,7 +2984,7 @@ static int s3c_hsotg_udc_start(struct us + int ret; + + if (!hsotg) { +- printk(KERN_ERR "%s: called with no device\n", __func__); ++ pr_err("%s: called with no device\n", __func__); + return -ENODEV; + } + +@@ -3066,7 +3147,7 @@ static void s3c_hsotg_initep(struct s3c_ + + hs_ep->parent = hsotg; + hs_ep->ep.name = hs_ep->name; +- hs_ep->ep.maxpacket = epnum ? 512 : EP0_MPS_LIMIT; ++ hs_ep->ep.maxpacket = epnum ? 1024 : EP0_MPS_LIMIT; + hs_ep->ep.ops = &s3c_hsotg_ep_ops; + + /* +@@ -3200,7 +3281,7 @@ static int state_show(struct seq_file *s + readl(regs + GNPTXSTS), + readl(regs + GRXSTSR)); + +- seq_printf(seq, "\nEndpoint status:\n"); ++ seq_puts(seq, "\nEndpoint status:\n"); + + for (idx = 0; idx < 15; idx++) { + u32 in, out; +@@ -3217,7 +3298,7 @@ static int state_show(struct seq_file *s + seq_printf(seq, ", DIEPTSIZ=0x%08x, DOEPTSIZ=0x%08x", + in, out); + +- seq_printf(seq, "\n"); ++ seq_puts(seq, "\n"); + } + + return 0; +@@ -3251,7 +3332,7 @@ static int fifo_show(struct seq_file *se + u32 val; + int idx; + +- seq_printf(seq, "Non-periodic FIFOs:\n"); ++ seq_puts(seq, "Non-periodic FIFOs:\n"); + seq_printf(seq, "RXFIFO: Size %d\n", readl(regs + GRXFSIZ)); + + val = readl(regs + GNPTXFSIZ); +@@ -3259,7 +3340,7 @@ static int fifo_show(struct seq_file *se + val >> GNPTXFSIZ_NPTxFDep_SHIFT, + val & GNPTXFSIZ_NPTxFStAddr_MASK); + +- seq_printf(seq, "\nPeriodic TXFIFOs:\n"); ++ seq_puts(seq, "\nPeriodic TXFIFOs:\n"); + + for (idx = 1; idx <= 15; idx++) { + val = readl(regs + DPTXFSIZn(idx)); +@@ -3330,7 +3411,7 @@ static int ep_show(struct seq_file *seq, + readl(regs + DIEPTSIZ(index)), + readl(regs + DOEPTSIZ(index))); + +- seq_printf(seq, "\n"); ++ seq_puts(seq, "\n"); + seq_printf(seq, "mps %d\n", ep->ep.maxpacket); + seq_printf(seq, "total_data=%ld\n", ep->total_data); + +@@ -3341,7 +3422,7 @@ static int ep_show(struct seq_file *seq, + + list_for_each_entry(req, &ep->queue, queue) { + if (--show_limit < 0) { +- seq_printf(seq, "not showing more requests...\n"); ++ seq_puts(seq, "not showing more requests...\n"); + break; + } + +--- a/drivers/usb/gadget/storage_common.c ++++ b/drivers/usb/gadget/storage_common.c +@@ -23,242 +23,17 @@ + * The valid range of num_buffers is: num >= 2 && num <= 4. + */ + ++#include <linux/module.h> ++#include <linux/blkdev.h> ++#include <linux/file.h> ++#include <linux/fs.h> ++#include <linux/usb/composite.h> + +-#include <linux/usb/storage.h> +-#include <scsi/scsi.h> +-#include <asm/unaligned.h> +- +- +-/* +- * Thanks to NetChip Technologies for donating this product ID. +- * +- * DO NOT REUSE THESE IDs with any other driver!! Ever!! +- * Instead: allocate your own, using normal USB-IF procedures. +- */ +-#define FSG_VENDOR_ID 0x0525 /* NetChip */ +-#define FSG_PRODUCT_ID 0xa4a5 /* Linux-USB File-backed Storage Gadget */ +- +- +-/*-------------------------------------------------------------------------*/ +- +- +-#ifndef DEBUG +-#undef VERBOSE_DEBUG +-#undef DUMP_MSGS +-#endif /* !DEBUG */ +- +-#ifdef VERBOSE_DEBUG +-#define VLDBG LDBG +-#else +-#define VLDBG(lun, fmt, args...) do { } while (0) +-#endif /* VERBOSE_DEBUG */ +- +-#define LDBG(lun, fmt, args...) dev_dbg (&(lun)->dev, fmt, ## args) +-#define LERROR(lun, fmt, args...) dev_err (&(lun)->dev, fmt, ## args) +-#define LWARN(lun, fmt, args...) dev_warn(&(lun)->dev, fmt, ## args) +-#define LINFO(lun, fmt, args...) dev_info(&(lun)->dev, fmt, ## args) +- +- +-#ifdef DUMP_MSGS +- +-# define dump_msg(fsg, /* const char * */ label, \ +- /* const u8 * */ buf, /* unsigned */ length) do { \ +- if (length < 512) { \ +- DBG(fsg, "%s, length %u:\n", label, length); \ +- print_hex_dump(KERN_DEBUG, "", DUMP_PREFIX_OFFSET, \ +- 16, 1, buf, length, 0); \ +- } \ +-} while (0) +- +-# define dump_cdb(fsg) do { } while (0) +- +-#else +- +-# define dump_msg(fsg, /* const char * */ label, \ +- /* const u8 * */ buf, /* unsigned */ length) do { } while (0) +- +-# ifdef VERBOSE_DEBUG +- +-# define dump_cdb(fsg) \ +- print_hex_dump(KERN_DEBUG, "SCSI CDB: ", DUMP_PREFIX_NONE, \ +- 16, 1, (fsg)->cmnd, (fsg)->cmnd_size, 0) \ +- +-# else +- +-# define dump_cdb(fsg) do { } while (0) +- +-# endif /* VERBOSE_DEBUG */ +- +-#endif /* DUMP_MSGS */ +- +-/*-------------------------------------------------------------------------*/ +- +-/* Length of a SCSI Command Data Block */ +-#define MAX_COMMAND_SIZE 16 +- +-/* SCSI Sense Key/Additional Sense Code/ASC Qualifier values */ +-#define SS_NO_SENSE 0 +-#define SS_COMMUNICATION_FAILURE 0x040800 +-#define SS_INVALID_COMMAND 0x052000 +-#define SS_INVALID_FIELD_IN_CDB 0x052400 +-#define SS_LOGICAL_BLOCK_ADDRESS_OUT_OF_RANGE 0x052100 +-#define SS_LOGICAL_UNIT_NOT_SUPPORTED 0x052500 +-#define SS_MEDIUM_NOT_PRESENT 0x023a00 +-#define SS_MEDIUM_REMOVAL_PREVENTED 0x055302 +-#define SS_NOT_READY_TO_READY_TRANSITION 0x062800 +-#define SS_RESET_OCCURRED 0x062900 +-#define SS_SAVING_PARAMETERS_NOT_SUPPORTED 0x053900 +-#define SS_UNRECOVERED_READ_ERROR 0x031100 +-#define SS_WRITE_ERROR 0x030c02 +-#define SS_WRITE_PROTECTED 0x072700 +- +-#define SK(x) ((u8) ((x) >> 16)) /* Sense Key byte, etc. */ +-#define ASC(x) ((u8) ((x) >> 8)) +-#define ASCQ(x) ((u8) (x)) +- +- +-/*-------------------------------------------------------------------------*/ +- +- +-struct fsg_lun { +- struct file *filp; +- loff_t file_length; +- loff_t num_sectors; +- +- unsigned int initially_ro:1; +- unsigned int ro:1; +- unsigned int removable:1; +- unsigned int cdrom:1; +- unsigned int prevent_medium_removal:1; +- unsigned int registered:1; +- unsigned int info_valid:1; +- unsigned int nofua:1; +- +- u32 sense_data; +- u32 sense_data_info; +- u32 unit_attention_data; +- +- unsigned int blkbits; /* Bits of logical block size of bound block device */ +- unsigned int blksize; /* logical block size of bound block device */ +- struct device dev; +-}; +- +-static inline bool fsg_lun_is_open(struct fsg_lun *curlun) +-{ +- return curlun->filp != NULL; +-} +- +-static inline struct fsg_lun *fsg_lun_from_dev(struct device *dev) +-{ +- return container_of(dev, struct fsg_lun, dev); +-} +- +- +-/* Big enough to hold our biggest descriptor */ +-#define EP0_BUFSIZE 256 +-#define DELAYED_STATUS (EP0_BUFSIZE + 999) /* An impossibly large value */ +- +-#ifdef CONFIG_USB_GADGET_DEBUG_FILES +- +-static unsigned int fsg_num_buffers = CONFIG_USB_GADGET_STORAGE_NUM_BUFFERS; +-module_param_named(num_buffers, fsg_num_buffers, uint, S_IRUGO); +-MODULE_PARM_DESC(num_buffers, "Number of pipeline buffers"); +- +-#else +- +-/* +- * Number of buffers we will use. +- * 2 is usually enough for good buffering pipeline +- */ +-#define fsg_num_buffers CONFIG_USB_GADGET_STORAGE_NUM_BUFFERS +- +-#endif /* CONFIG_USB_GADGET_DEBUG_FILES */ +- +-/* check if fsg_num_buffers is within a valid range */ +-static inline int fsg_num_buffers_validate(void) +-{ +- if (fsg_num_buffers >= 2 && fsg_num_buffers <= 4) +- return 0; +- pr_err("fsg_num_buffers %u is out of range (%d to %d)\n", +- fsg_num_buffers, 2 ,4); +- return -EINVAL; +-} +- +-/* Default size of buffer length. */ +-#define FSG_BUFLEN ((u32)16384) +- +-/* Maximal number of LUNs supported in mass storage function */ +-#define FSG_MAX_LUNS 8 +- +-enum fsg_buffer_state { +- BUF_STATE_EMPTY = 0, +- BUF_STATE_FULL, +- BUF_STATE_BUSY +-}; +- +-struct fsg_buffhd { +- void *buf; +- enum fsg_buffer_state state; +- struct fsg_buffhd *next; +- +- /* +- * The NetChip 2280 is faster, and handles some protocol faults +- * better, if we don't submit any short bulk-out read requests. +- * So we will record the intended request length here. +- */ +- unsigned int bulk_out_intended_length; +- +- struct usb_request *inreq; +- int inreq_busy; +- struct usb_request *outreq; +- int outreq_busy; +-}; +- +-enum fsg_state { +- /* This one isn't used anywhere */ +- FSG_STATE_COMMAND_PHASE = -10, +- FSG_STATE_DATA_PHASE, +- FSG_STATE_STATUS_PHASE, +- +- FSG_STATE_IDLE = 0, +- FSG_STATE_ABORT_BULK_OUT, +- FSG_STATE_RESET, +- FSG_STATE_INTERFACE_CHANGE, +- FSG_STATE_CONFIG_CHANGE, +- FSG_STATE_DISCONNECT, +- FSG_STATE_EXIT, +- FSG_STATE_TERMINATED +-}; +- +-enum data_direction { +- DATA_DIR_UNKNOWN = 0, +- DATA_DIR_FROM_HOST, +- DATA_DIR_TO_HOST, +- DATA_DIR_NONE +-}; +- +- +-/*-------------------------------------------------------------------------*/ +- +- +-static inline u32 get_unaligned_be24(u8 *buf) +-{ +- return 0xffffff & (u32) get_unaligned_be32(buf - 1); +-} +- +- +-/*-------------------------------------------------------------------------*/ +- +- +-enum { +- FSG_STRING_INTERFACE +-}; +- ++#include "storage_common.h" + + /* There is only one interface. */ + +-static struct usb_interface_descriptor +-fsg_intf_desc = { ++struct usb_interface_descriptor fsg_intf_desc = { + .bLength = sizeof fsg_intf_desc, + .bDescriptorType = USB_DT_INTERFACE, + +@@ -268,14 +43,14 @@ fsg_intf_desc = { + .bInterfaceProtocol = USB_PR_BULK, /* Adjusted during fsg_bind() */ + .iInterface = FSG_STRING_INTERFACE, + }; ++EXPORT_SYMBOL(fsg_intf_desc); + + /* + * Three full-speed endpoint descriptors: bulk-in, bulk-out, and + * interrupt-in. + */ + +-static struct usb_endpoint_descriptor +-fsg_fs_bulk_in_desc = { ++struct usb_endpoint_descriptor fsg_fs_bulk_in_desc = { + .bLength = USB_DT_ENDPOINT_SIZE, + .bDescriptorType = USB_DT_ENDPOINT, + +@@ -283,9 +58,9 @@ fsg_fs_bulk_in_desc = { + .bmAttributes = USB_ENDPOINT_XFER_BULK, + /* wMaxPacketSize set by autoconfiguration */ + }; ++EXPORT_SYMBOL(fsg_fs_bulk_in_desc); + +-static struct usb_endpoint_descriptor +-fsg_fs_bulk_out_desc = { ++struct usb_endpoint_descriptor fsg_fs_bulk_out_desc = { + .bLength = USB_DT_ENDPOINT_SIZE, + .bDescriptorType = USB_DT_ENDPOINT, + +@@ -293,13 +68,15 @@ fsg_fs_bulk_out_desc = { + .bmAttributes = USB_ENDPOINT_XFER_BULK, + /* wMaxPacketSize set by autoconfiguration */ + }; ++EXPORT_SYMBOL(fsg_fs_bulk_out_desc); + +-static struct usb_descriptor_header *fsg_fs_function[] = { ++struct usb_descriptor_header *fsg_fs_function[] = { + (struct usb_descriptor_header *) &fsg_intf_desc, + (struct usb_descriptor_header *) &fsg_fs_bulk_in_desc, + (struct usb_descriptor_header *) &fsg_fs_bulk_out_desc, + NULL, + }; ++EXPORT_SYMBOL(fsg_fs_function); + + + /* +@@ -310,8 +87,7 @@ static struct usb_descriptor_header *fsg + * and a "device qualifier" ... plus more construction options + * for the configuration descriptor. + */ +-static struct usb_endpoint_descriptor +-fsg_hs_bulk_in_desc = { ++struct usb_endpoint_descriptor fsg_hs_bulk_in_desc = { + .bLength = USB_DT_ENDPOINT_SIZE, + .bDescriptorType = USB_DT_ENDPOINT, + +@@ -319,9 +95,9 @@ fsg_hs_bulk_in_desc = { + .bmAttributes = USB_ENDPOINT_XFER_BULK, + .wMaxPacketSize = cpu_to_le16(512), + }; ++EXPORT_SYMBOL(fsg_hs_bulk_in_desc); + +-static struct usb_endpoint_descriptor +-fsg_hs_bulk_out_desc = { ++struct usb_endpoint_descriptor fsg_hs_bulk_out_desc = { + .bLength = USB_DT_ENDPOINT_SIZE, + .bDescriptorType = USB_DT_ENDPOINT, + +@@ -330,17 +106,18 @@ fsg_hs_bulk_out_desc = { + .wMaxPacketSize = cpu_to_le16(512), + .bInterval = 1, /* NAK every 1 uframe */ + }; ++EXPORT_SYMBOL(fsg_hs_bulk_out_desc); + + +-static struct usb_descriptor_header *fsg_hs_function[] = { ++struct usb_descriptor_header *fsg_hs_function[] = { + (struct usb_descriptor_header *) &fsg_intf_desc, + (struct usb_descriptor_header *) &fsg_hs_bulk_in_desc, + (struct usb_descriptor_header *) &fsg_hs_bulk_out_desc, + NULL, + }; ++EXPORT_SYMBOL(fsg_hs_function); + +-static struct usb_endpoint_descriptor +-fsg_ss_bulk_in_desc = { ++struct usb_endpoint_descriptor fsg_ss_bulk_in_desc = { + .bLength = USB_DT_ENDPOINT_SIZE, + .bDescriptorType = USB_DT_ENDPOINT, + +@@ -348,16 +125,17 @@ fsg_ss_bulk_in_desc = { + .bmAttributes = USB_ENDPOINT_XFER_BULK, + .wMaxPacketSize = cpu_to_le16(1024), + }; ++EXPORT_SYMBOL(fsg_ss_bulk_in_desc); + +-static struct usb_ss_ep_comp_descriptor fsg_ss_bulk_in_comp_desc = { ++struct usb_ss_ep_comp_descriptor fsg_ss_bulk_in_comp_desc = { + .bLength = sizeof(fsg_ss_bulk_in_comp_desc), + .bDescriptorType = USB_DT_SS_ENDPOINT_COMP, + + /*.bMaxBurst = DYNAMIC, */ + }; ++EXPORT_SYMBOL(fsg_ss_bulk_in_comp_desc); + +-static struct usb_endpoint_descriptor +-fsg_ss_bulk_out_desc = { ++struct usb_endpoint_descriptor fsg_ss_bulk_out_desc = { + .bLength = USB_DT_ENDPOINT_SIZE, + .bDescriptorType = USB_DT_ENDPOINT, + +@@ -365,15 +143,17 @@ fsg_ss_bulk_out_desc = { + .bmAttributes = USB_ENDPOINT_XFER_BULK, + .wMaxPacketSize = cpu_to_le16(1024), + }; ++EXPORT_SYMBOL(fsg_ss_bulk_out_desc); + +-static struct usb_ss_ep_comp_descriptor fsg_ss_bulk_out_comp_desc = { ++struct usb_ss_ep_comp_descriptor fsg_ss_bulk_out_comp_desc = { + .bLength = sizeof(fsg_ss_bulk_in_comp_desc), + .bDescriptorType = USB_DT_SS_ENDPOINT_COMP, + + /*.bMaxBurst = DYNAMIC, */ + }; ++EXPORT_SYMBOL(fsg_ss_bulk_out_comp_desc); + +-static struct usb_descriptor_header *fsg_ss_function[] = { ++struct usb_descriptor_header *fsg_ss_function[] = { + (struct usb_descriptor_header *) &fsg_intf_desc, + (struct usb_descriptor_header *) &fsg_ss_bulk_in_desc, + (struct usb_descriptor_header *) &fsg_ss_bulk_in_comp_desc, +@@ -381,17 +161,7 @@ static struct usb_descriptor_header *fsg + (struct usb_descriptor_header *) &fsg_ss_bulk_out_comp_desc, + NULL, + }; +- +-/* Static strings, in UTF-8 (for simplicity we use only ASCII characters) */ +-static struct usb_string fsg_strings[] = { +- {FSG_STRING_INTERFACE, fsg_string_interface}, +- {} +-}; +- +-static struct usb_gadget_strings fsg_stringtab = { +- .language = 0x0409, /* en-us */ +- .strings = fsg_strings, +-}; ++EXPORT_SYMBOL(fsg_ss_function); + + + /*-------------------------------------------------------------------------*/ +@@ -401,7 +171,7 @@ static struct usb_gadget_strings fsg_str + * the caller must own fsg->filesem for writing. + */ + +-static void fsg_lun_close(struct fsg_lun *curlun) ++void fsg_lun_close(struct fsg_lun *curlun) + { + if (curlun->filp) { + LDBG(curlun, "close backing file\n"); +@@ -409,9 +179,9 @@ static void fsg_lun_close(struct fsg_lun + curlun->filp = NULL; + } + } ++EXPORT_SYMBOL(fsg_lun_close); + +- +-static int fsg_lun_open(struct fsg_lun *curlun, const char *filename) ++int fsg_lun_open(struct fsg_lun *curlun, const char *filename) + { + int ro; + struct file *filp = NULL; +@@ -508,6 +278,7 @@ out: + fput(filp); + return rc; + } ++EXPORT_SYMBOL(fsg_lun_open); + + + /*-------------------------------------------------------------------------*/ +@@ -516,7 +287,7 @@ out: + * Sync the file data, don't bother with the metadata. + * This code was copied from fs/buffer.c:sys_fdatasync(). + */ +-static int fsg_lun_fsync_sub(struct fsg_lun *curlun) ++int fsg_lun_fsync_sub(struct fsg_lun *curlun) + { + struct file *filp = curlun->filp; + +@@ -524,8 +295,9 @@ static int fsg_lun_fsync_sub(struct fsg_ + return 0; + return vfs_fsync(filp, 1); + } ++EXPORT_SYMBOL(fsg_lun_fsync_sub); + +-static void store_cdrom_address(u8 *dest, int msf, u32 addr) ++void store_cdrom_address(u8 *dest, int msf, u32 addr) + { + if (msf) { + /* Convert to Minutes-Seconds-Frames */ +@@ -542,34 +314,28 @@ static void store_cdrom_address(u8 *dest + put_unaligned_be32(addr, dest); + } + } +- ++EXPORT_SYMBOL(store_cdrom_address); + + /*-------------------------------------------------------------------------*/ + + +-static ssize_t ro_show(struct device *dev, struct device_attribute *attr, +- char *buf) ++ssize_t fsg_show_ro(struct fsg_lun *curlun, char *buf) + { +- struct fsg_lun *curlun = fsg_lun_from_dev(dev); +- + return sprintf(buf, "%d\n", fsg_lun_is_open(curlun) + ? curlun->ro + : curlun->initially_ro); + } ++EXPORT_SYMBOL(fsg_show_ro); + +-static ssize_t nofua_show(struct device *dev, struct device_attribute *attr, +- char *buf) ++ssize_t fsg_show_nofua(struct fsg_lun *curlun, char *buf) + { +- struct fsg_lun *curlun = fsg_lun_from_dev(dev); +- + return sprintf(buf, "%u\n", curlun->nofua); + } ++EXPORT_SYMBOL(fsg_show_nofua); + +-static ssize_t file_show(struct device *dev, struct device_attribute *attr, +- char *buf) ++ssize_t fsg_show_file(struct fsg_lun *curlun, struct rw_semaphore *filesem, ++ char *buf) + { +- struct fsg_lun *curlun = fsg_lun_from_dev(dev); +- struct rw_semaphore *filesem = dev_get_drvdata(dev); + char *p; + ssize_t rc; + +@@ -591,17 +357,44 @@ static ssize_t file_show(struct device * + up_read(filesem); + return rc; + } ++EXPORT_SYMBOL(fsg_show_file); + ++ssize_t fsg_show_cdrom(struct fsg_lun *curlun, char *buf) ++{ ++ return sprintf(buf, "%u\n", curlun->cdrom); ++} ++EXPORT_SYMBOL(fsg_show_cdrom); + +-static ssize_t ro_store(struct device *dev, struct device_attribute *attr, +- const char *buf, size_t count) ++ssize_t fsg_show_removable(struct fsg_lun *curlun, char *buf) ++{ ++ return sprintf(buf, "%u\n", curlun->removable); ++} ++EXPORT_SYMBOL(fsg_show_removable); ++ ++/* ++ * The caller must hold fsg->filesem for reading when calling this function. ++ */ ++static ssize_t _fsg_store_ro(struct fsg_lun *curlun, bool ro) ++{ ++ if (fsg_lun_is_open(curlun)) { ++ LDBG(curlun, "read-only status change prevented\n"); ++ return -EBUSY; ++ } ++ ++ curlun->ro = ro; ++ curlun->initially_ro = ro; ++ LDBG(curlun, "read-only status set to %d\n", curlun->ro); ++ ++ return 0; ++} ++ ++ssize_t fsg_store_ro(struct fsg_lun *curlun, struct rw_semaphore *filesem, ++ const char *buf, size_t count) + { + ssize_t rc; +- struct fsg_lun *curlun = fsg_lun_from_dev(dev); +- struct rw_semaphore *filesem = dev_get_drvdata(dev); +- unsigned ro; ++ bool ro; + +- rc = kstrtouint(buf, 2, &ro); ++ rc = strtobool(buf, &ro); + if (rc) + return rc; + +@@ -610,27 +403,21 @@ static ssize_t ro_store(struct device *d + * backing file is closed. + */ + down_read(filesem); +- if (fsg_lun_is_open(curlun)) { +- LDBG(curlun, "read-only status change prevented\n"); +- rc = -EBUSY; +- } else { +- curlun->ro = ro; +- curlun->initially_ro = ro; +- LDBG(curlun, "read-only status set to %d\n", curlun->ro); ++ rc = _fsg_store_ro(curlun, ro); ++ if (!rc) + rc = count; +- } + up_read(filesem); ++ + return rc; + } ++EXPORT_SYMBOL(fsg_store_ro); + +-static ssize_t nofua_store(struct device *dev, struct device_attribute *attr, +- const char *buf, size_t count) ++ssize_t fsg_store_nofua(struct fsg_lun *curlun, const char *buf, size_t count) + { +- struct fsg_lun *curlun = fsg_lun_from_dev(dev); +- unsigned nofua; ++ bool nofua; + int ret; + +- ret = kstrtouint(buf, 2, &nofua); ++ ret = strtobool(buf, &nofua); + if (ret) + return ret; + +@@ -642,12 +429,11 @@ static ssize_t nofua_store(struct device + + return count; + } ++EXPORT_SYMBOL(fsg_store_nofua); + +-static ssize_t file_store(struct device *dev, struct device_attribute *attr, +- const char *buf, size_t count) ++ssize_t fsg_store_file(struct fsg_lun *curlun, struct rw_semaphore *filesem, ++ const char *buf, size_t count) + { +- struct fsg_lun *curlun = fsg_lun_from_dev(dev); +- struct rw_semaphore *filesem = dev_get_drvdata(dev); + int rc = 0; + + if (curlun->prevent_medium_removal && fsg_lun_is_open(curlun)) { +@@ -674,3 +460,45 @@ static ssize_t file_store(struct device + up_write(filesem); + return (rc < 0 ? rc : count); + } ++EXPORT_SYMBOL(fsg_store_file); ++ ++ssize_t fsg_store_cdrom(struct fsg_lun *curlun, struct rw_semaphore *filesem, ++ const char *buf, size_t count) ++{ ++ bool cdrom; ++ int ret; ++ ++ ret = strtobool(buf, &cdrom); ++ if (ret) ++ return ret; ++ ++ down_read(filesem); ++ ret = cdrom ? _fsg_store_ro(curlun, true) : 0; ++ ++ if (!ret) { ++ curlun->cdrom = cdrom; ++ ret = count; ++ } ++ up_read(filesem); ++ ++ return ret; ++} ++EXPORT_SYMBOL(fsg_store_cdrom); ++ ++ssize_t fsg_store_removable(struct fsg_lun *curlun, const char *buf, ++ size_t count) ++{ ++ bool removable; ++ int ret; ++ ++ ret = strtobool(buf, &removable); ++ if (ret) ++ return ret; ++ ++ curlun->removable = removable; ++ ++ return count; ++} ++EXPORT_SYMBOL(fsg_store_removable); ++ ++MODULE_LICENSE("GPL"); +--- /dev/null ++++ b/drivers/usb/gadget/storage_common.h +@@ -0,0 +1,229 @@ ++#ifndef USB_STORAGE_COMMON_H ++#define USB_STORAGE_COMMON_H ++ ++#include <linux/device.h> ++#include <linux/usb/storage.h> ++#include <scsi/scsi.h> ++#include <asm/unaligned.h> ++ ++#ifndef DEBUG ++#undef VERBOSE_DEBUG ++#undef DUMP_MSGS ++#endif /* !DEBUG */ ++ ++#ifdef VERBOSE_DEBUG ++#define VLDBG LDBG ++#else ++#define VLDBG(lun, fmt, args...) do { } while (0) ++#endif /* VERBOSE_DEBUG */ ++ ++#define _LMSG(func, lun, fmt, args...) \ ++ do { \ ++ if ((lun)->name_pfx && *(lun)->name_pfx) \ ++ func("%s/%s: " fmt, *(lun)->name_pfx, \ ++ (lun)->name, ## args); \ ++ else \ ++ func("%s: " fmt, (lun)->name, ## args); \ ++ } while (0) ++ ++#define LDBG(lun, fmt, args...) _LMSG(pr_debug, lun, fmt, ## args) ++#define LERROR(lun, fmt, args...) _LMSG(pr_err, lun, fmt, ## args) ++#define LWARN(lun, fmt, args...) _LMSG(pr_warn, lun, fmt, ## args) ++#define LINFO(lun, fmt, args...) _LMSG(pr_info, lun, fmt, ## args) ++ ++ ++#ifdef DUMP_MSGS ++ ++# define dump_msg(fsg, /* const char * */ label, \ ++ /* const u8 * */ buf, /* unsigned */ length) \ ++do { \ ++ if (length < 512) { \ ++ DBG(fsg, "%s, length %u:\n", label, length); \ ++ print_hex_dump(KERN_DEBUG, "", DUMP_PREFIX_OFFSET, \ ++ 16, 1, buf, length, 0); \ ++ } \ ++} while (0) ++ ++# define dump_cdb(fsg) do { } while (0) ++ ++#else ++ ++# define dump_msg(fsg, /* const char * */ label, \ ++ /* const u8 * */ buf, /* unsigned */ length) do { } while (0) ++ ++# ifdef VERBOSE_DEBUG ++ ++# define dump_cdb(fsg) \ ++ print_hex_dump(KERN_DEBUG, "SCSI CDB: ", DUMP_PREFIX_NONE, \ ++ 16, 1, (fsg)->cmnd, (fsg)->cmnd_size, 0) \ ++ ++# else ++ ++# define dump_cdb(fsg) do { } while (0) ++ ++# endif /* VERBOSE_DEBUG */ ++ ++#endif /* DUMP_MSGS */ ++ ++/* Length of a SCSI Command Data Block */ ++#define MAX_COMMAND_SIZE 16 ++ ++/* SCSI Sense Key/Additional Sense Code/ASC Qualifier values */ ++#define SS_NO_SENSE 0 ++#define SS_COMMUNICATION_FAILURE 0x040800 ++#define SS_INVALID_COMMAND 0x052000 ++#define SS_INVALID_FIELD_IN_CDB 0x052400 ++#define SS_LOGICAL_BLOCK_ADDRESS_OUT_OF_RANGE 0x052100 ++#define SS_LOGICAL_UNIT_NOT_SUPPORTED 0x052500 ++#define SS_MEDIUM_NOT_PRESENT 0x023a00 ++#define SS_MEDIUM_REMOVAL_PREVENTED 0x055302 ++#define SS_NOT_READY_TO_READY_TRANSITION 0x062800 ++#define SS_RESET_OCCURRED 0x062900 ++#define SS_SAVING_PARAMETERS_NOT_SUPPORTED 0x053900 ++#define SS_UNRECOVERED_READ_ERROR 0x031100 ++#define SS_WRITE_ERROR 0x030c02 ++#define SS_WRITE_PROTECTED 0x072700 ++ ++#define SK(x) ((u8) ((x) >> 16)) /* Sense Key byte, etc. */ ++#define ASC(x) ((u8) ((x) >> 8)) ++#define ASCQ(x) ((u8) (x)) ++ ++struct fsg_lun { ++ struct file *filp; ++ loff_t file_length; ++ loff_t num_sectors; ++ ++ unsigned int initially_ro:1; ++ unsigned int ro:1; ++ unsigned int removable:1; ++ unsigned int cdrom:1; ++ unsigned int prevent_medium_removal:1; ++ unsigned int registered:1; ++ unsigned int info_valid:1; ++ unsigned int nofua:1; ++ ++ u32 sense_data; ++ u32 sense_data_info; ++ u32 unit_attention_data; ++ ++ unsigned int blkbits; /* Bits of logical block size ++ of bound block device */ ++ unsigned int blksize; /* logical block size of bound block device */ ++ struct device dev; ++ const char *name; /* "lun.name" */ ++ const char **name_pfx; /* "function.name" */ ++}; ++ ++static inline bool fsg_lun_is_open(struct fsg_lun *curlun) ++{ ++ return curlun->filp != NULL; ++} ++ ++/* Big enough to hold our biggest descriptor */ ++#define EP0_BUFSIZE 256 ++#define DELAYED_STATUS (EP0_BUFSIZE + 999) /* An impossibly large value */ ++ ++/* Default size of buffer length. */ ++#define FSG_BUFLEN ((u32)16384) ++ ++/* Maximal number of LUNs supported in mass storage function */ ++#define FSG_MAX_LUNS 8 ++ ++enum fsg_buffer_state { ++ BUF_STATE_EMPTY = 0, ++ BUF_STATE_FULL, ++ BUF_STATE_BUSY ++}; ++ ++struct fsg_buffhd { ++ void *buf; ++ enum fsg_buffer_state state; ++ struct fsg_buffhd *next; ++ ++ /* ++ * The NetChip 2280 is faster, and handles some protocol faults ++ * better, if we don't submit any short bulk-out read requests. ++ * So we will record the intended request length here. ++ */ ++ unsigned int bulk_out_intended_length; ++ ++ struct usb_request *inreq; ++ int inreq_busy; ++ struct usb_request *outreq; ++ int outreq_busy; ++}; ++ ++enum fsg_state { ++ /* This one isn't used anywhere */ ++ FSG_STATE_COMMAND_PHASE = -10, ++ FSG_STATE_DATA_PHASE, ++ FSG_STATE_STATUS_PHASE, ++ ++ FSG_STATE_IDLE = 0, ++ FSG_STATE_ABORT_BULK_OUT, ++ FSG_STATE_RESET, ++ FSG_STATE_INTERFACE_CHANGE, ++ FSG_STATE_CONFIG_CHANGE, ++ FSG_STATE_DISCONNECT, ++ FSG_STATE_EXIT, ++ FSG_STATE_TERMINATED ++}; ++ ++enum data_direction { ++ DATA_DIR_UNKNOWN = 0, ++ DATA_DIR_FROM_HOST, ++ DATA_DIR_TO_HOST, ++ DATA_DIR_NONE ++}; ++ ++static inline u32 get_unaligned_be24(u8 *buf) ++{ ++ return 0xffffff & (u32) get_unaligned_be32(buf - 1); ++} ++ ++static inline struct fsg_lun *fsg_lun_from_dev(struct device *dev) ++{ ++ return container_of(dev, struct fsg_lun, dev); ++} ++ ++enum { ++ FSG_STRING_INTERFACE ++}; ++ ++extern struct usb_interface_descriptor fsg_intf_desc; ++ ++extern struct usb_endpoint_descriptor fsg_fs_bulk_in_desc; ++extern struct usb_endpoint_descriptor fsg_fs_bulk_out_desc; ++extern struct usb_descriptor_header *fsg_fs_function[]; ++ ++extern struct usb_endpoint_descriptor fsg_hs_bulk_in_desc; ++extern struct usb_endpoint_descriptor fsg_hs_bulk_out_desc; ++extern struct usb_descriptor_header *fsg_hs_function[]; ++ ++extern struct usb_endpoint_descriptor fsg_ss_bulk_in_desc; ++extern struct usb_ss_ep_comp_descriptor fsg_ss_bulk_in_comp_desc; ++extern struct usb_endpoint_descriptor fsg_ss_bulk_out_desc; ++extern struct usb_ss_ep_comp_descriptor fsg_ss_bulk_out_comp_desc; ++extern struct usb_descriptor_header *fsg_ss_function[]; ++ ++void fsg_lun_close(struct fsg_lun *curlun); ++int fsg_lun_open(struct fsg_lun *curlun, const char *filename); ++int fsg_lun_fsync_sub(struct fsg_lun *curlun); ++void store_cdrom_address(u8 *dest, int msf, u32 addr); ++ssize_t fsg_show_ro(struct fsg_lun *curlun, char *buf); ++ssize_t fsg_show_nofua(struct fsg_lun *curlun, char *buf); ++ssize_t fsg_show_file(struct fsg_lun *curlun, struct rw_semaphore *filesem, ++ char *buf); ++ssize_t fsg_show_cdrom(struct fsg_lun *curlun, char *buf); ++ssize_t fsg_show_removable(struct fsg_lun *curlun, char *buf); ++ssize_t fsg_store_ro(struct fsg_lun *curlun, struct rw_semaphore *filesem, ++ const char *buf, size_t count); ++ssize_t fsg_store_nofua(struct fsg_lun *curlun, const char *buf, size_t count); ++ssize_t fsg_store_file(struct fsg_lun *curlun, struct rw_semaphore *filesem, ++ const char *buf, size_t count); ++ssize_t fsg_store_cdrom(struct fsg_lun *curlun, struct rw_semaphore *filesem, ++ const char *buf, size_t count); ++ssize_t fsg_store_removable(struct fsg_lun *curlun, const char *buf, ++ size_t count); ++ ++#endif /* USB_STORAGE_COMMON_H */ +--- a/drivers/usb/gadget/udc-core.c ++++ b/drivers/usb/gadget/udc-core.c +@@ -356,7 +356,8 @@ static int udc_bind_to_driver(struct usb + kobject_uevent(&udc->dev.kobj, KOBJ_CHANGE); + return 0; + err1: +- dev_err(&udc->dev, "failed to start %s: %d\n", ++ if (ret != -EISNAM) ++ dev_err(&udc->dev, "failed to start %s: %d\n", + udc->driver->function, ret); + udc->driver = NULL; + udc->dev.driver = NULL; +--- a/drivers/usb/gadget/zero.c ++++ b/drivers/usb/gadget/zero.c +@@ -95,6 +95,18 @@ unsigned autoresume = DEFAULT_AUTORESUME + module_param(autoresume, uint, S_IRUGO); + MODULE_PARM_DESC(autoresume, "zero, or seconds before remote wakeup"); + ++/* Maximum Autoresume time */ ++unsigned max_autoresume; ++module_param(max_autoresume, uint, S_IRUGO); ++MODULE_PARM_DESC(max_autoresume, "maximum seconds before remote wakeup"); ++ ++/* Interval between two remote wakeups */ ++unsigned autoresume_interval_ms; ++module_param(autoresume_interval_ms, uint, S_IRUGO); ++MODULE_PARM_DESC(autoresume_interval_ms, ++ "milliseconds to increase successive wakeup delays"); ++ ++static unsigned autoresume_step_ms; + /*-------------------------------------------------------------------------*/ + + static struct usb_device_descriptor device_desc = { +@@ -183,8 +195,16 @@ static void zero_suspend(struct usb_comp + return; + + if (autoresume) { +- mod_timer(&autoresume_timer, jiffies + (HZ * autoresume)); +- DBG(cdev, "suspend, wakeup in %d seconds\n", autoresume); ++ if (max_autoresume && ++ (autoresume_step_ms > max_autoresume * 1000)) ++ autoresume_step_ms = autoresume * 1000; ++ ++ mod_timer(&autoresume_timer, jiffies + ++ msecs_to_jiffies(autoresume_step_ms)); ++ DBG(cdev, "suspend, wakeup in %d milliseconds\n", ++ autoresume_step_ms); ++ ++ autoresume_step_ms += autoresume_interval_ms; + } else + DBG(cdev, "%s\n", __func__); + } +@@ -316,6 +336,7 @@ static int __init zero_bind(struct usb_c + if (autoresume) { + sourcesink_driver.bmAttributes |= USB_CONFIG_ATT_WAKEUP; + loopback_driver.bmAttributes |= USB_CONFIG_ATT_WAKEUP; ++ autoresume_step_ms = autoresume * 1000; + } + + /* support OTG systems */ +--- a/drivers/usb/misc/usbtest.c ++++ b/drivers/usb/misc/usbtest.c +@@ -120,7 +120,7 @@ get_endpoints(struct usbtest_dev *dev, s + struct usb_host_endpoint *e; + + e = alt->endpoint + ep; +- switch (e->desc.bmAttributes) { ++ switch (usb_endpoint_type(&e->desc)) { + case USB_ENDPOINT_XFER_BULK: + break; + case USB_ENDPOINT_XFER_ISOC: +--- a/drivers/usb/musb/am35x.c ++++ b/drivers/usb/musb/am35x.c +@@ -89,7 +89,6 @@ struct am35x_glue { + struct clk *phy_clk; + struct clk *clk; + }; +-#define glue_to_musb(g) platform_get_drvdata(g->musb) + + /* + * am35x_musb_enable - enable interrupts +@@ -452,14 +451,18 @@ static const struct musb_platform_ops am + .set_vbus = am35x_musb_set_vbus, + }; + +-static u64 am35x_dmamask = DMA_BIT_MASK(32); ++static const struct platform_device_info am35x_dev_info = { ++ .name = "musb-hdrc", ++ .id = PLATFORM_DEVID_AUTO, ++ .dma_mask = DMA_BIT_MASK(32), ++}; + + static int am35x_probe(struct platform_device *pdev) + { + struct musb_hdrc_platform_data *pdata = dev_get_platdata(&pdev->dev); + struct platform_device *musb; + struct am35x_glue *glue; +- ++ struct platform_device_info pinfo; + struct clk *phy_clk; + struct clk *clk; + +@@ -471,12 +474,6 @@ static int am35x_probe(struct platform_d + goto err0; + } + +- musb = platform_device_alloc("musb-hdrc", PLATFORM_DEVID_AUTO); +- if (!musb) { +- dev_err(&pdev->dev, "failed to allocate musb device\n"); +- goto err1; +- } +- + phy_clk = clk_get(&pdev->dev, "fck"); + if (IS_ERR(phy_clk)) { + dev_err(&pdev->dev, "failed to get PHY clock\n"); +@@ -503,12 +500,7 @@ static int am35x_probe(struct platform_d + goto err6; + } + +- musb->dev.parent = &pdev->dev; +- musb->dev.dma_mask = &am35x_dmamask; +- musb->dev.coherent_dma_mask = am35x_dmamask; +- + glue->dev = &pdev->dev; +- glue->musb = musb; + glue->phy_clk = phy_clk; + glue->clk = clk; + +@@ -516,22 +508,17 @@ static int am35x_probe(struct platform_d + + platform_set_drvdata(pdev, glue); + +- ret = platform_device_add_resources(musb, pdev->resource, +- pdev->num_resources); +- if (ret) { +- dev_err(&pdev->dev, "failed to add resources\n"); +- goto err7; +- } +- +- ret = platform_device_add_data(musb, pdata, sizeof(*pdata)); +- if (ret) { +- dev_err(&pdev->dev, "failed to add platform_data\n"); +- goto err7; +- } +- +- ret = platform_device_add(musb); +- if (ret) { +- dev_err(&pdev->dev, "failed to register musb device\n"); ++ pinfo = am35x_dev_info; ++ pinfo.parent = &pdev->dev; ++ pinfo.res = pdev->resource; ++ pinfo.num_res = pdev->num_resources; ++ pinfo.data = pdata; ++ pinfo.size_data = sizeof(*pdata); ++ ++ glue->musb = musb = platform_device_register_full(&pinfo); ++ if (IS_ERR(musb)) { ++ ret = PTR_ERR(musb); ++ dev_err(&pdev->dev, "failed to register musb device: %d\n", ret); + goto err7; + } + +@@ -550,9 +537,6 @@ err4: + clk_put(phy_clk); + + err3: +- platform_device_put(musb); +- +-err1: + kfree(glue); + + err0: +@@ -615,23 +599,16 @@ static int am35x_resume(struct device *d + + return 0; + } +- +-static struct dev_pm_ops am35x_pm_ops = { +- .suspend = am35x_suspend, +- .resume = am35x_resume, +-}; +- +-#define DEV_PM_OPS &am35x_pm_ops +-#else +-#define DEV_PM_OPS NULL + #endif + ++static SIMPLE_DEV_PM_OPS(am35x_pm_ops, am35x_suspend, am35x_resume); ++ + static struct platform_driver am35x_driver = { + .probe = am35x_probe, + .remove = am35x_remove, + .driver = { + .name = "musb-am35x", +- .pm = DEV_PM_OPS, ++ .pm = &am35x_pm_ops, + }, + }; + +--- a/drivers/usb/musb/blackfin.c ++++ b/drivers/usb/musb/blackfin.c +@@ -561,23 +561,16 @@ static int bfin_resume(struct device *de + + return 0; + } +- +-static struct dev_pm_ops bfin_pm_ops = { +- .suspend = bfin_suspend, +- .resume = bfin_resume, +-}; +- +-#define DEV_PM_OPS &bfin_pm_ops +-#else +-#define DEV_PM_OPS NULL + #endif + ++static SIMPLE_DEV_PM_OPS(bfin_pm_ops, bfin_suspend, bfin_resume); ++ + static struct platform_driver bfin_driver = { + .probe = bfin_probe, + .remove = __exit_p(bfin_remove), + .driver = { + .name = "musb-blackfin", +- .pm = DEV_PM_OPS, ++ .pm = &bfin_pm_ops, + }, + }; + +--- a/drivers/usb/musb/da8xx.c ++++ b/drivers/usb/musb/da8xx.c +@@ -472,7 +472,11 @@ static const struct musb_platform_ops da + .set_vbus = da8xx_musb_set_vbus, + }; + +-static u64 da8xx_dmamask = DMA_BIT_MASK(32); ++static const struct platform_device_info da8xx_dev_info = { ++ .name = "musb-hdrc", ++ .id = PLATFORM_DEVID_AUTO, ++ .dma_mask = DMA_BIT_MASK(32), ++}; + + static int da8xx_probe(struct platform_device *pdev) + { +@@ -480,7 +484,7 @@ static int da8xx_probe(struct platform_d + struct musb_hdrc_platform_data *pdata = dev_get_platdata(&pdev->dev); + struct platform_device *musb; + struct da8xx_glue *glue; +- ++ struct platform_device_info pinfo; + struct clk *clk; + + int ret = -ENOMEM; +@@ -491,12 +495,6 @@ static int da8xx_probe(struct platform_d + goto err0; + } + +- musb = platform_device_alloc("musb-hdrc", PLATFORM_DEVID_AUTO); +- if (!musb) { +- dev_err(&pdev->dev, "failed to allocate musb device\n"); +- goto err1; +- } +- + clk = clk_get(&pdev->dev, "usb20"); + if (IS_ERR(clk)) { + dev_err(&pdev->dev, "failed to get clock\n"); +@@ -510,12 +508,7 @@ static int da8xx_probe(struct platform_d + goto err4; + } + +- musb->dev.parent = &pdev->dev; +- musb->dev.dma_mask = &da8xx_dmamask; +- musb->dev.coherent_dma_mask = da8xx_dmamask; +- + glue->dev = &pdev->dev; +- glue->musb = musb; + glue->clk = clk; + + pdata->platform_ops = &da8xx_ops; +@@ -535,22 +528,17 @@ static int da8xx_probe(struct platform_d + musb_resources[1].end = pdev->resource[1].end; + musb_resources[1].flags = pdev->resource[1].flags; + +- ret = platform_device_add_resources(musb, musb_resources, +- ARRAY_SIZE(musb_resources)); +- if (ret) { +- dev_err(&pdev->dev, "failed to add resources\n"); +- goto err5; +- } +- +- ret = platform_device_add_data(musb, pdata, sizeof(*pdata)); +- if (ret) { +- dev_err(&pdev->dev, "failed to add platform_data\n"); +- goto err5; +- } +- +- ret = platform_device_add(musb); +- if (ret) { +- dev_err(&pdev->dev, "failed to register musb device\n"); ++ pinfo = da8xx_dev_info; ++ pinfo.parent = &pdev->dev; ++ pinfo.res = musb_resources; ++ pinfo.num_res = ARRAY_SIZE(musb_resources); ++ pinfo.data = pdata; ++ pinfo.size_data = sizeof(*pdata); ++ ++ glue->musb = musb = platform_device_register_full(&pinfo); ++ if (IS_ERR(musb)) { ++ ret = PTR_ERR(musb); ++ dev_err(&pdev->dev, "failed to register musb device: %d\n", ret); + goto err5; + } + +@@ -563,9 +551,6 @@ err4: + clk_put(clk); + + err3: +- platform_device_put(musb); +- +-err1: + kfree(glue); + + err0: +--- a/drivers/usb/musb/davinci.c ++++ b/drivers/usb/musb/davinci.c +@@ -505,14 +505,19 @@ static const struct musb_platform_ops da + .set_vbus = davinci_musb_set_vbus, + }; + +-static u64 davinci_dmamask = DMA_BIT_MASK(32); ++static const struct platform_device_info davinci_dev_info = { ++ .name = "musb-hdrc", ++ .id = PLATFORM_DEVID_AUTO, ++ .dma_mask = DMA_BIT_MASK(32), ++}; + + static int davinci_probe(struct platform_device *pdev) + { +- struct resource musb_resources[2]; ++ struct resource musb_resources[3]; + struct musb_hdrc_platform_data *pdata = dev_get_platdata(&pdev->dev); + struct platform_device *musb; + struct davinci_glue *glue; ++ struct platform_device_info pinfo; + struct clk *clk; + + int ret = -ENOMEM; +@@ -523,12 +528,6 @@ static int davinci_probe(struct platform + goto err0; + } + +- musb = platform_device_alloc("musb-hdrc", PLATFORM_DEVID_AUTO); +- if (!musb) { +- dev_err(&pdev->dev, "failed to allocate musb device\n"); +- goto err1; +- } +- + clk = clk_get(&pdev->dev, "usb"); + if (IS_ERR(clk)) { + dev_err(&pdev->dev, "failed to get clock\n"); +@@ -542,12 +541,7 @@ static int davinci_probe(struct platform + goto err4; + } + +- musb->dev.parent = &pdev->dev; +- musb->dev.dma_mask = &davinci_dmamask; +- musb->dev.coherent_dma_mask = davinci_dmamask; +- + glue->dev = &pdev->dev; +- glue->musb = musb; + glue->clk = clk; + + pdata->platform_ops = &davinci_ops; +@@ -567,22 +561,26 @@ static int davinci_probe(struct platform + musb_resources[1].end = pdev->resource[1].end; + musb_resources[1].flags = pdev->resource[1].flags; + +- ret = platform_device_add_resources(musb, musb_resources, +- ARRAY_SIZE(musb_resources)); +- if (ret) { +- dev_err(&pdev->dev, "failed to add resources\n"); +- goto err5; +- } +- +- ret = platform_device_add_data(musb, pdata, sizeof(*pdata)); +- if (ret) { +- dev_err(&pdev->dev, "failed to add platform_data\n"); +- goto err5; +- } +- +- ret = platform_device_add(musb); +- if (ret) { +- dev_err(&pdev->dev, "failed to register musb device\n"); ++ /* ++ * For DM6467 3 resources are passed. A placeholder for the 3rd ++ * resource is always there, so it's safe to always copy it... ++ */ ++ musb_resources[2].name = pdev->resource[2].name; ++ musb_resources[2].start = pdev->resource[2].start; ++ musb_resources[2].end = pdev->resource[2].end; ++ musb_resources[2].flags = pdev->resource[2].flags; ++ ++ pinfo = davinci_dev_info; ++ pinfo.parent = &pdev->dev; ++ pinfo.res = musb_resources; ++ pinfo.num_res = ARRAY_SIZE(musb_resources); ++ pinfo.data = pdata; ++ pinfo.size_data = sizeof(*pdata); ++ ++ glue->musb = musb = platform_device_register_full(&pinfo); ++ if (IS_ERR(musb)) { ++ ret = PTR_ERR(musb); ++ dev_err(&pdev->dev, "failed to register musb device: %d\n", ret); + goto err5; + } + +@@ -595,9 +593,6 @@ err4: + clk_put(clk); + + err3: +- platform_device_put(musb); +- +-err1: + kfree(glue); + + err0: +--- a/drivers/usb/musb/Kconfig ++++ b/drivers/usb/musb/Kconfig +@@ -75,6 +75,7 @@ config USB_MUSB_TUSB6010 + config USB_MUSB_OMAP2PLUS + tristate "OMAP2430 and onwards" + depends on ARCH_OMAP2PLUS ++ select GENERIC_PHY + + config USB_MUSB_AM35X + tristate "AM35x" +@@ -90,7 +91,7 @@ config USB_MUSB_BLACKFIN + depends on (BF54x && !BF544) || (BF52x && ! BF522 && !BF523) + + config USB_MUSB_UX500 +- tristate "U8500 and U5500" ++ tristate "Ux500 platforms" + + endchoice + +@@ -112,7 +113,7 @@ choice + allow using DMA on multiplatform kernels. + + config USB_UX500_DMA +- bool 'ST Ericsson U8500 and U5500' ++ bool 'ST Ericsson Ux500' + depends on USB_MUSB_UX500 + help + Enable DMA transfers on UX500 platforms. +--- a/drivers/usb/musb/musb_am335x.c ++++ b/drivers/usb/musb/musb_am335x.c +@@ -46,7 +46,7 @@ static struct platform_driver am335x_chi + .remove = am335x_child_remove, + .driver = { + .name = "am335x-usb-childs", +- .of_match_table = of_match_ptr(am335x_child_of_match), ++ .of_match_table = am335x_child_of_match, + }, + }; + +--- a/drivers/usb/musb/musb_core.c ++++ b/drivers/usb/musb/musb_core.c +@@ -94,6 +94,7 @@ + #include <linux/sched.h> + #include <linux/slab.h> + #include <linux/init.h> ++#include <linux/idr.h> + #include <linux/list.h> + #include <linux/kobject.h> + #include <linux/prefetch.h> +@@ -120,7 +121,7 @@ MODULE_DESCRIPTION(DRIVER_INFO); + MODULE_AUTHOR(DRIVER_AUTHOR); + MODULE_LICENSE("GPL"); + MODULE_ALIAS("platform:" MUSB_DRIVER_NAME); +- ++static DEFINE_IDA(musb_ida); + + /*-------------------------------------------------------------------------*/ + +@@ -131,6 +132,35 @@ static inline struct musb *dev_to_musb(s + + /*-------------------------------------------------------------------------*/ + ++int musb_get_id(struct device *dev, gfp_t gfp_mask) ++{ ++ int ret; ++ int id; ++ ++ ret = ida_pre_get(&musb_ida, gfp_mask); ++ if (!ret) { ++ dev_err(dev, "failed to reserve resource for id\n"); ++ return -ENOMEM; ++ } ++ ++ ret = ida_get_new(&musb_ida, &id); ++ if (ret < 0) { ++ dev_err(dev, "failed to allocate a new id\n"); ++ return ret; ++ } ++ ++ return id; ++} ++EXPORT_SYMBOL_GPL(musb_get_id); ++ ++void musb_put_id(struct device *dev, int id) ++{ ++ ++ dev_dbg(dev, "removing id %d\n", id); ++ ida_remove(&musb_ida, id); ++} ++EXPORT_SYMBOL_GPL(musb_put_id); ++ + #ifndef CONFIG_BLACKFIN + static int musb_ulpi_read(struct usb_phy *phy, u32 offset) + { +@@ -1809,8 +1839,7 @@ static void musb_free(struct musb *musb) + disable_irq_wake(musb->nIrq); + free_irq(musb->nIrq, musb); + } +- if (musb->dma_controller) +- dma_controller_destroy(musb->dma_controller); ++ cancel_work_sync(&musb->irq_work); + + musb_host_free(musb); + } +@@ -1885,8 +1914,13 @@ musb_init_controller(struct device *dev, + + pm_runtime_get_sync(musb->controller); + +- if (use_dma && dev->dma_mask) ++ if (use_dma && dev->dma_mask) { + musb->dma_controller = dma_controller_create(musb, musb->mregs); ++ if (IS_ERR(musb->dma_controller)) { ++ status = PTR_ERR(musb->dma_controller); ++ goto fail2_5; ++ } ++ } + + /* be sure interrupts are disabled before connecting ISR */ + musb_platform_disable(musb); +@@ -1937,15 +1971,26 @@ musb_init_controller(struct device *dev, + switch (musb->port_mode) { + case MUSB_PORT_MODE_HOST: + status = musb_host_setup(musb, plat->power); ++ if (status < 0) ++ goto fail3; ++ status = musb_platform_set_mode(musb, MUSB_HOST); + break; + case MUSB_PORT_MODE_GADGET: + status = musb_gadget_setup(musb); ++ if (status < 0) ++ goto fail3; ++ status = musb_platform_set_mode(musb, MUSB_PERIPHERAL); + break; + case MUSB_PORT_MODE_DUAL_ROLE: + status = musb_host_setup(musb, plat->power); + if (status < 0) + goto fail3; + status = musb_gadget_setup(musb); ++ if (status) { ++ musb_host_cleanup(musb); ++ goto fail3; ++ } ++ status = musb_platform_set_mode(musb, MUSB_OTG); + break; + default: + dev_err(dev, "unsupported port mode %d\n", musb->port_mode); +@@ -1972,10 +2017,12 @@ fail5: + + fail4: + musb_gadget_cleanup(musb); ++ musb_host_cleanup(musb); + + fail3: + if (musb->dma_controller) + dma_controller_destroy(musb->dma_controller); ++fail2_5: + pm_runtime_put_sync(musb->controller); + + fail2: +@@ -2032,6 +2079,9 @@ static int musb_remove(struct platform_d + musb_exit_debugfs(musb); + musb_shutdown(pdev); + ++ if (musb->dma_controller) ++ dma_controller_destroy(musb->dma_controller); ++ + musb_free(musb); + device_init_wakeup(dev, 0); + return 0; +--- a/drivers/usb/musb/musb_core.h ++++ b/drivers/usb/musb/musb_core.h +@@ -46,6 +46,7 @@ + #include <linux/usb.h> + #include <linux/usb/otg.h> + #include <linux/usb/musb.h> ++#include <linux/phy/phy.h> + + struct musb; + struct musb_hw_ep; +@@ -341,6 +342,7 @@ struct musb { + u16 int_tx; + + struct usb_phy *xceiv; ++ struct phy *phy; + + int nIrq; + unsigned irq_wake:1; +@@ -505,6 +507,9 @@ extern const char musb_driver_name[]; + extern void musb_stop(struct musb *musb); + extern void musb_start(struct musb *musb); + ++extern int musb_get_id(struct device *dev, gfp_t gfp_mask); ++extern void musb_put_id(struct device *dev, int id); ++ + extern void musb_write_fifo(struct musb_hw_ep *ep, u16 len, const u8 *src); + extern void musb_read_fifo(struct musb_hw_ep *ep, u16 len, u8 *dst); + +--- a/drivers/usb/musb/musb_cppi41.c ++++ b/drivers/usb/musb/musb_cppi41.c +@@ -484,6 +484,7 @@ static int cppi41_dma_controller_start(s + if (ret) + goto err; + ++ ret = -EINVAL; + if (port > MUSB_DMA_NUM_CHANNELS || !port) + goto err; + if (is_tx) +@@ -503,6 +504,7 @@ static int cppi41_dma_controller_start(s + dc = dma_request_slave_channel(dev, str); + if (!dc) { + dev_err(dev, "Falied to request %s.\n", str); ++ ret = -EPROBE_DEFER; + goto err; + } + cppi41_channel->dc = dc; +@@ -510,7 +512,7 @@ static int cppi41_dma_controller_start(s + return 0; + err: + cppi41_release_all_dma_chans(controller); +- return -EINVAL; ++ return ret; + } + + void dma_controller_destroy(struct dma_controller *c) +@@ -526,7 +528,7 @@ struct dma_controller *dma_controller_cr + void __iomem *base) + { + struct cppi41_dma_controller *controller; +- int ret; ++ int ret = 0; + + if (!musb->controller->of_node) { + dev_err(musb->controller, "Need DT for the DMA engine.\n"); +@@ -553,5 +555,7 @@ struct dma_controller *dma_controller_cr + plat_get_fail: + kfree(controller); + kzalloc_fail: ++ if (ret == -EPROBE_DEFER) ++ return ERR_PTR(ret); + return NULL; + } +--- a/drivers/usb/musb/musb_dsps.c ++++ b/drivers/usb/musb/musb_dsps.c +@@ -106,6 +106,7 @@ struct dsps_musb_wrapper { + + /* bit positions for mode */ + unsigned iddig:5; ++ unsigned iddig_mux:5; + /* miscellaneous stuff */ + u8 poll_seconds; + }; +@@ -121,6 +122,43 @@ struct dsps_glue { + unsigned long last_timer; /* last timer data for each instance */ + }; + ++static void dsps_musb_try_idle(struct musb *musb, unsigned long timeout) ++{ ++ struct device *dev = musb->controller; ++ struct dsps_glue *glue = dev_get_drvdata(dev->parent); ++ ++ if (timeout == 0) ++ timeout = jiffies + msecs_to_jiffies(3); ++ ++ /* Never idle if active, or when VBUS timeout is not set as host */ ++ if (musb->is_active || (musb->a_wait_bcon == 0 && ++ musb->xceiv->state == OTG_STATE_A_WAIT_BCON)) { ++ dev_dbg(musb->controller, "%s active, deleting timer\n", ++ usb_otg_state_string(musb->xceiv->state)); ++ del_timer(&glue->timer); ++ glue->last_timer = jiffies; ++ return; ++ } ++ if (musb->port_mode != MUSB_PORT_MODE_DUAL_ROLE) ++ return; ++ ++ if (!musb->g.dev.driver) ++ return; ++ ++ if (time_after(glue->last_timer, timeout) && ++ timer_pending(&glue->timer)) { ++ dev_dbg(musb->controller, ++ "Longer idle timer already pending, ignoring...\n"); ++ return; ++ } ++ glue->last_timer = timeout; ++ ++ dev_dbg(musb->controller, "%s inactive, starting idle timer for %u ms\n", ++ usb_otg_state_string(musb->xceiv->state), ++ jiffies_to_msecs(timeout - jiffies)); ++ mod_timer(&glue->timer, timeout); ++} ++ + /** + * dsps_musb_enable - enable interrupts + */ +@@ -143,6 +181,7 @@ static void dsps_musb_enable(struct musb + /* Force the DRVVBUS IRQ so we can start polling for ID change. */ + dsps_writel(reg_base, wrp->coreintr_set, + (1 << wrp->drvvbus) << wrp->usb_shift); ++ dsps_musb_try_idle(musb, 0); + } + + /** +@@ -171,6 +210,7 @@ static void otg_timer(unsigned long _mus + const struct dsps_musb_wrapper *wrp = glue->wrp; + u8 devctl; + unsigned long flags; ++ int skip_session = 0; + + /* + * We poll because DSPS IP's won't expose several OTG-critical +@@ -183,10 +223,12 @@ static void otg_timer(unsigned long _mus + spin_lock_irqsave(&musb->lock, flags); + switch (musb->xceiv->state) { + case OTG_STATE_A_WAIT_BCON: +- devctl &= ~MUSB_DEVCTL_SESSION; +- dsps_writeb(musb->mregs, MUSB_DEVCTL, devctl); ++ dsps_writeb(musb->mregs, MUSB_DEVCTL, 0); ++ skip_session = 1; ++ /* fall */ + +- devctl = dsps_readb(musb->mregs, MUSB_DEVCTL); ++ case OTG_STATE_A_IDLE: ++ case OTG_STATE_B_IDLE: + if (devctl & MUSB_DEVCTL_BDEVICE) { + musb->xceiv->state = OTG_STATE_B_IDLE; + MUSB_DEV_MODE(musb); +@@ -194,60 +236,21 @@ static void otg_timer(unsigned long _mus + musb->xceiv->state = OTG_STATE_A_IDLE; + MUSB_HST_MODE(musb); + } ++ if (!(devctl & MUSB_DEVCTL_SESSION) && !skip_session) ++ dsps_writeb(mregs, MUSB_DEVCTL, MUSB_DEVCTL_SESSION); ++ mod_timer(&glue->timer, jiffies + wrp->poll_seconds * HZ); + break; + case OTG_STATE_A_WAIT_VFALL: + musb->xceiv->state = OTG_STATE_A_WAIT_VRISE; + dsps_writel(musb->ctrl_base, wrp->coreintr_set, + MUSB_INTR_VBUSERROR << wrp->usb_shift); + break; +- case OTG_STATE_B_IDLE: +- devctl = dsps_readb(mregs, MUSB_DEVCTL); +- if (devctl & MUSB_DEVCTL_BDEVICE) +- mod_timer(&glue->timer, +- jiffies + wrp->poll_seconds * HZ); +- else +- musb->xceiv->state = OTG_STATE_A_IDLE; +- break; + default: + break; + } + spin_unlock_irqrestore(&musb->lock, flags); + } + +-static void dsps_musb_try_idle(struct musb *musb, unsigned long timeout) +-{ +- struct device *dev = musb->controller; +- struct dsps_glue *glue = dev_get_drvdata(dev->parent); +- +- if (timeout == 0) +- timeout = jiffies + msecs_to_jiffies(3); +- +- /* Never idle if active, or when VBUS timeout is not set as host */ +- if (musb->is_active || (musb->a_wait_bcon == 0 && +- musb->xceiv->state == OTG_STATE_A_WAIT_BCON)) { +- dev_dbg(musb->controller, "%s active, deleting timer\n", +- usb_otg_state_string(musb->xceiv->state)); +- del_timer(&glue->timer); +- glue->last_timer = jiffies; +- return; +- } +- if (musb->port_mode == MUSB_PORT_MODE_HOST) +- return; +- +- if (time_after(glue->last_timer, timeout) && +- timer_pending(&glue->timer)) { +- dev_dbg(musb->controller, +- "Longer idle timer already pending, ignoring...\n"); +- return; +- } +- glue->last_timer = timeout; +- +- dev_dbg(musb->controller, "%s inactive, starting idle timer for %u ms\n", +- usb_otg_state_string(musb->xceiv->state), +- jiffies_to_msecs(timeout - jiffies)); +- mod_timer(&glue->timer, timeout); +-} +- + static irqreturn_t dsps_interrupt(int irq, void *hci) + { + struct musb *musb = hci; +@@ -404,6 +407,54 @@ static int dsps_musb_exit(struct musb *m + return 0; + } + ++static int dsps_musb_set_mode(struct musb *musb, u8 mode) ++{ ++ struct device *dev = musb->controller; ++ struct dsps_glue *glue = dev_get_drvdata(dev->parent); ++ const struct dsps_musb_wrapper *wrp = glue->wrp; ++ void __iomem *ctrl_base = musb->ctrl_base; ++ void __iomem *base = musb->mregs; ++ u32 reg; ++ ++ reg = dsps_readl(base, wrp->mode); ++ ++ switch (mode) { ++ case MUSB_HOST: ++ reg &= ~(1 << wrp->iddig); ++ ++ /* ++ * if we're setting mode to host-only or device-only, we're ++ * going to ignore whatever the PHY sends us and just force ++ * ID pin status by SW ++ */ ++ reg |= (1 << wrp->iddig_mux); ++ ++ dsps_writel(base, wrp->mode, reg); ++ dsps_writel(ctrl_base, wrp->phy_utmi, 0x02); ++ break; ++ case MUSB_PERIPHERAL: ++ reg |= (1 << wrp->iddig); ++ ++ /* ++ * if we're setting mode to host-only or device-only, we're ++ * going to ignore whatever the PHY sends us and just force ++ * ID pin status by SW ++ */ ++ reg |= (1 << wrp->iddig_mux); ++ ++ dsps_writel(base, wrp->mode, reg); ++ break; ++ case MUSB_OTG: ++ dsps_writel(base, wrp->phy_utmi, 0x02); ++ break; ++ default: ++ dev_err(glue->dev, "unsupported mode %d\n", mode); ++ return -EINVAL; ++ } ++ ++ return 0; ++} ++ + static struct musb_platform_ops dsps_ops = { + .init = dsps_musb_init, + .exit = dsps_musb_exit, +@@ -412,6 +463,7 @@ static struct musb_platform_ops dsps_ops + .disable = dsps_musb_disable, + + .try_idle = dsps_musb_try_idle, ++ .set_mode = dsps_musb_set_mode, + }; + + static u64 musb_dmamask = DMA_BIT_MASK(32); +@@ -606,6 +658,7 @@ static const struct dsps_musb_wrapper am + .reset = 0, + .otg_disable = 21, + .iddig = 8, ++ .iddig_mux = 7, + .usb_shift = 0, + .usb_mask = 0x1ff, + .usb_bitmap = (0x1ff << 0), +@@ -631,7 +684,7 @@ static struct platform_driver dsps_usbss + .remove = dsps_remove, + .driver = { + .name = "musb-dsps", +- .of_match_table = of_match_ptr(musb_dsps_of_match), ++ .of_match_table = musb_dsps_of_match, + }, + }; + +--- a/drivers/usb/musb/musb_virthub.c ++++ b/drivers/usb/musb/musb_virthub.c +@@ -220,6 +220,23 @@ int musb_hub_status_data(struct usb_hcd + return retval; + } + ++static int musb_has_gadget(struct musb *musb) ++{ ++ /* ++ * In host-only mode we start a connection right away. In OTG mode ++ * we have to wait until we loaded a gadget. We don't really need a ++ * gadget if we operate as a host but we should not start a session ++ * as a device without a gadget or else we explode. ++ */ ++#ifdef CONFIG_USB_MUSB_HOST ++ return 1; ++#else ++ if (musb->port_mode == MUSB_PORT_MODE_HOST) ++ return 1; ++ return musb->g.dev.driver != NULL; ++#endif ++} ++ + int musb_hub_control( + struct usb_hcd *hcd, + u16 typeReq, +@@ -362,7 +379,7 @@ int musb_hub_control( + * initialization logic, e.g. for OTG, or change any + * logic relating to VBUS power-up. + */ +- if (!hcd->self.is_b_host) ++ if (!hcd->self.is_b_host && musb_has_gadget(musb)) + musb_start(musb); + break; + case USB_PORT_FEAT_RESET: +--- a/drivers/usb/musb/omap2430.c ++++ b/drivers/usb/musb/omap2430.c +@@ -37,7 +37,8 @@ + #include <linux/err.h> + #include <linux/delay.h> + #include <linux/usb/musb-omap.h> +-#include <linux/usb/omap_control_usb.h> ++#include <linux/phy/omap_control_phy.h> ++#include <linux/of_platform.h> + + #include "musb_core.h" + #include "omap2430.h" +@@ -305,6 +306,9 @@ static void omap_musb_set_mailbox(struct + default: + dev_dbg(dev, "ID float\n"); + } ++ ++ atomic_notifier_call_chain(&musb->xceiv->notifier, ++ musb->xceiv->last_event, NULL); + } + + +@@ -348,11 +352,21 @@ static int omap2430_musb_init(struct mus + * up through ULPI. TWL4030-family PMICs include one, + * which needs a driver, drivers aren't always needed. + */ +- if (dev->parent->of_node) ++ if (dev->parent->of_node) { ++ musb->phy = devm_phy_get(dev->parent, "usb2-phy"); ++ ++ /* We can't totally remove musb->xceiv as of now because ++ * musb core uses xceiv.state and xceiv.otg. Once we have ++ * a separate state machine to handle otg, these can be moved ++ * out of xceiv and then we can start using the generic PHY ++ * framework ++ */ + musb->xceiv = devm_usb_get_phy_by_phandle(dev->parent, + "usb-phy", 0); +- else ++ } else { + musb->xceiv = devm_usb_get_phy_dev(dev, 0); ++ musb->phy = devm_phy_get(dev, "usb"); ++ } + + if (IS_ERR(musb->xceiv)) { + status = PTR_ERR(musb->xceiv); +@@ -364,6 +378,10 @@ static int omap2430_musb_init(struct mus + return -EPROBE_DEFER; + } + ++ if (IS_ERR(musb->phy)) { ++ pr_err("HS USB OTG: no PHY configured\n"); ++ return PTR_ERR(musb->phy); ++ } + musb->isr = omap2430_musb_interrupt; + + status = pm_runtime_get_sync(dev); +@@ -397,7 +415,7 @@ static int omap2430_musb_init(struct mus + if (glue->status != OMAP_MUSB_UNKNOWN) + omap_musb_set_mailbox(glue); + +- usb_phy_init(musb->xceiv); ++ phy_init(musb->phy); + + pm_runtime_put_noidle(musb->controller); + return 0; +@@ -460,6 +478,7 @@ static int omap2430_musb_exit(struct mus + del_timer_sync(&musb_idle_timer); + + omap2430_low_level_exit(musb); ++ phy_exit(musb->phy); + + return 0; + } +@@ -489,6 +508,7 @@ static int omap2430_probe(struct platfor + struct device_node *np = pdev->dev.of_node; + struct musb_hdrc_config *config; + int ret = -ENOMEM; ++ int musbid; + + glue = devm_kzalloc(&pdev->dev, sizeof(*glue), GFP_KERNEL); + if (!glue) { +@@ -496,10 +516,18 @@ static int omap2430_probe(struct platfor + goto err0; + } + +- musb = platform_device_alloc("musb-hdrc", PLATFORM_DEVID_AUTO); ++ /* get the musb id */ ++ musbid = musb_get_id(&pdev->dev, GFP_KERNEL); ++ if (musbid < 0) { ++ dev_err(&pdev->dev, "failed to allocate musb id\n"); ++ ret = -ENOMEM; ++ goto err0; ++ } ++ ++ musb = platform_device_alloc("musb-hdrc", musbid); + if (!musb) { + dev_err(&pdev->dev, "failed to allocate musb device\n"); +- goto err0; ++ goto err1; + } + + musb->dev.parent = &pdev->dev; +@@ -509,8 +537,12 @@ static int omap2430_probe(struct platfor + glue->dev = &pdev->dev; + glue->musb = musb; + glue->status = OMAP_MUSB_UNKNOWN; ++ glue->control_otghs = ERR_PTR(-ENODEV); + + if (np) { ++ struct device_node *control_node; ++ struct platform_device *control_pdev; ++ + pdata = devm_kzalloc(&pdev->dev, sizeof(*pdata), GFP_KERNEL); + if (!pdata) { + dev_err(&pdev->dev, +@@ -539,22 +571,20 @@ static int omap2430_probe(struct platfor + of_property_read_u32(np, "ram-bits", (u32 *)&config->ram_bits); + of_property_read_u32(np, "power", (u32 *)&pdata->power); + config->multipoint = of_property_read_bool(np, "multipoint"); +- pdata->has_mailbox = of_property_read_bool(np, +- "ti,has-mailbox"); + + pdata->board_data = data; + pdata->config = config; +- } + +- if (pdata->has_mailbox) { +- glue->control_otghs = omap_get_control_dev(); +- if (IS_ERR(glue->control_otghs)) { +- dev_vdbg(&pdev->dev, "Failed to get control device\n"); +- ret = PTR_ERR(glue->control_otghs); +- goto err2; ++ control_node = of_parse_phandle(np, "ctrl-module", 0); ++ if (control_node) { ++ control_pdev = of_find_device_by_node(control_node); ++ if (!control_pdev) { ++ dev_err(&pdev->dev, "Failed to get control device\n"); ++ ret = -EINVAL; ++ goto err2; ++ } ++ glue->control_otghs = &control_pdev->dev; + } +- } else { +- glue->control_otghs = ERR_PTR(-ENODEV); + } + pdata->platform_ops = &omap2430_ops; + +@@ -612,6 +642,9 @@ static int omap2430_probe(struct platfor + err2: + platform_device_put(musb); + ++err1: ++ musb_put_id(&pdev->dev, musbid); ++ + err0: + return ret; + } +@@ -638,7 +671,7 @@ static int omap2430_runtime_suspend(stru + OTG_INTERFSEL); + + omap2430_low_level_exit(musb); +- usb_phy_set_suspend(musb->xceiv, 1); ++ phy_power_off(musb->phy); + } + + return 0; +@@ -653,8 +686,7 @@ static int omap2430_runtime_resume(struc + omap2430_low_level_init(musb); + musb_writel(musb->mregs, OTG_INTERFSEL, + musb->context.otg_interfsel); +- +- usb_phy_set_suspend(musb->xceiv, 0); ++ phy_power_on(musb->phy); + } + + return 0; +--- a/drivers/usb/musb/tusb6010.c ++++ b/drivers/usb/musb/tusb6010.c +@@ -1152,7 +1152,11 @@ static const struct musb_platform_ops tu + .set_vbus = tusb_musb_set_vbus, + }; + +-static u64 tusb_dmamask = DMA_BIT_MASK(32); ++static const struct platform_device_info tusb_dev_info = { ++ .name = "musb-hdrc", ++ .id = PLATFORM_DEVID_AUTO, ++ .dma_mask = DMA_BIT_MASK(32), ++}; + + static int tusb_probe(struct platform_device *pdev) + { +@@ -1160,7 +1164,7 @@ static int tusb_probe(struct platform_de + struct musb_hdrc_platform_data *pdata = dev_get_platdata(&pdev->dev); + struct platform_device *musb; + struct tusb6010_glue *glue; +- ++ struct platform_device_info pinfo; + int ret = -ENOMEM; + + glue = kzalloc(sizeof(*glue), GFP_KERNEL); +@@ -1169,18 +1173,7 @@ static int tusb_probe(struct platform_de + goto err0; + } + +- musb = platform_device_alloc("musb-hdrc", PLATFORM_DEVID_AUTO); +- if (!musb) { +- dev_err(&pdev->dev, "failed to allocate musb device\n"); +- goto err1; +- } +- +- musb->dev.parent = &pdev->dev; +- musb->dev.dma_mask = &tusb_dmamask; +- musb->dev.coherent_dma_mask = tusb_dmamask; +- + glue->dev = &pdev->dev; +- glue->musb = musb; + + pdata->platform_ops = &tusb_ops; + +@@ -1204,31 +1197,23 @@ static int tusb_probe(struct platform_de + musb_resources[2].end = pdev->resource[2].end; + musb_resources[2].flags = pdev->resource[2].flags; + +- ret = platform_device_add_resources(musb, musb_resources, +- ARRAY_SIZE(musb_resources)); +- if (ret) { +- dev_err(&pdev->dev, "failed to add resources\n"); +- goto err3; +- } +- +- ret = platform_device_add_data(musb, pdata, sizeof(*pdata)); +- if (ret) { +- dev_err(&pdev->dev, "failed to add platform_data\n"); +- goto err3; +- } +- +- ret = platform_device_add(musb); +- if (ret) { +- dev_err(&pdev->dev, "failed to register musb device\n"); ++ pinfo = tusb_dev_info; ++ pinfo.parent = &pdev->dev; ++ pinfo.res = musb_resources; ++ pinfo.num_res = ARRAY_SIZE(musb_resources); ++ pinfo.data = pdata; ++ pinfo.size_data = sizeof(*pdata); ++ ++ glue->musb = musb = platform_device_register_full(&pinfo); ++ if (IS_ERR(musb)) { ++ ret = PTR_ERR(musb); ++ dev_err(&pdev->dev, "failed to register musb device: %d\n", ret); + goto err3; + } + + return 0; + + err3: +- platform_device_put(musb); +- +-err1: + kfree(glue); + + err0: +--- a/drivers/usb/musb/ux500.c ++++ b/drivers/usb/musb/ux500.c +@@ -376,17 +376,10 @@ static int ux500_resume(struct device *d + + return 0; + } +- +-static const struct dev_pm_ops ux500_pm_ops = { +- .suspend = ux500_suspend, +- .resume = ux500_resume, +-}; +- +-#define DEV_PM_OPS (&ux500_pm_ops) +-#else +-#define DEV_PM_OPS NULL + #endif + ++static SIMPLE_DEV_PM_OPS(ux500_pm_ops, ux500_suspend, ux500_resume); ++ + static const struct of_device_id ux500_match[] = { + { .compatible = "stericsson,db8500-musb", }, + {} +@@ -397,7 +390,7 @@ static struct platform_driver ux500_driv + .remove = ux500_remove, + .driver = { + .name = "musb-ux500", +- .pm = DEV_PM_OPS, ++ .pm = &ux500_pm_ops, + .of_match_table = ux500_match, + }, + }; +--- a/drivers/usb/phy/Kconfig ++++ b/drivers/usb/phy/Kconfig +@@ -56,38 +56,6 @@ config NOP_USB_XCEIV + built-in with usb ip or which are autonomous and doesn't require any + phy programming such as ISP1x04 etc. + +-config OMAP_CONTROL_USB +- tristate "OMAP CONTROL USB Driver" +- depends on ARCH_OMAP2PLUS || COMPILE_TEST +- help +- Enable this to add support for the USB part present in the control +- module. This driver has API to power on the USB2 PHY and to write to +- the mailbox. The mailbox is present only in omap4 and the register to +- power on the USB2 PHY is present in OMAP4 and OMAP5. OMAP5 has an +- additional register to power on USB3 PHY. +- +-config OMAP_USB2 +- tristate "OMAP USB2 PHY Driver" +- depends on ARCH_OMAP2PLUS +- select OMAP_CONTROL_USB +- select USB_PHY +- help +- Enable this to support the transceiver that is part of SOC. This +- driver takes care of all the PHY functionality apart from comparator. +- The USB OTG controller communicates with the comparator using this +- driver. +- +-config OMAP_USB3 +- tristate "OMAP USB3 PHY Driver" +- depends on ARCH_OMAP2PLUS || COMPILE_TEST +- select OMAP_CONTROL_USB +- select USB_PHY +- help +- Enable this to support the USB3 PHY that is part of SOC. This +- driver takes care of all the PHY functionality apart from comparator. +- This driver interacts with the "OMAP Control USB Driver" to power +- on/off the PHY. +- + config AM335X_CONTROL_USB + tristate + +@@ -123,16 +91,6 @@ config SAMSUNG_USB3PHY + Enable this to support Samsung USB 3.0 (Super Speed) phy controller + for samsung SoCs. + +-config TWL4030_USB +- tristate "TWL4030 USB Transceiver Driver" +- depends on TWL4030_CORE && REGULATOR_TWL4030 && USB_MUSB_OMAP2PLUS +- select USB_PHY +- help +- Enable this to support the USB OTG transceiver on TWL4030 +- family chips (including the TWL5030 and TPS659x0 devices). +- This transceiver supports high and full speed devices plus, +- in host mode, low speed. +- + config TWL6030_USB + tristate "TWL6030 USB Transceiver Driver" + depends on TWL4030_CORE && OMAP_USB2 && USB_MUSB_OMAP2PLUS +@@ -214,6 +172,19 @@ config USB_RCAR_PHY + To compile this driver as a module, choose M here: the + module will be called phy-rcar-usb. + ++config USB_RCAR_GEN2_PHY ++ tristate "Renesas R-Car Gen2 USB PHY support" ++ depends on ARCH_R8A7790 || ARCH_R8A7791 || COMPILE_TEST ++ select USB_PHY ++ help ++ Say Y here to add support for the Renesas R-Car Gen2 USB PHY driver. ++ It is typically used to control internal USB PHY for USBHS, ++ and to configure shared USB channels 0 and 2. ++ This driver supports R8A7790 and R8A7791. ++ ++ To compile this driver as a module, choose M here: the ++ module will be called phy-rcar-gen2-usb. ++ + config USB_ULPI + bool "Generic ULPI Transceiver Driver" + depends on ARM +--- a/drivers/usb/phy/Makefile ++++ b/drivers/usb/phy/Makefile +@@ -12,15 +12,11 @@ obj-$(CONFIG_FSL_USB2_OTG) += phy-fsl-u + obj-$(CONFIG_ISP1301_OMAP) += phy-isp1301-omap.o + obj-$(CONFIG_MV_U3D_PHY) += phy-mv-u3d-usb.o + obj-$(CONFIG_NOP_USB_XCEIV) += phy-generic.o +-obj-$(CONFIG_OMAP_CONTROL_USB) += phy-omap-control.o + obj-$(CONFIG_AM335X_CONTROL_USB) += phy-am335x-control.o + obj-$(CONFIG_AM335X_PHY_USB) += phy-am335x.o +-obj-$(CONFIG_OMAP_USB2) += phy-omap-usb2.o +-obj-$(CONFIG_OMAP_USB3) += phy-omap-usb3.o + obj-$(CONFIG_SAMSUNG_USBPHY) += phy-samsung-usb.o + obj-$(CONFIG_SAMSUNG_USB2PHY) += phy-samsung-usb2.o + obj-$(CONFIG_SAMSUNG_USB3PHY) += phy-samsung-usb3.o +-obj-$(CONFIG_TWL4030_USB) += phy-twl4030-usb.o + obj-$(CONFIG_TWL6030_USB) += phy-twl6030-usb.o + obj-$(CONFIG_USB_EHCI_TEGRA) += phy-tegra-usb.o + obj-$(CONFIG_USB_GPIO_VBUS) += phy-gpio-vbus-usb.o +@@ -29,5 +25,6 @@ obj-$(CONFIG_USB_MSM_OTG) += phy-msm-us + obj-$(CONFIG_USB_MV_OTG) += phy-mv-usb.o + obj-$(CONFIG_USB_MXS_PHY) += phy-mxs-usb.o + obj-$(CONFIG_USB_RCAR_PHY) += phy-rcar-usb.o ++obj-$(CONFIG_USB_RCAR_GEN2_PHY) += phy-rcar-gen2-usb.o + obj-$(CONFIG_USB_ULPI) += phy-ulpi.o + obj-$(CONFIG_USB_ULPI_VIEWPORT) += phy-ulpi-viewport.o +--- a/drivers/usb/phy/phy-am335x.c ++++ b/drivers/usb/phy/phy-am335x.c +@@ -52,23 +52,19 @@ static int am335x_phy_probe(struct platf + return am_phy->id; + } + +- ret = usb_phy_gen_create_phy(dev, &am_phy->usb_phy_gen, +- USB_PHY_TYPE_USB2, 0, false, false); ++ ret = usb_phy_gen_create_phy(dev, &am_phy->usb_phy_gen, NULL); + if (ret) + return ret; + + ret = usb_add_phy_dev(&am_phy->usb_phy_gen.phy); + if (ret) +- goto err_add; ++ return ret; + am_phy->usb_phy_gen.phy.init = am335x_init; + am_phy->usb_phy_gen.phy.shutdown = am335x_shutdown; + + platform_set_drvdata(pdev, am_phy); +- return 0; + +-err_add: +- usb_phy_gen_cleanup_phy(&am_phy->usb_phy_gen); +- return ret; ++ return 0; + } + + static int am335x_phy_remove(struct platform_device *pdev) +@@ -79,6 +75,40 @@ static int am335x_phy_remove(struct plat + return 0; + } + ++#ifdef CONFIG_PM_RUNTIME ++ ++static int am335x_phy_runtime_suspend(struct device *dev) ++{ ++ struct platform_device *pdev = to_platform_device(dev); ++ struct am335x_phy *am_phy = platform_get_drvdata(pdev); ++ ++ if (device_may_wakeup(dev)) ++ phy_ctrl_wkup(am_phy->phy_ctrl, am_phy->id, true); ++ phy_ctrl_power(am_phy->phy_ctrl, am_phy->id, false); ++ return 0; ++} ++ ++static int am335x_phy_runtime_resume(struct device *dev) ++{ ++ struct platform_device *pdev = to_platform_device(dev); ++ struct am335x_phy *am_phy = platform_get_drvdata(pdev); ++ ++ phy_ctrl_power(am_phy->phy_ctrl, am_phy->id, true); ++ if (device_may_wakeup(dev)) ++ phy_ctrl_wkup(am_phy->phy_ctrl, am_phy->id, false); ++ return 0; ++} ++ ++static const struct dev_pm_ops am335x_pm_ops = { ++ SET_RUNTIME_PM_OPS(am335x_phy_runtime_suspend, ++ am335x_phy_runtime_resume, NULL) ++}; ++ ++#define DEV_PM_OPS (&am335x_pm_ops) ++#else ++#define DEV_PM_OPS NULL ++#endif ++ + static const struct of_device_id am335x_phy_ids[] = { + { .compatible = "ti,am335x-usb-phy" }, + { } +@@ -91,7 +121,8 @@ static struct platform_driver am335x_phy + .driver = { + .name = "am335x-phy-driver", + .owner = THIS_MODULE, +- .of_match_table = of_match_ptr(am335x_phy_ids), ++ .pm = DEV_PM_OPS, ++ .of_match_table = am335x_phy_ids, + }, + }; + +--- a/drivers/usb/phy/phy-am335x-control.c ++++ b/drivers/usb/phy/phy-am335x-control.c +@@ -26,6 +26,41 @@ struct am335x_control_usb { + #define USBPHY_OTGVDET_EN (1 << 19) + #define USBPHY_OTGSESSEND_EN (1 << 20) + ++#define AM335X_PHY0_WK_EN (1 << 0) ++#define AM335X_PHY1_WK_EN (1 << 8) ++ ++static void am335x_phy_wkup(struct phy_control *phy_ctrl, u32 id, bool on) ++{ ++ struct am335x_control_usb *usb_ctrl; ++ u32 val; ++ u32 reg; ++ ++ usb_ctrl = container_of(phy_ctrl, struct am335x_control_usb, phy_ctrl); ++ ++ switch (id) { ++ case 0: ++ reg = AM335X_PHY0_WK_EN; ++ break; ++ case 1: ++ reg = AM335X_PHY1_WK_EN; ++ break; ++ default: ++ WARN_ON(1); ++ return; ++ } ++ ++ spin_lock(&usb_ctrl->lock); ++ val = readl(usb_ctrl->wkup); ++ ++ if (on) ++ val |= reg; ++ else ++ val &= ~reg; ++ ++ writel(val, usb_ctrl->wkup); ++ spin_unlock(&usb_ctrl->lock); ++} ++ + static void am335x_phy_power(struct phy_control *phy_ctrl, u32 id, bool on) + { + struct am335x_control_usb *usb_ctrl; +@@ -59,6 +94,7 @@ static void am335x_phy_power(struct phy_ + + static const struct phy_control ctrl_am335x = { + .phy_power = am335x_phy_power, ++ .phy_wkup = am335x_phy_wkup, + }; + + static const struct of_device_id omap_control_usb_id_table[] = { +@@ -117,6 +153,12 @@ static int am335x_control_usb_probe(stru + ctrl_usb->phy_reg = devm_ioremap_resource(&pdev->dev, res); + if (IS_ERR(ctrl_usb->phy_reg)) + return PTR_ERR(ctrl_usb->phy_reg); ++ ++ res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "wakeup"); ++ ctrl_usb->wkup = devm_ioremap_resource(&pdev->dev, res); ++ if (IS_ERR(ctrl_usb->wkup)) ++ return PTR_ERR(ctrl_usb->wkup); ++ + spin_lock_init(&ctrl_usb->lock); + ctrl_usb->phy_ctrl = *phy_ctrl; + +@@ -129,7 +171,7 @@ static struct platform_driver am335x_con + .driver = { + .name = "am335x-control-usb", + .owner = THIS_MODULE, +- .of_match_table = of_match_ptr(omap_control_usb_id_table), ++ .of_match_table = omap_control_usb_id_table, + }, + }; + +--- a/drivers/usb/phy/phy.c ++++ b/drivers/usb/phy/phy.c +@@ -98,7 +98,7 @@ struct usb_phy *devm_usb_get_phy(struct + + ptr = devres_alloc(devm_usb_phy_release, sizeof(*ptr), GFP_KERNEL); + if (!ptr) +- return NULL; ++ return ERR_PTR(-ENOMEM); + + phy = usb_get_phy(type); + if (!IS_ERR(phy)) { +--- a/drivers/usb/phy/phy-fsl-usb.c ++++ b/drivers/usb/phy/phy-fsl-usb.c +@@ -134,7 +134,7 @@ int write_ulpi(u8 addr, u8 data) + /* Operations that will be called from OTG Finite State Machine */ + + /* Charge vbus for vbus pulsing in SRP */ +-void fsl_otg_chrg_vbus(int on) ++void fsl_otg_chrg_vbus(struct otg_fsm *fsm, int on) + { + u32 tmp; + +@@ -170,7 +170,7 @@ void fsl_otg_dischrg_vbus(int on) + } + + /* A-device driver vbus, controlled through PP bit in PORTSC */ +-void fsl_otg_drv_vbus(int on) ++void fsl_otg_drv_vbus(struct otg_fsm *fsm, int on) + { + u32 tmp; + +@@ -188,7 +188,7 @@ void fsl_otg_drv_vbus(int on) + * Pull-up D+, signalling connect by periperal. Also used in + * data-line pulsing in SRP + */ +-void fsl_otg_loc_conn(int on) ++void fsl_otg_loc_conn(struct otg_fsm *fsm, int on) + { + u32 tmp; + +@@ -207,7 +207,7 @@ void fsl_otg_loc_conn(int on) + * port. In host mode, controller will automatically send SOF. + * Suspend will block the data on the port. + */ +-void fsl_otg_loc_sof(int on) ++void fsl_otg_loc_sof(struct otg_fsm *fsm, int on) + { + u32 tmp; + +@@ -222,7 +222,7 @@ void fsl_otg_loc_sof(int on) + } + + /* Start SRP pulsing by data-line pulsing, followed with v-bus pulsing. */ +-void fsl_otg_start_pulse(void) ++void fsl_otg_start_pulse(struct otg_fsm *fsm) + { + u32 tmp; + +@@ -235,7 +235,7 @@ void fsl_otg_start_pulse(void) + fsl_otg_loc_conn(1); + #endif + +- fsl_otg_add_timer(b_data_pulse_tmr); ++ fsl_otg_add_timer(fsm, b_data_pulse_tmr); + } + + void b_data_pulse_end(unsigned long foo) +@@ -252,14 +252,14 @@ void b_data_pulse_end(unsigned long foo) + void fsl_otg_pulse_vbus(void) + { + srp_wait_done = 0; +- fsl_otg_chrg_vbus(1); ++ fsl_otg_chrg_vbus(&fsl_otg_dev->fsm, 1); + /* start the timer to end vbus charge */ +- fsl_otg_add_timer(b_vbus_pulse_tmr); ++ fsl_otg_add_timer(&fsl_otg_dev->fsm, b_vbus_pulse_tmr); + } + + void b_vbus_pulse_end(unsigned long foo) + { +- fsl_otg_chrg_vbus(0); ++ fsl_otg_chrg_vbus(&fsl_otg_dev->fsm, 0); + + /* + * As USB3300 using the same a_sess_vld and b_sess_vld voltage +@@ -267,7 +267,7 @@ void b_vbus_pulse_end(unsigned long foo) + * residual voltage of vbus pulsing and A device pull up + */ + fsl_otg_dischrg_vbus(1); +- fsl_otg_add_timer(b_srp_wait_tmr); ++ fsl_otg_add_timer(&fsl_otg_dev->fsm, b_srp_wait_tmr); + } + + void b_srp_end(unsigned long foo) +@@ -289,7 +289,7 @@ void a_wait_enum(unsigned long foo) + { + VDBG("a_wait_enum timeout\n"); + if (!fsl_otg_dev->phy.otg->host->b_hnp_enable) +- fsl_otg_add_timer(a_wait_enum_tmr); ++ fsl_otg_add_timer(&fsl_otg_dev->fsm, a_wait_enum_tmr); + else + otg_statemachine(&fsl_otg_dev->fsm); + } +@@ -375,8 +375,42 @@ void fsl_otg_uninit_timers(void) + kfree(b_vbus_pulse_tmr); + } + ++static struct fsl_otg_timer *fsl_otg_get_timer(enum otg_fsm_timer t) ++{ ++ struct fsl_otg_timer *timer; ++ ++ /* REVISIT: use array of pointers to timers instead */ ++ switch (t) { ++ case A_WAIT_VRISE: ++ timer = a_wait_vrise_tmr; ++ break; ++ case A_WAIT_BCON: ++ timer = a_wait_vrise_tmr; ++ break; ++ case A_AIDL_BDIS: ++ timer = a_wait_vrise_tmr; ++ break; ++ case B_ASE0_BRST: ++ timer = a_wait_vrise_tmr; ++ break; ++ case B_SE0_SRP: ++ timer = a_wait_vrise_tmr; ++ break; ++ case B_SRP_FAIL: ++ timer = a_wait_vrise_tmr; ++ break; ++ case A_WAIT_ENUM: ++ timer = a_wait_vrise_tmr; ++ break; ++ default: ++ timer = NULL; ++ } ++ ++ return timer; ++} ++ + /* Add timer to timer list */ +-void fsl_otg_add_timer(void *gtimer) ++void fsl_otg_add_timer(struct otg_fsm *fsm, void *gtimer) + { + struct fsl_otg_timer *timer = gtimer; + struct fsl_otg_timer *tmp_timer; +@@ -394,8 +428,19 @@ void fsl_otg_add_timer(void *gtimer) + list_add_tail(&timer->list, &active_timers); + } + ++static void fsl_otg_fsm_add_timer(struct otg_fsm *fsm, enum otg_fsm_timer t) ++{ ++ struct fsl_otg_timer *timer; ++ ++ timer = fsl_otg_get_timer(t); ++ if (!timer) ++ return; ++ ++ fsl_otg_add_timer(fsm, timer); ++} ++ + /* Remove timer from the timer list; clear timeout status */ +-void fsl_otg_del_timer(void *gtimer) ++void fsl_otg_del_timer(struct otg_fsm *fsm, void *gtimer) + { + struct fsl_otg_timer *timer = gtimer; + struct fsl_otg_timer *tmp_timer, *del_tmp; +@@ -405,6 +450,17 @@ void fsl_otg_del_timer(void *gtimer) + list_del(&timer->list); + } + ++static void fsl_otg_fsm_del_timer(struct otg_fsm *fsm, enum otg_fsm_timer t) ++{ ++ struct fsl_otg_timer *timer; ++ ++ timer = fsl_otg_get_timer(t); ++ if (!timer) ++ return; ++ ++ fsl_otg_del_timer(fsm, timer); ++} ++ + /* + * Reduce timer count by 1, and find timeout conditions. + * Called by fsl_otg 1ms timer interrupt +@@ -468,7 +524,7 @@ int fsl_otg_start_host(struct otg_fsm *f + retval = dev->driver->pm->resume(dev); + if (fsm->id) { + /* default-b */ +- fsl_otg_drv_vbus(1); ++ fsl_otg_drv_vbus(fsm, 1); + /* + * Workaround: b_host can't driver + * vbus, but PP in PORTSC needs to +@@ -493,7 +549,7 @@ int fsl_otg_start_host(struct otg_fsm *f + retval = dev->driver->pm->suspend(dev); + if (fsm->id) + /* default-b */ +- fsl_otg_drv_vbus(0); ++ fsl_otg_drv_vbus(fsm, 0); + } + otg_dev->host_working = 0; + } +@@ -757,8 +813,8 @@ static struct otg_fsm_ops fsl_otg_ops = + .loc_sof = fsl_otg_loc_sof, + .start_pulse = fsl_otg_start_pulse, + +- .add_timer = fsl_otg_add_timer, +- .del_timer = fsl_otg_del_timer, ++ .add_timer = fsl_otg_fsm_add_timer, ++ .del_timer = fsl_otg_fsm_del_timer, + + .start_host = fsl_otg_start_host, + .start_gadget = fsl_otg_start_gadget, +@@ -1011,7 +1067,7 @@ static int show_fsl_usb2_otg_state(struc + "b_bus_suspend: %d\n" + "b_conn: %d\n" + "b_se0_srp: %d\n" +- "b_sess_end: %d\n" ++ "b_ssend_srp: %d\n" + "b_sess_vld: %d\n" + "id: %d\n", + fsm->a_bus_req, +@@ -1026,7 +1082,7 @@ static int show_fsl_usb2_otg_state(struc + fsm->b_bus_suspend, + fsm->b_conn, + fsm->b_se0_srp, +- fsm->b_sess_end, ++ fsm->b_ssend_srp, + fsm->b_sess_vld, + fsm->id); + size -= t; +@@ -1057,7 +1113,7 @@ static long fsl_otg_ioctl(struct file *f + break; + + case SET_A_SUSPEND_REQ: +- fsl_otg_dev->fsm.a_suspend_req = arg; ++ fsl_otg_dev->fsm.a_suspend_req_inf = arg; + break; + + case SET_A_BUS_DROP: +--- a/drivers/usb/phy/phy-fsl-usb.h ++++ b/drivers/usb/phy/phy-fsl-usb.h +@@ -401,6 +401,6 @@ struct fsl_otg_config { + #define GET_A_BUS_REQ _IOR(OTG_IOCTL_MAGIC, 8, int) + #define GET_B_BUS_REQ _IOR(OTG_IOCTL_MAGIC, 9, int) + +-void fsl_otg_add_timer(void *timer); +-void fsl_otg_del_timer(void *timer); ++void fsl_otg_add_timer(struct otg_fsm *fsm, void *timer); ++void fsl_otg_del_timer(struct otg_fsm *fsm, void *timer); + void fsl_otg_pulse_vbus(void); +--- a/drivers/usb/phy/phy-fsm-usb.c ++++ b/drivers/usb/phy/phy-fsm-usb.c +@@ -41,17 +41,17 @@ static int otg_set_protocol(struct otg_f + fsm->protocol, protocol); + /* stop old protocol */ + if (fsm->protocol == PROTO_HOST) +- ret = fsm->ops->start_host(fsm, 0); ++ ret = otg_start_host(fsm, 0); + else if (fsm->protocol == PROTO_GADGET) +- ret = fsm->ops->start_gadget(fsm, 0); ++ ret = otg_start_gadget(fsm, 0); + if (ret) + return ret; + + /* start new protocol */ + if (protocol == PROTO_HOST) +- ret = fsm->ops->start_host(fsm, 1); ++ ret = otg_start_host(fsm, 1); + else if (protocol == PROTO_GADGET) +- ret = fsm->ops->start_gadget(fsm, 1); ++ ret = otg_start_gadget(fsm, 1); + if (ret) + return ret; + +@@ -69,42 +69,50 @@ void otg_leave_state(struct otg_fsm *fsm + { + switch (old_state) { + case OTG_STATE_B_IDLE: +- otg_del_timer(fsm, b_se0_srp_tmr); ++ otg_del_timer(fsm, B_SE0_SRP); + fsm->b_se0_srp = 0; ++ fsm->adp_sns = 0; ++ fsm->adp_prb = 0; + break; + case OTG_STATE_B_SRP_INIT: ++ fsm->data_pulse = 0; + fsm->b_srp_done = 0; + break; + case OTG_STATE_B_PERIPHERAL: + break; + case OTG_STATE_B_WAIT_ACON: +- otg_del_timer(fsm, b_ase0_brst_tmr); ++ otg_del_timer(fsm, B_ASE0_BRST); + fsm->b_ase0_brst_tmout = 0; + break; + case OTG_STATE_B_HOST: + break; + case OTG_STATE_A_IDLE: ++ fsm->adp_prb = 0; + break; + case OTG_STATE_A_WAIT_VRISE: +- otg_del_timer(fsm, a_wait_vrise_tmr); ++ otg_del_timer(fsm, A_WAIT_VRISE); + fsm->a_wait_vrise_tmout = 0; + break; + case OTG_STATE_A_WAIT_BCON: +- otg_del_timer(fsm, a_wait_bcon_tmr); ++ otg_del_timer(fsm, A_WAIT_BCON); + fsm->a_wait_bcon_tmout = 0; + break; + case OTG_STATE_A_HOST: +- otg_del_timer(fsm, a_wait_enum_tmr); ++ otg_del_timer(fsm, A_WAIT_ENUM); + break; + case OTG_STATE_A_SUSPEND: +- otg_del_timer(fsm, a_aidl_bdis_tmr); ++ otg_del_timer(fsm, A_AIDL_BDIS); + fsm->a_aidl_bdis_tmout = 0; +- fsm->a_suspend_req = 0; ++ fsm->a_suspend_req_inf = 0; + break; + case OTG_STATE_A_PERIPHERAL: ++ otg_del_timer(fsm, A_BIDL_ADIS); ++ fsm->a_bidl_adis_tmout = 0; + break; + case OTG_STATE_A_WAIT_VFALL: +- otg_del_timer(fsm, a_wait_vrise_tmr); ++ otg_del_timer(fsm, A_WAIT_VFALL); ++ fsm->a_wait_vfall_tmout = 0; ++ otg_del_timer(fsm, A_WAIT_VRISE); + break; + case OTG_STATE_A_VBUS_ERR: + break; +@@ -127,14 +135,19 @@ int otg_set_state(struct otg_fsm *fsm, e + otg_chrg_vbus(fsm, 0); + otg_loc_conn(fsm, 0); + otg_loc_sof(fsm, 0); ++ /* ++ * Driver is responsible for starting ADP probing ++ * if ADP sensing times out. ++ */ ++ otg_start_adp_sns(fsm); + otg_set_protocol(fsm, PROTO_UNDEF); +- otg_add_timer(fsm, b_se0_srp_tmr); ++ otg_add_timer(fsm, B_SE0_SRP); + break; + case OTG_STATE_B_SRP_INIT: + otg_start_pulse(fsm); + otg_loc_sof(fsm, 0); + otg_set_protocol(fsm, PROTO_UNDEF); +- otg_add_timer(fsm, b_srp_fail_tmr); ++ otg_add_timer(fsm, B_SRP_FAIL); + break; + case OTG_STATE_B_PERIPHERAL: + otg_chrg_vbus(fsm, 0); +@@ -147,7 +160,7 @@ int otg_set_state(struct otg_fsm *fsm, e + otg_loc_conn(fsm, 0); + otg_loc_sof(fsm, 0); + otg_set_protocol(fsm, PROTO_HOST); +- otg_add_timer(fsm, b_ase0_brst_tmr); ++ otg_add_timer(fsm, B_ASE0_BRST); + fsm->a_bus_suspend = 0; + break; + case OTG_STATE_B_HOST: +@@ -163,6 +176,7 @@ int otg_set_state(struct otg_fsm *fsm, e + otg_chrg_vbus(fsm, 0); + otg_loc_conn(fsm, 0); + otg_loc_sof(fsm, 0); ++ otg_start_adp_prb(fsm); + otg_set_protocol(fsm, PROTO_HOST); + break; + case OTG_STATE_A_WAIT_VRISE: +@@ -170,14 +184,14 @@ int otg_set_state(struct otg_fsm *fsm, e + otg_loc_conn(fsm, 0); + otg_loc_sof(fsm, 0); + otg_set_protocol(fsm, PROTO_HOST); +- otg_add_timer(fsm, a_wait_vrise_tmr); ++ otg_add_timer(fsm, A_WAIT_VRISE); + break; + case OTG_STATE_A_WAIT_BCON: + otg_drv_vbus(fsm, 1); + otg_loc_conn(fsm, 0); + otg_loc_sof(fsm, 0); + otg_set_protocol(fsm, PROTO_HOST); +- otg_add_timer(fsm, a_wait_bcon_tmr); ++ otg_add_timer(fsm, A_WAIT_BCON); + break; + case OTG_STATE_A_HOST: + otg_drv_vbus(fsm, 1); +@@ -188,15 +202,15 @@ int otg_set_state(struct otg_fsm *fsm, e + * When HNP is triggered while a_bus_req = 0, a_host will + * suspend too fast to complete a_set_b_hnp_en + */ +- if (!fsm->a_bus_req || fsm->a_suspend_req) +- otg_add_timer(fsm, a_wait_enum_tmr); ++ if (!fsm->a_bus_req || fsm->a_suspend_req_inf) ++ otg_add_timer(fsm, A_WAIT_ENUM); + break; + case OTG_STATE_A_SUSPEND: + otg_drv_vbus(fsm, 1); + otg_loc_conn(fsm, 0); + otg_loc_sof(fsm, 0); + otg_set_protocol(fsm, PROTO_HOST); +- otg_add_timer(fsm, a_aidl_bdis_tmr); ++ otg_add_timer(fsm, A_AIDL_BDIS); + + break; + case OTG_STATE_A_PERIPHERAL: +@@ -204,12 +218,14 @@ int otg_set_state(struct otg_fsm *fsm, e + otg_loc_sof(fsm, 0); + otg_set_protocol(fsm, PROTO_GADGET); + otg_drv_vbus(fsm, 1); ++ otg_add_timer(fsm, A_BIDL_ADIS); + break; + case OTG_STATE_A_WAIT_VFALL: + otg_drv_vbus(fsm, 0); + otg_loc_conn(fsm, 0); + otg_loc_sof(fsm, 0); + otg_set_protocol(fsm, PROTO_HOST); ++ otg_add_timer(fsm, A_WAIT_VFALL); + break; + case OTG_STATE_A_VBUS_ERR: + otg_drv_vbus(fsm, 0); +@@ -250,7 +266,8 @@ int otg_statemachine(struct otg_fsm *fsm + otg_set_state(fsm, OTG_STATE_A_IDLE); + else if (fsm->b_sess_vld && fsm->otg->gadget) + otg_set_state(fsm, OTG_STATE_B_PERIPHERAL); +- else if (fsm->b_bus_req && fsm->b_sess_end && fsm->b_se0_srp) ++ else if ((fsm->b_bus_req || fsm->adp_change || fsm->power_up) && ++ fsm->b_ssend_srp && fsm->b_se0_srp) + otg_set_state(fsm, OTG_STATE_B_SRP_INIT); + break; + case OTG_STATE_B_SRP_INIT: +@@ -277,13 +294,14 @@ int otg_statemachine(struct otg_fsm *fsm + case OTG_STATE_B_HOST: + if (!fsm->id || !fsm->b_sess_vld) + otg_set_state(fsm, OTG_STATE_B_IDLE); +- else if (!fsm->b_bus_req || !fsm->a_conn) ++ else if (!fsm->b_bus_req || !fsm->a_conn || fsm->test_device) + otg_set_state(fsm, OTG_STATE_B_PERIPHERAL); + break; + case OTG_STATE_A_IDLE: + if (fsm->id) + otg_set_state(fsm, OTG_STATE_B_IDLE); +- else if (!fsm->a_bus_drop && (fsm->a_bus_req || fsm->a_srp_det)) ++ else if (!fsm->a_bus_drop && (fsm->a_bus_req || ++ fsm->a_srp_det || fsm->adp_change || fsm->power_up)) + otg_set_state(fsm, OTG_STATE_A_WAIT_VRISE); + break; + case OTG_STATE_A_WAIT_VRISE: +@@ -301,7 +319,7 @@ int otg_statemachine(struct otg_fsm *fsm + otg_set_state(fsm, OTG_STATE_A_WAIT_VFALL); + break; + case OTG_STATE_A_HOST: +- if ((!fsm->a_bus_req || fsm->a_suspend_req) && ++ if ((!fsm->a_bus_req || fsm->a_suspend_req_inf) && + fsm->otg->host->b_hnp_enable) + otg_set_state(fsm, OTG_STATE_A_SUSPEND); + else if (fsm->id || !fsm->b_conn || fsm->a_bus_drop) +@@ -324,14 +342,14 @@ int otg_statemachine(struct otg_fsm *fsm + case OTG_STATE_A_PERIPHERAL: + if (fsm->id || fsm->a_bus_drop) + otg_set_state(fsm, OTG_STATE_A_WAIT_VFALL); +- else if (fsm->b_bus_suspend) ++ else if (fsm->a_bidl_adis_tmout || fsm->b_bus_suspend) + otg_set_state(fsm, OTG_STATE_A_WAIT_BCON); + else if (!fsm->a_vbus_vld) + otg_set_state(fsm, OTG_STATE_A_VBUS_ERR); + break; + case OTG_STATE_A_WAIT_VFALL: +- if (fsm->id || fsm->a_bus_req || (!fsm->a_sess_vld && +- !fsm->b_conn)) ++ if (fsm->a_wait_vfall_tmout || fsm->id || fsm->a_bus_req || ++ (!fsm->a_sess_vld && !fsm->b_conn)) + otg_set_state(fsm, OTG_STATE_A_IDLE); + break; + case OTG_STATE_A_VBUS_ERR: +--- a/drivers/usb/phy/phy-fsm-usb.h ++++ b/drivers/usb/phy/phy-fsm-usb.h +@@ -34,45 +34,76 @@ + #define PROTO_HOST (1) + #define PROTO_GADGET (2) + ++enum otg_fsm_timer { ++ /* Standard OTG timers */ ++ A_WAIT_VRISE, ++ A_WAIT_VFALL, ++ A_WAIT_BCON, ++ A_AIDL_BDIS, ++ B_ASE0_BRST, ++ A_BIDL_ADIS, ++ ++ /* Auxiliary timers */ ++ B_SE0_SRP, ++ B_SRP_FAIL, ++ A_WAIT_ENUM, ++ ++ NUM_OTG_FSM_TIMERS, ++}; ++ + /* OTG state machine according to the OTG spec */ + struct otg_fsm { + /* Input */ ++ int id; ++ int adp_change; ++ int power_up; ++ int test_device; ++ int a_bus_drop; ++ int a_bus_req; ++ int a_srp_det; ++ int a_vbus_vld; ++ int b_conn; + int a_bus_resume; + int a_bus_suspend; + int a_conn; ++ int b_bus_req; ++ int b_se0_srp; ++ int b_ssend_srp; ++ int b_sess_vld; ++ /* Auxilary inputs */ + int a_sess_vld; +- int a_srp_det; +- int a_vbus_vld; + int b_bus_resume; + int b_bus_suspend; +- int b_conn; +- int b_se0_srp; +- int b_sess_end; +- int b_sess_vld; +- int id; ++ ++ /* Output */ ++ int data_pulse; ++ int drv_vbus; ++ int loc_conn; ++ int loc_sof; ++ int adp_prb; ++ int adp_sns; + + /* Internal variables */ + int a_set_b_hnp_en; + int b_srp_done; + int b_hnp_enable; ++ int a_clr_err; ++ ++ /* Informative variables */ ++ int a_bus_drop_inf; ++ int a_bus_req_inf; ++ int a_clr_err_inf; ++ int b_bus_req_inf; ++ /* Auxilary informative variables */ ++ int a_suspend_req_inf; + + /* Timeout indicator for timers */ + int a_wait_vrise_tmout; ++ int a_wait_vfall_tmout; + int a_wait_bcon_tmout; + int a_aidl_bdis_tmout; + int b_ase0_brst_tmout; +- +- /* Informative variables */ +- int a_bus_drop; +- int a_bus_req; +- int a_clr_err; +- int a_suspend_req; +- int b_bus_req; +- +- /* Output */ +- int drv_vbus; +- int loc_conn; +- int loc_sof; ++ int a_bidl_adis_tmout; + + struct otg_fsm_ops *ops; + struct usb_otg *otg; +@@ -83,65 +114,123 @@ struct otg_fsm { + }; + + struct otg_fsm_ops { +- void (*chrg_vbus)(int on); +- void (*drv_vbus)(int on); +- void (*loc_conn)(int on); +- void (*loc_sof)(int on); +- void (*start_pulse)(void); +- void (*add_timer)(void *timer); +- void (*del_timer)(void *timer); ++ void (*chrg_vbus)(struct otg_fsm *fsm, int on); ++ void (*drv_vbus)(struct otg_fsm *fsm, int on); ++ void (*loc_conn)(struct otg_fsm *fsm, int on); ++ void (*loc_sof)(struct otg_fsm *fsm, int on); ++ void (*start_pulse)(struct otg_fsm *fsm); ++ void (*start_adp_prb)(struct otg_fsm *fsm); ++ void (*start_adp_sns)(struct otg_fsm *fsm); ++ void (*add_timer)(struct otg_fsm *fsm, enum otg_fsm_timer timer); ++ void (*del_timer)(struct otg_fsm *fsm, enum otg_fsm_timer timer); + int (*start_host)(struct otg_fsm *fsm, int on); + int (*start_gadget)(struct otg_fsm *fsm, int on); + }; + + +-static inline void otg_chrg_vbus(struct otg_fsm *fsm, int on) ++static inline int otg_chrg_vbus(struct otg_fsm *fsm, int on) + { +- fsm->ops->chrg_vbus(on); ++ if (!fsm->ops->chrg_vbus) ++ return -EOPNOTSUPP; ++ fsm->ops->chrg_vbus(fsm, on); ++ return 0; + } + +-static inline void otg_drv_vbus(struct otg_fsm *fsm, int on) ++static inline int otg_drv_vbus(struct otg_fsm *fsm, int on) + { ++ if (!fsm->ops->drv_vbus) ++ return -EOPNOTSUPP; + if (fsm->drv_vbus != on) { + fsm->drv_vbus = on; +- fsm->ops->drv_vbus(on); ++ fsm->ops->drv_vbus(fsm, on); + } ++ return 0; + } + +-static inline void otg_loc_conn(struct otg_fsm *fsm, int on) ++static inline int otg_loc_conn(struct otg_fsm *fsm, int on) + { ++ if (!fsm->ops->loc_conn) ++ return -EOPNOTSUPP; + if (fsm->loc_conn != on) { + fsm->loc_conn = on; +- fsm->ops->loc_conn(on); ++ fsm->ops->loc_conn(fsm, on); + } ++ return 0; + } + +-static inline void otg_loc_sof(struct otg_fsm *fsm, int on) ++static inline int otg_loc_sof(struct otg_fsm *fsm, int on) + { ++ if (!fsm->ops->loc_sof) ++ return -EOPNOTSUPP; + if (fsm->loc_sof != on) { + fsm->loc_sof = on; +- fsm->ops->loc_sof(on); ++ fsm->ops->loc_sof(fsm, on); ++ } ++ return 0; ++} ++ ++static inline int otg_start_pulse(struct otg_fsm *fsm) ++{ ++ if (!fsm->ops->start_pulse) ++ return -EOPNOTSUPP; ++ if (!fsm->data_pulse) { ++ fsm->data_pulse = 1; ++ fsm->ops->start_pulse(fsm); + } ++ return 0; + } + +-static inline void otg_start_pulse(struct otg_fsm *fsm) ++static inline int otg_start_adp_prb(struct otg_fsm *fsm) + { +- fsm->ops->start_pulse(); ++ if (!fsm->ops->start_adp_prb) ++ return -EOPNOTSUPP; ++ if (!fsm->adp_prb) { ++ fsm->adp_sns = 0; ++ fsm->adp_prb = 1; ++ fsm->ops->start_adp_prb(fsm); ++ } ++ return 0; + } + +-static inline void otg_add_timer(struct otg_fsm *fsm, void *timer) ++static inline int otg_start_adp_sns(struct otg_fsm *fsm) + { +- fsm->ops->add_timer(timer); ++ if (!fsm->ops->start_adp_sns) ++ return -EOPNOTSUPP; ++ if (!fsm->adp_sns) { ++ fsm->adp_sns = 1; ++ fsm->ops->start_adp_sns(fsm); ++ } ++ return 0; + } + +-static inline void otg_del_timer(struct otg_fsm *fsm, void *timer) ++static inline int otg_add_timer(struct otg_fsm *fsm, enum otg_fsm_timer timer) + { +- fsm->ops->del_timer(timer); ++ if (!fsm->ops->add_timer) ++ return -EOPNOTSUPP; ++ fsm->ops->add_timer(fsm, timer); ++ return 0; + } + +-int otg_statemachine(struct otg_fsm *fsm); ++static inline int otg_del_timer(struct otg_fsm *fsm, enum otg_fsm_timer timer) ++{ ++ if (!fsm->ops->del_timer) ++ return -EOPNOTSUPP; ++ fsm->ops->del_timer(fsm, timer); ++ return 0; ++} + +-/* Defined by device specific driver, for different timer implementation */ +-extern struct fsl_otg_timer *a_wait_vrise_tmr, *a_wait_bcon_tmr, +- *a_aidl_bdis_tmr, *b_ase0_brst_tmr, *b_se0_srp_tmr, *b_srp_fail_tmr, +- *a_wait_enum_tmr; ++static inline int otg_start_host(struct otg_fsm *fsm, int on) ++{ ++ if (!fsm->ops->start_host) ++ return -EOPNOTSUPP; ++ return fsm->ops->start_host(fsm, on); ++} ++ ++static inline int otg_start_gadget(struct otg_fsm *fsm, int on) ++{ ++ if (!fsm->ops->start_gadget) ++ return -EOPNOTSUPP; ++ return fsm->ops->start_gadget(fsm, on); ++} ++ ++int otg_statemachine(struct otg_fsm *fsm); +--- a/drivers/usb/phy/phy-generic.c ++++ b/drivers/usb/phy/phy-generic.c +@@ -35,6 +35,9 @@ + #include <linux/clk.h> + #include <linux/regulator/consumer.h> + #include <linux/of.h> ++#include <linux/of_gpio.h> ++#include <linux/gpio.h> ++#include <linux/delay.h> + + #include "phy-generic.h" + +@@ -64,6 +67,23 @@ static int nop_set_suspend(struct usb_ph + return 0; + } + ++static void nop_reset_set(struct usb_phy_gen_xceiv *nop, int asserted) ++{ ++ int value; ++ ++ if (!gpio_is_valid(nop->gpio_reset)) ++ return; ++ ++ value = asserted; ++ if (nop->reset_active_low) ++ value = !value; ++ ++ gpio_set_value_cansleep(nop->gpio_reset, value); ++ ++ if (!asserted) ++ usleep_range(10000, 20000); ++} ++ + int usb_gen_phy_init(struct usb_phy *phy) + { + struct usb_phy_gen_xceiv *nop = dev_get_drvdata(phy->dev); +@@ -74,13 +94,10 @@ int usb_gen_phy_init(struct usb_phy *phy + } + + if (!IS_ERR(nop->clk)) +- clk_enable(nop->clk); ++ clk_prepare_enable(nop->clk); + +- if (!IS_ERR(nop->reset)) { +- /* De-assert RESET */ +- if (regulator_enable(nop->reset)) +- dev_err(phy->dev, "Failed to de-assert reset\n"); +- } ++ /* De-assert RESET */ ++ nop_reset_set(nop, 0); + + return 0; + } +@@ -90,14 +107,11 @@ void usb_gen_phy_shutdown(struct usb_phy + { + struct usb_phy_gen_xceiv *nop = dev_get_drvdata(phy->dev); + +- if (!IS_ERR(nop->reset)) { +- /* Assert RESET */ +- if (regulator_disable(nop->reset)) +- dev_err(phy->dev, "Failed to assert reset\n"); +- } ++ /* Assert RESET */ ++ nop_reset_set(nop, 1); + + if (!IS_ERR(nop->clk)) +- clk_disable(nop->clk); ++ clk_disable_unprepare(nop->clk); + + if (!IS_ERR(nop->vcc)) { + if (regulator_disable(nop->vcc)) +@@ -136,11 +150,38 @@ static int nop_set_host(struct usb_otg * + } + + int usb_phy_gen_create_phy(struct device *dev, struct usb_phy_gen_xceiv *nop, +- enum usb_phy_type type, u32 clk_rate, bool needs_vcc, +- bool needs_reset) ++ struct usb_phy_gen_xceiv_platform_data *pdata) + { ++ enum usb_phy_type type = USB_PHY_TYPE_USB2; + int err; + ++ u32 clk_rate = 0; ++ bool needs_vcc = false; ++ ++ nop->reset_active_low = true; /* default behaviour */ ++ ++ if (dev->of_node) { ++ struct device_node *node = dev->of_node; ++ enum of_gpio_flags flags; ++ ++ if (of_property_read_u32(node, "clock-frequency", &clk_rate)) ++ clk_rate = 0; ++ ++ needs_vcc = of_property_read_bool(node, "vcc-supply"); ++ nop->gpio_reset = of_get_named_gpio_flags(node, "reset-gpios", ++ 0, &flags); ++ if (nop->gpio_reset == -EPROBE_DEFER) ++ return -EPROBE_DEFER; ++ ++ nop->reset_active_low = flags & OF_GPIO_ACTIVE_LOW; ++ ++ } else if (pdata) { ++ type = pdata->type; ++ clk_rate = pdata->clk_rate; ++ needs_vcc = pdata->needs_vcc; ++ nop->gpio_reset = pdata->gpio_reset; ++ } ++ + nop->phy.otg = devm_kzalloc(dev, sizeof(*nop->phy.otg), + GFP_KERNEL); + if (!nop->phy.otg) +@@ -160,14 +201,6 @@ int usb_phy_gen_create_phy(struct device + } + } + +- if (!IS_ERR(nop->clk)) { +- err = clk_prepare(nop->clk); +- if (err) { +- dev_err(dev, "Error preparing clock\n"); +- return err; +- } +- } +- + nop->vcc = devm_regulator_get(dev, "vcc"); + if (IS_ERR(nop->vcc)) { + dev_dbg(dev, "Error getting vcc regulator: %ld\n", +@@ -176,12 +209,22 @@ int usb_phy_gen_create_phy(struct device + return -EPROBE_DEFER; + } + +- nop->reset = devm_regulator_get(dev, "reset"); +- if (IS_ERR(nop->reset)) { +- dev_dbg(dev, "Error getting reset regulator: %ld\n", +- PTR_ERR(nop->reset)); +- if (needs_reset) +- return -EPROBE_DEFER; ++ if (gpio_is_valid(nop->gpio_reset)) { ++ unsigned long gpio_flags; ++ ++ /* Assert RESET */ ++ if (nop->reset_active_low) ++ gpio_flags = GPIOF_OUT_INIT_LOW; ++ else ++ gpio_flags = GPIOF_OUT_INIT_HIGH; ++ ++ err = devm_gpio_request_one(dev, nop->gpio_reset, ++ gpio_flags, dev_name(dev)); ++ if (err) { ++ dev_err(dev, "Error requesting RESET GPIO %d\n", ++ nop->gpio_reset); ++ return err; ++ } + } + + nop->dev = dev; +@@ -200,48 +243,17 @@ int usb_phy_gen_create_phy(struct device + } + EXPORT_SYMBOL_GPL(usb_phy_gen_create_phy); + +-void usb_phy_gen_cleanup_phy(struct usb_phy_gen_xceiv *nop) +-{ +- if (!IS_ERR(nop->clk)) +- clk_unprepare(nop->clk); +-} +-EXPORT_SYMBOL_GPL(usb_phy_gen_cleanup_phy); +- + static int usb_phy_gen_xceiv_probe(struct platform_device *pdev) + { + struct device *dev = &pdev->dev; +- struct usb_phy_gen_xceiv_platform_data *pdata = +- dev_get_platdata(&pdev->dev); + struct usb_phy_gen_xceiv *nop; +- enum usb_phy_type type = USB_PHY_TYPE_USB2; + int err; +- u32 clk_rate = 0; +- bool needs_vcc = false; +- bool needs_reset = false; +- +- if (dev->of_node) { +- struct device_node *node = dev->of_node; +- +- if (of_property_read_u32(node, "clock-frequency", &clk_rate)) +- clk_rate = 0; +- +- needs_vcc = of_property_read_bool(node, "vcc-supply"); +- needs_reset = of_property_read_bool(node, "reset-supply"); +- +- } else if (pdata) { +- type = pdata->type; +- clk_rate = pdata->clk_rate; +- needs_vcc = pdata->needs_vcc; +- needs_reset = pdata->needs_reset; +- } + + nop = devm_kzalloc(dev, sizeof(*nop), GFP_KERNEL); + if (!nop) + return -ENOMEM; + +- +- err = usb_phy_gen_create_phy(dev, nop, type, clk_rate, needs_vcc, +- needs_reset); ++ err = usb_phy_gen_create_phy(dev, nop, dev_get_platdata(&pdev->dev)); + if (err) + return err; + +@@ -252,23 +264,18 @@ static int usb_phy_gen_xceiv_probe(struc + if (err) { + dev_err(&pdev->dev, "can't register transceiver, err: %d\n", + err); +- goto err_add; ++ return err; + } + + platform_set_drvdata(pdev, nop); + + return 0; +- +-err_add: +- usb_phy_gen_cleanup_phy(nop); +- return err; + } + + static int usb_phy_gen_xceiv_remove(struct platform_device *pdev) + { + struct usb_phy_gen_xceiv *nop = platform_get_drvdata(pdev); + +- usb_phy_gen_cleanup_phy(nop); + usb_remove_phy(&nop->phy); + + return 0; +--- a/drivers/usb/phy/phy-generic.h ++++ b/drivers/usb/phy/phy-generic.h +@@ -1,20 +1,21 @@ + #ifndef _PHY_GENERIC_H_ + #define _PHY_GENERIC_H_ + ++#include <linux/usb/usb_phy_gen_xceiv.h> ++ + struct usb_phy_gen_xceiv { + struct usb_phy phy; + struct device *dev; + struct clk *clk; + struct regulator *vcc; +- struct regulator *reset; ++ int gpio_reset; ++ bool reset_active_low; + }; + + int usb_gen_phy_init(struct usb_phy *phy); + void usb_gen_phy_shutdown(struct usb_phy *phy); + + int usb_phy_gen_create_phy(struct device *dev, struct usb_phy_gen_xceiv *nop, +- enum usb_phy_type type, u32 clk_rate, bool needs_vcc, +- bool needs_reset); +-void usb_phy_gen_cleanup_phy(struct usb_phy_gen_xceiv *nop); ++ struct usb_phy_gen_xceiv_platform_data *pdata); + + #endif +--- a/drivers/usb/phy/phy-omap-control.c ++++ /dev/null +@@ -1,290 +0,0 @@ +-/* +- * omap-control-usb.c - The USB part of control module. +- * +- * Copyright (C) 2013 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; either version 2 of the License, or +- * (at your option) any later version. +- * +- * Author: Kishon Vijay Abraham I <kishon@ti.com> +- * +- * 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/module.h> +-#include <linux/platform_device.h> +-#include <linux/slab.h> +-#include <linux/of.h> +-#include <linux/err.h> +-#include <linux/io.h> +-#include <linux/clk.h> +-#include <linux/usb/omap_control_usb.h> +- +-static struct omap_control_usb *control_usb; +- +-/** +- * omap_get_control_dev - returns the device pointer for this control device +- * +- * This API should be called to get the device pointer for this control +- * module device. This device pointer should be used for called other +- * exported API's in this driver. +- * +- * To be used by PHY driver and glue driver. +- */ +-struct device *omap_get_control_dev(void) +-{ +- if (!control_usb) +- return ERR_PTR(-ENODEV); +- +- return control_usb->dev; +-} +-EXPORT_SYMBOL_GPL(omap_get_control_dev); +- +-/** +- * omap_control_usb3_phy_power - power on/off the serializer using control +- * module +- * @dev: the control module device +- * @on: 0 to off and 1 to on based on powering on or off the PHY +- * +- * usb3 PHY driver should call this API to power on or off the PHY. +- */ +-void omap_control_usb3_phy_power(struct device *dev, bool on) +-{ +- u32 val; +- unsigned long rate; +- struct omap_control_usb *control_usb = dev_get_drvdata(dev); +- +- if (control_usb->type != OMAP_CTRL_DEV_TYPE2) +- return; +- +- rate = clk_get_rate(control_usb->sys_clk); +- rate = rate/1000000; +- +- val = readl(control_usb->phy_power); +- +- if (on) { +- val &= ~(OMAP_CTRL_USB_PWRCTL_CLK_CMD_MASK | +- OMAP_CTRL_USB_PWRCTL_CLK_FREQ_MASK); +- val |= OMAP_CTRL_USB3_PHY_TX_RX_POWERON << +- OMAP_CTRL_USB_PWRCTL_CLK_CMD_SHIFT; +- val |= rate << OMAP_CTRL_USB_PWRCTL_CLK_FREQ_SHIFT; +- } else { +- val &= ~OMAP_CTRL_USB_PWRCTL_CLK_CMD_MASK; +- val |= OMAP_CTRL_USB3_PHY_TX_RX_POWEROFF << +- OMAP_CTRL_USB_PWRCTL_CLK_CMD_SHIFT; +- } +- +- writel(val, control_usb->phy_power); +-} +-EXPORT_SYMBOL_GPL(omap_control_usb3_phy_power); +- +-/** +- * omap_control_usb_phy_power - power on/off the phy using control module reg +- * @dev: the control module device +- * @on: 0 or 1, based on powering on or off the PHY +- */ +-void omap_control_usb_phy_power(struct device *dev, int on) +-{ +- u32 val; +- struct omap_control_usb *control_usb = dev_get_drvdata(dev); +- +- val = readl(control_usb->dev_conf); +- +- if (on) +- val &= ~OMAP_CTRL_DEV_PHY_PD; +- else +- val |= OMAP_CTRL_DEV_PHY_PD; +- +- writel(val, control_usb->dev_conf); +-} +-EXPORT_SYMBOL_GPL(omap_control_usb_phy_power); +- +-/** +- * omap_control_usb_host_mode - set AVALID, VBUSVALID and ID pin in grounded +- * @ctrl_usb: struct omap_control_usb * +- * +- * Writes to the mailbox register to notify the usb core that a usb +- * device has been connected. +- */ +-static void omap_control_usb_host_mode(struct omap_control_usb *ctrl_usb) +-{ +- u32 val; +- +- val = readl(ctrl_usb->otghs_control); +- val &= ~(OMAP_CTRL_DEV_IDDIG | OMAP_CTRL_DEV_SESSEND); +- val |= OMAP_CTRL_DEV_AVALID | OMAP_CTRL_DEV_VBUSVALID; +- writel(val, ctrl_usb->otghs_control); +-} +- +-/** +- * omap_control_usb_device_mode - set AVALID, VBUSVALID and ID pin in high +- * impedance +- * @ctrl_usb: struct omap_control_usb * +- * +- * Writes to the mailbox register to notify the usb core that it has been +- * connected to a usb host. +- */ +-static void omap_control_usb_device_mode(struct omap_control_usb *ctrl_usb) +-{ +- u32 val; +- +- val = readl(ctrl_usb->otghs_control); +- val &= ~OMAP_CTRL_DEV_SESSEND; +- val |= OMAP_CTRL_DEV_IDDIG | OMAP_CTRL_DEV_AVALID | +- OMAP_CTRL_DEV_VBUSVALID; +- writel(val, ctrl_usb->otghs_control); +-} +- +-/** +- * omap_control_usb_set_sessionend - Enable SESSIONEND and IDIG to high +- * impedance +- * @ctrl_usb: struct omap_control_usb * +- * +- * Writes to the mailbox register to notify the usb core it's now in +- * disconnected state. +- */ +-static void omap_control_usb_set_sessionend(struct omap_control_usb *ctrl_usb) +-{ +- u32 val; +- +- val = readl(ctrl_usb->otghs_control); +- val &= ~(OMAP_CTRL_DEV_AVALID | OMAP_CTRL_DEV_VBUSVALID); +- val |= OMAP_CTRL_DEV_IDDIG | OMAP_CTRL_DEV_SESSEND; +- writel(val, ctrl_usb->otghs_control); +-} +- +-/** +- * omap_control_usb_set_mode - Calls to functions to set USB in one of host mode +- * or device mode or to denote disconnected state +- * @dev: the control module device +- * @mode: The mode to which usb should be configured +- * +- * This is an API to write to the mailbox register to notify the usb core that +- * a usb device has been connected. +- */ +-void omap_control_usb_set_mode(struct device *dev, +- enum omap_control_usb_mode mode) +-{ +- struct omap_control_usb *ctrl_usb; +- +- if (IS_ERR(dev) || control_usb->type != OMAP_CTRL_DEV_TYPE1) +- return; +- +- ctrl_usb = dev_get_drvdata(dev); +- +- switch (mode) { +- case USB_MODE_HOST: +- omap_control_usb_host_mode(ctrl_usb); +- break; +- case USB_MODE_DEVICE: +- omap_control_usb_device_mode(ctrl_usb); +- break; +- case USB_MODE_DISCONNECT: +- omap_control_usb_set_sessionend(ctrl_usb); +- break; +- default: +- dev_vdbg(dev, "invalid omap control usb mode\n"); +- } +-} +-EXPORT_SYMBOL_GPL(omap_control_usb_set_mode); +- +-static int omap_control_usb_probe(struct platform_device *pdev) +-{ +- struct resource *res; +- struct device_node *np = pdev->dev.of_node; +- struct omap_control_usb_platform_data *pdata = +- dev_get_platdata(&pdev->dev); +- +- control_usb = devm_kzalloc(&pdev->dev, sizeof(*control_usb), +- GFP_KERNEL); +- if (!control_usb) { +- dev_err(&pdev->dev, "unable to alloc memory for control usb\n"); +- return -ENOMEM; +- } +- +- if (np) { +- of_property_read_u32(np, "ti,type", &control_usb->type); +- } else if (pdata) { +- control_usb->type = pdata->type; +- } else { +- dev_err(&pdev->dev, "no pdata present\n"); +- return -EINVAL; +- } +- +- control_usb->dev = &pdev->dev; +- +- res = platform_get_resource_byname(pdev, IORESOURCE_MEM, +- "control_dev_conf"); +- control_usb->dev_conf = devm_ioremap_resource(&pdev->dev, res); +- if (IS_ERR(control_usb->dev_conf)) +- return PTR_ERR(control_usb->dev_conf); +- +- if (control_usb->type == OMAP_CTRL_DEV_TYPE1) { +- res = platform_get_resource_byname(pdev, IORESOURCE_MEM, +- "otghs_control"); +- control_usb->otghs_control = devm_ioremap_resource( +- &pdev->dev, res); +- if (IS_ERR(control_usb->otghs_control)) +- return PTR_ERR(control_usb->otghs_control); +- } +- +- if (control_usb->type == OMAP_CTRL_DEV_TYPE2) { +- res = platform_get_resource_byname(pdev, IORESOURCE_MEM, +- "phy_power_usb"); +- control_usb->phy_power = devm_ioremap_resource( +- &pdev->dev, res); +- if (IS_ERR(control_usb->phy_power)) +- return PTR_ERR(control_usb->phy_power); +- +- control_usb->sys_clk = devm_clk_get(control_usb->dev, +- "sys_clkin"); +- if (IS_ERR(control_usb->sys_clk)) { +- pr_err("%s: unable to get sys_clkin\n", __func__); +- return -EINVAL; +- } +- } +- +- +- dev_set_drvdata(control_usb->dev, control_usb); +- +- return 0; +-} +- +-#ifdef CONFIG_OF +-static const struct of_device_id omap_control_usb_id_table[] = { +- { .compatible = "ti,omap-control-usb" }, +- {} +-}; +-MODULE_DEVICE_TABLE(of, omap_control_usb_id_table); +-#endif +- +-static struct platform_driver omap_control_usb_driver = { +- .probe = omap_control_usb_probe, +- .driver = { +- .name = "omap-control-usb", +- .owner = THIS_MODULE, +- .of_match_table = of_match_ptr(omap_control_usb_id_table), +- }, +-}; +- +-static int __init omap_control_usb_init(void) +-{ +- return platform_driver_register(&omap_control_usb_driver); +-} +-subsys_initcall(omap_control_usb_init); +- +-static void __exit omap_control_usb_exit(void) +-{ +- platform_driver_unregister(&omap_control_usb_driver); +-} +-module_exit(omap_control_usb_exit); +- +-MODULE_ALIAS("platform: omap_control_usb"); +-MODULE_AUTHOR("Texas Instruments Inc."); +-MODULE_DESCRIPTION("OMAP Control Module USB Driver"); +-MODULE_LICENSE("GPL v2"); +--- a/drivers/usb/phy/phy-omap-usb2.c ++++ /dev/null +@@ -1,272 +0,0 @@ +-/* +- * omap-usb2.c - USB PHY, talking to musb controller in OMAP. +- * +- * Copyright (C) 2012 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; either version 2 of the License, or +- * (at your option) any later version. +- * +- * Author: Kishon Vijay Abraham I <kishon@ti.com> +- * +- * 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/module.h> +-#include <linux/platform_device.h> +-#include <linux/slab.h> +-#include <linux/of.h> +-#include <linux/io.h> +-#include <linux/usb/omap_usb.h> +-#include <linux/usb/phy_companion.h> +-#include <linux/clk.h> +-#include <linux/err.h> +-#include <linux/pm_runtime.h> +-#include <linux/delay.h> +-#include <linux/usb/omap_control_usb.h> +- +-/** +- * omap_usb2_set_comparator - links the comparator present in the sytem with +- * this phy +- * @comparator - the companion phy(comparator) for this phy +- * +- * The phy companion driver should call this API passing the phy_companion +- * filled with set_vbus and start_srp to be used by usb phy. +- * +- * For use by phy companion driver +- */ +-int omap_usb2_set_comparator(struct phy_companion *comparator) +-{ +- struct omap_usb *phy; +- struct usb_phy *x = usb_get_phy(USB_PHY_TYPE_USB2); +- +- if (IS_ERR(x)) +- return -ENODEV; +- +- phy = phy_to_omapusb(x); +- phy->comparator = comparator; +- return 0; +-} +-EXPORT_SYMBOL_GPL(omap_usb2_set_comparator); +- +-static int omap_usb_set_vbus(struct usb_otg *otg, bool enabled) +-{ +- struct omap_usb *phy = phy_to_omapusb(otg->phy); +- +- if (!phy->comparator) +- return -ENODEV; +- +- return phy->comparator->set_vbus(phy->comparator, enabled); +-} +- +-static int omap_usb_start_srp(struct usb_otg *otg) +-{ +- struct omap_usb *phy = phy_to_omapusb(otg->phy); +- +- if (!phy->comparator) +- return -ENODEV; +- +- return phy->comparator->start_srp(phy->comparator); +-} +- +-static int omap_usb_set_host(struct usb_otg *otg, struct usb_bus *host) +-{ +- struct usb_phy *phy = otg->phy; +- +- otg->host = host; +- if (!host) +- phy->state = OTG_STATE_UNDEFINED; +- +- return 0; +-} +- +-static int omap_usb_set_peripheral(struct usb_otg *otg, +- struct usb_gadget *gadget) +-{ +- struct usb_phy *phy = otg->phy; +- +- otg->gadget = gadget; +- if (!gadget) +- phy->state = OTG_STATE_UNDEFINED; +- +- return 0; +-} +- +-static int omap_usb2_suspend(struct usb_phy *x, int suspend) +-{ +- struct omap_usb *phy = phy_to_omapusb(x); +- int ret; +- +- if (suspend && !phy->is_suspended) { +- omap_control_usb_phy_power(phy->control_dev, 0); +- pm_runtime_put_sync(phy->dev); +- phy->is_suspended = 1; +- } else if (!suspend && phy->is_suspended) { +- ret = pm_runtime_get_sync(phy->dev); +- if (ret < 0) { +- dev_err(phy->dev, "get_sync failed with err %d\n", ret); +- return ret; +- } +- omap_control_usb_phy_power(phy->control_dev, 1); +- phy->is_suspended = 0; +- } +- +- return 0; +-} +- +-static int omap_usb2_probe(struct platform_device *pdev) +-{ +- struct omap_usb *phy; +- struct usb_otg *otg; +- +- phy = devm_kzalloc(&pdev->dev, sizeof(*phy), GFP_KERNEL); +- if (!phy) { +- dev_err(&pdev->dev, "unable to allocate memory for USB2 PHY\n"); +- return -ENOMEM; +- } +- +- otg = devm_kzalloc(&pdev->dev, sizeof(*otg), GFP_KERNEL); +- if (!otg) { +- dev_err(&pdev->dev, "unable to allocate memory for USB OTG\n"); +- return -ENOMEM; +- } +- +- phy->dev = &pdev->dev; +- +- phy->phy.dev = phy->dev; +- phy->phy.label = "omap-usb2"; +- phy->phy.set_suspend = omap_usb2_suspend; +- phy->phy.otg = otg; +- phy->phy.type = USB_PHY_TYPE_USB2; +- +- phy->control_dev = omap_get_control_dev(); +- if (IS_ERR(phy->control_dev)) { +- dev_dbg(&pdev->dev, "Failed to get control device\n"); +- return -ENODEV; +- } +- +- phy->is_suspended = 1; +- omap_control_usb_phy_power(phy->control_dev, 0); +- +- otg->set_host = omap_usb_set_host; +- otg->set_peripheral = omap_usb_set_peripheral; +- otg->set_vbus = omap_usb_set_vbus; +- otg->start_srp = omap_usb_start_srp; +- otg->phy = &phy->phy; +- +- phy->wkupclk = devm_clk_get(phy->dev, "usb_phy_cm_clk32k"); +- if (IS_ERR(phy->wkupclk)) { +- dev_err(&pdev->dev, "unable to get usb_phy_cm_clk32k\n"); +- return PTR_ERR(phy->wkupclk); +- } +- clk_prepare(phy->wkupclk); +- +- phy->optclk = devm_clk_get(phy->dev, "usb_otg_ss_refclk960m"); +- if (IS_ERR(phy->optclk)) +- dev_vdbg(&pdev->dev, "unable to get refclk960m\n"); +- else +- clk_prepare(phy->optclk); +- +- usb_add_phy_dev(&phy->phy); +- +- platform_set_drvdata(pdev, phy); +- +- pm_runtime_enable(phy->dev); +- +- return 0; +-} +- +-static int omap_usb2_remove(struct platform_device *pdev) +-{ +- struct omap_usb *phy = platform_get_drvdata(pdev); +- +- clk_unprepare(phy->wkupclk); +- if (!IS_ERR(phy->optclk)) +- clk_unprepare(phy->optclk); +- usb_remove_phy(&phy->phy); +- +- return 0; +-} +- +-#ifdef CONFIG_PM_RUNTIME +- +-static int omap_usb2_runtime_suspend(struct device *dev) +-{ +- struct platform_device *pdev = to_platform_device(dev); +- struct omap_usb *phy = platform_get_drvdata(pdev); +- +- clk_disable(phy->wkupclk); +- if (!IS_ERR(phy->optclk)) +- clk_disable(phy->optclk); +- +- return 0; +-} +- +-static int omap_usb2_runtime_resume(struct device *dev) +-{ +- struct platform_device *pdev = to_platform_device(dev); +- struct omap_usb *phy = platform_get_drvdata(pdev); +- int ret; +- +- ret = clk_enable(phy->wkupclk); +- if (ret < 0) { +- dev_err(phy->dev, "Failed to enable wkupclk %d\n", ret); +- goto err0; +- } +- +- if (!IS_ERR(phy->optclk)) { +- ret = clk_enable(phy->optclk); +- if (ret < 0) { +- dev_err(phy->dev, "Failed to enable optclk %d\n", ret); +- goto err1; +- } +- } +- +- return 0; +- +-err1: +- clk_disable(phy->wkupclk); +- +-err0: +- return ret; +-} +- +-static const struct dev_pm_ops omap_usb2_pm_ops = { +- SET_RUNTIME_PM_OPS(omap_usb2_runtime_suspend, omap_usb2_runtime_resume, +- NULL) +-}; +- +-#define DEV_PM_OPS (&omap_usb2_pm_ops) +-#else +-#define DEV_PM_OPS NULL +-#endif +- +-#ifdef CONFIG_OF +-static const struct of_device_id omap_usb2_id_table[] = { +- { .compatible = "ti,omap-usb2" }, +- {} +-}; +-MODULE_DEVICE_TABLE(of, omap_usb2_id_table); +-#endif +- +-static struct platform_driver omap_usb2_driver = { +- .probe = omap_usb2_probe, +- .remove = omap_usb2_remove, +- .driver = { +- .name = "omap-usb2", +- .owner = THIS_MODULE, +- .pm = DEV_PM_OPS, +- .of_match_table = of_match_ptr(omap_usb2_id_table), +- }, +-}; +- +-module_platform_driver(omap_usb2_driver); +- +-MODULE_ALIAS("platform: omap_usb2"); +-MODULE_AUTHOR("Texas Instruments Inc."); +-MODULE_DESCRIPTION("OMAP USB2 phy driver"); +-MODULE_LICENSE("GPL v2"); +--- a/drivers/usb/phy/phy-omap-usb3.c ++++ /dev/null +@@ -1,347 +0,0 @@ +-/* +- * omap-usb3 - USB PHY, talking to dwc3 controller in OMAP. +- * +- * Copyright (C) 2013 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; either version 2 of the License, or +- * (at your option) any later version. +- * +- * Author: Kishon Vijay Abraham I <kishon@ti.com> +- * +- * 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/module.h> +-#include <linux/platform_device.h> +-#include <linux/slab.h> +-#include <linux/usb/omap_usb.h> +-#include <linux/of.h> +-#include <linux/clk.h> +-#include <linux/err.h> +-#include <linux/pm_runtime.h> +-#include <linux/delay.h> +-#include <linux/usb/omap_control_usb.h> +- +-#define PLL_STATUS 0x00000004 +-#define PLL_GO 0x00000008 +-#define PLL_CONFIGURATION1 0x0000000C +-#define PLL_CONFIGURATION2 0x00000010 +-#define PLL_CONFIGURATION3 0x00000014 +-#define PLL_CONFIGURATION4 0x00000020 +- +-#define PLL_REGM_MASK 0x001FFE00 +-#define PLL_REGM_SHIFT 0x9 +-#define PLL_REGM_F_MASK 0x0003FFFF +-#define PLL_REGM_F_SHIFT 0x0 +-#define PLL_REGN_MASK 0x000001FE +-#define PLL_REGN_SHIFT 0x1 +-#define PLL_SELFREQDCO_MASK 0x0000000E +-#define PLL_SELFREQDCO_SHIFT 0x1 +-#define PLL_SD_MASK 0x0003FC00 +-#define PLL_SD_SHIFT 0x9 +-#define SET_PLL_GO 0x1 +-#define PLL_TICOPWDN 0x10000 +-#define PLL_LOCK 0x2 +-#define PLL_IDLE 0x1 +- +-/* +- * This is an Empirical value that works, need to confirm the actual +- * value required for the USB3PHY_PLL_CONFIGURATION2.PLL_IDLE status +- * to be correctly reflected in the USB3PHY_PLL_STATUS register. +- */ +-# define PLL_IDLE_TIME 100; +- +-struct usb_dpll_map { +- unsigned long rate; +- struct usb_dpll_params params; +-}; +- +-static struct usb_dpll_map dpll_map[] = { +- {12000000, {1250, 5, 4, 20, 0} }, /* 12 MHz */ +- {16800000, {3125, 20, 4, 20, 0} }, /* 16.8 MHz */ +- {19200000, {1172, 8, 4, 20, 65537} }, /* 19.2 MHz */ +- {20000000, {1000, 7, 4, 10, 0} }, /* 20 MHz */ +- {26000000, {1250, 12, 4, 20, 0} }, /* 26 MHz */ +- {38400000, {3125, 47, 4, 20, 92843} }, /* 38.4 MHz */ +-}; +- +-static struct usb_dpll_params *omap_usb3_get_dpll_params(unsigned long rate) +-{ +- int i; +- +- for (i = 0; i < ARRAY_SIZE(dpll_map); i++) { +- if (rate == dpll_map[i].rate) +- return &dpll_map[i].params; +- } +- +- return NULL; +-} +- +-static int omap_usb3_suspend(struct usb_phy *x, int suspend) +-{ +- struct omap_usb *phy = phy_to_omapusb(x); +- int val; +- int timeout = PLL_IDLE_TIME; +- +- if (suspend && !phy->is_suspended) { +- val = omap_usb_readl(phy->pll_ctrl_base, PLL_CONFIGURATION2); +- val |= PLL_IDLE; +- omap_usb_writel(phy->pll_ctrl_base, PLL_CONFIGURATION2, val); +- +- do { +- val = omap_usb_readl(phy->pll_ctrl_base, PLL_STATUS); +- if (val & PLL_TICOPWDN) +- break; +- udelay(1); +- } while (--timeout); +- +- omap_control_usb3_phy_power(phy->control_dev, 0); +- +- phy->is_suspended = 1; +- } else if (!suspend && phy->is_suspended) { +- phy->is_suspended = 0; +- +- val = omap_usb_readl(phy->pll_ctrl_base, PLL_CONFIGURATION2); +- val &= ~PLL_IDLE; +- omap_usb_writel(phy->pll_ctrl_base, PLL_CONFIGURATION2, val); +- +- do { +- val = omap_usb_readl(phy->pll_ctrl_base, PLL_STATUS); +- if (!(val & PLL_TICOPWDN)) +- break; +- udelay(1); +- } while (--timeout); +- } +- +- return 0; +-} +- +-static void omap_usb_dpll_relock(struct omap_usb *phy) +-{ +- u32 val; +- unsigned long timeout; +- +- omap_usb_writel(phy->pll_ctrl_base, PLL_GO, SET_PLL_GO); +- +- timeout = jiffies + msecs_to_jiffies(20); +- do { +- val = omap_usb_readl(phy->pll_ctrl_base, PLL_STATUS); +- if (val & PLL_LOCK) +- break; +- } while (!WARN_ON(time_after(jiffies, timeout))); +-} +- +-static int omap_usb_dpll_lock(struct omap_usb *phy) +-{ +- u32 val; +- unsigned long rate; +- struct usb_dpll_params *dpll_params; +- +- rate = clk_get_rate(phy->sys_clk); +- dpll_params = omap_usb3_get_dpll_params(rate); +- if (!dpll_params) { +- dev_err(phy->dev, +- "No DPLL configuration for %lu Hz SYS CLK\n", rate); +- return -EINVAL; +- } +- +- val = omap_usb_readl(phy->pll_ctrl_base, PLL_CONFIGURATION1); +- val &= ~PLL_REGN_MASK; +- val |= dpll_params->n << PLL_REGN_SHIFT; +- omap_usb_writel(phy->pll_ctrl_base, PLL_CONFIGURATION1, val); +- +- val = omap_usb_readl(phy->pll_ctrl_base, PLL_CONFIGURATION2); +- val &= ~PLL_SELFREQDCO_MASK; +- val |= dpll_params->freq << PLL_SELFREQDCO_SHIFT; +- omap_usb_writel(phy->pll_ctrl_base, PLL_CONFIGURATION2, val); +- +- val = omap_usb_readl(phy->pll_ctrl_base, PLL_CONFIGURATION1); +- val &= ~PLL_REGM_MASK; +- val |= dpll_params->m << PLL_REGM_SHIFT; +- omap_usb_writel(phy->pll_ctrl_base, PLL_CONFIGURATION1, val); +- +- val = omap_usb_readl(phy->pll_ctrl_base, PLL_CONFIGURATION4); +- val &= ~PLL_REGM_F_MASK; +- val |= dpll_params->mf << PLL_REGM_F_SHIFT; +- omap_usb_writel(phy->pll_ctrl_base, PLL_CONFIGURATION4, val); +- +- val = omap_usb_readl(phy->pll_ctrl_base, PLL_CONFIGURATION3); +- val &= ~PLL_SD_MASK; +- val |= dpll_params->sd << PLL_SD_SHIFT; +- omap_usb_writel(phy->pll_ctrl_base, PLL_CONFIGURATION3, val); +- +- omap_usb_dpll_relock(phy); +- +- return 0; +-} +- +-static int omap_usb3_init(struct usb_phy *x) +-{ +- struct omap_usb *phy = phy_to_omapusb(x); +- int ret; +- +- ret = omap_usb_dpll_lock(phy); +- if (ret) +- return ret; +- +- omap_control_usb3_phy_power(phy->control_dev, 1); +- +- return 0; +-} +- +-static int omap_usb3_probe(struct platform_device *pdev) +-{ +- struct omap_usb *phy; +- struct resource *res; +- +- phy = devm_kzalloc(&pdev->dev, sizeof(*phy), GFP_KERNEL); +- if (!phy) { +- dev_err(&pdev->dev, "unable to alloc mem for OMAP USB3 PHY\n"); +- return -ENOMEM; +- } +- +- res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "pll_ctrl"); +- phy->pll_ctrl_base = devm_ioremap_resource(&pdev->dev, res); +- if (IS_ERR(phy->pll_ctrl_base)) +- return PTR_ERR(phy->pll_ctrl_base); +- +- phy->dev = &pdev->dev; +- +- phy->phy.dev = phy->dev; +- phy->phy.label = "omap-usb3"; +- phy->phy.init = omap_usb3_init; +- phy->phy.set_suspend = omap_usb3_suspend; +- phy->phy.type = USB_PHY_TYPE_USB3; +- +- phy->is_suspended = 1; +- phy->wkupclk = devm_clk_get(phy->dev, "usb_phy_cm_clk32k"); +- if (IS_ERR(phy->wkupclk)) { +- dev_err(&pdev->dev, "unable to get usb_phy_cm_clk32k\n"); +- return PTR_ERR(phy->wkupclk); +- } +- clk_prepare(phy->wkupclk); +- +- phy->optclk = devm_clk_get(phy->dev, "usb_otg_ss_refclk960m"); +- if (IS_ERR(phy->optclk)) { +- dev_err(&pdev->dev, "unable to get usb_otg_ss_refclk960m\n"); +- return PTR_ERR(phy->optclk); +- } +- clk_prepare(phy->optclk); +- +- phy->sys_clk = devm_clk_get(phy->dev, "sys_clkin"); +- if (IS_ERR(phy->sys_clk)) { +- pr_err("%s: unable to get sys_clkin\n", __func__); +- return -EINVAL; +- } +- +- phy->control_dev = omap_get_control_dev(); +- if (IS_ERR(phy->control_dev)) { +- dev_dbg(&pdev->dev, "Failed to get control device\n"); +- return -ENODEV; +- } +- +- omap_control_usb3_phy_power(phy->control_dev, 0); +- usb_add_phy_dev(&phy->phy); +- +- platform_set_drvdata(pdev, phy); +- +- pm_runtime_enable(phy->dev); +- pm_runtime_get(&pdev->dev); +- +- return 0; +-} +- +-static int omap_usb3_remove(struct platform_device *pdev) +-{ +- struct omap_usb *phy = platform_get_drvdata(pdev); +- +- clk_unprepare(phy->wkupclk); +- clk_unprepare(phy->optclk); +- usb_remove_phy(&phy->phy); +- if (!pm_runtime_suspended(&pdev->dev)) +- pm_runtime_put(&pdev->dev); +- pm_runtime_disable(&pdev->dev); +- +- return 0; +-} +- +-#ifdef CONFIG_PM_RUNTIME +- +-static int omap_usb3_runtime_suspend(struct device *dev) +-{ +- struct platform_device *pdev = to_platform_device(dev); +- struct omap_usb *phy = platform_get_drvdata(pdev); +- +- clk_disable(phy->wkupclk); +- clk_disable(phy->optclk); +- +- return 0; +-} +- +-static int omap_usb3_runtime_resume(struct device *dev) +-{ +- u32 ret = 0; +- struct platform_device *pdev = to_platform_device(dev); +- struct omap_usb *phy = platform_get_drvdata(pdev); +- +- ret = clk_enable(phy->optclk); +- if (ret) { +- dev_err(phy->dev, "Failed to enable optclk %d\n", ret); +- goto err1; +- } +- +- ret = clk_enable(phy->wkupclk); +- if (ret) { +- dev_err(phy->dev, "Failed to enable wkupclk %d\n", ret); +- goto err2; +- } +- +- return 0; +- +-err2: +- clk_disable(phy->optclk); +- +-err1: +- return ret; +-} +- +-static const struct dev_pm_ops omap_usb3_pm_ops = { +- SET_RUNTIME_PM_OPS(omap_usb3_runtime_suspend, omap_usb3_runtime_resume, +- NULL) +-}; +- +-#define DEV_PM_OPS (&omap_usb3_pm_ops) +-#else +-#define DEV_PM_OPS NULL +-#endif +- +-#ifdef CONFIG_OF +-static const struct of_device_id omap_usb3_id_table[] = { +- { .compatible = "ti,omap-usb3" }, +- {} +-}; +-MODULE_DEVICE_TABLE(of, omap_usb3_id_table); +-#endif +- +-static struct platform_driver omap_usb3_driver = { +- .probe = omap_usb3_probe, +- .remove = omap_usb3_remove, +- .driver = { +- .name = "omap-usb3", +- .owner = THIS_MODULE, +- .pm = DEV_PM_OPS, +- .of_match_table = of_match_ptr(omap_usb3_id_table), +- }, +-}; +- +-module_platform_driver(omap_usb3_driver); +- +-MODULE_ALIAS("platform: omap_usb3"); +-MODULE_AUTHOR("Texas Instruments Inc."); +-MODULE_DESCRIPTION("OMAP USB3 phy driver"); +-MODULE_LICENSE("GPL v2"); +--- /dev/null ++++ b/drivers/usb/phy/phy-rcar-gen2-usb.c +@@ -0,0 +1,248 @@ ++/* ++ * Renesas R-Car Gen2 USB phy driver ++ * ++ * Copyright (C) 2013 Renesas Solutions Corp. ++ * Copyright (C) 2013 Cogent Embedded, 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/clk.h> ++#include <linux/delay.h> ++#include <linux/io.h> ++#include <linux/module.h> ++#include <linux/platform_data/usb-rcar-gen2-phy.h> ++#include <linux/platform_device.h> ++#include <linux/spinlock.h> ++#include <linux/usb/otg.h> ++ ++struct rcar_gen2_usb_phy_priv { ++ struct usb_phy phy; ++ void __iomem *base; ++ struct clk *clk; ++ spinlock_t lock; ++ int usecount; ++ u32 ugctrl2; ++}; ++ ++#define usb_phy_to_priv(p) container_of(p, struct rcar_gen2_usb_phy_priv, phy) ++ ++/* Low Power Status register */ ++#define USBHS_LPSTS_REG 0x02 ++#define USBHS_LPSTS_SUSPM (1 << 14) ++ ++/* USB General control register */ ++#define USBHS_UGCTRL_REG 0x80 ++#define USBHS_UGCTRL_CONNECT (1 << 2) ++#define USBHS_UGCTRL_PLLRESET (1 << 0) ++ ++/* USB General control register 2 */ ++#define USBHS_UGCTRL2_REG 0x84 ++#define USBHS_UGCTRL2_USB0_PCI (1 << 4) ++#define USBHS_UGCTRL2_USB0_HS (3 << 4) ++#define USBHS_UGCTRL2_USB2_PCI (0 << 31) ++#define USBHS_UGCTRL2_USB2_SS (1 << 31) ++ ++/* USB General status register */ ++#define USBHS_UGSTS_REG 0x88 ++#define USBHS_UGSTS_LOCK (3 << 8) ++ ++/* Enable USBHS internal phy */ ++static int __rcar_gen2_usbhs_phy_enable(void __iomem *base) ++{ ++ u32 val; ++ int i; ++ ++ /* USBHS PHY power on */ ++ val = ioread32(base + USBHS_UGCTRL_REG); ++ val &= ~USBHS_UGCTRL_PLLRESET; ++ iowrite32(val, base + USBHS_UGCTRL_REG); ++ ++ val = ioread16(base + USBHS_LPSTS_REG); ++ val |= USBHS_LPSTS_SUSPM; ++ iowrite16(val, base + USBHS_LPSTS_REG); ++ ++ for (i = 0; i < 20; i++) { ++ val = ioread32(base + USBHS_UGSTS_REG); ++ if ((val & USBHS_UGSTS_LOCK) == USBHS_UGSTS_LOCK) { ++ val = ioread32(base + USBHS_UGCTRL_REG); ++ val |= USBHS_UGCTRL_CONNECT; ++ iowrite32(val, base + USBHS_UGCTRL_REG); ++ return 0; ++ } ++ udelay(1); ++ } ++ ++ /* Timed out waiting for the PLL lock */ ++ return -ETIMEDOUT; ++} ++ ++/* Disable USBHS internal phy */ ++static int __rcar_gen2_usbhs_phy_disable(void __iomem *base) ++{ ++ u32 val; ++ ++ /* USBHS PHY power off */ ++ val = ioread32(base + USBHS_UGCTRL_REG); ++ val &= ~USBHS_UGCTRL_CONNECT; ++ iowrite32(val, base + USBHS_UGCTRL_REG); ++ ++ val = ioread16(base + USBHS_LPSTS_REG); ++ val &= ~USBHS_LPSTS_SUSPM; ++ iowrite16(val, base + USBHS_LPSTS_REG); ++ ++ val = ioread32(base + USBHS_UGCTRL_REG); ++ val |= USBHS_UGCTRL_PLLRESET; ++ iowrite32(val, base + USBHS_UGCTRL_REG); ++ return 0; ++} ++ ++/* Setup USB channels */ ++static void __rcar_gen2_usb_phy_init(struct rcar_gen2_usb_phy_priv *priv) ++{ ++ u32 val; ++ ++ clk_prepare_enable(priv->clk); ++ ++ /* Set USB channels in the USBHS UGCTRL2 register */ ++ val = ioread32(priv->base); ++ val &= ~(USBHS_UGCTRL2_USB0_HS | USBHS_UGCTRL2_USB2_SS); ++ val |= priv->ugctrl2; ++ iowrite32(val, priv->base); ++} ++ ++/* Shutdown USB channels */ ++static void __rcar_gen2_usb_phy_shutdown(struct rcar_gen2_usb_phy_priv *priv) ++{ ++ __rcar_gen2_usbhs_phy_disable(priv->base); ++ clk_disable_unprepare(priv->clk); ++} ++ ++static int rcar_gen2_usb_phy_set_suspend(struct usb_phy *phy, int suspend) ++{ ++ struct rcar_gen2_usb_phy_priv *priv = usb_phy_to_priv(phy); ++ unsigned long flags; ++ int retval; ++ ++ spin_lock_irqsave(&priv->lock, flags); ++ retval = suspend ? __rcar_gen2_usbhs_phy_disable(priv->base) : ++ __rcar_gen2_usbhs_phy_enable(priv->base); ++ spin_unlock_irqrestore(&priv->lock, flags); ++ return retval; ++} ++ ++static int rcar_gen2_usb_phy_init(struct usb_phy *phy) ++{ ++ struct rcar_gen2_usb_phy_priv *priv = usb_phy_to_priv(phy); ++ unsigned long flags; ++ ++ spin_lock_irqsave(&priv->lock, flags); ++ /* ++ * Enable the clock and setup USB channels ++ * if it's the first user ++ */ ++ if (!priv->usecount++) ++ __rcar_gen2_usb_phy_init(priv); ++ spin_unlock_irqrestore(&priv->lock, flags); ++ return 0; ++} ++ ++static void rcar_gen2_usb_phy_shutdown(struct usb_phy *phy) ++{ ++ struct rcar_gen2_usb_phy_priv *priv = usb_phy_to_priv(phy); ++ unsigned long flags; ++ ++ spin_lock_irqsave(&priv->lock, flags); ++ if (!priv->usecount) { ++ dev_warn(phy->dev, "Trying to disable phy with 0 usecount\n"); ++ goto out; ++ } ++ ++ /* Disable everything if it's the last user */ ++ if (!--priv->usecount) ++ __rcar_gen2_usb_phy_shutdown(priv); ++out: ++ spin_unlock_irqrestore(&priv->lock, flags); ++} ++ ++static int rcar_gen2_usb_phy_probe(struct platform_device *pdev) ++{ ++ struct device *dev = &pdev->dev; ++ struct rcar_gen2_phy_platform_data *pdata; ++ struct rcar_gen2_usb_phy_priv *priv; ++ struct resource *res; ++ void __iomem *base; ++ struct clk *clk; ++ int retval; ++ ++ pdata = dev_get_platdata(&pdev->dev); ++ if (!pdata) { ++ dev_err(dev, "No platform data\n"); ++ return -EINVAL; ++ } ++ ++ clk = devm_clk_get(&pdev->dev, "usbhs"); ++ if (IS_ERR(clk)) { ++ dev_err(&pdev->dev, "Can't get the clock\n"); ++ return PTR_ERR(clk); ++ } ++ ++ res = platform_get_resource(pdev, IORESOURCE_MEM, 0); ++ base = devm_ioremap_resource(dev, res); ++ if (IS_ERR(base)) ++ return PTR_ERR(base); ++ ++ priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL); ++ if (!priv) { ++ dev_err(dev, "Memory allocation failed\n"); ++ return -ENOMEM; ++ } ++ ++ spin_lock_init(&priv->lock); ++ priv->clk = clk; ++ priv->base = base; ++ priv->ugctrl2 = pdata->chan0_pci ? ++ USBHS_UGCTRL2_USB0_PCI : USBHS_UGCTRL2_USB0_HS; ++ priv->ugctrl2 |= pdata->chan2_pci ? ++ USBHS_UGCTRL2_USB2_PCI : USBHS_UGCTRL2_USB2_SS; ++ priv->phy.dev = dev; ++ priv->phy.label = dev_name(dev); ++ priv->phy.init = rcar_gen2_usb_phy_init; ++ priv->phy.shutdown = rcar_gen2_usb_phy_shutdown; ++ priv->phy.set_suspend = rcar_gen2_usb_phy_set_suspend; ++ ++ retval = usb_add_phy(&priv->phy, USB_PHY_TYPE_USB2); ++ if (retval < 0) { ++ dev_err(dev, "Failed to add USB phy\n"); ++ return retval; ++ } ++ ++ platform_set_drvdata(pdev, priv); ++ ++ return retval; ++} ++ ++static int rcar_gen2_usb_phy_remove(struct platform_device *pdev) ++{ ++ struct rcar_gen2_usb_phy_priv *priv = platform_get_drvdata(pdev); ++ ++ usb_remove_phy(&priv->phy); ++ ++ return 0; ++} ++ ++static struct platform_driver rcar_gen2_usb_phy_driver = { ++ .driver = { ++ .name = "usb_phy_rcar_gen2", ++ }, ++ .probe = rcar_gen2_usb_phy_probe, ++ .remove = rcar_gen2_usb_phy_remove, ++}; ++ ++module_platform_driver(rcar_gen2_usb_phy_driver); ++ ++MODULE_LICENSE("GPL v2"); ++MODULE_DESCRIPTION("Renesas R-Car Gen2 USB phy"); ++MODULE_AUTHOR("Valentine Barshak <valentine.barshak@cogentembedded.com>"); +--- a/drivers/usb/phy/phy-tegra-usb.c ++++ b/drivers/usb/phy/phy-tegra-usb.c +@@ -1090,7 +1090,7 @@ static struct platform_driver tegra_usb_ + .driver = { + .name = "tegra-phy", + .owner = THIS_MODULE, +- .of_match_table = of_match_ptr(tegra_usb_phy_id_table), ++ .of_match_table = tegra_usb_phy_id_table, + }, + }; + module_platform_driver(tegra_usb_phy_driver); +--- a/drivers/usb/phy/phy-twl4030-usb.c ++++ /dev/null +@@ -1,794 +0,0 @@ +-/* +- * twl4030_usb - TWL4030 USB transceiver, talking to OMAP OTG controller +- * +- * Copyright (C) 2004-2007 Texas Instruments +- * Copyright (C) 2008 Nokia Corporation +- * Contact: Felipe Balbi <felipe.balbi@nokia.com> +- * +- * This program is free software; you can redistribute it and/or modify +- * it under the terms of the GNU General Public License as published by +- * the Free Software Foundation; either version 2 of the License, or +- * (at your option) any later version. +- * +- * This program is distributed in the hope that it will be useful, +- * but WITHOUT ANY WARRANTY; without even the implied warranty of +- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +- * GNU General Public License for more details. +- * +- * You should have received a copy of the GNU General Public License +- * along with this program; if not, write to the Free Software +- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +- * +- * Current status: +- * - HS USB ULPI mode works. +- * - 3-pin mode support may be added in future. +- */ +- +-#include <linux/module.h> +-#include <linux/init.h> +-#include <linux/interrupt.h> +-#include <linux/platform_device.h> +-#include <linux/spinlock.h> +-#include <linux/workqueue.h> +-#include <linux/io.h> +-#include <linux/delay.h> +-#include <linux/usb/otg.h> +-#include <linux/usb/musb-omap.h> +-#include <linux/usb/ulpi.h> +-#include <linux/i2c/twl.h> +-#include <linux/regulator/consumer.h> +-#include <linux/err.h> +-#include <linux/slab.h> +- +-/* Register defines */ +- +-#define MCPC_CTRL 0x30 +-#define MCPC_CTRL_RTSOL (1 << 7) +-#define MCPC_CTRL_EXTSWR (1 << 6) +-#define MCPC_CTRL_EXTSWC (1 << 5) +-#define MCPC_CTRL_VOICESW (1 << 4) +-#define MCPC_CTRL_OUT64K (1 << 3) +-#define MCPC_CTRL_RTSCTSSW (1 << 2) +-#define MCPC_CTRL_HS_UART (1 << 0) +- +-#define MCPC_IO_CTRL 0x33 +-#define MCPC_IO_CTRL_MICBIASEN (1 << 5) +-#define MCPC_IO_CTRL_CTS_NPU (1 << 4) +-#define MCPC_IO_CTRL_RXD_PU (1 << 3) +-#define MCPC_IO_CTRL_TXDTYP (1 << 2) +-#define MCPC_IO_CTRL_CTSTYP (1 << 1) +-#define MCPC_IO_CTRL_RTSTYP (1 << 0) +- +-#define MCPC_CTRL2 0x36 +-#define MCPC_CTRL2_MCPC_CK_EN (1 << 0) +- +-#define OTHER_FUNC_CTRL 0x80 +-#define OTHER_FUNC_CTRL_BDIS_ACON_EN (1 << 4) +-#define OTHER_FUNC_CTRL_FIVEWIRE_MODE (1 << 2) +- +-#define OTHER_IFC_CTRL 0x83 +-#define OTHER_IFC_CTRL_OE_INT_EN (1 << 6) +-#define OTHER_IFC_CTRL_CEA2011_MODE (1 << 5) +-#define OTHER_IFC_CTRL_FSLSSERIALMODE_4PIN (1 << 4) +-#define OTHER_IFC_CTRL_HIZ_ULPI_60MHZ_OUT (1 << 3) +-#define OTHER_IFC_CTRL_HIZ_ULPI (1 << 2) +-#define OTHER_IFC_CTRL_ALT_INT_REROUTE (1 << 0) +- +-#define OTHER_INT_EN_RISE 0x86 +-#define OTHER_INT_EN_FALL 0x89 +-#define OTHER_INT_STS 0x8C +-#define OTHER_INT_LATCH 0x8D +-#define OTHER_INT_VB_SESS_VLD (1 << 7) +-#define OTHER_INT_DM_HI (1 << 6) /* not valid for "latch" reg */ +-#define OTHER_INT_DP_HI (1 << 5) /* not valid for "latch" reg */ +-#define OTHER_INT_BDIS_ACON (1 << 3) /* not valid for "fall" regs */ +-#define OTHER_INT_MANU (1 << 1) +-#define OTHER_INT_ABNORMAL_STRESS (1 << 0) +- +-#define ID_STATUS 0x96 +-#define ID_RES_FLOAT (1 << 4) +-#define ID_RES_440K (1 << 3) +-#define ID_RES_200K (1 << 2) +-#define ID_RES_102K (1 << 1) +-#define ID_RES_GND (1 << 0) +- +-#define POWER_CTRL 0xAC +-#define POWER_CTRL_OTG_ENAB (1 << 5) +- +-#define OTHER_IFC_CTRL2 0xAF +-#define OTHER_IFC_CTRL2_ULPI_STP_LOW (1 << 4) +-#define OTHER_IFC_CTRL2_ULPI_TXEN_POL (1 << 3) +-#define OTHER_IFC_CTRL2_ULPI_4PIN_2430 (1 << 2) +-#define OTHER_IFC_CTRL2_USB_INT_OUTSEL_MASK (3 << 0) /* bits 0 and 1 */ +-#define OTHER_IFC_CTRL2_USB_INT_OUTSEL_INT1N (0 << 0) +-#define OTHER_IFC_CTRL2_USB_INT_OUTSEL_INT2N (1 << 0) +- +-#define REG_CTRL_EN 0xB2 +-#define REG_CTRL_ERROR 0xB5 +-#define ULPI_I2C_CONFLICT_INTEN (1 << 0) +- +-#define OTHER_FUNC_CTRL2 0xB8 +-#define OTHER_FUNC_CTRL2_VBAT_TIMER_EN (1 << 0) +- +-/* following registers do not have separate _clr and _set registers */ +-#define VBUS_DEBOUNCE 0xC0 +-#define ID_DEBOUNCE 0xC1 +-#define VBAT_TIMER 0xD3 +-#define PHY_PWR_CTRL 0xFD +-#define PHY_PWR_PHYPWD (1 << 0) +-#define PHY_CLK_CTRL 0xFE +-#define PHY_CLK_CTRL_CLOCKGATING_EN (1 << 2) +-#define PHY_CLK_CTRL_CLK32K_EN (1 << 1) +-#define REQ_PHY_DPLL_CLK (1 << 0) +-#define PHY_CLK_CTRL_STS 0xFF +-#define PHY_DPLL_CLK (1 << 0) +- +-/* In module TWL_MODULE_PM_MASTER */ +-#define STS_HW_CONDITIONS 0x0F +- +-/* In module TWL_MODULE_PM_RECEIVER */ +-#define VUSB_DEDICATED1 0x7D +-#define VUSB_DEDICATED2 0x7E +-#define VUSB1V5_DEV_GRP 0x71 +-#define VUSB1V5_TYPE 0x72 +-#define VUSB1V5_REMAP 0x73 +-#define VUSB1V8_DEV_GRP 0x74 +-#define VUSB1V8_TYPE 0x75 +-#define VUSB1V8_REMAP 0x76 +-#define VUSB3V1_DEV_GRP 0x77 +-#define VUSB3V1_TYPE 0x78 +-#define VUSB3V1_REMAP 0x79 +- +-/* In module TWL4030_MODULE_INTBR */ +-#define PMBR1 0x0D +-#define GPIO_USB_4PIN_ULPI_2430C (3 << 0) +- +-struct twl4030_usb { +- struct usb_phy phy; +- struct device *dev; +- +- /* TWL4030 internal USB regulator supplies */ +- struct regulator *usb1v5; +- struct regulator *usb1v8; +- struct regulator *usb3v1; +- +- /* for vbus reporting with irqs disabled */ +- spinlock_t lock; +- +- /* pin configuration */ +- enum twl4030_usb_mode usb_mode; +- +- int irq; +- enum omap_musb_vbus_id_status linkstat; +- bool vbus_supplied; +- u8 asleep; +- bool irq_enabled; +- +- struct delayed_work id_workaround_work; +-}; +- +-/* internal define on top of container_of */ +-#define phy_to_twl(x) container_of((x), struct twl4030_usb, phy) +- +-/*-------------------------------------------------------------------------*/ +- +-static int twl4030_i2c_write_u8_verify(struct twl4030_usb *twl, +- u8 module, u8 data, u8 address) +-{ +- u8 check; +- +- if ((twl_i2c_write_u8(module, data, address) >= 0) && +- (twl_i2c_read_u8(module, &check, address) >= 0) && +- (check == data)) +- return 0; +- dev_dbg(twl->dev, "Write%d[%d,0x%x] wrote %02x but read %02x\n", +- 1, module, address, check, data); +- +- /* Failed once: Try again */ +- if ((twl_i2c_write_u8(module, data, address) >= 0) && +- (twl_i2c_read_u8(module, &check, address) >= 0) && +- (check == data)) +- return 0; +- dev_dbg(twl->dev, "Write%d[%d,0x%x] wrote %02x but read %02x\n", +- 2, module, address, check, data); +- +- /* Failed again: Return error */ +- return -EBUSY; +-} +- +-#define twl4030_usb_write_verify(twl, address, data) \ +- twl4030_i2c_write_u8_verify(twl, TWL_MODULE_USB, (data), (address)) +- +-static inline int twl4030_usb_write(struct twl4030_usb *twl, +- u8 address, u8 data) +-{ +- int ret = 0; +- +- ret = twl_i2c_write_u8(TWL_MODULE_USB, data, address); +- if (ret < 0) +- dev_dbg(twl->dev, +- "TWL4030:USB:Write[0x%x] Error %d\n", address, ret); +- return ret; +-} +- +-static inline int twl4030_readb(struct twl4030_usb *twl, u8 module, u8 address) +-{ +- u8 data; +- int ret = 0; +- +- ret = twl_i2c_read_u8(module, &data, address); +- if (ret >= 0) +- ret = data; +- else +- dev_dbg(twl->dev, +- "TWL4030:readb[0x%x,0x%x] Error %d\n", +- module, address, ret); +- +- return ret; +-} +- +-static inline int twl4030_usb_read(struct twl4030_usb *twl, u8 address) +-{ +- return twl4030_readb(twl, TWL_MODULE_USB, address); +-} +- +-/*-------------------------------------------------------------------------*/ +- +-static inline int +-twl4030_usb_set_bits(struct twl4030_usb *twl, u8 reg, u8 bits) +-{ +- return twl4030_usb_write(twl, ULPI_SET(reg), bits); +-} +- +-static inline int +-twl4030_usb_clear_bits(struct twl4030_usb *twl, u8 reg, u8 bits) +-{ +- return twl4030_usb_write(twl, ULPI_CLR(reg), bits); +-} +- +-/*-------------------------------------------------------------------------*/ +- +-static bool twl4030_is_driving_vbus(struct twl4030_usb *twl) +-{ +- int ret; +- +- ret = twl4030_usb_read(twl, PHY_CLK_CTRL_STS); +- if (ret < 0 || !(ret & PHY_DPLL_CLK)) +- /* +- * if clocks are off, registers are not updated, +- * but we can assume we don't drive VBUS in this case +- */ +- return false; +- +- ret = twl4030_usb_read(twl, ULPI_OTG_CTRL); +- if (ret < 0) +- return false; +- +- return (ret & (ULPI_OTG_DRVVBUS | ULPI_OTG_CHRGVBUS)) ? true : false; +-} +- +-static enum omap_musb_vbus_id_status +- twl4030_usb_linkstat(struct twl4030_usb *twl) +-{ +- int status; +- enum omap_musb_vbus_id_status linkstat = OMAP_MUSB_UNKNOWN; +- +- twl->vbus_supplied = false; +- +- /* +- * For ID/VBUS sensing, see manual section 15.4.8 ... +- * except when using only battery backup power, two +- * comparators produce VBUS_PRES and ID_PRES signals, +- * which don't match docs elsewhere. But ... BIT(7) +- * and BIT(2) of STS_HW_CONDITIONS, respectively, do +- * seem to match up. If either is true the USB_PRES +- * signal is active, the OTG module is activated, and +- * its interrupt may be raised (may wake the system). +- */ +- status = twl4030_readb(twl, TWL_MODULE_PM_MASTER, STS_HW_CONDITIONS); +- if (status < 0) +- dev_err(twl->dev, "USB link status err %d\n", status); +- else if (status & (BIT(7) | BIT(2))) { +- if (status & BIT(7)) { +- if (twl4030_is_driving_vbus(twl)) +- status &= ~BIT(7); +- else +- twl->vbus_supplied = true; +- } +- +- if (status & BIT(2)) +- linkstat = OMAP_MUSB_ID_GROUND; +- else if (status & BIT(7)) +- linkstat = OMAP_MUSB_VBUS_VALID; +- else +- linkstat = OMAP_MUSB_VBUS_OFF; +- } else { +- if (twl->linkstat != OMAP_MUSB_UNKNOWN) +- linkstat = OMAP_MUSB_VBUS_OFF; +- } +- +- dev_dbg(twl->dev, "HW_CONDITIONS 0x%02x/%d; link %d\n", +- status, status, linkstat); +- +- /* REVISIT this assumes host and peripheral controllers +- * are registered, and that both are active... +- */ +- +- return linkstat; +-} +- +-static void twl4030_usb_set_mode(struct twl4030_usb *twl, int mode) +-{ +- twl->usb_mode = mode; +- +- switch (mode) { +- case T2_USB_MODE_ULPI: +- twl4030_usb_clear_bits(twl, ULPI_IFC_CTRL, +- ULPI_IFC_CTRL_CARKITMODE); +- twl4030_usb_set_bits(twl, POWER_CTRL, POWER_CTRL_OTG_ENAB); +- twl4030_usb_clear_bits(twl, ULPI_FUNC_CTRL, +- ULPI_FUNC_CTRL_XCVRSEL_MASK | +- ULPI_FUNC_CTRL_OPMODE_MASK); +- break; +- case -1: +- /* FIXME: power on defaults */ +- break; +- default: +- dev_err(twl->dev, "unsupported T2 transceiver mode %d\n", +- mode); +- break; +- }; +-} +- +-static void twl4030_i2c_access(struct twl4030_usb *twl, int on) +-{ +- unsigned long timeout; +- int val = twl4030_usb_read(twl, PHY_CLK_CTRL); +- +- if (val >= 0) { +- if (on) { +- /* enable DPLL to access PHY registers over I2C */ +- val |= REQ_PHY_DPLL_CLK; +- WARN_ON(twl4030_usb_write_verify(twl, PHY_CLK_CTRL, +- (u8)val) < 0); +- +- timeout = jiffies + HZ; +- while (!(twl4030_usb_read(twl, PHY_CLK_CTRL_STS) & +- PHY_DPLL_CLK) +- && time_before(jiffies, timeout)) +- udelay(10); +- if (!(twl4030_usb_read(twl, PHY_CLK_CTRL_STS) & +- PHY_DPLL_CLK)) +- dev_err(twl->dev, "Timeout setting T2 HSUSB " +- "PHY DPLL clock\n"); +- } else { +- /* let ULPI control the DPLL clock */ +- val &= ~REQ_PHY_DPLL_CLK; +- WARN_ON(twl4030_usb_write_verify(twl, PHY_CLK_CTRL, +- (u8)val) < 0); +- } +- } +-} +- +-static void __twl4030_phy_power(struct twl4030_usb *twl, int on) +-{ +- u8 pwr = twl4030_usb_read(twl, PHY_PWR_CTRL); +- +- if (on) +- pwr &= ~PHY_PWR_PHYPWD; +- else +- pwr |= PHY_PWR_PHYPWD; +- +- WARN_ON(twl4030_usb_write_verify(twl, PHY_PWR_CTRL, pwr) < 0); +-} +- +-static void twl4030_phy_power(struct twl4030_usb *twl, int on) +-{ +- int ret; +- +- if (on) { +- ret = regulator_enable(twl->usb3v1); +- if (ret) +- dev_err(twl->dev, "Failed to enable usb3v1\n"); +- +- ret = regulator_enable(twl->usb1v8); +- if (ret) +- dev_err(twl->dev, "Failed to enable usb1v8\n"); +- +- /* +- * Disabling usb3v1 regulator (= writing 0 to VUSB3V1_DEV_GRP +- * in twl4030) resets the VUSB_DEDICATED2 register. This reset +- * enables VUSB3V1_SLEEP bit that remaps usb3v1 ACTIVE state to +- * SLEEP. We work around this by clearing the bit after usv3v1 +- * is re-activated. This ensures that VUSB3V1 is really active. +- */ +- twl_i2c_write_u8(TWL_MODULE_PM_RECEIVER, 0, VUSB_DEDICATED2); +- +- ret = regulator_enable(twl->usb1v5); +- if (ret) +- dev_err(twl->dev, "Failed to enable usb1v5\n"); +- +- __twl4030_phy_power(twl, 1); +- twl4030_usb_write(twl, PHY_CLK_CTRL, +- twl4030_usb_read(twl, PHY_CLK_CTRL) | +- (PHY_CLK_CTRL_CLOCKGATING_EN | +- PHY_CLK_CTRL_CLK32K_EN)); +- } else { +- __twl4030_phy_power(twl, 0); +- regulator_disable(twl->usb1v5); +- regulator_disable(twl->usb1v8); +- regulator_disable(twl->usb3v1); +- } +-} +- +-static void twl4030_phy_suspend(struct twl4030_usb *twl, int controller_off) +-{ +- if (twl->asleep) +- return; +- +- twl4030_phy_power(twl, 0); +- twl->asleep = 1; +- dev_dbg(twl->dev, "%s\n", __func__); +-} +- +-static void __twl4030_phy_resume(struct twl4030_usb *twl) +-{ +- twl4030_phy_power(twl, 1); +- twl4030_i2c_access(twl, 1); +- twl4030_usb_set_mode(twl, twl->usb_mode); +- if (twl->usb_mode == T2_USB_MODE_ULPI) +- twl4030_i2c_access(twl, 0); +-} +- +-static void twl4030_phy_resume(struct twl4030_usb *twl) +-{ +- if (!twl->asleep) +- return; +- __twl4030_phy_resume(twl); +- twl->asleep = 0; +- dev_dbg(twl->dev, "%s\n", __func__); +- +- /* +- * XXX When VBUS gets driven after musb goes to A mode, +- * ID_PRES related interrupts no longer arrive, why? +- * Register itself is updated fine though, so we must poll. +- */ +- if (twl->linkstat == OMAP_MUSB_ID_GROUND) { +- cancel_delayed_work(&twl->id_workaround_work); +- schedule_delayed_work(&twl->id_workaround_work, HZ); +- } +-} +- +-static int twl4030_usb_ldo_init(struct twl4030_usb *twl) +-{ +- /* Enable writing to power configuration registers */ +- twl_i2c_write_u8(TWL_MODULE_PM_MASTER, TWL4030_PM_MASTER_KEY_CFG1, +- TWL4030_PM_MASTER_PROTECT_KEY); +- +- twl_i2c_write_u8(TWL_MODULE_PM_MASTER, TWL4030_PM_MASTER_KEY_CFG2, +- TWL4030_PM_MASTER_PROTECT_KEY); +- +- /* Keep VUSB3V1 LDO in sleep state until VBUS/ID change detected*/ +- /*twl_i2c_write_u8(TWL_MODULE_PM_RECEIVER, 0, VUSB_DEDICATED2);*/ +- +- /* input to VUSB3V1 LDO is from VBAT, not VBUS */ +- twl_i2c_write_u8(TWL_MODULE_PM_RECEIVER, 0x14, VUSB_DEDICATED1); +- +- /* Initialize 3.1V regulator */ +- twl_i2c_write_u8(TWL_MODULE_PM_RECEIVER, 0, VUSB3V1_DEV_GRP); +- +- twl->usb3v1 = devm_regulator_get(twl->dev, "usb3v1"); +- if (IS_ERR(twl->usb3v1)) +- return -ENODEV; +- +- twl_i2c_write_u8(TWL_MODULE_PM_RECEIVER, 0, VUSB3V1_TYPE); +- +- /* Initialize 1.5V regulator */ +- twl_i2c_write_u8(TWL_MODULE_PM_RECEIVER, 0, VUSB1V5_DEV_GRP); +- +- twl->usb1v5 = devm_regulator_get(twl->dev, "usb1v5"); +- if (IS_ERR(twl->usb1v5)) +- return -ENODEV; +- +- twl_i2c_write_u8(TWL_MODULE_PM_RECEIVER, 0, VUSB1V5_TYPE); +- +- /* Initialize 1.8V regulator */ +- twl_i2c_write_u8(TWL_MODULE_PM_RECEIVER, 0, VUSB1V8_DEV_GRP); +- +- twl->usb1v8 = devm_regulator_get(twl->dev, "usb1v8"); +- if (IS_ERR(twl->usb1v8)) +- return -ENODEV; +- +- twl_i2c_write_u8(TWL_MODULE_PM_RECEIVER, 0, VUSB1V8_TYPE); +- +- /* disable access to power configuration registers */ +- twl_i2c_write_u8(TWL_MODULE_PM_MASTER, 0, +- TWL4030_PM_MASTER_PROTECT_KEY); +- +- return 0; +-} +- +-static ssize_t twl4030_usb_vbus_show(struct device *dev, +- struct device_attribute *attr, char *buf) +-{ +- struct twl4030_usb *twl = dev_get_drvdata(dev); +- unsigned long flags; +- int ret = -EINVAL; +- +- spin_lock_irqsave(&twl->lock, flags); +- ret = sprintf(buf, "%s\n", +- twl->vbus_supplied ? "on" : "off"); +- spin_unlock_irqrestore(&twl->lock, flags); +- +- return ret; +-} +-static DEVICE_ATTR(vbus, 0444, twl4030_usb_vbus_show, NULL); +- +-static irqreturn_t twl4030_usb_irq(int irq, void *_twl) +-{ +- struct twl4030_usb *twl = _twl; +- enum omap_musb_vbus_id_status status; +- bool status_changed = false; +- +- status = twl4030_usb_linkstat(twl); +- +- spin_lock_irq(&twl->lock); +- if (status >= 0 && status != twl->linkstat) { +- twl->linkstat = status; +- status_changed = true; +- } +- spin_unlock_irq(&twl->lock); +- +- if (status_changed) { +- /* FIXME add a set_power() method so that B-devices can +- * configure the charger appropriately. It's not always +- * correct to consume VBUS power, and how much current to +- * consume is a function of the USB configuration chosen +- * by the host. +- * +- * REVISIT usb_gadget_vbus_connect(...) as needed, ditto +- * its disconnect() sibling, when changing to/from the +- * USB_LINK_VBUS state. musb_hdrc won't care until it +- * starts to handle softconnect right. +- */ +- omap_musb_mailbox(status); +- } +- sysfs_notify(&twl->dev->kobj, NULL, "vbus"); +- +- return IRQ_HANDLED; +-} +- +-static void twl4030_id_workaround_work(struct work_struct *work) +-{ +- struct twl4030_usb *twl = container_of(work, struct twl4030_usb, +- id_workaround_work.work); +- enum omap_musb_vbus_id_status status; +- bool status_changed = false; +- +- status = twl4030_usb_linkstat(twl); +- +- spin_lock_irq(&twl->lock); +- if (status >= 0 && status != twl->linkstat) { +- twl->linkstat = status; +- status_changed = true; +- } +- spin_unlock_irq(&twl->lock); +- +- if (status_changed) { +- dev_dbg(twl->dev, "handle missing status change to %d\n", +- status); +- omap_musb_mailbox(status); +- } +- +- /* don't schedule during sleep - irq works right then */ +- if (status == OMAP_MUSB_ID_GROUND && !twl->asleep) { +- cancel_delayed_work(&twl->id_workaround_work); +- schedule_delayed_work(&twl->id_workaround_work, HZ); +- } +-} +- +-static int twl4030_usb_phy_init(struct usb_phy *phy) +-{ +- struct twl4030_usb *twl = phy_to_twl(phy); +- enum omap_musb_vbus_id_status status; +- +- /* +- * Start in sleep state, we'll get called through set_suspend() +- * callback when musb is runtime resumed and it's time to start. +- */ +- __twl4030_phy_power(twl, 0); +- twl->asleep = 1; +- +- status = twl4030_usb_linkstat(twl); +- twl->linkstat = status; +- +- if (status == OMAP_MUSB_ID_GROUND || status == OMAP_MUSB_VBUS_VALID) +- omap_musb_mailbox(twl->linkstat); +- +- sysfs_notify(&twl->dev->kobj, NULL, "vbus"); +- return 0; +-} +- +-static int twl4030_set_suspend(struct usb_phy *x, int suspend) +-{ +- struct twl4030_usb *twl = phy_to_twl(x); +- +- if (suspend) +- twl4030_phy_suspend(twl, 1); +- else +- twl4030_phy_resume(twl); +- +- return 0; +-} +- +-static int twl4030_set_peripheral(struct usb_otg *otg, +- struct usb_gadget *gadget) +-{ +- if (!otg) +- return -ENODEV; +- +- otg->gadget = gadget; +- if (!gadget) +- otg->phy->state = OTG_STATE_UNDEFINED; +- +- return 0; +-} +- +-static int twl4030_set_host(struct usb_otg *otg, struct usb_bus *host) +-{ +- if (!otg) +- return -ENODEV; +- +- otg->host = host; +- if (!host) +- otg->phy->state = OTG_STATE_UNDEFINED; +- +- return 0; +-} +- +-static int twl4030_usb_probe(struct platform_device *pdev) +-{ +- struct twl4030_usb_data *pdata = dev_get_platdata(&pdev->dev); +- struct twl4030_usb *twl; +- int status, err; +- struct usb_otg *otg; +- struct device_node *np = pdev->dev.of_node; +- +- twl = devm_kzalloc(&pdev->dev, sizeof *twl, GFP_KERNEL); +- if (!twl) +- return -ENOMEM; +- +- if (np) +- of_property_read_u32(np, "usb_mode", +- (enum twl4030_usb_mode *)&twl->usb_mode); +- else if (pdata) +- twl->usb_mode = pdata->usb_mode; +- else { +- dev_err(&pdev->dev, "twl4030 initialized without pdata\n"); +- return -EINVAL; +- } +- +- otg = devm_kzalloc(&pdev->dev, sizeof *otg, GFP_KERNEL); +- if (!otg) +- return -ENOMEM; +- +- twl->dev = &pdev->dev; +- twl->irq = platform_get_irq(pdev, 0); +- twl->vbus_supplied = false; +- twl->asleep = 1; +- twl->linkstat = OMAP_MUSB_UNKNOWN; +- +- twl->phy.dev = twl->dev; +- twl->phy.label = "twl4030"; +- twl->phy.otg = otg; +- twl->phy.type = USB_PHY_TYPE_USB2; +- twl->phy.set_suspend = twl4030_set_suspend; +- twl->phy.init = twl4030_usb_phy_init; +- +- otg->phy = &twl->phy; +- otg->set_host = twl4030_set_host; +- otg->set_peripheral = twl4030_set_peripheral; +- +- /* init spinlock for workqueue */ +- spin_lock_init(&twl->lock); +- +- INIT_DELAYED_WORK(&twl->id_workaround_work, twl4030_id_workaround_work); +- +- err = twl4030_usb_ldo_init(twl); +- if (err) { +- dev_err(&pdev->dev, "ldo init failed\n"); +- return err; +- } +- usb_add_phy_dev(&twl->phy); +- +- platform_set_drvdata(pdev, twl); +- if (device_create_file(&pdev->dev, &dev_attr_vbus)) +- dev_warn(&pdev->dev, "could not create sysfs file\n"); +- +- /* Our job is to use irqs and status from the power module +- * to keep the transceiver disabled when nothing's connected. +- * +- * FIXME we actually shouldn't start enabling it until the +- * USB controller drivers have said they're ready, by calling +- * set_host() and/or set_peripheral() ... OTG_capable boards +- * need both handles, otherwise just one suffices. +- */ +- twl->irq_enabled = true; +- status = devm_request_threaded_irq(twl->dev, twl->irq, NULL, +- twl4030_usb_irq, IRQF_TRIGGER_FALLING | +- IRQF_TRIGGER_RISING | IRQF_ONESHOT, "twl4030_usb", twl); +- if (status < 0) { +- dev_dbg(&pdev->dev, "can't get IRQ %d, err %d\n", +- twl->irq, status); +- return status; +- } +- +- dev_info(&pdev->dev, "Initialized TWL4030 USB module\n"); +- return 0; +-} +- +-static int twl4030_usb_remove(struct platform_device *pdev) +-{ +- struct twl4030_usb *twl = platform_get_drvdata(pdev); +- int val; +- +- cancel_delayed_work(&twl->id_workaround_work); +- device_remove_file(twl->dev, &dev_attr_vbus); +- +- /* set transceiver mode to power on defaults */ +- twl4030_usb_set_mode(twl, -1); +- +- /* autogate 60MHz ULPI clock, +- * clear dpll clock request for i2c access, +- * disable 32KHz +- */ +- val = twl4030_usb_read(twl, PHY_CLK_CTRL); +- if (val >= 0) { +- val |= PHY_CLK_CTRL_CLOCKGATING_EN; +- val &= ~(PHY_CLK_CTRL_CLK32K_EN | REQ_PHY_DPLL_CLK); +- twl4030_usb_write(twl, PHY_CLK_CTRL, (u8)val); +- } +- +- /* disable complete OTG block */ +- twl4030_usb_clear_bits(twl, POWER_CTRL, POWER_CTRL_OTG_ENAB); +- +- if (!twl->asleep) +- twl4030_phy_power(twl, 0); +- +- return 0; +-} +- +-#ifdef CONFIG_OF +-static const struct of_device_id twl4030_usb_id_table[] = { +- { .compatible = "ti,twl4030-usb" }, +- {} +-}; +-MODULE_DEVICE_TABLE(of, twl4030_usb_id_table); +-#endif +- +-static struct platform_driver twl4030_usb_driver = { +- .probe = twl4030_usb_probe, +- .remove = twl4030_usb_remove, +- .driver = { +- .name = "twl4030_usb", +- .owner = THIS_MODULE, +- .of_match_table = of_match_ptr(twl4030_usb_id_table), +- }, +-}; +- +-static int __init twl4030_usb_init(void) +-{ +- return platform_driver_register(&twl4030_usb_driver); +-} +-subsys_initcall(twl4030_usb_init); +- +-static void __exit twl4030_usb_exit(void) +-{ +- platform_driver_unregister(&twl4030_usb_driver); +-} +-module_exit(twl4030_usb_exit); +- +-MODULE_ALIAS("platform:twl4030_usb"); +-MODULE_AUTHOR("Texas Instruments, Inc, Nokia Corporation"); +-MODULE_DESCRIPTION("TWL4030 USB transceiver driver"); +-MODULE_LICENSE("GPL"); +--- a/drivers/usb/phy/phy-twl6030-usb.c ++++ b/drivers/usb/phy/phy-twl6030-usb.c +@@ -26,13 +26,14 @@ + #include <linux/platform_device.h> + #include <linux/io.h> + #include <linux/usb/musb-omap.h> ++#include <linux/phy/omap_usb.h> + #include <linux/usb/phy_companion.h> +-#include <linux/usb/omap_usb.h> + #include <linux/i2c/twl.h> + #include <linux/regulator/consumer.h> + #include <linux/err.h> + #include <linux/slab.h> + #include <linux/delay.h> ++#include <linux/of.h> + + /* usb register definitions */ + #define USB_VENDOR_ID_LSB 0x00 +--- a/drivers/video/da8xx-fb.c ++++ b/drivers/video/da8xx-fb.c +@@ -19,6 +19,9 @@ + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ ++ ++#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt ++ + #include <linux/module.h> + #include <linux/kernel.h> + #include <linux/fb.h> +@@ -36,9 +39,16 @@ + #include <linux/slab.h> + #include <linux/delay.h> + #include <linux/lcm.h> ++#include <video/of_display_timing.h> + #include <video/da8xx-fb.h> ++ ++#ifdef CONFIG_FB_DA8XX_TDA998X ++#include <video/da8xx-tda998x-hdmi.h> ++#endif ++ + #include <asm/div64.h> + ++ + #define DRIVER_NAME "da8xx_lcdc" + + #define LCD_VERSION_1 1 +@@ -141,6 +151,32 @@ static irq_handler_t lcdc_irq_handler; + static wait_queue_head_t frame_done_wq; + static int frame_done_flag; + ++static LIST_HEAD(encoder_modules); ++ ++void da8xx_register_encoder(struct da8xx_encoder *encoder) ++{ ++ INIT_LIST_HEAD(&encoder->list); ++ list_add(&encoder->list, &encoder_modules); ++} ++EXPORT_SYMBOL(da8xx_register_encoder); ++ ++void da8xx_unregister_encoder(struct da8xx_encoder *encoder) ++{ ++ list_del(&encoder->list); ++} ++EXPORT_SYMBOL(da8xx_unregister_encoder); ++ ++ ++struct da8xx_encoder *da8xx_get_encoder_from_phandle(struct device_node *node) ++{ ++ struct da8xx_encoder *entry; ++ list_for_each_entry(entry, &encoder_modules, list) ++ if (entry->node == node) ++ return entry; ++ ++ return 0; ++} ++ + static unsigned int lcdc_read(unsigned int addr) + { + return (unsigned int)__raw_readl(da8xx_fb_reg_base + (addr)); +@@ -161,6 +197,7 @@ struct da8xx_fb_par { + unsigned int dma_start; + unsigned int dma_end; + struct clk *lcdc_clk; ++ struct clk *disp_clk; + int irq; + unsigned int palette_sz; + int blank; +@@ -182,6 +219,7 @@ struct da8xx_fb_par { + u32 pseudo_palette[16]; + struct fb_videomode mode; + struct lcd_ctrl_config cfg; ++ struct device_node *hdmi_node; + }; + + static struct fb_var_screeninfo da8xx_fb_var; +@@ -197,6 +235,9 @@ static struct fb_fix_screeninfo da8xx_fb + .accel = FB_ACCEL_NONE + }; + ++static vsync_callback_t vsync_cb_handler; ++static void *vsync_cb_arg; ++ + static struct fb_videomode known_lcd_panels[] = { + /* Sharp LCD035Q3DG01 */ + [0] = { +@@ -730,8 +771,8 @@ static int da8xx_fb_config_clk_divider(s + } + + static unsigned int da8xx_fb_calc_clk_divider(struct da8xx_fb_par *par, +- unsigned pixclock, +- unsigned *lcdc_clk_rate) ++ unsigned pixclock, ++ unsigned *lcdc_clk_rate) + { + unsigned lcdc_clk_div; + +@@ -765,7 +806,7 @@ static int da8xx_fb_calc_config_clk_divi + } + + static unsigned da8xx_fb_round_clk(struct da8xx_fb_par *par, +- unsigned pixclock) ++ unsigned pixclock) + { + unsigned lcdc_clk_div, lcdc_clk_rate; + +@@ -778,11 +819,53 @@ static int lcd_init(struct da8xx_fb_par + { + u32 bpp; + int ret = 0; ++ struct da8xx_encoder *enc = 0; + +- ret = da8xx_fb_calc_config_clk_divider(par, panel); +- if (IS_ERR_VALUE(ret)) { +- dev_err(par->dev, "unable to configure clock\n"); +- return ret; ++ if (IS_ENABLED(CONFIG_FB_DA8XX_TDA998X) && par->hdmi_node) { ++ unsigned int div = 0; ++ unsigned long pixclock = 0; ++ ++ pr_debug("pixclock from panel %d\n", panel->pixclock); ++ pixclock = PICOS2KHZ(panel->pixclock) * 1000; ++ pr_debug("pixclock converted to hz %ld\n", pixclock); ++ /* remove any rounding errors as this seems to mess up clk */ ++ pixclock = (pixclock/10000)*10000; ++ pr_debug("rounded clock rate %ld\n", ++ clk_round_rate(par->lcdc_clk, pixclock*2)); ++ /* in raster mode, minimum divisor is 2: */ ++ ret = clk_set_rate(par->disp_clk, pixclock * 2); ++ if (IS_ERR_VALUE(ret)) { ++ dev_err(par->dev, "failed to set display clock rate to: %ld\n", ++ pixclock); ++ return ret; ++ } ++ ++ par->lcdc_clk_rate = clk_get_rate(par->lcdc_clk); ++ div = par->lcdc_clk_rate / pixclock; ++ ++ pr_debug("lcd_clk=%u, mode clock=%ld, div=%u\n", ++ par->lcdc_clk_rate, pixclock, div); ++ pr_debug("fck=%lu, dpll_disp_ck=%lu\n", ++ clk_get_rate(par->lcdc_clk), ++ clk_get_rate(par->disp_clk)); ++ ++ /* Configure the LCD clock divisor. */ ++ lcdc_write(LCD_CLK_DIVISOR(div) | ++ (LCD_RASTER_MODE & 0x1), LCD_CTRL_REG); ++ ++ if (lcd_revision == LCD_VERSION_2) ++ lcdc_write(LCD_V2_DMA_CLK_EN | LCD_V2_LIDD_CLK_EN | ++ LCD_V2_CORE_CLK_EN, LCD_CLK_ENABLE_REG); ++ } else { ++ /* ++ * Not using external encoder, using old and more inaccurate ++ * method of setting the clocks. ++ */ ++ ret = da8xx_fb_calc_config_clk_divider(par, panel); ++ if (IS_ERR_VALUE(ret)) { ++ dev_err(par->dev, "unable to configure clock\n"); ++ return ret; ++ } + } + + if (panel->sync & FB_SYNC_CLK_INVERT) +@@ -822,9 +905,45 @@ static int lcd_init(struct da8xx_fb_par + lcdc_write((lcdc_read(LCD_RASTER_CTRL_REG) & 0xfff00fff) | + (cfg->fdd << 12), LCD_RASTER_CTRL_REG); + ++ if (IS_ENABLED(CONFIG_FB_DA8XX_TDA998X) && par->hdmi_node) { ++ /* ++ * keep doing this lookup, because there is a posibility that ++ * somebody went and unloaded the encoder driver from out ++ * beneath us ++ */ ++ enc = da8xx_get_encoder_from_phandle(par->hdmi_node); ++ if (enc) ++ enc->set_mode(enc, panel); ++ } + return 0; + } + ++int register_vsync_cb(vsync_callback_t handler, void *arg, int idx) ++{ ++ if ((vsync_cb_handler == NULL) && (vsync_cb_arg == NULL)) { ++ vsync_cb_arg = arg; ++ vsync_cb_handler = handler; ++ } else { ++ return -EEXIST; ++ } ++ ++ return 0; ++} ++EXPORT_SYMBOL(register_vsync_cb); ++ ++int unregister_vsync_cb(vsync_callback_t handler, void *arg, int idx) ++{ ++ if ((vsync_cb_handler == handler) && (vsync_cb_arg == arg)) { ++ vsync_cb_handler = NULL; ++ vsync_cb_arg = NULL; ++ } else { ++ return -ENXIO; ++ } ++ ++ return 0; ++} ++EXPORT_SYMBOL(unregister_vsync_cb); ++ + /* IRQ handler for version 2 of LCDC */ + static irqreturn_t lcdc_irq_handler_rev02(int irq, void *arg) + { +@@ -862,6 +981,8 @@ static irqreturn_t lcdc_irq_handler_rev0 + LCD_DMA_FRM_BUF_CEILING_ADDR_0_REG); + par->vsync_flag = 1; + wake_up_interruptible(&par->vsync_wait); ++ if (vsync_cb_handler) ++ vsync_cb_handler(vsync_cb_arg); + } + + if (stat & LCD_END_OF_FRAME1) { +@@ -872,6 +993,8 @@ static irqreturn_t lcdc_irq_handler_rev0 + LCD_DMA_FRM_BUF_CEILING_ADDR_1_REG); + par->vsync_flag = 1; + wake_up_interruptible(&par->vsync_wait); ++ if (vsync_cb_handler) ++ vsync_cb_handler(vsync_cb_arg); + } + + /* Set only when controller is disabled and at the end of +@@ -1032,7 +1155,13 @@ static int fb_check_var(struct fb_var_sc + if (var->yres + var->yoffset > var->yres_virtual) + var->yoffset = var->yres_virtual - var->yres; + +- var->pixclock = da8xx_fb_round_clk(par, var->pixclock); ++ /* ++ * if we don't have an encoder attached, use the legacy ++ * clock setting code that works on da8xx but is a bit ++ * inaccurate for the encoders on AM335x ++ */ ++ if (!IS_ENABLED(CONFIG_FB_DA8XX_TDA998X) || (par->hdmi_node == 0)) ++ var->pixclock = da8xx_fb_round_clk(par, var->pixclock); + + return err; + } +@@ -1312,12 +1441,54 @@ static struct fb_ops da8xx_fb_ops = { + .fb_blank = cfb_blank, + }; + ++static struct lcd_ctrl_config *da8xx_fb_create_cfg(struct platform_device *dev) ++{ ++ struct lcd_ctrl_config *cfg; ++ ++ cfg = devm_kzalloc(&dev->dev, sizeof(struct fb_videomode), GFP_KERNEL); ++ if (!cfg) ++ return NULL; ++ ++ /* default values */ ++ ++ if (lcd_revision == LCD_VERSION_1) ++ cfg->bpp = 16; ++ else ++ cfg->bpp = 32; ++ ++ /* ++ * For panels so far used with this LCDC, below statement is sufficient. ++ * For new panels, if required, struct lcd_ctrl_cfg fields to be updated ++ * with additional/modified values. Those values would have to be then ++ * obtained from dt(requiring new dt bindings). ++ */ ++ ++ cfg->panel_shade = COLOR_ACTIVE; ++ ++ return cfg; ++} ++ + static struct fb_videomode *da8xx_fb_get_videomode(struct platform_device *dev) + { + struct da8xx_lcdc_platform_data *fb_pdata = dev->dev.platform_data; + struct fb_videomode *lcdc_info; ++ struct device_node *np = dev->dev.of_node; + int i; + ++ if (np) { ++ lcdc_info = devm_kzalloc(&dev->dev, ++ sizeof(struct fb_videomode), ++ GFP_KERNEL); ++ if (!lcdc_info) ++ return NULL; ++ ++ if (of_get_fb_videomode(np, lcdc_info, OF_USE_NATIVE_MODE)) { ++ dev_err(&dev->dev, "timings not available in DT\n"); ++ return NULL; ++ } ++ return lcdc_info; ++ } ++ + for (i = 0, lcdc_info = known_lcd_panels; + i < ARRAY_SIZE(known_lcd_panels); i++, lcdc_info++) { + if (strcmp(fb_pdata->type, lcdc_info->name) == 0) +@@ -1342,15 +1513,28 @@ static int fb_probe(struct platform_devi + struct fb_videomode *lcdc_info; + struct fb_info *da8xx_fb_info; + struct da8xx_fb_par *par; +- struct clk *tmp_lcdc_clk; ++ struct clk *tmp_lcdc_clk, *tmp_disp_clk; + int ret; + unsigned long ulcm; ++ struct device_node *hdmi_node = NULL; ++ + +- if (fb_pdata == NULL) { ++ if (fb_pdata == NULL && !device->dev.of_node) { + dev_err(&device->dev, "Can not get platform data\n"); + return -ENOENT; + } + ++ if (device->dev.of_node) { ++ hdmi_node = of_parse_phandle(device->dev.of_node, ++ "hdmi", 0); ++ if (hdmi_node && ++ (da8xx_get_encoder_from_phandle(hdmi_node) == 0)) { ++ /* i2c encoder has not initialized yet, defer */ ++ of_node_put(hdmi_node); ++ return -EPROBE_DEFER; ++ } ++ } ++ + lcdc_info = da8xx_fb_get_videomode(device); + if (lcdc_info == NULL) + return -ENODEV; +@@ -1366,6 +1550,12 @@ static int fb_probe(struct platform_devi + return PTR_ERR(tmp_lcdc_clk); + } + ++ tmp_disp_clk = devm_clk_get(&device->dev, "dpll_disp_ck"); ++ if (IS_ERR(tmp_disp_clk)) { ++ /* we can live if dpll_disp_ck is not available */ ++ tmp_disp_clk = 0; ++ } ++ + pm_runtime_enable(&device->dev); + pm_runtime_get_sync(&device->dev); + +@@ -1386,7 +1576,10 @@ static int fb_probe(struct platform_devi + break; + } + +- lcd_cfg = (struct lcd_ctrl_config *)fb_pdata->controller_data; ++ if (device->dev.of_node) ++ lcd_cfg = da8xx_fb_create_cfg(device); ++ else ++ lcd_cfg = fb_pdata->controller_data; + + if (!lcd_cfg) { + ret = -EINVAL; +@@ -1405,11 +1598,16 @@ static int fb_probe(struct platform_devi + par->dev = &device->dev; + par->lcdc_clk = tmp_lcdc_clk; + par->lcdc_clk_rate = clk_get_rate(par->lcdc_clk); +- if (fb_pdata->panel_power_ctrl) { ++ par->disp_clk = tmp_disp_clk; ++ ++ if (fb_pdata && fb_pdata->panel_power_ctrl) { + par->panel_power_ctrl = fb_pdata->panel_power_ctrl; + par->panel_power_ctrl(1); + } + ++ if (device->dev.of_node) ++ par->hdmi_node = hdmi_node; ++ + fb_videomode_to_var(&da8xx_fb_var, lcdc_info); + par->cfg = *lcd_cfg; + +@@ -1653,6 +1851,19 @@ static int fb_resume(struct platform_dev + #define fb_resume NULL + #endif + ++#if IS_ENABLED(CONFIG_OF) ++static const struct of_device_id da8xx_fb_of_match[] = { ++ /* ++ * this driver supports version 1 and version 2 of the ++ * Texas Instruments lcd controller (lcdc) hardware block ++ */ ++ {.compatible = "ti,da8xx-tilcdc", }, ++ {.compatible = "ti,am33xx-tilcdc", }, ++ {}, ++}; ++MODULE_DEVICE_TABLE(of, da8xx_fb_of_match); ++#endif ++ + static struct platform_driver da8xx_fb_driver = { + .probe = fb_probe, + .remove = fb_remove, +@@ -1661,6 +1872,7 @@ static struct platform_driver da8xx_fb_d + .driver = { + .name = DRIVER_NAME, + .owner = THIS_MODULE, ++ .of_match_table = of_match_ptr(da8xx_fb_of_match), + }, + }; + +--- /dev/null ++++ b/drivers/video/da8xx-tda998x-hdmi.c +@@ -0,0 +1,840 @@ ++/* ++ * Copyright (C) 2012 Texas Instruments ++ * Author: Rob Clark <robdclark@gmail.com> ++ * Author: Darren Etheridge <detheridge@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, see <http://www.gnu.org/licenses/>. ++ */ ++ ++ ++#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt ++ ++ ++#include <linux/module.h> ++#include <linux/i2c.h> ++#include <linux/slab.h> ++#include <linux/delay.h> ++#include <video/da8xx-fb.h> ++#include <video/da8xx-tda998x-hdmi.h> ++ ++#define TDA998X_DEBUG ++ ++#ifdef TDA998X_DEBUG ++#define DBG(fmt, ...) printk(KERN_DEBUG "%s: " fmt, __func__, ##__VA_ARGS__) ++#else ++#define DBG(fmt, ...) ++#endif ++ ++ ++#define tda998x_encoder da8xx_encoder ++ ++struct tda998x_priv { ++ struct i2c_client *cec; ++ uint16_t rev; ++ uint8_t current_page; ++ int dpms; ++ bool is_hdmi_sink; ++ u8 vip_cntrl_0; ++ u8 vip_cntrl_1; ++ u8 vip_cntrl_2; ++ struct tda998x_encoder_params params; ++}; ++ ++#define to_tda998x_priv(x) ((struct tda998x_priv *)x->priv) ++#define tda998x_i2c_encoder_get_client(x) ((struct i2c_client *)x->client) ++ ++/* The TDA9988 series of devices use a paged register scheme.. to simplify ++ * things we encode the page # in upper bits of the register #. To read/ ++ * write a given register, we need to make sure CURPAGE register is set ++ * appropriately. Which implies reads/writes are not atomic. Fun! ++ */ ++ ++#define REG(page, addr) (((page) << 8) | (addr)) ++#define REG2ADDR(reg) ((reg) & 0xff) ++#define REG2PAGE(reg) (((reg) >> 8) & 0xff) ++ ++#define REG_CURPAGE 0xff /* write */ ++ ++ ++/* Page 00h: General Control */ ++#define REG_VERSION_LSB REG(0x00, 0x00) /* read */ ++#define REG_MAIN_CNTRL0 REG(0x00, 0x01) /* read/write */ ++# define MAIN_CNTRL0_SR (1 << 0) ++# define MAIN_CNTRL0_DECS (1 << 1) ++# define MAIN_CNTRL0_DEHS (1 << 2) ++# define MAIN_CNTRL0_CECS (1 << 3) ++# define MAIN_CNTRL0_CEHS (1 << 4) ++# define MAIN_CNTRL0_SCALER (1 << 7) ++#define REG_VERSION_MSB REG(0x00, 0x02) /* read */ ++#define REG_SOFTRESET REG(0x00, 0x0a) /* write */ ++# define SOFTRESET_AUDIO (1 << 0) ++# define SOFTRESET_I2C_MASTER (1 << 1) ++#define REG_DDC_DISABLE REG(0x00, 0x0b) /* read/write */ ++#define REG_CCLK_ON REG(0x00, 0x0c) /* read/write */ ++#define REG_I2C_MASTER REG(0x00, 0x0d) /* read/write */ ++# define I2C_MASTER_DIS_MM (1 << 0) ++# define I2C_MASTER_DIS_FILT (1 << 1) ++# define I2C_MASTER_APP_STRT_LAT (1 << 2) ++#define REG_FEAT_POWERDOWN REG(0x00, 0x0e) /* read/write */ ++# define FEAT_POWERDOWN_SPDIF (1 << 3) ++#define REG_INT_FLAGS_0 REG(0x00, 0x0f) /* read/write */ ++#define REG_INT_FLAGS_1 REG(0x00, 0x10) /* read/write */ ++#define REG_INT_FLAGS_2 REG(0x00, 0x11) /* read/write */ ++# define INT_FLAGS_2_EDID_BLK_RD (1 << 1) ++#define REG_ENA_ACLK REG(0x00, 0x16) /* read/write */ ++#define REG_ENA_VP_0 REG(0x00, 0x18) /* read/write */ ++#define REG_ENA_VP_1 REG(0x00, 0x19) /* read/write */ ++#define REG_ENA_VP_2 REG(0x00, 0x1a) /* read/write */ ++#define REG_ENA_AP REG(0x00, 0x1e) /* read/write */ ++#define REG_VIP_CNTRL_0 REG(0x00, 0x20) /* write */ ++# define VIP_CNTRL_0_MIRR_A (1 << 7) ++# define VIP_CNTRL_0_SWAP_A(x) (((x) & 7) << 4) ++# define VIP_CNTRL_0_MIRR_B (1 << 3) ++# define VIP_CNTRL_0_SWAP_B(x) (((x) & 7) << 0) ++#define REG_VIP_CNTRL_1 REG(0x00, 0x21) /* write */ ++# define VIP_CNTRL_1_MIRR_C (1 << 7) ++# define VIP_CNTRL_1_SWAP_C(x) (((x) & 7) << 4) ++# define VIP_CNTRL_1_MIRR_D (1 << 3) ++# define VIP_CNTRL_1_SWAP_D(x) (((x) & 7) << 0) ++#define REG_VIP_CNTRL_2 REG(0x00, 0x22) /* write */ ++# define VIP_CNTRL_2_MIRR_E (1 << 7) ++# define VIP_CNTRL_2_SWAP_E(x) (((x) & 7) << 4) ++# define VIP_CNTRL_2_MIRR_F (1 << 3) ++# define VIP_CNTRL_2_SWAP_F(x) (((x) & 7) << 0) ++#define REG_VIP_CNTRL_3 REG(0x00, 0x23) /* write */ ++# define VIP_CNTRL_3_X_TGL (1 << 0) ++# define VIP_CNTRL_3_H_TGL (1 << 1) ++# define VIP_CNTRL_3_V_TGL (1 << 2) ++# define VIP_CNTRL_3_EMB (1 << 3) ++# define VIP_CNTRL_3_SYNC_DE (1 << 4) ++# define VIP_CNTRL_3_SYNC_HS (1 << 5) ++# define VIP_CNTRL_3_DE_INT (1 << 6) ++# define VIP_CNTRL_3_EDGE (1 << 7) ++#define REG_VIP_CNTRL_4 REG(0x00, 0x24) /* write */ ++# define VIP_CNTRL_4_BLC(x) (((x) & 3) << 0) ++# define VIP_CNTRL_4_BLANKIT(x) (((x) & 3) << 2) ++# define VIP_CNTRL_4_CCIR656 (1 << 4) ++# define VIP_CNTRL_4_656_ALT (1 << 5) ++# define VIP_CNTRL_4_TST_656 (1 << 6) ++# define VIP_CNTRL_4_TST_PAT (1 << 7) ++#define REG_VIP_CNTRL_5 REG(0x00, 0x25) /* write */ ++# define VIP_CNTRL_5_CKCASE (1 << 0) ++# define VIP_CNTRL_5_SP_CNT(x) (((x) & 3) << 1) ++#define REG_MUX_AP REG(0x00, 0x26) /* read/write */ ++#define REG_MUX_VP_VIP_OUT REG(0x00, 0x27) /* read/write */ ++#define REG_MAT_CONTRL REG(0x00, 0x80) /* write */ ++# define MAT_CONTRL_MAT_SC(x) (((x) & 3) << 0) ++# define MAT_CONTRL_MAT_BP (1 << 2) ++#define REG_VIDFORMAT REG(0x00, 0xa0) /* write */ ++#define REG_REFPIX_MSB REG(0x00, 0xa1) /* write */ ++#define REG_REFPIX_LSB REG(0x00, 0xa2) /* write */ ++#define REG_REFLINE_MSB REG(0x00, 0xa3) /* write */ ++#define REG_REFLINE_LSB REG(0x00, 0xa4) /* write */ ++#define REG_NPIX_MSB REG(0x00, 0xa5) /* write */ ++#define REG_NPIX_LSB REG(0x00, 0xa6) /* write */ ++#define REG_NLINE_MSB REG(0x00, 0xa7) /* write */ ++#define REG_NLINE_LSB REG(0x00, 0xa8) /* write */ ++#define REG_VS_LINE_STRT_1_MSB REG(0x00, 0xa9) /* write */ ++#define REG_VS_LINE_STRT_1_LSB REG(0x00, 0xaa) /* write */ ++#define REG_VS_PIX_STRT_1_MSB REG(0x00, 0xab) /* write */ ++#define REG_VS_PIX_STRT_1_LSB REG(0x00, 0xac) /* write */ ++#define REG_VS_LINE_END_1_MSB REG(0x00, 0xad) /* write */ ++#define REG_VS_LINE_END_1_LSB REG(0x00, 0xae) /* write */ ++#define REG_VS_PIX_END_1_MSB REG(0x00, 0xaf) /* write */ ++#define REG_VS_PIX_END_1_LSB REG(0x00, 0xb0) /* write */ ++#define REG_VS_LINE_STRT_2_MSB REG(0x00, 0xb1) /* write */ ++#define REG_VS_LINE_STRT_2_LSB REG(0x00, 0xb2) /* write */ ++#define REG_VS_PIX_STRT_2_MSB REG(0x00, 0xb3) /* write */ ++#define REG_VS_PIX_STRT_2_LSB REG(0x00, 0xb4) /* write */ ++#define REG_VS_LINE_END_2_MSB REG(0x00, 0xb5) /* write */ ++#define REG_VS_LINE_END_2_LSB REG(0x00, 0xb6) /* write */ ++#define REG_VS_PIX_END_2_MSB REG(0x00, 0xb7) /* write */ ++#define REG_VS_PIX_END_2_LSB REG(0x00, 0xb8) /* write */ ++#define REG_HS_PIX_START_MSB REG(0x00, 0xb9) /* write */ ++#define REG_HS_PIX_START_LSB REG(0x00, 0xba) /* write */ ++#define REG_HS_PIX_STOP_MSB REG(0x00, 0xbb) /* write */ ++#define REG_HS_PIX_STOP_LSB REG(0x00, 0xbc) /* write */ ++#define REG_VWIN_START_1_MSB REG(0x00, 0xbd) /* write */ ++#define REG_VWIN_START_1_LSB REG(0x00, 0xbe) /* write */ ++#define REG_VWIN_END_1_MSB REG(0x00, 0xbf) /* write */ ++#define REG_VWIN_END_1_LSB REG(0x00, 0xc0) /* write */ ++#define REG_VWIN_START_2_MSB REG(0x00, 0xc1) /* write */ ++#define REG_VWIN_START_2_LSB REG(0x00, 0xc2) /* write */ ++#define REG_VWIN_END_2_MSB REG(0x00, 0xc3) /* write */ ++#define REG_VWIN_END_2_LSB REG(0x00, 0xc4) /* write */ ++#define REG_DE_START_MSB REG(0x00, 0xc5) /* write */ ++#define REG_DE_START_LSB REG(0x00, 0xc6) /* write */ ++#define REG_DE_STOP_MSB REG(0x00, 0xc7) /* write */ ++#define REG_DE_STOP_LSB REG(0x00, 0xc8) /* write */ ++#define REG_TBG_CNTRL_0 REG(0x00, 0xca) /* write */ ++# define TBG_CNTRL_0_TOP_TGL (1 << 0) ++# define TBG_CNTRL_0_TOP_SEL (1 << 1) ++# define TBG_CNTRL_0_DE_EXT (1 << 2) ++# define TBG_CNTRL_0_TOP_EXT (1 << 3) ++# define TBG_CNTRL_0_FRAME_DIS (1 << 5) ++# define TBG_CNTRL_0_SYNC_MTHD (1 << 6) ++# define TBG_CNTRL_0_SYNC_ONCE (1 << 7) ++#define REG_TBG_CNTRL_1 REG(0x00, 0xcb) /* write */ ++# define TBG_CNTRL_1_H_TGL (1 << 0) ++# define TBG_CNTRL_1_V_TGL (1 << 1) ++# define TBG_CNTRL_1_TGL_EN (1 << 2) ++# define TBG_CNTRL_1_X_EXT (1 << 3) ++# define TBG_CNTRL_1_H_EXT (1 << 4) ++# define TBG_CNTRL_1_V_EXT (1 << 5) ++# define TBG_CNTRL_1_DWIN_DIS (1 << 6) ++#define REG_ENABLE_SPACE REG(0x00, 0xd6) /* write */ ++#define REG_HVF_CNTRL_0 REG(0x00, 0xe4) /* write */ ++# define HVF_CNTRL_0_SM (1 << 7) ++# define HVF_CNTRL_0_RWB (1 << 6) ++# define HVF_CNTRL_0_PREFIL(x) (((x) & 3) << 2) ++# define HVF_CNTRL_0_INTPOL(x) (((x) & 3) << 0) ++#define REG_HVF_CNTRL_1 REG(0x00, 0xe5) /* write */ ++# define HVF_CNTRL_1_FOR (1 << 0) ++# define HVF_CNTRL_1_YUVBLK (1 << 1) ++# define HVF_CNTRL_1_VQR(x) (((x) & 3) << 2) ++# define HVF_CNTRL_1_PAD(x) (((x) & 3) << 4) ++# define HVF_CNTRL_1_SEMI_PLANAR (1 << 6) ++#define REG_RPT_CNTRL REG(0x00, 0xf0) /* write */ ++#define REG_I2S_FORMAT REG(0x00, 0xfc) /* read/write */ ++# define I2S_FORMAT(x) (((x) & 3) << 0) ++#define REG_AIP_CLKSEL REG(0x00, 0xfd) /* write */ ++# define AIP_CLKSEL_FS(x) (((x) & 3) << 0) ++# define AIP_CLKSEL_CLK_POL(x) (((x) & 1) << 2) ++# define AIP_CLKSEL_AIP(x) (((x) & 7) << 3) ++ ++ ++/* Page 02h: PLL settings */ ++#define REG_PLL_SERIAL_1 REG(0x02, 0x00) /* read/write */ ++# define PLL_SERIAL_1_SRL_FDN (1 << 0) ++# define PLL_SERIAL_1_SRL_IZ(x) (((x) & 3) << 1) ++# define PLL_SERIAL_1_SRL_MAN_IZ (1 << 6) ++#define REG_PLL_SERIAL_2 REG(0x02, 0x01) /* read/write */ ++# define PLL_SERIAL_2_SRL_NOSC(x) (((x) & 3) << 0) ++# define PLL_SERIAL_2_SRL_PR(x) (((x) & 0xf) << 4) ++#define REG_PLL_SERIAL_3 REG(0x02, 0x02) /* read/write */ ++# define PLL_SERIAL_3_SRL_CCIR (1 << 0) ++# define PLL_SERIAL_3_SRL_DE (1 << 2) ++# define PLL_SERIAL_3_SRL_PXIN_SEL (1 << 4) ++#define REG_SERIALIZER REG(0x02, 0x03) /* read/write */ ++#define REG_BUFFER_OUT REG(0x02, 0x04) /* read/write */ ++#define REG_PLL_SCG1 REG(0x02, 0x05) /* read/write */ ++#define REG_PLL_SCG2 REG(0x02, 0x06) /* read/write */ ++#define REG_PLL_SCGN1 REG(0x02, 0x07) /* read/write */ ++#define REG_PLL_SCGN2 REG(0x02, 0x08) /* read/write */ ++#define REG_PLL_SCGR1 REG(0x02, 0x09) /* read/write */ ++#define REG_PLL_SCGR2 REG(0x02, 0x0a) /* read/write */ ++#define REG_AUDIO_DIV REG(0x02, 0x0e) /* read/write */ ++#define REG_SEL_CLK REG(0x02, 0x11) /* read/write */ ++# define SEL_CLK_SEL_CLK1 (1 << 0) ++# define SEL_CLK_SEL_VRF_CLK(x) (((x) & 3) << 1) ++# define SEL_CLK_ENA_SC_CLK (1 << 3) ++#define REG_ANA_GENERAL REG(0x02, 0x12) /* read/write */ ++ ++ ++/* Page 09h: EDID Control */ ++#define REG_EDID_DATA_0 REG(0x09, 0x00) /* read */ ++/* next 127 successive registers are the EDID block */ ++#define REG_EDID_CTRL REG(0x09, 0xfa) /* read/write */ ++#define REG_DDC_ADDR REG(0x09, 0xfb) /* read/write */ ++#define REG_DDC_OFFS REG(0x09, 0xfc) /* read/write */ ++#define REG_DDC_SEGM_ADDR REG(0x09, 0xfd) /* read/write */ ++#define REG_DDC_SEGM REG(0x09, 0xfe) /* read/write */ ++ ++ ++/* Page 10h: information frames and packets */ ++#define REG_IF1_HB0 REG(0x10, 0x20) /* read/write */ ++#define REG_IF2_HB0 REG(0x10, 0x40) /* read/write */ ++#define REG_IF3_HB0 REG(0x10, 0x60) /* read/write */ ++#define REG_IF4_HB0 REG(0x10, 0x80) /* read/write */ ++#define REG_IF5_HB0 REG(0x10, 0xa0) /* read/write */ ++ ++ ++/* Page 11h: audio settings and content info packets */ ++#define REG_AIP_CNTRL_0 REG(0x11, 0x00) /* read/write */ ++# define AIP_CNTRL_0_RST_FIFO (1 << 0) ++# define AIP_CNTRL_0_SWAP (1 << 1) ++# define AIP_CNTRL_0_LAYOUT (1 << 2) ++# define AIP_CNTRL_0_ACR_MAN (1 << 5) ++# define AIP_CNTRL_0_RST_CTS (1 << 6) ++#define REG_CA_I2S REG(0x11, 0x01) /* read/write */ ++# define CA_I2S_CA_I2S(x) (((x) & 31) << 0) ++# define CA_I2S_HBR_CHSTAT (1 << 6) ++#define REG_LATENCY_RD REG(0x11, 0x04) /* read/write */ ++#define REG_ACR_CTS_0 REG(0x11, 0x05) /* read/write */ ++#define REG_ACR_CTS_1 REG(0x11, 0x06) /* read/write */ ++#define REG_ACR_CTS_2 REG(0x11, 0x07) /* read/write */ ++#define REG_ACR_N_0 REG(0x11, 0x08) /* read/write */ ++#define REG_ACR_N_1 REG(0x11, 0x09) /* read/write */ ++#define REG_ACR_N_2 REG(0x11, 0x0a) /* read/write */ ++#define REG_CTS_N REG(0x11, 0x0c) /* read/write */ ++# define CTS_N_K(x) (((x) & 7) << 0) ++# define CTS_N_M(x) (((x) & 3) << 4) ++#define REG_ENC_CNTRL REG(0x11, 0x0d) /* read/write */ ++# define ENC_CNTRL_RST_ENC (1 << 0) ++# define ENC_CNTRL_RST_SEL (1 << 1) ++# define ENC_CNTRL_CTL_CODE(x) (((x) & 3) << 2) ++#define REG_DIP_FLAGS REG(0x11, 0x0e) /* read/write */ ++# define DIP_FLAGS_ACR (1 << 0) ++# define DIP_FLAGS_GC (1 << 1) ++#define REG_DIP_IF_FLAGS REG(0x11, 0x0f) /* read/write */ ++# define DIP_IF_FLAGS_IF1 (1 << 1) ++# define DIP_IF_FLAGS_IF2 (1 << 2) ++# define DIP_IF_FLAGS_IF3 (1 << 3) ++# define DIP_IF_FLAGS_IF4 (1 << 4) ++# define DIP_IF_FLAGS_IF5 (1 << 5) ++#define REG_CH_STAT_B(x) REG(0x11, 0x14 + (x)) /* read/write */ ++ ++ ++/* Page 12h: HDCP and OTP */ ++#define REG_TX3 REG(0x12, 0x9a) /* read/write */ ++#define REG_TX4 REG(0x12, 0x9b) /* read/write */ ++# define TX4_PD_RAM (1 << 1) ++#define REG_TX33 REG(0x12, 0xb8) /* read/write */ ++# define TX33_HDMI (1 << 1) ++ ++ ++/* Page 13h: Gamut related metadata packets */ ++ ++ ++ ++/* CEC registers: (not paged) ++ */ ++#define REG_CEC_FRO_IM_CLK_CTRL 0xfb /* read/write */ ++# define CEC_FRO_IM_CLK_CTRL_GHOST_DIS (1 << 7) ++# define CEC_FRO_IM_CLK_CTRL_ENA_OTP (1 << 6) ++# define CEC_FRO_IM_CLK_CTRL_IMCLK_SEL (1 << 1) ++# define CEC_FRO_IM_CLK_CTRL_FRO_DIV (1 << 0) ++#define REG_CEC_RXSHPDLEV 0xfe /* read */ ++# define CEC_RXSHPDLEV_RXSENS (1 << 0) ++# define CEC_RXSHPDLEV_HPD (1 << 1) ++ ++#define REG_CEC_ENAMODS 0xff /* read/write */ ++# define CEC_ENAMODS_DIS_FRO (1 << 6) ++# define CEC_ENAMODS_DIS_CCLK (1 << 5) ++# define CEC_ENAMODS_EN_RXSENS (1 << 2) ++# define CEC_ENAMODS_EN_HDMI (1 << 1) ++# define CEC_ENAMODS_EN_CEC (1 << 0) ++ ++ ++/* Device versions: */ ++#define TDA9989N2 0x0101 ++#define TDA19989 0x0201 ++#define TDA19989N2 0x0202 ++#define TDA19988 0x0301 ++ ++static void ++cec_write(struct tda998x_encoder *encoder, uint16_t addr, uint8_t val) ++{ ++ struct i2c_client *client = to_tda998x_priv(encoder)->cec; ++ uint8_t buf[] = {addr, val}; ++ int ret; ++ ++ ret = i2c_master_send(client, buf, ARRAY_SIZE(buf)); ++ if (ret < 0) ++ dev_err(&client->dev, "Error %d writing to cec:0x%x\n", ++ ret, addr); ++} ++ ++static void ++set_page(struct tda998x_encoder *encoder, uint16_t reg) ++{ ++ struct tda998x_priv *priv = to_tda998x_priv(encoder); ++ ++ if (REG2PAGE(reg) != priv->current_page) { ++ struct i2c_client *client = ++ tda998x_i2c_encoder_get_client(encoder); ++ uint8_t buf[] = { ++ REG_CURPAGE, REG2PAGE(reg) ++ }; ++ int ret = i2c_master_send(client, buf, sizeof(buf)); ++ if (ret < 0) ++ dev_err(&client->dev, ++ "Error %d writing to REG_CURPAGE\n", ret); ++ ++ priv->current_page = REG2PAGE(reg); ++ } ++} ++ ++static int ++reg_read_range(struct tda998x_encoder *encoder, ++ uint16_t reg, char *buf, int cnt) ++{ ++ struct i2c_client *client = tda998x_i2c_encoder_get_client(encoder); ++ uint8_t addr = REG2ADDR(reg); ++ int ret; ++ ++ set_page(encoder, reg); ++ ++ ret = i2c_master_send(client, &addr, sizeof(addr)); ++ if (ret < 0) ++ goto fail; ++ ++ ret = i2c_master_recv(client, buf, cnt); ++ if (ret < 0) ++ goto fail; ++ ++ return ret; ++ ++fail: ++ dev_err(&client->dev, "Error %d reading from 0x%x\n", ret, reg); ++ return ret; ++} ++ ++static uint8_t ++reg_read(struct tda998x_encoder *encoder, uint16_t reg) ++{ ++ uint8_t val = 0; ++ reg_read_range(encoder, reg, &val, sizeof(val)); ++ return val; ++} ++ ++static void ++reg_write(struct tda998x_encoder *encoder, uint16_t reg, uint8_t val) ++{ ++ struct i2c_client *client = tda998x_i2c_encoder_get_client(encoder); ++ uint8_t buf[] = {REG2ADDR(reg), val}; ++ int ret; ++ ++ set_page(encoder, reg); ++ ++ ret = i2c_master_send(client, buf, ARRAY_SIZE(buf)); ++ if (ret < 0) ++ dev_err(&client->dev, "Error %d writing to 0x%x\n", ret, reg); ++} ++ ++static void ++reg_write16(struct tda998x_encoder *encoder, uint16_t reg, uint16_t val) ++{ ++ struct i2c_client *client = tda998x_i2c_encoder_get_client(encoder); ++ uint8_t buf[] = {REG2ADDR(reg), val >> 8, val}; ++ int ret; ++ ++ set_page(encoder, reg); ++ ++ ret = i2c_master_send(client, buf, ARRAY_SIZE(buf)); ++ if (ret < 0) ++ dev_err(&client->dev, "Error %d writing to 0x%x\n", ret, reg); ++} ++ ++static void ++reg_set(struct tda998x_encoder *encoder, uint16_t reg, uint8_t val) ++{ ++ reg_write(encoder, reg, reg_read(encoder, reg) | val); ++} ++ ++static void ++reg_clear(struct tda998x_encoder *encoder, uint16_t reg, uint8_t val) ++{ ++ reg_write(encoder, reg, reg_read(encoder, reg) & ~val); ++} ++ ++static void ++tda998x_reset(struct tda998x_encoder *encoder) ++{ ++ /* reset audio and i2c master: */ ++ reg_set(encoder, REG_SOFTRESET, SOFTRESET_AUDIO | SOFTRESET_I2C_MASTER); ++ msleep(50); ++ reg_clear(encoder, REG_SOFTRESET, ++ SOFTRESET_AUDIO | SOFTRESET_I2C_MASTER); ++ msleep(50); ++ ++ /* reset transmitter: */ ++ reg_set(encoder, REG_MAIN_CNTRL0, MAIN_CNTRL0_SR); ++ reg_clear(encoder, REG_MAIN_CNTRL0, MAIN_CNTRL0_SR); ++ ++ /* PLL registers common configuration */ ++ reg_write(encoder, REG_PLL_SERIAL_1, 0x00); ++ reg_write(encoder, REG_PLL_SERIAL_2, PLL_SERIAL_2_SRL_NOSC(1)); ++ reg_write(encoder, REG_PLL_SERIAL_3, 0x00); ++ reg_write(encoder, REG_SERIALIZER, 0x00); ++ reg_write(encoder, REG_BUFFER_OUT, 0x00); ++ reg_write(encoder, REG_PLL_SCG1, 0x00); ++ reg_write(encoder, REG_AUDIO_DIV, 0x03); ++ reg_write(encoder, REG_SEL_CLK, ++ SEL_CLK_SEL_CLK1 | SEL_CLK_ENA_SC_CLK); ++ reg_write(encoder, REG_PLL_SCGN1, 0xfa); ++ reg_write(encoder, REG_PLL_SCGN2, 0x00); ++ reg_write(encoder, REG_PLL_SCGR1, 0x5b); ++ reg_write(encoder, REG_PLL_SCGR2, 0x00); ++ reg_write(encoder, REG_PLL_SCG2, 0x10); ++} ++ ++struct tda_mode { ++ uint32_t clock; ++ uint32_t vrefresh; ++ uint32_t hdisplay; ++ uint32_t hsync_start; ++ uint32_t hsync_end; ++ uint32_t htotal; ++ uint32_t vdisplay; ++ uint32_t vsync_start; ++ uint32_t vsync_end; ++ uint32_t vtotal; ++ uint32_t flags; ++ uint32_t hskew; ++}; ++ ++static void convert_to_display_mode(struct tda_mode *mode, ++ struct fb_videomode *timing) ++{ ++ mode->clock = (PICOS2KHZ(timing->pixclock)/10)*10; ++ mode->vrefresh = timing->refresh; ++ ++ mode->hdisplay = timing->xres; ++ mode->hsync_start = mode->hdisplay + timing->right_margin; ++ mode->hsync_end = mode->hsync_start + timing->hsync_len; ++ mode->htotal = mode->hsync_end + timing->left_margin; ++ ++ mode->vdisplay = timing->yres; ++ mode->vsync_start = mode->vdisplay + timing->lower_margin; ++ mode->vsync_end = mode->vsync_start + timing->vsync_len; ++ mode->vtotal = mode->vsync_end + timing->upper_margin; ++ ++ mode->flags = timing->sync; ++ ++ ++ ++ pr_debug("mode->htotal %d, mode->vtotal %d, mode->flags %x\n", ++ mode->htotal, mode->vtotal, mode->flags); ++ pr_debug("mode->clock %d\n", mode->clock); ++ pr_debug("mode->vrefresh %d\n", mode->vrefresh); ++ pr_debug("mode->hdisplay %d\n", mode->hdisplay); ++ pr_debug("mode->hsync_start %d\n", mode->hsync_start); ++ pr_debug("mode->hsync_end %d\n", mode->hsync_end); ++ pr_debug("mode->vdisplay %d\n", mode->vdisplay); ++ pr_debug("mode->vsync_start %d\n", mode->vsync_start); ++ pr_debug("mode->vsync_end %d\n", mode->vsync_end); ++ ++ /* ++ * this is a workaround to fix up the mode so that the non-vesa ++ * compliant LCD controller can work with the NXP HDMI encoder ++ * we invert the horizontal sync pulse, and then add some hskew ++ * to move the picture to the right on the screen by a sync pulse ++ * worth of pixels ++ */ ++ mode->hskew = mode->hsync_end - mode->hsync_start; ++ mode->flags ^= FB_SYNC_HOR_HIGH_ACT; ++ ++ pr_debug("mode->hskew %d\n", mode->hskew); ++ ++} ++ ++ ++void da8xx_tda998x_setmode(struct tda998x_encoder *encoder, ++ struct fb_videomode *vid_mode) ++{ ++ struct tda998x_priv *priv = to_tda998x_priv(encoder); ++ uint16_t ref_pix, ref_line, n_pix, n_line; ++ uint16_t hs_pix_s, hs_pix_e; ++ uint16_t vs1_pix_s, vs1_pix_e, vs1_line_s, vs1_line_e; ++ uint16_t vs2_pix_s, vs2_pix_e, vs2_line_s, vs2_line_e; ++ uint16_t vwin1_line_s, vwin1_line_e; ++ uint16_t vwin2_line_s, vwin2_line_e; ++ uint16_t de_pix_s, de_pix_e; ++ uint8_t reg, div, rep; ++ struct tda_mode tda_mode; ++ struct tda_mode *mode = &tda_mode; ++ ++ convert_to_display_mode(mode, vid_mode); ++ ++ /* ++ * Internally TDA998x is using ITU-R BT.656 style sync but ++ * we get VESA style sync. TDA998x is using a reference pixel ++ * relative to ITU to sync to the input frame and for output ++ * sync generation. ++ * ++ * Now there is some issues to take care of: ++ * - HDMI data islands require sync-before-active ++ * - TDA998x register values must be > 0 to be enabled ++ * - REFLINE needs an additional offset of +1 ++ * - REFPIX needs an addtional offset of +1 for UYUV and +3 for RGB ++ * ++ * So we add +1 to all horizontal and vertical register values, ++ * plus an additional +3 for REFPIX as we are using RGB input only. ++ */ ++ n_pix = mode->htotal; ++ n_line = mode->vtotal; ++ ++ ref_pix = 3 + mode->hsync_start - mode->hdisplay; ++ ++ /* ++ * handle issue on TILCDC where it is outputing ++ * non-VESA compliant sync signals the workaround ++ * forces us to invert the HSYNC, so need to adjust display to ++ * the left by hskew pixels, provided by the tilcdc driver ++ */ ++ ref_pix += mode->hskew; ++ ++ de_pix_s = mode->htotal - mode->hdisplay; ++ de_pix_e = de_pix_s + mode->hdisplay; ++ hs_pix_s = mode->hsync_start - mode->hdisplay; ++ hs_pix_e = hs_pix_s + mode->hsync_end - mode->hsync_start; ++ ++ ref_line = 1 + mode->vsync_start - mode->vdisplay; ++ vwin1_line_s = mode->vtotal - mode->vdisplay - 1; ++ vwin1_line_e = vwin1_line_s + mode->vdisplay; ++ vs1_pix_s = vs1_pix_e = hs_pix_s; ++ vs1_line_s = mode->vsync_start - mode->vdisplay; ++ ++ vs1_line_e = vs1_line_s + ++ mode->vsync_end - mode->vsync_start; ++ ++ vwin2_line_s = vwin2_line_e = 0; ++ vs2_pix_s = vs2_pix_e = 0; ++ vs2_line_s = vs2_line_e = 0; ++ ++ div = 148500 / mode->clock; ++ ++ /* Setup the VIP mappings, enable audio and video ports */ ++ reg_write(encoder, REG_ENA_AP, 0xff); ++ reg_write(encoder, REG_ENA_VP_0, 0xff); ++ reg_write(encoder, REG_ENA_VP_1, 0xff); ++ reg_write(encoder, REG_ENA_VP_2, 0xff); ++ /* set muxing after enabling ports: */ ++ reg_write(encoder, REG_VIP_CNTRL_0, ++ VIP_CNTRL_0_SWAP_A(2) | VIP_CNTRL_0_SWAP_B(3)); ++ reg_write(encoder, REG_VIP_CNTRL_1, ++ VIP_CNTRL_1_SWAP_C(4) | VIP_CNTRL_1_SWAP_D(5)); ++ reg_write(encoder, REG_VIP_CNTRL_2, ++ VIP_CNTRL_2_SWAP_E(0) | VIP_CNTRL_2_SWAP_F(1)); ++ ++ ++ /* mute the audio FIFO: */ ++ reg_set(encoder, REG_AIP_CNTRL_0, AIP_CNTRL_0_RST_FIFO); ++ ++ /* set HDMI HDCP mode off: */ ++ reg_set(encoder, REG_TBG_CNTRL_1, TBG_CNTRL_1_DWIN_DIS); ++ reg_clear(encoder, REG_TX33, TX33_HDMI); ++ ++ reg_write(encoder, REG_ENC_CNTRL, ENC_CNTRL_CTL_CODE(0)); ++ /* no pre-filter or interpolator: */ ++ reg_write(encoder, REG_HVF_CNTRL_0, HVF_CNTRL_0_PREFIL(0) | ++ HVF_CNTRL_0_INTPOL(0)); ++ reg_write(encoder, REG_VIP_CNTRL_5, VIP_CNTRL_5_SP_CNT(0)); ++ reg_write(encoder, REG_VIP_CNTRL_4, VIP_CNTRL_4_BLANKIT(0) | ++ VIP_CNTRL_4_BLC(0)); ++ reg_clear(encoder, REG_PLL_SERIAL_3, PLL_SERIAL_3_SRL_CCIR); ++ ++ reg_clear(encoder, REG_PLL_SERIAL_1, PLL_SERIAL_1_SRL_MAN_IZ); ++ reg_clear(encoder, REG_PLL_SERIAL_3, PLL_SERIAL_3_SRL_DE); ++ reg_write(encoder, REG_SERIALIZER, 0); ++ reg_write(encoder, REG_HVF_CNTRL_1, HVF_CNTRL_1_VQR(0)); ++ ++ /* TODO enable pixel repeat for pixel rates less than 25Msamp/s */ ++ rep = 0; ++ reg_write(encoder, REG_RPT_CNTRL, 0); ++ reg_write(encoder, REG_SEL_CLK, SEL_CLK_SEL_VRF_CLK(0) | ++ SEL_CLK_SEL_CLK1 | SEL_CLK_ENA_SC_CLK); ++ ++ reg_write(encoder, REG_PLL_SERIAL_2, PLL_SERIAL_2_SRL_NOSC(div) | ++ PLL_SERIAL_2_SRL_PR(rep)); ++ ++ /* set color matrix bypass flag: */ ++ reg_set(encoder, REG_MAT_CONTRL, MAT_CONTRL_MAT_BP); ++ ++ /* set BIAS tmds value: */ ++ reg_write(encoder, REG_ANA_GENERAL, 0x09); ++ ++ reg_clear(encoder, REG_TBG_CNTRL_0, TBG_CNTRL_0_SYNC_MTHD); ++ ++ /* ++ * Sync on rising HSYNC/VSYNC ++ */ ++ reg_write(encoder, REG_VIP_CNTRL_3, 0); ++ reg_set(encoder, REG_VIP_CNTRL_3, VIP_CNTRL_3_SYNC_HS); ++ ++ /* ++ * TDA19988 requires high-active sync at input stage, ++ * so invert low-active sync provided by master encoder here ++ */ ++ if ((mode->flags & FB_SYNC_HOR_HIGH_ACT) == 0) ++ reg_set(encoder, REG_VIP_CNTRL_3, VIP_CNTRL_3_H_TGL); ++ if ((mode->flags & FB_SYNC_VERT_HIGH_ACT) == 0) ++ reg_set(encoder, REG_VIP_CNTRL_3, VIP_CNTRL_3_V_TGL); ++ ++ /* ++ * Always generate sync polarity relative to input sync and ++ * revert input stage toggled sync at output stage ++ */ ++ reg = TBG_CNTRL_1_TGL_EN; ++ if ((mode->flags & FB_SYNC_HOR_HIGH_ACT) == 0) ++ reg |= TBG_CNTRL_1_H_TGL; ++ if ((mode->flags & FB_SYNC_VERT_HIGH_ACT) == 0) ++ reg |= TBG_CNTRL_1_V_TGL; ++ reg_write(encoder, REG_TBG_CNTRL_1, reg); ++ ++ reg_write(encoder, REG_VIDFORMAT, 0x00); ++ reg_write16(encoder, REG_REFPIX_MSB, ref_pix); ++ reg_write16(encoder, REG_REFLINE_MSB, ref_line); ++ reg_write16(encoder, REG_NPIX_MSB, n_pix); ++ reg_write16(encoder, REG_NLINE_MSB, n_line); ++ reg_write16(encoder, REG_VS_LINE_STRT_1_MSB, vs1_line_s); ++ reg_write16(encoder, REG_VS_PIX_STRT_1_MSB, vs1_pix_s); ++ reg_write16(encoder, REG_VS_LINE_END_1_MSB, vs1_line_e); ++ reg_write16(encoder, REG_VS_PIX_END_1_MSB, vs1_pix_e); ++ reg_write16(encoder, REG_VS_LINE_STRT_2_MSB, vs2_line_s); ++ reg_write16(encoder, REG_VS_PIX_STRT_2_MSB, vs2_pix_s); ++ reg_write16(encoder, REG_VS_LINE_END_2_MSB, vs2_line_e); ++ reg_write16(encoder, REG_VS_PIX_END_2_MSB, vs2_pix_e); ++ reg_write16(encoder, REG_HS_PIX_START_MSB, hs_pix_s); ++ reg_write16(encoder, REG_HS_PIX_STOP_MSB, hs_pix_e); ++ reg_write16(encoder, REG_VWIN_START_1_MSB, vwin1_line_s); ++ reg_write16(encoder, REG_VWIN_END_1_MSB, vwin1_line_e); ++ reg_write16(encoder, REG_VWIN_START_2_MSB, vwin2_line_s); ++ reg_write16(encoder, REG_VWIN_END_2_MSB, vwin2_line_e); ++ reg_write16(encoder, REG_DE_START_MSB, de_pix_s); ++ reg_write16(encoder, REG_DE_STOP_MSB, de_pix_e); ++ ++ if (priv->rev == TDA19988) { ++ /* let incoming pixels fill the active space (if any) */ ++ reg_write(encoder, REG_ENABLE_SPACE, 0x01); ++ } ++ ++ /* must be last register set: */ ++ reg_clear(encoder, REG_TBG_CNTRL_0, TBG_CNTRL_0_SYNC_ONCE); ++ ++} ++ ++/* I2C driver functions */ ++static int ++da8xx_tda998x_probe(struct i2c_client *client, const struct i2c_device_id *id) ++{ ++ struct tda998x_priv *priv; ++ struct da8xx_encoder *encoder; ++ ++ priv = kzalloc(sizeof(*priv), GFP_KERNEL); ++ if (!priv) ++ return -ENOMEM; ++ ++ priv->current_page = 0; ++ ++ encoder = kzalloc(sizeof(*encoder), GFP_KERNEL); ++ if (!encoder) { ++ kfree(priv); ++ return -ENOMEM; ++ } ++ ++ priv->cec = i2c_new_dummy(client->adapter, 0x34); ++ ++ encoder->client = client; ++ encoder->priv = priv; ++ encoder->node = client->dev.of_node; ++ encoder->set_mode = da8xx_tda998x_setmode; ++ ++ ++ /* wake up the device: */ ++ cec_write(encoder, REG_CEC_ENAMODS, ++ CEC_ENAMODS_EN_RXSENS | CEC_ENAMODS_EN_HDMI); ++ ++ tda998x_reset(encoder); ++ ++ /* read version: */ ++ priv->rev = reg_read(encoder, REG_VERSION_LSB) | ++ reg_read(encoder, REG_VERSION_MSB) << 8; ++ ++ /* mask off feature bits: */ ++ priv->rev &= ~0x30; /* not-hdcp and not-scalar bit */ ++ ++ switch (priv->rev) { ++ case TDA9989N2: ++ dev_info(&client->dev, "found TDA9989 n2"); ++ break; ++ case TDA19989: ++ dev_info(&client->dev, "found TDA19989"); ++ break; ++ case TDA19989N2: ++ dev_info(&client->dev, "found TDA19989 n2"); ++ break; ++ case TDA19988: ++ dev_info(&client->dev, "found TDA19988"); ++ break; ++ default: ++ DBG("found unsupported device: %04x", priv->rev); ++ goto fail; ++ } ++ ++ da8xx_register_encoder(encoder); ++ ++ /* after reset, enable DDC: */ ++ reg_write(encoder, REG_DDC_DISABLE, 0x00); ++ ++ /* set clock on DDC channel: */ ++ reg_write(encoder, REG_TX3, 39); ++ ++ /* if necessary, disable multi-master: */ ++ if (priv->rev == TDA19989) ++ reg_set(encoder, REG_I2C_MASTER, I2C_MASTER_DIS_MM); ++ ++ cec_write(encoder, REG_CEC_FRO_IM_CLK_CTRL, ++ CEC_FRO_IM_CLK_CTRL_GHOST_DIS | ++ CEC_FRO_IM_CLK_CTRL_IMCLK_SEL); ++ ++ i2c_set_clientdata(client, encoder); ++ ++ return 0; ++ ++fail: ++ /* if encoder_init fails, the encoder slave is never registered, ++ * so cleanup here: ++ */ ++ if (priv->cec) ++ i2c_unregister_device(priv->cec); ++ ++ kfree(priv); ++ kfree(encoder); ++ return -ENXIO; ++} ++ ++static int ++da8xx_tda998x_remove(struct i2c_client *client) ++{ ++ struct da8xx_encoder *da8xx_encoder; ++ struct tda998x_priv *priv; ++ ++ da8xx_encoder = i2c_get_clientdata(client); ++ if (da8xx_encoder) { ++ da8xx_unregister_encoder(da8xx_encoder); ++ priv = to_tda998x_priv(da8xx_encoder); ++ if (priv->cec) { ++ /* disable the device: */ ++ cec_write(da8xx_encoder, REG_CEC_ENAMODS, 0); ++ i2c_unregister_device(priv->cec); ++ } ++ kfree(da8xx_encoder->priv); ++ kfree(da8xx_encoder); ++ } ++ return 0; ++} ++ ++ ++static struct i2c_device_id da8xx_tda998x_ids[] = { ++ { "tda998x", 0 }, ++ { } ++}; ++MODULE_DEVICE_TABLE(i2c, da8xx_tda998x_ids); ++ ++static struct i2c_driver da8xx_tda998x_driver = { ++ .probe = da8xx_tda998x_probe, ++ .remove = da8xx_tda998x_remove, ++ .driver = { ++ .owner = THIS_MODULE, ++ .name = "tda998x", ++ }, ++ .id_table = da8xx_tda998x_ids, ++}; ++ ++module_i2c_driver(da8xx_tda998x_driver); ++ ++MODULE_DESCRIPTION("NXP TDA998x HDMI encoder driver for TI AM335x/DA8xx"); ++MODULE_AUTHOR("Texas Instruments"); ++MODULE_LICENSE("GPL"); +--- a/drivers/video/Kconfig ++++ b/drivers/video/Kconfig +@@ -2234,6 +2234,14 @@ config FB_DA8XX + found on DA8xx/OMAP-L1xx/AM335x SoCs. + If unsure, say N. + ++config FB_DA8XX_TDA998X ++ tristate "NXP TDA998x HDMI driver for BeagleBone Black" ++ depends on FB_DA8XX ++ ---help--- ++ This is a driver for NXP TDA998X HDMI as used on the BeagleBone ++ Black. ++ If unsure, say N. ++ + config FB_VIRTUAL + tristate "Virtual Frame Buffer support (ONLY FOR TESTING!)" + depends on FB +--- a/drivers/video/Makefile ++++ b/drivers/video/Makefile +@@ -164,6 +164,7 @@ obj-$(CONFIG_FB_BFIN_T350MCQB) += bfin + obj-$(CONFIG_FB_BFIN_7393) += bfin_adv7393fb.o + obj-$(CONFIG_FB_MX3) += mx3fb.o + obj-$(CONFIG_FB_DA8XX) += da8xx-fb.o ++obj-$(CONFIG_FB_DA8XX_TDA998X) += da8xx-tda998x-hdmi.o + obj-$(CONFIG_FB_MXS) += mxsfb.o + obj-$(CONFIG_FB_SSD1307) += ssd1307fb.o + obj-$(CONFIG_FB_SIMPLE) += simplefb.o +--- a/drivers/video/omap2/displays-new/connector-analog-tv.c ++++ b/drivers/video/omap2/displays-new/connector-analog-tv.c +@@ -12,6 +12,7 @@ + #include <linux/slab.h> + #include <linux/module.h> + #include <linux/platform_device.h> ++#include <linux/of.h> + + #include <video/omapdss.h> + #include <video/omap-panel-data.h> +@@ -42,6 +43,12 @@ static const struct omap_video_timings t + .interlace = true, + }; + ++static const struct of_device_id tvc_of_match[]; ++ ++struct tvc_of_data { ++ enum omap_dss_venc_type connector_type; ++}; ++ + #define to_panel_data(x) container_of(x, struct panel_drv_data, dssdev) + + static int tvc_connect(struct omap_dss_device *dssdev) +@@ -205,6 +212,36 @@ static int tvc_probe_pdata(struct platfo + return 0; + } + ++static int tvc_probe_of(struct platform_device *pdev, ++ const struct tvc_of_data *data) ++{ ++ struct panel_drv_data *ddata = platform_get_drvdata(pdev); ++ struct device_node *node = pdev->dev.of_node; ++ struct omap_dss_device *in; ++ struct device_node *src_node; ++ ++ src_node = of_parse_phandle(node, "video-source", 0); ++ if (!src_node) { ++ dev_err(&pdev->dev, "failed to parse video source\n"); ++ return -ENODEV; ++ } ++ ++ in = omap_dss_find_output_by_node(src_node); ++ if (in == NULL) { ++ dev_err(&pdev->dev, "failed to find video source\n"); ++ return -EPROBE_DEFER; ++ } ++ ddata->in = in; ++ ++ ddata->connector_type = data->connector_type; ++ ++ ddata->invert_polarity = ++ of_property_read_bool(node, "invert-polarity"); ++ ++ return 0; ++} ++ ++ + static int tvc_probe(struct platform_device *pdev) + { + struct panel_drv_data *ddata; +@@ -222,6 +259,18 @@ static int tvc_probe(struct platform_dev + r = tvc_probe_pdata(pdev); + if (r) + return r; ++ } else if (pdev->dev.of_node) { ++ const struct of_device_id *match; ++ ++ match = of_match_node(tvc_of_match, pdev->dev.of_node); ++ if (!match) { ++ dev_err(&pdev->dev, "unsupported device\n"); ++ return -ENODEV; ++ } ++ ++ r = tvc_probe_of(pdev, match->data); ++ if (r) ++ return r; + } else { + return -ENODEV; + } +@@ -263,12 +312,33 @@ static int __exit tvc_remove(struct plat + return 0; + } + ++static const struct tvc_of_data tv_svideo_data = { ++ .connector_type = OMAP_DSS_VENC_TYPE_SVIDEO, ++}; ++ ++static const struct tvc_of_data tv_composite_video_data = { ++ .connector_type = OMAP_DSS_VENC_TYPE_COMPOSITE, ++}; ++ ++static const struct of_device_id tvc_of_match[] = { ++ { ++ .compatible = "ti,svideo-connector", ++ .data = &tv_svideo_data, ++ }, ++ { ++ .compatible = "ti,composite-video-connector", ++ .data = &tv_composite_video_data, ++ }, ++ {}, ++}; ++ + static struct platform_driver tvc_connector_driver = { + .probe = tvc_probe, + .remove = __exit_p(tvc_remove), + .driver = { + .name = "connector-analog-tv", + .owner = THIS_MODULE, ++ .of_match_table = tvc_of_match, + }, + }; + +--- a/drivers/video/omap2/displays-new/connector-dvi.c ++++ b/drivers/video/omap2/displays-new/connector-dvi.c +@@ -274,6 +274,42 @@ static int dvic_probe_pdata(struct platf + return 0; + } + ++static int dvic_probe_of(struct platform_device *pdev) ++{ ++ struct panel_drv_data *ddata = platform_get_drvdata(pdev); ++ struct device_node *node = pdev->dev.of_node; ++ struct omap_dss_device *in; ++ struct device_node *src_node; ++ struct device_node *adapter_node; ++ struct i2c_adapter *adapter; ++ ++ src_node = of_parse_phandle(node, "video-source", 0); ++ if (!src_node) { ++ dev_err(&pdev->dev, "failed to parse video source\n"); ++ return -ENODEV; ++ } ++ ++ in = omap_dss_find_output_by_node(src_node); ++ if (in == NULL) { ++ dev_err(&pdev->dev, "failed to find video source\n"); ++ return -EPROBE_DEFER; ++ } ++ ddata->in = in; ++ ++ adapter_node = of_parse_phandle(node, "i2c-bus", 0); ++ if (adapter_node) { ++ adapter = of_find_i2c_adapter_by_node(adapter_node); ++ if (adapter == NULL) { ++ dev_err(&pdev->dev, "failed to parse i2c-bus\n"); ++ return -EPROBE_DEFER; ++ } ++ ++ ddata->i2c_adapter = adapter; ++ } ++ ++ return 0; ++} ++ + static int dvic_probe(struct platform_device *pdev) + { + struct panel_drv_data *ddata; +@@ -290,6 +326,10 @@ static int dvic_probe(struct platform_de + r = dvic_probe_pdata(pdev); + if (r) + return r; ++ } else if (pdev->dev.of_node) { ++ r = dvic_probe_of(pdev); ++ if (r) ++ return r; + } else { + return -ENODEV; + } +@@ -335,12 +375,20 @@ static int __exit dvic_remove(struct pla + return 0; + } + ++static const struct of_device_id dvic_of_match[] = { ++ { .compatible = "ti,dvi_connector", }, ++ {}, ++}; ++ ++MODULE_DEVICE_TABLE(of, dvic_of_match); ++ + static struct platform_driver dvi_connector_driver = { + .probe = dvic_probe, + .remove = __exit_p(dvic_remove), + .driver = { + .name = "connector-dvi", + .owner = THIS_MODULE, ++ .of_match_table = dvic_of_match, + }, + }; + +--- a/drivers/video/omap2/displays-new/connector-hdmi.c ++++ b/drivers/video/omap2/displays-new/connector-hdmi.c +@@ -12,6 +12,7 @@ + #include <linux/slab.h> + #include <linux/module.h> + #include <linux/platform_device.h> ++#include <linux/of.h> + + #include <drm/drm_edid.h> + +@@ -301,6 +302,29 @@ static int hdmic_probe_pdata(struct plat + return 0; + } + ++static int hdmic_probe_of(struct platform_device *pdev) ++{ ++ struct panel_drv_data *ddata = platform_get_drvdata(pdev); ++ struct device_node *node = pdev->dev.of_node; ++ struct omap_dss_device *in; ++ struct device_node *src_node; ++ ++ src_node = of_parse_phandle(node, "video-source", 0); ++ if (!src_node) { ++ dev_err(&pdev->dev, "failed to parse video source\n"); ++ return -ENODEV; ++ } ++ ++ in = omap_dss_find_output_by_node(src_node); ++ if (in == NULL) { ++ dev_err(&pdev->dev, "failed to find video source\n"); ++ return -EPROBE_DEFER; ++ } ++ ddata->in = in; ++ ++ return 0; ++} ++ + static int hdmic_probe(struct platform_device *pdev) + { + struct panel_drv_data *ddata; +@@ -318,6 +342,10 @@ static int hdmic_probe(struct platform_d + r = hdmic_probe_pdata(pdev); + if (r) + return r; ++ } else if (pdev->dev.of_node) { ++ r = hdmic_probe_of(pdev); ++ if (r) ++ return r; + } else { + return -ENODEV; + } +@@ -359,12 +387,20 @@ static int __exit hdmic_remove(struct pl + return 0; + } + ++static const struct of_device_id hdmic_of_match[] = { ++ { .compatible = "ti,hdmi_connector", }, ++ {}, ++}; ++ ++MODULE_DEVICE_TABLE(of, hdmic_of_match); ++ + static struct platform_driver hdmi_connector_driver = { + .probe = hdmic_probe, + .remove = __exit_p(hdmic_remove), + .driver = { + .name = "connector-hdmi", + .owner = THIS_MODULE, ++ .of_match_table = hdmic_of_match, + }, + }; + +--- /dev/null ++++ b/drivers/video/omap2/displays-new/dra-evm-encoder-tpd12s015.c +@@ -0,0 +1,556 @@ ++/* ++ * TPD12S015 HDMI ESD protection & level shifter chip driver ++ * ++ * Copyright (C) 2013 Texas Instruments ++ * Author: Tomi Valkeinen <tomi.valkeinen@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/delay.h> ++#include <linux/module.h> ++#include <linux/slab.h> ++#include <linux/gpio.h> ++#include <linux/io.h> ++#include <linux/platform_device.h> ++#include <linux/of_gpio.h> ++ ++#include <video/omapdss.h> ++#include <video/omap-panel-data.h> ++ ++#define CLK_BASE 0x4a009000 ++#define MCASP2_BASE 0x48464000 ++#define CTRL_BASE 0x4a003400 ++#define PINMUX_BASE 0x4a003600 ++ ++#define CM_L4PER2_MCASP2_CLKCTRL 0x860 ++#define CM_L4PER2_CLKSTCTRL 0x8fc ++#define MCASP_PFUNC 0x10 ++#define MCASP_PDIR 0x14 ++#define MCASP_PDOUT 0x18 ++#define PAD_I2C2_SDA 0x408 ++#define PAD_I2C2_SCL 0x40c ++ ++#define SEL_I2C2 0 ++#define SEL_HDMI 1 ++ ++struct panel_drv_data { ++ struct omap_dss_device dssdev; ++ struct omap_dss_device *in; ++ ++ int ct_cp_hpd_gpio; ++ int ls_oe_gpio; ++ int hpd_gpio; ++ ++ struct omap_video_timings timings; ++}; ++ ++static void config_sel_hdmi_i2c2(struct device *dev) ++{ ++ void __iomem *clk_base = ioremap(CLK_BASE, SZ_4K); ++ void __iomem *mcasp2_base = ioremap(MCASP2_BASE, SZ_1K); ++ void __iomem *pmux_base = ioremap(PINMUX_BASE, SZ_1K); ++ ++ if (!clk_base) { ++ dev_err(dev, "couldn't ioremap clock domain regs\n"); ++ return; ++ } ++ ++ if (!mcasp2_base) { ++ dev_err(dev, "couldn't ioremap MCASP2 regs\n"); ++ goto mcasp_err; ++ } ++ ++ if (!pmux_base) { ++ dev_err(dev, "couldn't ioremap PMUX regs\n"); ++ goto pmux_err; ++ } ++ ++ iowrite32(0x40000, pmux_base + 0xfc); ++ ++ /* set CM_L4PER2_CLKSTCTRL to sw supervised wkup */ ++ iowrite32(0x2, clk_base + CM_L4PER2_CLKSTCTRL); ++ ++ /* ++ * Enable the MCASP8_AUX_GFCLK[22:23]: 0x0 - use default ++ * CM_L4PER2_MCASP8_CLKCTRL[1:0]: 0x2 - Enable explicitly ++ */ ++ iowrite32(0x2, clk_base + CM_L4PER2_MCASP2_CLKCTRL); ++ ++ dev_dbg(dev, "CM_L4PER2_CLKSTCTRL %08x\n", ++ ioread32(clk_base + CM_L4PER2_CLKSTCTRL)); ++ ++ /* let it propogate */ ++ ++ udelay(5); ++ /* ++ * make mcasp8_axr2 a gpio and set direction to high ++ */ ++ iowrite32(1 << 29, mcasp2_base + MCASP_PFUNC); ++ iowrite32(1 << 29, mcasp2_base + MCASP_PDIR); ++ ++ iounmap(pmux_base); ++pmux_err: ++ iounmap(mcasp2_base); ++mcasp_err: ++ iounmap(clk_base); ++} ++ ++/* ++ * use I2C2 to configure pcf8575@26 to set/unset LS_OE and CT_HPD, use HDMI to ++ * read edid via the HDMI ddc lines, and recieve HPD events ++ */ ++void config_demux(struct device *dev, int sel) ++{ ++ void __iomem *mcasp2_base = ioremap(MCASP2_BASE, SZ_1K); ++ void __iomem *ctrl_base = ioremap(CTRL_BASE, SZ_1K); ++ ++ if (!mcasp2_base) { ++ dev_err(dev, "couldn't ioremap MCASP8 regs\n"); ++ return; ++ } ++ ++ if (!ctrl_base) { ++ dev_err(dev, "couldn't ioremap CTRL base\n"); ++ goto err_ctrl; ++ } ++ ++ /* ++ * switch to I2C2 or HDMI DDC internal pinmux and drive MCASP8_PDOUT ++ * to low or high to select I2C2 or HDMI path respectively ++ */ ++ if (sel == SEL_I2C2) { ++ iowrite32(0x0, mcasp2_base + MCASP_PDOUT); ++ iowrite32(0x60000, ctrl_base + PAD_I2C2_SDA); ++ iowrite32(0x60000, ctrl_base + PAD_I2C2_SCL); ++ } else { ++ iowrite32(1 << 29, mcasp2_base + MCASP_PDOUT); ++ iowrite32(0x60001, ctrl_base + PAD_I2C2_SDA); ++ iowrite32(0x60001, ctrl_base + PAD_I2C2_SCL); ++ } ++ ++ /* let it propogate */ ++ udelay(5); ++ ++ dev_dbg(dev, "select %d, PDOUT %08x\n", sel, ++ ioread32(mcasp2_base + MCASP_PDOUT)); ++ ++ iounmap(ctrl_base); ++err_ctrl: ++ iounmap(mcasp2_base); ++} ++ ++#define to_panel_data(x) container_of(x, struct panel_drv_data, dssdev) ++ ++static int tpd_connect(struct omap_dss_device *dssdev, ++ struct omap_dss_device *dst) ++{ ++ struct panel_drv_data *ddata = to_panel_data(dssdev); ++ struct omap_dss_device *in = ddata->in; ++ bool hpd; ++ int r; ++ ++ r = in->ops.hdmi->connect(in, dssdev); ++ if (r) ++ return r; ++ ++ dst->src = dssdev; ++ dssdev->dst = dst; ++ ++ config_demux(dssdev->dev, SEL_I2C2); ++ ++ gpio_set_value_cansleep(ddata->ct_cp_hpd_gpio, 1); ++ ++ config_demux(dssdev->dev, SEL_HDMI); ++ ++ /* DC-DC converter needs at max 300us to get to 90% of 5V */ ++ udelay(300); ++ ++ /* ++ * If there's a cable connected, hpd will be up, turn the level shifters ++ * accordingly ++ */ ++ hpd = gpio_get_value_cansleep(ddata->hpd_gpio); ++ ++ config_demux(dssdev->dev, SEL_I2C2); ++ ++ if (gpio_is_valid(ddata->ls_oe_gpio)) { ++ if (hpd) ++ gpio_set_value_cansleep(ddata->ls_oe_gpio, 1); ++ else ++ gpio_set_value_cansleep(ddata->ls_oe_gpio, 0); ++ } ++ ++ config_demux(dssdev->dev, SEL_HDMI); ++ ++ return 0; ++} ++ ++static void tpd_disconnect(struct omap_dss_device *dssdev, ++ struct omap_dss_device *dst) ++{ ++ struct panel_drv_data *ddata = to_panel_data(dssdev); ++ struct omap_dss_device *in = ddata->in; ++ ++ WARN_ON(dst != dssdev->dst); ++ ++ if (dst != dssdev->dst) ++ return; ++ ++ config_demux(dssdev->dev, SEL_I2C2); ++ ++ gpio_set_value_cansleep(ddata->ct_cp_hpd_gpio, 0); ++ ++ config_demux(dssdev->dev, SEL_HDMI); ++ ++ dst->src = NULL; ++ dssdev->dst = NULL; ++ ++ in->ops.hdmi->disconnect(in, &ddata->dssdev); ++} ++ ++static int tpd_enable(struct omap_dss_device *dssdev) ++{ ++ struct panel_drv_data *ddata = to_panel_data(dssdev); ++ struct omap_dss_device *in = ddata->in; ++ int r; ++ ++ if (dssdev->state == OMAP_DSS_DISPLAY_ACTIVE) ++ return 0; ++ ++ in->ops.hdmi->set_timings(in, &ddata->timings); ++ ++ r = in->ops.hdmi->enable(in); ++ if (r) ++ return r; ++ ++ dssdev->state = OMAP_DSS_DISPLAY_ACTIVE; ++ ++ return r; ++} ++ ++static void tpd_disable(struct omap_dss_device *dssdev) ++{ ++ struct panel_drv_data *ddata = to_panel_data(dssdev); ++ struct omap_dss_device *in = ddata->in; ++ ++ if (dssdev->state != OMAP_DSS_DISPLAY_ACTIVE) ++ return; ++ ++ in->ops.hdmi->disable(in); ++ ++ dssdev->state = OMAP_DSS_DISPLAY_DISABLED; ++} ++ ++static void tpd_set_timings(struct omap_dss_device *dssdev, ++ struct omap_video_timings *timings) ++{ ++ struct panel_drv_data *ddata = to_panel_data(dssdev); ++ struct omap_dss_device *in = ddata->in; ++ ++ ddata->timings = *timings; ++ dssdev->panel.timings = *timings; ++ ++ in->ops.hdmi->set_timings(in, timings); ++} ++ ++static void tpd_get_timings(struct omap_dss_device *dssdev, ++ struct omap_video_timings *timings) ++{ ++ struct panel_drv_data *ddata = to_panel_data(dssdev); ++ ++ *timings = ddata->timings; ++} ++ ++static int tpd_check_timings(struct omap_dss_device *dssdev, ++ struct omap_video_timings *timings) ++{ ++ struct panel_drv_data *ddata = to_panel_data(dssdev); ++ struct omap_dss_device *in = ddata->in; ++ int r; ++ ++ r = in->ops.hdmi->check_timings(in, timings); ++ ++ return r; ++} ++ ++static int tpd_read_edid(struct omap_dss_device *dssdev, ++ u8 *edid, int len) ++{ ++ struct panel_drv_data *ddata = to_panel_data(dssdev); ++ struct omap_dss_device *in = ddata->in; ++ ++ if (!gpio_get_value_cansleep(ddata->hpd_gpio)) ++ return -ENODEV; ++ ++ return in->ops.hdmi->read_edid(in, edid, len); ++} ++ ++static bool tpd_detect(struct omap_dss_device *dssdev) ++{ ++ struct panel_drv_data *ddata = to_panel_data(dssdev); ++ ++ return gpio_get_value_cansleep(ddata->hpd_gpio); ++} ++ ++static int tpd_audio_enable(struct omap_dss_device *dssdev) ++{ ++ struct panel_drv_data *ddata = to_panel_data(dssdev); ++ struct omap_dss_device *in = ddata->in; ++ ++ return in->ops.hdmi->audio_enable(in); ++} ++ ++static void tpd_audio_disable(struct omap_dss_device *dssdev) ++{ ++ struct panel_drv_data *ddata = to_panel_data(dssdev); ++ struct omap_dss_device *in = ddata->in; ++ ++ in->ops.hdmi->audio_disable(in); ++} ++ ++static int tpd_audio_start(struct omap_dss_device *dssdev) ++{ ++ struct panel_drv_data *ddata = to_panel_data(dssdev); ++ struct omap_dss_device *in = ddata->in; ++ ++ return in->ops.hdmi->audio_start(in); ++} ++ ++static void tpd_audio_stop(struct omap_dss_device *dssdev) ++{ ++ struct panel_drv_data *ddata = to_panel_data(dssdev); ++ struct omap_dss_device *in = ddata->in; ++ ++ in->ops.hdmi->audio_stop(in); ++} ++ ++static bool tpd_audio_supported(struct omap_dss_device *dssdev) ++{ ++ struct panel_drv_data *ddata = to_panel_data(dssdev); ++ struct omap_dss_device *in = ddata->in; ++ ++ return in->ops.hdmi->audio_supported(in); ++} ++ ++static int tpd_audio_config(struct omap_dss_device *dssdev, ++ struct omap_dss_audio *audio) ++{ ++ struct panel_drv_data *ddata = to_panel_data(dssdev); ++ struct omap_dss_device *in = ddata->in; ++ ++ return in->ops.hdmi->audio_config(in, audio); ++} ++ ++static const struct omapdss_hdmi_ops tpd_hdmi_ops = { ++ .connect = tpd_connect, ++ .disconnect = tpd_disconnect, ++ ++ .enable = tpd_enable, ++ .disable = tpd_disable, ++ ++ .check_timings = tpd_check_timings, ++ .set_timings = tpd_set_timings, ++ .get_timings = tpd_get_timings, ++ ++ .read_edid = tpd_read_edid, ++ .detect = tpd_detect, ++ ++ .audio_enable = tpd_audio_enable, ++ .audio_disable = tpd_audio_disable, ++ .audio_start = tpd_audio_start, ++ .audio_stop = tpd_audio_stop, ++ .audio_supported = tpd_audio_supported, ++ .audio_config = tpd_audio_config, ++}; ++ ++static int tpd_probe_pdata(struct platform_device *pdev) ++{ ++ struct panel_drv_data *ddata = platform_get_drvdata(pdev); ++ struct encoder_tpd12s015_platform_data *pdata; ++ struct omap_dss_device *dssdev, *in; ++ ++ pdata = dev_get_platdata(&pdev->dev); ++ ++ ddata->ct_cp_hpd_gpio = pdata->ct_cp_hpd_gpio; ++ ddata->ls_oe_gpio = pdata->ls_oe_gpio; ++ ddata->hpd_gpio = pdata->hpd_gpio; ++ ++ in = omap_dss_find_output(pdata->source); ++ if (in == NULL) { ++ dev_err(&pdev->dev, "Failed to find video source\n"); ++ return -ENODEV; ++ } ++ ++ ddata->in = in; ++ ++ dssdev = &ddata->dssdev; ++ dssdev->name = pdata->name; ++ ++ return 0; ++} ++ ++static int tpd_probe_of(struct platform_device *pdev) ++{ ++ struct panel_drv_data *ddata = platform_get_drvdata(pdev); ++ struct device_node *node = pdev->dev.of_node; ++ struct omap_dss_device *in; ++ struct device_node *src_node; ++ int gpio; ++ ++ src_node = of_parse_phandle(node, "video-source", 0); ++ if (!src_node) { ++ dev_err(&pdev->dev, "failed to parse video source\n"); ++ return -ENODEV; ++ } ++ ++ in = omap_dss_find_output_by_node(src_node); ++ if (in == NULL) { ++ dev_err(&pdev->dev, "failed to find video source\n"); ++ return -EPROBE_DEFER; ++ } ++ ddata->in = in; ++ ++ /* CT CP HPD GPIO */ ++ gpio = of_get_gpio(node, 0); ++ if (!gpio_is_valid(gpio)) { ++ dev_err(&pdev->dev, "failed to parse CT CP HPD gpio\n"); ++ return gpio; ++ } ++ ddata->ct_cp_hpd_gpio = gpio; ++ ++ /* LS OE GPIO */ ++ gpio = of_get_gpio(node, 1); ++ if (gpio_is_valid(gpio) || gpio == -ENOENT) { ++ ddata->ls_oe_gpio = gpio; ++ } else { ++ dev_err(&pdev->dev, "failed to parse LS OE gpio\n"); ++ return gpio; ++ } ++ ++ /* HPD GPIO */ ++ gpio = of_get_gpio(node, 2); ++ if (!gpio_is_valid(gpio)) { ++ dev_err(&pdev->dev, "failed to parse HPD gpio\n"); ++ return gpio; ++ } ++ ddata->hpd_gpio = gpio; ++ ++ return 0; ++} ++ ++static int tpd_probe(struct platform_device *pdev) ++{ ++ struct omap_dss_device *in, *dssdev; ++ struct panel_drv_data *ddata; ++ int r; ++ ++ ddata = devm_kzalloc(&pdev->dev, sizeof(*ddata), GFP_KERNEL); ++ if (!ddata) ++ return -ENOMEM; ++ ++ platform_set_drvdata(pdev, ddata); ++ ++ if (dev_get_platdata(&pdev->dev)) { ++ r = tpd_probe_pdata(pdev); ++ if (r) ++ return r; ++ } else if (pdev->dev.of_node) { ++ r = tpd_probe_of(pdev); ++ if (r) ++ return r; ++ } else { ++ return -ENODEV; ++ } ++ ++ /* configure the SEL_HDMI_I2C2 line going to the demux */ ++ config_sel_hdmi_i2c2(&pdev->dev); ++ ++ config_demux(&pdev->dev, SEL_I2C2); ++ ++ r = devm_gpio_request_one(&pdev->dev, ddata->ct_cp_hpd_gpio, ++ GPIOF_OUT_INIT_LOW, "hdmi_ct_cp_hpd"); ++ if (r) ++ goto err_gpio; ++ ++ if (gpio_is_valid(ddata->ls_oe_gpio)) { ++ r = devm_gpio_request_one(&pdev->dev, ddata->ls_oe_gpio, ++ GPIOF_OUT_INIT_LOW, "hdmi_ls_oe"); ++ if (r) ++ goto err_gpio; ++ } ++ ++ r = devm_gpio_request_one(&pdev->dev, ddata->hpd_gpio, ++ GPIOF_DIR_IN, "hdmi_hpd"); ++ if (r) ++ goto err_gpio; ++ ++ config_demux(&pdev->dev, SEL_HDMI); ++ ++ dssdev = &ddata->dssdev; ++ dssdev->ops.hdmi = &tpd_hdmi_ops; ++ dssdev->dev = &pdev->dev; ++ dssdev->type = OMAP_DISPLAY_TYPE_HDMI; ++ dssdev->output_type = OMAP_DISPLAY_TYPE_HDMI; ++ dssdev->owner = THIS_MODULE; ++ ++ in = ddata->in; ++ ++ r = omapdss_register_output(dssdev); ++ if (r) { ++ dev_err(&pdev->dev, "Failed to register output\n"); ++ goto err_reg; ++ } ++ ++ return 0; ++err_reg: ++err_gpio: ++ omap_dss_put_device(ddata->in); ++ return r; ++} ++ ++static int __exit tpd_remove(struct platform_device *pdev) ++{ ++ struct panel_drv_data *ddata = platform_get_drvdata(pdev); ++ struct omap_dss_device *dssdev = &ddata->dssdev; ++ struct omap_dss_device *in = ddata->in; ++ ++ omapdss_unregister_output(&ddata->dssdev); ++ ++ WARN_ON(omapdss_device_is_enabled(dssdev)); ++ if (omapdss_device_is_enabled(dssdev)) ++ tpd_disable(dssdev); ++ ++ WARN_ON(omapdss_device_is_connected(dssdev)); ++ if (omapdss_device_is_connected(dssdev)) ++ tpd_disconnect(dssdev, dssdev->dst); ++ ++ omap_dss_put_device(in); ++ ++ return 0; ++} ++ ++static const struct of_device_id tpd_of_match[] = { ++ { .compatible = "ti,draevm-tpd12s015", }, ++ {}, ++}; ++ ++MODULE_DEVICE_TABLE(of, tpd_of_match); ++ ++static struct platform_driver tpd_driver = { ++ .probe = tpd_probe, ++ .remove = __exit_p(tpd_remove), ++ .driver = { ++ .name = "draevm-tpd12s015", ++ .owner = THIS_MODULE, ++ .of_match_table = tpd_of_match, ++ }, ++}; ++ ++module_platform_driver(tpd_driver); ++ ++MODULE_AUTHOR("Tomi Valkeinen <tomi.valkeinen@ti.com>"); ++MODULE_DESCRIPTION("DRAEVM-TPD12S015 driver"); ++MODULE_LICENSE("GPL"); +--- /dev/null ++++ b/drivers/video/omap2/displays-new/encoder-sil9022.c +@@ -0,0 +1,880 @@ ++/* ++ * Silicon image Sil9022 DPI-to-HDMI encoder driver ++ * ++ * Copyright (C) 2013 Texas Instruments ++ * Author: Sathya Prakash M R <sathyap@ti.com> ++ * ++ * This file is licensed under the terms of the GNU General Public License ++ * version 2. This program is licensed "as is" without any warranty of any ++ * kind, whether express or implied. ++ * ++ */ ++ ++#include <linux/module.h> ++#include <linux/kernel.h> ++#include <linux/errno.h> ++#include <linux/string.h> ++#include <linux/types.h> ++#include <linux/slab.h> ++#include <linux/io.h> ++#include <linux/init.h> ++#include <linux/interrupt.h> ++#include <linux/i2c.h> ++#include <linux/device.h> ++#include <linux/delay.h> ++#include <linux/gpio.h> ++#include <linux/platform_device.h> ++#include <linux/regmap.h> ++#include <linux/of_gpio.h> ++ ++#include <video/omapdss.h> ++#include <video/omap-panel-data.h> ++#include "encoder-sil9022.h" ++ ++struct panel_drv_data { ++ struct omap_dss_device dssdev; ++ struct omap_dss_device *in; ++ struct i2c_client *i2c_client; ++ int reset_gpio; ++ int data_lines; ++ struct regmap *regmap; ++ struct omap_video_timings timings; ++}; ++ ++#define to_panel_data(x) container_of(x, struct panel_drv_data, dssdev) ++ ++static int sil9022_blockwrite_reg(struct i2c_client *client, ++ u8 reg, u16 alength, u8 *val, u16 *out_len) ++{ ++ int err = 0, i; ++ struct i2c_msg msg[1]; ++ u8 data[2]; ++ ++ if (!client->adapter) { ++ dev_err(&client->dev, "ERROR: No HDMI Device\n"); ++ return -ENODEV; ++ } ++ ++ msg->addr = client->addr; ++ msg->flags = 0; ++ msg->len = 2; ++ msg->buf = data; ++ ++ /* high byte goes out first */ ++ data[0] = reg >> 8; ++ ++ for (i = 0; i < alength - 1; i++) { ++ data[1] = val[i]; ++ err = i2c_transfer(client->adapter, msg, 1); ++ udelay(50); ++ dev_dbg(&client->dev, "i2c Block write at 0x%x, " ++ "*val=%d flags=%d byte[%d] err=%d\n", ++ data[0], data[1], msg->flags, i, err); ++ if (err < 0) ++ break; ++ } ++ /* set the number of bytes written*/ ++ *out_len = i; ++ ++ if (err < 0) { ++ dev_err(&client->dev, "ERROR: i2c Block Write at 0x%x, " ++ "*val=%d flags=%d bytes written=%d " ++ "err=%d\n", ++ data[0], data[1], msg->flags, i, err); ++ return err; ++ } ++ return 0; ++} ++ ++static int sil9022_blockread_reg(struct i2c_client *client, ++ u16 data_length, u16 alength, ++ u8 reg, u8 *val, u16 *out_len) ++{ ++ int err = 0, i; ++ struct i2c_msg msg[1]; ++ u8 data[2]; ++ ++ if (!client->adapter) { ++ dev_err(&client->dev, "ERROR: No HDMI Device\n"); ++ return -ENODEV; ++ } ++ ++ msg->addr = client->addr; ++ msg->flags = 0; ++ msg->len = 1; ++ msg->buf = data; ++ ++ /* High byte goes out first */ ++ data[0] = reg; ++ err = i2c_transfer(client->adapter, msg, 1); ++ dev_dbg(&client->dev, "Block Read1 at 0x%x, " ++ "*val=%d flags=%d err=%d\n", ++ data[0], data[1], msg->flags, err); ++ ++ for (i = 0; i < alength; i++) { ++ if (err >= 0) { ++ mdelay(3); ++ msg->flags = I2C_M_RD; ++ msg->len = data_length; ++ err = i2c_transfer(client->adapter, msg, 1); ++ } else { ++ break; ++ } ++ if (err >= 0) { ++ val[i] = 0; ++ /* High byte comes first */ ++ if (data_length == 1) ++ val[i] = data[0]; ++ else if (data_length == 2) ++ val[i] = data[1] + (data[0] << 8); ++ dev_dbg(&client->dev, "i2c Block Read2 at 0x%x, " ++ "*val=%d flags=%d byte=%d " ++ "err=%d\n", ++ reg, val[i], msg->flags, i, err); ++ } else { ++ break; ++ } ++ } ++ *out_len = i; ++ dev_dbg(&client->dev, "i2c Block Read at 0x%x, bytes read = %d\n", ++ client->addr, *out_len); ++ ++ if (err < 0) { ++ dev_err(&client->dev, "ERROR: i2c Read at 0x%x, " ++ "*val=%d flags=%d bytes read=%d err=%d\n", ++ reg, *val, msg->flags, i, err); ++ return err; ++ } ++ return 0; ++} ++ ++static int sil9022_write_reg(struct omap_dss_device *dssdev, ++ u8 reg, unsigned int val) ++{ ++ struct panel_drv_data *ddata = to_panel_data(dssdev); ++ struct regmap *map = ddata->regmap; ++ int err = 0; ++ err = regmap_write(map, reg, val); ++ return err; ++} ++ ++static int sil9022_read_reg(struct omap_dss_device *dssdev, ++ u8 reg, unsigned int *val) ++{ ++ struct panel_drv_data *ddata = to_panel_data(dssdev); ++ struct regmap *map = ddata->regmap; ++ int err = 0; ++ err = regmap_read(map, reg, val); ++ return err; ++} ++ ++static int sil9022_hw_enable(struct omap_dss_device *dssdev) ++{ ++ int err; ++ u8 vals[14]; ++ unsigned int val; ++ u16 out_len = 0; ++ u16 horizontal_res; ++ u16 vertical_res; ++ u16 pixel_clk; ++ ++ struct panel_drv_data *ddata = to_panel_data(dssdev); ++ struct omap_video_timings *hdmi_timings = &ddata->timings; ++ struct i2c_client *sil9022_client = ddata->i2c_client; ++ ++ memset(vals, 0, 14); ++ ++ horizontal_res = hdmi_timings->x_res; ++ vertical_res = hdmi_timings->y_res; ++ pixel_clk = hdmi_timings->pixel_clock; ++ ++ dev_info(dssdev->dev, ++ "HW_ENABLE -> Timings\n" ++ "pixel_clk = %d\n" ++ "horizontal res = %d\n" ++ "vertical res = %d\n", ++ hdmi_timings->pixel_clock, ++ hdmi_timings->x_res, ++ hdmi_timings->y_res ++ ); ++ ++ /* Fill the TPI Video Mode Data structure */ ++ vals[0] = (pixel_clk & 0xFF); /* Pixel clock */ ++ vals[1] = ((pixel_clk & 0xFF00) >> 8); ++ vals[2] = VERTICAL_FREQ; /* Vertical freq */ ++ /* register programming information on how vertical freq is to be ++ programmed to Sil9022 not clear. Hence setting to 60 for now */ ++ vals[3] = 0x00; ++ vals[4] = (horizontal_res & 0xFF); /* Horizontal pixels*/ ++ vals[5] = ((horizontal_res & 0xFF00) >> 8); ++ vals[6] = (vertical_res & 0xFF); /* Vertical pixels */ ++ vals[7] = ((vertical_res & 0xFF00) >> 8); ++ ++ /* Write out the TPI Video Mode Data */ ++ out_len = 0; ++ err = sil9022_blockwrite_reg(sil9022_client, ++ HDMI_TPI_VIDEO_DATA_BASE_REG, ++ 8, vals, &out_len); ++ if (err < 0) { ++ dev_err(dssdev->dev, ++ "ERROR: writing TPI video mode data\n"); ++ return err; ++ } ++ ++ /* Write out the TPI Input bus and pixel repetition Data: ++ (24 bit wide bus, falling edge, no pixel replication, 1:1 CLK ration) */ ++ val = TPI_AVI_PIXEL_REP_BUS_24BIT | ++ TPI_AVI_PIXEL_REP_FALLING_EDGE | ++ TPI_AVI_PIXEL_REP_NONE | TPI_CLK_RATIO_1X; ++ err = sil9022_write_reg(dssdev, ++ HDMI_TPI_PIXEL_REPETITION_REG, ++ val); ++ ++ if (err < 0) { ++ dev_err(dssdev->dev, ++ "ERROR: writing TPI pixel repetition data\n"); ++ return err; ++ } ++ ++ /* Write out the TPI AVI Input Format */ ++ val = TPI_AVI_INPUT_BITMODE_8BIT | ++ TPI_AVI_INPUT_RANGE_AUTO | ++ TPI_AVI_INPUT_COLORSPACE_RGB; ++ err = sil9022_write_reg(dssdev, ++ HDMI_TPI_AVI_IN_FORMAT_REG, ++ val); ++ if (err < 0) { ++ dev_err(dssdev->dev, ++ "ERROR: writing TPI AVI Input format\n"); ++ return err; ++ } ++ ++ /* Write out the TPI AVI Output Format */ ++ val = TPI_AVI_OUTPUT_CONV_BT709 | ++ TPI_AVI_OUTPUT_RANGE_AUTO | ++ TPI_AVI_OUTPUT_COLORSPACE_RGBHDMI; ++ err = sil9022_write_reg(dssdev, ++ HDMI_TPI_AVI_OUT_FORMAT_REG, val); ++ if (err < 0) { ++ dev_err(dssdev->dev, ++ "ERROR: writing TPI AVI output format\n"); ++ return err; ++ } ++ ++ /* Write out the TPI System Control Data to power down */ ++ val = TPI_SYS_CTRL_POWER_DOWN; ++ err = sil9022_write_reg(dssdev, HDMI_SYS_CTRL_DATA_REG, val); ++ if (err < 0) { ++ dev_err(dssdev->dev, ++ "ERROR: writing TPI power down control data\n"); ++ return err; ++ } ++ ++ /* Move from ENABLED -> FULLY ENABLED Power State */ ++ val = TPI_AVI_POWER_STATE_D0; ++ err = sil9022_write_reg(dssdev, ++ HDMI_TPI_POWER_STATE_CTRL_REG, val); ++ if (err < 0) { ++ dev_err(&sil9022_client->dev, ++ "<%s> ERROR: Setting device power state to D0\n", ++ __func__); ++ return err; ++ } ++ ++ /* Write out the TPI System Control Data to power up and ++ * select output mode ++ */ ++ val = TPI_SYS_CTRL_POWER_ACTIVE | TPI_SYS_CTRL_OUTPUT_MODE_HDMI; ++ err = sil9022_write_reg(dssdev, HDMI_SYS_CTRL_DATA_REG, val); ++ if (err < 0) { ++ dev_err(&sil9022_client->dev, ++ "<%s> ERROR: Writing system control data\n", __func__); ++ return err; ++ } ++ ++ /* Read back TPI System Control Data to latch settings */ ++ msleep(20); ++ err = sil9022_read_reg(dssdev, HDMI_SYS_CTRL_DATA_REG, &val); ++ if (err < 0) { ++ dev_err(&sil9022_client->dev, ++ "<%s> ERROR: Writing system control data\n", ++ __func__); ++ return err; ++ } ++ ++ /* HDCP */ ++ val = 0; /* DISABLED */ ++ err = sil9022_write_reg(dssdev, ++ HDMI_TPI_HDCP_CONTROLDATA_REG, val); ++ if (err < 0) { ++ dev_err(&sil9022_client->dev, ++ "<%s> ERROR: Enable (1) / Disable (0) => HDCP: %d\n", ++ __func__, val); ++ return err; ++ } ++ ++ dev_info(&sil9022_client->dev, "<%s> hdmi enabled\n", __func__); ++ return 0; ++ ++} ++ ++static int sil9022_hw_disable(struct omap_dss_device *dssdev) ++{ ++ unsigned int val = 0; ++ int err = 0; ++ ++ /* Write out the TPI System Control Data to power down */ ++ val = TPI_SYS_CTRL_POWER_DOWN; ++ err = sil9022_write_reg(dssdev, HDMI_SYS_CTRL_DATA_REG, val); ++ if (err < 0) { ++ dev_err(dssdev->dev, ++ "ERROR: writing control data - power down\n"); ++ return err; ++ } ++ ++ /* Move from FULLY ENABLED -> ENABLED Power state */ ++ val = TPI_AVI_POWER_STATE_D2; ++ err = sil9022_write_reg(dssdev, ++ HDMI_TPI_DEVICE_POWER_STATE_DATA, val); ++ if (err < 0) { ++ dev_err(dssdev->dev, ++ "ERROR: Setting device power state to D2\n"); ++ return err; ++ } ++ ++ /* Read back TPI System Control Data to latch settings */ ++ mdelay(10); ++ err = sil9022_read_reg(dssdev, HDMI_SYS_CTRL_DATA_REG, &val); ++ if (err < 0) { ++ dev_err(dssdev->dev, ++ "ERROR: Reading System control data " ++ "- latch settings\n"); ++ return err; ++ } ++ ++ dev_info(dssdev->dev, "hdmi disabled\n"); ++ return 0; ++ ++} ++ ++static int sil9022_probe_chip_version(struct omap_dss_device *dssdev) ++{ ++ int err = 0; ++ unsigned int ver; ++ ++ /* probe for sil9022 chip version*/ ++ err = sil9022_write_reg(dssdev, SIL9022_REG_TPI_RQB, 0x00); ++ if (err < 0) { ++ dev_err(dssdev->dev, ++ "ERROR: Writing HDMI configuration to " ++ "reg - SI9022_REG_TPI_RQB\n"); ++ err = -ENODEV; ++ return err; ++ } ++ ++ err = sil9022_read_reg(dssdev, SIL9022_REG_CHIPID0, &ver); ++ if (err < 0) { ++ dev_err(dssdev->dev, ++ "ERROR: Reading HDMI version Id\n"); ++ err = -ENODEV; ++ } else if (ver != SIL9022_CHIPID_902x) { ++ dev_err(dssdev->dev, ++ "Not a valid verId: 0x%x\n", ver); ++ err = -ENODEV; ++ } else { ++ dev_info(dssdev->dev, ++ "sil9022 HDMI Chip version = %x\n", ver); ++ } ++ return err; ++} ++ ++/* Hdmi ops */ ++ ++static int sil9022_connect(struct omap_dss_device *dssdev, ++ struct omap_dss_device *dst) ++{ ++ struct panel_drv_data *ddata = to_panel_data(dssdev); ++ struct omap_dss_device *in = ddata->in; ++ int err; ++ ++ dev_err(dssdev->dev, "CONNECT\n"); ++ ++ if (omapdss_device_is_connected(dssdev)) ++ return -EBUSY; ++ ++ err = in->ops.dpi->connect(in, dssdev); ++ if (err) ++ return err; ++ ++ dst->src = dssdev; ++ dssdev->dst = dst; ++ ++ /* Move from LOW -> ENABLED Power state */ ++ err = sil9022_write_reg(dssdev, HDMI_TPI_POWER_STATE_CTRL_REG, ++ TPI_AVI_POWER_STATE_D2); ++ if (err < 0) { ++ dev_err(dssdev->dev, "ERROR: Setting device power state to D2\n"); ++ return err; ++ } ++ ++ return 0; ++ ++} ++ ++static void sil9022_disconnect(struct omap_dss_device *dssdev, ++ struct omap_dss_device *dst) ++{ ++ struct panel_drv_data *ddata = to_panel_data(dssdev); ++ struct omap_dss_device *in = ddata->in; ++ int err; ++ ++ WARN_ON(!omapdss_device_is_connected(dssdev)); ++ if (!omapdss_device_is_connected(dssdev)) ++ return; ++ ++ WARN_ON(dst != dssdev->dst); ++ if (dst != dssdev->dst) ++ return; ++ ++ dst->src = NULL; ++ dssdev->dst = NULL; ++ ++ /* Move from ENABLED -> LOW Power state */ ++ err = sil9022_write_reg(dssdev, HDMI_TPI_POWER_STATE_CTRL_REG, ++ TPI_AVI_POWER_STATE_D3); ++ if (err < 0) { ++ dev_err(dssdev->dev, "ERROR: Setting device power state to D3\n"); ++ } ++ ++ in->ops.dpi->disconnect(in, &ddata->dssdev); ++ return; ++ ++} ++ ++static int sil9022_enable(struct omap_dss_device *dssdev) ++{ ++ struct panel_drv_data *ddata = to_panel_data(dssdev); ++ struct omap_dss_device *in = ddata->in; ++ int r; ++ ++ dev_err(dssdev->dev, "ENABLE\n"); ++ ++ if (!omapdss_device_is_connected(dssdev)) ++ return -ENODEV; ++ ++ if (omapdss_device_is_enabled(dssdev)) ++ return 0; ++ ++ in->ops.dpi->set_timings(in, &ddata->timings); ++ in->ops.dpi->set_data_lines(in, ddata->data_lines); ++ ++ r = in->ops.dpi->enable(in); ++ if (r) ++ return r; ++ ++ if (gpio_is_valid(ddata->reset_gpio)) ++ gpio_set_value_cansleep(ddata->reset_gpio, 0); ++ ++ r = sil9022_hw_enable(dssdev); ++ if (r) ++ return r; ++ ++ dssdev->state = OMAP_DSS_DISPLAY_ACTIVE; ++ return 0; ++} ++ ++static void sil9022_disable(struct omap_dss_device *dssdev) ++{ ++ struct panel_drv_data *ddata = to_panel_data(dssdev); ++ struct omap_dss_device *in = ddata->in; ++ ++ if (!omapdss_device_is_enabled(dssdev)) ++ return; ++ ++ if (!sil9022_hw_disable(dssdev)) ++ return; ++ ++ if (gpio_is_valid(ddata->reset_gpio)) ++ gpio_set_value_cansleep(ddata->reset_gpio, 1); ++ ++ in->ops.dpi->disable(in); ++ ++ dssdev->state = OMAP_DSS_DISPLAY_DISABLED; ++ return; ++} ++ ++static void sil9022_set_timings(struct omap_dss_device *dssdev, ++ struct omap_video_timings *timings) ++{ ++ struct panel_drv_data *ddata = to_panel_data(dssdev); ++ struct omap_dss_device *in = ddata->in; ++ struct omap_video_timings *sil9022_timings = timings; ++ ++ /* update DPI specific timing info */ ++ sil9022_timings->data_pclk_edge = OMAPDSS_DRIVE_SIG_RISING_EDGE; ++ sil9022_timings->de_level = OMAPDSS_SIG_ACTIVE_HIGH; ++ sil9022_timings->sync_pclk_edge = OMAPDSS_DRIVE_SIG_OPPOSITE_EDGES; ++ ddata->timings = *sil9022_timings; ++ dssdev->panel.timings = *sil9022_timings; ++ ++ in->ops.dpi->set_timings(in, sil9022_timings); ++ return; ++} ++ ++static void sil9022_get_timings(struct omap_dss_device *dssdev, ++ struct omap_video_timings *timings) ++{ ++ struct panel_drv_data *ddata = to_panel_data(dssdev); ++ *timings = ddata->timings; ++ return; ++} ++ ++static int sil9022_check_timings(struct omap_dss_device *dssdev, ++ struct omap_video_timings *timings) ++{ ++ struct panel_drv_data *ddata = to_panel_data(dssdev); ++ struct omap_dss_device *in = ddata->in; ++ struct omap_video_timings *sil9022_timings = timings; ++ ++ /* update DPI specific timing info */ ++ sil9022_timings->data_pclk_edge = OMAPDSS_DRIVE_SIG_RISING_EDGE; ++ sil9022_timings->de_level = OMAPDSS_SIG_ACTIVE_HIGH; ++ sil9022_timings->sync_pclk_edge = OMAPDSS_DRIVE_SIG_OPPOSITE_EDGES; ++ ++ return in->ops.dpi->check_timings(in, sil9022_timings); ++} ++ ++static int sil9022_read_edid(struct omap_dss_device *dssdev, ++ u8 *edid, int len) ++{ ++ ++ int err = 0; ++ unsigned int val = 0; ++ int retries = 0; ++ u16 out_len = 0; ++ int i2c_client_addr; ++ struct panel_drv_data *ddata = to_panel_data(dssdev); ++ struct i2c_client *client = ddata->i2c_client; ++ ++ len = (len < HDMI_EDID_MAX_LENGTH) ? len : HDMI_EDID_MAX_LENGTH; ++ ++ /* Request DDC bus access to read EDID info from HDTV */ ++ dev_info(&client->dev, "Reading HDMI EDID\n"); ++ ++ val = 0; ++ err = sil9022_read_reg(dssdev, 0x3D, &val); ++ if (err < 0) { ++ dev_err(&client->dev, ++ "ERROR: Reading Monitor Status register\n"); ++ return err; ++ } ++ ++ if (val & 0x2) ++ dev_err(&client->dev, " MONITOR PRESENT \n"); ++ else ++ dev_err(&client->dev, " MONITOR NOT PRESENT \n"); ++ ++ /* Disable TMDS clock */ ++ val = 0x11; ++ err = sil9022_write_reg(dssdev, HDMI_SYS_CTRL_DATA_REG, val); ++ if (err < 0) { ++ dev_err(&client->dev, ++ "ERROR: Failed to disable TMDS clock\n"); ++ return err; ++ } ++ ++ val = 0; ++ ++ /* Read TPI system control register*/ ++ err = sil9022_read_reg(dssdev, HDMI_SYS_CTRL_DATA_REG, &val); ++ if (err < 0) { ++ dev_err(&client->dev, ++ "ERROR: Reading DDC BUS REQUEST\n"); ++ return err; ++ } ++ ++ /* The host writes 0x1A[2]=1 to request the ++ * DDC(Display Data Channel) bus ++ */ ++ val |= TPI_SYS_CTRL_DDC_BUS_REQUEST; ++ err = sil9022_write_reg(dssdev, HDMI_SYS_CTRL_DATA_REG, val); ++ if (err < 0) { ++ dev_err(&client->dev, ++ "ERROR: Writing DDC BUS REQUEST\n"); ++ return err; ++ } ++ ++ /* Poll for bus DDC Bus control to be granted */ ++ dev_info(&client->dev, "Poll for DDC bus access\n"); ++ val = 0; ++ do { ++ err = sil9022_read_reg(dssdev, HDMI_SYS_CTRL_DATA_REG, &val); ++ if (retries++ > 100) ++ return err; ++ ++ } while ((val & TPI_SYS_CTRL_DDC_BUS_GRANTED) == 0); ++ ++ /* Close the switch to the DDC */ ++ val |= TPI_SYS_CTRL_DDC_BUS_REQUEST | TPI_SYS_CTRL_DDC_BUS_GRANTED; ++ err = sil9022_write_reg(dssdev, HDMI_SYS_CTRL_DATA_REG, val); ++ if (err < 0) { ++ dev_err(&client->dev, ++ "<%s> ERROR: Close switch to DDC BUS REQUEST\n", ++ __func__); ++ return err; ++ } ++ ++ memset(edid, 0, len); ++ /* change I2C SetSlaveAddress to HDMI_I2C_MONITOR_ADDRESS */ ++ /* Read the EDID structure from the monitor I2C address */ ++ i2c_client_addr = client->addr; ++ client->addr = HDMI_I2C_MONITOR_ADDRESS; ++ err = sil9022_blockread_reg(client, 1, len, ++ 0x00, edid, &out_len); ++ if (err < 0 || out_len <= 0) { ++ dev_err(&client->dev, "ERROR: Reading EDID\n"); ++ return err; ++ } ++ ++ /* Release DDC bus access */ ++ client->addr = i2c_client_addr; ++ val &= ~(TPI_SYS_CTRL_DDC_BUS_REQUEST | TPI_SYS_CTRL_DDC_BUS_GRANTED); ++ ++ retries = 0; ++ do { ++ err = sil9022_write_reg(dssdev, HDMI_SYS_CTRL_DATA_REG, val); ++ if (err >= 0) ++ break; ++ retries++; ++ } while (retries < 5); ++ if (err < 0) { ++ dev_err(&client->dev, "ERROR: Releasing DDC Bus Access\n"); ++ return err; ++ } ++ ++ print_hex_dump(KERN_ERR, "\t", DUMP_PREFIX_NONE, 16, 1, edid, len, 0); ++ ++ return 0; ++ ++} ++ ++static bool sil9022_detect(struct omap_dss_device *dssdev) ++{ ++ /* Hot plug detection is not implemented */ ++ /* Hence we assume monitor connected */ ++ /* This will be fixed once HPD / polling is implemented */ ++ return true; ++} ++ ++static bool sil9022_audio_supported(struct omap_dss_device *dssdev) ++{ ++ /* Audio configuration not present, hence returning false */ ++ return false; ++} ++ ++static const struct omapdss_hdmi_ops sil9022_hdmi_ops = { ++ .connect = sil9022_connect, ++ .disconnect = sil9022_disconnect, ++ ++ .enable = sil9022_enable, ++ .disable = sil9022_disable, ++ ++ .check_timings = sil9022_check_timings, ++ .set_timings = sil9022_set_timings, ++ .get_timings = sil9022_get_timings, ++ ++ .read_edid = sil9022_read_edid, ++ .detect = sil9022_detect, ++ ++ .audio_supported = sil9022_audio_supported, ++ /* Yet to implement audio ops */ ++ /* For now audio_supported ops to return false */ ++}; ++ ++ ++static int sil9022_probe_of(struct i2c_client *client) ++{ ++ struct panel_drv_data *ddata = dev_get_drvdata(&client->dev); ++ struct device_node *node = client->dev.of_node; ++ struct device_node *src_node; ++ struct omap_dss_device *dssdev, *in; ++ ++ int r, reset_gpio, datalines; ++ ++ src_node = of_parse_phandle(node, "video-source", 0); ++ if (!src_node) { ++ dev_err(&client->dev, "failed to parse video source\n"); ++ return -ENODEV; ++ } ++ ++ in = omap_dss_find_output_by_node(src_node); ++ if (in == NULL) { ++ dev_err(&client->dev, "failed to find video source\n"); ++ return -EPROBE_DEFER; ++ } ++ ddata->in = in; ++ ++ reset_gpio = of_get_named_gpio(node, "reset-gpio", 0); ++ ++ if (gpio_is_valid(reset_gpio) || reset_gpio == -ENOENT) { ++ ddata->reset_gpio = reset_gpio; ++ } else { ++ dev_err(&client->dev, "failed to parse lcdorhdmi gpio\n"); ++ return reset_gpio; ++ } ++ ++ r = of_property_read_u32(node, "data-lines", &datalines); ++ if (r) { ++ dev_err(&client->dev, "failed to parse datalines\n"); ++ return r; ++ } ++ ++ ddata->data_lines = datalines; ++ ddata->reset_gpio = reset_gpio; ++ dssdev = &ddata->dssdev; ++ ++ return 0; ++ ++} ++static int sil9022_probe_pdata(struct i2c_client *client) ++{ ++ struct encoder_sil9022_platform_data *pdata; ++ struct panel_drv_data *ddata = dev_get_drvdata(&client->dev); ++ struct omap_dss_device *dssdev, *in; ++ pdata = dev_get_platdata(&client->dev); ++ ++ ddata->reset_gpio = pdata->reset_gpio; ++ ddata->data_lines = pdata->data_lines; ++ ++ in = omap_dss_find_output(pdata->source); ++ if (in == NULL) { ++ dev_err(&client->dev, "Failed to find video source\n"); ++ return -ENODEV; ++ } ++ ++ ddata->in = in; ++ dssdev = &ddata->dssdev; ++ dssdev->name = pdata->name; ++ ++ return 0; ++} ++ ++static int sil9022_probe(struct i2c_client *client, ++ const struct i2c_device_id *id) ++{ ++ struct panel_drv_data *ddata; ++ struct omap_dss_device *dssdev; ++ struct regmap *regmap; ++ int err = 0; ++ ++ regmap = devm_regmap_init_i2c(client, &sil9022_regmap_config); ++ if (IS_ERR(regmap)) { ++ err = PTR_ERR(regmap); ++ dev_err(&client->dev, "Failed to init regmap: %d\n", err); ++ return err; ++ } ++ ++ ddata = devm_kzalloc(&client->dev, sizeof(*ddata), GFP_KERNEL); ++ if (ddata == NULL) ++ return -ENOMEM; ++ ++ dev_set_drvdata(&client->dev, ddata); ++ ++ if (dev_get_platdata(&client->dev)) { ++ err = sil9022_probe_pdata(client); ++ if (err) ++ return err; ++ } else if (client->dev.of_node) { ++ err = sil9022_probe_of(client); ++ if (err) ++ return err; ++ } else { ++ return -ENODEV; ++ } ++ ++ if (gpio_is_valid(ddata->reset_gpio)) { ++ err = devm_gpio_request_one(&client->dev, ddata->reset_gpio, ++ GPIOF_OUT_INIT_HIGH, "Sil9022-Encoder"); ++ if (err) ++ goto err_gpio; ++ } ++ ++ ddata->regmap = regmap; ++ ddata->i2c_client = client; ++ dssdev = &ddata->dssdev; ++ dssdev->dev = &client->dev; ++ dssdev->ops.hdmi = &sil9022_hdmi_ops; ++ dssdev->type = OMAP_DISPLAY_TYPE_DPI; ++ dssdev->output_type = OMAP_DISPLAY_TYPE_HDMI; ++ dssdev->owner = THIS_MODULE; ++ dssdev->phy.dpi.data_lines = ddata->data_lines; ++ err = omapdss_register_output(dssdev); ++ if (err) { ++ dev_err(&client->dev, "Failed to register output\n"); ++ goto err_reg; ++ } ++ ++ /* Read sil9022 chip version */ ++ err = sil9022_probe_chip_version(dssdev); ++ if (err) { ++ dev_err(&client->dev, "Failed to read CHIP VERSION\n"); ++ goto err_i2c; ++ } ++ ++ return 0; ++ ++err_gpio: ++err_reg: ++err_i2c: ++ omap_dss_put_device(ddata->in); ++ return err; ++} ++ ++ ++static int sil9022_remove(struct i2c_client *client) ++{ ++ struct panel_drv_data *ddata = dev_get_drvdata(&client->dev); ++ struct omap_dss_device *dssdev = &ddata->dssdev; ++ ++ omapdss_unregister_output(&ddata->dssdev); ++ ++ WARN_ON(omapdss_device_is_enabled(dssdev)); ++ if (omapdss_device_is_enabled(dssdev)) ++ sil9022_disable(dssdev); ++ ++ WARN_ON(omapdss_device_is_connected(dssdev)); ++ if (omapdss_device_is_connected(dssdev)) ++ sil9022_disconnect(dssdev, dssdev->dst); ++ ++ omap_dss_put_device(ddata->in); ++ ++ if (!client->adapter) { ++ dev_err(&client->dev, "No HDMI Device\n"); ++ return -ENODEV; ++ } ++ ++ return 0; ++} ++ ++static const struct i2c_device_id sil9022_id[] = { ++ { SIL9022_DRV_NAME, 0 }, ++ { }, ++}; ++ ++MODULE_DEVICE_TABLE(i2c, sil9022_id); ++ ++static struct i2c_driver sil9022_driver = { ++ .driver = { ++ .name = SIL9022_DRV_NAME, ++ .owner = THIS_MODULE, ++ }, ++ .probe = sil9022_probe, ++ .remove = sil9022_remove, ++ .id_table = sil9022_id, ++}; ++ ++module_i2c_driver(sil9022_driver); ++ ++MODULE_AUTHOR("Sathya Prakash M R <sathyap@ti.com>"); ++MODULE_DESCRIPTION("Sil9022 DPI to HDMI encoder Driver"); ++MODULE_LICENSE("GPL"); +--- /dev/null ++++ b/drivers/video/omap2/displays-new/encoder-sil9022.h +@@ -0,0 +1,123 @@ ++/* ++ * drivers/video/omap2/displays-new/encoder-sil9022.c ++ * ++ * Copyright (C) 2013 Texas Instruments ++ * Author : Sathya Prakash M R <sathyap@ti.com> ++ * ++ * This file is licensed under the terms of the GNU General Public License ++ * version 2. This program is licensed "as is" without any warranty of any ++ * kind, whether express or implied. ++ * ++ */ ++ ++#ifndef _SI9022_H_ ++#define _SI9022_H_ ++ ++#define SIL9022_DRV_NAME "sii9022" ++ ++#define SIL9022_REG_CHIPID0 0x1B ++#define SIL9022_REG_TPI_RQB 0xC7 ++#define SIL9022_CHIPID_902x 0xB0 ++ ++#define HDMI_I2C_MONITOR_ADDRESS 0x50 ++ ++/* HDMI EDID Length */ ++#define HDMI_EDID_MAX_LENGTH 256 ++ ++#define VERTICAL_FREQ 0x3C ++ ++/* HDMI TPI Registers */ ++#define HDMI_TPI_VIDEO_DATA_BASE_REG 0x00 ++#define HDMI_TPI_PIXEL_CLK_LSB_REG (HDMI_TPI_VIDEO_DATA_BASE_REG + 0x00) ++#define HDMI_TPI_PIXEL_CLK_MSB_REG (HDMI_TPI_VIDEO_DATA_BASE_REG + 0x01) ++#define HDMI_TPI_VFREQ_LSB_REG (HDMI_TPI_VIDEO_DATA_BASE_REG + 0x02) ++#define HDMI_TPI_VFREQ_MSB_REG (HDMI_TPI_VIDEO_DATA_BASE_REG + 0x03) ++#define HDMI_TPI_PIXELS_LSB_REG (HDMI_TPI_VIDEO_DATA_BASE_REG + 0x04) ++#define HDMI_TPI_PIXELS_MSB_REG (HDMI_TPI_VIDEO_DATA_BASE_REG + 0x05) ++#define HDMI_TPI_LINES_LSB_REG (HDMI_TPI_VIDEO_DATA_BASE_REG + 0x06) ++#define HDMI_TPI_LINES_MSB_REG (HDMI_TPI_VIDEO_DATA_BASE_REG + 0x07) ++ ++#define HDMI_TPI_PIXEL_REPETITION_REG 0x08 ++ ++#define HDMI_TPI_AVI_INOUT_BASE_REG 0x09 ++#define HDMI_TPI_AVI_IN_FORMAT_REG (HDMI_TPI_AVI_INOUT_BASE_REG + 0x00) ++#define HDMI_TPI_AVI_OUT_FORMAT_REG (HDMI_TPI_AVI_INOUT_BASE_REG + 0x01) ++ ++#define HDMI_SYS_CTRL_DATA_REG 0x1A ++#define HDMI_TPI_POWER_STATE_CTRL_REG 0x1E ++#define HDMI_TPI_DEVICE_POWER_STATE_DATA 0x1E ++ ++ ++/* HDCP */ ++#define HDMI_TPI_HDCP_QUERYDATA_REG 0x29 ++#define HDMI_TPI_HDCP_CONTROLDATA_REG 0x2A ++ ++/* HDMI_TPI_DEVICE_ID_REG */ ++#define TPI_DEVICE_ID 0xB0 ++ ++/* HDMI_TPI_REVISION_REG */ ++#define TPI_REVISION 0x00 ++ ++/* HDMI_TPI_ID_BYTE2_REG */ ++#define TPI_ID_BYTE2_VALUE 0x00 ++ ++/* HDMI_SYS_CTRL_DATA_REG */ ++#define TPI_SYS_CTRL_POWER_DOWN (1 << 4) ++#define TPI_SYS_CTRL_POWER_ACTIVE (0 << 4) ++#define TPI_SYS_CTRL_AV_MUTE (1 << 3) ++#define TPI_SYS_CTRL_DDC_BUS_REQUEST (1 << 2) ++#define TPI_SYS_CTRL_DDC_BUS_GRANTED (1 << 1) ++#define TPI_SYS_CTRL_OUTPUT_MODE_HDMI (1 << 0) ++#define TPI_SYS_CTRL_OUTPUT_MODE_DVI (0 << 0) ++ ++/* HDMI_TPI_PIXEL_REPETITION */ ++#define TPI_AVI_PIXEL_REP_BUS_24BIT (1 << 5) ++#define TPI_AVI_PIXEL_REP_BUS_12BIT (0 << 5) ++#define TPI_AVI_PIXEL_REP_RISING_EDGE (1 << 4) ++#define TPI_AVI_PIXEL_REP_FALLING_EDGE (0 << 4) ++#define TPI_AVI_PIXEL_REP_4X (3 << 0) ++#define TPI_AVI_PIXEL_REP_2X (1 << 0) ++#define TPI_AVI_PIXEL_REP_NONE (0 << 0) ++ ++/*Ratio of TDMS Clock to input Video Clock*/ ++#define TPI_CLK_RATIO_HALF (0 << 6) ++#define TPI_CLK_RATIO_1X (1 << 6) ++#define TPI_CLK_RATIO_2X (2 << 6) ++#define TPI_CLK_RATIO_4X (3 << 6) ++ ++ ++/* HDMI_TPI_AVI_INPUT_FORMAT */ ++#define TPI_AVI_INPUT_BITMODE_12BIT (1 << 7) ++#define TPI_AVI_INPUT_BITMODE_8BIT (0 << 7) ++#define TPI_AVI_INPUT_DITHER (1 << 6) ++#define TPI_AVI_INPUT_RANGE_LIMITED (2 << 2) ++#define TPI_AVI_INPUT_RANGE_FULL (1 << 2) ++#define TPI_AVI_INPUT_RANGE_AUTO (0 << 2) ++#define TPI_AVI_INPUT_COLORSPACE_BLACK (3 << 0) ++#define TPI_AVI_INPUT_COLORSPACE_YUV422 (2 << 0) ++#define TPI_AVI_INPUT_COLORSPACE_YUV444 (1 << 0) ++#define TPI_AVI_INPUT_COLORSPACE_RGB (0 << 0) ++ ++ ++/* HDMI_TPI_AVI_OUTPUT_FORMAT */ ++#define TPI_AVI_OUTPUT_CONV_BT709 (1 << 4) ++#define TPI_AVI_OUTPUT_CONV_BT601 (0 << 4) ++#define TPI_AVI_OUTPUT_RANGE_LIMITED (2 << 2) ++#define TPI_AVI_OUTPUT_RANGE_FULL (1 << 2) ++#define TPI_AVI_OUTPUT_RANGE_AUTO (0 << 2) ++#define TPI_AVI_OUTPUT_COLORSPACE_RGBDVI (3 << 0) ++#define TPI_AVI_OUTPUT_COLORSPACE_YUV422 (2 << 0) ++#define TPI_AVI_OUTPUT_COLORSPACE_YUV444 (1 << 0) ++#define TPI_AVI_OUTPUT_COLORSPACE_RGBHDMI (0 << 0) ++ ++/* HDMI_TPI_DEVICE_POWER_STATE */ ++#define TPI_AVI_POWER_STATE_D3 (3 << 0) ++#define TPI_AVI_POWER_STATE_D2 (2 << 0) ++#define TPI_AVI_POWER_STATE_D0 (0 << 0) ++ ++struct regmap_config sil9022_regmap_config = { ++ .reg_bits = 8, ++ .val_bits = 8, ++}; ++ ++#endif +--- a/drivers/video/omap2/displays-new/encoder-tfp410.c ++++ b/drivers/video/omap2/displays-new/encoder-tfp410.c +@@ -13,6 +13,7 @@ + #include <linux/module.h> + #include <linux/platform_device.h> + #include <linux/slab.h> ++#include <linux/of_gpio.h> + + #include <video/omapdss.h> + #include <video/omap-panel-data.h> +@@ -179,6 +180,47 @@ static int tfp410_probe_pdata(struct pla + return 0; + } + ++static int tfp410_probe_of(struct platform_device *pdev) ++{ ++ struct panel_drv_data *ddata = platform_get_drvdata(pdev); ++ struct device_node *node = pdev->dev.of_node; ++ struct omap_dss_device *in; ++ struct device_node *src_node; ++ int r, gpio, datalines; ++ ++ src_node = of_parse_phandle(node, "video-source", 0); ++ if (!src_node) { ++ dev_err(&pdev->dev, "failed to parse video source\n"); ++ return -ENODEV; ++ } ++ ++ in = omap_dss_find_output_by_node(src_node); ++ if (in == NULL) { ++ dev_err(&pdev->dev, "failed to find video source\n"); ++ return -EPROBE_DEFER; ++ } ++ ddata->in = in; ++ ++ gpio = of_get_gpio(node, 0); ++ ++ if (gpio_is_valid(gpio) || gpio == -ENOENT) { ++ ddata->pd_gpio = gpio; ++ } else { ++ dev_err(&pdev->dev, "failed to parse PD gpio\n"); ++ return gpio; ++ } ++ ++ r = of_property_read_u32(node, "data-lines", &datalines); ++ if (r) { ++ dev_err(&pdev->dev, "failed to parse datalines\n"); ++ return r; ++ } ++ ++ ddata->data_lines = datalines; ++ ++ return 0; ++} ++ + static int tfp410_probe(struct platform_device *pdev) + { + struct panel_drv_data *ddata; +@@ -195,6 +237,10 @@ static int tfp410_probe(struct platform_ + r = tfp410_probe_pdata(pdev); + if (r) + return r; ++ } else if (pdev->dev.of_node) { ++ r = tfp410_probe_of(pdev); ++ if (r) ++ return r; + } else { + return -ENODEV; + } +@@ -251,12 +297,20 @@ static int __exit tfp410_remove(struct p + return 0; + } + ++static const struct of_device_id tfp410_of_match[] = { ++ { .compatible = "ti,tfp410", }, ++ {}, ++}; ++ ++MODULE_DEVICE_TABLE(of, tfp410_of_match); ++ + static struct platform_driver tfp410_driver = { + .probe = tfp410_probe, + .remove = __exit_p(tfp410_remove), + .driver = { + .name = "tfp410", + .owner = THIS_MODULE, ++ .of_match_table = tfp410_of_match, + }, + }; + +--- a/drivers/video/omap2/displays-new/encoder-tpd12s015.c ++++ b/drivers/video/omap2/displays-new/encoder-tpd12s015.c +@@ -15,6 +15,7 @@ + #include <linux/slab.h> + #include <linux/gpio.h> + #include <linux/platform_device.h> ++#include <linux/of_gpio.h> + + #include <video/omapdss.h> + #include <video/omap-panel-data.h> +@@ -289,6 +290,55 @@ static int tpd_probe_pdata(struct platfo + return 0; + } + ++static int tpd_probe_of(struct platform_device *pdev) ++{ ++ struct panel_drv_data *ddata = platform_get_drvdata(pdev); ++ struct device_node *node = pdev->dev.of_node; ++ struct omap_dss_device *in; ++ struct device_node *src_node; ++ int gpio; ++ ++ src_node = of_parse_phandle(node, "video-source", 0); ++ if (!src_node) { ++ dev_err(&pdev->dev, "failed to parse video source\n"); ++ return -ENODEV; ++ } ++ ++ in = omap_dss_find_output_by_node(src_node); ++ if (in == NULL) { ++ dev_err(&pdev->dev, "failed to find video source\n"); ++ return -EPROBE_DEFER; ++ } ++ ddata->in = in; ++ ++ /* CT CP HPD GPIO */ ++ gpio = of_get_gpio(node, 0); ++ if (!gpio_is_valid(gpio)) { ++ dev_err(&pdev->dev, "failed to parse CT CP HPD gpio\n"); ++ return gpio; ++ } ++ ddata->ct_cp_hpd_gpio = gpio; ++ ++ /* LS OE GPIO */ ++ gpio = of_get_gpio(node, 1); ++ if (gpio_is_valid(gpio) || gpio == -ENOENT) { ++ ddata->ls_oe_gpio = gpio; ++ } else { ++ dev_err(&pdev->dev, "failed to parse LS OE gpio\n"); ++ return gpio; ++ } ++ ++ /* HPD GPIO */ ++ gpio = of_get_gpio(node, 2); ++ if (!gpio_is_valid(gpio)) { ++ dev_err(&pdev->dev, "failed to parse HPD gpio\n"); ++ return gpio; ++ } ++ ddata->hpd_gpio = gpio; ++ ++ return 0; ++} ++ + static int tpd_probe(struct platform_device *pdev) + { + struct omap_dss_device *in, *dssdev; +@@ -307,6 +357,10 @@ static int tpd_probe(struct platform_dev + r = tpd_probe_pdata(pdev); + if (r) + return r; ++ } else if (pdev->dev.of_node) { ++ r = tpd_probe_of(pdev); ++ if (r) ++ return r; + } else { + return -ENODEV; + } +@@ -379,12 +433,20 @@ static int __exit tpd_remove(struct plat + return 0; + } + ++static const struct of_device_id tpd_of_match[] = { ++ { .compatible = "ti,tpd12s015", }, ++ {}, ++}; ++ ++MODULE_DEVICE_TABLE(of, tpd_of_match); ++ + static struct platform_driver tpd_driver = { + .probe = tpd_probe, + .remove = __exit_p(tpd_remove), + .driver = { + .name = "tpd12s015", + .owner = THIS_MODULE, ++ .of_match_table = tpd_of_match, + }, + }; + +--- a/drivers/video/omap2/displays-new/Kconfig ++++ b/drivers/video/omap2/displays-new/Kconfig +@@ -12,6 +12,20 @@ config DISPLAY_ENCODER_TPD12S015 + Driver for TPD12S015, which offers HDMI ESD protection and level + shifting. + ++config DISPLAY_DRA_EVM_ENCODER_TPD12S015 ++ tristate "TPD12S015 HDMI ESD protection and level shifter on DRA7 EVM" ++ help ++ Driver for TPD12S015, which offers HDMI ESD protection and level ++ shifting on DRA EVM. ++ ++config DISPLAY_ENCODER_SIL9022 ++ tristate "Sil9022 DPI to HDMI Encoder" ++ depends on I2C ++ help ++ Driver for Silicon Image Sil9022 DPI to HDMI encoder and ++ a brief about Sil9022 can be found here: ++ http://www.semiconductorstore.com/pdf/newsite/siliconimage/SiI9022a_pb.pdf ++ + config DISPLAY_CONNECTOR_DVI + tristate "DVI Connector" + depends on I2C +@@ -71,4 +85,11 @@ config DISPLAY_PANEL_NEC_NL8048HL11 + This NEC NL8048HL11 panel is TFT LCD used in the + Zoom2/3/3630 sdp boards. + ++config DISPLAY_PANEL_TFCS9700 ++ tristate "Three Five DPI panel" ++ depends on I2C ++ help ++ A TFT LCD DPI panel used on the LCD daughter board ++ of Vayu EVM ++ + endmenu +--- a/drivers/video/omap2/displays-new/Makefile ++++ b/drivers/video/omap2/displays-new/Makefile +@@ -1,5 +1,7 @@ + obj-$(CONFIG_DISPLAY_ENCODER_TFP410) += encoder-tfp410.o + obj-$(CONFIG_DISPLAY_ENCODER_TPD12S015) += encoder-tpd12s015.o ++obj-$(CONFIG_DISPLAY_DRA_EVM_ENCODER_TPD12S015) += dra-evm-encoder-tpd12s015.o ++obj-$(CONFIG_DISPLAY_ENCODER_SIL9022) += encoder-sil9022.o + obj-$(CONFIG_DISPLAY_CONNECTOR_DVI) += connector-dvi.o + obj-$(CONFIG_DISPLAY_CONNECTOR_HDMI) += connector-hdmi.o + obj-$(CONFIG_DISPLAY_CONNECTOR_ANALOG_TV) += connector-analog-tv.o +@@ -10,3 +12,4 @@ obj-$(CONFIG_DISPLAY_PANEL_LGPHILIPS_LB0 + obj-$(CONFIG_DISPLAY_PANEL_SHARP_LS037V7DW01) += panel-sharp-ls037v7dw01.o + obj-$(CONFIG_DISPLAY_PANEL_TPO_TD043MTEA1) += panel-tpo-td043mtea1.o + obj-$(CONFIG_DISPLAY_PANEL_NEC_NL8048HL11) += panel-nec-nl8048hl11.o ++obj-$(CONFIG_DISPLAY_PANEL_TFCS9700) += panel-tfcs9700.o +--- a/drivers/video/omap2/displays-new/panel-dpi.c ++++ b/drivers/video/omap2/displays-new/panel-dpi.c +@@ -13,9 +13,12 @@ + #include <linux/module.h> + #include <linux/platform_device.h> + #include <linux/slab.h> ++#include <linux/of.h> ++#include <linux/of_gpio.h> + + #include <video/omapdss.h> + #include <video/omap-panel-data.h> ++#include <video/of_display_timing.h> + + struct panel_drv_data { + struct omap_dss_device dssdev; +@@ -26,6 +29,7 @@ struct panel_drv_data { + struct omap_video_timings videomode; + + int backlight_gpio; ++ bool backlight_enable; + int enable_gpio; + }; + +@@ -81,7 +85,7 @@ static int panel_dpi_enable(struct omap_ + gpio_set_value_cansleep(ddata->enable_gpio, 1); + + if (gpio_is_valid(ddata->backlight_gpio)) +- gpio_set_value_cansleep(ddata->backlight_gpio, 1); ++ gpio_set_value_cansleep(ddata->backlight_gpio, ddata->backlight_enable); + + dssdev->state = OMAP_DSS_DISPLAY_ACTIVE; + +@@ -100,7 +104,7 @@ static void panel_dpi_disable(struct oma + gpio_set_value_cansleep(ddata->enable_gpio, 0); + + if (gpio_is_valid(ddata->backlight_gpio)) +- gpio_set_value_cansleep(ddata->backlight_gpio, 0); ++ gpio_set_value_cansleep(ddata->backlight_gpio, ~(ddata->backlight_enable)); + + in->ops.dpi->disable(in); + +@@ -182,6 +186,73 @@ static int panel_dpi_probe_pdata(struct + return 0; + } + ++static int panel_dpi_probe_of(struct platform_device *pdev) ++{ ++ struct panel_drv_data *ddata = platform_get_drvdata(pdev); ++ struct device_node *node = pdev->dev.of_node; ++ struct omap_dss_device *in; ++ struct device_node *src_node; ++ int r, datalines; ++ struct display_timing timing; ++ struct videomode vm; ++ int gpio; ++ enum of_gpio_flags gpio_flags; ++ ++ src_node = of_parse_phandle(node, "video-source", 0); ++ if (!src_node) { ++ dev_err(&pdev->dev, "failed to parse video source\n"); ++ return -ENODEV; ++ } ++ ++ in = omap_dss_find_output_by_node(src_node); ++ if (in == NULL) { ++ dev_err(&pdev->dev, "failed to find video source\n"); ++ return -EPROBE_DEFER; ++ } ++ ddata->in = in; ++ ++ r = of_property_read_u32(node, "data-lines", &datalines); ++ if (r) { ++ dev_err(&pdev->dev, "failed to parse datalines\n"); ++ return r; ++ } ++ ++ ddata->data_lines = datalines; ++ ++ gpio = of_get_gpio(node, 0); ++ if (gpio_is_valid(gpio) || gpio == -ENOENT) { ++ ddata->enable_gpio = gpio; ++ } else { ++ dev_err(&pdev->dev, "failed to parse enable gpio\n"); ++ return gpio; ++ } ++ ++ gpio = of_get_gpio_flags(node, 1, &gpio_flags); ++ ++ if (gpio_is_valid(gpio) || gpio == -ENOENT) { ++ ddata->backlight_gpio = gpio; ++ } else { ++ dev_err(&pdev->dev, "failed to parse backlight gpio\n"); ++ return gpio; ++ } ++ ++ if (gpio_flags == OF_GPIO_ACTIVE_LOW) ++ ddata->backlight_enable = 0; ++ else ++ ddata->backlight_enable = 1; ++ ++ r = of_get_display_timing(node, "panel-timing", &timing); ++ if (r) { ++ dev_err(&pdev->dev, "failed to get video timing\n"); ++ return r; ++ } ++ ++ videomode_from_timing(&timing, &vm); ++ videomode_to_omap_video_timings(&vm, &ddata->videomode); ++ ++ return 0; ++} ++ + static int panel_dpi_probe(struct platform_device *pdev) + { + struct panel_drv_data *ddata; +@@ -198,6 +269,10 @@ static int panel_dpi_probe(struct platfo + r = panel_dpi_probe_pdata(pdev); + if (r) + return r; ++ } else if (pdev->dev.of_node) { ++ r = panel_dpi_probe_of(pdev); ++ if (r) ++ return r; + } else { + return -ENODEV; + } +@@ -254,12 +329,20 @@ static int __exit panel_dpi_remove(struc + return 0; + } + ++static const struct of_device_id panel_dpi_of_match[] = { ++ { .compatible = "panel-dpi", }, ++ {}, ++}; ++ ++MODULE_DEVICE_TABLE(of, panel_dpi_of_match); ++ + static struct platform_driver panel_dpi_driver = { + .probe = panel_dpi_probe, + .remove = __exit_p(panel_dpi_remove), + .driver = { + .name = "panel-dpi", + .owner = THIS_MODULE, ++ .of_match_table = panel_dpi_of_match, + }, + }; + +--- a/drivers/video/omap2/displays-new/panel-dsi-cm.c ++++ b/drivers/video/omap2/displays-new/panel-dsi-cm.c +@@ -22,6 +22,8 @@ + #include <linux/sched.h> + #include <linux/slab.h> + #include <linux/workqueue.h> ++#include <linux/of_device.h> ++#include <linux/of_gpio.h> + + #include <video/omapdss.h> + #include <video/omap-panel-data.h> +@@ -1156,6 +1158,79 @@ static int dsicm_probe_pdata(struct plat + return 0; + } + ++static int dsicm_probe_of(struct platform_device *pdev) ++{ ++ struct device_node *node = pdev->dev.of_node; ++ struct panel_drv_data *ddata = platform_get_drvdata(pdev); ++ struct omap_dss_device *in; ++ struct property *prop; ++ struct device_node *src_node; ++ u32 lane_arr[10]; ++ int gpio, len, num_pins; ++ int r, i; ++ ++ src_node = of_parse_phandle(node, "video-source", 0); ++ if (!src_node) { ++ dev_err(&pdev->dev, "failed to parse video source\n"); ++ return -ENODEV; ++ } ++ ++ in = omap_dss_find_output_by_node(src_node); ++ if (in == NULL) { ++ dev_err(&pdev->dev, "failed to find video source\n"); ++ return -EPROBE_DEFER; ++ } ++ ddata->in = in; ++ ++ gpio = of_get_gpio(node, 0); ++ if (!gpio_is_valid(gpio)) { ++ dev_err(&pdev->dev, "failed to parse reset gpio\n"); ++ return gpio; ++ } ++ ddata->reset_gpio = gpio; ++ ++ if (of_gpio_count(node) > 1) { ++ gpio = of_get_gpio(node, 1); ++ ++ if (gpio_is_valid(gpio) || gpio == -ENOENT) { ++ ddata->ext_te_gpio = gpio; ++ } else { ++ dev_err(&pdev->dev, "failed to parse TE gpio\n"); ++ return gpio; ++ } ++ } else { ++ ddata->ext_te_gpio = -1; ++ } ++ ++ prop = of_find_property(node, "lanes", &len); ++ if (prop == NULL) { ++ dev_err(&pdev->dev, "failed to find lane data\n"); ++ return -EINVAL; ++ } ++ ++ num_pins = len / sizeof(u32); ++ ++ if (num_pins < 4 || num_pins % 2 != 0 ++ || num_pins > ARRAY_SIZE(lane_arr)) { ++ dev_err(&pdev->dev, "bad number of lanes\n"); ++ return -EINVAL; ++ } ++ ++ r = of_property_read_u32_array(node, "lanes", lane_arr, num_pins); ++ if (r) { ++ dev_err(&pdev->dev, "failed to read lane data\n"); ++ return r; ++ } ++ ++ ddata->pin_config.num_pins = num_pins; ++ for (i = 0; i < num_pins; ++i) ++ ddata->pin_config.pins[i] = (int)lane_arr[i]; ++ ++ /* TODO: ulps, backlight */ ++ ++ return 0; ++} ++ + static int dsicm_probe(struct platform_device *pdev) + { + struct backlight_properties props; +@@ -1178,6 +1253,10 @@ static int dsicm_probe(struct platform_d + r = dsicm_probe_pdata(pdev); + if (r) + return r; ++ } else if (pdev->dev.of_node) { ++ r = dsicm_probe_of(pdev); ++ if (r) ++ return r; + } else { + return -ENODEV; + } +@@ -1320,12 +1399,20 @@ static int __exit dsicm_remove(struct pl + return 0; + } + ++static const struct of_device_id dsicm_of_match[] = { ++ { .compatible = "panel-dsi-cm", }, ++ {}, ++}; ++ ++MODULE_DEVICE_TABLE(of, dsicm_of_match); ++ + static struct platform_driver dsicm_driver = { + .probe = dsicm_probe, + .remove = __exit_p(dsicm_remove), + .driver = { + .name = "panel-dsi-cm", + .owner = THIS_MODULE, ++ .of_match_table = dsicm_of_match, + }, + }; + +--- /dev/null ++++ b/drivers/video/omap2/displays-new/panel-tfcs9700.c +@@ -0,0 +1,387 @@ ++/* ++ * TLC59108 TFC-S9700 Panel Driver ++ * ++ * Copyright (C) 2013 Texas Instruments ++ * Author: Tomi Valkeinen <tomi.valkeinen@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/gpio.h> ++#include <linux/module.h> ++#include <linux/platform_device.h> ++#include <linux/slab.h> ++#include <linux/of.h> ++#include <linux/of_gpio.h> ++#include <linux/i2c.h> ++#include <linux/regmap.h> ++#include <linux/delay.h> ++ ++#include <video/omapdss.h> ++#include <video/omap-panel-data.h> ++#include <video/of_display_timing.h> ++ ++#define TLC_NAME "tlc59108" ++#define TLC_I2C_ADDR 0x40 ++ ++#define TLC59108_MODE1 0x00 ++#define TLC59108_PWM2 0x04 ++#define TLC59108_LEDOUT0 0x0c ++#define TLC59108_LEDOUT1 0x0d ++ ++struct panel_drv_data { ++ struct omap_dss_device dssdev; ++ struct omap_dss_device *in; ++ ++ int data_lines; ++ struct omap_video_timings videomode; ++ ++ int enable_gpio; ++ struct regmap *regmap; ++}; ++ ++static const struct omap_video_timings tfc_s9700_timings = { ++ .x_res = 800, ++ .y_res = 480, ++ ++ .pixel_clock = 29232, ++ ++ .hfp = 41, ++ .hsw = 49, ++ .hbp = 41, ++ ++ .vfp = 13, ++ .vsw = 4, ++ .vbp = 29, ++ ++ .vsync_level = OMAPDSS_SIG_ACTIVE_LOW, ++ .hsync_level = OMAPDSS_SIG_ACTIVE_LOW, ++ .data_pclk_edge = OMAPDSS_DRIVE_SIG_RISING_EDGE, ++ .de_level = OMAPDSS_SIG_ACTIVE_HIGH, ++ .sync_pclk_edge = OMAPDSS_DRIVE_SIG_OPPOSITE_EDGES, ++}; ++ ++static int tlc_init(struct panel_drv_data *ddata) ++{ ++ struct regmap *map = ddata->regmap; ++ ++ /* init the TLC chip */ ++ regmap_write(map, TLC59108_MODE1, 0x01); ++ ++ /* ++ * set LED1(AVDD) to ON state(default), enable LED2 in PWM mode, enable ++ * LED0 to OFF state ++ */ ++ regmap_write(map, TLC59108_LEDOUT0, 0x21); ++ ++ /* set LED2 PWM to full freq */ ++ regmap_write(map, TLC59108_PWM2, 0xff); ++ ++ /* set LED4(UPDN) and LED6(MODE3) to OFF state */ ++ regmap_write(map, TLC59108_LEDOUT1, 0x11); ++ ++ return 0; ++} ++ ++static int tlc_uninit(struct panel_drv_data *ddata) ++{ ++ struct regmap *map = ddata->regmap; ++ ++ /* clear TLC chip regs */ ++ regmap_write(map, TLC59108_PWM2, 0x0); ++ regmap_write(map, TLC59108_LEDOUT0, 0x0); ++ regmap_write(map, TLC59108_LEDOUT1, 0x0); ++ ++ regmap_write(map, TLC59108_MODE1, 0x0); ++ ++ return 0; ++} ++ ++#define to_panel_data(p) container_of(p, struct panel_drv_data, dssdev) ++ ++static int panel_dpi_connect(struct omap_dss_device *dssdev) ++{ ++ struct panel_drv_data *ddata = to_panel_data(dssdev); ++ struct omap_dss_device *in = ddata->in; ++ int r; ++ ++ if (omapdss_device_is_connected(dssdev)) ++ return 0; ++ ++ r = in->ops.dpi->connect(in, dssdev); ++ if (r) ++ return r; ++ ++ return 0; ++} ++ ++static void panel_dpi_disconnect(struct omap_dss_device *dssdev) ++{ ++ struct panel_drv_data *ddata = to_panel_data(dssdev); ++ struct omap_dss_device *in = ddata->in; ++ ++ if (!omapdss_device_is_connected(dssdev)) ++ return; ++ ++ in->ops.dpi->disconnect(in, dssdev); ++} ++ ++static int panel_dpi_enable(struct omap_dss_device *dssdev) ++{ ++ struct panel_drv_data *ddata = to_panel_data(dssdev); ++ struct omap_dss_device *in = ddata->in; ++ int r; ++ ++ if (!omapdss_device_is_connected(dssdev)) ++ return -ENODEV; ++ ++ if (omapdss_device_is_enabled(dssdev)) ++ return 0; ++ ++ in->ops.dpi->set_data_lines(in, ddata->data_lines); ++ in->ops.dpi->set_timings(in, &ddata->videomode); ++ ++ r = in->ops.dpi->enable(in); ++ if (r) ++ return r; ++ ++ tlc_init(ddata); ++ ++ dssdev->state = OMAP_DSS_DISPLAY_ACTIVE; ++ ++ return 0; ++} ++ ++static void panel_dpi_disable(struct omap_dss_device *dssdev) ++{ ++ struct panel_drv_data *ddata = to_panel_data(dssdev); ++ struct omap_dss_device *in = ddata->in; ++ ++ if (!omapdss_device_is_enabled(dssdev)) ++ return; ++ ++ tlc_uninit(ddata); ++ ++ in->ops.dpi->disable(in); ++ ++ dssdev->state = OMAP_DSS_DISPLAY_DISABLED; ++} ++ ++static void panel_dpi_set_timings(struct omap_dss_device *dssdev, ++ struct omap_video_timings *timings) ++{ ++ struct panel_drv_data *ddata = to_panel_data(dssdev); ++ struct omap_dss_device *in = ddata->in; ++ ++ ddata->videomode = *timings; ++ dssdev->panel.timings = *timings; ++ ++ in->ops.dpi->set_timings(in, timings); ++} ++ ++static void panel_dpi_get_timings(struct omap_dss_device *dssdev, ++ struct omap_video_timings *timings) ++{ ++ struct panel_drv_data *ddata = to_panel_data(dssdev); ++ ++ *timings = ddata->videomode; ++} ++ ++static int panel_dpi_check_timings(struct omap_dss_device *dssdev, ++ struct omap_video_timings *timings) ++{ ++ struct panel_drv_data *ddata = to_panel_data(dssdev); ++ struct omap_dss_device *in = ddata->in; ++ ++ return in->ops.dpi->check_timings(in, timings); ++} ++ ++static struct omap_dss_driver panel_dpi_ops = { ++ .connect = panel_dpi_connect, ++ .disconnect = panel_dpi_disconnect, ++ ++ .enable = panel_dpi_enable, ++ .disable = panel_dpi_disable, ++ ++ .set_timings = panel_dpi_set_timings, ++ .get_timings = panel_dpi_get_timings, ++ .check_timings = panel_dpi_check_timings, ++ ++ .get_resolution = omapdss_default_get_resolution, ++}; ++ ++static int tlc_probe_of(struct device *dev) ++{ ++ struct panel_drv_data *ddata = dev_get_drvdata(dev); ++ struct device_node *node = dev->of_node; ++ struct omap_dss_device *in; ++ struct device_node *src_node; ++ int r, datalines; ++ int gpio; ++ ++ src_node = of_parse_phandle(node, "video-source", 0); ++ if (!src_node) { ++ dev_err(dev, "failed to parse video source\n"); ++ return -ENODEV; ++ } ++ ++ in = omap_dss_find_output_by_node(src_node); ++ if (in == NULL) { ++ dev_err(dev, "failed to find video source\n"); ++ return -EPROBE_DEFER; ++ } ++ ++ ddata->in = in; ++ ++ r = of_property_read_u32(node, "data-lines", &datalines); ++ if (r) { ++ dev_err(dev, "failed to parse datalines\n"); ++ return r; ++ } ++ ++ ddata->data_lines = datalines; ++ ++ gpio = of_get_gpio(node, 0); ++ if (gpio_is_valid(gpio) || gpio == -ENOENT) { ++ ddata->enable_gpio = gpio; ++ } else { ++ dev_err(dev, "failed to parse enable gpio\n"); ++ return gpio; ++ } ++ ++ return 0; ++} ++ ++struct regmap_config tlc59108_regmap_config = { ++ .reg_bits = 8, ++ .val_bits = 8, ++}; ++ ++static int tlc59108_i2c_probe(struct i2c_client *client, ++ const struct i2c_device_id *id) ++{ ++ int r; ++ struct regmap *regmap; ++ struct panel_drv_data *ddata; ++ struct device *dev = &client->dev; ++ struct omap_dss_device *dssdev; ++ unsigned int val; ++ ++ ddata = devm_kzalloc(dev, sizeof(*ddata), GFP_KERNEL); ++ if (ddata == NULL) ++ return -ENOMEM; ++ ++ dev_set_drvdata(dev, ddata); ++ ++ r = tlc_probe_of(dev); ++ if (r) ++ return r; ++ ++ ddata->videomode = tfc_s9700_timings; ++ ++ if (gpio_is_valid(ddata->enable_gpio)) { ++ r = devm_gpio_request_one(dev, ddata->enable_gpio, ++ GPIOF_OUT_INIT_LOW, "panel enable"); ++ if (r) ++ goto err_gpio; ++ } ++ ++ regmap = devm_regmap_init_i2c(client, &tlc59108_regmap_config); ++ if (IS_ERR(regmap)) { ++ r = PTR_ERR(regmap); ++ dev_err(dev, "Failed to init regmap: %d\n", r); ++ goto err_gpio; ++ } ++ ++ ddata->regmap = regmap; ++ ++ msleep(10); ++ ++ /* Try to read a TLC register to verify if i2c works */ ++ r = regmap_read(ddata->regmap, TLC59108_MODE1, &val); ++ if (r < 0) { ++ dev_err(dev, "Failed to set MODE1: %d\n", r); ++ return r; ++ } ++ ++ dssdev = &ddata->dssdev; ++ dssdev->dev = dev; ++ dssdev->driver = &panel_dpi_ops; ++ dssdev->type = OMAP_DISPLAY_TYPE_DPI; ++ dssdev->owner = THIS_MODULE; ++ dssdev->panel.timings = ddata->videomode; ++ dssdev->phy.dpi.data_lines = ddata->data_lines; ++ ++ r = omapdss_register_display(dssdev); ++ if (r) { ++ dev_err(dev, "Failed to register panel\n"); ++ goto err_reg; ++ } ++ ++ dev_info(dev, "Successfully initialized %s\n", TLC_NAME); ++ ++ return 0; ++err_reg: ++err_gpio: ++ omap_dss_put_device(ddata->in); ++ return r; ++} ++ ++static int tlc59108_i2c_remove(struct i2c_client *client) ++{ ++ struct panel_drv_data *ddata = dev_get_drvdata(&client->dev); ++ struct omap_dss_device *dssdev = &ddata->dssdev; ++ struct omap_dss_device *in = ddata->in; ++ ++ if (gpio_is_valid(ddata->enable_gpio)) ++ gpio_set_value_cansleep(ddata->enable_gpio, 1); ++ ++ omapdss_unregister_display(dssdev); ++ ++ panel_dpi_disable(dssdev); ++ panel_dpi_disconnect(dssdev); ++ ++ omap_dss_put_device(in); ++ ++ return 0; ++} ++ ++static const struct i2c_device_id tlc59108_id[] = { ++ { TLC_NAME, 0 }, ++ { } ++}; ++MODULE_DEVICE_TABLE(i2c, tlc59108_id); ++ ++static const struct of_device_id tlc59108_of_match[] = { ++ { .compatible = "ti,tlc59108", }, ++ { }, ++}; ++MODULE_DEVICE_TABLE(of, tlc59108_of_match); ++ ++static struct i2c_driver tlc59108_i2c_driver = { ++ .driver = { ++ .owner = THIS_MODULE, ++ .name = TLC_NAME, ++ .of_match_table = tlc59108_of_match, ++ }, ++ .id_table = tlc59108_id, ++ .probe = tlc59108_i2c_probe, ++ .remove = tlc59108_i2c_remove, ++}; ++ ++static int __init tfc_s9700_init(void) ++{ ++ return i2c_add_driver(&tlc59108_i2c_driver); ++} ++ ++static void __exit tfc_s9700_exit(void) ++{ ++} ++module_init(tfc_s9700_init); ++module_exit(tfc_s9700_exit); ++ ++MODULE_AUTHOR("Archit Taneja <archit@ti.com>"); ++MODULE_DESCRIPTION("TFC-S9700 DPI Panel Driver"); ++MODULE_LICENSE("GPL"); +--- a/drivers/video/omap2/dss/core.c ++++ b/drivers/video/omap2/dss/core.c +@@ -256,6 +256,9 @@ static int (*dss_output_drv_reg_funcs[]) + #ifdef CONFIG_OMAP2_DSS_DPI + dpi_init_platform_driver, + #endif ++#ifdef CONFIG_OMAP2_DSS_DRA7XX_DPI ++ dra7xx_dpi_init_platform_driver, ++#endif + #ifdef CONFIG_OMAP2_DSS_SDI + sdi_init_platform_driver, + #endif +@@ -266,7 +269,10 @@ static int (*dss_output_drv_reg_funcs[]) + venc_init_platform_driver, + #endif + #ifdef CONFIG_OMAP4_DSS_HDMI +- hdmi_init_platform_driver, ++ hdmi4_init_platform_driver, ++#endif ++#ifdef CONFIG_OMAP5_DSS_HDMI ++ hdmi5_init_platform_driver, + #endif + }; + +@@ -277,6 +283,9 @@ static void (*dss_output_drv_unreg_funcs + #ifdef CONFIG_OMAP2_DSS_DPI + dpi_uninit_platform_driver, + #endif ++#ifdef CONFIG_OMAP2_DSS_DRA7XX_DPI ++ dra7xx_dpi_uninit_platform_driver, ++#endif + #ifdef CONFIG_OMAP2_DSS_SDI + sdi_uninit_platform_driver, + #endif +@@ -287,7 +296,10 @@ static void (*dss_output_drv_unreg_funcs + venc_uninit_platform_driver, + #endif + #ifdef CONFIG_OMAP4_DSS_HDMI +- hdmi_uninit_platform_driver, ++ hdmi4_uninit_platform_driver, ++#endif ++#ifdef CONFIG_OMAP5_DSS_HDMI ++ hdmi5_uninit_platform_driver, + #endif + }; + +--- a/drivers/video/omap2/dss/dispc.c ++++ b/drivers/video/omap2/dss/dispc.c +@@ -3622,6 +3622,7 @@ static int __init dispc_init_features(st + case OMAPDSS_VER_OMAP34xx_ES3: + case OMAPDSS_VER_OMAP3630: + case OMAPDSS_VER_AM35xx: ++ case OMAPDSS_VER_AM43xx: + src = &omap34xx_rev3_0_dispc_feats; + break; + +@@ -3632,6 +3633,7 @@ static int __init dispc_init_features(st + break; + + case OMAPDSS_VER_OMAP5: ++ case OMAPDSS_VER_DRA7xx: + src = &omap54xx_dispc_feats; + break; + +@@ -3691,7 +3693,6 @@ static int __init omap_dispchw_probe(str + } + + pm_runtime_enable(&pdev->dev); +- pm_runtime_irq_safe(&pdev->dev); + + r = dispc_runtime_get(); + if (r) +@@ -3744,12 +3745,19 @@ static const struct dev_pm_ops dispc_pm_ + .runtime_resume = dispc_runtime_resume, + }; + ++static const struct of_device_id dispc_of_match[] = { ++ { .compatible = "ti,omap3-dispc", }, ++ { .compatible = "ti,omap4-dispc", }, ++ {}, ++}; ++ + static struct platform_driver omap_dispchw_driver = { + .remove = __exit_p(omap_dispchw_remove), + .driver = { + .name = "omapdss_dispc", + .owner = THIS_MODULE, + .pm = &dispc_pm_ops, ++ .of_match_table = dispc_of_match, + }, + }; + +--- a/drivers/video/omap2/dss/display.c ++++ b/drivers/video/omap2/dss/display.c +@@ -26,6 +26,7 @@ + #include <linux/module.h> + #include <linux/jiffies.h> + #include <linux/platform_device.h> ++#include <linux/of.h> + + #include <video/omapdss.h> + #include "dss.h" +@@ -133,9 +134,27 @@ static int disp_num_counter; + int omapdss_register_display(struct omap_dss_device *dssdev) + { + struct omap_dss_driver *drv = dssdev->driver; ++ int id; + +- snprintf(dssdev->alias, sizeof(dssdev->alias), +- "display%d", disp_num_counter++); ++ /* ++ * Note: this presumes all the displays are either using DT or non-DT, ++ * which normally should be the case. This also presumes that all ++ * displays either have an DT alias, or none has. ++ */ ++ ++ if (dssdev->dev->of_node) { ++ id = of_alias_get_id(dssdev->dev->of_node, "display"); ++ ++ if (id < 0) ++ id = disp_num_counter++; ++ } else { ++ id = disp_num_counter++; ++ } ++ ++ snprintf(dssdev->alias, sizeof(dssdev->alias), "display%d", id); ++ ++ if (dssdev->name == NULL) ++ dssdev->name = dssdev->alias; + + if (drv && drv->get_resolution == NULL) + drv->get_resolution = omapdss_default_get_resolution; +--- a/drivers/video/omap2/dss/display-sysfs.c ++++ b/drivers/video/omap2/dss/display-sysfs.c +@@ -277,7 +277,7 @@ static ssize_t display_wss_store(struct + return size; + } + +-static DEVICE_ATTR(name, S_IRUGO, display_name_show, NULL); ++static DEVICE_ATTR(disp_name, S_IRUGO, display_name_show, NULL); + static DEVICE_ATTR(enabled, S_IRUGO|S_IWUSR, + display_enabled_show, display_enabled_store); + static DEVICE_ATTR(tear_elim, S_IRUGO|S_IWUSR, +@@ -292,7 +292,7 @@ static DEVICE_ATTR(wss, S_IRUGO|S_IWUSR, + display_wss_show, display_wss_store); + + static const struct attribute *display_sysfs_attrs[] = { +- &dev_attr_name.attr, ++ &dev_attr_disp_name.attr, + &dev_attr_enabled.attr, + &dev_attr_tear_elim.attr, + &dev_attr_timings.attr, +--- a/drivers/video/omap2/dss/dpi.c ++++ b/drivers/video/omap2/dss/dpi.c +@@ -30,6 +30,7 @@ + #include <linux/platform_device.h> + #include <linux/regulator/consumer.h> + #include <linux/string.h> ++#include <linux/of.h> + + #include <video/omapdss.h> + +@@ -64,6 +65,7 @@ static struct platform_device *dpi_get_d + case OMAPDSS_VER_OMAP34xx_ES3: + case OMAPDSS_VER_OMAP3630: + case OMAPDSS_VER_AM35xx: ++ case OMAPDSS_VER_AM43xx: + return NULL; + + case OMAPDSS_VER_OMAP4430_ES1: +@@ -374,7 +376,7 @@ static int dpi_display_enable(struct oma + if (r) + goto err_get_dispc; + +- r = dss_dpi_select_source(out->manager->id); ++ r = dss_dpi_select_source(0, out->manager->id); + if (r) + goto err_src_sel; + +@@ -593,6 +595,7 @@ static enum omap_channel dpi_get_channel + case OMAPDSS_VER_OMAP34xx_ES3: + case OMAPDSS_VER_OMAP3630: + case OMAPDSS_VER_AM35xx: ++ case OMAPDSS_VER_AM43xx: + return OMAP_DSS_CHANNEL_LCD; + + case OMAPDSS_VER_OMAP4430_ES1: +@@ -708,12 +711,19 @@ static int __exit omap_dpi_remove(struct + return 0; + } + ++static const struct of_device_id dpi_of_match[] = { ++ { .compatible = "ti,omap3-dpi", }, ++ { .compatible = "ti,omap4-dpi", }, ++ {}, ++}; ++ + static struct platform_driver omap_dpi_driver = { + .probe = omap_dpi_probe, + .remove = __exit_p(omap_dpi_remove), + .driver = { + .name = "omapdss_dpi", + .owner = THIS_MODULE, ++ .of_match_table = dpi_of_match, + }, + }; + +--- /dev/null ++++ b/drivers/video/omap2/dss/dra7xx_dpi.c +@@ -0,0 +1,632 @@ ++/* ++ * Some code and ideas taken from drivers/video/omap/ driver ++ * by Imre Deak. ++ * ++ * 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, see <http://www.gnu.org/licenses/>. ++ */ ++ ++#define DSS_SUBSYS_NAME "DRA7XX_DPI" ++ ++#include <linux/kernel.h> ++#include <linux/delay.h> ++#include <linux/export.h> ++#include <linux/err.h> ++#include <linux/errno.h> ++#include <linux/platform_device.h> ++#include <linux/regulator/consumer.h> ++#include <linux/string.h> ++#include <linux/slab.h> ++#include <linux/of.h> ++ ++#include <video/omapdss.h> ++ ++#include "dss.h" ++#include "dss_features.h" ++ ++struct dpi_data { ++ enum dss_dpll dpll; ++ ++ struct mutex lock; ++ ++ u32 module_id; ++ enum omap_channel channel; ++ ++ struct omap_video_timings timings; ++ struct dss_lcd_mgr_config mgr_config; ++ int data_lines; ++ ++ struct omap_dss_device output; ++}; ++ ++/* ++ * On DRA7xx, we will try to use the DPLL_VIDEOx PLLs, only if we can't get one, ++ * we will try to modify the DSS_FCLK to get the pixel clock. Leave HDMI PLL out ++ * for now ++ */ ++enum dss_dpll dpi_get_dpll(struct dpi_data *dpi) ++{ ++ switch (dpi->module_id) { ++ case 0: ++ if (dss_dpll_disabled(DSS_DPLL_VIDEO1)) ++ return DSS_DPLL_VIDEO1; ++ else ++ return DSS_DPLL_NONE; ++ case 1: ++ case 2: ++ if (dss_dpll_disabled(DSS_DPLL_VIDEO1)) ++ return DSS_DPLL_VIDEO1; ++ else if (dss_dpll_disabled(DSS_DPLL_VIDEO2)) ++ return DSS_DPLL_VIDEO2; ++ else ++ return DSS_DPLL_NONE; ++ default: ++ return DSS_DPLL_NONE; ++ } ++ ++ return DSS_DPLL_NONE; ++} ++ ++struct dpi_clk_calc_ctx { ++ enum dss_dpll dpll; ++ ++ /* inputs */ ++ unsigned long pck_min, pck_max; ++ ++ /* outputs */ ++ struct dss_dpll_cinfo dpll_cinfo; ++ struct dss_clock_info dss_cinfo; ++ struct dispc_clock_info dispc_cinfo; ++}; ++ ++static bool dpi_calc_dispc_cb(int lckd, int pckd, unsigned long lck, ++ unsigned long pck, void *data) ++{ ++ struct dpi_clk_calc_ctx *ctx = data; ++ ++ /* ++ * Odd dividers give us uneven duty cycle, causing problem when level ++ * shifted. So skip all odd dividers when the pixel clock is on the ++ * higher side. ++ */ ++ if (ctx->pck_min >= 100000000) { ++ if (lckd > 1 && lckd % 2 != 0) ++ return false; ++ ++ if (pckd > 1 && pckd % 2 != 0) ++ return false; ++ } ++ ++ ctx->dispc_cinfo.lck_div = lckd; ++ ctx->dispc_cinfo.pck_div = pckd; ++ ctx->dispc_cinfo.lck = lck; ++ ctx->dispc_cinfo.pck = pck; ++ ++ return true; ++} ++ ++static bool dpi_calc_hsdiv_cb(int regm_hsdiv, unsigned long dispc, ++ void *data) ++{ ++ struct dpi_clk_calc_ctx *ctx = data; ++ ++ /* ++ * Odd dividers give us uneven duty cycle, causing problem when level ++ * shifted. So skip all odd dividers when the pixel clock is on the ++ * higher side. ++ */ ++ if (regm_hsdiv > 1 && regm_hsdiv % 2 != 0 && ctx->pck_min >= 100000000) ++ return false; ++ ++ ctx->dpll_cinfo.regm_hsdiv = regm_hsdiv; ++ ctx->dpll_cinfo.hsdiv_clk = dispc; ++ ++ return dispc_div_calc(dispc, ctx->pck_min, ctx->pck_max, ++ dpi_calc_dispc_cb, ctx); ++} ++ ++static bool dpi_calc_pll_cb(int regn, int regm, unsigned long fint, ++ unsigned long pll, ++ void *data) ++{ ++ struct dpi_clk_calc_ctx *ctx = data; ++ ++ ctx->dpll_cinfo.regn = regn; ++ ctx->dpll_cinfo.regm = regm; ++ ctx->dpll_cinfo.fint = fint; ++ ctx->dpll_cinfo.clkout = pll; ++ ++ return dss_dpll_hsdiv_calc(ctx->dpll, pll, ctx->pck_min, ++ dpi_calc_hsdiv_cb, ctx); ++} ++ ++static bool dpi_calc_dss_cb(int fckd, unsigned long fck, void *data) ++{ ++ struct dpi_clk_calc_ctx *ctx = data; ++ ++ ctx->dss_cinfo.fck = fck; ++ ctx->dss_cinfo.fck_div = fckd; ++ ++ return dispc_div_calc(fck, ctx->pck_min, ctx->pck_max, ++ dpi_calc_dispc_cb, ctx); ++} ++ ++ ++static bool dpi_dpll_clk_calc(enum dss_dpll dpll, unsigned long pck, ++ struct dpi_clk_calc_ctx *ctx) ++{ ++ unsigned long clkin; ++ unsigned long pll_min, pll_max; ++ ++ clkin = dpll_get_clkin(dpll); ++ ++ memset(ctx, 0, sizeof(*ctx)); ++ ctx->dpll = dpll; ++ ctx->pck_min = pck - 1000; ++ ctx->pck_max = pck + 1000; ++ ctx->dpll_cinfo.clkin = clkin; ++ ++ pll_min = 0; ++ pll_max = 0; ++ ++ return dss_dpll_calc(dpll, clkin, pll_min, pll_max, dpi_calc_pll_cb, ++ ctx); ++} ++ ++static bool dpi_dss_clk_calc(unsigned long pck, struct dpi_clk_calc_ctx *ctx) ++{ ++ int i; ++ ++ /* ++ * DSS fck gives us very few possibilities, so finding a good pixel ++ * clock may not be possible. We try multiple times to find the clock, ++ * each time widening the pixel clock range we look for, up to ++ * +/- ~15MHz. ++ */ ++ ++ for (i = 0; i < 25; ++i) { ++ bool ok; ++ ++ memset(ctx, 0, sizeof(*ctx)); ++ if (pck > 1000 * i * i * i) ++ ctx->pck_min = max(pck - 1000 * i * i * i, 0lu); ++ else ++ ctx->pck_min = 0; ++ ctx->pck_max = pck + 1000 * i * i * i; ++ ++ ok = dss_div_calc(ctx->pck_min, dpi_calc_dss_cb, ctx); ++ if (ok) ++ return ok; ++ } ++ ++ return false; ++} ++ ++static int dpi_set_dss_dpll_clk(struct dpi_data *dpi, unsigned long pck_req, ++ unsigned long *fck, u16 *lck_div, u16 *pck_div) ++{ ++ struct dpi_clk_calc_ctx ctx; ++ int r; ++ bool ok; ++ ++ ok = dpi_dpll_clk_calc(dpi->dpll, pck_req, &ctx); ++ if (!ok) ++ return -EINVAL; ++ ++ r = dss_dpll_set_clock_div(dpi->dpll, &ctx.dpll_cinfo); ++ if (r) ++ return r; ++ ++ dss_use_dpll_lcd(dpi->output.dispc_channel, true); ++ ++ dpi->mgr_config.clock_info = ctx.dispc_cinfo; ++ ++ *fck = ctx.dpll_cinfo.hsdiv_clk; ++ *lck_div = ctx.dispc_cinfo.lck_div; ++ *pck_div = ctx.dispc_cinfo.pck_div; ++ ++ return 0; ++} ++ ++static int dpi_set_dispc_clk(struct dpi_data *dpi, unsigned long pck_req, ++ unsigned long *fck, u16 *lck_div, u16 *pck_div) ++{ ++ struct dpi_clk_calc_ctx ctx; ++ int r; ++ bool ok; ++ ++ ok = dpi_dss_clk_calc(pck_req, &ctx); ++ if (!ok) ++ return -EINVAL; ++ ++ r = dss_set_clock_div(&ctx.dss_cinfo); ++ if (r) ++ return r; ++ ++ dpi->mgr_config.clock_info = ctx.dispc_cinfo; ++ ++ *fck = ctx.dss_cinfo.fck; ++ *lck_div = ctx.dispc_cinfo.lck_div; ++ *pck_div = ctx.dispc_cinfo.pck_div; ++ ++ return 0; ++} ++ ++static int dpi_set_mode(struct dpi_data *dpi) ++{ ++ struct omap_overlay_manager *mgr = dpi->output.manager; ++ struct omap_video_timings *t = &dpi->timings; ++ u16 lck_div = 0, pck_div = 0; ++ unsigned long fck = 0; ++ unsigned long pck; ++ int r = 0; ++ ++ if (dpi->dpll != DSS_DPLL_NONE) ++ r = dpi_set_dss_dpll_clk(dpi, t->pixel_clock * 1000, &fck, ++ &lck_div, &pck_div); ++ else ++ r = dpi_set_dispc_clk(dpi, t->pixel_clock * 1000, &fck, ++ &lck_div, &pck_div); ++ if (r) ++ return r; ++ ++ pck = fck / lck_div / pck_div / 1000; ++ ++ if (pck != t->pixel_clock) { ++ DSSWARN("Could not find exact pixel clock. " ++ "Requested %d kHz, got %lu kHz\n", ++ t->pixel_clock, pck); ++ ++ t->pixel_clock = pck; ++ } ++ ++ dss_mgr_set_timings(mgr, t); ++ ++ return 0; ++} ++ ++static void dpi_config_lcd_manager(struct dpi_data *dpi) ++{ ++ struct omap_overlay_manager *mgr = dpi->output.manager; ++ ++ dpi->mgr_config.io_pad_mode = DSS_IO_PAD_MODE_BYPASS; ++ ++ dpi->mgr_config.stallmode = false; ++ dpi->mgr_config.fifohandcheck = false; ++ ++ dpi->mgr_config.video_port_width = dpi->data_lines; ++ ++ dpi->mgr_config.lcden_sig_polarity = 0; ++ ++ dss_mgr_set_lcd_config(mgr, &dpi->mgr_config); ++} ++ ++static int dra7xx_dpi_display_enable(struct omap_dss_device *dssdev) ++{ ++ struct dpi_data *dpi = dev_get_drvdata(dssdev->dev); ++ struct omap_dss_device *out = &dpi->output; ++ int r; ++ ++ mutex_lock(&dpi->lock); ++ ++ if (out == NULL || out->manager == NULL) { ++ DSSERR("failed to enable display: no output/manager\n"); ++ r = -ENODEV; ++ goto err_no_out_mgr; ++ } ++ ++ r = dispc_runtime_get(); ++ if (r) ++ goto err_get_dispc; ++ ++ r = dss_dpi_select_source(dpi->module_id, out->dispc_channel); ++ if (r) ++ goto err_src_sel; ++ ++ if (dpi->dpll != DSS_DPLL_NONE) { ++ DSSDBG("using DPLL %d for DPI%d\n", dpi->dpll, dpi->module_id); ++ dss_dpll_activate(dpi->dpll); ++ dss_dpll_set_control_mux(out->dispc_channel, dpi->dpll); ++ } ++ ++ r = dpi_set_mode(dpi); ++ if (r) ++ goto err_set_mode; ++ ++ ++ dpi_config_lcd_manager(dpi); ++ ++ mdelay(2); ++ ++ r = dss_mgr_enable(out->manager); ++ if (r) ++ goto err_mgr_enable; ++ ++ mutex_unlock(&dpi->lock); ++ ++ return 0; ++ ++err_mgr_enable: ++err_set_mode: ++ if (dpi->dpll != DSS_DPLL_NONE) ++ dss_dpll_disable(dpi->dpll); ++err_src_sel: ++ dispc_runtime_put(); ++err_get_dispc: ++err_no_out_mgr: ++ mutex_unlock(&dpi->lock); ++ return r; ++} ++ ++static void dra7xx_dpi_display_disable(struct omap_dss_device *dssdev) ++{ ++ struct dpi_data *dpi = dev_get_drvdata(dssdev->dev); ++ struct omap_overlay_manager *mgr = dpi->output.manager; ++ ++ mutex_lock(&dpi->lock); ++ ++ dss_mgr_disable(mgr); ++ ++ if (dpi->dpll != DSS_DPLL_NONE) { ++ dss_use_dpll_lcd(dssdev->dispc_channel, false); ++ dss_dpll_disable(dpi->dpll); ++ } ++ ++ dispc_runtime_put(); ++ ++ mutex_unlock(&dpi->lock); ++} ++ ++static void dra7xx_dpi_set_timings(struct omap_dss_device *dssdev, ++ struct omap_video_timings *timings) ++{ ++ struct dpi_data *dpi = dev_get_drvdata(dssdev->dev); ++ ++ DSSDBG("set_timings\n"); ++ ++ mutex_lock(&dpi->lock); ++ ++ dpi->timings = *timings; ++ ++ mutex_unlock(&dpi->lock); ++} ++ ++static int dra7xx_dpi_check_timings(struct omap_dss_device *dssdev, ++ struct omap_video_timings *timings) ++{ ++ DSSDBG("check_timings\n"); ++ ++ return 0; ++} ++ ++static void dra7xx_dpi_get_timings(struct omap_dss_device *dssdev, ++ struct omap_video_timings *timings) ++{ ++ struct dpi_data *dpi = dev_get_drvdata(dssdev->dev); ++ ++ DSSDBG("set_timings\n"); ++ ++ mutex_lock(&dpi->lock); ++ ++ *timings = dpi->timings; ++ ++ mutex_unlock(&dpi->lock); ++} ++ ++static void dra7xx_dpi_set_data_lines(struct omap_dss_device *dssdev, ++ int data_lines) ++{ ++ struct dpi_data *dpi = dev_get_drvdata(dssdev->dev); ++ ++ mutex_lock(&dpi->lock); ++ ++ dpi->data_lines = data_lines; ++ ++ mutex_unlock(&dpi->lock); ++} ++ ++static int dra7xx_dpi_connect(struct omap_dss_device *dssdev, ++ struct omap_dss_device *dst) ++{ ++ struct dpi_data *dpi = dev_get_drvdata(dssdev->dev); ++ struct omap_overlay_manager *mgr; ++ int r; ++ ++ /* try to get a free dpll */ ++ dpi->dpll = dpi_get_dpll(dpi); ++ ++ r = dss_dpll_init_regulator(dpi->dpll); ++ if (r) ++ return r; ++ ++ mgr = omap_dss_get_overlay_manager(dssdev->dispc_channel); ++ if (!mgr) ++ return -ENODEV; ++ ++ r = dss_mgr_connect(mgr, dssdev); ++ if (r) ++ return r; ++ ++ r = omapdss_output_set_device(dssdev, dst); ++ if (r) { ++ DSSERR("failed to connect output to new device: %s\n", ++ dst->name); ++ dss_mgr_disconnect(mgr, dssdev); ++ return r; ++ } ++ ++ return 0; ++} ++ ++static void dra7xx_dpi_disconnect(struct omap_dss_device *dssdev, ++ struct omap_dss_device *dst) ++{ ++ struct dpi_data *dpi = dev_get_drvdata(dssdev->dev); ++ ++ WARN_ON(dst != dssdev->dst); ++ ++ if (dst != dssdev->dst) ++ return; ++ ++ dpi->dpll = DSS_DPLL_NONE; ++ ++ omapdss_output_unset_device(dssdev); ++ ++ if (dssdev->manager) ++ dss_mgr_disconnect(dssdev->manager, dssdev); ++} ++ ++static const struct omapdss_dpi_ops dra7xx_dpi_ops = { ++ .connect = dra7xx_dpi_connect, ++ .disconnect = dra7xx_dpi_disconnect, ++ ++ .enable = dra7xx_dpi_display_enable, ++ .disable = dra7xx_dpi_display_disable, ++ ++ .check_timings = dra7xx_dpi_check_timings, ++ .set_timings = dra7xx_dpi_set_timings, ++ .get_timings = dra7xx_dpi_get_timings, ++ ++ .set_data_lines = dra7xx_dpi_set_data_lines, ++}; ++ ++static enum omap_channel dra7xx_dpi_get_channel(struct dpi_data *dpi) ++{ ++ switch (dpi->module_id) { ++ case 0: ++ return dpi->channel; ++ case 1: ++ return OMAP_DSS_CHANNEL_LCD2; ++ case 2: ++ return OMAP_DSS_CHANNEL_LCD3; ++ default: ++ DSSWARN("unknown DPI instance\n"); ++ return OMAP_DSS_CHANNEL_LCD; ++ } ++} ++ ++static void dra7xx_dpi_init_output(struct platform_device *pdev) ++{ ++ struct dpi_data *dpi = dev_get_drvdata(&pdev->dev); ++ struct omap_dss_device *out = &dpi->output; ++ char *name; ++ ++ out->dev = &pdev->dev; ++ name = devm_kzalloc(&pdev->dev, 5, GFP_KERNEL); ++ ++ switch (dpi->module_id) { ++ case 0: ++ out->id = OMAP_DSS_OUTPUT_DPI; ++ break; ++ case 1: ++ out->id = OMAP_DSS_OUTPUT_DPI1; ++ break; ++ case 2: ++ out->id = OMAP_DSS_OUTPUT_DPI2; ++ break; ++ }; ++ ++ snprintf(name, 5, "dpi.%d", dpi->module_id); ++ out->name = name; ++ out->output_type = OMAP_DISPLAY_TYPE_DPI; ++ out->dispc_channel = dra7xx_dpi_get_channel(dpi); ++ out->ops.dpi = &dra7xx_dpi_ops; ++ out->owner = THIS_MODULE; ++ ++ omapdss_register_output(out); ++} ++ ++static void __exit dra7xx_dpi_uninit_output(struct platform_device *pdev) ++{ ++ struct dpi_data *dpi = dev_get_drvdata(&pdev->dev); ++ struct omap_dss_device *out = &dpi->output; ++ ++ omapdss_unregister_output(out); ++} ++ ++static int dra7xx_dpi_probe(struct platform_device *pdev) ++{ ++ int r; ++ struct dpi_data *dpi; ++ ++ dpi = devm_kzalloc(&pdev->dev, sizeof(*dpi), GFP_KERNEL); ++ if (!dpi) ++ return -ENOMEM; ++ ++ dev_set_drvdata(&pdev->dev, dpi); ++ ++ mutex_init(&dpi->lock); ++ ++ if (pdev->dev.of_node) { ++ u32 id; ++ enum omap_channel channel; ++ ++ r = of_property_read_u32(pdev->dev.of_node, "id", &id); ++ if (r) { ++ DSSERR("failed to read DPI module ID\n"); ++ return r; ++ } ++ ++ r = of_property_read_u32(pdev->dev.of_node, "channel", &channel); ++ if (r && id == 0) { ++ DSSERR("failed to read DPI channel\n"); ++ return r; ++ } ++ ++ dpi->module_id = id; ++ dpi->channel = channel; ++ } else { ++ dpi->module_id = pdev->id; ++ } ++ ++ dra7xx_dpi_init_output(pdev); ++ ++ return 0; ++} ++ ++static int __exit dra7xx_dpi_remove(struct platform_device *pdev) ++{ ++ dra7xx_dpi_uninit_output(pdev); ++ ++ return 0; ++} ++ ++#if defined(CONFIG_OF) ++static const struct of_device_id dpi_of_match[] = { ++ { ++ .compatible = "ti,dra7xx-dpi", ++ }, ++ {}, ++}; ++#else ++#define dpi_of_match NULL ++#endif ++ ++static struct platform_driver dra7xx_dpi_driver = { ++ .probe = dra7xx_dpi_probe, ++ .remove = __exit_p(dra7xx_dpi_remove), ++ .driver = { ++ .name = "omapdss_dra7xx_dpi", ++ .owner = THIS_MODULE, ++ .of_match_table = dpi_of_match, ++ }, ++}; ++ ++int __init dra7xx_dpi_init_platform_driver(void) ++{ ++ return platform_driver_register(&dra7xx_dpi_driver); ++} ++ ++void __exit dra7xx_dpi_uninit_platform_driver(void) ++{ ++ platform_driver_unregister(&dra7xx_dpi_driver); ++} +--- a/drivers/video/omap2/dss/dsi.c ++++ b/drivers/video/omap2/dss/dsi.c +@@ -38,6 +38,7 @@ + #include <linux/slab.h> + #include <linux/debugfs.h> + #include <linux/pm_runtime.h> ++#include <linux/of.h> + + #include <video/omapdss.h> + #include <video/mipi_display.h> +@@ -373,6 +374,13 @@ struct dsi_packet_sent_handler_data { + struct completion *completion; + }; + ++struct dsi_module_id_data { ++ u32 address; ++ int id; ++}; ++ ++static const struct of_device_id dsi_of_match[]; ++ + #ifdef DEBUG + static bool dsi_perf; + module_param(dsi_perf, bool, 0644); +@@ -1123,11 +1131,6 @@ static int dsi_regulator_init(struct pla + return 0; + + vdds_dsi = devm_regulator_get(&dsi->pdev->dev, "vdds_dsi"); +- +- /* DT HACK: try VCXIO to make omapdss work for o4 sdp/panda */ +- if (IS_ERR(vdds_dsi)) +- vdds_dsi = devm_regulator_get(&dsi->pdev->dev, "VCXIO"); +- + if (IS_ERR(vdds_dsi)) { + DSSERR("can't get VDDS_DSI regulator\n"); + return PTR_ERR(vdds_dsi); +@@ -5082,6 +5085,7 @@ static enum omap_channel dsi_get_channel + { + switch (omapdss_get_version()) { + case OMAPDSS_VER_OMAP24xx: ++ case OMAPDSS_VER_AM43xx: + DSSWARN("DSI not supported\n"); + return OMAP_DSS_CHANNEL_LCD; + +@@ -5352,7 +5356,6 @@ static int omap_dsihw_probe(struct platf + if (!dsi) + return -ENOMEM; + +- dsi->module_id = dsidev->id; + dsi->pdev = dsidev; + dev_set_drvdata(&dsidev->dev, dsi); + +@@ -5402,6 +5405,31 @@ static int omap_dsihw_probe(struct platf + return r; + } + ++ if (dsidev->dev.of_node) { ++ const struct of_device_id *match; ++ const struct dsi_module_id_data *d; ++ ++ match = of_match_node(dsi_of_match, dsidev->dev.of_node); ++ if (!match) { ++ DSSERR("unsupported DSI module\n"); ++ return -ENODEV; ++ } ++ ++ d = match->data; ++ ++ while (d->address != 0 && d->address != dsi_mem->start) ++ d++; ++ ++ if (d->address == 0) { ++ DSSERR("unsupported DSI module\n"); ++ return -ENODEV; ++ } ++ ++ dsi->module_id = d->id; ++ } else { ++ dsi->module_id = dsidev->id; ++ } ++ + /* DSI VCs initialization */ + for (i = 0; i < ARRAY_SIZE(dsi->vc); i++) { + dsi->vc[i].source = DSI_VC_SOURCE_L4; +@@ -5450,6 +5478,7 @@ static int omap_dsihw_probe(struct platf + else if (dsi->module_id == 1) + dss_debugfs_create_file("dsi2_irqs", dsi2_dump_irqs); + #endif ++ + return 0; + + err_runtime_get: +@@ -5498,6 +5527,23 @@ static const struct dev_pm_ops dsi_pm_op + .runtime_resume = dsi_runtime_resume, + }; + ++static const struct dsi_module_id_data dsi_of_data_omap3[] = { ++ { .address = 0x4804fc00, .id = 0, }, ++ { }, ++}; ++ ++static const struct dsi_module_id_data dsi_of_data_omap4[] = { ++ { .address = 0x58004000, .id = 0, }, ++ { .address = 0x58005000, .id = 1, }, ++ { }, ++}; ++ ++static const struct of_device_id dsi_of_match[] = { ++ { .compatible = "ti,omap3-dsi", .data = dsi_of_data_omap3, }, ++ { .compatible = "ti,omap4-dsi", .data = dsi_of_data_omap4, }, ++ {}, ++}; ++ + static struct platform_driver omap_dsihw_driver = { + .probe = omap_dsihw_probe, + .remove = __exit_p(omap_dsihw_remove), +@@ -5505,6 +5551,7 @@ static struct platform_driver omap_dsihw + .name = "omapdss_dsi", + .owner = THIS_MODULE, + .pm = &dsi_pm_ops, ++ .of_match_table = dsi_of_match, + }, + }; + +--- a/drivers/video/omap2/dss/dss.c ++++ b/drivers/video/omap2/dss/dss.c +@@ -23,6 +23,7 @@ + #define DSS_SUBSYS_NAME "DSS" + + #include <linux/kernel.h> ++#include <linux/module.h> + #include <linux/io.h> + #include <linux/export.h> + #include <linux/err.h> +@@ -33,6 +34,7 @@ + #include <linux/pm_runtime.h> + #include <linux/gfp.h> + #include <linux/sizes.h> ++#include <linux/clk-private.h> + + #include <video/omapdss.h> + +@@ -68,7 +70,8 @@ struct dss_features { + u8 fck_div_max; + u8 dss_fck_multiplier; + const char *clk_name; +- int (*dpi_select_source)(enum omap_channel channel); ++ int (*dpi_select_source)(int module_id, enum omap_channel channel); ++ bool dpll_clks; + }; + + static struct { +@@ -428,6 +431,28 @@ void dss_select_lcd_clk_source(enum omap + dss.lcd_clk_source[ix] = clk_src; + } + ++void dss_use_dpll_lcd(enum omap_channel channel, bool use_dpll) ++{ ++ u8 bit; ++ ++ switch (channel) { ++ case OMAP_DSS_CHANNEL_LCD: ++ bit = 0; ++ break; ++ case OMAP_DSS_CHANNEL_LCD2: ++ bit = 12; ++ break; ++ case OMAP_DSS_CHANNEL_LCD3: ++ bit = 19; ++ break; ++ case OMAP_DSS_CHANNEL_DIGIT: ++ default: ++ return; ++ } ++ ++ REG_FLD_MOD(DSS_CONTROL, use_dpll, bit, bit); ++} ++ + enum omap_dss_clk_source dss_get_dispc_clk_source(void) + { + return dss.dispc_clk_source; +@@ -466,7 +491,7 @@ int dss_calc_clock_rates(struct dss_cloc + cinfo->fck = prate / cinfo->fck_div * + dss.feat->dss_fck_multiplier; + } else { +- if (cinfo->fck_div != 0) ++ if (cinfo->fck_div != 1) + return -EINVAL; + cinfo->fck = clk_get_rate(dss.dss_clk); + } +@@ -529,7 +554,7 @@ int dss_set_clock_div(struct dss_clock_i + if (r) + return r; + } else { +- if (cinfo->fck_div != 0) ++ if (cinfo->fck_div != 1) + return -EINVAL; + } + +@@ -635,7 +660,8 @@ enum dss_hdmi_venc_clk_source_select dss + return REG_GET(DSS_CONTROL, 15, 15); + } + +-static int dss_dpi_select_source_omap2_omap3(enum omap_channel channel) ++static int dss_dpi_select_source_omap2_omap3(int module_id, ++ enum omap_channel channel) + { + if (channel != OMAP_DSS_CHANNEL_LCD) + return -EINVAL; +@@ -643,7 +669,7 @@ static int dss_dpi_select_source_omap2_o + return 0; + } + +-static int dss_dpi_select_source_omap4(enum omap_channel channel) ++static int dss_dpi_select_source_omap4(int module_id, enum omap_channel channel) + { + int val; + +@@ -663,7 +689,7 @@ static int dss_dpi_select_source_omap4(e + return 0; + } + +-static int dss_dpi_select_source_omap5(enum omap_channel channel) ++static int dss_dpi_select_source_omap5(int module_id, enum omap_channel channel) + { + int val; + +@@ -689,9 +715,17 @@ static int dss_dpi_select_source_omap5(e + return 0; + } + +-int dss_dpi_select_source(enum omap_channel channel) ++static int dss_dpi_select_source_dra7xx(int module_id, enum omap_channel channel) ++{ ++ if (module_id != 0) ++ return 0; ++ ++ return dss_dpi_select_source_omap5(module_id, channel); ++} ++ ++int dss_dpi_select_source(int module_id, enum omap_channel channel) + { +- return dss.feat->dpi_select_source(channel); ++ return dss.feat->dpi_select_source(module_id, channel); + } + + static int dss_get_clocks(void) +@@ -713,11 +747,26 @@ static int dss_get_clocks(void) + return PTR_ERR(clk); + } + } else { ++ int r; ++ ++ DSSDBG("DSS CLOCK HACK\n"); ++ printk("FCK %s\n", clk->name); ++ ++ clk = clk_get_parent(clk); ++ DSSDBG("GATE %s\n", clk->name); ++ ++ clk = clk_get_parent(clk); ++ DSSDBG("PLL %s\n", clk->name); ++ ++ r = clk_set_rate(clk, 150000000); ++ if (!r) ++ DSSERR("SET CLK RATE Failed"); + clk = NULL; + } + + dss.dpll4_m4_ck = clk; + ++ + return 0; + } + +@@ -795,6 +844,21 @@ static const struct dss_features omap54x + .dpi_select_source = &dss_dpi_select_source_omap5, + }; + ++static const struct dss_features dra7xx_dss_feats __initconst = { ++ .fck_div_max = 64, ++ .dss_fck_multiplier = 1, ++ .clk_name = "dpll_per_h12x2_ck", ++ .dpi_select_source = &dss_dpi_select_source_dra7xx, ++ .dpll_clks = true, ++}; ++ ++static const struct dss_features am43xx_dss_feats __initconst = { ++ .fck_div_max = 0, ++ .dss_fck_multiplier = 0, ++ .clk_name = NULL, ++ .dpi_select_source = &dss_dpi_select_source_omap2_omap3, ++}; ++ + static int __init dss_init_features(struct platform_device *pdev) + { + const struct dss_features *src; +@@ -831,6 +895,14 @@ static int __init dss_init_features(stru + src = &omap54xx_dss_feats; + break; + ++ case OMAPDSS_VER_DRA7xx: ++ src = &dra7xx_dss_feats; ++ break; ++ ++ case OMAPDSS_VER_AM43xx: ++ src = &am43xx_dss_feats; ++ break; ++ + default: + return -ENODEV; + } +@@ -907,6 +979,15 @@ static int __init omap_dsshw_probe(struc + + dss_debugfs_create_file("dss", dss_dump_regs); + ++ if (dss.feat->dpll_clks) { ++ r = dss_dpll_configure(pdev); ++ if (r) ++ goto err_runtime_get; ++ r = dss_dpll_configure_ctrl(); ++ if (r) ++ goto err_runtime_get; ++ } ++ + return 0; + + err_runtime_get: +@@ -920,6 +1001,9 @@ static int __exit omap_dsshw_remove(stru + { + pm_runtime_disable(&pdev->dev); + ++ if (dss.feat->dpll_clks) ++ dss_dpll_unconfigure_ctrl(); ++ + dss_put_clocks(); + + return 0; +@@ -955,12 +1039,21 @@ static const struct dev_pm_ops dss_pm_op + .runtime_resume = dss_runtime_resume, + }; + ++static const struct of_device_id dss_of_match[] = { ++ { .compatible = "ti,omap3-dss", }, ++ { .compatible = "ti,omap4-dss", }, ++ {}, ++}; ++ ++MODULE_DEVICE_TABLE(of, dss_of_match); ++ + static struct platform_driver omap_dsshw_driver = { + .remove = __exit_p(omap_dsshw_remove), + .driver = { + .name = "omapdss_dss", + .owner = THIS_MODULE, + .pm = &dss_pm_ops, ++ .of_match_table = dss_of_match, + }, + }; + +--- /dev/null ++++ b/drivers/video/omap2/dss/dss_dpll.c +@@ -0,0 +1,536 @@ ++/* ++ * Copyright (C) 2013 Texas Instruments Ltd ++ * ++ * Copy of the DSI PLL code ++ * ++ * 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, see <http://www.gnu.org/licenses/>. ++ */ ++ ++#include <linux/kernel.h> ++#include <linux/err.h> ++#include <linux/delay.h> ++#include <linux/io.h> ++#include <linux/clk.h> ++#include <linux/platform_device.h> ++#include <linux/regulator/consumer.h> ++#include <linux/sched.h> ++#include <linux/wait.h> ++ ++#include <video/omapdss.h> ++ ++#include "dss.h" ++#include "dss_features.h" ++ ++#define CLK_CTRL 0x054 ++#define PLL_CONTROL 0x300 ++#define PLL_STATUS 0x304 ++#define PLL_GO 0x308 ++#define PLL_CONFIGURATION1 0x30C ++#define PLL_CONFIGURATION2 0x310 ++#define PLL_CONFIGURATION3 0x314 ++#define PLL_SSC_CONFIGURATION1 0x318 ++#define PLL_SSC_CONFIGURATION2 0x31C ++ ++#define CTRL_BASE 0x4a002500 ++#define DSS_PLL_CONTROL 0x38 ++ ++#define REG_GET(dpll, idx, start, end) \ ++ FLD_GET(dpll_read_reg(dpll, idx), start, end) ++ ++#define REG_FLD_MOD(dpll, idx, val, start, end) \ ++ dpll_write_reg(dpll, idx, FLD_MOD(dpll_read_reg(dpll, idx), val, start, end)) ++ ++static struct { ++ struct platform_device *pdev; ++ struct regulator *vdda_video_reg; ++ ++ void __iomem *base[2], *control_base; ++ unsigned scp_refcount[2]; ++ struct clk *sys_clk[2]; ++ bool enabled[3]; ++} dss_dpll; ++ ++static inline u32 dpll_read_reg(enum dss_dpll dpll, u16 offset) ++{ ++ return __raw_readl(dss_dpll.base[dpll] + offset); ++} ++ ++static inline void dpll_write_reg(enum dss_dpll dpll, u16 offset, u32 val) ++{ ++ __raw_writel(val, dss_dpll.base[dpll] + offset); ++} ++ ++#define CTRL_REG_GET(start, end) \ ++ FLD_GET(ctrl_read_reg(), start, end) ++ ++#define CTRL_REG_FLD_MOD(val, start, end) \ ++ ctrl_write_reg(FLD_MOD(ctrl_read_reg(), val, start, end)) ++ ++static inline u32 ctrl_read_reg(void) ++{ ++ return __raw_readl(dss_dpll.control_base + DSS_PLL_CONTROL); ++} ++ ++static inline void ctrl_write_reg(u32 val) ++{ ++ __raw_writel(val, dss_dpll.control_base + DSS_PLL_CONTROL); ++} ++ ++static inline int wait_for_bit_change(enum dss_dpll dpll, ++ const u16 offset, int bitnum, int value) ++{ ++ unsigned long timeout; ++ ktime_t wait; ++ int t; ++ ++ /* first busyloop to see if the bit changes right away */ ++ t = 100; ++ while (t-- > 0) { ++ if (REG_GET(dpll, offset, bitnum, bitnum) == value) ++ return value; ++ } ++ ++ /* then loop for 500ms, sleeping for 1ms in between */ ++ timeout = jiffies + msecs_to_jiffies(500); ++ while (time_before(jiffies, timeout)) { ++ if (REG_GET(dpll, offset, bitnum, bitnum) == value) ++ return value; ++ ++ wait = ns_to_ktime(1000 * 1000); ++ set_current_state(TASK_UNINTERRUPTIBLE); ++ schedule_hrtimeout(&wait, HRTIMER_MODE_REL); ++ } ++ ++ return !value; ++} ++ ++bool dss_dpll_disabled(enum dss_dpll dpll) ++{ ++ return !dss_dpll.enabled[dpll]; ++} ++ ++unsigned long dpll_get_clkin(enum dss_dpll dpll) ++{ ++ return clk_get_rate(dss_dpll.sys_clk[dpll]); ++} ++ ++bool dss_dpll_calc(enum dss_dpll dpll, unsigned long clkin, ++ unsigned long pll_min, unsigned long pll_max, ++ dss_dpll_calc_func func, void *data) ++{ ++ int regn, regn_start, regn_stop; ++ int regm, regm_start, regm_stop; ++ unsigned long fint, pll; ++ const unsigned long pll_hw_max = 1800000000; ++ unsigned long fint_hw_min, fint_hw_max, regm_max, regn_max; ++ ++ fint_hw_min = dss_feat_get_param_min(FEAT_PARAM_DSIPLL_FINT); ++ fint_hw_max = dss_feat_get_param_max(FEAT_PARAM_DSIPLL_FINT); ++ regm_max = dss_feat_get_param_max(FEAT_PARAM_DSIPLL_REGM); ++ regn_max = dss_feat_get_param_max(FEAT_PARAM_DSIPLL_REGN); ++ ++ regn_start = max(DIV_ROUND_UP(clkin, fint_hw_max), 1ul); ++ regn_stop = min(clkin / fint_hw_min, regn_max); ++ ++ pll_max = pll_max ? pll_max : ULONG_MAX; ++ ++ for (regn = regn_start; regn <= regn_stop; ++regn) { ++ fint = clkin / regn; ++ ++ regm_start = max(DIV_ROUND_UP(DIV_ROUND_UP(pll_min, fint), 2), ++ 1ul); ++ regm_stop = min3(pll_max / fint / 2, ++ pll_hw_max / fint / 2, ++ regm_max); ++ ++ for (regm = regm_start; regm <= regm_stop; ++regm) { ++ pll = 2 * regm * fint; ++ ++ if (func(regn, regm, fint, pll, data)) ++ return true; ++ } ++ } ++ ++ return false; ++} ++ ++bool dss_dpll_hsdiv_calc(enum dss_dpll dpll, unsigned long pll, ++ unsigned long out_min, dss_dpll_hsdiv_calc_func func, void *data) ++{ ++ int regm, regm_start, regm_stop; ++ unsigned long out_max; ++ unsigned long out; ++ unsigned long regm_dispc_max; ++ ++ regm_dispc_max = dss_feat_get_param_max(FEAT_PARAM_DSIPLL_REGM_DISPC); ++ ++ out_min = out_min ? out_min : 1; ++ out_max = dss_feat_get_param_max(FEAT_PARAM_DSS_FCK); ++ ++ regm_start = max(DIV_ROUND_UP(pll, out_max), 1ul); ++ regm_stop = min(pll / out_min, regm_dispc_max); ++ ++ for (regm = regm_start; regm <= regm_stop; ++regm) { ++ out = pll / regm; ++ ++ if (func(regm, out, data)) ++ return true; ++ } ++ ++ return false; ++} ++ ++int dss_dpll_set_clock_div(enum dss_dpll dpll, struct dss_dpll_cinfo *cinfo) ++{ ++ int r = 0; ++ u32 l; ++ u8 regn_start, regn_end, regm_start, regm_end; ++ u8 regm_hsdiv_start, regm_hsdiv_end; ++ ++ DSSDBG("DPLL_VIDEO%d clock config starts\n", dpll + 1); ++ ++ DSSDBG("DPLL Fint %ld\n", cinfo->fint); ++ ++ DSSDBG("clkin rate %ld\n", cinfo->clkin); ++ ++ DSSDBG("CLKOUT = 2 * %d / %d * %lu = %lu\n", ++ cinfo->regm, ++ cinfo->regn, ++ cinfo->clkin, ++ cinfo->clkout); ++ ++ DSSDBG("regm_hsdiv = %d\n", cinfo->regm_hsdiv); ++ ++ dss_feat_get_reg_field(FEAT_REG_DSIPLL_REGN, ®n_start, ®n_end); ++ dss_feat_get_reg_field(FEAT_REG_DSIPLL_REGM, ®m_start, ®m_end); ++ dss_feat_get_reg_field(FEAT_REG_DSIPLL_REGM_DISPC, ®m_hsdiv_start, ++ ®m_hsdiv_end); ++ ++ /* PLL_AUTOMODE = manual */ ++ REG_FLD_MOD(dpll, PLL_CONTROL, 0, 0, 0); ++ ++ /* CONFIGURATION1 */ ++ l = dpll_read_reg(dpll, PLL_CONFIGURATION1); ++ /* PLL_REGN */ ++ l = FLD_MOD(l, cinfo->regn - 1, regn_start, regn_end); ++ /* PLL_REGM */ ++ l = FLD_MOD(l, cinfo->regm, regm_start, regm_end); ++ /* M4_CLOCK_DIV */ ++ l = FLD_MOD(l, cinfo->regm_hsdiv > 0 ? cinfo->regm_hsdiv - 1 : 0, ++ regm_hsdiv_start, regm_hsdiv_end); ++ dpll_write_reg(dpll, PLL_CONFIGURATION1, l); ++ ++ /* CONFIGURATION3 */ ++ l = dpll_read_reg(dpll, PLL_CONFIGURATION3); ++ /* M6_CLOCK_DIV */ ++ l = FLD_MOD(l, cinfo->regm_hsdiv > 0 ? cinfo->regm_hsdiv - 1 : 0, 4, 0); ++ dpll_write_reg(dpll, PLL_CONFIGURATION3, l); ++ ++ /* CONFIGURATION2 */ ++ l = dpll_read_reg(dpll, PLL_CONFIGURATION2); ++ l = FLD_MOD(l, 1, 13, 13); /* PLL_REFEN */ ++ l = FLD_MOD(l, 0, 14, 14); /* DSIPHY_CLKINEN */ ++ l = FLD_MOD(l, 1, 20, 20); /* HSDIVBYPASS */ ++ l = FLD_MOD(l, 3, 22, 21); /* REF_SYSCLK = sysclk */ ++ dpll_write_reg(dpll, PLL_CONFIGURATION2, l); ++ ++ REG_FLD_MOD(dpll, PLL_GO, 1, 0, 0); /* PLL_GO */ ++ ++ if (wait_for_bit_change(dpll, PLL_GO, 0, 0) != 0) { ++ DSSERR("dsi pll go bit not going down.\n"); ++ r = -EIO; ++ goto err; ++ } ++ ++ if (wait_for_bit_change(dpll, PLL_STATUS, 1, 1) != 1) { ++ DSSERR("cannot lock PLL\n"); ++ r = -EIO; ++ goto err; ++ } ++ ++ l = dpll_read_reg(dpll, PLL_CONFIGURATION2); ++ l = FLD_MOD(l, 0, 0, 0); /* PLL_IDLE */ ++ l = FLD_MOD(l, 0, 5, 5); /* PLL_PLLLPMODE */ ++ l = FLD_MOD(l, 0, 6, 6); /* PLL_LOWCURRSTBY */ ++ l = FLD_MOD(l, 0, 7, 7); /* PLL_TIGHTPHASELOCK */ ++ l = FLD_MOD(l, 0, 8, 8); /* PLL_DRIFTGUARDEN */ ++ l = FLD_MOD(l, 0, 10, 9); /* PLL_LOCKSEL */ ++ l = FLD_MOD(l, 1, 13, 13); /* PLL_REFEN */ ++ l = FLD_MOD(l, 1, 14, 14); /* PHY_CLKINEN */ ++ l = FLD_MOD(l, 0, 15, 15); /* BYPASSEN */ ++ l = FLD_MOD(l, 1, 16, 16); /* M4_CLOCK_EN */ ++ l = FLD_MOD(l, 0, 17, 17); /* CLOCK_PWDN */ ++ l = FLD_MOD(l, 1, 18, 18); /* PROTO_CLOCK_EN */ ++ l = FLD_MOD(l, 0, 19, 19); /* PROTO_CLOCK_PWDN */ ++ l = FLD_MOD(l, 0, 20, 20); /* HSDIVBYPASS */ ++ l = FLD_MOD(l, 1, 23, 23); /* M6_CLOCK_EN */ ++ dpll_write_reg(dpll, PLL_CONFIGURATION2, l); ++ ++ DSSDBG("PLL config done\n"); ++ ++err: ++ return r; ++} ++ ++static void dss_dpll_disable_scp_clk(enum dss_dpll dpll) ++{ ++ unsigned *refcount; ++ ++ refcount = &dss_dpll.scp_refcount[dpll]; ++ ++ WARN_ON(*refcount == 0); ++ if (--(*refcount) == 0) ++ REG_FLD_MOD(dpll, CLK_CTRL, 0, 14, 14); /* CIO_CLK_ICG */ ++} ++ ++static void dss_dpll_enable_scp_clk(enum dss_dpll dpll) ++{ ++ unsigned *refcount; ++ ++ refcount = &dss_dpll.scp_refcount[dpll]; ++ ++ if ((*refcount)++ == 0) ++ REG_FLD_MOD(dpll, CLK_CTRL, 1, 14, 14); /* CIO_CLK_ICG */ ++} ++ ++static int dpll_power(enum dss_dpll dpll, int state) ++{ ++ int t = 0; ++ /* PLL_PWR_CMD = enable both hsdiv and clkout*/ ++ REG_FLD_MOD(dpll, CLK_CTRL, state, 31, 30); ++ ++ /* PLL_PWR_STATUS: (NOTE: apparently buggy) */ ++ while (FLD_GET(dpll_read_reg(dpll, CLK_CTRL), 29, 28) != state) { ++ if (++t > 1000) { ++ DSSERR("Failed to set DPLL power mode to %d\n", state); ++ /* return -ENODEV; */ ++ return 0; ++ } ++ udelay(1); ++ } ++ ++ return 0; ++} ++ ++void dss_dpll_enable_ctrl(enum dss_dpll dpll, bool enable) ++{ ++ u8 bit; ++ ++ switch (dpll) { ++ case DSS_DPLL_VIDEO1: ++ bit = 0; ++ break; ++ case DSS_DPLL_VIDEO2: ++ bit = 1; ++ break; ++ case DSS_DPLL_HDMI: ++ bit = 2; ++ break; ++ default: ++ DSSERR("invalid dpll\n"); ++ return; ++ } ++ ++ CTRL_REG_FLD_MOD(!enable, bit, bit); ++ ++ dss_dpll.enabled[dpll] = enable; ++} ++ ++static int dpll_init(enum dss_dpll dpll) ++{ ++ int r; ++ ++ clk_prepare_enable(dss_dpll.sys_clk[dpll]); ++ dss_dpll_enable_scp_clk(dpll); ++ ++ r = regulator_enable(dss_dpll.vdda_video_reg); ++ if (r) ++ goto err_reg; ++ ++ if (wait_for_bit_change(dpll, PLL_STATUS, 0, 1) != 1) { ++ DSSERR("PLL not coming out of reset.\n"); ++ r = -ENODEV; ++ goto err_reset; ++ } ++ ++ r = dpll_power(dpll, 0x2); ++ if (r) ++ goto err_reset; ++ ++ return 0; ++ ++err_reset: ++ regulator_disable(dss_dpll.vdda_video_reg); ++err_reg: ++ dss_dpll_disable_scp_clk(dpll); ++ clk_disable_unprepare(dss_dpll.sys_clk[dpll]); ++ ++ return r; ++} ++ ++int dss_dpll_activate(enum dss_dpll dpll) ++{ ++ int r; ++ ++ /* enable from control module */ ++ dss_dpll_enable_ctrl(dpll, true); ++ ++ r = dpll_init(dpll); ++ ++ return r; ++} ++ ++void dss_dpll_set_control_mux(enum omap_channel channel, enum dss_dpll dpll) ++{ ++ u8 start, end; ++ u8 val; ++ ++ if (channel == OMAP_DSS_CHANNEL_LCD) { ++ start = 4; ++ end = 3; ++ ++ switch (dpll) { ++ case DSS_DPLL_VIDEO1: ++ val = 0; ++ break; ++ default: ++ DSSERR("error in mux config for LCD\n"); ++ return; ++ } ++ } else if (channel == OMAP_DSS_CHANNEL_LCD2) { ++ start = 6; ++ end = 5; ++ ++ switch (dpll) { ++ case DSS_DPLL_VIDEO1: ++ val = 0; ++ break; ++ case DSS_DPLL_VIDEO2: ++ val = 1; ++ break; ++ default: ++ DSSERR("error in mux config for LCD2\n"); ++ return; ++ } ++ } else { ++ start = 8; ++ end = 7; ++ ++ switch (dpll) { ++ case DSS_DPLL_VIDEO1: ++ val = 1; ++ break; ++ case DSS_DPLL_VIDEO2: ++ val = 0; ++ break; ++ default: ++ DSSERR("error in mux config for LCD3\n"); ++ return; ++ } ++ } ++ ++ CTRL_REG_FLD_MOD(val, start, end); ++} ++ ++void dss_dpll_disable(enum dss_dpll dpll) ++{ ++ dpll_power(dpll, 0); ++ ++ regulator_disable(dss_dpll.vdda_video_reg); ++ ++ dss_dpll_disable_scp_clk(dpll); ++ clk_disable_unprepare(dss_dpll.sys_clk[dpll]); ++ ++ dss_dpll_enable_ctrl(dpll, false); ++} ++ ++static int dss_dpll_configure_one(struct platform_device *pdev, ++ enum dss_dpll dpll) ++{ ++ struct resource *dpll_mem; ++ ++ dpll_mem = platform_get_resource(pdev, IORESOURCE_MEM, dpll + 1); ++ if (!dpll_mem) { ++ DSSERR("can't get IORESOURCE_MEM for DPLL %d\n", dpll); ++ return -EINVAL; ++ } ++ ++ dss_dpll.base[dpll] = devm_ioremap(&pdev->dev, dpll_mem->start, ++ resource_size(dpll_mem)); ++ if (!dss_dpll.base[dpll]) { ++ DSSERR("can't ioremap DPLL %d\n", dpll); ++ return -ENOMEM; ++ } ++ ++ dss_dpll.sys_clk[dpll] = devm_clk_get(&pdev->dev, ++ dpll == DSS_DPLL_VIDEO1 ? "video1_clk" : "video2_clk"); ++ if (IS_ERR(dss_dpll.sys_clk[dpll])) { ++ DSSERR("can't get sys clock for DPLL_VIDEO%d\n", dpll + 1); ++ return PTR_ERR(dss_dpll.sys_clk[dpll]); ++ } ++ ++ return 0; ++} ++ ++int dss_dpll_init_regulator(enum dss_dpll dpll) ++{ ++ struct regulator *reg; ++ struct platform_device *pdev = dss_dpll.pdev; ++ ++ if (dpll == DSS_DPLL_NONE) ++ return 0; ++ ++ reg = devm_regulator_get(&pdev->dev, "vdda_video"); ++ if (IS_ERR(reg)) { ++ DSSERR("can't get vdda_video regulator\n"); ++ return PTR_ERR(reg); ++ } ++ ++ dss_dpll.vdda_video_reg = reg; ++ ++ return 0; ++} ++ ++int dss_dpll_configure(struct platform_device *pdev) ++{ ++ int r; ++ ++ r = dss_dpll_configure_one(pdev, DSS_DPLL_VIDEO1); ++ if (r) ++ return r; ++ ++ r = dss_dpll_configure_one(pdev, DSS_DPLL_VIDEO2); ++ if (r) ++ return r; ++ ++ dss_dpll.pdev = pdev; ++ ++ return 0; ++} ++ ++int dss_dpll_configure_ctrl(void) ++{ ++ dss_dpll.control_base = ioremap(CTRL_BASE, SZ_1K); ++ ++ if (!dss_dpll.control_base) { ++ DSSERR("can't ioremap control base\n"); ++ return -ENOMEM; ++ } ++ ++ return 0; ++} ++ ++void dss_dpll_unconfigure_ctrl(void) { ++ if (dss_dpll.control_base) ++ iounmap(dss_dpll.control_base); ++} +--- a/drivers/video/omap2/dss/dss_features.c ++++ b/drivers/video/omap2/dss/dss_features.c +@@ -93,6 +93,17 @@ static const struct dss_reg_field omap3_ + [FEAT_REG_DSIPLL_REGM_DSI] = { 26, 23 }, + }; + ++static const struct dss_reg_field am43xx_dss_reg_fields[] = { ++ [FEAT_REG_FIRHINC] = { 12, 0 }, ++ [FEAT_REG_FIRVINC] = { 28, 16 }, ++ [FEAT_REG_FIFOLOWTHRESHOLD] = { 11, 0 }, ++ [FEAT_REG_FIFOHIGHTHRESHOLD] = { 27, 16 }, ++ [FEAT_REG_FIFOSIZE] = { 10, 0 }, ++ [FEAT_REG_HORIZONTALACCU] = { 9, 0 }, ++ [FEAT_REG_VERTICALACCU] = { 25, 16 }, ++ [FEAT_REG_DISPC_CLK_SWITCH] = { 0, 0 }, ++}; ++ + static const struct dss_reg_field omap4_dss_reg_fields[] = { + [FEAT_REG_FIRHINC] = { 12, 0 }, + [FEAT_REG_FIRVINC] = { 28, 16 }, +@@ -149,6 +160,11 @@ static const enum omap_display_type omap + OMAP_DISPLAY_TYPE_VENC, + }; + ++static const enum omap_display_type am43xx_dss_supported_displays[] = { ++ /* OMAP_DSS_CHANNEL_LCD */ ++ OMAP_DISPLAY_TYPE_DPI | OMAP_DISPLAY_TYPE_DBI, ++}; ++ + static const enum omap_display_type omap4_dss_supported_displays[] = { + /* OMAP_DSS_CHANNEL_LCD */ + OMAP_DISPLAY_TYPE_DBI | OMAP_DISPLAY_TYPE_DSI, +@@ -174,6 +190,20 @@ static const enum omap_display_type omap + OMAP_DISPLAY_TYPE_DSI, + }; + ++static const enum omap_display_type dra7xx_dss_supported_displays[] = { ++ /* OMAP_DSS_CHANNEL_LCD */ ++ OMAP_DISPLAY_TYPE_DPI, ++ ++ /* OMAP_DSS_CHANNEL_DIGIT */ ++ OMAP_DISPLAY_TYPE_HDMI | OMAP_DISPLAY_TYPE_DPI, ++ ++ /* OMAP_DSS_CHANNEL_LCD2 */ ++ OMAP_DISPLAY_TYPE_DPI, ++ ++ /* OMAP_DSS_CHANNEL_LCD3 */ ++ OMAP_DISPLAY_TYPE_DPI, ++}; ++ + static const enum omap_dss_output_id omap2_dss_supported_outputs[] = { + /* OMAP_DSS_CHANNEL_LCD */ + OMAP_DSS_OUTPUT_DPI | OMAP_DSS_OUTPUT_DBI, +@@ -200,6 +230,11 @@ static const enum omap_dss_output_id oma + OMAP_DSS_OUTPUT_VENC, + }; + ++static const enum omap_dss_output_id am43xx_dss_supported_outputs[] = { ++ /* OMAP_DSS_CHANNEL_LCD */ ++ OMAP_DSS_OUTPUT_DPI | OMAP_DSS_OUTPUT_DBI, ++}; ++ + static const enum omap_dss_output_id omap4_dss_supported_outputs[] = { + /* OMAP_DSS_CHANNEL_LCD */ + OMAP_DSS_OUTPUT_DBI | OMAP_DSS_OUTPUT_DSI1, +@@ -229,6 +264,20 @@ static const enum omap_dss_output_id oma + OMAP_DSS_OUTPUT_DSI2, + }; + ++static const enum omap_dss_output_id dra7xx_dss_supported_outputs[] = { ++ /* OMAP_DSS_CHANNEL_LCD */ ++ OMAP_DSS_OUTPUT_DPI, ++ ++ /* OMAP_DSS_CHANNEL_DIGIT */ ++ OMAP_DSS_OUTPUT_HDMI | OMAP_DSS_OUTPUT_DPI, ++ ++ /* OMAP_DSS_CHANNEL_LCD2 */ ++ OMAP_DSS_OUTPUT_DPI | OMAP_DSS_OUTPUT_DPI1, ++ ++ /* OMAP_DSS_CHANNEL_LCD3 */ ++ OMAP_DSS_OUTPUT_DPI | OMAP_DSS_OUTPUT_DPI2, ++}; ++ + static const enum omap_color_mode omap2_dss_supported_color_modes[] = { + /* OMAP_DSS_GFX */ + OMAP_DSS_COLOR_CLUT1 | OMAP_DSS_COLOR_CLUT2 | +@@ -444,6 +493,13 @@ static const struct dss_param_range omap + [FEAT_PARAM_LINEWIDTH] = { 1, 1024 }, + }; + ++static const struct dss_param_range am43xx_dss_param_range[] = { ++ [FEAT_PARAM_DSS_FCK] = { 0, 200000000 }, ++ [FEAT_PARAM_DSS_PCD] = { 2, 255 }, ++ [FEAT_PARAM_DOWNSCALE] = { 1, 4 }, ++ [FEAT_PARAM_LINEWIDTH] = { 1, 1024 }, ++}; ++ + static const struct dss_param_range omap4_dss_param_range[] = { + [FEAT_PARAM_DSS_FCK] = { 0, 186000000 }, + [FEAT_PARAM_DSS_PCD] = { 1, 255 }, +@@ -520,6 +576,21 @@ static const enum dss_feat_id am35xx_dss + FEAT_OMAP3_DSI_FIFO_BUG, + }; + ++static const enum dss_feat_id am43xx_dss_feat_list[] = { ++ FEAT_LCDENABLEPOL, ++ FEAT_LCDENABLESIGNAL, ++ FEAT_PCKFREEENABLE, ++ FEAT_FUNCGATED, ++ FEAT_LINEBUFFERSPLIT, ++ FEAT_ROWREPEATENABLE, ++ FEAT_RESIZECONF, ++ FEAT_CPR, ++ FEAT_PRELOAD, ++ FEAT_FIR_COEF_V, ++ FEAT_ALPHA_FIXED_ZORDER, ++ FEAT_FIFO_MERGE, ++}; ++ + static const enum dss_feat_id omap3630_dss_feat_list[] = { + FEAT_LCDENABLEPOL, + FEAT_LCDENABLESIGNAL, +@@ -595,6 +666,7 @@ static const enum dss_feat_id omap4_dss_ + + static const enum dss_feat_id omap5_dss_feat_list[] = { + FEAT_MGR_LCD2, ++ FEAT_MGR_LCD3, + FEAT_CORE_CLK_DIV, + FEAT_LCD_CLK_SRC, + FEAT_DSI_DCS_CMD_CONFIG_VC, +@@ -681,6 +753,26 @@ static const struct omap_dss_features am + .burst_size_unit = 8, + }; + ++static const struct omap_dss_features am43xx_dss_features = { ++ .reg_fields = am43xx_dss_reg_fields, ++ .num_reg_fields = ARRAY_SIZE(am43xx_dss_reg_fields), ++ ++ .features = am43xx_dss_feat_list, ++ .num_features = ARRAY_SIZE(am43xx_dss_feat_list), ++ ++ .num_mgrs = 1, ++ .num_ovls = 3, ++ .supported_displays = am43xx_dss_supported_displays, ++ .supported_outputs = am43xx_dss_supported_outputs, ++ .supported_color_modes = omap3_dss_supported_color_modes, ++ .overlay_caps = omap3430_dss_overlay_caps, ++ .clksrc_names = omap2_dss_clk_source_names, ++ .dss_params = am43xx_dss_param_range, ++ .supported_rotation_types = OMAP_DSS_ROT_DMA, ++ .buffer_size_unit = 1, ++ .burst_size_unit = 8, ++}; ++ + static const struct omap_dss_features omap3630_dss_features = { + .reg_fields = omap3_dss_reg_fields, + .num_reg_fields = ARRAY_SIZE(omap3_dss_reg_fields), +@@ -789,49 +881,26 @@ static const struct omap_dss_features om + .burst_size_unit = 16, + }; + +-#if defined(CONFIG_OMAP4_DSS_HDMI) +-/* HDMI OMAP4 Functions*/ +-static const struct ti_hdmi_ip_ops omap4_hdmi_functions = { +- +- .video_configure = ti_hdmi_4xxx_basic_configure, +- .phy_enable = ti_hdmi_4xxx_phy_enable, +- .phy_disable = ti_hdmi_4xxx_phy_disable, +- .read_edid = ti_hdmi_4xxx_read_edid, +- .pll_enable = ti_hdmi_4xxx_pll_enable, +- .pll_disable = ti_hdmi_4xxx_pll_disable, +- .video_enable = ti_hdmi_4xxx_wp_video_start, +- .video_disable = ti_hdmi_4xxx_wp_video_stop, +- .dump_wrapper = ti_hdmi_4xxx_wp_dump, +- .dump_core = ti_hdmi_4xxx_core_dump, +- .dump_pll = ti_hdmi_4xxx_pll_dump, +- .dump_phy = ti_hdmi_4xxx_phy_dump, +-#if defined(CONFIG_OMAP4_DSS_HDMI_AUDIO) +- .audio_enable = ti_hdmi_4xxx_wp_audio_enable, +- .audio_disable = ti_hdmi_4xxx_wp_audio_disable, +- .audio_start = ti_hdmi_4xxx_audio_start, +- .audio_stop = ti_hdmi_4xxx_audio_stop, +- .audio_config = ti_hdmi_4xxx_audio_config, +- .audio_get_dma_port = ti_hdmi_4xxx_audio_get_dma_port, +-#endif +- +-}; ++/* DRA DSS Features */ ++static const struct omap_dss_features dra7xx_dss_features = { ++ .reg_fields = omap5_dss_reg_fields, ++ .num_reg_fields = ARRAY_SIZE(omap5_dss_reg_fields), + +-void dss_init_hdmi_ip_ops(struct hdmi_ip_data *ip_data, +- enum omapdss_version version) +-{ +- switch (version) { +- case OMAPDSS_VER_OMAP4430_ES1: +- case OMAPDSS_VER_OMAP4430_ES2: +- case OMAPDSS_VER_OMAP4: +- ip_data->ops = &omap4_hdmi_functions; +- break; +- default: +- ip_data->ops = NULL; +- } ++ .features = omap5_dss_feat_list, ++ .num_features = ARRAY_SIZE(omap5_dss_feat_list), + +- WARN_ON(ip_data->ops == NULL); +-} +-#endif ++ .num_mgrs = 4, ++ .num_ovls = 4, ++ .supported_displays = dra7xx_dss_supported_displays, ++ .supported_outputs = dra7xx_dss_supported_outputs, ++ .supported_color_modes = omap4_dss_supported_color_modes, ++ .overlay_caps = omap4_dss_overlay_caps, ++ .clksrc_names = omap5_dss_clk_source_names, ++ .dss_params = omap5_dss_param_range, ++ .supported_rotation_types = OMAP_DSS_ROT_DMA | OMAP_DSS_ROT_TILER, ++ .buffer_size_unit = 16, ++ .burst_size_unit = 16, ++}; + + /* Functions returning values related to a DSS feature */ + int dss_feat_get_num_mgrs(void) +@@ -967,10 +1036,18 @@ void dss_features_init(enum omapdss_vers + omap_current_dss_features = &omap5_dss_features; + break; + ++ case OMAPDSS_VER_DRA7xx: ++ omap_current_dss_features = &dra7xx_dss_features; ++ break; ++ + case OMAPDSS_VER_AM35xx: + omap_current_dss_features = &am35xx_dss_features; + break; + ++ case OMAPDSS_VER_AM43xx: ++ omap_current_dss_features = &am43xx_dss_features; ++ break; ++ + default: + DSSWARN("Unsupported OMAP version"); + break; +--- a/drivers/video/omap2/dss/dss_features.h ++++ b/drivers/video/omap2/dss/dss_features.h +@@ -20,10 +20,6 @@ + #ifndef __OMAP2_DSS_FEATURES_H + #define __OMAP2_DSS_FEATURES_H + +-#if defined(CONFIG_OMAP4_DSS_HDMI) +-#include "ti_hdmi.h" +-#endif +- + #define MAX_DSS_MANAGERS 4 + #define MAX_DSS_OVERLAYS 4 + #define MAX_DSS_LCD_MANAGERS 3 +@@ -117,8 +113,4 @@ bool dss_feat_rotation_type_supported(en + bool dss_has_feature(enum dss_feat_id id); + void dss_feat_get_reg_field(enum dss_feat_reg_field id, u8 *start, u8 *end); + void dss_features_init(enum omapdss_version version); +-#if defined(CONFIG_OMAP4_DSS_HDMI) +-void dss_init_hdmi_ip_ops(struct hdmi_ip_data *ip_data, +- enum omapdss_version version); +-#endif + #endif +--- a/drivers/video/omap2/dss/dss.h ++++ b/drivers/video/omap2/dss/dss.h +@@ -100,6 +100,13 @@ enum dss_writeback_channel { + DSS_WB_LCD3_MGR = 7, + }; + ++enum dss_dpll { ++ DSS_DPLL_VIDEO1 = 0, ++ DSS_DPLL_VIDEO2, ++ DSS_DPLL_HDMI, ++ DSS_DPLL_NONE, ++}; ++ + struct dss_clock_info { + /* rates that we get with dividers below */ + unsigned long fck; +@@ -139,6 +146,12 @@ struct dsi_clock_info { + u16 lp_clk_div; + }; + ++struct dss_dpll_cinfo { ++ unsigned long fint, clkin, clkout, hsdiv_clk; ++ ++ u16 regm, regn, regm_hsdiv; ++}; ++ + struct reg_field { + u16 reg; + u8 high; +@@ -223,9 +236,10 @@ int dss_init_platform_driver(void) __ini + void dss_uninit_platform_driver(void); + + unsigned long dss_get_dispc_clk_rate(void); +-int dss_dpi_select_source(enum omap_channel channel); ++int dss_dpi_select_source(int module_id, enum omap_channel channel); + void dss_select_hdmi_venc_clk_source(enum dss_hdmi_venc_clk_source_select); + enum dss_hdmi_venc_clk_source_select dss_get_hdmi_venc_clk_source(void); ++void dss_use_dpll_lcd(enum omap_channel channel, bool use_dpll); + const char *dss_get_generic_clk_source_name(enum omap_dss_clk_source clk_src); + void dss_dump_clocks(struct seq_file *s); + +@@ -372,6 +386,10 @@ static inline bool dsi_pll_calc(struct p + int dpi_init_platform_driver(void) __init; + void dpi_uninit_platform_driver(void) __exit; + ++/* DRA7x DPI */ ++int dra7xx_dpi_init_platform_driver(void) __init; ++void dra7xx_dpi_uninit_platform_driver(void) __exit; ++ + /* DISPC */ + int dispc_init_platform_driver(void) __init; + void dispc_uninit_platform_driver(void) __exit; +@@ -398,12 +416,6 @@ unsigned long dispc_fclk_rate(void); + int dispc_calc_clock_rates(unsigned long dispc_fclk_rate, + struct dispc_clock_info *cinfo); + +- +-void dispc_ovl_set_fifo_threshold(enum omap_plane plane, u32 low, u32 high); +-void dispc_ovl_compute_fifo_thresholds(enum omap_plane plane, +- u32 *fifo_low, u32 *fifo_high, bool use_fifomerge, +- bool manual_update); +- + unsigned long dispc_mgr_lclk_rate(enum omap_channel channel); + unsigned long dispc_mgr_pclk_rate(enum omap_channel channel); + unsigned long dispc_core_clk_rate(void); +@@ -427,8 +439,11 @@ int venc_init_platform_driver(void) __in + void venc_uninit_platform_driver(void) __exit; + + /* HDMI */ +-int hdmi_init_platform_driver(void) __init; +-void hdmi_uninit_platform_driver(void) __exit; ++int hdmi4_init_platform_driver(void) __init; ++void hdmi4_uninit_platform_driver(void) __exit; ++ ++int hdmi5_init_platform_driver(void) __init; ++void hdmi5_uninit_platform_driver(void) __exit; + + /* RFBI */ + int rfbi_init_platform_driver(void) __init; +@@ -446,4 +461,27 @@ static inline void dss_collect_irq_stats + } + #endif + ++typedef bool (*dss_dpll_calc_func)(int regn, int regm, unsigned long fint, ++ unsigned long pll, void *data); ++typedef bool (*dss_dpll_hsdiv_calc_func)(int regm_dispc, unsigned long dispc, ++ void *data); ++bool dss_dpll_disabled(enum dss_dpll dpll); ++unsigned long dpll_get_clkin(enum dss_dpll dpll); ++bool dss_dpll_calc(enum dss_dpll dpll, unsigned long clkin, ++ unsigned long pll_min, unsigned long pll_max, ++ dss_dpll_calc_func func, void *data); ++bool dss_dpll_hsdiv_calc(enum dss_dpll dpll, unsigned long pll, ++ unsigned long out_min, dss_dpll_hsdiv_calc_func func, ++ void *data); ++int dss_dpll_set_clock_div(enum dss_dpll dpll, struct dss_dpll_cinfo *cinfo); ++ ++void dss_dpll_enable_ctrl(enum dss_dpll dpll, bool enable); ++int dss_dpll_activate(enum dss_dpll dpll); ++void dss_dpll_set_control_mux(enum omap_channel channel, enum dss_dpll dpll); ++void dss_dpll_disable(enum dss_dpll dpll); ++int dss_dpll_init_regulator(enum dss_dpll dpll); ++int dss_dpll_configure(struct platform_device *pdev); ++int dss_dpll_configure_ctrl(void); ++void dss_dpll_unconfigure_ctrl(void); ++ + #endif +--- /dev/null ++++ b/drivers/video/omap2/dss/hdmi4.c +@@ -0,0 +1,761 @@ ++/* ++ * HDMI interface DSS driver for TI's OMAP4 family of SoCs. ++ * Copyright (C) 2010-2011 Texas Instruments Incorporated - http://www.ti.com/ ++ * Authors: Yong Zhi ++ * Mythri pk <mythripk@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, see <http://www.gnu.org/licenses/>. ++ */ ++ ++#define DSS_SUBSYS_NAME "HDMI" ++ ++#include <linux/kernel.h> ++#include <linux/module.h> ++#include <linux/err.h> ++#include <linux/io.h> ++#include <linux/interrupt.h> ++#include <linux/mutex.h> ++#include <linux/delay.h> ++#include <linux/string.h> ++#include <linux/platform_device.h> ++#include <linux/pm_runtime.h> ++#include <linux/clk.h> ++#include <linux/gpio.h> ++#include <linux/regulator/consumer.h> ++#include <video/omapdss.h> ++ ++#include "hdmi4_core.h" ++#include "dss.h" ++#include "dss_features.h" ++ ++static struct { ++ struct mutex lock; ++ struct platform_device *pdev; ++ ++ struct hdmi_wp_data wp; ++ struct hdmi_pll_data pll; ++ struct hdmi_phy_data phy; ++ struct hdmi_core_data core; ++ ++ struct hdmi_config cfg; ++ ++ struct clk *sys_clk; ++ struct regulator *vdda_hdmi_dac_reg; ++ ++ bool core_enabled; ++ ++ struct omap_dss_device output; ++} hdmi; ++ ++static int hdmi_runtime_get(void) ++{ ++ int r; ++ ++ DSSDBG("hdmi_runtime_get\n"); ++ ++ r = pm_runtime_get_sync(&hdmi.pdev->dev); ++ WARN_ON(r < 0); ++ if (r < 0) ++ return r; ++ ++ return 0; ++} ++ ++static void hdmi_runtime_put(void) ++{ ++ int r; ++ ++ DSSDBG("hdmi_runtime_put\n"); ++ ++ r = pm_runtime_put_sync(&hdmi.pdev->dev); ++ WARN_ON(r < 0 && r != -ENOSYS); ++} ++ ++static irqreturn_t hdmi_irq_handler(int irq, void *data) ++{ ++ struct hdmi_wp_data *wp = data; ++ u32 irqstatus; ++ ++ irqstatus = hdmi_wp_get_irqstatus(wp); ++ hdmi_wp_set_irqstatus(wp, irqstatus); ++ ++ if ((irqstatus & HDMI_IRQ_LINK_CONNECT) && ++ irqstatus & HDMI_IRQ_LINK_DISCONNECT) { ++ /* ++ * If we get both connect and disconnect interrupts at the same ++ * time, turn off the PHY, clear interrupts, and restart, which ++ * raises connect interrupt if a cable is connected, or nothing ++ * if cable is not connected. ++ */ ++ hdmi_wp_set_phy_pwr(wp, HDMI_PHYPWRCMD_OFF); ++ ++ hdmi_wp_set_irqstatus(wp, HDMI_IRQ_LINK_CONNECT | ++ HDMI_IRQ_LINK_DISCONNECT); ++ ++ hdmi_wp_set_phy_pwr(wp, HDMI_PHYPWRCMD_LDOON); ++ } else if (irqstatus & HDMI_IRQ_LINK_CONNECT) { ++ hdmi_wp_set_phy_pwr(wp, HDMI_PHYPWRCMD_TXON); ++ } else if (irqstatus & HDMI_IRQ_LINK_DISCONNECT) { ++ hdmi_wp_set_phy_pwr(wp, HDMI_PHYPWRCMD_LDOON); ++ } ++ ++ return IRQ_HANDLED; ++} ++ ++static int hdmi_init_regulator(void) ++{ ++ int r; ++ struct regulator *reg; ++ ++ if (hdmi.vdda_hdmi_dac_reg != NULL) ++ return 0; ++ ++ reg = devm_regulator_get(&hdmi.pdev->dev, "vdda_hdmi_dac"); ++ if (IS_ERR(reg)) { ++ DSSERR("can't get VDDA_HDMI_DAC regulator\n"); ++ return PTR_ERR(reg); ++ } ++ ++ r = regulator_set_voltage(reg, 1800000, 1980000); ++ if (r) ++ DSSWARN("can't set the regulator voltage"); ++ ++ hdmi.vdda_hdmi_dac_reg = reg; ++ ++ return 0; ++} ++ ++static int hdmi_power_on_core(struct omap_dss_device *dssdev) ++{ ++ int r; ++ ++ r = regulator_enable(hdmi.vdda_hdmi_dac_reg); ++ if (r) ++ return r; ++ ++ r = hdmi_runtime_get(); ++ if (r) ++ goto err_runtime_get; ++ ++ /* Make selection of HDMI in DSS */ ++ dss_select_hdmi_venc_clk_source(DSS_HDMI_M_PCLK); ++ ++ hdmi.core_enabled = true; ++ ++ return 0; ++ ++err_runtime_get: ++ regulator_disable(hdmi.vdda_hdmi_dac_reg); ++ ++ return r; ++} ++ ++static void hdmi_power_off_core(struct omap_dss_device *dssdev) ++{ ++ hdmi.core_enabled = false; ++ ++ hdmi_runtime_put(); ++ regulator_disable(hdmi.vdda_hdmi_dac_reg); ++} ++ ++static int hdmi_power_on_full(struct omap_dss_device *dssdev) ++{ ++ int r; ++ struct omap_video_timings *p; ++ struct omap_overlay_manager *mgr = hdmi.output.manager; ++ unsigned long phy; ++ struct hdmi_wp_data *wp = &hdmi.wp; ++ ++ r = hdmi_power_on_core(dssdev); ++ if (r) ++ return r; ++ ++ /* disable and clear irqs */ ++ hdmi_wp_clear_irqenable(wp, 0xffffffff); ++ hdmi_wp_set_irqstatus(wp, 0xffffffff); ++ ++ p = &hdmi.cfg.timings; ++ ++ DSSDBG("hdmi_power_on x_res= %d y_res = %d\n", p->x_res, p->y_res); ++ ++ phy = p->pixel_clock; ++ ++ hdmi_pll_compute(&hdmi.pll, clk_get_rate(hdmi.sys_clk), phy); ++ ++ /* config the PLL and PHY hdmi_set_pll_pwrfirst */ ++ r = hdmi_pll_enable(&hdmi.pll, &hdmi.wp); ++ if (r) { ++ DSSDBG("Failed to lock PLL\n"); ++ goto err_pll_enable; ++ } ++ ++ r = hdmi_phy_configure(&hdmi.phy, &hdmi.cfg); ++ if (r) { ++ DSSDBG("Failed to configure PHY\n"); ++ goto err_phy_cfg; ++ } ++ ++ r = hdmi_wp_set_phy_pwr(wp, HDMI_PHYPWRCMD_LDOON); ++ if (r) ++ goto err_phy_pwr; ++ ++ hdmi4_configure(&hdmi.core, &hdmi.wp, &hdmi.cfg); ++ ++ /* bypass TV gamma table */ ++ dispc_enable_gamma_table(0); ++ ++ /* tv size */ ++ dss_mgr_set_timings(mgr, p); ++ ++ r = hdmi_wp_video_start(&hdmi.wp); ++ if (r) ++ goto err_vid_enable; ++ ++ r = dss_mgr_enable(mgr); ++ if (r) ++ goto err_mgr_enable; ++ ++ hdmi_wp_set_irqenable(wp, ++ HDMI_IRQ_LINK_CONNECT | HDMI_IRQ_LINK_DISCONNECT); ++ ++ return 0; ++ ++err_mgr_enable: ++ hdmi_wp_video_stop(&hdmi.wp); ++err_vid_enable: ++err_phy_cfg: ++ hdmi_wp_set_phy_pwr(&hdmi.wp, HDMI_PHYPWRCMD_OFF); ++err_phy_pwr: ++ hdmi_pll_disable(&hdmi.pll, &hdmi.wp); ++err_pll_enable: ++ hdmi_power_off_core(dssdev); ++ return -EIO; ++} ++ ++static void hdmi_power_off_full(struct omap_dss_device *dssdev) ++{ ++ struct omap_overlay_manager *mgr = hdmi.output.manager; ++ ++ hdmi_wp_clear_irqenable(&hdmi.wp, 0xffffffff); ++ ++ dss_mgr_disable(mgr); ++ ++ hdmi_wp_video_stop(&hdmi.wp); ++ ++ hdmi_wp_set_phy_pwr(&hdmi.wp, HDMI_PHYPWRCMD_OFF); ++ ++ hdmi_pll_disable(&hdmi.pll, &hdmi.wp); ++ ++ hdmi_power_off_core(dssdev); ++} ++ ++static int hdmi_display_check_timing(struct omap_dss_device *dssdev, ++ struct omap_video_timings *timings) ++{ ++ struct hdmi_cm cm; ++ ++ cm = hdmi_get_code(timings); ++ if (cm.code == -1) ++ return -EINVAL; ++ ++ return 0; ++ ++} ++ ++static void hdmi_display_set_timing(struct omap_dss_device *dssdev, ++ struct omap_video_timings *timings) ++{ ++ struct hdmi_cm cm; ++ const struct hdmi_config *t; ++ ++ mutex_lock(&hdmi.lock); ++ ++ cm = hdmi_get_code(timings); ++ hdmi.cfg.cm = cm; ++ ++ t = hdmi_get_timings(cm.mode, cm.code); ++ if (t != NULL) { ++ hdmi.cfg = *t; ++ ++ dispc_set_tv_pclk(t->timings.pixel_clock * 1000); ++ } ++ ++ mutex_unlock(&hdmi.lock); ++} ++ ++static void hdmi_display_get_timings(struct omap_dss_device *dssdev, ++ struct omap_video_timings *timings) ++{ ++ const struct hdmi_config *cfg; ++ struct hdmi_cm cm = hdmi.cfg.cm; ++ ++ cfg = hdmi_get_timings(cm.mode, cm.code); ++ if (cfg == NULL) ++ cfg = hdmi_default_timing(); ++ ++ memcpy(timings, &cfg->timings, sizeof(cfg->timings)); ++} ++ ++static void hdmi_dump_regs(struct seq_file *s) ++{ ++ mutex_lock(&hdmi.lock); ++ ++ if (hdmi_runtime_get()) { ++ mutex_unlock(&hdmi.lock); ++ return; ++ } ++ ++ hdmi_wp_dump(&hdmi.wp, s); ++ hdmi_pll_dump(&hdmi.pll, s); ++ hdmi_phy_dump(&hdmi.phy, s); ++ hdmi4_core_dump(&hdmi.core, s); ++ ++ hdmi_runtime_put(); ++ mutex_unlock(&hdmi.lock); ++} ++ ++static int read_edid(u8 *buf, int len) ++{ ++ int r; ++ ++ mutex_lock(&hdmi.lock); ++ ++ r = hdmi_runtime_get(); ++ BUG_ON(r); ++ ++ r = hdmi4_read_edid(&hdmi.core, buf, len); ++ ++ hdmi_runtime_put(); ++ mutex_unlock(&hdmi.lock); ++ ++ return r; ++} ++ ++static int hdmi_display_enable(struct omap_dss_device *dssdev) ++{ ++ struct omap_dss_device *out = &hdmi.output; ++ int r = 0; ++ ++ DSSDBG("ENTER hdmi_display_enable\n"); ++ ++ mutex_lock(&hdmi.lock); ++ ++ if (out == NULL || out->manager == NULL) { ++ DSSERR("failed to enable display: no output/manager\n"); ++ r = -ENODEV; ++ goto err0; ++ } ++ ++ r = hdmi_power_on_full(dssdev); ++ if (r) { ++ DSSERR("failed to power on device\n"); ++ goto err0; ++ } ++ ++ mutex_unlock(&hdmi.lock); ++ return 0; ++ ++err0: ++ mutex_unlock(&hdmi.lock); ++ return r; ++} ++ ++static void hdmi_display_disable(struct omap_dss_device *dssdev) ++{ ++ DSSDBG("Enter hdmi_display_disable\n"); ++ ++ mutex_lock(&hdmi.lock); ++ ++ hdmi_power_off_full(dssdev); ++ ++ mutex_unlock(&hdmi.lock); ++} ++ ++static int hdmi_core_enable(struct omap_dss_device *dssdev) ++{ ++ int r = 0; ++ ++ DSSDBG("ENTER omapdss_hdmi_core_enable\n"); ++ ++ mutex_lock(&hdmi.lock); ++ ++ r = hdmi_power_on_core(dssdev); ++ if (r) { ++ DSSERR("failed to power on device\n"); ++ goto err0; ++ } ++ ++ mutex_unlock(&hdmi.lock); ++ return 0; ++ ++err0: ++ mutex_unlock(&hdmi.lock); ++ return r; ++} ++ ++static void hdmi_core_disable(struct omap_dss_device *dssdev) ++{ ++ DSSDBG("Enter omapdss_hdmi_core_disable\n"); ++ ++ mutex_lock(&hdmi.lock); ++ ++ hdmi_power_off_core(dssdev); ++ ++ mutex_unlock(&hdmi.lock); ++} ++ ++static int hdmi_get_clocks(struct platform_device *pdev) ++{ ++ struct clk *clk; ++ ++ clk = devm_clk_get(&pdev->dev, "sys_clk"); ++ if (IS_ERR(clk)) { ++ DSSERR("can't get sys_clk\n"); ++ return PTR_ERR(clk); ++ } ++ ++ hdmi.sys_clk = clk; ++ ++ return 0; ++} ++ ++static int hdmi_connect(struct omap_dss_device *dssdev, ++ struct omap_dss_device *dst) ++{ ++ struct omap_overlay_manager *mgr; ++ int r; ++ ++ r = hdmi_init_regulator(); ++ if (r) ++ return r; ++ ++ mgr = omap_dss_get_overlay_manager(dssdev->dispc_channel); ++ if (!mgr) ++ return -ENODEV; ++ ++ r = dss_mgr_connect(mgr, dssdev); ++ if (r) ++ return r; ++ ++ r = omapdss_output_set_device(dssdev, dst); ++ if (r) { ++ DSSERR("failed to connect output to new device: %s\n", ++ dst->name); ++ dss_mgr_disconnect(mgr, dssdev); ++ return r; ++ } ++ ++ return 0; ++} ++ ++static void hdmi_disconnect(struct omap_dss_device *dssdev, ++ struct omap_dss_device *dst) ++{ ++ WARN_ON(dst != dssdev->dst); ++ ++ if (dst != dssdev->dst) ++ return; ++ ++ omapdss_output_unset_device(dssdev); ++ ++ if (dssdev->manager) ++ dss_mgr_disconnect(dssdev->manager, dssdev); ++} ++ ++static int hdmi_read_edid(struct omap_dss_device *dssdev, ++ u8 *edid, int len) ++{ ++ bool need_enable; ++ int r; ++ ++ need_enable = hdmi.core_enabled == false; ++ ++ if (need_enable) { ++ r = hdmi_core_enable(dssdev); ++ if (r) ++ return r; ++ } ++ ++ r = read_edid(edid, len); ++ ++ if (need_enable) ++ hdmi_core_disable(dssdev); ++ ++ return r; ++} ++ ++#if defined(CONFIG_OMAP4_DSS_HDMI_AUDIO) ++static int hdmi_audio_enable(struct omap_dss_device *dssdev) ++{ ++ int r; ++ ++ mutex_lock(&hdmi.lock); ++ ++ if (!hdmi_mode_has_audio(hdmi.cfg.cm.mode)) { ++ r = -EPERM; ++ goto err; ++ } ++ ++ r = hdmi_wp_audio_enable(&hdmi.wp, true); ++ if (r) ++ goto err; ++ ++ mutex_unlock(&hdmi.lock); ++ return 0; ++ ++err: ++ mutex_unlock(&hdmi.lock); ++ return r; ++} ++ ++static void hdmi_audio_disable(struct omap_dss_device *dssdev) ++{ ++ hdmi_wp_audio_enable(&hdmi.wp, false); ++} ++ ++static int hdmi_audio_start(struct omap_dss_device *dssdev) ++{ ++ return hdmi4_audio_start(&hdmi.core, &hdmi.wp); ++} ++ ++static void hdmi_audio_stop(struct omap_dss_device *dssdev) ++{ ++ hdmi4_audio_stop(&hdmi.core, &hdmi.wp); ++} ++ ++static bool hdmi_audio_supported(struct omap_dss_device *dssdev) ++{ ++ bool r; ++ ++ mutex_lock(&hdmi.lock); ++ ++ r = hdmi_mode_has_audio(hdmi.cfg.cm.mode); ++ ++ mutex_unlock(&hdmi.lock); ++ return r; ++} ++ ++static int hdmi_audio_config(struct omap_dss_device *dssdev, ++ struct omap_dss_audio *audio) ++{ ++ int r; ++ u32 pclk = hdmi.cfg.timings.pixel_clock; ++ ++ mutex_lock(&hdmi.lock); ++ ++ if (!hdmi_mode_has_audio(hdmi.cfg.cm.mode)) { ++ r = -EPERM; ++ goto err; ++ } ++ ++ r = hdmi4_audio_config(&hdmi.core, &hdmi.wp, audio, pclk); ++ if (r) ++ goto err; ++ ++ mutex_unlock(&hdmi.lock); ++ return 0; ++ ++err: ++ mutex_unlock(&hdmi.lock); ++ return r; ++} ++#else ++static int hdmi_audio_enable(struct omap_dss_device *dssdev) ++{ ++ return -EPERM; ++} ++ ++static void hdmi_audio_disable(struct omap_dss_device *dssdev) ++{ ++} ++ ++static int hdmi_audio_start(struct omap_dss_device *dssdev) ++{ ++ return -EPERM; ++} ++ ++static void hdmi_audio_stop(struct omap_dss_device *dssdev) ++{ ++} ++ ++static bool hdmi_audio_supported(struct omap_dss_device *dssdev) ++{ ++ return false; ++} ++ ++static int hdmi_audio_config(struct omap_dss_device *dssdev, ++ struct omap_dss_audio *audio) ++{ ++ return -EPERM; ++} ++#endif ++ ++static const struct omapdss_hdmi_ops hdmi_ops = { ++ .connect = hdmi_connect, ++ .disconnect = hdmi_disconnect, ++ ++ .enable = hdmi_display_enable, ++ .disable = hdmi_display_disable, ++ ++ .check_timings = hdmi_display_check_timing, ++ .set_timings = hdmi_display_set_timing, ++ .get_timings = hdmi_display_get_timings, ++ ++ .read_edid = hdmi_read_edid, ++ ++ .audio_enable = hdmi_audio_enable, ++ .audio_disable = hdmi_audio_disable, ++ .audio_start = hdmi_audio_start, ++ .audio_stop = hdmi_audio_stop, ++ .audio_supported = hdmi_audio_supported, ++ .audio_config = hdmi_audio_config, ++}; ++ ++static void hdmi_init_output(struct platform_device *pdev) ++{ ++ struct omap_dss_device *out = &hdmi.output; ++ ++ out->dev = &pdev->dev; ++ out->id = OMAP_DSS_OUTPUT_HDMI; ++ out->output_type = OMAP_DISPLAY_TYPE_HDMI; ++ out->name = "hdmi.0"; ++ out->dispc_channel = OMAP_DSS_CHANNEL_DIGIT; ++ out->ops.hdmi = &hdmi_ops; ++ out->owner = THIS_MODULE; ++ ++ omapdss_register_output(out); ++} ++ ++static void __exit hdmi_uninit_output(struct platform_device *pdev) ++{ ++ struct omap_dss_device *out = &hdmi.output; ++ ++ omapdss_unregister_output(out); ++} ++ ++/* HDMI HW IP initialisation */ ++static int omapdss_hdmihw_probe(struct platform_device *pdev) ++{ ++ int r; ++ int irq; ++ ++ hdmi.pdev = pdev; ++ ++ mutex_init(&hdmi.lock); ++ ++ r = hdmi_wp_init(pdev, &hdmi.wp); ++ if (r) ++ return r; ++ ++ r = hdmi_pll_init(pdev, &hdmi.pll); ++ if (r) ++ return r; ++ ++ r = hdmi_phy_init(pdev, &hdmi.phy); ++ if (r) ++ return r; ++ ++ r = hdmi4_core_init(pdev, &hdmi.core); ++ if (r) ++ return r; ++ ++ r = hdmi_get_clocks(pdev); ++ if (r) { ++ DSSERR("can't get clocks\n"); ++ return r; ++ } ++ ++ irq = platform_get_irq(pdev, 0); ++ if (irq < 0) { ++ DSSERR("platform_get_irq failed\n"); ++ return -ENODEV; ++ } ++ ++ r = devm_request_threaded_irq(&pdev->dev, irq, ++ NULL, hdmi_irq_handler, ++ IRQF_ONESHOT, "OMAP HDMI", &hdmi.wp); ++ if (r) { ++ DSSERR("HDMI IRQ request failed\n"); ++ return r; ++ } ++ ++ pm_runtime_enable(&pdev->dev); ++ ++ hdmi_init_output(pdev); ++ ++ dss_debugfs_create_file("hdmi", hdmi_dump_regs); ++ ++ return 0; ++} ++ ++static int __exit omapdss_hdmihw_remove(struct platform_device *pdev) ++{ ++ hdmi_uninit_output(pdev); ++ ++ pm_runtime_disable(&pdev->dev); ++ ++ return 0; ++} ++ ++static int hdmi_runtime_suspend(struct device *dev) ++{ ++ clk_disable_unprepare(hdmi.sys_clk); ++ ++ dispc_runtime_put(); ++ ++ return 0; ++} ++ ++static int hdmi_runtime_resume(struct device *dev) ++{ ++ int r; ++ ++ r = dispc_runtime_get(); ++ if (r < 0) ++ return r; ++ ++ clk_prepare_enable(hdmi.sys_clk); ++ ++ return 0; ++} ++ ++static const struct dev_pm_ops hdmi_pm_ops = { ++ .runtime_suspend = hdmi_runtime_suspend, ++ .runtime_resume = hdmi_runtime_resume, ++}; ++ ++static const struct of_device_id hdmi_of_match[] = { ++ { .compatible = "ti,omap4-hdmi", }, ++ {}, ++}; ++ ++static struct platform_driver omapdss_hdmihw_driver = { ++ .probe = omapdss_hdmihw_probe, ++ .remove = __exit_p(omapdss_hdmihw_remove), ++ .driver = { ++ .name = "omapdss_hdmi", ++ .owner = THIS_MODULE, ++ .pm = &hdmi_pm_ops, ++ .of_match_table = hdmi_of_match, ++ }, ++}; ++ ++int __init hdmi4_init_platform_driver(void) ++{ ++ return platform_driver_register(&omapdss_hdmihw_driver); ++} ++ ++void __exit hdmi4_uninit_platform_driver(void) ++{ ++ platform_driver_unregister(&omapdss_hdmihw_driver); ++} +--- /dev/null ++++ b/drivers/video/omap2/dss/hdmi4_core.c +@@ -0,0 +1,1016 @@ ++/* ++ * ti_hdmi_4xxx_ip.c ++ * ++ * HDMI TI81xx, TI38xx, TI OMAP4 etc IP driver Library ++ * Copyright (C) 2010-2011 Texas Instruments Incorporated - http://www.ti.com/ ++ * Authors: Yong Zhi ++ * Mythri pk <mythripk@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, see <http://www.gnu.org/licenses/>. ++ */ ++ ++#include <linux/kernel.h> ++#include <linux/module.h> ++#include <linux/err.h> ++#include <linux/io.h> ++#include <linux/interrupt.h> ++#include <linux/mutex.h> ++#include <linux/delay.h> ++#include <linux/platform_device.h> ++#include <linux/string.h> ++#include <linux/seq_file.h> ++#if defined(CONFIG_OMAP4_DSS_HDMI_AUDIO) ++#include <sound/asound.h> ++#include <sound/asoundef.h> ++#endif ++ ++#include "hdmi4_core.h" ++#include "dss_features.h" ++ ++#define HDMI_CORE_AV 0x500 ++ ++static inline void __iomem *hdmi_av_base(struct hdmi_core_data *core) ++{ ++ return core->base + HDMI_CORE_AV; ++} ++ ++static int hdmi_core_ddc_init(struct hdmi_core_data *core) ++{ ++ void __iomem *base = core->base; ++ ++ /* Turn on CLK for DDC */ ++ REG_FLD_MOD(base, HDMI_CORE_AV_DPD, 0x7, 2, 0); ++ ++ /* IN_PROG */ ++ if (REG_GET(base, HDMI_CORE_DDC_STATUS, 4, 4) == 1) { ++ /* Abort transaction */ ++ REG_FLD_MOD(base, HDMI_CORE_DDC_CMD, 0xf, 3, 0); ++ /* IN_PROG */ ++ if (hdmi_wait_for_bit_change(base, HDMI_CORE_DDC_STATUS, ++ 4, 4, 0) != 0) { ++ DSSERR("Timeout aborting DDC transaction\n"); ++ return -ETIMEDOUT; ++ } ++ } ++ ++ /* Clk SCL Devices */ ++ REG_FLD_MOD(base, HDMI_CORE_DDC_CMD, 0xA, 3, 0); ++ ++ /* HDMI_CORE_DDC_STATUS_IN_PROG */ ++ if (hdmi_wait_for_bit_change(base, HDMI_CORE_DDC_STATUS, ++ 4, 4, 0) != 0) { ++ DSSERR("Timeout starting SCL clock\n"); ++ return -ETIMEDOUT; ++ } ++ ++ /* Clear FIFO */ ++ REG_FLD_MOD(base, HDMI_CORE_DDC_CMD, 0x9, 3, 0); ++ ++ /* HDMI_CORE_DDC_STATUS_IN_PROG */ ++ if (hdmi_wait_for_bit_change(base, HDMI_CORE_DDC_STATUS, ++ 4, 4, 0) != 0) { ++ DSSERR("Timeout clearing DDC fifo\n"); ++ return -ETIMEDOUT; ++ } ++ ++ return 0; ++} ++ ++static int hdmi_core_ddc_edid(struct hdmi_core_data *core, ++ u8 *pedid, int ext) ++{ ++ void __iomem *base = core->base; ++ u32 i; ++ char checksum; ++ u32 offset = 0; ++ ++ /* HDMI_CORE_DDC_STATUS_IN_PROG */ ++ if (hdmi_wait_for_bit_change(base, HDMI_CORE_DDC_STATUS, ++ 4, 4, 0) != 0) { ++ DSSERR("Timeout waiting DDC to be ready\n"); ++ return -ETIMEDOUT; ++ } ++ ++ if (ext % 2 != 0) ++ offset = 0x80; ++ ++ /* Load Segment Address Register */ ++ REG_FLD_MOD(base, HDMI_CORE_DDC_SEGM, ext / 2, 7, 0); ++ ++ /* Load Slave Address Register */ ++ REG_FLD_MOD(base, HDMI_CORE_DDC_ADDR, 0xA0 >> 1, 7, 1); ++ ++ /* Load Offset Address Register */ ++ REG_FLD_MOD(base, HDMI_CORE_DDC_OFFSET, offset, 7, 0); ++ ++ /* Load Byte Count */ ++ REG_FLD_MOD(base, HDMI_CORE_DDC_COUNT1, 0x80, 7, 0); ++ REG_FLD_MOD(base, HDMI_CORE_DDC_COUNT2, 0x0, 1, 0); ++ ++ /* Set DDC_CMD */ ++ if (ext) ++ REG_FLD_MOD(base, HDMI_CORE_DDC_CMD, 0x4, 3, 0); ++ else ++ REG_FLD_MOD(base, HDMI_CORE_DDC_CMD, 0x2, 3, 0); ++ ++ /* HDMI_CORE_DDC_STATUS_BUS_LOW */ ++ if (REG_GET(base, HDMI_CORE_DDC_STATUS, 6, 6) == 1) { ++ pr_err("I2C Bus Low?\n"); ++ return -EIO; ++ } ++ /* HDMI_CORE_DDC_STATUS_NO_ACK */ ++ if (REG_GET(base, HDMI_CORE_DDC_STATUS, 5, 5) == 1) { ++ pr_err("I2C No Ack\n"); ++ return -EIO; ++ } ++ ++ for (i = 0; i < 0x80; ++i) { ++ int t; ++ ++ /* IN_PROG */ ++ if (REG_GET(base, HDMI_CORE_DDC_STATUS, 4, 4) == 0) { ++ DSSERR("operation stopped when reading edid\n"); ++ return -EIO; ++ } ++ ++ t = 0; ++ /* FIFO_EMPTY */ ++ while (REG_GET(base, HDMI_CORE_DDC_STATUS, 2, 2) == 1) { ++ if (t++ > 10000) { ++ DSSERR("timeout reading edid\n"); ++ return -ETIMEDOUT; ++ } ++ udelay(1); ++ } ++ ++ pedid[i] = REG_GET(base, HDMI_CORE_DDC_DATA, 7, 0); ++ } ++ ++ checksum = 0; ++ for (i = 0; i < 0x80; ++i) ++ checksum += pedid[i]; ++ ++ if (checksum != 0) { ++ pr_err("E-EDID checksum failed!!\n"); ++ return -EIO; ++ } ++ ++ return 0; ++} ++ ++int hdmi4_read_edid(struct hdmi_core_data *core, u8 *edid, int len) ++{ ++ int r, l; ++ ++ if (len < 128) ++ return -EINVAL; ++ ++ r = hdmi_core_ddc_init(core); ++ if (r) ++ return r; ++ ++ r = hdmi_core_ddc_edid(core, edid, 0); ++ if (r) ++ return r; ++ ++ l = 128; ++ ++ if (len >= 128 * 2 && edid[0x7e] > 0) { ++ r = hdmi_core_ddc_edid(core, edid + 0x80, 1); ++ if (r) ++ return r; ++ l += 128; ++ } ++ ++ return l; ++} ++ ++static void hdmi_core_init(struct hdmi_core_video_config *video_cfg, ++ struct hdmi_core_infoframe_avi *avi_cfg, ++ struct hdmi_core_packet_enable_repeat *repeat_cfg) ++{ ++ pr_debug("Enter hdmi_core_init\n"); ++ ++ /* video core */ ++ video_cfg->ip_bus_width = HDMI_INPUT_8BIT; ++ video_cfg->op_dither_truc = HDMI_OUTPUTTRUNCATION_8BIT; ++ video_cfg->deep_color_pkt = HDMI_DEEPCOLORPACKECTDISABLE; ++ video_cfg->pkt_mode = HDMI_PACKETMODERESERVEDVALUE; ++ video_cfg->hdmi_dvi = HDMI_DVI; ++ video_cfg->tclk_sel_clkmult = HDMI_FPLL10IDCK; ++ ++ /* info frame */ ++ avi_cfg->db1_format = 0; ++ avi_cfg->db1_active_info = 0; ++ avi_cfg->db1_bar_info_dv = 0; ++ avi_cfg->db1_scan_info = 0; ++ avi_cfg->db2_colorimetry = 0; ++ avi_cfg->db2_aspect_ratio = 0; ++ avi_cfg->db2_active_fmt_ar = 0; ++ avi_cfg->db3_itc = 0; ++ avi_cfg->db3_ec = 0; ++ avi_cfg->db3_q_range = 0; ++ avi_cfg->db3_nup_scaling = 0; ++ avi_cfg->db4_videocode = 0; ++ avi_cfg->db5_pixel_repeat = 0; ++ avi_cfg->db6_7_line_eoftop = 0; ++ avi_cfg->db8_9_line_sofbottom = 0; ++ avi_cfg->db10_11_pixel_eofleft = 0; ++ avi_cfg->db12_13_pixel_sofright = 0; ++ ++ /* packet enable and repeat */ ++ repeat_cfg->audio_pkt = 0; ++ repeat_cfg->audio_pkt_repeat = 0; ++ repeat_cfg->avi_infoframe = 0; ++ repeat_cfg->avi_infoframe_repeat = 0; ++ repeat_cfg->gen_cntrl_pkt = 0; ++ repeat_cfg->gen_cntrl_pkt_repeat = 0; ++ repeat_cfg->generic_pkt = 0; ++ repeat_cfg->generic_pkt_repeat = 0; ++} ++ ++static void hdmi_core_powerdown_disable(struct hdmi_core_data *core) ++{ ++ pr_debug("Enter hdmi_core_powerdown_disable\n"); ++ REG_FLD_MOD(core->base, HDMI_CORE_SYS_SYS_CTRL1, 0x0, 0, 0); ++} ++ ++static void hdmi_core_swreset_release(struct hdmi_core_data *core) ++{ ++ pr_debug("Enter hdmi_core_swreset_release\n"); ++ REG_FLD_MOD(core->base, HDMI_CORE_SYS_SRST, 0x0, 0, 0); ++} ++ ++static void hdmi_core_swreset_assert(struct hdmi_core_data *core) ++{ ++ pr_debug("Enter hdmi_core_swreset_assert\n"); ++ REG_FLD_MOD(core->base, HDMI_CORE_SYS_SRST, 0x1, 0, 0); ++} ++ ++/* HDMI_CORE_VIDEO_CONFIG */ ++static void hdmi_core_video_config(struct hdmi_core_data *core, ++ struct hdmi_core_video_config *cfg) ++{ ++ u32 r = 0; ++ void __iomem *core_sys_base = core->base; ++ void __iomem *core_av_base = hdmi_av_base(core); ++ ++ /* sys_ctrl1 default configuration not tunable */ ++ r = hdmi_read_reg(core_sys_base, HDMI_CORE_SYS_SYS_CTRL1); ++ r = FLD_MOD(r, HDMI_CORE_SYS_SYS_CTRL1_VEN_FOLLOWVSYNC, 5, 5); ++ r = FLD_MOD(r, HDMI_CORE_SYS_SYS_CTRL1_HEN_FOLLOWHSYNC, 4, 4); ++ r = FLD_MOD(r, HDMI_CORE_SYS_SYS_CTRL1_BSEL_24BITBUS, 2, 2); ++ r = FLD_MOD(r, HDMI_CORE_SYS_SYS_CTRL1_EDGE_RISINGEDGE, 1, 1); ++ hdmi_write_reg(core_sys_base, HDMI_CORE_SYS_SYS_CTRL1, r); ++ ++ REG_FLD_MOD(core_sys_base, ++ HDMI_CORE_SYS_VID_ACEN, cfg->ip_bus_width, 7, 6); ++ ++ /* Vid_Mode */ ++ r = hdmi_read_reg(core_sys_base, HDMI_CORE_SYS_VID_MODE); ++ ++ /* dither truncation configuration */ ++ if (cfg->op_dither_truc > HDMI_OUTPUTTRUNCATION_12BIT) { ++ r = FLD_MOD(r, cfg->op_dither_truc - 3, 7, 6); ++ r = FLD_MOD(r, 1, 5, 5); ++ } else { ++ r = FLD_MOD(r, cfg->op_dither_truc, 7, 6); ++ r = FLD_MOD(r, 0, 5, 5); ++ } ++ hdmi_write_reg(core_sys_base, HDMI_CORE_SYS_VID_MODE, r); ++ ++ /* HDMI_Ctrl */ ++ r = hdmi_read_reg(core_av_base, HDMI_CORE_AV_HDMI_CTRL); ++ r = FLD_MOD(r, cfg->deep_color_pkt, 6, 6); ++ r = FLD_MOD(r, cfg->pkt_mode, 5, 3); ++ r = FLD_MOD(r, cfg->hdmi_dvi, 0, 0); ++ hdmi_write_reg(core_av_base, HDMI_CORE_AV_HDMI_CTRL, r); ++ ++ /* TMDS_CTRL */ ++ REG_FLD_MOD(core_sys_base, ++ HDMI_CORE_SYS_TMDS_CTRL, cfg->tclk_sel_clkmult, 6, 5); ++} ++ ++static void hdmi_core_aux_infoframe_avi_config(struct hdmi_core_data *core) ++{ ++ u32 val; ++ char sum = 0, checksum = 0; ++ void __iomem *av_base = hdmi_av_base(core); ++ struct hdmi_core_infoframe_avi info_avi = core->avi_cfg; ++ ++ sum += 0x82 + 0x002 + 0x00D; ++ hdmi_write_reg(av_base, HDMI_CORE_AV_AVI_TYPE, 0x082); ++ hdmi_write_reg(av_base, HDMI_CORE_AV_AVI_VERS, 0x002); ++ hdmi_write_reg(av_base, HDMI_CORE_AV_AVI_LEN, 0x00D); ++ ++ val = (info_avi.db1_format << 5) | ++ (info_avi.db1_active_info << 4) | ++ (info_avi.db1_bar_info_dv << 2) | ++ (info_avi.db1_scan_info); ++ hdmi_write_reg(av_base, HDMI_CORE_AV_AVI_DBYTE(0), val); ++ sum += val; ++ ++ val = (info_avi.db2_colorimetry << 6) | ++ (info_avi.db2_aspect_ratio << 4) | ++ (info_avi.db2_active_fmt_ar); ++ hdmi_write_reg(av_base, HDMI_CORE_AV_AVI_DBYTE(1), val); ++ sum += val; ++ ++ val = (info_avi.db3_itc << 7) | ++ (info_avi.db3_ec << 4) | ++ (info_avi.db3_q_range << 2) | ++ (info_avi.db3_nup_scaling); ++ hdmi_write_reg(av_base, HDMI_CORE_AV_AVI_DBYTE(2), val); ++ sum += val; ++ ++ hdmi_write_reg(av_base, HDMI_CORE_AV_AVI_DBYTE(3), ++ info_avi.db4_videocode); ++ sum += info_avi.db4_videocode; ++ ++ val = info_avi.db5_pixel_repeat; ++ hdmi_write_reg(av_base, HDMI_CORE_AV_AVI_DBYTE(4), val); ++ sum += val; ++ ++ val = info_avi.db6_7_line_eoftop & 0x00FF; ++ hdmi_write_reg(av_base, HDMI_CORE_AV_AVI_DBYTE(5), val); ++ sum += val; ++ ++ val = ((info_avi.db6_7_line_eoftop >> 8) & 0x00FF); ++ hdmi_write_reg(av_base, HDMI_CORE_AV_AVI_DBYTE(6), val); ++ sum += val; ++ ++ val = info_avi.db8_9_line_sofbottom & 0x00FF; ++ hdmi_write_reg(av_base, HDMI_CORE_AV_AVI_DBYTE(7), val); ++ sum += val; ++ ++ val = ((info_avi.db8_9_line_sofbottom >> 8) & 0x00FF); ++ hdmi_write_reg(av_base, HDMI_CORE_AV_AVI_DBYTE(8), val); ++ sum += val; ++ ++ val = info_avi.db10_11_pixel_eofleft & 0x00FF; ++ hdmi_write_reg(av_base, HDMI_CORE_AV_AVI_DBYTE(9), val); ++ sum += val; ++ ++ val = ((info_avi.db10_11_pixel_eofleft >> 8) & 0x00FF); ++ hdmi_write_reg(av_base, HDMI_CORE_AV_AVI_DBYTE(10), val); ++ sum += val; ++ ++ val = info_avi.db12_13_pixel_sofright & 0x00FF; ++ hdmi_write_reg(av_base, HDMI_CORE_AV_AVI_DBYTE(11), val); ++ sum += val; ++ ++ val = ((info_avi.db12_13_pixel_sofright >> 8) & 0x00FF); ++ hdmi_write_reg(av_base, HDMI_CORE_AV_AVI_DBYTE(12), val); ++ sum += val; ++ ++ checksum = 0x100 - sum; ++ hdmi_write_reg(av_base, HDMI_CORE_AV_AVI_CHSUM, checksum); ++} ++ ++static void hdmi_core_av_packet_config(struct hdmi_core_data *core, ++ struct hdmi_core_packet_enable_repeat repeat_cfg) ++{ ++ /* enable/repeat the infoframe */ ++ hdmi_write_reg(hdmi_av_base(core), HDMI_CORE_AV_PB_CTRL1, ++ (repeat_cfg.audio_pkt << 5) | ++ (repeat_cfg.audio_pkt_repeat << 4) | ++ (repeat_cfg.avi_infoframe << 1) | ++ (repeat_cfg.avi_infoframe_repeat)); ++ ++ /* enable/repeat the packet */ ++ hdmi_write_reg(hdmi_av_base(core), HDMI_CORE_AV_PB_CTRL2, ++ (repeat_cfg.gen_cntrl_pkt << 3) | ++ (repeat_cfg.gen_cntrl_pkt_repeat << 2) | ++ (repeat_cfg.generic_pkt << 1) | ++ (repeat_cfg.generic_pkt_repeat)); ++} ++ ++void hdmi4_configure(struct hdmi_core_data *core, ++ struct hdmi_wp_data *wp, struct hdmi_config *cfg) ++{ ++ /* HDMI */ ++ struct omap_video_timings video_timing; ++ struct hdmi_video_format video_format; ++ /* HDMI core */ ++ struct hdmi_core_infoframe_avi *avi_cfg = &core->avi_cfg; ++ struct hdmi_core_video_config v_core_cfg; ++ struct hdmi_core_packet_enable_repeat repeat_cfg; ++ ++ hdmi_core_init(&v_core_cfg, avi_cfg, &repeat_cfg); ++ ++ hdmi_wp_init_vid_fmt_timings(&video_format, &video_timing, cfg); ++ ++ hdmi_wp_video_config_timing(wp, &video_timing); ++ ++ /* video config */ ++ video_format.packing_mode = HDMI_PACK_24b_RGB_YUV444_YUV422; ++ ++ hdmi_wp_video_config_format(wp, &video_format); ++ ++ hdmi_wp_video_config_interface(wp, &video_timing); ++ ++ /* ++ * configure core video part ++ * set software reset in the core ++ */ ++ hdmi_core_swreset_assert(core); ++ ++ /* power down off */ ++ hdmi_core_powerdown_disable(core); ++ ++ v_core_cfg.pkt_mode = HDMI_PACKETMODE24BITPERPIXEL; ++ v_core_cfg.hdmi_dvi = cfg->cm.mode; ++ ++ hdmi_core_video_config(core, &v_core_cfg); ++ ++ /* release software reset in the core */ ++ hdmi_core_swreset_release(core); ++ ++ /* ++ * configure packet ++ * info frame video see doc CEA861-D page 65 ++ */ ++ avi_cfg->db1_format = HDMI_INFOFRAME_AVI_DB1Y_RGB; ++ avi_cfg->db1_active_info = ++ HDMI_INFOFRAME_AVI_DB1A_ACTIVE_FORMAT_OFF; ++ avi_cfg->db1_bar_info_dv = HDMI_INFOFRAME_AVI_DB1B_NO; ++ avi_cfg->db1_scan_info = HDMI_INFOFRAME_AVI_DB1S_0; ++ avi_cfg->db2_colorimetry = HDMI_INFOFRAME_AVI_DB2C_NO; ++ avi_cfg->db2_aspect_ratio = HDMI_INFOFRAME_AVI_DB2M_NO; ++ avi_cfg->db2_active_fmt_ar = HDMI_INFOFRAME_AVI_DB2R_SAME; ++ avi_cfg->db3_itc = HDMI_INFOFRAME_AVI_DB3ITC_NO; ++ avi_cfg->db3_ec = HDMI_INFOFRAME_AVI_DB3EC_XVYUV601; ++ avi_cfg->db3_q_range = HDMI_INFOFRAME_AVI_DB3Q_DEFAULT; ++ avi_cfg->db3_nup_scaling = HDMI_INFOFRAME_AVI_DB3SC_NO; ++ avi_cfg->db4_videocode = cfg->cm.code; ++ avi_cfg->db5_pixel_repeat = HDMI_INFOFRAME_AVI_DB5PR_NO; ++ avi_cfg->db6_7_line_eoftop = 0; ++ avi_cfg->db8_9_line_sofbottom = 0; ++ avi_cfg->db10_11_pixel_eofleft = 0; ++ avi_cfg->db12_13_pixel_sofright = 0; ++ ++ hdmi_core_aux_infoframe_avi_config(core); ++ ++ /* enable/repeat the infoframe */ ++ repeat_cfg.avi_infoframe = HDMI_PACKETENABLE; ++ repeat_cfg.avi_infoframe_repeat = HDMI_PACKETREPEATON; ++ /* wakeup */ ++ repeat_cfg.audio_pkt = HDMI_PACKETENABLE; ++ repeat_cfg.audio_pkt_repeat = HDMI_PACKETREPEATON; ++ hdmi_core_av_packet_config(core, repeat_cfg); ++} ++ ++void hdmi4_core_dump(struct hdmi_core_data *core, struct seq_file *s) ++{ ++ int i; ++ ++#define CORE_REG(i, name) name(i) ++#define DUMPCORE(r) seq_printf(s, "%-35s %08x\n", #r,\ ++ hdmi_read_reg(core->base, r)) ++#define DUMPCOREAV(r) seq_printf(s, "%-35s %08x\n", #r,\ ++ hdmi_read_reg(hdmi_av_base(core), r)) ++#define DUMPCOREAV2(i, r) seq_printf(s, "%s[%d]%*s %08x\n", #r, i, \ ++ (i < 10) ? 32 - (int)strlen(#r) : 31 - (int)strlen(#r), " ", \ ++ hdmi_read_reg(hdmi_av_base(core), CORE_REG(i, r))) ++ ++ DUMPCORE(HDMI_CORE_SYS_VND_IDL); ++ DUMPCORE(HDMI_CORE_SYS_DEV_IDL); ++ DUMPCORE(HDMI_CORE_SYS_DEV_IDH); ++ DUMPCORE(HDMI_CORE_SYS_DEV_REV); ++ DUMPCORE(HDMI_CORE_SYS_SRST); ++ DUMPCORE(HDMI_CORE_SYS_SYS_CTRL1); ++ DUMPCORE(HDMI_CORE_SYS_SYS_STAT); ++ DUMPCORE(HDMI_CORE_SYS_SYS_CTRL3); ++ DUMPCORE(HDMI_CORE_SYS_DE_DLY); ++ DUMPCORE(HDMI_CORE_SYS_DE_CTRL); ++ DUMPCORE(HDMI_CORE_SYS_DE_TOP); ++ DUMPCORE(HDMI_CORE_SYS_DE_CNTL); ++ DUMPCORE(HDMI_CORE_SYS_DE_CNTH); ++ DUMPCORE(HDMI_CORE_SYS_DE_LINL); ++ DUMPCORE(HDMI_CORE_SYS_DE_LINH_1); ++ DUMPCORE(HDMI_CORE_SYS_HRES_L); ++ DUMPCORE(HDMI_CORE_SYS_HRES_H); ++ DUMPCORE(HDMI_CORE_SYS_VRES_L); ++ DUMPCORE(HDMI_CORE_SYS_VRES_H); ++ DUMPCORE(HDMI_CORE_SYS_IADJUST); ++ DUMPCORE(HDMI_CORE_SYS_POLDETECT); ++ DUMPCORE(HDMI_CORE_SYS_HWIDTH1); ++ DUMPCORE(HDMI_CORE_SYS_HWIDTH2); ++ DUMPCORE(HDMI_CORE_SYS_VWIDTH); ++ DUMPCORE(HDMI_CORE_SYS_VID_CTRL); ++ DUMPCORE(HDMI_CORE_SYS_VID_ACEN); ++ DUMPCORE(HDMI_CORE_SYS_VID_MODE); ++ DUMPCORE(HDMI_CORE_SYS_VID_BLANK1); ++ DUMPCORE(HDMI_CORE_SYS_VID_BLANK3); ++ DUMPCORE(HDMI_CORE_SYS_VID_BLANK1); ++ DUMPCORE(HDMI_CORE_SYS_DC_HEADER); ++ DUMPCORE(HDMI_CORE_SYS_VID_DITHER); ++ DUMPCORE(HDMI_CORE_SYS_RGB2XVYCC_CT); ++ DUMPCORE(HDMI_CORE_SYS_R2Y_COEFF_LOW); ++ DUMPCORE(HDMI_CORE_SYS_R2Y_COEFF_UP); ++ DUMPCORE(HDMI_CORE_SYS_G2Y_COEFF_LOW); ++ DUMPCORE(HDMI_CORE_SYS_G2Y_COEFF_UP); ++ DUMPCORE(HDMI_CORE_SYS_B2Y_COEFF_LOW); ++ DUMPCORE(HDMI_CORE_SYS_B2Y_COEFF_UP); ++ DUMPCORE(HDMI_CORE_SYS_R2CB_COEFF_LOW); ++ DUMPCORE(HDMI_CORE_SYS_R2CB_COEFF_UP); ++ DUMPCORE(HDMI_CORE_SYS_G2CB_COEFF_LOW); ++ DUMPCORE(HDMI_CORE_SYS_G2CB_COEFF_UP); ++ DUMPCORE(HDMI_CORE_SYS_B2CB_COEFF_LOW); ++ DUMPCORE(HDMI_CORE_SYS_B2CB_COEFF_UP); ++ DUMPCORE(HDMI_CORE_SYS_R2CR_COEFF_LOW); ++ DUMPCORE(HDMI_CORE_SYS_R2CR_COEFF_UP); ++ DUMPCORE(HDMI_CORE_SYS_G2CR_COEFF_LOW); ++ DUMPCORE(HDMI_CORE_SYS_G2CR_COEFF_UP); ++ DUMPCORE(HDMI_CORE_SYS_B2CR_COEFF_LOW); ++ DUMPCORE(HDMI_CORE_SYS_B2CR_COEFF_UP); ++ DUMPCORE(HDMI_CORE_SYS_RGB_OFFSET_LOW); ++ DUMPCORE(HDMI_CORE_SYS_RGB_OFFSET_UP); ++ DUMPCORE(HDMI_CORE_SYS_Y_OFFSET_LOW); ++ DUMPCORE(HDMI_CORE_SYS_Y_OFFSET_UP); ++ DUMPCORE(HDMI_CORE_SYS_CBCR_OFFSET_LOW); ++ DUMPCORE(HDMI_CORE_SYS_CBCR_OFFSET_UP); ++ DUMPCORE(HDMI_CORE_SYS_INTR_STATE); ++ DUMPCORE(HDMI_CORE_SYS_INTR1); ++ DUMPCORE(HDMI_CORE_SYS_INTR2); ++ DUMPCORE(HDMI_CORE_SYS_INTR3); ++ DUMPCORE(HDMI_CORE_SYS_INTR4); ++ DUMPCORE(HDMI_CORE_SYS_INTR_UNMASK1); ++ DUMPCORE(HDMI_CORE_SYS_INTR_UNMASK2); ++ DUMPCORE(HDMI_CORE_SYS_INTR_UNMASK3); ++ DUMPCORE(HDMI_CORE_SYS_INTR_UNMASK4); ++ DUMPCORE(HDMI_CORE_SYS_INTR_CTRL); ++ DUMPCORE(HDMI_CORE_SYS_TMDS_CTRL); ++ ++ DUMPCORE(HDMI_CORE_DDC_ADDR); ++ DUMPCORE(HDMI_CORE_DDC_SEGM); ++ DUMPCORE(HDMI_CORE_DDC_OFFSET); ++ DUMPCORE(HDMI_CORE_DDC_COUNT1); ++ DUMPCORE(HDMI_CORE_DDC_COUNT2); ++ DUMPCORE(HDMI_CORE_DDC_STATUS); ++ DUMPCORE(HDMI_CORE_DDC_CMD); ++ DUMPCORE(HDMI_CORE_DDC_DATA); ++ ++ DUMPCOREAV(HDMI_CORE_AV_ACR_CTRL); ++ DUMPCOREAV(HDMI_CORE_AV_FREQ_SVAL); ++ DUMPCOREAV(HDMI_CORE_AV_N_SVAL1); ++ DUMPCOREAV(HDMI_CORE_AV_N_SVAL2); ++ DUMPCOREAV(HDMI_CORE_AV_N_SVAL3); ++ DUMPCOREAV(HDMI_CORE_AV_CTS_SVAL1); ++ DUMPCOREAV(HDMI_CORE_AV_CTS_SVAL2); ++ DUMPCOREAV(HDMI_CORE_AV_CTS_SVAL3); ++ DUMPCOREAV(HDMI_CORE_AV_CTS_HVAL1); ++ DUMPCOREAV(HDMI_CORE_AV_CTS_HVAL2); ++ DUMPCOREAV(HDMI_CORE_AV_CTS_HVAL3); ++ DUMPCOREAV(HDMI_CORE_AV_AUD_MODE); ++ DUMPCOREAV(HDMI_CORE_AV_SPDIF_CTRL); ++ DUMPCOREAV(HDMI_CORE_AV_HW_SPDIF_FS); ++ DUMPCOREAV(HDMI_CORE_AV_SWAP_I2S); ++ DUMPCOREAV(HDMI_CORE_AV_SPDIF_ERTH); ++ DUMPCOREAV(HDMI_CORE_AV_I2S_IN_MAP); ++ DUMPCOREAV(HDMI_CORE_AV_I2S_IN_CTRL); ++ DUMPCOREAV(HDMI_CORE_AV_I2S_CHST0); ++ DUMPCOREAV(HDMI_CORE_AV_I2S_CHST1); ++ DUMPCOREAV(HDMI_CORE_AV_I2S_CHST2); ++ DUMPCOREAV(HDMI_CORE_AV_I2S_CHST4); ++ DUMPCOREAV(HDMI_CORE_AV_I2S_CHST5); ++ DUMPCOREAV(HDMI_CORE_AV_ASRC); ++ DUMPCOREAV(HDMI_CORE_AV_I2S_IN_LEN); ++ DUMPCOREAV(HDMI_CORE_AV_HDMI_CTRL); ++ DUMPCOREAV(HDMI_CORE_AV_AUDO_TXSTAT); ++ DUMPCOREAV(HDMI_CORE_AV_AUD_PAR_BUSCLK_1); ++ DUMPCOREAV(HDMI_CORE_AV_AUD_PAR_BUSCLK_2); ++ DUMPCOREAV(HDMI_CORE_AV_AUD_PAR_BUSCLK_3); ++ DUMPCOREAV(HDMI_CORE_AV_TEST_TXCTRL); ++ DUMPCOREAV(HDMI_CORE_AV_DPD); ++ DUMPCOREAV(HDMI_CORE_AV_PB_CTRL1); ++ DUMPCOREAV(HDMI_CORE_AV_PB_CTRL2); ++ DUMPCOREAV(HDMI_CORE_AV_AVI_TYPE); ++ DUMPCOREAV(HDMI_CORE_AV_AVI_VERS); ++ DUMPCOREAV(HDMI_CORE_AV_AVI_LEN); ++ DUMPCOREAV(HDMI_CORE_AV_AVI_CHSUM); ++ ++ for (i = 0; i < HDMI_CORE_AV_AVI_DBYTE_NELEMS; i++) ++ DUMPCOREAV2(i, HDMI_CORE_AV_AVI_DBYTE); ++ ++ DUMPCOREAV(HDMI_CORE_AV_SPD_TYPE); ++ DUMPCOREAV(HDMI_CORE_AV_SPD_VERS); ++ DUMPCOREAV(HDMI_CORE_AV_SPD_LEN); ++ DUMPCOREAV(HDMI_CORE_AV_SPD_CHSUM); ++ ++ for (i = 0; i < HDMI_CORE_AV_SPD_DBYTE_NELEMS; i++) ++ DUMPCOREAV2(i, HDMI_CORE_AV_SPD_DBYTE); ++ ++ DUMPCOREAV(HDMI_CORE_AV_AUDIO_TYPE); ++ DUMPCOREAV(HDMI_CORE_AV_AUDIO_VERS); ++ DUMPCOREAV(HDMI_CORE_AV_AUDIO_LEN); ++ DUMPCOREAV(HDMI_CORE_AV_AUDIO_CHSUM); ++ ++ for (i = 0; i < HDMI_CORE_AV_AUD_DBYTE_NELEMS; i++) ++ DUMPCOREAV2(i, HDMI_CORE_AV_AUD_DBYTE); ++ ++ DUMPCOREAV(HDMI_CORE_AV_MPEG_TYPE); ++ DUMPCOREAV(HDMI_CORE_AV_MPEG_VERS); ++ DUMPCOREAV(HDMI_CORE_AV_MPEG_LEN); ++ DUMPCOREAV(HDMI_CORE_AV_MPEG_CHSUM); ++ ++ for (i = 0; i < HDMI_CORE_AV_MPEG_DBYTE_NELEMS; i++) ++ DUMPCOREAV2(i, HDMI_CORE_AV_MPEG_DBYTE); ++ ++ for (i = 0; i < HDMI_CORE_AV_GEN_DBYTE_NELEMS; i++) ++ DUMPCOREAV2(i, HDMI_CORE_AV_GEN_DBYTE); ++ ++ DUMPCOREAV(HDMI_CORE_AV_CP_BYTE1); ++ ++ for (i = 0; i < HDMI_CORE_AV_GEN2_DBYTE_NELEMS; i++) ++ DUMPCOREAV2(i, HDMI_CORE_AV_GEN2_DBYTE); ++ ++ DUMPCOREAV(HDMI_CORE_AV_CEC_ADDR_ID); ++} ++ ++#if defined(CONFIG_OMAP4_DSS_HDMI_AUDIO) ++static void hdmi_core_audio_config(struct hdmi_core_data *core, ++ struct hdmi_core_audio_config *cfg) ++{ ++ u32 r; ++ void __iomem *av_base = hdmi_av_base(core); ++ ++ /* ++ * Parameters for generation of Audio Clock Recovery packets ++ */ ++ REG_FLD_MOD(av_base, HDMI_CORE_AV_N_SVAL1, cfg->n, 7, 0); ++ REG_FLD_MOD(av_base, HDMI_CORE_AV_N_SVAL2, cfg->n >> 8, 7, 0); ++ REG_FLD_MOD(av_base, HDMI_CORE_AV_N_SVAL3, cfg->n >> 16, 7, 0); ++ ++ if (cfg->cts_mode == HDMI_AUDIO_CTS_MODE_SW) { ++ REG_FLD_MOD(av_base, HDMI_CORE_AV_CTS_SVAL1, cfg->cts, 7, 0); ++ REG_FLD_MOD(av_base, ++ HDMI_CORE_AV_CTS_SVAL2, cfg->cts >> 8, 7, 0); ++ REG_FLD_MOD(av_base, ++ HDMI_CORE_AV_CTS_SVAL3, cfg->cts >> 16, 7, 0); ++ } else { ++ REG_FLD_MOD(av_base, HDMI_CORE_AV_AUD_PAR_BUSCLK_1, ++ cfg->aud_par_busclk, 7, 0); ++ REG_FLD_MOD(av_base, HDMI_CORE_AV_AUD_PAR_BUSCLK_2, ++ (cfg->aud_par_busclk >> 8), 7, 0); ++ REG_FLD_MOD(av_base, HDMI_CORE_AV_AUD_PAR_BUSCLK_3, ++ (cfg->aud_par_busclk >> 16), 7, 0); ++ } ++ ++ /* Set ACR clock divisor */ ++ REG_FLD_MOD(av_base, ++ HDMI_CORE_AV_FREQ_SVAL, cfg->mclk_mode, 2, 0); ++ ++ r = hdmi_read_reg(av_base, HDMI_CORE_AV_ACR_CTRL); ++ /* ++ * Use TMDS clock for ACR packets. For devices that use ++ * the MCLK, this is the first part of the MCLK initialization. ++ */ ++ r = FLD_MOD(r, 0, 2, 2); ++ ++ r = FLD_MOD(r, cfg->en_acr_pkt, 1, 1); ++ r = FLD_MOD(r, cfg->cts_mode, 0, 0); ++ hdmi_write_reg(av_base, HDMI_CORE_AV_ACR_CTRL, r); ++ ++ /* For devices using MCLK, this completes its initialization. */ ++ if (cfg->use_mclk) ++ REG_FLD_MOD(av_base, HDMI_CORE_AV_ACR_CTRL, 1, 2, 2); ++ ++ /* Override of SPDIF sample frequency with value in I2S_CHST4 */ ++ REG_FLD_MOD(av_base, HDMI_CORE_AV_SPDIF_CTRL, ++ cfg->fs_override, 1, 1); ++ ++ /* ++ * Set IEC-60958-3 channel status word. It is passed to the IP ++ * just as it is received. The user of the driver is responsible ++ * for its contents. ++ */ ++ hdmi_write_reg(av_base, HDMI_CORE_AV_I2S_CHST0, ++ cfg->iec60958_cfg->status[0]); ++ hdmi_write_reg(av_base, HDMI_CORE_AV_I2S_CHST1, ++ cfg->iec60958_cfg->status[1]); ++ hdmi_write_reg(av_base, HDMI_CORE_AV_I2S_CHST2, ++ cfg->iec60958_cfg->status[2]); ++ /* yes, this is correct: status[3] goes to CHST4 register */ ++ hdmi_write_reg(av_base, HDMI_CORE_AV_I2S_CHST4, ++ cfg->iec60958_cfg->status[3]); ++ /* yes, this is correct: status[4] goes to CHST5 register */ ++ hdmi_write_reg(av_base, HDMI_CORE_AV_I2S_CHST5, ++ cfg->iec60958_cfg->status[4]); ++ ++ /* set I2S parameters */ ++ r = hdmi_read_reg(av_base, HDMI_CORE_AV_I2S_IN_CTRL); ++ r = FLD_MOD(r, cfg->i2s_cfg.sck_edge_mode, 6, 6); ++ r = FLD_MOD(r, cfg->i2s_cfg.vbit, 4, 4); ++ r = FLD_MOD(r, cfg->i2s_cfg.justification, 2, 2); ++ r = FLD_MOD(r, cfg->i2s_cfg.direction, 1, 1); ++ r = FLD_MOD(r, cfg->i2s_cfg.shift, 0, 0); ++ hdmi_write_reg(av_base, HDMI_CORE_AV_I2S_IN_CTRL, r); ++ ++ REG_FLD_MOD(av_base, HDMI_CORE_AV_I2S_IN_LEN, ++ cfg->i2s_cfg.in_length_bits, 3, 0); ++ ++ /* Audio channels and mode parameters */ ++ REG_FLD_MOD(av_base, HDMI_CORE_AV_HDMI_CTRL, cfg->layout, 2, 1); ++ r = hdmi_read_reg(av_base, HDMI_CORE_AV_AUD_MODE); ++ r = FLD_MOD(r, cfg->i2s_cfg.active_sds, 7, 4); ++ r = FLD_MOD(r, cfg->en_dsd_audio, 3, 3); ++ r = FLD_MOD(r, cfg->en_parallel_aud_input, 2, 2); ++ r = FLD_MOD(r, cfg->en_spdif, 1, 1); ++ hdmi_write_reg(av_base, HDMI_CORE_AV_AUD_MODE, r); ++ ++ /* Audio channel mappings */ ++ /* TODO: Make channel mapping dynamic. For now, map channels ++ * in the ALSA order: FL/FR/RL/RR/C/LFE/SL/SR. Remapping is needed as ++ * HDMI speaker order is different. See CEA-861 Section 6.6.2. ++ */ ++ hdmi_write_reg(av_base, HDMI_CORE_AV_I2S_IN_MAP, 0x78); ++ REG_FLD_MOD(av_base, HDMI_CORE_AV_SWAP_I2S, 1, 5, 5); ++} ++ ++static void hdmi_core_audio_infoframe_cfg(struct hdmi_core_data *core, ++ struct snd_cea_861_aud_if *info_aud) ++{ ++ u8 sum = 0, checksum = 0; ++ void __iomem *av_base = hdmi_av_base(core); ++ ++ /* ++ * Set audio info frame type, version and length as ++ * described in HDMI 1.4a Section 8.2.2 specification. ++ * Checksum calculation is defined in Section 5.3.5. ++ */ ++ hdmi_write_reg(av_base, HDMI_CORE_AV_AUDIO_TYPE, 0x84); ++ hdmi_write_reg(av_base, HDMI_CORE_AV_AUDIO_VERS, 0x01); ++ hdmi_write_reg(av_base, HDMI_CORE_AV_AUDIO_LEN, 0x0a); ++ sum += 0x84 + 0x001 + 0x00a; ++ ++ hdmi_write_reg(av_base, HDMI_CORE_AV_AUD_DBYTE(0), ++ info_aud->db1_ct_cc); ++ sum += info_aud->db1_ct_cc; ++ ++ hdmi_write_reg(av_base, HDMI_CORE_AV_AUD_DBYTE(1), ++ info_aud->db2_sf_ss); ++ sum += info_aud->db2_sf_ss; ++ ++ hdmi_write_reg(av_base, HDMI_CORE_AV_AUD_DBYTE(2), info_aud->db3); ++ sum += info_aud->db3; ++ ++ hdmi_write_reg(av_base, HDMI_CORE_AV_AUD_DBYTE(3), info_aud->db4_ca); ++ sum += info_aud->db4_ca; ++ ++ hdmi_write_reg(av_base, HDMI_CORE_AV_AUD_DBYTE(4), ++ info_aud->db5_dminh_lsv); ++ sum += info_aud->db5_dminh_lsv; ++ ++ hdmi_write_reg(av_base, HDMI_CORE_AV_AUD_DBYTE(5), 0x00); ++ hdmi_write_reg(av_base, HDMI_CORE_AV_AUD_DBYTE(6), 0x00); ++ hdmi_write_reg(av_base, HDMI_CORE_AV_AUD_DBYTE(7), 0x00); ++ hdmi_write_reg(av_base, HDMI_CORE_AV_AUD_DBYTE(8), 0x00); ++ hdmi_write_reg(av_base, HDMI_CORE_AV_AUD_DBYTE(9), 0x00); ++ ++ checksum = 0x100 - sum; ++ hdmi_write_reg(av_base, ++ HDMI_CORE_AV_AUDIO_CHSUM, checksum); ++ ++ /* ++ * TODO: Add MPEG and SPD enable and repeat cfg when EDID parsing ++ * is available. ++ */ ++} ++ ++int hdmi4_audio_config(struct hdmi_core_data *core, struct hdmi_wp_data *wp, ++ struct omap_dss_audio *audio, u32 pclk) ++{ ++ struct hdmi_audio_format audio_format; ++ struct hdmi_audio_dma audio_dma; ++ struct hdmi_core_audio_config acore; ++ int err, n, cts, channel_count; ++ unsigned int fs_nr; ++ bool word_length_16b = false; ++ ++ if (!audio || !audio->iec || !audio->cea || !core) ++ return -EINVAL; ++ ++ acore.iec60958_cfg = audio->iec; ++ /* ++ * In the IEC-60958 status word, check if the audio sample word length ++ * is 16-bit as several optimizations can be performed in such case. ++ */ ++ if (!(audio->iec->status[4] & IEC958_AES4_CON_MAX_WORDLEN_24)) ++ if (audio->iec->status[4] & IEC958_AES4_CON_WORDLEN_20_16) ++ word_length_16b = true; ++ ++ /* I2S configuration. See Phillips' specification */ ++ if (word_length_16b) ++ acore.i2s_cfg.justification = HDMI_AUDIO_JUSTIFY_LEFT; ++ else ++ acore.i2s_cfg.justification = HDMI_AUDIO_JUSTIFY_RIGHT; ++ /* ++ * The I2S input word length is twice the lenght given in the IEC-60958 ++ * status word. If the word size is greater than ++ * 20 bits, increment by one. ++ */ ++ acore.i2s_cfg.in_length_bits = audio->iec->status[4] ++ & IEC958_AES4_CON_WORDLEN; ++ if (audio->iec->status[4] & IEC958_AES4_CON_MAX_WORDLEN_24) ++ acore.i2s_cfg.in_length_bits++; ++ acore.i2s_cfg.sck_edge_mode = HDMI_AUDIO_I2S_SCK_EDGE_RISING; ++ acore.i2s_cfg.vbit = HDMI_AUDIO_I2S_VBIT_FOR_PCM; ++ acore.i2s_cfg.direction = HDMI_AUDIO_I2S_MSB_SHIFTED_FIRST; ++ acore.i2s_cfg.shift = HDMI_AUDIO_I2S_FIRST_BIT_SHIFT; ++ ++ /* convert sample frequency to a number */ ++ switch (audio->iec->status[3] & IEC958_AES3_CON_FS) { ++ case IEC958_AES3_CON_FS_32000: ++ fs_nr = 32000; ++ break; ++ case IEC958_AES3_CON_FS_44100: ++ fs_nr = 44100; ++ break; ++ case IEC958_AES3_CON_FS_48000: ++ fs_nr = 48000; ++ break; ++ case IEC958_AES3_CON_FS_88200: ++ fs_nr = 88200; ++ break; ++ case IEC958_AES3_CON_FS_96000: ++ fs_nr = 96000; ++ break; ++ case IEC958_AES3_CON_FS_176400: ++ fs_nr = 176400; ++ break; ++ case IEC958_AES3_CON_FS_192000: ++ fs_nr = 192000; ++ break; ++ default: ++ return -EINVAL; ++ } ++ ++ err = hdmi_compute_acr(pclk, fs_nr, &n, &cts); ++ ++ /* Audio clock regeneration settings */ ++ acore.n = n; ++ acore.cts = cts; ++ if (dss_has_feature(FEAT_HDMI_CTS_SWMODE)) { ++ acore.aud_par_busclk = 0; ++ acore.cts_mode = HDMI_AUDIO_CTS_MODE_SW; ++ acore.use_mclk = dss_has_feature(FEAT_HDMI_AUDIO_USE_MCLK); ++ } else { ++ acore.aud_par_busclk = (((128 * 31) - 1) << 8); ++ acore.cts_mode = HDMI_AUDIO_CTS_MODE_HW; ++ acore.use_mclk = true; ++ } ++ ++ if (acore.use_mclk) ++ acore.mclk_mode = HDMI_AUDIO_MCLK_128FS; ++ ++ /* Audio channels settings */ ++ channel_count = (audio->cea->db1_ct_cc & ++ CEA861_AUDIO_INFOFRAME_DB1CC) + 1; ++ ++ switch (channel_count) { ++ case 2: ++ audio_format.active_chnnls_msk = 0x03; ++ break; ++ case 3: ++ audio_format.active_chnnls_msk = 0x07; ++ break; ++ case 4: ++ audio_format.active_chnnls_msk = 0x0f; ++ break; ++ case 5: ++ audio_format.active_chnnls_msk = 0x1f; ++ break; ++ case 6: ++ audio_format.active_chnnls_msk = 0x3f; ++ break; ++ case 7: ++ audio_format.active_chnnls_msk = 0x7f; ++ break; ++ case 8: ++ audio_format.active_chnnls_msk = 0xff; ++ break; ++ default: ++ return -EINVAL; ++ } ++ ++ /* ++ * the HDMI IP needs to enable four stereo channels when transmitting ++ * more than 2 audio channels ++ */ ++ if (channel_count == 2) { ++ audio_format.stereo_channels = HDMI_AUDIO_STEREO_ONECHANNEL; ++ acore.i2s_cfg.active_sds = HDMI_AUDIO_I2S_SD0_EN; ++ acore.layout = HDMI_AUDIO_LAYOUT_2CH; ++ } else { ++ audio_format.stereo_channels = HDMI_AUDIO_STEREO_FOURCHANNELS; ++ acore.i2s_cfg.active_sds = HDMI_AUDIO_I2S_SD0_EN | ++ HDMI_AUDIO_I2S_SD1_EN | HDMI_AUDIO_I2S_SD2_EN | ++ HDMI_AUDIO_I2S_SD3_EN; ++ acore.layout = HDMI_AUDIO_LAYOUT_8CH; ++ } ++ ++ acore.en_spdif = false; ++ /* use sample frequency from channel status word */ ++ acore.fs_override = true; ++ /* enable ACR packets */ ++ acore.en_acr_pkt = true; ++ /* disable direct streaming digital audio */ ++ acore.en_dsd_audio = false; ++ /* use parallel audio interface */ ++ acore.en_parallel_aud_input = true; ++ ++ /* DMA settings */ ++ if (word_length_16b) ++ audio_dma.transfer_size = 0x10; ++ else ++ audio_dma.transfer_size = 0x20; ++ audio_dma.block_size = 0xC0; ++ audio_dma.mode = HDMI_AUDIO_TRANSF_DMA; ++ audio_dma.fifo_threshold = 0x20; /* in number of samples */ ++ ++ /* audio FIFO format settings */ ++ if (word_length_16b) { ++ audio_format.samples_per_word = HDMI_AUDIO_ONEWORD_TWOSAMPLES; ++ audio_format.sample_size = HDMI_AUDIO_SAMPLE_16BITS; ++ audio_format.justification = HDMI_AUDIO_JUSTIFY_LEFT; ++ } else { ++ audio_format.samples_per_word = HDMI_AUDIO_ONEWORD_ONESAMPLE; ++ audio_format.sample_size = HDMI_AUDIO_SAMPLE_24BITS; ++ audio_format.justification = HDMI_AUDIO_JUSTIFY_RIGHT; ++ } ++ audio_format.type = HDMI_AUDIO_TYPE_LPCM; ++ audio_format.sample_order = HDMI_AUDIO_SAMPLE_LEFT_FIRST; ++ /* disable start/stop signals of IEC 60958 blocks */ ++ audio_format.en_sig_blk_strt_end = HDMI_AUDIO_BLOCK_SIG_STARTEND_ON; ++ ++ /* configure DMA and audio FIFO format*/ ++ hdmi_wp_audio_config_dma(wp, &audio_dma); ++ hdmi_wp_audio_config_format(wp, &audio_format); ++ ++ /* configure the core*/ ++ hdmi_core_audio_config(core, &acore); ++ ++ /* configure CEA 861 audio infoframe*/ ++ hdmi_core_audio_infoframe_cfg(core, audio->cea); ++ ++ return 0; ++} ++ ++int hdmi4_audio_start(struct hdmi_core_data *core, struct hdmi_wp_data *wp) ++{ ++ REG_FLD_MOD(hdmi_av_base(core), ++ HDMI_CORE_AV_AUD_MODE, true, 0, 0); ++ ++ hdmi_wp_audio_core_req_enable(wp, true); ++ ++ return 0; ++} ++ ++void hdmi4_audio_stop(struct hdmi_core_data *core, struct hdmi_wp_data *wp) ++{ ++ REG_FLD_MOD(hdmi_av_base(core), ++ HDMI_CORE_AV_AUD_MODE, false, 0, 0); ++ ++ hdmi_wp_audio_core_req_enable(wp, false); ++} ++ ++int hdmi4_audio_get_dma_port(u32 *offset, u32 *size) ++{ ++ if (!offset || !size) ++ return -EINVAL; ++ *offset = HDMI_WP_AUDIO_DATA; ++ *size = 4; ++ return 0; ++} ++ ++#endif ++ ++int hdmi4_core_init(struct platform_device *pdev, struct hdmi_core_data *core) ++{ ++ struct resource *res; ++ ++ res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "hdmi_core"); ++ if (!res) { ++ DSSERR("can't get CORE IORESOURCE_MEM HDMI\n"); ++ return -EINVAL; ++ } ++ ++ core->base = devm_request_and_ioremap(&pdev->dev, res); ++ if (!core->base) { ++ DSSERR("can't ioremap HDMI core\n"); ++ return -ENOMEM; ++ } ++ ++ return 0; ++} +--- /dev/null ++++ b/drivers/video/omap2/dss/hdmi4_core.h +@@ -0,0 +1,276 @@ ++/* ++ * HDMI header definition for OMAP4 HDMI core IP ++ * ++ * Copyright (C) 2010-2011 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 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, see <http://www.gnu.org/licenses/>. ++ */ ++ ++#ifndef _HDMI4_CORE_H_ ++#define _HDMI4_CORE_H_ ++ ++#include "hdmi.h" ++ ++/* OMAP4 HDMI IP Core System */ ++ ++#define HDMI_CORE_SYS_VND_IDL 0x0 ++#define HDMI_CORE_SYS_DEV_IDL 0x8 ++#define HDMI_CORE_SYS_DEV_IDH 0xC ++#define HDMI_CORE_SYS_DEV_REV 0x10 ++#define HDMI_CORE_SYS_SRST 0x14 ++#define HDMI_CORE_SYS_SYS_CTRL1 0x20 ++#define HDMI_CORE_SYS_SYS_STAT 0x24 ++#define HDMI_CORE_SYS_SYS_CTRL3 0x28 ++#define HDMI_CORE_SYS_DCTL 0x34 ++#define HDMI_CORE_SYS_DE_DLY 0xC8 ++#define HDMI_CORE_SYS_DE_CTRL 0xCC ++#define HDMI_CORE_SYS_DE_TOP 0xD0 ++#define HDMI_CORE_SYS_DE_CNTL 0xD8 ++#define HDMI_CORE_SYS_DE_CNTH 0xDC ++#define HDMI_CORE_SYS_DE_LINL 0xE0 ++#define HDMI_CORE_SYS_DE_LINH_1 0xE4 ++#define HDMI_CORE_SYS_HRES_L 0xE8 ++#define HDMI_CORE_SYS_HRES_H 0xEC ++#define HDMI_CORE_SYS_VRES_L 0xF0 ++#define HDMI_CORE_SYS_VRES_H 0xF4 ++#define HDMI_CORE_SYS_IADJUST 0xF8 ++#define HDMI_CORE_SYS_POLDETECT 0xFC ++#define HDMI_CORE_SYS_HWIDTH1 0x110 ++#define HDMI_CORE_SYS_HWIDTH2 0x114 ++#define HDMI_CORE_SYS_VWIDTH 0x11C ++#define HDMI_CORE_SYS_VID_CTRL 0x120 ++#define HDMI_CORE_SYS_VID_ACEN 0x124 ++#define HDMI_CORE_SYS_VID_MODE 0x128 ++#define HDMI_CORE_SYS_VID_BLANK1 0x12C ++#define HDMI_CORE_SYS_VID_BLANK2 0x130 ++#define HDMI_CORE_SYS_VID_BLANK3 0x134 ++#define HDMI_CORE_SYS_DC_HEADER 0x138 ++#define HDMI_CORE_SYS_VID_DITHER 0x13C ++#define HDMI_CORE_SYS_RGB2XVYCC_CT 0x140 ++#define HDMI_CORE_SYS_R2Y_COEFF_LOW 0x144 ++#define HDMI_CORE_SYS_R2Y_COEFF_UP 0x148 ++#define HDMI_CORE_SYS_G2Y_COEFF_LOW 0x14C ++#define HDMI_CORE_SYS_G2Y_COEFF_UP 0x150 ++#define HDMI_CORE_SYS_B2Y_COEFF_LOW 0x154 ++#define HDMI_CORE_SYS_B2Y_COEFF_UP 0x158 ++#define HDMI_CORE_SYS_R2CB_COEFF_LOW 0x15C ++#define HDMI_CORE_SYS_R2CB_COEFF_UP 0x160 ++#define HDMI_CORE_SYS_G2CB_COEFF_LOW 0x164 ++#define HDMI_CORE_SYS_G2CB_COEFF_UP 0x168 ++#define HDMI_CORE_SYS_B2CB_COEFF_LOW 0x16C ++#define HDMI_CORE_SYS_B2CB_COEFF_UP 0x170 ++#define HDMI_CORE_SYS_R2CR_COEFF_LOW 0x174 ++#define HDMI_CORE_SYS_R2CR_COEFF_UP 0x178 ++#define HDMI_CORE_SYS_G2CR_COEFF_LOW 0x17C ++#define HDMI_CORE_SYS_G2CR_COEFF_UP 0x180 ++#define HDMI_CORE_SYS_B2CR_COEFF_LOW 0x184 ++#define HDMI_CORE_SYS_B2CR_COEFF_UP 0x188 ++#define HDMI_CORE_SYS_RGB_OFFSET_LOW 0x18C ++#define HDMI_CORE_SYS_RGB_OFFSET_UP 0x190 ++#define HDMI_CORE_SYS_Y_OFFSET_LOW 0x194 ++#define HDMI_CORE_SYS_Y_OFFSET_UP 0x198 ++#define HDMI_CORE_SYS_CBCR_OFFSET_LOW 0x19C ++#define HDMI_CORE_SYS_CBCR_OFFSET_UP 0x1A0 ++#define HDMI_CORE_SYS_INTR_STATE 0x1C0 ++#define HDMI_CORE_SYS_INTR1 0x1C4 ++#define HDMI_CORE_SYS_INTR2 0x1C8 ++#define HDMI_CORE_SYS_INTR3 0x1CC ++#define HDMI_CORE_SYS_INTR4 0x1D0 ++#define HDMI_CORE_SYS_INTR_UNMASK1 0x1D4 ++#define HDMI_CORE_SYS_INTR_UNMASK2 0x1D8 ++#define HDMI_CORE_SYS_INTR_UNMASK3 0x1DC ++#define HDMI_CORE_SYS_INTR_UNMASK4 0x1E0 ++#define HDMI_CORE_SYS_INTR_CTRL 0x1E4 ++#define HDMI_CORE_SYS_TMDS_CTRL 0x208 ++ ++/* value definitions for HDMI_CORE_SYS_SYS_CTRL1 fields */ ++#define HDMI_CORE_SYS_SYS_CTRL1_VEN_FOLLOWVSYNC 0x1 ++#define HDMI_CORE_SYS_SYS_CTRL1_HEN_FOLLOWHSYNC 0x1 ++#define HDMI_CORE_SYS_SYS_CTRL1_BSEL_24BITBUS 0x1 ++#define HDMI_CORE_SYS_SYS_CTRL1_EDGE_RISINGEDGE 0x1 ++ ++/* HDMI DDC E-DID */ ++#define HDMI_CORE_DDC_ADDR 0x3B4 ++#define HDMI_CORE_DDC_SEGM 0x3B8 ++#define HDMI_CORE_DDC_OFFSET 0x3BC ++#define HDMI_CORE_DDC_COUNT1 0x3C0 ++#define HDMI_CORE_DDC_COUNT2 0x3C4 ++#define HDMI_CORE_DDC_STATUS 0x3C8 ++#define HDMI_CORE_DDC_CMD 0x3CC ++#define HDMI_CORE_DDC_DATA 0x3D0 ++ ++/* HDMI IP Core Audio Video */ ++ ++#define HDMI_CORE_AV_ACR_CTRL 0x4 ++#define HDMI_CORE_AV_FREQ_SVAL 0x8 ++#define HDMI_CORE_AV_N_SVAL1 0xC ++#define HDMI_CORE_AV_N_SVAL2 0x10 ++#define HDMI_CORE_AV_N_SVAL3 0x14 ++#define HDMI_CORE_AV_CTS_SVAL1 0x18 ++#define HDMI_CORE_AV_CTS_SVAL2 0x1C ++#define HDMI_CORE_AV_CTS_SVAL3 0x20 ++#define HDMI_CORE_AV_CTS_HVAL1 0x24 ++#define HDMI_CORE_AV_CTS_HVAL2 0x28 ++#define HDMI_CORE_AV_CTS_HVAL3 0x2C ++#define HDMI_CORE_AV_AUD_MODE 0x50 ++#define HDMI_CORE_AV_SPDIF_CTRL 0x54 ++#define HDMI_CORE_AV_HW_SPDIF_FS 0x60 ++#define HDMI_CORE_AV_SWAP_I2S 0x64 ++#define HDMI_CORE_AV_SPDIF_ERTH 0x6C ++#define HDMI_CORE_AV_I2S_IN_MAP 0x70 ++#define HDMI_CORE_AV_I2S_IN_CTRL 0x74 ++#define HDMI_CORE_AV_I2S_CHST0 0x78 ++#define HDMI_CORE_AV_I2S_CHST1 0x7C ++#define HDMI_CORE_AV_I2S_CHST2 0x80 ++#define HDMI_CORE_AV_I2S_CHST4 0x84 ++#define HDMI_CORE_AV_I2S_CHST5 0x88 ++#define HDMI_CORE_AV_ASRC 0x8C ++#define HDMI_CORE_AV_I2S_IN_LEN 0x90 ++#define HDMI_CORE_AV_HDMI_CTRL 0xBC ++#define HDMI_CORE_AV_AUDO_TXSTAT 0xC0 ++#define HDMI_CORE_AV_AUD_PAR_BUSCLK_1 0xCC ++#define HDMI_CORE_AV_AUD_PAR_BUSCLK_2 0xD0 ++#define HDMI_CORE_AV_AUD_PAR_BUSCLK_3 0xD4 ++#define HDMI_CORE_AV_TEST_TXCTRL 0xF0 ++#define HDMI_CORE_AV_DPD 0xF4 ++#define HDMI_CORE_AV_PB_CTRL1 0xF8 ++#define HDMI_CORE_AV_PB_CTRL2 0xFC ++#define HDMI_CORE_AV_AVI_TYPE 0x100 ++#define HDMI_CORE_AV_AVI_VERS 0x104 ++#define HDMI_CORE_AV_AVI_LEN 0x108 ++#define HDMI_CORE_AV_AVI_CHSUM 0x10C ++#define HDMI_CORE_AV_AVI_DBYTE(n) (n * 4 + 0x110) ++#define HDMI_CORE_AV_SPD_TYPE 0x180 ++#define HDMI_CORE_AV_SPD_VERS 0x184 ++#define HDMI_CORE_AV_SPD_LEN 0x188 ++#define HDMI_CORE_AV_SPD_CHSUM 0x18C ++#define HDMI_CORE_AV_SPD_DBYTE(n) (n * 4 + 0x190) ++#define HDMI_CORE_AV_AUDIO_TYPE 0x200 ++#define HDMI_CORE_AV_AUDIO_VERS 0x204 ++#define HDMI_CORE_AV_AUDIO_LEN 0x208 ++#define HDMI_CORE_AV_AUDIO_CHSUM 0x20C ++#define HDMI_CORE_AV_AUD_DBYTE(n) (n * 4 + 0x210) ++#define HDMI_CORE_AV_MPEG_TYPE 0x280 ++#define HDMI_CORE_AV_MPEG_VERS 0x284 ++#define HDMI_CORE_AV_MPEG_LEN 0x288 ++#define HDMI_CORE_AV_MPEG_CHSUM 0x28C ++#define HDMI_CORE_AV_MPEG_DBYTE(n) (n * 4 + 0x290) ++#define HDMI_CORE_AV_GEN_DBYTE(n) (n * 4 + 0x300) ++#define HDMI_CORE_AV_CP_BYTE1 0x37C ++#define HDMI_CORE_AV_GEN2_DBYTE(n) (n * 4 + 0x380) ++#define HDMI_CORE_AV_CEC_ADDR_ID 0x3FC ++ ++#define HDMI_CORE_AV_SPD_DBYTE_ELSIZE 0x4 ++#define HDMI_CORE_AV_GEN2_DBYTE_ELSIZE 0x4 ++#define HDMI_CORE_AV_MPEG_DBYTE_ELSIZE 0x4 ++#define HDMI_CORE_AV_GEN_DBYTE_ELSIZE 0x4 ++ ++#define HDMI_CORE_AV_AVI_DBYTE_NELEMS 15 ++#define HDMI_CORE_AV_SPD_DBYTE_NELEMS 27 ++#define HDMI_CORE_AV_AUD_DBYTE_NELEMS 10 ++#define HDMI_CORE_AV_MPEG_DBYTE_NELEMS 27 ++#define HDMI_CORE_AV_GEN_DBYTE_NELEMS 31 ++#define HDMI_CORE_AV_GEN2_DBYTE_NELEMS 31 ++ ++enum hdmi_core_inputbus_width { ++ HDMI_INPUT_8BIT = 0, ++ HDMI_INPUT_10BIT = 1, ++ HDMI_INPUT_12BIT = 2 ++}; ++ ++enum hdmi_core_dither_trunc { ++ HDMI_OUTPUTTRUNCATION_8BIT = 0, ++ HDMI_OUTPUTTRUNCATION_10BIT = 1, ++ HDMI_OUTPUTTRUNCATION_12BIT = 2, ++ HDMI_OUTPUTDITHER_8BIT = 3, ++ HDMI_OUTPUTDITHER_10BIT = 4, ++ HDMI_OUTPUTDITHER_12BIT = 5 ++}; ++ ++enum hdmi_core_deepcolor_ed { ++ HDMI_DEEPCOLORPACKECTDISABLE = 0, ++ HDMI_DEEPCOLORPACKECTENABLE = 1 ++}; ++ ++enum hdmi_core_packet_mode { ++ HDMI_PACKETMODERESERVEDVALUE = 0, ++ HDMI_PACKETMODE24BITPERPIXEL = 4, ++ HDMI_PACKETMODE30BITPERPIXEL = 5, ++ HDMI_PACKETMODE36BITPERPIXEL = 6, ++ HDMI_PACKETMODE48BITPERPIXEL = 7 ++}; ++ ++enum hdmi_core_tclkselclkmult { ++ HDMI_FPLL05IDCK = 0, ++ HDMI_FPLL10IDCK = 1, ++ HDMI_FPLL20IDCK = 2, ++ HDMI_FPLL40IDCK = 3 ++}; ++ ++enum hdmi_core_packet_ctrl { ++ HDMI_PACKETENABLE = 1, ++ HDMI_PACKETDISABLE = 0, ++ HDMI_PACKETREPEATON = 1, ++ HDMI_PACKETREPEATOFF = 0 ++}; ++ ++enum hdmi_audio_i2s_config { ++ HDMI_AUDIO_I2S_MSB_SHIFTED_FIRST = 0, ++ HDMI_AUDIO_I2S_LSB_SHIFTED_FIRST = 1, ++ HDMI_AUDIO_I2S_SCK_EDGE_FALLING = 0, ++ HDMI_AUDIO_I2S_SCK_EDGE_RISING = 1, ++ HDMI_AUDIO_I2S_VBIT_FOR_PCM = 0, ++ HDMI_AUDIO_I2S_VBIT_FOR_COMPRESSED = 1, ++ HDMI_AUDIO_I2S_FIRST_BIT_SHIFT = 0, ++ HDMI_AUDIO_I2S_FIRST_BIT_NO_SHIFT = 1, ++ HDMI_AUDIO_I2S_SD0_EN = 1, ++ HDMI_AUDIO_I2S_SD1_EN = 1 << 1, ++ HDMI_AUDIO_I2S_SD2_EN = 1 << 2, ++ HDMI_AUDIO_I2S_SD3_EN = 1 << 3, ++}; ++ ++struct hdmi_core_video_config { ++ enum hdmi_core_inputbus_width ip_bus_width; ++ enum hdmi_core_dither_trunc op_dither_truc; ++ enum hdmi_core_deepcolor_ed deep_color_pkt; ++ enum hdmi_core_packet_mode pkt_mode; ++ enum hdmi_core_hdmi_dvi hdmi_dvi; ++ enum hdmi_core_tclkselclkmult tclk_sel_clkmult; ++}; ++ ++struct hdmi_core_packet_enable_repeat { ++ u32 audio_pkt; ++ u32 audio_pkt_repeat; ++ u32 avi_infoframe; ++ u32 avi_infoframe_repeat; ++ u32 gen_cntrl_pkt; ++ u32 gen_cntrl_pkt_repeat; ++ u32 generic_pkt; ++ u32 generic_pkt_repeat; ++}; ++ ++int hdmi4_read_edid(struct hdmi_core_data *core, u8 *edid, int len); ++void hdmi4_configure(struct hdmi_core_data *core, struct hdmi_wp_data *wp, ++ struct hdmi_config *cfg); ++void hdmi4_core_dump(struct hdmi_core_data *core, struct seq_file *s); ++int hdmi4_core_init(struct platform_device *pdev, struct hdmi_core_data *core); ++ ++#if defined(CONFIG_OMAP4_DSS_HDMI_AUDIO) ++int hdmi4_audio_start(struct hdmi_core_data *core, struct hdmi_wp_data *wp); ++void hdmi4_audio_stop(struct hdmi_core_data *core, struct hdmi_wp_data *wp); ++int hdmi4_audio_config(struct hdmi_core_data *core, struct hdmi_wp_data *wp, ++ struct omap_dss_audio *audio, u32 pclk); ++int hdmi4_audio_get_dma_port(u32 *offset, u32 *size); ++#endif ++ ++#endif +--- /dev/null ++++ b/drivers/video/omap2/dss/hdmi5.c +@@ -0,0 +1,786 @@ ++/* ++ * hdmi.c ++ * ++ * HDMI interface DSS driver setting for TI's OMAP4 family of processor. ++ * Copyright (C) 2010-2011 Texas Instruments Incorporated - http://www.ti.com/ ++ * Authors: Yong Zhi ++ * Mythri pk <mythripk@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, see <http://www.gnu.org/licenses/>. ++ */ ++ ++#define DSS_SUBSYS_NAME "HDMI" ++ ++#include <linux/kernel.h> ++#include <linux/module.h> ++#include <linux/err.h> ++#include <linux/io.h> ++#include <linux/interrupt.h> ++#include <linux/mutex.h> ++#include <linux/delay.h> ++#include <linux/string.h> ++#include <linux/platform_device.h> ++#include <linux/pm_runtime.h> ++#include <linux/clk.h> ++#include <linux/gpio.h> ++#include <linux/regulator/consumer.h> ++#include <video/omapdss.h> ++ ++#include "hdmi5_core.h" ++#include "dss.h" ++#include "dss_features.h" ++ ++static struct { ++ struct mutex lock; ++ struct platform_device *pdev; ++ ++ struct hdmi_wp_data wp; ++ struct hdmi_pll_data pll; ++ struct hdmi_phy_data phy; ++ struct hdmi_core_data core; ++ ++ struct hdmi_config cfg; ++ ++ struct clk *sys_clk; ++ struct regulator *vdda_hdmi_dac_reg; ++ ++ bool core_enabled; ++ ++ struct omap_dss_device output; ++} hdmi; ++ ++static int hdmi_runtime_get(void) ++{ ++ int r; ++ ++ DSSDBG("hdmi_runtime_get\n"); ++ ++ r = pm_runtime_get_sync(&hdmi.pdev->dev); ++ WARN_ON(r < 0); ++ if (r < 0) ++ return r; ++ ++ return 0; ++} ++ ++static void hdmi_runtime_put(void) ++{ ++ int r; ++ ++ DSSDBG("hdmi_runtime_put\n"); ++ ++ r = pm_runtime_put_sync(&hdmi.pdev->dev); ++ WARN_ON(r < 0 && r != -ENOSYS); ++} ++ ++static irqreturn_t hdmi_irq_handler(int irq, void *data) ++{ ++ struct hdmi_wp_data *wp = data; ++ u32 irqstatus; ++ ++ irqstatus = hdmi_wp_get_irqstatus(wp); ++ hdmi_wp_set_irqstatus(wp, irqstatus); ++ ++ if ((irqstatus & HDMI_IRQ_LINK_CONNECT) && ++ irqstatus & HDMI_IRQ_LINK_DISCONNECT) { ++ u32 v; ++ /* ++ * If we get both connect and disconnect interrupts at the same ++ * time, turn off the PHY, clear interrupts, and restart, which ++ * raises connect interrupt if a cable is connected, or nothing ++ * if cable is not connected. ++ */ ++ ++ hdmi_wp_set_phy_pwr(wp, HDMI_PHYPWRCMD_OFF); ++ ++ /* ++ * We always get bogus CONNECT & DISCONNECT interrupts when ++ * setting the PHY to LDOON. To ignore those, we force the RXDET ++ * line to 0 until the PHY power state has been changed. ++ */ ++ v = hdmi_read_reg(hdmi.phy.base, HDMI_TXPHY_PAD_CFG_CTRL); ++ v = FLD_MOD(v, 1, 15, 15); /* FORCE_RXDET_HIGH */ ++ v = FLD_MOD(v, 0, 14, 7); /* RXDET_LINE */ ++ hdmi_write_reg(hdmi.phy.base, HDMI_TXPHY_PAD_CFG_CTRL, v); ++ ++ hdmi_wp_set_irqstatus(wp, HDMI_IRQ_LINK_CONNECT | ++ HDMI_IRQ_LINK_DISCONNECT); ++ ++ hdmi_wp_set_phy_pwr(wp, HDMI_PHYPWRCMD_LDOON); ++ ++ REG_FLD_MOD(hdmi.phy.base, HDMI_TXPHY_PAD_CFG_CTRL, 0, 15, 15); ++ ++ } else if (irqstatus & HDMI_IRQ_LINK_CONNECT) { ++ hdmi_wp_set_phy_pwr(wp, HDMI_PHYPWRCMD_TXON); ++ } else if (irqstatus & HDMI_IRQ_LINK_DISCONNECT) { ++ hdmi_wp_set_phy_pwr(wp, HDMI_PHYPWRCMD_LDOON); ++ } ++ ++ return IRQ_HANDLED; ++} ++ ++static int hdmi_init_regulator(void) ++{ ++ int r; ++ struct regulator *reg; ++ ++ if (hdmi.vdda_hdmi_dac_reg != NULL) ++ return 0; ++ ++ reg = devm_regulator_get(&hdmi.pdev->dev, "vdda_hdmi_dac"); ++ if (IS_ERR(reg)) { ++ DSSERR("can't get VDDA_HDMI_DAC regulator\n"); ++ return PTR_ERR(reg); ++ } ++ ++ r = regulator_set_voltage(reg, 1500000, 1800000); ++ if (r) ++ DSSWARN("can't set the regulator voltage"); ++ ++ hdmi.vdda_hdmi_dac_reg = reg; ++ ++ return 0; ++} ++ ++static int hdmi_power_on_core(struct omap_dss_device *dssdev) ++{ ++ int r; ++ ++ r = regulator_enable(hdmi.vdda_hdmi_dac_reg); ++ if (r) ++ return r; ++ ++ r = hdmi_runtime_get(); ++ if (r) ++ goto err_runtime_get; ++ ++ /* Make selection of HDMI in DSS */ ++ dss_select_hdmi_venc_clk_source(DSS_HDMI_M_PCLK); ++ ++ hdmi.core_enabled = true; ++ ++ return 0; ++ ++err_runtime_get: ++ regulator_disable(hdmi.vdda_hdmi_dac_reg); ++ ++ return r; ++} ++ ++static void hdmi_power_off_core(struct omap_dss_device *dssdev) ++{ ++ hdmi.core_enabled = false; ++ ++ hdmi_runtime_put(); ++ regulator_disable(hdmi.vdda_hdmi_dac_reg); ++} ++ ++static int hdmi_power_on_full(struct omap_dss_device *dssdev) ++{ ++ int r; ++ struct omap_video_timings *p; ++ struct omap_overlay_manager *mgr = hdmi.output.manager; ++ unsigned long phy; ++ ++ r = hdmi_power_on_core(dssdev); ++ if (r) ++ return r; ++ ++ p = &hdmi.cfg.timings; ++ ++ DSSDBG("hdmi_power_on x_res= %d y_res = %d\n", p->x_res, p->y_res); ++ ++ phy = p->pixel_clock; ++ ++ hdmi_pll_compute(&hdmi.pll, clk_get_rate(hdmi.sys_clk), phy); ++ ++ /* disable and clear irqs */ ++ hdmi_wp_clear_irqenable(&hdmi.wp, 0xffffffff); ++ hdmi_wp_set_irqstatus(&hdmi.wp, ++ hdmi_wp_get_irqstatus(&hdmi.wp)); ++ ++ /* config the PLL and PHY hdmi_set_pll_pwrfirst */ ++ r = hdmi_pll_enable(&hdmi.pll, &hdmi.wp); ++ if (r) { ++ DSSDBG("Failed to lock PLL\n"); ++ goto err_pll_enable; ++ } ++ ++ r = hdmi_phy_configure(&hdmi.phy, &hdmi.cfg); ++ if (r) { ++ DSSDBG("Failed to start PHY\n"); ++ goto err_phy_cfg; ++ } ++ ++ r = hdmi_wp_set_phy_pwr(&hdmi.wp, HDMI_PHYPWRCMD_LDOON); ++ if (r) ++ goto err_phy_pwr; ++ ++ hdmi5_configure(&hdmi.core, &hdmi.wp, &hdmi.cfg); ++ ++ /* bypass TV gamma table */ ++ dispc_enable_gamma_table(0); ++ ++ /* tv size */ ++ dss_mgr_set_timings(mgr, p); ++ ++ r = hdmi_wp_video_start(&hdmi.wp); ++ if (r) ++ goto err_vid_enable; ++ ++ r = dss_mgr_enable(mgr); ++ if (r) ++ goto err_mgr_enable; ++ ++ hdmi_wp_set_irqenable(&hdmi.wp, ++ HDMI_IRQ_LINK_CONNECT | HDMI_IRQ_LINK_DISCONNECT); ++ ++ return 0; ++ ++err_mgr_enable: ++ hdmi_wp_video_stop(&hdmi.wp); ++err_vid_enable: ++ hdmi_wp_set_phy_pwr(&hdmi.wp, HDMI_PHYPWRCMD_OFF); ++err_phy_pwr: ++err_phy_cfg: ++ hdmi_pll_disable(&hdmi.pll, &hdmi.wp); ++err_pll_enable: ++ hdmi_power_off_core(dssdev); ++ return -EIO; ++} ++ ++static void hdmi_power_off_full(struct omap_dss_device *dssdev) ++{ ++ struct omap_overlay_manager *mgr = hdmi.output.manager; ++ ++ hdmi_wp_clear_irqenable(&hdmi.wp, 0xffffffff); ++ ++ dss_mgr_disable(mgr); ++ ++ hdmi_wp_video_stop(&hdmi.wp); ++ ++ hdmi_wp_set_phy_pwr(&hdmi.wp, HDMI_PHYPWRCMD_OFF); ++ ++ hdmi_pll_disable(&hdmi.pll, &hdmi.wp); ++ ++ hdmi_power_off_core(dssdev); ++} ++ ++static int hdmi_display_check_timing(struct omap_dss_device *dssdev, ++ struct omap_video_timings *timings) ++{ ++ struct hdmi_cm cm; ++ ++ cm = hdmi_get_code(timings); ++ if (cm.code == -1) { ++ return -EINVAL; ++ } ++ ++ return 0; ++ ++} ++ ++static void hdmi_display_set_timing(struct omap_dss_device *dssdev, ++ struct omap_video_timings *timings) ++{ ++ struct hdmi_cm cm; ++ const struct hdmi_config *t; ++ ++ mutex_lock(&hdmi.lock); ++ ++ cm = hdmi_get_code(timings); ++ hdmi.cfg.cm = cm; ++ ++ t = hdmi_get_timings(cm.mode, cm.code); ++ if (t != NULL) { ++ hdmi.cfg = *t; ++ ++ dispc_set_tv_pclk(t->timings.pixel_clock * 1000); ++ } ++ ++ mutex_unlock(&hdmi.lock); ++} ++ ++static void hdmi_display_get_timings(struct omap_dss_device *dssdev, ++ struct omap_video_timings *timings) ++{ ++ const struct hdmi_config *cfg; ++ struct hdmi_cm cm = hdmi.cfg.cm; ++ ++ cfg = hdmi_get_timings(cm.mode, cm.code); ++ if (cfg == NULL) ++ cfg = hdmi_default_timing(); ++ ++ memcpy(timings, &cfg->timings, sizeof(cfg->timings)); ++} ++ ++static void hdmi_dump_regs(struct seq_file *s) ++{ ++ mutex_lock(&hdmi.lock); ++ ++ if (hdmi_runtime_get()) { ++ mutex_unlock(&hdmi.lock); ++ return; ++ } ++ ++ hdmi_wp_dump(&hdmi.wp, s); ++ hdmi_pll_dump(&hdmi.pll, s); ++ hdmi_phy_dump(&hdmi.phy, s); ++ hdmi5_core_dump(&hdmi.core, s); ++ ++ hdmi_runtime_put(); ++ mutex_unlock(&hdmi.lock); ++} ++ ++static int read_edid(u8 *buf, int len) ++{ ++ int r; ++ int idlemode; ++ ++ mutex_lock(&hdmi.lock); ++ ++ r = hdmi_runtime_get(); ++ BUG_ON(r); ++ ++ idlemode = REG_GET(hdmi.wp.base, HDMI_WP_SYSCONFIG, 3, 2); ++ /* No-idle mode */ ++ REG_FLD_MOD(hdmi.wp.base, HDMI_WP_SYSCONFIG, 1, 3, 2); ++ ++ r = hdmi5_read_edid(&hdmi.core, buf, len); ++ ++ REG_FLD_MOD(hdmi.wp.base, HDMI_WP_SYSCONFIG, idlemode, 3, 2); ++ ++ hdmi_runtime_put(); ++ mutex_unlock(&hdmi.lock); ++ ++ return r; ++} ++ ++static int hdmi_display_enable(struct omap_dss_device *dssdev) ++{ ++ struct omap_dss_device *out = &hdmi.output; ++ int r = 0; ++ ++ DSSDBG("ENTER hdmi_display_enable\n"); ++ ++ mutex_lock(&hdmi.lock); ++ ++ if (out == NULL || out->manager == NULL) { ++ DSSERR("failed to enable display: no output/manager\n"); ++ r = -ENODEV; ++ goto err0; ++ } ++ ++ r = hdmi_power_on_full(dssdev); ++ if (r) { ++ DSSERR("failed to power on device\n"); ++ goto err0; ++ } ++ ++ mutex_unlock(&hdmi.lock); ++ return 0; ++ ++err0: ++ mutex_unlock(&hdmi.lock); ++ return r; ++} ++ ++static void hdmi_display_disable(struct omap_dss_device *dssdev) ++{ ++ DSSDBG("Enter hdmi_display_disable\n"); ++ ++ mutex_lock(&hdmi.lock); ++ ++ hdmi_power_off_full(dssdev); ++ ++ mutex_unlock(&hdmi.lock); ++} ++ ++static int hdmi_core_enable(struct omap_dss_device *dssdev) ++{ ++ int r = 0; ++ ++ DSSDBG("ENTER omapdss_hdmi_core_enable\n"); ++ ++ mutex_lock(&hdmi.lock); ++ ++ r = hdmi_power_on_core(dssdev); ++ if (r) { ++ DSSERR("failed to power on device\n"); ++ goto err0; ++ } ++ ++ mutex_unlock(&hdmi.lock); ++ return 0; ++ ++err0: ++ mutex_unlock(&hdmi.lock); ++ return r; ++} ++ ++static void hdmi_core_disable(struct omap_dss_device *dssdev) ++{ ++ DSSDBG("Enter omapdss_hdmi_core_disable\n"); ++ ++ mutex_lock(&hdmi.lock); ++ ++ hdmi_power_off_core(dssdev); ++ ++ mutex_unlock(&hdmi.lock); ++} ++ ++static int hdmi_get_clocks(struct platform_device *pdev) ++{ ++ struct clk *clk; ++ ++ clk = devm_clk_get(&pdev->dev, "sys_clk"); ++ if (IS_ERR(clk)) { ++ DSSERR("can't get sys_clk\n"); ++ return PTR_ERR(clk); ++ } ++ ++ hdmi.sys_clk = clk; ++ ++ return 0; ++} ++ ++static int hdmi_connect(struct omap_dss_device *dssdev, ++ struct omap_dss_device *dst) ++{ ++ struct omap_overlay_manager *mgr; ++ int r; ++ ++ r = hdmi_init_regulator(); ++ if (r) ++ return r; ++ ++ mgr = omap_dss_get_overlay_manager(dssdev->dispc_channel); ++ if (!mgr) ++ return -ENODEV; ++ ++ r = dss_mgr_connect(mgr, dssdev); ++ if (r) ++ return r; ++ ++ r = omapdss_output_set_device(dssdev, dst); ++ if (r) { ++ DSSERR("failed to connect output to new device: %s\n", ++ dst->name); ++ dss_mgr_disconnect(mgr, dssdev); ++ return r; ++ } ++ ++ return 0; ++} ++ ++static void hdmi_disconnect(struct omap_dss_device *dssdev, ++ struct omap_dss_device *dst) ++{ ++ WARN_ON(dst != dssdev->dst); ++ ++ if (dst != dssdev->dst) ++ return; ++ ++ omapdss_output_unset_device(dssdev); ++ ++ if (dssdev->manager) ++ dss_mgr_disconnect(dssdev->manager, dssdev); ++} ++ ++static int hdmi_read_edid(struct omap_dss_device *dssdev, ++ u8 *edid, int len) ++{ ++ bool need_enable; ++ int r; ++ ++ need_enable = hdmi.core_enabled == false; ++ ++ if (need_enable) { ++ r = hdmi_core_enable(dssdev); ++ if (r) ++ return r; ++ } ++ ++ r = read_edid(edid, len); ++ ++ if (need_enable) ++ hdmi_core_disable(dssdev); ++ ++ return r; ++} ++ ++#if defined(CONFIG_OMAP5_DSS_HDMI_AUDIO) ++static int hdmi_audio_enable(struct omap_dss_device *dssdev) ++{ ++ int r; ++ ++ mutex_lock(&hdmi.lock); ++ ++ if (!hdmi_mode_has_audio(hdmi.cfg.cm.mode)) { ++ r = -EPERM; ++ goto err; ++ } ++ ++ r = hdmi_wp_audio_enable(&hdmi.wp, true); ++ if (r) ++ goto err; ++ ++ mutex_unlock(&hdmi.lock); ++ return 0; ++ ++err: ++ mutex_unlock(&hdmi.lock); ++ return r; ++} ++ ++static void hdmi_audio_disable(struct omap_dss_device *dssdev) ++{ ++ hdmi_wp_audio_enable(&hdmi.wp, false); ++} ++ ++static int hdmi_audio_start(struct omap_dss_device *dssdev) ++{ ++ return hdmi_wp_audio_core_req_enable(&hdmi.wp, true); ++} ++ ++static void hdmi_audio_stop(struct omap_dss_device *dssdev) ++{ ++ hdmi_wp_audio_core_req_enable(&hdmi.wp, false); ++} ++ ++static bool hdmi_audio_supported(struct omap_dss_device *dssdev) ++{ ++ bool r; ++ ++ mutex_lock(&hdmi.lock); ++ ++ r = hdmi_mode_has_audio(hdmi.cfg.cm.mode); ++ ++ mutex_unlock(&hdmi.lock); ++ return r; ++} ++ ++static int hdmi_audio_config(struct omap_dss_device *dssdev, ++ struct omap_dss_audio *audio) ++{ ++ int r; ++ u32 pclk = hdmi.cfg.timings.pixel_clock; ++ ++ mutex_lock(&hdmi.lock); ++ ++ if (!hdmi_mode_has_audio(hdmi.cfg.cm.mode)) { ++ r = -EPERM; ++ goto err; ++ } ++ ++ r = hdmi5_audio_config(&hdmi.core, &hdmi.wp, audio, pclk); ++ if (r) ++ goto err; ++ ++ mutex_unlock(&hdmi.lock); ++ return 0; ++ ++err: ++ mutex_unlock(&hdmi.lock); ++ return r; ++} ++#else ++static int hdmi_audio_enable(struct omap_dss_device *dssdev) ++{ ++ return -EPERM; ++} ++ ++static void hdmi_audio_disable(struct omap_dss_device *dssdev) ++{ ++} ++ ++static int hdmi_audio_start(struct omap_dss_device *dssdev) ++{ ++ return -EPERM; ++} ++ ++static void hdmi_audio_stop(struct omap_dss_device *dssdev) ++{ ++} ++ ++static bool hdmi_audio_supported(struct omap_dss_device *dssdev) ++{ ++ return false; ++} ++ ++static int hdmi_audio_config(struct omap_dss_device *dssdev, ++ struct omap_dss_audio *audio) ++{ ++ return -EPERM; ++} ++#endif ++ ++static const struct omapdss_hdmi_ops hdmi_ops = { ++ .connect = hdmi_connect, ++ .disconnect = hdmi_disconnect, ++ ++ .enable = hdmi_display_enable, ++ .disable = hdmi_display_disable, ++ ++ .check_timings = hdmi_display_check_timing, ++ .set_timings = hdmi_display_set_timing, ++ .get_timings = hdmi_display_get_timings, ++ ++ .read_edid = hdmi_read_edid, ++ ++ .audio_enable = hdmi_audio_enable, ++ .audio_disable = hdmi_audio_disable, ++ .audio_start = hdmi_audio_start, ++ .audio_stop = hdmi_audio_stop, ++ .audio_supported = hdmi_audio_supported, ++ .audio_config = hdmi_audio_config, ++}; ++ ++static void hdmi_init_output(struct platform_device *pdev) ++{ ++ struct omap_dss_device *out = &hdmi.output; ++ ++ out->dev = &pdev->dev; ++ out->id = OMAP_DSS_OUTPUT_HDMI; ++ out->output_type = OMAP_DISPLAY_TYPE_HDMI; ++ out->name = "hdmi.0"; ++ out->dispc_channel = OMAP_DSS_CHANNEL_DIGIT; ++ out->ops.hdmi = &hdmi_ops; ++ out->owner = THIS_MODULE; ++ ++ omapdss_register_output(out); ++} ++ ++static void __exit hdmi_uninit_output(struct platform_device *pdev) ++{ ++ struct omap_dss_device *out = &hdmi.output; ++ ++ omapdss_unregister_output(out); ++} ++ ++/* HDMI HW IP initialisation */ ++static int omapdss_hdmihw_probe(struct platform_device *pdev) ++{ ++ int r; ++ int irq; ++ ++ hdmi.pdev = pdev; ++ ++ mutex_init(&hdmi.lock); ++ ++ r = hdmi_wp_init(pdev, &hdmi.wp); ++ if (r) ++ return r; ++ ++ r = hdmi_pll_init(pdev, &hdmi.pll); ++ if (r) ++ return r; ++ ++ r = hdmi_phy_init(pdev, &hdmi.phy); ++ if (r) ++ return r; ++ ++ r = hdmi5_core_init(pdev, &hdmi.core); ++ if (r) ++ return r; ++ ++ r = hdmi_get_clocks(pdev); ++ if (r) { ++ DSSERR("can't get clocks\n"); ++ return r; ++ } ++ ++ irq = platform_get_irq(pdev, 0); ++ if (irq < 0) { ++ DSSERR("platform_get_irq failed\n"); ++ return -ENODEV; ++ } ++ ++ r = devm_request_threaded_irq(&pdev->dev, irq, ++ NULL, hdmi_irq_handler, ++ IRQF_ONESHOT, "OMAP HDMI", &hdmi.wp); ++ if (r) { ++ DSSERR("HDMI IRQ request failed\n"); ++ return r; ++ } ++ ++ pm_runtime_enable(&pdev->dev); ++ ++ hdmi_init_output(pdev); ++ ++ dss_debugfs_create_file("hdmi", hdmi_dump_regs); ++ ++ return 0; ++} ++ ++static int __exit omapdss_hdmihw_remove(struct platform_device *pdev) ++{ ++ hdmi_uninit_output(pdev); ++ ++ pm_runtime_disable(&pdev->dev); ++ ++ return 0; ++} ++ ++static int hdmi_runtime_suspend(struct device *dev) ++{ ++ clk_disable_unprepare(hdmi.sys_clk); ++ ++ dispc_runtime_put(); ++ ++ return 0; ++} ++ ++static int hdmi_runtime_resume(struct device *dev) ++{ ++ int r; ++ ++ r = dispc_runtime_get(); ++ if (r < 0) ++ return r; ++ ++ clk_prepare_enable(hdmi.sys_clk); ++ ++ return 0; ++} ++ ++static const struct dev_pm_ops hdmi_pm_ops = { ++ .runtime_suspend = hdmi_runtime_suspend, ++ .runtime_resume = hdmi_runtime_resume, ++}; ++ ++static const struct of_device_id hdmi_of_match[] = { ++ { .compatible = "ti,omap5-hdmi", }, ++ {}, ++}; ++ ++static struct platform_driver omapdss_hdmihw_driver = { ++ .probe = omapdss_hdmihw_probe, ++ .remove = __exit_p(omapdss_hdmihw_remove), ++ .driver = { ++ .name = "omapdss_hdmi5", ++ .owner = THIS_MODULE, ++ .pm = &hdmi_pm_ops, ++ .of_match_table = hdmi_of_match, ++ }, ++}; ++ ++int __init hdmi5_init_platform_driver(void) ++{ ++ return platform_driver_register(&omapdss_hdmihw_driver); ++} ++ ++void __exit hdmi5_uninit_platform_driver(void) ++{ ++ platform_driver_unregister(&omapdss_hdmihw_driver); ++} +--- /dev/null ++++ b/drivers/video/omap2/dss/hdmi5_core.c +@@ -0,0 +1,915 @@ ++/* ++ * OMAP5 HDMI CORE IP driver Library ++ * Copyright (C) 2011-2012 Texas Instruments Incorporated - http://www.ti.com/ ++ * Author: Mythri pk <mythripk@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, see <http://www.gnu.org/licenses/>. ++ */ ++ ++#include <linux/kernel.h> ++#include <linux/module.h> ++#include <linux/err.h> ++#include <linux/io.h> ++#include <linux/delay.h> ++#include <linux/string.h> ++#include <linux/seq_file.h> ++#include <drm/drm_edid.h> ++#if defined(CONFIG_OMAP5_DSS_HDMI_AUDIO) ++#include <sound/asound.h> ++#include <sound/asoundef.h> ++#endif ++ ++#include "hdmi5_core.h" ++ ++/* only 24 bit color depth used for now */ ++static const struct csc_table csc_table_deepcolor[] = { ++ /* HDMI_DEEP_COLOR_24BIT */ ++ [0] = { 7036, 0, 0, 32, 0, 7036, 0, 32, 0, 0, 7036, 32, }, ++ /* HDMI_DEEP_COLOR_30BIT */ ++ [1] = { 7015, 0, 0, 128, 0, 7015, 0, 128, 0, 0, 7015, 128, }, ++ /* HDMI_DEEP_COLOR_36BIT */ ++ [2] = { 7010, 0, 0, 512, 0, 7010, 0, 512, 0, 0, 7010, 512, }, ++ /* FULL RANGE */ ++ [3] = { 8192, 0, 0, 0, 0, 8192, 0, 0, 0, 0, 8192, 0, }, ++}; ++ ++static void hdmi_core_ddc_init(struct hdmi_core_data *core) ++{ ++ void __iomem *base = core->base; ++ const unsigned long long iclk = 266000000; /* DSS L3 ICLK */ ++ const unsigned ss_scl_high = 4000; /* ns */ ++ const unsigned ss_scl_low = 4700; /* ns */ ++ const unsigned fs_scl_high = 600; /* ns */ ++ const unsigned fs_scl_low = 1300; /* ns */ ++ const unsigned sda_hold = 300; /* ns */ ++ const unsigned sfr_div = 10; ++ unsigned long long sfr; ++ unsigned v; ++ ++ sfr = iclk / sfr_div; /* SFR_DIV */ ++ sfr /= 1000; /* SFR clock in kHz */ ++ ++ /* Reset */ ++ REG_FLD_MOD(base, HDMI_CORE_I2CM_SOFTRSTZ, 0, 0, 0); ++ if (hdmi_wait_for_bit_change(base, HDMI_CORE_I2CM_SOFTRSTZ, ++ 0, 0, 1) != 1) ++ DSSERR("HDMI I2CM reset failed\n"); ++ ++ /* Standard (0) or Fast (1) Mode */ ++ REG_FLD_MOD(base, HDMI_CORE_I2CM_DIV, 0, 3, 3); ++ ++ /* Standard Mode SCL High counter */ ++ v = DIV_ROUND_UP_ULL(ss_scl_high * sfr, 1000000); ++ REG_FLD_MOD(base, HDMI_CORE_I2CM_SS_SCL_HCNT_1_ADDR, ++ (v >> 8) & 0xff, 7, 0); ++ REG_FLD_MOD(base, HDMI_CORE_I2CM_SS_SCL_HCNT_0_ADDR, ++ v & 0xff, 7, 0); ++ ++ /* Standard Mode SCL Low counter */ ++ v = DIV_ROUND_UP_ULL(ss_scl_low * sfr, 1000000); ++ REG_FLD_MOD(base, HDMI_CORE_I2CM_SS_SCL_LCNT_1_ADDR, ++ (v >> 8) & 0xff, 7, 0); ++ REG_FLD_MOD(base, HDMI_CORE_I2CM_SS_SCL_LCNT_0_ADDR, ++ v & 0xff, 7, 0); ++ ++ /* Fast Mode SCL High Counter */ ++ v = DIV_ROUND_UP_ULL(fs_scl_high * sfr, 1000000); ++ REG_FLD_MOD(base, HDMI_CORE_I2CM_FS_SCL_HCNT_1_ADDR, ++ (v >> 8) & 0xff, 7, 0); ++ REG_FLD_MOD(base, HDMI_CORE_I2CM_FS_SCL_HCNT_0_ADDR, ++ v & 0xff, 7, 0); ++ ++ /* Fast Mode SCL Low Counter */ ++ v = DIV_ROUND_UP_ULL(fs_scl_low * sfr, 1000000); ++ REG_FLD_MOD(base, HDMI_CORE_I2CM_FS_SCL_LCNT_1_ADDR, ++ (v >> 8) & 0xff, 7, 0); ++ REG_FLD_MOD(base, HDMI_CORE_I2CM_FS_SCL_LCNT_0_ADDR, ++ v & 0xff, 7, 0); ++ ++ /* SDA Hold Time */ ++ v = DIV_ROUND_UP_ULL(sda_hold * sfr, 1000000); ++ REG_FLD_MOD(base, HDMI_CORE_I2CM_SDA_HOLD_ADDR, v & 0xff, 7, 0); ++ ++ REG_FLD_MOD(base, HDMI_CORE_I2CM_SLAVE, 0x50, 6, 0); ++ REG_FLD_MOD(base, HDMI_CORE_I2CM_SEGADDR, 0x30, 6, 0); ++ ++ /* NACK_POL to high */ ++ REG_FLD_MOD(base, HDMI_CORE_I2CM_CTLINT, 0x1, 7, 7); ++ ++ /* NACK_MASK to unmasked */ ++ REG_FLD_MOD(base, HDMI_CORE_I2CM_CTLINT, 0x0, 6, 6); ++ ++ /* ARBITRATION_POL to high */ ++ REG_FLD_MOD(base, HDMI_CORE_I2CM_CTLINT, 0x1, 3, 3); ++ ++ /* ARBITRATION_MASK to unmasked */ ++ REG_FLD_MOD(base, HDMI_CORE_I2CM_CTLINT, 0x0, 2, 2); ++ ++ /* DONE_POL to high */ ++ REG_FLD_MOD(base, HDMI_CORE_I2CM_INT, 0x1, 3, 3); ++ ++ /* DONE_MASK to unmasked */ ++ REG_FLD_MOD(base, HDMI_CORE_I2CM_INT, 0x0, 2, 2); ++} ++ ++static void hdmi_core_ddc_uninit(struct hdmi_core_data *core) ++{ ++ void __iomem *base = core->base; ++ ++ /* Mask I2C interrupts */ ++ REG_FLD_MOD(base, HDMI_CORE_I2CM_CTLINT, 0x1, 6, 6); ++ REG_FLD_MOD(base, HDMI_CORE_I2CM_CTLINT, 0x1, 2, 2); ++ REG_FLD_MOD(base, HDMI_CORE_I2CM_INT, 0x1, 2, 2); ++} ++ ++static int hdmi_core_ddc_edid(struct hdmi_core_data *core, u8 *pedid, u8 ext) ++{ ++ void __iomem *base = core->base; ++ u8 cur_addr; ++ char checksum = 0; ++ const int retries = 1000; ++ u8 seg_ptr = ext / 2; ++ u8 edidbase = ((ext % 2) * 0x80); ++ ++ REG_FLD_MOD(base, HDMI_CORE_I2CM_SEGPTR, seg_ptr, 7, 0); ++ ++ /* ++ * TODO: We use polling here, although we probably should use proper ++ * interrupts. ++ */ ++ for (cur_addr = 0; cur_addr < 128; ++cur_addr) { ++ int i; ++ ++ /* clear ERROR and DONE */ ++ REG_FLD_MOD(base, HDMI_CORE_IH_I2CM_STAT0, 0x3, 1, 0); ++ ++ REG_FLD_MOD(base, HDMI_CORE_I2CM_ADDRESS, ++ edidbase + cur_addr, 7, 0); ++ ++ if (seg_ptr) ++ REG_FLD_MOD(base, HDMI_CORE_I2CM_OPERATION, 1, 1, 1); ++ else ++ REG_FLD_MOD(base, HDMI_CORE_I2CM_OPERATION, 1, 0, 0); ++ ++ for (i = 0; i < retries; ++i) { ++ u32 stat; ++ ++ stat = REG_GET(base, HDMI_CORE_IH_I2CM_STAT0, 1, 0); ++ ++ /* I2CM_ERROR */ ++ if (stat & 1) { ++ DSSERR("HDMI I2C Master Error\n"); ++ return -EIO; ++ } ++ ++ /* I2CM_DONE */ ++ if (stat & (1 << 1)) ++ break; ++ ++ usleep_range(250, 1000); ++ } ++ ++ if (i == retries) { ++ DSSERR("HDMI I2C timeout reading EDID\n"); ++ return -EIO; ++ } ++ ++ pedid[cur_addr] = REG_GET(base, HDMI_CORE_I2CM_DATAI, 7, 0); ++ checksum += pedid[cur_addr]; ++ } ++ ++ return 0; ++ ++} ++ ++int hdmi5_read_edid(struct hdmi_core_data *core, u8 *edid, int len) ++{ ++ int r, n, i; ++ int max_ext_blocks = (len / 128) - 1; ++ ++ if (len < 128) ++ return -EINVAL; ++ ++ hdmi_core_ddc_init(core); ++ ++ r = hdmi_core_ddc_edid(core, edid, 0); ++ if (r) ++ goto out; ++ ++ n = edid[0x7e]; ++ ++ if (n > max_ext_blocks) ++ n = max_ext_blocks; ++ ++ for (i = 1; i <= n; i++) { ++ r = hdmi_core_ddc_edid(core, edid + i * EDID_LENGTH, i); ++ if (r) ++ goto out; ++ } ++ ++out: ++ hdmi_core_ddc_uninit(core); ++ ++ return r; ++} ++ ++void hdmi5_core_dump(struct hdmi_core_data *core, struct seq_file *s) ++{ ++ ++#define DUMPCORE(r) seq_printf(s, "%-35s %08x\n", #r,\ ++ hdmi_read_reg(core->base, r)) ++ ++ DUMPCORE(HDMI_CORE_FC_INVIDCONF); ++ DUMPCORE(HDMI_CORE_FC_INHACTIV0); ++ DUMPCORE(HDMI_CORE_FC_INHACTIV1); ++ DUMPCORE(HDMI_CORE_FC_INHBLANK0); ++ DUMPCORE(HDMI_CORE_FC_INHBLANK1); ++ DUMPCORE(HDMI_CORE_FC_INVACTIV0); ++ DUMPCORE(HDMI_CORE_FC_INVACTIV1); ++ DUMPCORE(HDMI_CORE_FC_INVBLANK); ++ DUMPCORE(HDMI_CORE_FC_HSYNCINDELAY0); ++ DUMPCORE(HDMI_CORE_FC_HSYNCINDELAY1); ++ DUMPCORE(HDMI_CORE_FC_HSYNCINWIDTH0); ++ DUMPCORE(HDMI_CORE_FC_HSYNCINWIDTH1); ++ DUMPCORE(HDMI_CORE_FC_VSYNCINDELAY); ++ DUMPCORE(HDMI_CORE_FC_VSYNCINWIDTH); ++ DUMPCORE(HDMI_CORE_FC_CTRLDUR); ++ DUMPCORE(HDMI_CORE_FC_EXCTRLDUR); ++ DUMPCORE(HDMI_CORE_FC_EXCTRLSPAC); ++ DUMPCORE(HDMI_CORE_FC_CH0PREAM); ++ DUMPCORE(HDMI_CORE_FC_CH1PREAM); ++ DUMPCORE(HDMI_CORE_FC_CH2PREAM); ++ DUMPCORE(HDMI_CORE_FC_AVICONF0); ++ DUMPCORE(HDMI_CORE_FC_AVICONF1); ++ DUMPCORE(HDMI_CORE_FC_AVICONF2); ++ DUMPCORE(HDMI_CORE_FC_AVIVID); ++ DUMPCORE(HDMI_CORE_FC_PRCONF); ++ ++ DUMPCORE(HDMI_CORE_MC_CLKDIS); ++ DUMPCORE(HDMI_CORE_MC_SWRSTZREQ); ++ DUMPCORE(HDMI_CORE_MC_FLOWCTRL); ++ DUMPCORE(HDMI_CORE_MC_PHYRSTZ); ++ DUMPCORE(HDMI_CORE_MC_LOCKONCLOCK); ++ ++ DUMPCORE(HDMI_CORE_I2CM_SLAVE); ++ DUMPCORE(HDMI_CORE_I2CM_ADDRESS); ++ DUMPCORE(HDMI_CORE_I2CM_DATAO); ++ DUMPCORE(HDMI_CORE_I2CM_DATAI); ++ DUMPCORE(HDMI_CORE_I2CM_OPERATION); ++ DUMPCORE(HDMI_CORE_I2CM_INT); ++ DUMPCORE(HDMI_CORE_I2CM_CTLINT); ++ DUMPCORE(HDMI_CORE_I2CM_DIV); ++ DUMPCORE(HDMI_CORE_I2CM_SEGADDR); ++ DUMPCORE(HDMI_CORE_I2CM_SOFTRSTZ); ++ DUMPCORE(HDMI_CORE_I2CM_SEGPTR); ++ DUMPCORE(HDMI_CORE_I2CM_SS_SCL_HCNT_1_ADDR); ++ DUMPCORE(HDMI_CORE_I2CM_SS_SCL_HCNT_0_ADDR); ++ DUMPCORE(HDMI_CORE_I2CM_SS_SCL_LCNT_1_ADDR); ++ DUMPCORE(HDMI_CORE_I2CM_SS_SCL_LCNT_0_ADDR); ++ DUMPCORE(HDMI_CORE_I2CM_FS_SCL_HCNT_1_ADDR); ++ DUMPCORE(HDMI_CORE_I2CM_FS_SCL_HCNT_0_ADDR); ++ DUMPCORE(HDMI_CORE_I2CM_FS_SCL_LCNT_1_ADDR); ++ DUMPCORE(HDMI_CORE_I2CM_FS_SCL_LCNT_0_ADDR); ++ DUMPCORE(HDMI_CORE_I2CM_SDA_HOLD_ADDR); ++} ++ ++static void hdmi_core_init(struct hdmi_core_vid_config *video_cfg, ++ struct hdmi_core_infoframe_avi *avi_cfg, ++ struct hdmi_config *cfg) ++{ ++ DSSDBG("hdmi_core_init\n"); ++ ++ /* video core */ ++ video_cfg->data_enable_pol = 1; /* It is always 1*/ ++ video_cfg->v_fc_config.timings.hsync_level = cfg->timings.hsync_level; ++ video_cfg->v_fc_config.timings.x_res = cfg->timings.x_res; ++ video_cfg->v_fc_config.timings.hsw = cfg->timings.hsw - 1; ++ video_cfg->v_fc_config.timings.hbp = cfg->timings.hbp; ++ video_cfg->v_fc_config.timings.hfp = cfg->timings.hfp; ++ video_cfg->hblank = cfg->timings.hfp + ++ cfg->timings.hbp + cfg->timings.hsw - 1; ++ video_cfg->v_fc_config.timings.vsync_level = cfg->timings.vsync_level; ++ video_cfg->v_fc_config.timings.y_res = cfg->timings.y_res; ++ video_cfg->v_fc_config.timings.vsw = cfg->timings.vsw; ++ video_cfg->v_fc_config.timings.vfp = cfg->timings.vfp; ++ video_cfg->v_fc_config.timings.vbp = cfg->timings.vbp; ++ video_cfg->vblank_osc = 0; /* Always 0 - need to confirm */ ++ video_cfg->vblank = cfg->timings.vsw + ++ cfg->timings.vfp + cfg->timings.vbp; ++ video_cfg->v_fc_config.cm.mode = cfg->cm.mode; ++ video_cfg->v_fc_config.timings.interlace = cfg->timings.interlace; ++ ++ /* info frame */ ++ avi_cfg->db1_format = 0; ++ avi_cfg->db1_active_info = 0; ++ avi_cfg->db1_bar_info_dv = 0; ++ avi_cfg->db1_scan_info = 0; ++ avi_cfg->db2_colorimetry = 0; ++ avi_cfg->db2_aspect_ratio = 0; ++ avi_cfg->db2_active_fmt_ar = 0; ++ avi_cfg->db3_itc = 0; ++ avi_cfg->db3_ec = 0; ++ avi_cfg->db3_q_range = 0; ++ avi_cfg->db3_nup_scaling = 0; ++ avi_cfg->db4_videocode = 0; ++ avi_cfg->db5_pixel_repeat = 0; ++ avi_cfg->db6_7_line_eoftop = 0 ; ++ avi_cfg->db8_9_line_sofbottom = 0; ++ avi_cfg->db10_11_pixel_eofleft = 0; ++ avi_cfg->db12_13_pixel_sofright = 0; ++} ++ ++/* DSS_HDMI_CORE_VIDEO_CONFIG */ ++static void hdmi_core_video_config(struct hdmi_core_data *core, ++ struct hdmi_core_vid_config *cfg) ++{ ++ void __iomem *base = core->base; ++ unsigned char r = 0; ++ bool vsync_pol, hsync_pol; ++ ++ vsync_pol = ++ cfg->v_fc_config.timings.vsync_level == OMAPDSS_SIG_ACTIVE_HIGH; ++ hsync_pol = ++ cfg->v_fc_config.timings.hsync_level == OMAPDSS_SIG_ACTIVE_HIGH; ++ ++ /* Set hsync, vsync and data-enable polarity */ ++ r = hdmi_read_reg(base, HDMI_CORE_FC_INVIDCONF); ++ r = FLD_MOD(r, vsync_pol, 6, 6); ++ r = FLD_MOD(r, hsync_pol, 5, 5); ++ r = FLD_MOD(r, cfg->data_enable_pol, 4, 4); ++ r = FLD_MOD(r, cfg->vblank_osc, 1, 1); ++ r = FLD_MOD(r, cfg->v_fc_config.timings.interlace, 0, 0); ++ hdmi_write_reg(base, HDMI_CORE_FC_INVIDCONF, r); ++ ++ /* set x resolution */ ++ REG_FLD_MOD(base, HDMI_CORE_FC_INHACTIV1, ++ cfg->v_fc_config.timings.x_res >> 8, 4, 0); ++ REG_FLD_MOD(base, HDMI_CORE_FC_INHACTIV0, ++ cfg->v_fc_config.timings.x_res & 0xFF, 7, 0); ++ ++ /* set y resolution */ ++ REG_FLD_MOD(base, HDMI_CORE_FC_INVACTIV1, ++ cfg->v_fc_config.timings.y_res >> 8, 4, 0); ++ REG_FLD_MOD(base, HDMI_CORE_FC_INVACTIV0, ++ cfg->v_fc_config.timings.y_res & 0xFF, 7, 0); ++ ++ /* set horizontal blanking pixels */ ++ REG_FLD_MOD(base, HDMI_CORE_FC_INHBLANK1, cfg->hblank >> 8, 4, 0); ++ REG_FLD_MOD(base, HDMI_CORE_FC_INHBLANK0, cfg->hblank & 0xFF, 7, 0); ++ ++ /* set vertial blanking pixels */ ++ REG_FLD_MOD(base, HDMI_CORE_FC_INVBLANK, cfg->vblank, 7, 0); ++ ++ /* set horizontal sync offset */ ++ REG_FLD_MOD(base, HDMI_CORE_FC_HSYNCINDELAY1, ++ cfg->v_fc_config.timings.hfp >> 8, 4, 0); ++ REG_FLD_MOD(base, HDMI_CORE_FC_HSYNCINDELAY0, ++ cfg->v_fc_config.timings.hfp & 0xFF, 7, 0); ++ ++ /* set vertical sync offset */ ++ REG_FLD_MOD(base, HDMI_CORE_FC_VSYNCINDELAY, ++ cfg->v_fc_config.timings.vfp, 7, 0); ++ ++ /* set horizontal sync pulse width */ ++ REG_FLD_MOD(base, HDMI_CORE_FC_HSYNCINWIDTH1, ++ (cfg->v_fc_config.timings.hsw >> 8), 1, 0); ++ REG_FLD_MOD(base, HDMI_CORE_FC_HSYNCINWIDTH0, ++ cfg->v_fc_config.timings.hsw & 0xFF, 7, 0); ++ ++ /* set vertical sync pulse width */ ++ REG_FLD_MOD(base, HDMI_CORE_FC_VSYNCINWIDTH, ++ cfg->v_fc_config.timings.vsw, 5, 0); ++ ++ /* select DVI mode */ ++ REG_FLD_MOD(base, HDMI_CORE_FC_INVIDCONF, ++ cfg->v_fc_config.cm.mode, 3, 3); ++} ++ ++static void hdmi_core_config_video_packetizer(struct hdmi_core_data *core) ++{ ++ void __iomem *base = core->base; ++ int clr_depth = 0; /* 24 bit color depth */ ++ ++ /* COLOR_DEPTH */ ++ REG_FLD_MOD(base, HDMI_CORE_VP_PR_CD, clr_depth, 7, 4); ++ /* BYPASS_EN */ ++ REG_FLD_MOD(base, HDMI_CORE_VP_CONF, clr_depth ? 0 : 1, 6, 6); ++ /* PP_EN */ ++ REG_FLD_MOD(base, HDMI_CORE_VP_CONF, clr_depth ? 1 : 0, 5, 5); ++ /* YCC422_EN */ ++ REG_FLD_MOD(base, HDMI_CORE_VP_CONF, 0, 3, 3); ++ /* PP_STUFFING */ ++ REG_FLD_MOD(base, HDMI_CORE_VP_STUFF, clr_depth ? 1 : 0, 1, 1); ++ /* YCC422_STUFFING */ ++ REG_FLD_MOD(base, HDMI_CORE_VP_STUFF, 1, 2, 2); ++ /* OUTPUT_SELECTOR */ ++ REG_FLD_MOD(base, HDMI_CORE_VP_CONF, clr_depth ? 0 : 2, 1, 0); ++} ++ ++static void hdmi_core_config_csc(struct hdmi_core_data *core) ++{ ++ int clr_depth = 0; /* 24 bit color depth */ ++ ++ /* CSC_COLORDEPTH */ ++ REG_FLD_MOD(core->base, HDMI_CORE_CSC_SCALE, clr_depth, 7, 4); ++} ++ ++static void hdmi_core_config_video_sampler(struct hdmi_core_data *core) ++{ ++ int video_mapping = 1; /* for 24 bit color depth */ ++ ++ /* VIDEO_MAPPING */ ++ REG_FLD_MOD(core->base, HDMI_CORE_TX_INVID0, video_mapping, 4, 0); ++} ++ ++static void hdmi_core_aux_infoframe_avi_config(struct hdmi_core_data *core) ++{ ++ void __iomem *base = core->base; ++ struct hdmi_core_infoframe_avi avi = core->avi_cfg; ++ ++ REG_FLD_MOD(base, HDMI_CORE_FC_AVICONF0, avi.db1_format, 1, 0); ++ REG_FLD_MOD(base, HDMI_CORE_FC_AVICONF0, avi.db1_active_info, 6, 6); ++ REG_FLD_MOD(base, HDMI_CORE_FC_AVICONF0, avi.db1_bar_info_dv, 3, 2); ++ REG_FLD_MOD(base, HDMI_CORE_FC_AVICONF0, avi.db1_scan_info, 5, 4); ++ REG_FLD_MOD(base, HDMI_CORE_FC_AVICONF1, avi.db2_colorimetry, 7, 6); ++ REG_FLD_MOD(base, HDMI_CORE_FC_AVICONF1, avi.db2_aspect_ratio, 5, 4); ++ REG_FLD_MOD(base, HDMI_CORE_FC_AVICONF1, avi.db2_active_fmt_ar, 3, 0); ++ REG_FLD_MOD(base, HDMI_CORE_FC_AVICONF2, avi.db3_itc, 7, 7); ++ REG_FLD_MOD(base, HDMI_CORE_FC_AVICONF2, avi.db3_ec, 6, 4); ++ REG_FLD_MOD(base, HDMI_CORE_FC_AVICONF2, avi.db3_q_range, 3, 2); ++ REG_FLD_MOD(base, HDMI_CORE_FC_AVICONF2, avi.db3_nup_scaling, 1, 0); ++ REG_FLD_MOD(base, HDMI_CORE_FC_AVIVID, avi.db4_videocode, 6, 0); ++ REG_FLD_MOD(base, HDMI_CORE_FC_PRCONF, avi.db5_pixel_repeat, 3, 0); ++} ++ ++static void hdmi_core_csc_config(struct hdmi_core_data *core, ++ struct csc_table csc_coeff) ++{ ++ void __iomem *base = core->base; ++ ++ REG_FLD_MOD(base, HDMI_CORE_CSC_COEF_A1_MSB, csc_coeff.a1 >> 8 , 6, 0); ++ REG_FLD_MOD(base, HDMI_CORE_CSC_COEF_A1_LSB, csc_coeff.a1, 7, 0); ++ REG_FLD_MOD(base, HDMI_CORE_CSC_COEF_A2_MSB, csc_coeff.a2 >> 8, 6, 0); ++ REG_FLD_MOD(base, HDMI_CORE_CSC_COEF_A2_LSB, csc_coeff.a2, 7, 0); ++ REG_FLD_MOD(base, HDMI_CORE_CSC_COEF_A3_MSB, csc_coeff.a3 >> 8, 6, 0); ++ REG_FLD_MOD(base, HDMI_CORE_CSC_COEF_A3_LSB, csc_coeff.a3, 7, 0); ++ REG_FLD_MOD(base, HDMI_CORE_CSC_COEF_A4_MSB, csc_coeff.a4 >> 8, 6, 0); ++ REG_FLD_MOD(base, HDMI_CORE_CSC_COEF_A4_LSB, csc_coeff.a4, 7, 0); ++ REG_FLD_MOD(base, HDMI_CORE_CSC_COEF_B1_MSB, csc_coeff.b1 >> 8, 6, 0); ++ REG_FLD_MOD(base, HDMI_CORE_CSC_COEF_B1_LSB, csc_coeff.b1, 7, 0); ++ REG_FLD_MOD(base, HDMI_CORE_CSC_COEF_B2_MSB, csc_coeff.b2 >> 8, 6, 0); ++ REG_FLD_MOD(base, HDMI_CORE_CSC_COEF_B2_LSB, csc_coeff.b2, 7, 0); ++ REG_FLD_MOD(base, HDMI_CORE_CSC_COEF_B3_MSB, csc_coeff.b3 >> 8, 6, 0); ++ REG_FLD_MOD(base, HDMI_CORE_CSC_COEF_B3_LSB, csc_coeff.b3, 7, 0); ++ REG_FLD_MOD(base, HDMI_CORE_CSC_COEF_B4_MSB, csc_coeff.b4 >> 8, 6, 0); ++ REG_FLD_MOD(base, HDMI_CORE_CSC_COEF_B4_LSB, csc_coeff.b4, 7, 0); ++ REG_FLD_MOD(base, HDMI_CORE_CSC_COEF_C1_MSB, csc_coeff.c1 >> 8, 6, 0); ++ REG_FLD_MOD(base, HDMI_CORE_CSC_COEF_C1_LSB, csc_coeff.c1, 7, 0); ++ REG_FLD_MOD(base, HDMI_CORE_CSC_COEF_C2_MSB, csc_coeff.c2 >> 8, 6, 0); ++ REG_FLD_MOD(base, HDMI_CORE_CSC_COEF_C2_LSB, csc_coeff.c2, 7, 0); ++ REG_FLD_MOD(base, HDMI_CORE_CSC_COEF_C3_MSB, csc_coeff.c3 >> 8, 6, 0); ++ REG_FLD_MOD(base, HDMI_CORE_CSC_COEF_C3_LSB, csc_coeff.c3, 7, 0); ++ REG_FLD_MOD(base, HDMI_CORE_CSC_COEF_C4_MSB, csc_coeff.c4 >> 8, 6, 0); ++ REG_FLD_MOD(base, HDMI_CORE_CSC_COEF_C4_LSB, csc_coeff.c4, 7, 0); ++ ++ REG_FLD_MOD(base, HDMI_CORE_MC_FLOWCTRL, 0x1, 0, 0); ++} ++ ++static void hdmi_core_configure_range(struct hdmi_core_data *core) ++{ ++ struct csc_table csc_coeff = { 0 }; ++ ++ /* support limited range with 24 bit color depth for now */ ++ csc_coeff = csc_table_deepcolor[0]; ++ core->avi_cfg.db3_q_range = HDMI_INFOFRAME_AVI_DB3Q_LR; ++ ++ hdmi_core_csc_config(core, csc_coeff); ++ hdmi_core_aux_infoframe_avi_config(core); ++} ++ ++static void hdmi_core_enable_video_path(struct hdmi_core_data *core) ++{ ++ void __iomem *base = core->base; ++ ++ DSSDBG("hdmi_core_enable_video_path\n"); ++ ++ REG_FLD_MOD(base, HDMI_CORE_FC_CTRLDUR, 0x0C, 7, 0); ++ REG_FLD_MOD(base, HDMI_CORE_FC_EXCTRLDUR, 0x20, 7, 0); ++ REG_FLD_MOD(base, HDMI_CORE_FC_EXCTRLSPAC, 0x01, 7, 0); ++ REG_FLD_MOD(base, HDMI_CORE_FC_CH0PREAM, 0x0B, 7, 0); ++ REG_FLD_MOD(base, HDMI_CORE_FC_CH1PREAM, 0x16, 5, 0); ++ REG_FLD_MOD(base, HDMI_CORE_FC_CH2PREAM, 0x21, 5, 0); ++ REG_FLD_MOD(base, HDMI_CORE_MC_CLKDIS, 0x00, 0, 0); ++ REG_FLD_MOD(base, HDMI_CORE_MC_CLKDIS, 0x00, 1, 1); ++} ++ ++static void hdmi_core_mask_interrupts(struct hdmi_core_data *core) ++{ ++ void __iomem *base = core->base; ++ ++ /* Master IRQ mask */ ++ REG_FLD_MOD(base, HDMI_CORE_IH_MUTE, 0x3, 1, 0); ++ ++ /* Mask all the interrupts in HDMI core */ ++ ++ REG_FLD_MOD(base, HDMI_CORE_VP_MASK, 0xff, 7, 0); ++ REG_FLD_MOD(base, HDMI_CORE_FC_MASK0, 0xe7, 7, 0); ++ REG_FLD_MOD(base, HDMI_CORE_FC_MASK1, 0xfb, 7, 0); ++ REG_FLD_MOD(base, HDMI_CORE_FC_MASK2, 0x3, 1, 0); ++ ++ REG_FLD_MOD(base, HDMI_CORE_AUD_INT, 0x3, 3, 2); ++ REG_FLD_MOD(base, HDMI_CORE_AUD_GP_MASK, 0x3, 1, 0); ++ ++ REG_FLD_MOD(base, HDMI_CORE_CEC_MASK, 0x7f, 6, 0); ++ ++ REG_FLD_MOD(base, HDMI_CORE_I2CM_CTLINT, 0x1, 6, 6); ++ REG_FLD_MOD(base, HDMI_CORE_I2CM_CTLINT, 0x1, 2, 2); ++ REG_FLD_MOD(base, HDMI_CORE_I2CM_INT, 0x1, 2, 2); ++ ++ REG_FLD_MOD(base, HDMI_CORE_PHY_MASK0, 0xf3, 7, 0); ++ ++ REG_FLD_MOD(base, HDMI_CORE_IH_PHY_STAT0, 0xff, 7, 0); ++ ++ /* Clear all the current interrupt bits */ ++ ++ REG_FLD_MOD(base, HDMI_CORE_IH_VP_STAT0, 0xff, 7, 0); ++ REG_FLD_MOD(base, HDMI_CORE_IH_FC_STAT0, 0xe7, 7, 0); ++ REG_FLD_MOD(base, HDMI_CORE_IH_FC_STAT1, 0xfb, 7, 0); ++ REG_FLD_MOD(base, HDMI_CORE_IH_FC_STAT2, 0x3, 1, 0); ++ ++ REG_FLD_MOD(base, HDMI_CORE_IH_AS_STAT0, 0x7, 2, 0); ++ ++ REG_FLD_MOD(base, HDMI_CORE_IH_CEC_STAT0, 0x7f, 6, 0); ++ ++ REG_FLD_MOD(base, HDMI_CORE_IH_I2CM_STAT0, 0x3, 1, 0); ++ ++ REG_FLD_MOD(base, HDMI_CORE_IH_PHY_STAT0, 0xff, 7, 0); ++} ++ ++static void hdmi_core_enable_interrupts(struct hdmi_core_data *core) ++{ ++ /* Unmute interrupts */ ++ REG_FLD_MOD(core->base, HDMI_CORE_IH_MUTE, 0x0, 1, 0); ++} ++ ++int hdmi5_core_handle_irqs(struct hdmi_core_data *core) ++{ ++ void __iomem *base = core->base; ++ ++ REG_FLD_MOD(base, HDMI_CORE_IH_FC_STAT0, 0xff, 7, 0); ++ REG_FLD_MOD(base, HDMI_CORE_IH_FC_STAT1, 0xff, 7, 0); ++ REG_FLD_MOD(base, HDMI_CORE_IH_FC_STAT2, 0xff, 7, 0); ++ REG_FLD_MOD(base, HDMI_CORE_IH_AS_STAT0, 0xff, 7, 0); ++ REG_FLD_MOD(base, HDMI_CORE_IH_PHY_STAT0, 0xff, 7, 0); ++ REG_FLD_MOD(base, HDMI_CORE_IH_I2CM_STAT0, 0xff, 7, 0); ++ REG_FLD_MOD(base, HDMI_CORE_IH_CEC_STAT0, 0xff, 7, 0); ++ REG_FLD_MOD(base, HDMI_CORE_IH_VP_STAT0, 0xff, 7, 0); ++ REG_FLD_MOD(base, HDMI_CORE_IH_I2CMPHY_STAT0, 0xff, 7, 0); ++ ++ return 0; ++} ++ ++void hdmi5_configure(struct hdmi_core_data *core, struct hdmi_wp_data *wp, ++ struct hdmi_config *cfg) ++{ ++ struct omap_video_timings video_timing; ++ struct hdmi_video_format video_format; ++ struct hdmi_core_vid_config v_core_cfg; ++ struct hdmi_core_infoframe_avi *avi_cfg = &core->avi_cfg; ++ ++ hdmi_core_mask_interrupts(core); ++ ++ hdmi_core_init(&v_core_cfg, avi_cfg, cfg); ++ ++ hdmi_wp_init_vid_fmt_timings(&video_format, &video_timing, cfg); ++ ++ hdmi_wp_video_config_timing(wp, &video_timing); ++ ++ /* video config */ ++ video_format.packing_mode = HDMI_PACK_24b_RGB_YUV444_YUV422; ++ ++ hdmi_wp_video_config_format(wp, &video_format); ++ ++ hdmi_wp_video_config_interface(wp, &video_timing); ++ ++ hdmi_core_configure_range(core); ++ ++ /* ++ * configure core video part, set software reset in the core ++ */ ++ v_core_cfg.packet_mode = HDMI_PACKETMODE24BITPERPIXEL; ++ ++ hdmi_core_video_config(core, &v_core_cfg); ++ ++ hdmi_core_config_video_packetizer(core); ++ hdmi_core_config_csc(core); ++ hdmi_core_config_video_sampler(core); ++ ++ /* ++ * configure packet info frame video see doc CEA861-D page 65 ++ */ ++ avi_cfg->db1_format = HDMI_INFOFRAME_AVI_DB1Y_RGB; ++ avi_cfg->db1_active_info = ++ HDMI_INFOFRAME_AVI_DB1A_ACTIVE_FORMAT_OFF; ++ avi_cfg->db1_bar_info_dv = HDMI_INFOFRAME_AVI_DB1B_NO; ++ avi_cfg->db1_scan_info = HDMI_INFOFRAME_AVI_DB1S_0; ++ avi_cfg->db2_colorimetry = HDMI_INFOFRAME_AVI_DB2C_NO; ++ avi_cfg->db2_aspect_ratio = HDMI_INFOFRAME_AVI_DB2M_NO; ++ avi_cfg->db2_active_fmt_ar = HDMI_INFOFRAME_AVI_DB2R_SAME; ++ avi_cfg->db3_itc = HDMI_INFOFRAME_AVI_DB3ITC_NO; ++ avi_cfg->db3_ec = HDMI_INFOFRAME_AVI_DB3EC_XVYUV601; ++ avi_cfg->db3_q_range = HDMI_INFOFRAME_AVI_DB3Q_DEFAULT; ++ avi_cfg->db3_nup_scaling = HDMI_INFOFRAME_AVI_DB3SC_NO; ++ avi_cfg->db4_videocode = cfg->cm.code; ++ avi_cfg->db5_pixel_repeat = HDMI_INFOFRAME_AVI_DB5PR_NO; ++ avi_cfg->db6_7_line_eoftop = 0; ++ avi_cfg->db8_9_line_sofbottom = 0; ++ avi_cfg->db10_11_pixel_eofleft = 0; ++ avi_cfg->db12_13_pixel_sofright = 0; ++ ++ hdmi_core_aux_infoframe_avi_config(core); ++ ++ hdmi_core_enable_video_path(core); ++ ++ hdmi_core_enable_interrupts(core); ++} ++ ++ ++#if defined(CONFIG_OMAP5_DSS_HDMI_AUDIO) ++ ++static void hdmi5_core_audio_config(struct hdmi_core_data *core, ++ struct hdmi_core_audio_config *cfg) ++{ ++ void __iomem *base = core->base; ++ u8 val; ++ ++ /* Mute audio before configuring */ ++ REG_FLD_MOD(base, HDMI_CORE_FC_AUDSCONF, 0xf, 7, 4); ++ ++ /* Set the N parameter */ ++ REG_FLD_MOD(base, HDMI_CORE_AUD_N1, cfg->n, 7, 0); ++ REG_FLD_MOD(base, HDMI_CORE_AUD_N2, cfg->n >> 8, 7, 0); ++ REG_FLD_MOD(base, HDMI_CORE_AUD_N3, cfg->n >> 16, 3, 0); ++ ++ /* ++ * CTS manual mode. Automatic mode is not supported when using audio ++ * parallel interface. ++ */ ++ REG_FLD_MOD(base, HDMI_CORE_AUD_CTS3, 1, 4, 4); ++ REG_FLD_MOD(base, HDMI_CORE_AUD_CTS1, cfg->cts, 7, 0); ++ REG_FLD_MOD(base, HDMI_CORE_AUD_CTS2, cfg->cts >> 8, 7, 0); ++ REG_FLD_MOD(base, HDMI_CORE_AUD_CTS3, cfg->cts >> 16, 3, 0); ++ ++ /* Layout of Audio Sample Packets: 2-channel or multichannels */ ++ if (cfg->layout == HDMI_AUDIO_LAYOUT_2CH) ++ REG_FLD_MOD(base, HDMI_CORE_FC_AUDSCONF, 0, 0, 0); ++ else ++ REG_FLD_MOD(base, HDMI_CORE_FC_AUDSCONF, 1, 0, 0); ++ ++ /* Configure IEC-609580 Validity bits */ ++ /* Channel 0 is valid */ ++ REG_FLD_MOD(base, HDMI_CORE_FC_AUDSV, 0, 0, 0); ++ REG_FLD_MOD(base, HDMI_CORE_FC_AUDSV, 0, 4, 4); ++ ++ if (cfg->layout == HDMI_AUDIO_LAYOUT_2CH) ++ val = 1; ++ else ++ val = 0; ++ ++ /* Channels 1, 2 setting */ ++ REG_FLD_MOD(base, HDMI_CORE_FC_AUDSV, val, 1, 1); ++ REG_FLD_MOD(base, HDMI_CORE_FC_AUDSV, val, 5, 5); ++ REG_FLD_MOD(base, HDMI_CORE_FC_AUDSV, val, 2, 2); ++ REG_FLD_MOD(base, HDMI_CORE_FC_AUDSV, val, 6, 6); ++ /* Channel 3 setting */ ++ if (cfg->layout == HDMI_AUDIO_LAYOUT_6CH) ++ val = 1; ++ REG_FLD_MOD(base, HDMI_CORE_FC_AUDSV, val, 3, 3); ++ REG_FLD_MOD(base, HDMI_CORE_FC_AUDSV, val, 7, 7); ++ ++ /* Configure IEC-60958 User bits */ ++ /* TODO: should be set by user. */ ++ REG_FLD_MOD(base, HDMI_CORE_FC_AUDSU, 0, 7, 0); ++ ++ /* Configure IEC-60958 Channel Status word */ ++ /* CGMSA */ ++ val = cfg->iec60958_cfg->status[5] & IEC958_AES5_CON_CGMSA; ++ REG_FLD_MOD(base, HDMI_CORE_FC_AUDSCHNLS(0), val, 5, 4); ++ ++ /* Copyright */ ++ val = (cfg->iec60958_cfg->status[0] & ++ IEC958_AES0_CON_NOT_COPYRIGHT) >> 2; ++ REG_FLD_MOD(base, HDMI_CORE_FC_AUDSCHNLS(0), val, 0, 0); ++ ++ /* Category */ ++ hdmi_write_reg(base, HDMI_CORE_FC_AUDSCHNLS(1), ++ cfg->iec60958_cfg->status[1]); ++ ++ /* PCM audio mode */ ++ val = (cfg->iec60958_cfg->status[0] & IEC958_AES0_CON_MODE) >> 6; ++ REG_FLD_MOD(base, HDMI_CORE_FC_AUDSCHNLS(2), val, 6, 4); ++ ++ /* Source number */ ++ val = cfg->iec60958_cfg->status[2] & IEC958_AES2_CON_SOURCE; ++ REG_FLD_MOD(base, HDMI_CORE_FC_AUDSCHNLS(2), val, 3, 4); ++ ++ /* Channel number right 0 */ ++ REG_FLD_MOD(base, HDMI_CORE_FC_AUDSCHNLS(3), 2, 3, 0); ++ /* Channel number right 1*/ ++ REG_FLD_MOD(base, HDMI_CORE_FC_AUDSCHNLS(3), 4, 7, 4); ++ /* Channel number right 2 */ ++ REG_FLD_MOD(base, HDMI_CORE_FC_AUDSCHNLS(4), 6, 3, 0); ++ /* Channel number right 3*/ ++ REG_FLD_MOD(base, HDMI_CORE_FC_AUDSCHNLS(4), 8, 7, 4); ++ /* Channel number left 0 */ ++ REG_FLD_MOD(base, HDMI_CORE_FC_AUDSCHNLS(5), 1, 3, 0); ++ /* Channel number left 1*/ ++ REG_FLD_MOD(base, HDMI_CORE_FC_AUDSCHNLS(5), 3, 7, 4); ++ /* Channel number left 2 */ ++ REG_FLD_MOD(base, HDMI_CORE_FC_AUDSCHNLS(6), 5, 3, 0); ++ /* Channel number left 3*/ ++ REG_FLD_MOD(base, HDMI_CORE_FC_AUDSCHNLS(6), 7, 7, 4); ++ ++ /* Clock accuracy and sample rate */ ++ hdmi_write_reg(base, HDMI_CORE_FC_AUDSCHNLS(7), ++ cfg->iec60958_cfg->status[3]); ++ ++ /* Original sample rate and word length */ ++ hdmi_write_reg(base, HDMI_CORE_FC_AUDSCHNLS(8), ++ cfg->iec60958_cfg->status[4]); ++ ++ /* Enable FIFO empty and full interrupts */ ++ REG_FLD_MOD(base, HDMI_CORE_AUD_INT, 3, 3, 2); ++ ++ /* Configure GPA */ ++ /* select HBR/SPDIF interfaces */ ++ if (cfg->layout == HDMI_AUDIO_LAYOUT_2CH) { ++ /* select HBR/SPDIF interfaces */ ++ REG_FLD_MOD(base, HDMI_CORE_AUD_CONF0, 0, 5, 5); ++ /* enable two channels in GPA */ ++ REG_FLD_MOD(base, HDMI_CORE_AUD_GP_CONF1, 3, 7, 0); ++ } else if (cfg->layout == HDMI_AUDIO_LAYOUT_6CH) { ++ /* select HBR/SPDIF interfaces */ ++ REG_FLD_MOD(base, HDMI_CORE_AUD_CONF0, 0, 5, 5); ++ /* enable six channels in GPA */ ++ REG_FLD_MOD(base, HDMI_CORE_AUD_GP_CONF1, 0x3F, 7, 0); ++ } else { ++ /* select HBR/SPDIF interfaces */ ++ REG_FLD_MOD(base, HDMI_CORE_AUD_CONF0, 0, 5, 5); ++ /* enable eight channels in GPA */ ++ REG_FLD_MOD(base, HDMI_CORE_AUD_GP_CONF1, 0xFF, 7, 0); ++ } ++ ++ /* disable HBR */ ++ REG_FLD_MOD(base, HDMI_CORE_AUD_GP_CONF2, 0, 0, 0); ++ /* enable PCUV */ ++ REG_FLD_MOD(base, HDMI_CORE_AUD_GP_CONF2, 1, 1, 1); ++ /* enable GPA FIFO full and empty mask */ ++ REG_FLD_MOD(base, HDMI_CORE_AUD_GP_MASK, 3, 1, 0); ++ /* set polarity of GPA FIFO empty interrupts */ ++ REG_FLD_MOD(base, HDMI_CORE_AUD_GP_POL, 1, 0, 0); ++ ++ /* unmute audio */ ++ REG_FLD_MOD(core_sys_base, HDMI_CORE_FC_AUDSCONF, 0, 7, 4); ++} ++ ++static void hdmi5_core_audio_infoframe_cfg(struct hdmi_core_data *core, ++ struct snd_cea_861_aud_if *info_aud) ++{ ++ void __iomem *base = core->base; ++ ++ /* channel count and coding type fields in AUDICONF0 are swapped */ ++ hdmi_write_reg(base, HDMI_CORE_FC_AUDICONF0, ++ (info_aud->db1_ct_cc & CEA861_AUDIO_INFOFRAME_DB1CC) << 4 | ++ (info_aud->db1_ct_cc & CEA861_AUDIO_INFOFRAME_DB1CT) >> 4); ++ ++ hdmi_write_reg(base, HDMI_CORE_FC_AUDICONF1, info_aud->db2_sf_ss); ++ hdmi_write_reg(base, HDMI_CORE_FC_AUDICONF2, info_aud->db4_ca); ++ hdmi_write_reg(base, HDMI_CORE_FC_AUDICONF3, info_aud->db5_dminh_lsv); ++} ++ ++int hdmi5_audio_config(struct hdmi_core_data *core, struct hdmi_wp_data *wp, ++ struct omap_dss_audio *audio, u32 pclk) ++{ ++ struct hdmi_audio_format audio_format; ++ struct hdmi_audio_dma audio_dma; ++ struct hdmi_core_audio_config core_cfg; ++ int err, n, cts, channel_count; ++ unsigned int fs_nr; ++ bool word_length_16b = false; ++ ++ if (!audio || !audio->iec || !audio->cea || !core) ++ return -EINVAL; ++ ++ core_cfg.iec60958_cfg = audio->iec; ++ ++ if (!(audio->iec->status[4] & IEC958_AES4_CON_MAX_WORDLEN_24) && ++ (audio->iec->status[4] & IEC958_AES4_CON_WORDLEN_20_16)) ++ word_length_16b = true; ++ ++ /* only 16-bit word length supported atm */ ++ if (!word_length_16b) ++ return -EINVAL; ++ ++ switch (audio->iec->status[3] & IEC958_AES3_CON_FS) { ++ case IEC958_AES3_CON_FS_32000: ++ fs_nr = 32000; ++ break; ++ case IEC958_AES3_CON_FS_44100: ++ fs_nr = 44100; ++ break; ++ case IEC958_AES3_CON_FS_48000: ++ fs_nr = 48000; ++ break; ++ case IEC958_AES3_CON_FS_88200: ++ fs_nr = 88200; ++ break; ++ case IEC958_AES3_CON_FS_96000: ++ fs_nr = 96000; ++ break; ++ case IEC958_AES3_CON_FS_176400: ++ fs_nr = 176400; ++ break; ++ case IEC958_AES3_CON_FS_192000: ++ fs_nr = 192000; ++ break; ++ default: ++ return -EINVAL; ++ } ++ ++ err = hdmi_compute_acr(pclk, fs_nr, &n, &cts); ++ core_cfg.n = n; ++ core_cfg.cts = cts; ++ ++ /* Audio channels settings */ ++ channel_count = (audio->cea->db1_ct_cc & CEA861_AUDIO_INFOFRAME_DB1CC) ++ + 1; ++ ++ if (channel_count == 2) ++ core_cfg.layout = HDMI_AUDIO_LAYOUT_2CH; ++ else if (channel_count == 6) ++ core_cfg.layout = HDMI_AUDIO_LAYOUT_6CH; ++ else ++ core_cfg.layout = HDMI_AUDIO_LAYOUT_8CH; ++ ++ /* DMA settings */ ++ if (word_length_16b) ++ audio_dma.transfer_size = 0x10; ++ else ++ audio_dma.transfer_size = 0x20; ++ audio_dma.block_size = 0xC0; ++ audio_dma.mode = HDMI_AUDIO_TRANSF_DMA; ++ audio_dma.fifo_threshold = 0x20; /* in number of samples */ ++ ++ /* audio FIFO format settings for 16-bit samples*/ ++ audio_format.samples_per_word = HDMI_AUDIO_ONEWORD_TWOSAMPLES; ++ audio_format.sample_size = HDMI_AUDIO_SAMPLE_16BITS; ++ audio_format.justification = HDMI_AUDIO_JUSTIFY_LEFT; ++ ++ /* only LPCM atm */ ++ audio_format.type = HDMI_AUDIO_TYPE_LPCM; ++ ++ /* disable start/stop signals of IEC 60958 blocks */ ++ audio_format.en_sig_blk_strt_end = HDMI_AUDIO_BLOCK_SIG_STARTEND_ON; ++ ++ /* configure DMA and audio FIFO format*/ ++ hdmi_wp_audio_config_dma(wp, &audio_dma); ++ hdmi_wp_audio_config_format(wp, &audio_format); ++ ++ /* configure the core */ ++ hdmi5_core_audio_config(core, &core_cfg); ++ ++ /* configure CEA 861 audio infoframe */ ++ hdmi5_core_audio_infoframe_cfg(core, audio->cea); ++ ++ return 0; ++} ++#endif ++ ++int hdmi5_core_init(struct platform_device *pdev, struct hdmi_core_data *core) ++{ ++ struct resource *res; ++ ++ res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "hdmi_core"); ++ if (!res) { ++ DSSERR("can't get CORE IORESOURCE_MEM HDMI\n"); ++ return -EINVAL; ++ } ++ ++ core->base = devm_request_and_ioremap(&pdev->dev, res); ++ if (!core->base) { ++ DSSERR("can't ioremap HDMI core\n"); ++ return -ENOMEM; ++ } ++ ++ return 0; ++} +--- /dev/null ++++ b/drivers/video/omap2/dss/hdmi5_core.h +@@ -0,0 +1,306 @@ ++/* ++ * HDMI driver definition for TI OMAP5 processors. ++ * ++ * Copyright (C) 2011-2012 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 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, see <http://www.gnu.org/licenses/>. ++ */ ++ ++#ifndef _HDMI5_CORE_H_ ++#define _HDMI5_CORE_H_ ++ ++#include "hdmi.h" ++ ++/* HDMI IP Core System */ ++ ++/* HDMI Identification */ ++#define HDMI_CORE_DESIGN_ID 0x00000 ++#define HDMI_CORE_REVISION_ID 0x00004 ++#define HDMI_CORE_PRODUCT_ID0 0x00008 ++#define HDMI_CORE_PRODUCT_ID1 0x0000C ++#define HDMI_CORE_CONFIG0_ID 0x00010 ++#define HDMI_CORE_CONFIG1_ID 0x00014 ++#define HDMI_CORE_CONFIG2_ID 0x00018 ++#define HDMI_CORE_CONFIG3_ID 0x0001C ++ ++/* HDMI Interrupt */ ++#define HDMI_CORE_IH_FC_STAT0 0x00400 ++#define HDMI_CORE_IH_FC_STAT1 0x00404 ++#define HDMI_CORE_IH_FC_STAT2 0x00408 ++#define HDMI_CORE_IH_AS_STAT0 0x0040C ++#define HDMI_CORE_IH_PHY_STAT0 0x00410 ++#define HDMI_CORE_IH_I2CM_STAT0 0x00414 ++#define HDMI_CORE_IH_CEC_STAT0 0x00418 ++#define HDMI_CORE_IH_VP_STAT0 0x0041C ++#define HDMI_CORE_IH_I2CMPHY_STAT0 0x00420 ++#define HDMI_CORE_IH_MUTE 0x007FC ++ ++/* HDMI Video Sampler */ ++#define HDMI_CORE_TX_INVID0 0x00800 ++#define HDMI_CORE_TX_INSTUFFING 0x00804 ++#define HDMI_CORE_TX_RGYDATA0 0x00808 ++#define HDMI_CORE_TX_RGYDATA1 0x0080C ++#define HDMI_CORE_TX_RCRDATA0 0x00810 ++#define HDMI_CORE_TX_RCRDATA1 0x00814 ++#define HDMI_CORE_TX_BCBDATA0 0x00818 ++#define HDMI_CORE_TX_BCBDATA1 0x0081C ++ ++/* HDMI Video Packetizer */ ++#define HDMI_CORE_VP_STATUS 0x02000 ++#define HDMI_CORE_VP_PR_CD 0x02004 ++#define HDMI_CORE_VP_STUFF 0x02008 ++#define HDMI_CORE_VP_REMAP 0x0200C ++#define HDMI_CORE_VP_CONF 0x02010 ++#define HDMI_CORE_VP_STAT 0x02014 ++#define HDMI_CORE_VP_INT 0x02018 ++#define HDMI_CORE_VP_MASK 0x0201C ++#define HDMI_CORE_VP_POL 0x02020 ++ ++/* Frame Composer */ ++#define HDMI_CORE_FC_INVIDCONF 0x04000 ++#define HDMI_CORE_FC_INHACTIV0 0x04004 ++#define HDMI_CORE_FC_INHACTIV1 0x04008 ++#define HDMI_CORE_FC_INHBLANK0 0x0400C ++#define HDMI_CORE_FC_INHBLANK1 0x04010 ++#define HDMI_CORE_FC_INVACTIV0 0x04014 ++#define HDMI_CORE_FC_INVACTIV1 0x04018 ++#define HDMI_CORE_FC_INVBLANK 0x0401C ++#define HDMI_CORE_FC_HSYNCINDELAY0 0x04020 ++#define HDMI_CORE_FC_HSYNCINDELAY1 0x04024 ++#define HDMI_CORE_FC_HSYNCINWIDTH0 0x04028 ++#define HDMI_CORE_FC_HSYNCINWIDTH1 0x0402C ++#define HDMI_CORE_FC_VSYNCINDELAY 0x04030 ++#define HDMI_CORE_FC_VSYNCINWIDTH 0x04034 ++#define HDMI_CORE_FC_INFREQ0 0x04038 ++#define HDMI_CORE_FC_INFREQ1 0x0403C ++#define HDMI_CORE_FC_INFREQ2 0x04040 ++#define HDMI_CORE_FC_CTRLDUR 0x04044 ++#define HDMI_CORE_FC_EXCTRLDUR 0x04048 ++#define HDMI_CORE_FC_EXCTRLSPAC 0x0404C ++#define HDMI_CORE_FC_CH0PREAM 0x04050 ++#define HDMI_CORE_FC_CH1PREAM 0x04054 ++#define HDMI_CORE_FC_CH2PREAM 0x04058 ++#define HDMI_CORE_FC_AVICONF3 0x0405C ++#define HDMI_CORE_FC_GCP 0x04060 ++#define HDMI_CORE_FC_AVICONF0 0x04064 ++#define HDMI_CORE_FC_AVICONF1 0x04068 ++#define HDMI_CORE_FC_AVICONF2 0x0406C ++#define HDMI_CORE_FC_AVIVID 0x04070 ++#define HDMI_CORE_FC_AVIETB0 0x04074 ++#define HDMI_CORE_FC_AVIETB1 0x04078 ++#define HDMI_CORE_FC_AVISBB0 0x0407C ++#define HDMI_CORE_FC_AVISBB1 0x04080 ++#define HDMI_CORE_FC_AVIELB0 0x04084 ++#define HDMI_CORE_FC_AVIELB1 0x04088 ++#define HDMI_CORE_FC_AVISRB0 0x0408C ++#define HDMI_CORE_FC_AVISRB1 0x04090 ++#define HDMI_CORE_FC_AUDICONF0 0x04094 ++#define HDMI_CORE_FC_AUDICONF1 0x04098 ++#define HDMI_CORE_FC_AUDICONF2 0x0409C ++#define HDMI_CORE_FC_AUDICONF3 0x040A0 ++#define HDMI_CORE_FC_VSDIEEEID0 0x040A4 ++#define HDMI_CORE_FC_VSDSIZE 0x040A8 ++#define HDMI_CORE_FC_VSDIEEEID1 0x040C0 ++#define HDMI_CORE_FC_VSDIEEEID2 0x040C4 ++#define HDMI_CORE_FC_VSDPAYLOAD(n) (n * 4 + 0x040C8) ++#define HDMI_CORE_FC_SPDVENDORNAME(n) (n * 4 + 0x04128) ++#define HDMI_CORE_FC_SPDPRODUCTNAME(n) (n * 4 + 0x04148) ++#define HDMI_CORE_FC_SPDDEVICEINF 0x04188 ++#define HDMI_CORE_FC_AUDSCONF 0x0418C ++#define HDMI_CORE_FC_AUDSSTAT 0x04190 ++#define HDMI_CORE_FC_AUDSV 0x04194 ++#define HDMI_CORE_FC_AUDSU 0x04198 ++#define HDMI_CORE_FC_AUDSCHNLS(n) (n * 4 + 0x0419C) ++#define HDMI_CORE_FC_CTRLQHIGH 0x041CC ++#define HDMI_CORE_FC_CTRLQLOW 0x041D0 ++#define HDMI_CORE_FC_ACP0 0x041D4 ++#define HDMI_CORE_FC_ACP(n) ((16-n) * 4 + 0x04208) ++#define HDMI_CORE_FC_ISCR1_0 0x04248 ++#define HDMI_CORE_FC_ISCR1(n) ((16-n) * 4 + 0x0424C) ++#define HDMI_CORE_FC_ISCR2(n) ((15-n) * 4 + 0x0428C) ++#define HDMI_CORE_FC_DATAUTO0 0x042CC ++#define HDMI_CORE_FC_DATAUTO1 0x042D0 ++#define HDMI_CORE_FC_DATAUTO2 0x042D4 ++#define HDMI_CORE_FC_DATMAN 0x042D8 ++#define HDMI_CORE_FC_DATAUTO3 0x042DC ++#define HDMI_CORE_FC_RDRB(n) (n * 4 + 0x042E0) ++#define HDMI_CORE_FC_STAT0 0x04340 ++#define HDMI_CORE_FC_INT0 0x04344 ++#define HDMI_CORE_FC_MASK0 0x04348 ++#define HDMI_CORE_FC_POL0 0x0434C ++#define HDMI_CORE_FC_STAT1 0x04350 ++#define HDMI_CORE_FC_INT1 0x04354 ++#define HDMI_CORE_FC_MASK1 0x04358 ++#define HDMI_CORE_FC_POL1 0x0435C ++#define HDMI_CORE_FC_STAT2 0x04360 ++#define HDMI_CORE_FC_INT2 0x04364 ++#define HDMI_CORE_FC_MASK2 0x04368 ++#define HDMI_CORE_FC_POL2 0x0436C ++#define HDMI_CORE_FC_PRCONF 0x04380 ++#define HDMI_CORE_FC_GMD_STAT 0x04400 ++#define HDMI_CORE_FC_GMD_EN 0x04404 ++#define HDMI_CORE_FC_GMD_UP 0x04408 ++#define HDMI_CORE_FC_GMD_CONF 0x0440C ++#define HDMI_CORE_FC_GMD_HB 0x04410 ++#define HDMI_CORE_FC_GMD_PB(n) (n * 4 + 0x04414) ++#define HDMI_CORE_FC_DBGFORCE 0x04800 ++#define HDMI_CORE_FC_DBGAUD0CH0 0x04804 ++#define HDMI_CORE_FC_DBGAUD1CH0 0x04808 ++#define HDMI_CORE_FC_DBGAUD2CH0 0x0480C ++#define HDMI_CORE_FC_DBGAUD0CH1 0x04810 ++#define HDMI_CORE_FC_DBGAUD1CH1 0x04814 ++#define HDMI_CORE_FC_DBGAUD2CH1 0x04818 ++#define HDMI_CORE_FC_DBGAUD0CH2 0x0481C ++#define HDMI_CORE_FC_DBGAUD1CH2 0x04820 ++#define HDMI_CORE_FC_DBGAUD2CH2 0x04824 ++#define HDMI_CORE_FC_DBGAUD0CH3 0x04828 ++#define HDMI_CORE_FC_DBGAUD1CH3 0x0482C ++#define HDMI_CORE_FC_DBGAUD2CH3 0x04830 ++#define HDMI_CORE_FC_DBGAUD0CH4 0x04834 ++#define HDMI_CORE_FC_DBGAUD1CH4 0x04838 ++#define HDMI_CORE_FC_DBGAUD2CH4 0x0483C ++#define HDMI_CORE_FC_DBGAUD0CH5 0x04840 ++#define HDMI_CORE_FC_DBGAUD1CH5 0x04844 ++#define HDMI_CORE_FC_DBGAUD2CH5 0x04848 ++#define HDMI_CORE_FC_DBGAUD0CH6 0x0484C ++#define HDMI_CORE_FC_DBGAUD1CH6 0x04850 ++#define HDMI_CORE_FC_DBGAUD2CH6 0x04854 ++#define HDMI_CORE_FC_DBGAUD0CH7 0x04858 ++#define HDMI_CORE_FC_DBGAUD1CH7 0x0485C ++#define HDMI_CORE_FC_DBGAUD2CH7 0x04860 ++#define HDMI_CORE_FC_DBGTMDS0 0x04864 ++#define HDMI_CORE_FC_DBGTMDS1 0x04868 ++#define HDMI_CORE_FC_DBGTMDS2 0x0486C ++#define HDMI_CORE_PHY_MASK0 0x0C018 ++#define HDMI_CORE_PHY_I2CM_INT_ADDR 0x0C09C ++#define HDMI_CORE_PHY_I2CM_CTLINT_ADDR 0x0C0A0 ++ ++/* HDMI Audio */ ++#define HDMI_CORE_AUD_CONF0 0x0C400 ++#define HDMI_CORE_AUD_CONF1 0x0C404 ++#define HDMI_CORE_AUD_INT 0x0C408 ++#define HDMI_CORE_AUD_N1 0x0C800 ++#define HDMI_CORE_AUD_N2 0x0C804 ++#define HDMI_CORE_AUD_N3 0x0C808 ++#define HDMI_CORE_AUD_CTS1 0x0C80C ++#define HDMI_CORE_AUD_CTS2 0x0C810 ++#define HDMI_CORE_AUD_CTS3 0x0C814 ++#define HDMI_CORE_AUD_INCLKFS 0x0C818 ++#define HDMI_CORE_AUD_CC08 0x0CC08 ++#define HDMI_CORE_AUD_GP_CONF0 0x0D400 ++#define HDMI_CORE_AUD_GP_CONF1 0x0D404 ++#define HDMI_CORE_AUD_GP_CONF2 0x0D408 ++#define HDMI_CORE_AUD_D010 0x0D010 ++#define HDMI_CORE_AUD_GP_STAT 0x0D40C ++#define HDMI_CORE_AUD_GP_INT 0x0D410 ++#define HDMI_CORE_AUD_GP_POL 0x0D414 ++#define HDMI_CORE_AUD_GP_MASK 0x0D418 ++ ++/* HDMI Main Controller */ ++#define HDMI_CORE_MC_CLKDIS 0x10004 ++#define HDMI_CORE_MC_SWRSTZREQ 0x10008 ++#define HDMI_CORE_MC_FLOWCTRL 0x10010 ++#define HDMI_CORE_MC_PHYRSTZ 0x10014 ++#define HDMI_CORE_MC_LOCKONCLOCK 0x10018 ++ ++/* HDMI COLOR SPACE CONVERTER */ ++#define HDMI_CORE_CSC_CFG 0x10400 ++#define HDMI_CORE_CSC_SCALE 0x10404 ++#define HDMI_CORE_CSC_COEF_A1_MSB 0x10408 ++#define HDMI_CORE_CSC_COEF_A1_LSB 0x1040C ++#define HDMI_CORE_CSC_COEF_A2_MSB 0x10410 ++#define HDMI_CORE_CSC_COEF_A2_LSB 0x10414 ++#define HDMI_CORE_CSC_COEF_A3_MSB 0x10418 ++#define HDMI_CORE_CSC_COEF_A3_LSB 0x1041C ++#define HDMI_CORE_CSC_COEF_A4_MSB 0x10420 ++#define HDMI_CORE_CSC_COEF_A4_LSB 0x10424 ++#define HDMI_CORE_CSC_COEF_B1_MSB 0x10428 ++#define HDMI_CORE_CSC_COEF_B1_LSB 0x1042C ++#define HDMI_CORE_CSC_COEF_B2_MSB 0x10430 ++#define HDMI_CORE_CSC_COEF_B2_LSB 0x10434 ++#define HDMI_CORE_CSC_COEF_B3_MSB 0x10438 ++#define HDMI_CORE_CSC_COEF_B3_LSB 0x1043C ++#define HDMI_CORE_CSC_COEF_B4_MSB 0x10440 ++#define HDMI_CORE_CSC_COEF_B4_LSB 0x10444 ++#define HDMI_CORE_CSC_COEF_C1_MSB 0x10448 ++#define HDMI_CORE_CSC_COEF_C1_LSB 0x1044C ++#define HDMI_CORE_CSC_COEF_C2_MSB 0x10450 ++#define HDMI_CORE_CSC_COEF_C2_LSB 0x10454 ++#define HDMI_CORE_CSC_COEF_C3_MSB 0x10458 ++#define HDMI_CORE_CSC_COEF_C3_LSB 0x1045C ++#define HDMI_CORE_CSC_COEF_C4_MSB 0x10460 ++#define HDMI_CORE_CSC_COEF_C4_LSB 0x10464 ++ ++/* HDMI HDCP */ ++#define HDMI_CORE_HDCP_MASK 0x14020 ++ ++/* HDMI CEC */ ++#define HDMI_CORE_CEC_MASK 0x17408 ++ ++/* HDMI I2C Master */ ++#define HDMI_CORE_I2CM_SLAVE 0x157C8 ++#define HDMI_CORE_I2CM_ADDRESS 0x157CC ++#define HDMI_CORE_I2CM_DATAO 0x157D0 ++#define HDMI_CORE_I2CM_DATAI 0X157D4 ++#define HDMI_CORE_I2CM_OPERATION 0x157D8 ++#define HDMI_CORE_I2CM_INT 0x157DC ++#define HDMI_CORE_I2CM_CTLINT 0x157E0 ++#define HDMI_CORE_I2CM_DIV 0x157E4 ++#define HDMI_CORE_I2CM_SEGADDR 0x157E8 ++#define HDMI_CORE_I2CM_SOFTRSTZ 0x157EC ++#define HDMI_CORE_I2CM_SEGPTR 0x157F0 ++#define HDMI_CORE_I2CM_SS_SCL_HCNT_1_ADDR 0x157F4 ++#define HDMI_CORE_I2CM_SS_SCL_HCNT_0_ADDR 0x157F8 ++#define HDMI_CORE_I2CM_SS_SCL_LCNT_1_ADDR 0x157FC ++#define HDMI_CORE_I2CM_SS_SCL_LCNT_0_ADDR 0x15800 ++#define HDMI_CORE_I2CM_FS_SCL_HCNT_1_ADDR 0x15804 ++#define HDMI_CORE_I2CM_FS_SCL_HCNT_0_ADDR 0x15808 ++#define HDMI_CORE_I2CM_FS_SCL_LCNT_1_ADDR 0x1580C ++#define HDMI_CORE_I2CM_FS_SCL_LCNT_0_ADDR 0x15810 ++#define HDMI_CORE_I2CM_SDA_HOLD_ADDR 0x15814 ++ ++enum hdmi_core_packet_mode { ++ HDMI_PACKETMODERESERVEDVALUE = 0, ++ HDMI_PACKETMODE24BITPERPIXEL = 4, ++ HDMI_PACKETMODE30BITPERPIXEL = 5, ++ HDMI_PACKETMODE36BITPERPIXEL = 6, ++ HDMI_PACKETMODE48BITPERPIXEL = 7, ++}; ++ ++struct hdmi_core_vid_config { ++ struct hdmi_config v_fc_config; ++ enum hdmi_core_packet_mode packet_mode; ++ int data_enable_pol; ++ int vblank_osc; ++ int hblank; ++ int vblank; ++}; ++ ++struct csc_table { ++ u16 a1, a2, a3, a4; ++ u16 b1, b2, b3, b4; ++ u16 c1, c2, c3, c4; ++}; ++ ++int hdmi5_read_edid(struct hdmi_core_data *core, u8 *edid, int len); ++void hdmi5_core_dump(struct hdmi_core_data *core, struct seq_file *s); ++int hdmi5_core_handle_irqs(struct hdmi_core_data *core); ++void hdmi5_configure(struct hdmi_core_data *core, struct hdmi_wp_data *wp, ++ struct hdmi_config *cfg); ++int hdmi5_core_init(struct platform_device *pdev, struct hdmi_core_data *core); ++ ++#if defined(CONFIG_OMAP5_DSS_HDMI_AUDIO) ++int hdmi5_audio_config(struct hdmi_core_data *core, struct hdmi_wp_data *wp, ++ struct omap_dss_audio *audio, u32 pclk); ++#endif ++#endif +--- a/drivers/video/omap2/dss/hdmi.c ++++ /dev/null +@@ -1,1184 +0,0 @@ +-/* +- * hdmi.c +- * +- * HDMI interface DSS driver setting for TI's OMAP4 family of processor. +- * Copyright (C) 2010-2011 Texas Instruments Incorporated - http://www.ti.com/ +- * Authors: Yong Zhi +- * Mythri pk <mythripk@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, see <http://www.gnu.org/licenses/>. +- */ +- +-#define DSS_SUBSYS_NAME "HDMI" +- +-#include <linux/kernel.h> +-#include <linux/module.h> +-#include <linux/err.h> +-#include <linux/io.h> +-#include <linux/interrupt.h> +-#include <linux/mutex.h> +-#include <linux/delay.h> +-#include <linux/string.h> +-#include <linux/platform_device.h> +-#include <linux/pm_runtime.h> +-#include <linux/clk.h> +-#include <linux/gpio.h> +-#include <linux/regulator/consumer.h> +-#include <video/omapdss.h> +- +-#include "ti_hdmi.h" +-#include "dss.h" +-#include "dss_features.h" +- +-#define HDMI_WP 0x0 +-#define HDMI_CORE_SYS 0x400 +-#define HDMI_CORE_AV 0x900 +-#define HDMI_PLLCTRL 0x200 +-#define HDMI_PHY 0x300 +- +-/* HDMI EDID Length move this */ +-#define HDMI_EDID_MAX_LENGTH 256 +-#define EDID_TIMING_DESCRIPTOR_SIZE 0x12 +-#define EDID_DESCRIPTOR_BLOCK0_ADDRESS 0x36 +-#define EDID_DESCRIPTOR_BLOCK1_ADDRESS 0x80 +-#define EDID_SIZE_BLOCK0_TIMING_DESCRIPTOR 4 +-#define EDID_SIZE_BLOCK1_TIMING_DESCRIPTOR 4 +- +-#define HDMI_DEFAULT_REGN 16 +-#define HDMI_DEFAULT_REGM2 1 +- +-static struct { +- struct mutex lock; +- struct platform_device *pdev; +- +- struct hdmi_ip_data ip_data; +- +- struct clk *sys_clk; +- struct regulator *vdda_hdmi_dac_reg; +- +- bool core_enabled; +- +- struct omap_dss_device output; +-} hdmi; +- +-/* +- * Logic for the below structure : +- * user enters the CEA or VESA timings by specifying the HDMI/DVI code. +- * There is a correspondence between CEA/VESA timing and code, please +- * refer to section 6.3 in HDMI 1.3 specification for timing code. +- * +- * In the below structure, cea_vesa_timings corresponds to all OMAP4 +- * supported CEA and VESA timing values.code_cea corresponds to the CEA +- * code, It is used to get the timing from cea_vesa_timing array.Similarly +- * with code_vesa. Code_index is used for back mapping, that is once EDID +- * is read from the TV, EDID is parsed to find the timing values and then +- * map it to corresponding CEA or VESA index. +- */ +- +-static const struct hdmi_config cea_timings[] = { +- { +- { 640, 480, 25200, 96, 16, 48, 2, 10, 33, +- OMAPDSS_SIG_ACTIVE_LOW, OMAPDSS_SIG_ACTIVE_LOW, +- false, }, +- { 1, HDMI_HDMI }, +- }, +- { +- { 720, 480, 27027, 62, 16, 60, 6, 9, 30, +- OMAPDSS_SIG_ACTIVE_LOW, OMAPDSS_SIG_ACTIVE_LOW, +- false, }, +- { 2, HDMI_HDMI }, +- }, +- { +- { 1280, 720, 74250, 40, 110, 220, 5, 5, 20, +- OMAPDSS_SIG_ACTIVE_HIGH, OMAPDSS_SIG_ACTIVE_HIGH, +- false, }, +- { 4, HDMI_HDMI }, +- }, +- { +- { 1920, 540, 74250, 44, 88, 148, 5, 2, 15, +- OMAPDSS_SIG_ACTIVE_HIGH, OMAPDSS_SIG_ACTIVE_HIGH, +- true, }, +- { 5, HDMI_HDMI }, +- }, +- { +- { 1440, 240, 27027, 124, 38, 114, 3, 4, 15, +- OMAPDSS_SIG_ACTIVE_LOW, OMAPDSS_SIG_ACTIVE_LOW, +- true, }, +- { 6, HDMI_HDMI }, +- }, +- { +- { 1920, 1080, 148500, 44, 88, 148, 5, 4, 36, +- OMAPDSS_SIG_ACTIVE_HIGH, OMAPDSS_SIG_ACTIVE_HIGH, +- false, }, +- { 16, HDMI_HDMI }, +- }, +- { +- { 720, 576, 27000, 64, 12, 68, 5, 5, 39, +- OMAPDSS_SIG_ACTIVE_LOW, OMAPDSS_SIG_ACTIVE_LOW, +- false, }, +- { 17, HDMI_HDMI }, +- }, +- { +- { 1280, 720, 74250, 40, 440, 220, 5, 5, 20, +- OMAPDSS_SIG_ACTIVE_HIGH, OMAPDSS_SIG_ACTIVE_HIGH, +- false, }, +- { 19, HDMI_HDMI }, +- }, +- { +- { 1920, 540, 74250, 44, 528, 148, 5, 2, 15, +- OMAPDSS_SIG_ACTIVE_HIGH, OMAPDSS_SIG_ACTIVE_HIGH, +- true, }, +- { 20, HDMI_HDMI }, +- }, +- { +- { 1440, 288, 27000, 126, 24, 138, 3, 2, 19, +- OMAPDSS_SIG_ACTIVE_LOW, OMAPDSS_SIG_ACTIVE_LOW, +- true, }, +- { 21, HDMI_HDMI }, +- }, +- { +- { 1440, 576, 54000, 128, 24, 136, 5, 5, 39, +- OMAPDSS_SIG_ACTIVE_LOW, OMAPDSS_SIG_ACTIVE_LOW, +- false, }, +- { 29, HDMI_HDMI }, +- }, +- { +- { 1920, 1080, 148500, 44, 528, 148, 5, 4, 36, +- OMAPDSS_SIG_ACTIVE_HIGH, OMAPDSS_SIG_ACTIVE_HIGH, +- false, }, +- { 31, HDMI_HDMI }, +- }, +- { +- { 1920, 1080, 74250, 44, 638, 148, 5, 4, 36, +- OMAPDSS_SIG_ACTIVE_HIGH, OMAPDSS_SIG_ACTIVE_HIGH, +- false, }, +- { 32, HDMI_HDMI }, +- }, +- { +- { 2880, 480, 108108, 248, 64, 240, 6, 9, 30, +- OMAPDSS_SIG_ACTIVE_LOW, OMAPDSS_SIG_ACTIVE_LOW, +- false, }, +- { 35, HDMI_HDMI }, +- }, +- { +- { 2880, 576, 108000, 256, 48, 272, 5, 5, 39, +- OMAPDSS_SIG_ACTIVE_LOW, OMAPDSS_SIG_ACTIVE_LOW, +- false, }, +- { 37, HDMI_HDMI }, +- }, +-}; +- +-static const struct hdmi_config vesa_timings[] = { +-/* VESA From Here */ +- { +- { 640, 480, 25175, 96, 16, 48, 2, 11, 31, +- OMAPDSS_SIG_ACTIVE_LOW, OMAPDSS_SIG_ACTIVE_LOW, +- false, }, +- { 4, HDMI_DVI }, +- }, +- { +- { 800, 600, 40000, 128, 40, 88, 4, 1, 23, +- OMAPDSS_SIG_ACTIVE_HIGH, OMAPDSS_SIG_ACTIVE_HIGH, +- false, }, +- { 9, HDMI_DVI }, +- }, +- { +- { 848, 480, 33750, 112, 16, 112, 8, 6, 23, +- OMAPDSS_SIG_ACTIVE_HIGH, OMAPDSS_SIG_ACTIVE_HIGH, +- false, }, +- { 0xE, HDMI_DVI }, +- }, +- { +- { 1280, 768, 79500, 128, 64, 192, 7, 3, 20, +- OMAPDSS_SIG_ACTIVE_HIGH, OMAPDSS_SIG_ACTIVE_LOW, +- false, }, +- { 0x17, HDMI_DVI }, +- }, +- { +- { 1280, 800, 83500, 128, 72, 200, 6, 3, 22, +- OMAPDSS_SIG_ACTIVE_HIGH, OMAPDSS_SIG_ACTIVE_LOW, +- false, }, +- { 0x1C, HDMI_DVI }, +- }, +- { +- { 1360, 768, 85500, 112, 64, 256, 6, 3, 18, +- OMAPDSS_SIG_ACTIVE_HIGH, OMAPDSS_SIG_ACTIVE_HIGH, +- false, }, +- { 0x27, HDMI_DVI }, +- }, +- { +- { 1280, 960, 108000, 112, 96, 312, 3, 1, 36, +- OMAPDSS_SIG_ACTIVE_HIGH, OMAPDSS_SIG_ACTIVE_HIGH, +- false, }, +- { 0x20, HDMI_DVI }, +- }, +- { +- { 1280, 1024, 108000, 112, 48, 248, 3, 1, 38, +- OMAPDSS_SIG_ACTIVE_HIGH, OMAPDSS_SIG_ACTIVE_HIGH, +- false, }, +- { 0x23, HDMI_DVI }, +- }, +- { +- { 1024, 768, 65000, 136, 24, 160, 6, 3, 29, +- OMAPDSS_SIG_ACTIVE_LOW, OMAPDSS_SIG_ACTIVE_LOW, +- false, }, +- { 0x10, HDMI_DVI }, +- }, +- { +- { 1400, 1050, 121750, 144, 88, 232, 4, 3, 32, +- OMAPDSS_SIG_ACTIVE_HIGH, OMAPDSS_SIG_ACTIVE_LOW, +- false, }, +- { 0x2A, HDMI_DVI }, +- }, +- { +- { 1440, 900, 106500, 152, 80, 232, 6, 3, 25, +- OMAPDSS_SIG_ACTIVE_HIGH, OMAPDSS_SIG_ACTIVE_LOW, +- false, }, +- { 0x2F, HDMI_DVI }, +- }, +- { +- { 1680, 1050, 146250, 176 , 104, 280, 6, 3, 30, +- OMAPDSS_SIG_ACTIVE_HIGH, OMAPDSS_SIG_ACTIVE_LOW, +- false, }, +- { 0x3A, HDMI_DVI }, +- }, +- { +- { 1366, 768, 85500, 143, 70, 213, 3, 3, 24, +- OMAPDSS_SIG_ACTIVE_HIGH, OMAPDSS_SIG_ACTIVE_HIGH, +- false, }, +- { 0x51, HDMI_DVI }, +- }, +- { +- { 1920, 1080, 148500, 44, 148, 80, 5, 4, 36, +- OMAPDSS_SIG_ACTIVE_HIGH, OMAPDSS_SIG_ACTIVE_HIGH, +- false, }, +- { 0x52, HDMI_DVI }, +- }, +- { +- { 1280, 768, 68250, 32, 48, 80, 7, 3, 12, +- OMAPDSS_SIG_ACTIVE_LOW, OMAPDSS_SIG_ACTIVE_HIGH, +- false, }, +- { 0x16, HDMI_DVI }, +- }, +- { +- { 1400, 1050, 101000, 32, 48, 80, 4, 3, 23, +- OMAPDSS_SIG_ACTIVE_LOW, OMAPDSS_SIG_ACTIVE_HIGH, +- false, }, +- { 0x29, HDMI_DVI }, +- }, +- { +- { 1680, 1050, 119000, 32, 48, 80, 6, 3, 21, +- OMAPDSS_SIG_ACTIVE_LOW, OMAPDSS_SIG_ACTIVE_HIGH, +- false, }, +- { 0x39, HDMI_DVI }, +- }, +- { +- { 1280, 800, 79500, 32, 48, 80, 6, 3, 14, +- OMAPDSS_SIG_ACTIVE_LOW, OMAPDSS_SIG_ACTIVE_HIGH, +- false, }, +- { 0x1B, HDMI_DVI }, +- }, +- { +- { 1280, 720, 74250, 40, 110, 220, 5, 5, 20, +- OMAPDSS_SIG_ACTIVE_HIGH, OMAPDSS_SIG_ACTIVE_HIGH, +- false, }, +- { 0x55, HDMI_DVI }, +- }, +- { +- { 1920, 1200, 154000, 32, 48, 80, 6, 3, 26, +- OMAPDSS_SIG_ACTIVE_LOW, OMAPDSS_SIG_ACTIVE_HIGH, +- false, }, +- { 0x44, HDMI_DVI }, +- }, +-}; +- +-static int hdmi_runtime_get(void) +-{ +- int r; +- +- DSSDBG("hdmi_runtime_get\n"); +- +- r = pm_runtime_get_sync(&hdmi.pdev->dev); +- WARN_ON(r < 0); +- if (r < 0) +- return r; +- +- return 0; +-} +- +-static void hdmi_runtime_put(void) +-{ +- int r; +- +- DSSDBG("hdmi_runtime_put\n"); +- +- r = pm_runtime_put_sync(&hdmi.pdev->dev); +- WARN_ON(r < 0 && r != -ENOSYS); +-} +- +-static int hdmi_init_regulator(void) +-{ +- struct regulator *reg; +- +- if (hdmi.vdda_hdmi_dac_reg != NULL) +- return 0; +- +- reg = devm_regulator_get(&hdmi.pdev->dev, "vdda_hdmi_dac"); +- +- /* DT HACK: try VDAC to make omapdss work for o4 sdp/panda */ +- if (IS_ERR(reg)) +- reg = devm_regulator_get(&hdmi.pdev->dev, "VDAC"); +- +- if (IS_ERR(reg)) { +- DSSERR("can't get VDDA_HDMI_DAC regulator\n"); +- return PTR_ERR(reg); +- } +- +- hdmi.vdda_hdmi_dac_reg = reg; +- +- return 0; +-} +- +-static const struct hdmi_config *hdmi_find_timing( +- const struct hdmi_config *timings_arr, +- int len) +-{ +- int i; +- +- for (i = 0; i < len; i++) { +- if (timings_arr[i].cm.code == hdmi.ip_data.cfg.cm.code) +- return &timings_arr[i]; +- } +- return NULL; +-} +- +-static const struct hdmi_config *hdmi_get_timings(void) +-{ +- const struct hdmi_config *arr; +- int len; +- +- if (hdmi.ip_data.cfg.cm.mode == HDMI_DVI) { +- arr = vesa_timings; +- len = ARRAY_SIZE(vesa_timings); +- } else { +- arr = cea_timings; +- len = ARRAY_SIZE(cea_timings); +- } +- +- return hdmi_find_timing(arr, len); +-} +- +-static bool hdmi_timings_compare(struct omap_video_timings *timing1, +- const struct omap_video_timings *timing2) +-{ +- int timing1_vsync, timing1_hsync, timing2_vsync, timing2_hsync; +- +- if ((DIV_ROUND_CLOSEST(timing2->pixel_clock, 1000) == +- DIV_ROUND_CLOSEST(timing1->pixel_clock, 1000)) && +- (timing2->x_res == timing1->x_res) && +- (timing2->y_res == timing1->y_res)) { +- +- timing2_hsync = timing2->hfp + timing2->hsw + timing2->hbp; +- timing1_hsync = timing1->hfp + timing1->hsw + timing1->hbp; +- timing2_vsync = timing2->vfp + timing2->vsw + timing2->vbp; +- timing1_vsync = timing2->vfp + timing2->vsw + timing2->vbp; +- +- DSSDBG("timing1_hsync = %d timing1_vsync = %d"\ +- "timing2_hsync = %d timing2_vsync = %d\n", +- timing1_hsync, timing1_vsync, +- timing2_hsync, timing2_vsync); +- +- if ((timing1_hsync == timing2_hsync) && +- (timing1_vsync == timing2_vsync)) { +- return true; +- } +- } +- return false; +-} +- +-static struct hdmi_cm hdmi_get_code(struct omap_video_timings *timing) +-{ +- int i; +- struct hdmi_cm cm = {-1}; +- DSSDBG("hdmi_get_code\n"); +- +- for (i = 0; i < ARRAY_SIZE(cea_timings); i++) { +- if (hdmi_timings_compare(timing, &cea_timings[i].timings)) { +- cm = cea_timings[i].cm; +- goto end; +- } +- } +- for (i = 0; i < ARRAY_SIZE(vesa_timings); i++) { +- if (hdmi_timings_compare(timing, &vesa_timings[i].timings)) { +- cm = vesa_timings[i].cm; +- goto end; +- } +- } +- +-end: return cm; +- +-} +- +-static void hdmi_compute_pll(struct omap_dss_device *dssdev, int phy, +- struct hdmi_pll_info *pi) +-{ +- unsigned long clkin, refclk; +- u32 mf; +- +- clkin = clk_get_rate(hdmi.sys_clk) / 10000; +- /* +- * Input clock is predivided by N + 1 +- * out put of which is reference clk +- */ +- +- pi->regn = HDMI_DEFAULT_REGN; +- +- refclk = clkin / pi->regn; +- +- pi->regm2 = HDMI_DEFAULT_REGM2; +- +- /* +- * multiplier is pixel_clk/ref_clk +- * Multiplying by 100 to avoid fractional part removal +- */ +- pi->regm = phy * pi->regm2 / refclk; +- +- /* +- * fractional multiplier is remainder of the difference between +- * multiplier and actual phy(required pixel clock thus should be +- * multiplied by 2^18(262144) divided by the reference clock +- */ +- mf = (phy - pi->regm / pi->regm2 * refclk) * 262144; +- pi->regmf = pi->regm2 * mf / refclk; +- +- /* +- * Dcofreq should be set to 1 if required pixel clock +- * is greater than 1000MHz +- */ +- pi->dcofreq = phy > 1000 * 100; +- pi->regsd = ((pi->regm * clkin / 10) / (pi->regn * 250) + 5) / 10; +- +- /* Set the reference clock to sysclk reference */ +- pi->refsel = HDMI_REFSEL_SYSCLK; +- +- DSSDBG("M = %d Mf = %d\n", pi->regm, pi->regmf); +- DSSDBG("range = %d sd = %d\n", pi->dcofreq, pi->regsd); +-} +- +-static int hdmi_power_on_core(struct omap_dss_device *dssdev) +-{ +- int r; +- +- r = regulator_enable(hdmi.vdda_hdmi_dac_reg); +- if (r) +- return r; +- +- r = hdmi_runtime_get(); +- if (r) +- goto err_runtime_get; +- +- /* Make selection of HDMI in DSS */ +- dss_select_hdmi_venc_clk_source(DSS_HDMI_M_PCLK); +- +- hdmi.core_enabled = true; +- +- return 0; +- +-err_runtime_get: +- regulator_disable(hdmi.vdda_hdmi_dac_reg); +- +- return r; +-} +- +-static void hdmi_power_off_core(struct omap_dss_device *dssdev) +-{ +- hdmi.core_enabled = false; +- +- hdmi_runtime_put(); +- regulator_disable(hdmi.vdda_hdmi_dac_reg); +-} +- +-static int hdmi_power_on_full(struct omap_dss_device *dssdev) +-{ +- int r; +- struct omap_video_timings *p; +- struct omap_overlay_manager *mgr = hdmi.output.manager; +- unsigned long phy; +- +- r = hdmi_power_on_core(dssdev); +- if (r) +- return r; +- +- dss_mgr_disable(mgr); +- +- p = &hdmi.ip_data.cfg.timings; +- +- DSSDBG("hdmi_power_on x_res= %d y_res = %d\n", p->x_res, p->y_res); +- +- phy = p->pixel_clock; +- +- hdmi_compute_pll(dssdev, phy, &hdmi.ip_data.pll_data); +- +- hdmi.ip_data.ops->video_disable(&hdmi.ip_data); +- +- /* config the PLL and PHY hdmi_set_pll_pwrfirst */ +- r = hdmi.ip_data.ops->pll_enable(&hdmi.ip_data); +- if (r) { +- DSSDBG("Failed to lock PLL\n"); +- goto err_pll_enable; +- } +- +- r = hdmi.ip_data.ops->phy_enable(&hdmi.ip_data); +- if (r) { +- DSSDBG("Failed to start PHY\n"); +- goto err_phy_enable; +- } +- +- hdmi.ip_data.ops->video_configure(&hdmi.ip_data); +- +- /* bypass TV gamma table */ +- dispc_enable_gamma_table(0); +- +- /* tv size */ +- dss_mgr_set_timings(mgr, p); +- +- r = hdmi.ip_data.ops->video_enable(&hdmi.ip_data); +- if (r) +- goto err_vid_enable; +- +- r = dss_mgr_enable(mgr); +- if (r) +- goto err_mgr_enable; +- +- return 0; +- +-err_mgr_enable: +- hdmi.ip_data.ops->video_disable(&hdmi.ip_data); +-err_vid_enable: +- hdmi.ip_data.ops->phy_disable(&hdmi.ip_data); +-err_phy_enable: +- hdmi.ip_data.ops->pll_disable(&hdmi.ip_data); +-err_pll_enable: +- hdmi_power_off_core(dssdev); +- return -EIO; +-} +- +-static void hdmi_power_off_full(struct omap_dss_device *dssdev) +-{ +- struct omap_overlay_manager *mgr = hdmi.output.manager; +- +- dss_mgr_disable(mgr); +- +- hdmi.ip_data.ops->video_disable(&hdmi.ip_data); +- hdmi.ip_data.ops->phy_disable(&hdmi.ip_data); +- hdmi.ip_data.ops->pll_disable(&hdmi.ip_data); +- +- hdmi_power_off_core(dssdev); +-} +- +-static int hdmi_display_check_timing(struct omap_dss_device *dssdev, +- struct omap_video_timings *timings) +-{ +- struct hdmi_cm cm; +- +- cm = hdmi_get_code(timings); +- if (cm.code == -1) { +- return -EINVAL; +- } +- +- return 0; +- +-} +- +-static void hdmi_display_set_timing(struct omap_dss_device *dssdev, +- struct omap_video_timings *timings) +-{ +- struct hdmi_cm cm; +- const struct hdmi_config *t; +- +- mutex_lock(&hdmi.lock); +- +- cm = hdmi_get_code(timings); +- hdmi.ip_data.cfg.cm = cm; +- +- t = hdmi_get_timings(); +- if (t != NULL) { +- hdmi.ip_data.cfg = *t; +- +- dispc_set_tv_pclk(t->timings.pixel_clock * 1000); +- } +- +- mutex_unlock(&hdmi.lock); +-} +- +-static void hdmi_display_get_timings(struct omap_dss_device *dssdev, +- struct omap_video_timings *timings) +-{ +- const struct hdmi_config *cfg; +- +- cfg = hdmi_get_timings(); +- if (cfg == NULL) +- cfg = &vesa_timings[0]; +- +- memcpy(timings, &cfg->timings, sizeof(cfg->timings)); +-} +- +-static void hdmi_dump_regs(struct seq_file *s) +-{ +- mutex_lock(&hdmi.lock); +- +- if (hdmi_runtime_get()) { +- mutex_unlock(&hdmi.lock); +- return; +- } +- +- hdmi.ip_data.ops->dump_wrapper(&hdmi.ip_data, s); +- hdmi.ip_data.ops->dump_pll(&hdmi.ip_data, s); +- hdmi.ip_data.ops->dump_phy(&hdmi.ip_data, s); +- hdmi.ip_data.ops->dump_core(&hdmi.ip_data, s); +- +- hdmi_runtime_put(); +- mutex_unlock(&hdmi.lock); +-} +- +-static int read_edid(u8 *buf, int len) +-{ +- int r; +- +- mutex_lock(&hdmi.lock); +- +- r = hdmi_runtime_get(); +- BUG_ON(r); +- +- r = hdmi.ip_data.ops->read_edid(&hdmi.ip_data, buf, len); +- +- hdmi_runtime_put(); +- mutex_unlock(&hdmi.lock); +- +- return r; +-} +- +-static int hdmi_display_enable(struct omap_dss_device *dssdev) +-{ +- struct omap_dss_device *out = &hdmi.output; +- int r = 0; +- +- DSSDBG("ENTER hdmi_display_enable\n"); +- +- mutex_lock(&hdmi.lock); +- +- if (out == NULL || out->manager == NULL) { +- DSSERR("failed to enable display: no output/manager\n"); +- r = -ENODEV; +- goto err0; +- } +- +- r = hdmi_power_on_full(dssdev); +- if (r) { +- DSSERR("failed to power on device\n"); +- goto err0; +- } +- +- mutex_unlock(&hdmi.lock); +- return 0; +- +-err0: +- mutex_unlock(&hdmi.lock); +- return r; +-} +- +-static void hdmi_display_disable(struct omap_dss_device *dssdev) +-{ +- DSSDBG("Enter hdmi_display_disable\n"); +- +- mutex_lock(&hdmi.lock); +- +- hdmi_power_off_full(dssdev); +- +- mutex_unlock(&hdmi.lock); +-} +- +-static int hdmi_core_enable(struct omap_dss_device *dssdev) +-{ +- int r = 0; +- +- DSSDBG("ENTER omapdss_hdmi_core_enable\n"); +- +- mutex_lock(&hdmi.lock); +- +- r = hdmi_power_on_core(dssdev); +- if (r) { +- DSSERR("failed to power on device\n"); +- goto err0; +- } +- +- mutex_unlock(&hdmi.lock); +- return 0; +- +-err0: +- mutex_unlock(&hdmi.lock); +- return r; +-} +- +-static void hdmi_core_disable(struct omap_dss_device *dssdev) +-{ +- DSSDBG("Enter omapdss_hdmi_core_disable\n"); +- +- mutex_lock(&hdmi.lock); +- +- hdmi_power_off_core(dssdev); +- +- mutex_unlock(&hdmi.lock); +-} +- +-static int hdmi_get_clocks(struct platform_device *pdev) +-{ +- struct clk *clk; +- +- clk = devm_clk_get(&pdev->dev, "sys_clk"); +- if (IS_ERR(clk)) { +- DSSERR("can't get sys_clk\n"); +- return PTR_ERR(clk); +- } +- +- hdmi.sys_clk = clk; +- +- return 0; +-} +- +-#if defined(CONFIG_OMAP4_DSS_HDMI_AUDIO) +-int hdmi_compute_acr(u32 sample_freq, u32 *n, u32 *cts) +-{ +- u32 deep_color; +- bool deep_color_correct = false; +- u32 pclk = hdmi.ip_data.cfg.timings.pixel_clock; +- +- if (n == NULL || cts == NULL) +- return -EINVAL; +- +- /* TODO: When implemented, query deep color mode here. */ +- deep_color = 100; +- +- /* +- * When using deep color, the default N value (as in the HDMI +- * specification) yields to an non-integer CTS. Hence, we +- * modify it while keeping the restrictions described in +- * section 7.2.1 of the HDMI 1.4a specification. +- */ +- switch (sample_freq) { +- case 32000: +- case 48000: +- case 96000: +- case 192000: +- if (deep_color == 125) +- if (pclk == 27027 || pclk == 74250) +- deep_color_correct = true; +- if (deep_color == 150) +- if (pclk == 27027) +- deep_color_correct = true; +- break; +- case 44100: +- case 88200: +- case 176400: +- if (deep_color == 125) +- if (pclk == 27027) +- deep_color_correct = true; +- break; +- default: +- return -EINVAL; +- } +- +- if (deep_color_correct) { +- switch (sample_freq) { +- case 32000: +- *n = 8192; +- break; +- case 44100: +- *n = 12544; +- break; +- case 48000: +- *n = 8192; +- break; +- case 88200: +- *n = 25088; +- break; +- case 96000: +- *n = 16384; +- break; +- case 176400: +- *n = 50176; +- break; +- case 192000: +- *n = 32768; +- break; +- default: +- return -EINVAL; +- } +- } else { +- switch (sample_freq) { +- case 32000: +- *n = 4096; +- break; +- case 44100: +- *n = 6272; +- break; +- case 48000: +- *n = 6144; +- break; +- case 88200: +- *n = 12544; +- break; +- case 96000: +- *n = 12288; +- break; +- case 176400: +- *n = 25088; +- break; +- case 192000: +- *n = 24576; +- break; +- default: +- return -EINVAL; +- } +- } +- /* Calculate CTS. See HDMI 1.3a or 1.4a specifications */ +- *cts = pclk * (*n / 128) * deep_color / (sample_freq / 10); +- +- return 0; +-} +- +-static bool hdmi_mode_has_audio(void) +-{ +- if (hdmi.ip_data.cfg.cm.mode == HDMI_HDMI) +- return true; +- else +- return false; +-} +- +-#endif +- +-static int hdmi_connect(struct omap_dss_device *dssdev, +- struct omap_dss_device *dst) +-{ +- struct omap_overlay_manager *mgr; +- int r; +- +- dss_init_hdmi_ip_ops(&hdmi.ip_data, omapdss_get_version()); +- +- r = hdmi_init_regulator(); +- if (r) +- return r; +- +- mgr = omap_dss_get_overlay_manager(dssdev->dispc_channel); +- if (!mgr) +- return -ENODEV; +- +- r = dss_mgr_connect(mgr, dssdev); +- if (r) +- return r; +- +- r = omapdss_output_set_device(dssdev, dst); +- if (r) { +- DSSERR("failed to connect output to new device: %s\n", +- dst->name); +- dss_mgr_disconnect(mgr, dssdev); +- return r; +- } +- +- return 0; +-} +- +-static void hdmi_disconnect(struct omap_dss_device *dssdev, +- struct omap_dss_device *dst) +-{ +- WARN_ON(dst != dssdev->dst); +- +- if (dst != dssdev->dst) +- return; +- +- omapdss_output_unset_device(dssdev); +- +- if (dssdev->manager) +- dss_mgr_disconnect(dssdev->manager, dssdev); +-} +- +-static int hdmi_read_edid(struct omap_dss_device *dssdev, +- u8 *edid, int len) +-{ +- bool need_enable; +- int r; +- +- need_enable = hdmi.core_enabled == false; +- +- if (need_enable) { +- r = hdmi_core_enable(dssdev); +- if (r) +- return r; +- } +- +- r = read_edid(edid, len); +- +- if (need_enable) +- hdmi_core_disable(dssdev); +- +- return r; +-} +- +-#if defined(CONFIG_OMAP4_DSS_HDMI_AUDIO) +-static int hdmi_audio_enable(struct omap_dss_device *dssdev) +-{ +- int r; +- +- mutex_lock(&hdmi.lock); +- +- if (!hdmi_mode_has_audio()) { +- r = -EPERM; +- goto err; +- } +- +- +- r = hdmi.ip_data.ops->audio_enable(&hdmi.ip_data); +- if (r) +- goto err; +- +- mutex_unlock(&hdmi.lock); +- return 0; +- +-err: +- mutex_unlock(&hdmi.lock); +- return r; +-} +- +-static void hdmi_audio_disable(struct omap_dss_device *dssdev) +-{ +- hdmi.ip_data.ops->audio_disable(&hdmi.ip_data); +-} +- +-static int hdmi_audio_start(struct omap_dss_device *dssdev) +-{ +- return hdmi.ip_data.ops->audio_start(&hdmi.ip_data); +-} +- +-static void hdmi_audio_stop(struct omap_dss_device *dssdev) +-{ +- hdmi.ip_data.ops->audio_stop(&hdmi.ip_data); +-} +- +-static bool hdmi_audio_supported(struct omap_dss_device *dssdev) +-{ +- bool r; +- +- mutex_lock(&hdmi.lock); +- +- r = hdmi_mode_has_audio(); +- +- mutex_unlock(&hdmi.lock); +- return r; +-} +- +-static int hdmi_audio_config(struct omap_dss_device *dssdev, +- struct omap_dss_audio *audio) +-{ +- int r; +- +- mutex_lock(&hdmi.lock); +- +- if (!hdmi_mode_has_audio()) { +- r = -EPERM; +- goto err; +- } +- +- r = hdmi.ip_data.ops->audio_config(&hdmi.ip_data, audio); +- if (r) +- goto err; +- +- mutex_unlock(&hdmi.lock); +- return 0; +- +-err: +- mutex_unlock(&hdmi.lock); +- return r; +-} +-#else +-static int hdmi_audio_enable(struct omap_dss_device *dssdev) +-{ +- return -EPERM; +-} +- +-static void hdmi_audio_disable(struct omap_dss_device *dssdev) +-{ +-} +- +-static int hdmi_audio_start(struct omap_dss_device *dssdev) +-{ +- return -EPERM; +-} +- +-static void hdmi_audio_stop(struct omap_dss_device *dssdev) +-{ +-} +- +-static bool hdmi_audio_supported(struct omap_dss_device *dssdev) +-{ +- return false; +-} +- +-static int hdmi_audio_config(struct omap_dss_device *dssdev, +- struct omap_dss_audio *audio) +-{ +- return -EPERM; +-} +-#endif +- +-static const struct omapdss_hdmi_ops hdmi_ops = { +- .connect = hdmi_connect, +- .disconnect = hdmi_disconnect, +- +- .enable = hdmi_display_enable, +- .disable = hdmi_display_disable, +- +- .check_timings = hdmi_display_check_timing, +- .set_timings = hdmi_display_set_timing, +- .get_timings = hdmi_display_get_timings, +- +- .read_edid = hdmi_read_edid, +- +- .audio_enable = hdmi_audio_enable, +- .audio_disable = hdmi_audio_disable, +- .audio_start = hdmi_audio_start, +- .audio_stop = hdmi_audio_stop, +- .audio_supported = hdmi_audio_supported, +- .audio_config = hdmi_audio_config, +-}; +- +-static void hdmi_init_output(struct platform_device *pdev) +-{ +- struct omap_dss_device *out = &hdmi.output; +- +- out->dev = &pdev->dev; +- out->id = OMAP_DSS_OUTPUT_HDMI; +- out->output_type = OMAP_DISPLAY_TYPE_HDMI; +- out->name = "hdmi.0"; +- out->dispc_channel = OMAP_DSS_CHANNEL_DIGIT; +- out->ops.hdmi = &hdmi_ops; +- out->owner = THIS_MODULE; +- +- omapdss_register_output(out); +-} +- +-static void __exit hdmi_uninit_output(struct platform_device *pdev) +-{ +- struct omap_dss_device *out = &hdmi.output; +- +- omapdss_unregister_output(out); +-} +- +-/* HDMI HW IP initialisation */ +-static int omapdss_hdmihw_probe(struct platform_device *pdev) +-{ +- struct resource *res; +- int r; +- +- hdmi.pdev = pdev; +- +- mutex_init(&hdmi.lock); +- mutex_init(&hdmi.ip_data.lock); +- +- res = platform_get_resource(hdmi.pdev, IORESOURCE_MEM, 0); +- +- /* Base address taken from platform */ +- hdmi.ip_data.base_wp = devm_ioremap_resource(&pdev->dev, res); +- if (IS_ERR(hdmi.ip_data.base_wp)) +- return PTR_ERR(hdmi.ip_data.base_wp); +- +- hdmi.ip_data.irq = platform_get_irq(pdev, 0); +- if (hdmi.ip_data.irq < 0) { +- DSSERR("platform_get_irq failed\n"); +- return -ENODEV; +- } +- +- r = hdmi_get_clocks(pdev); +- if (r) { +- DSSERR("can't get clocks\n"); +- return r; +- } +- +- pm_runtime_enable(&pdev->dev); +- +- hdmi.ip_data.core_sys_offset = HDMI_CORE_SYS; +- hdmi.ip_data.core_av_offset = HDMI_CORE_AV; +- hdmi.ip_data.pll_offset = HDMI_PLLCTRL; +- hdmi.ip_data.phy_offset = HDMI_PHY; +- +- hdmi_init_output(pdev); +- +- dss_debugfs_create_file("hdmi", hdmi_dump_regs); +- +- return 0; +-} +- +-static int __exit omapdss_hdmihw_remove(struct platform_device *pdev) +-{ +- hdmi_uninit_output(pdev); +- +- pm_runtime_disable(&pdev->dev); +- +- return 0; +-} +- +-static int hdmi_runtime_suspend(struct device *dev) +-{ +- clk_disable_unprepare(hdmi.sys_clk); +- +- dispc_runtime_put(); +- +- return 0; +-} +- +-static int hdmi_runtime_resume(struct device *dev) +-{ +- int r; +- +- r = dispc_runtime_get(); +- if (r < 0) +- return r; +- +- clk_prepare_enable(hdmi.sys_clk); +- +- return 0; +-} +- +-static const struct dev_pm_ops hdmi_pm_ops = { +- .runtime_suspend = hdmi_runtime_suspend, +- .runtime_resume = hdmi_runtime_resume, +-}; +- +-static struct platform_driver omapdss_hdmihw_driver = { +- .probe = omapdss_hdmihw_probe, +- .remove = __exit_p(omapdss_hdmihw_remove), +- .driver = { +- .name = "omapdss_hdmi", +- .owner = THIS_MODULE, +- .pm = &hdmi_pm_ops, +- }, +-}; +- +-int __init hdmi_init_platform_driver(void) +-{ +- return platform_driver_register(&omapdss_hdmihw_driver); +-} +- +-void __exit hdmi_uninit_platform_driver(void) +-{ +- platform_driver_unregister(&omapdss_hdmihw_driver); +-} +--- /dev/null ++++ b/drivers/video/omap2/dss/hdmi_common.c +@@ -0,0 +1,423 @@ ++ ++/* ++ * Logic for the below structure : ++ * user enters the CEA or VESA timings by specifying the HDMI/DVI code. ++ * There is a correspondence between CEA/VESA timing and code, please ++ * refer to section 6.3 in HDMI 1.3 specification for timing code. ++ * ++ * In the below structure, cea_vesa_timings corresponds to all OMAP4 ++ * supported CEA and VESA timing values.code_cea corresponds to the CEA ++ * code, It is used to get the timing from cea_vesa_timing array.Similarly ++ * with code_vesa. Code_index is used for back mapping, that is once EDID ++ * is read from the TV, EDID is parsed to find the timing values and then ++ * map it to corresponding CEA or VESA index. ++ */ ++ ++#include <linux/kernel.h> ++#include <linux/err.h> ++#include <video/omapdss.h> ++ ++#include "hdmi.h" ++ ++static const struct hdmi_config cea_timings[] = { ++ { ++ { 640, 480, 25200, 96, 16, 48, 2, 10, 33, ++ OMAPDSS_SIG_ACTIVE_LOW, OMAPDSS_SIG_ACTIVE_LOW, ++ false, }, ++ { 1, HDMI_HDMI }, ++ }, ++ { ++ { 720, 480, 27027, 62, 16, 60, 6, 9, 30, ++ OMAPDSS_SIG_ACTIVE_LOW, OMAPDSS_SIG_ACTIVE_LOW, ++ false, }, ++ { 2, HDMI_HDMI }, ++ }, ++ { ++ { 1280, 720, 74250, 40, 110, 220, 5, 5, 20, ++ OMAPDSS_SIG_ACTIVE_HIGH, OMAPDSS_SIG_ACTIVE_HIGH, ++ false, }, ++ { 4, HDMI_HDMI }, ++ }, ++ { ++ { 1920, 540, 74250, 44, 88, 148, 5, 2, 15, ++ OMAPDSS_SIG_ACTIVE_HIGH, OMAPDSS_SIG_ACTIVE_HIGH, ++ true, }, ++ { 5, HDMI_HDMI }, ++ }, ++ { ++ { 1440, 240, 27027, 124, 38, 114, 3, 4, 15, ++ OMAPDSS_SIG_ACTIVE_LOW, OMAPDSS_SIG_ACTIVE_LOW, ++ true, }, ++ { 6, HDMI_HDMI }, ++ }, ++ { ++ { 1920, 1080, 148500, 44, 88, 148, 5, 4, 36, ++ OMAPDSS_SIG_ACTIVE_HIGH, OMAPDSS_SIG_ACTIVE_HIGH, ++ false, }, ++ { 16, HDMI_HDMI }, ++ }, ++ { ++ { 720, 576, 27000, 64, 12, 68, 5, 5, 39, ++ OMAPDSS_SIG_ACTIVE_LOW, OMAPDSS_SIG_ACTIVE_LOW, ++ false, }, ++ { 17, HDMI_HDMI }, ++ }, ++ { ++ { 1280, 720, 74250, 40, 440, 220, 5, 5, 20, ++ OMAPDSS_SIG_ACTIVE_HIGH, OMAPDSS_SIG_ACTIVE_HIGH, ++ false, }, ++ { 19, HDMI_HDMI }, ++ }, ++ { ++ { 1920, 540, 74250, 44, 528, 148, 5, 2, 15, ++ OMAPDSS_SIG_ACTIVE_HIGH, OMAPDSS_SIG_ACTIVE_HIGH, ++ true, }, ++ { 20, HDMI_HDMI }, ++ }, ++ { ++ { 1440, 288, 27000, 126, 24, 138, 3, 2, 19, ++ OMAPDSS_SIG_ACTIVE_LOW, OMAPDSS_SIG_ACTIVE_LOW, ++ true, }, ++ { 21, HDMI_HDMI }, ++ }, ++ { ++ { 1440, 576, 54000, 128, 24, 136, 5, 5, 39, ++ OMAPDSS_SIG_ACTIVE_LOW, OMAPDSS_SIG_ACTIVE_LOW, ++ false, }, ++ { 29, HDMI_HDMI }, ++ }, ++ { ++ { 1920, 1080, 148500, 44, 528, 148, 5, 4, 36, ++ OMAPDSS_SIG_ACTIVE_HIGH, OMAPDSS_SIG_ACTIVE_HIGH, ++ false, }, ++ { 31, HDMI_HDMI }, ++ }, ++ { ++ { 1920, 1080, 74250, 44, 638, 148, 5, 4, 36, ++ OMAPDSS_SIG_ACTIVE_HIGH, OMAPDSS_SIG_ACTIVE_HIGH, ++ false, }, ++ { 32, HDMI_HDMI }, ++ }, ++ { ++ { 2880, 480, 108108, 248, 64, 240, 6, 9, 30, ++ OMAPDSS_SIG_ACTIVE_LOW, OMAPDSS_SIG_ACTIVE_LOW, ++ false, }, ++ { 35, HDMI_HDMI }, ++ }, ++ { ++ { 2880, 576, 108000, 256, 48, 272, 5, 5, 39, ++ OMAPDSS_SIG_ACTIVE_LOW, OMAPDSS_SIG_ACTIVE_LOW, ++ false, }, ++ { 37, HDMI_HDMI }, ++ }, ++}; ++ ++static const struct hdmi_config vesa_timings[] = { ++/* VESA From Here */ ++ { ++ { 640, 480, 25175, 96, 16, 48, 2, 11, 31, ++ OMAPDSS_SIG_ACTIVE_LOW, OMAPDSS_SIG_ACTIVE_LOW, ++ false, }, ++ { 4, HDMI_DVI }, ++ }, ++ { ++ { 800, 600, 40000, 128, 40, 88, 4, 1, 23, ++ OMAPDSS_SIG_ACTIVE_HIGH, OMAPDSS_SIG_ACTIVE_HIGH, ++ false, }, ++ { 9, HDMI_DVI }, ++ }, ++ { ++ { 848, 480, 33750, 112, 16, 112, 8, 6, 23, ++ OMAPDSS_SIG_ACTIVE_HIGH, OMAPDSS_SIG_ACTIVE_HIGH, ++ false, }, ++ { 0xE, HDMI_DVI }, ++ }, ++ { ++ { 1280, 768, 79500, 128, 64, 192, 7, 3, 20, ++ OMAPDSS_SIG_ACTIVE_HIGH, OMAPDSS_SIG_ACTIVE_LOW, ++ false, }, ++ { 0x17, HDMI_DVI }, ++ }, ++ { ++ { 1280, 800, 83500, 128, 72, 200, 6, 3, 22, ++ OMAPDSS_SIG_ACTIVE_HIGH, OMAPDSS_SIG_ACTIVE_LOW, ++ false, }, ++ { 0x1C, HDMI_DVI }, ++ }, ++ { ++ { 1360, 768, 85500, 112, 64, 256, 6, 3, 18, ++ OMAPDSS_SIG_ACTIVE_HIGH, OMAPDSS_SIG_ACTIVE_HIGH, ++ false, }, ++ { 0x27, HDMI_DVI }, ++ }, ++ { ++ { 1280, 960, 108000, 112, 96, 312, 3, 1, 36, ++ OMAPDSS_SIG_ACTIVE_HIGH, OMAPDSS_SIG_ACTIVE_HIGH, ++ false, }, ++ { 0x20, HDMI_DVI }, ++ }, ++ { ++ { 1280, 1024, 108000, 112, 48, 248, 3, 1, 38, ++ OMAPDSS_SIG_ACTIVE_HIGH, OMAPDSS_SIG_ACTIVE_HIGH, ++ false, }, ++ { 0x23, HDMI_DVI }, ++ }, ++ { ++ { 1024, 768, 65000, 136, 24, 160, 6, 3, 29, ++ OMAPDSS_SIG_ACTIVE_LOW, OMAPDSS_SIG_ACTIVE_LOW, ++ false, }, ++ { 0x10, HDMI_DVI }, ++ }, ++ { ++ { 1400, 1050, 121750, 144, 88, 232, 4, 3, 32, ++ OMAPDSS_SIG_ACTIVE_HIGH, OMAPDSS_SIG_ACTIVE_LOW, ++ false, }, ++ { 0x2A, HDMI_DVI }, ++ }, ++ { ++ { 1440, 900, 106500, 152, 80, 232, 6, 3, 25, ++ OMAPDSS_SIG_ACTIVE_HIGH, OMAPDSS_SIG_ACTIVE_LOW, ++ false, }, ++ { 0x2F, HDMI_DVI }, ++ }, ++ { ++ { 1680, 1050, 146250, 176 , 104, 280, 6, 3, 30, ++ OMAPDSS_SIG_ACTIVE_HIGH, OMAPDSS_SIG_ACTIVE_LOW, ++ false, }, ++ { 0x3A, HDMI_DVI }, ++ }, ++ { ++ { 1366, 768, 85500, 143, 70, 213, 3, 3, 24, ++ OMAPDSS_SIG_ACTIVE_HIGH, OMAPDSS_SIG_ACTIVE_HIGH, ++ false, }, ++ { 0x51, HDMI_DVI }, ++ }, ++ { ++ { 1920, 1080, 148500, 44, 148, 80, 5, 4, 36, ++ OMAPDSS_SIG_ACTIVE_HIGH, OMAPDSS_SIG_ACTIVE_HIGH, ++ false, }, ++ { 0x52, HDMI_DVI }, ++ }, ++ { ++ { 1280, 768, 68250, 32, 48, 80, 7, 3, 12, ++ OMAPDSS_SIG_ACTIVE_LOW, OMAPDSS_SIG_ACTIVE_HIGH, ++ false, }, ++ { 0x16, HDMI_DVI }, ++ }, ++ { ++ { 1400, 1050, 101000, 32, 48, 80, 4, 3, 23, ++ OMAPDSS_SIG_ACTIVE_LOW, OMAPDSS_SIG_ACTIVE_HIGH, ++ false, }, ++ { 0x29, HDMI_DVI }, ++ }, ++ { ++ { 1680, 1050, 119000, 32, 48, 80, 6, 3, 21, ++ OMAPDSS_SIG_ACTIVE_LOW, OMAPDSS_SIG_ACTIVE_HIGH, ++ false, }, ++ { 0x39, HDMI_DVI }, ++ }, ++ { ++ { 1280, 800, 79500, 32, 48, 80, 6, 3, 14, ++ OMAPDSS_SIG_ACTIVE_LOW, OMAPDSS_SIG_ACTIVE_HIGH, ++ false, }, ++ { 0x1B, HDMI_DVI }, ++ }, ++ { ++ { 1280, 720, 74250, 40, 110, 220, 5, 5, 20, ++ OMAPDSS_SIG_ACTIVE_HIGH, OMAPDSS_SIG_ACTIVE_HIGH, ++ false, }, ++ { 0x55, HDMI_DVI }, ++ }, ++ { ++ { 1920, 1200, 154000, 32, 48, 80, 6, 3, 26, ++ OMAPDSS_SIG_ACTIVE_LOW, OMAPDSS_SIG_ACTIVE_HIGH, ++ false, }, ++ { 0x44, HDMI_DVI }, ++ }, ++}; ++ ++const struct hdmi_config *hdmi_default_timing(void) ++{ ++ return &vesa_timings[0]; ++} ++ ++static const struct hdmi_config *hdmi_find_timing(int code, ++ const struct hdmi_config *timings_arr, int len) ++{ ++ int i; ++ ++ for (i = 0; i < len; i++) { ++ if (timings_arr[i].cm.code == code) ++ return &timings_arr[i]; ++ } ++ ++ return NULL; ++} ++ ++const struct hdmi_config *hdmi_get_timings(int mode, int code) ++{ ++ const struct hdmi_config *arr; ++ int len; ++ ++ if (mode == HDMI_DVI) { ++ arr = vesa_timings; ++ len = ARRAY_SIZE(vesa_timings); ++ } else { ++ arr = cea_timings; ++ len = ARRAY_SIZE(cea_timings); ++ } ++ ++ return hdmi_find_timing(code, arr, len); ++} ++ ++static bool hdmi_timings_compare(struct omap_video_timings *timing1, ++ const struct omap_video_timings *timing2) ++{ ++ int timing1_vsync, timing1_hsync, timing2_vsync, timing2_hsync; ++ ++ if ((DIV_ROUND_CLOSEST(timing2->pixel_clock, 1000) == ++ DIV_ROUND_CLOSEST(timing1->pixel_clock, 1000)) && ++ (timing2->x_res == timing1->x_res) && ++ (timing2->y_res == timing1->y_res)) { ++ ++ timing2_hsync = timing2->hfp + timing2->hsw + timing2->hbp; ++ timing1_hsync = timing1->hfp + timing1->hsw + timing1->hbp; ++ timing2_vsync = timing2->vfp + timing2->vsw + timing2->vbp; ++ timing1_vsync = timing2->vfp + timing2->vsw + timing2->vbp; ++ ++ DSSDBG("timing1_hsync = %d timing1_vsync = %d"\ ++ "timing2_hsync = %d timing2_vsync = %d\n", ++ timing1_hsync, timing1_vsync, ++ timing2_hsync, timing2_vsync); ++ ++ if ((timing1_hsync == timing2_hsync) && ++ (timing1_vsync == timing2_vsync)) { ++ return true; ++ } ++ } ++ return false; ++} ++ ++struct hdmi_cm hdmi_get_code(struct omap_video_timings *timing) ++{ ++ int i; ++ struct hdmi_cm cm = {-1}; ++ DSSDBG("hdmi_get_code\n"); ++ ++ for (i = 0; i < ARRAY_SIZE(cea_timings); i++) { ++ if (hdmi_timings_compare(timing, &cea_timings[i].timings)) { ++ cm = cea_timings[i].cm; ++ goto end; ++ } ++ } ++ for (i = 0; i < ARRAY_SIZE(vesa_timings); i++) { ++ if (hdmi_timings_compare(timing, &vesa_timings[i].timings)) { ++ cm = vesa_timings[i].cm; ++ goto end; ++ } ++ } ++ ++end: ++ return cm; ++} ++ ++#if defined(CONFIG_OMAP4_DSS_HDMI_AUDIO) ++int hdmi_compute_acr(u32 pclk, u32 sample_freq, u32 *n, u32 *cts) ++{ ++ u32 deep_color; ++ bool deep_color_correct = false; ++ ++ if (n == NULL || cts == NULL) ++ return -EINVAL; ++ ++ /* TODO: When implemented, query deep color mode here. */ ++ deep_color = 100; ++ ++ /* ++ * When using deep color, the default N value (as in the HDMI ++ * specification) yields to an non-integer CTS. Hence, we ++ * modify it while keeping the restrictions described in ++ * section 7.2.1 of the HDMI 1.4a specification. ++ */ ++ switch (sample_freq) { ++ case 32000: ++ case 48000: ++ case 96000: ++ case 192000: ++ if (deep_color == 125) ++ if (pclk == 27027 || pclk == 74250) ++ deep_color_correct = true; ++ if (deep_color == 150) ++ if (pclk == 27027) ++ deep_color_correct = true; ++ break; ++ case 44100: ++ case 88200: ++ case 176400: ++ if (deep_color == 125) ++ if (pclk == 27027) ++ deep_color_correct = true; ++ break; ++ default: ++ return -EINVAL; ++ } ++ ++ if (deep_color_correct) { ++ switch (sample_freq) { ++ case 32000: ++ *n = 8192; ++ break; ++ case 44100: ++ *n = 12544; ++ break; ++ case 48000: ++ *n = 8192; ++ break; ++ case 88200: ++ *n = 25088; ++ break; ++ case 96000: ++ *n = 16384; ++ break; ++ case 176400: ++ *n = 50176; ++ break; ++ case 192000: ++ *n = 32768; ++ break; ++ default: ++ return -EINVAL; ++ } ++ } else { ++ switch (sample_freq) { ++ case 32000: ++ *n = 4096; ++ break; ++ case 44100: ++ *n = 6272; ++ break; ++ case 48000: ++ *n = 6144; ++ break; ++ case 88200: ++ *n = 12544; ++ break; ++ case 96000: ++ *n = 12288; ++ break; ++ case 176400: ++ *n = 25088; ++ break; ++ case 192000: ++ *n = 24576; ++ break; ++ default: ++ return -EINVAL; ++ } ++ } ++ /* Calculate CTS. See HDMI 1.3a or 1.4a specifications */ ++ *cts = pclk * (*n / 128) * deep_color / (sample_freq / 10); ++ ++ return 0; ++} ++#endif +--- /dev/null ++++ b/drivers/video/omap2/dss/hdmi.h +@@ -0,0 +1,441 @@ ++/* ++ * HDMI driver definition for TI OMAP4 Processor. ++ * ++ * Copyright (C) 2010-2011 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 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, see <http://www.gnu.org/licenses/>. ++ */ ++ ++#ifndef _HDMI_H ++#define _HDMI_H ++ ++#include <linux/delay.h> ++#include <linux/io.h> ++#include <linux/platform_device.h> ++#include <video/omapdss.h> ++ ++#include "dss.h" ++ ++/* HDMI Wrapper */ ++ ++#define HDMI_WP_REVISION 0x0 ++#define HDMI_WP_SYSCONFIG 0x10 ++#define HDMI_WP_IRQSTATUS_RAW 0x24 ++#define HDMI_WP_IRQSTATUS 0x28 ++#define HDMI_WP_IRQENABLE_SET 0x2C ++#define HDMI_WP_IRQENABLE_CLR 0x30 ++#define HDMI_WP_IRQWAKEEN 0x34 ++#define HDMI_WP_PWR_CTRL 0x40 ++#define HDMI_WP_DEBOUNCE 0x44 ++#define HDMI_WP_VIDEO_CFG 0x50 ++#define HDMI_WP_VIDEO_SIZE 0x60 ++#define HDMI_WP_VIDEO_TIMING_H 0x68 ++#define HDMI_WP_VIDEO_TIMING_V 0x6C ++#define HDMI_WP_CLK 0x70 ++#define HDMI_WP_AUDIO_CFG 0x80 ++#define HDMI_WP_AUDIO_CFG2 0x84 ++#define HDMI_WP_AUDIO_CTRL 0x88 ++#define HDMI_WP_AUDIO_DATA 0x8C ++ ++/* HDMI WP IRQ flags */ ++#define HDMI_IRQ_CORE (1 << 0) ++#define HDMI_IRQ_OCP_TIMEOUT (1 << 4) ++#define HDMI_IRQ_AUDIO_FIFO_UNDERFLOW (1 << 8) ++#define HDMI_IRQ_AUDIO_FIFO_OVERFLOW (1 << 9) ++#define HDMI_IRQ_AUDIO_FIFO_SAMPLE_REQ (1 << 10) ++#define HDMI_IRQ_VIDEO_VSYNC (1 << 16) ++#define HDMI_IRQ_VIDEO_FRAME_DONE (1 << 17) ++#define HDMI_IRQ_PHY_LINE5V_ASSERT (1 << 24) ++#define HDMI_IRQ_LINK_CONNECT (1 << 25) ++#define HDMI_IRQ_LINK_DISCONNECT (1 << 26) ++#define HDMI_IRQ_PLL_LOCK (1 << 29) ++#define HDMI_IRQ_PLL_UNLOCK (1 << 30) ++#define HDMI_IRQ_PLL_RECAL (1 << 31) ++ ++/* HDMI PLL */ ++ ++#define PLLCTRL_PLL_CONTROL 0x0 ++#define PLLCTRL_PLL_STATUS 0x4 ++#define PLLCTRL_PLL_GO 0x8 ++#define PLLCTRL_CFG1 0xC ++#define PLLCTRL_CFG2 0x10 ++#define PLLCTRL_CFG3 0x14 ++#define PLLCTRL_SSC_CFG1 0x18 ++#define PLLCTRL_SSC_CFG2 0x1C ++#define PLLCTRL_CFG4 0x20 ++ ++/* HDMI PHY */ ++ ++#define HDMI_TXPHY_TX_CTRL 0x0 ++#define HDMI_TXPHY_DIGITAL_CTRL 0x4 ++#define HDMI_TXPHY_POWER_CTRL 0x8 ++#define HDMI_TXPHY_PAD_CFG_CTRL 0xC ++#define HDMI_TXPHY_BIST_CONTROL 0x1C ++ ++enum hdmi_pll_pwr { ++ HDMI_PLLPWRCMD_ALLOFF = 0, ++ HDMI_PLLPWRCMD_PLLONLY = 1, ++ HDMI_PLLPWRCMD_BOTHON_ALLCLKS = 2, ++ HDMI_PLLPWRCMD_BOTHON_NOPHYCLK = 3 ++}; ++ ++enum hdmi_phy_pwr { ++ HDMI_PHYPWRCMD_OFF = 0, ++ HDMI_PHYPWRCMD_LDOON = 1, ++ HDMI_PHYPWRCMD_TXON = 2 ++}; ++ ++enum hdmi_core_hdmi_dvi { ++ HDMI_DVI = 0, ++ HDMI_HDMI = 1 ++}; ++ ++enum hdmi_clk_refsel { ++ HDMI_REFSEL_PCLK = 0, ++ HDMI_REFSEL_REF1 = 1, ++ HDMI_REFSEL_REF2 = 2, ++ HDMI_REFSEL_SYSCLK = 3 ++}; ++ ++enum hdmi_packing_mode { ++ HDMI_PACK_10b_RGB_YUV444 = 0, ++ HDMI_PACK_24b_RGB_YUV444_YUV422 = 1, ++ HDMI_PACK_20b_YUV422 = 2, ++ HDMI_PACK_ALREADYPACKED = 7 ++}; ++ ++enum hdmi_stereo_channels { ++ HDMI_AUDIO_STEREO_NOCHANNELS = 0, ++ HDMI_AUDIO_STEREO_ONECHANNEL = 1, ++ HDMI_AUDIO_STEREO_TWOCHANNELS = 2, ++ HDMI_AUDIO_STEREO_THREECHANNELS = 3, ++ HDMI_AUDIO_STEREO_FOURCHANNELS = 4 ++}; ++ ++enum hdmi_audio_type { ++ HDMI_AUDIO_TYPE_LPCM = 0, ++ HDMI_AUDIO_TYPE_IEC = 1 ++}; ++ ++enum hdmi_audio_justify { ++ HDMI_AUDIO_JUSTIFY_LEFT = 0, ++ HDMI_AUDIO_JUSTIFY_RIGHT = 1 ++}; ++ ++enum hdmi_audio_sample_order { ++ HDMI_AUDIO_SAMPLE_RIGHT_FIRST = 0, ++ HDMI_AUDIO_SAMPLE_LEFT_FIRST = 1 ++}; ++ ++enum hdmi_audio_samples_perword { ++ HDMI_AUDIO_ONEWORD_ONESAMPLE = 0, ++ HDMI_AUDIO_ONEWORD_TWOSAMPLES = 1 ++}; ++ ++enum hdmi_audio_sample_size { ++ HDMI_AUDIO_SAMPLE_16BITS = 0, ++ HDMI_AUDIO_SAMPLE_24BITS = 1 ++}; ++ ++enum hdmi_audio_transf_mode { ++ HDMI_AUDIO_TRANSF_DMA = 0, ++ HDMI_AUDIO_TRANSF_IRQ = 1 ++}; ++ ++enum hdmi_audio_blk_strt_end_sig { ++ HDMI_AUDIO_BLOCK_SIG_STARTEND_ON = 0, ++ HDMI_AUDIO_BLOCK_SIG_STARTEND_OFF = 1 ++}; ++ ++enum hdmi_core_audio_layout { ++ HDMI_AUDIO_LAYOUT_2CH = 0, ++ HDMI_AUDIO_LAYOUT_8CH = 1 ++}; ++ ++enum hdmi_core_cts_mode { ++ HDMI_AUDIO_CTS_MODE_HW = 0, ++ HDMI_AUDIO_CTS_MODE_SW = 1 ++}; ++ ++enum hdmi_audio_mclk_mode { ++ HDMI_AUDIO_MCLK_128FS = 0, ++ HDMI_AUDIO_MCLK_256FS = 1, ++ HDMI_AUDIO_MCLK_384FS = 2, ++ HDMI_AUDIO_MCLK_512FS = 3, ++ HDMI_AUDIO_MCLK_768FS = 4, ++ HDMI_AUDIO_MCLK_1024FS = 5, ++ HDMI_AUDIO_MCLK_1152FS = 6, ++ HDMI_AUDIO_MCLK_192FS = 7 ++}; ++ ++/* INFOFRAME_AVI_ and INFOFRAME_AUDIO_ definitions */ ++enum hdmi_core_infoframe { ++ HDMI_INFOFRAME_AVI_DB1Y_RGB = 0, ++ HDMI_INFOFRAME_AVI_DB1Y_YUV422 = 1, ++ HDMI_INFOFRAME_AVI_DB1Y_YUV444 = 2, ++ HDMI_INFOFRAME_AVI_DB1A_ACTIVE_FORMAT_OFF = 0, ++ HDMI_INFOFRAME_AVI_DB1A_ACTIVE_FORMAT_ON = 1, ++ HDMI_INFOFRAME_AVI_DB1B_NO = 0, ++ HDMI_INFOFRAME_AVI_DB1B_VERT = 1, ++ HDMI_INFOFRAME_AVI_DB1B_HORI = 2, ++ HDMI_INFOFRAME_AVI_DB1B_VERTHORI = 3, ++ HDMI_INFOFRAME_AVI_DB1S_0 = 0, ++ HDMI_INFOFRAME_AVI_DB1S_1 = 1, ++ HDMI_INFOFRAME_AVI_DB1S_2 = 2, ++ HDMI_INFOFRAME_AVI_DB2C_NO = 0, ++ HDMI_INFOFRAME_AVI_DB2C_ITU601 = 1, ++ HDMI_INFOFRAME_AVI_DB2C_ITU709 = 2, ++ HDMI_INFOFRAME_AVI_DB2C_EC_EXTENDED = 3, ++ HDMI_INFOFRAME_AVI_DB2M_NO = 0, ++ HDMI_INFOFRAME_AVI_DB2M_43 = 1, ++ HDMI_INFOFRAME_AVI_DB2M_169 = 2, ++ HDMI_INFOFRAME_AVI_DB2R_SAME = 8, ++ HDMI_INFOFRAME_AVI_DB2R_43 = 9, ++ HDMI_INFOFRAME_AVI_DB2R_169 = 10, ++ HDMI_INFOFRAME_AVI_DB2R_149 = 11, ++ HDMI_INFOFRAME_AVI_DB3ITC_NO = 0, ++ HDMI_INFOFRAME_AVI_DB3ITC_YES = 1, ++ HDMI_INFOFRAME_AVI_DB3EC_XVYUV601 = 0, ++ HDMI_INFOFRAME_AVI_DB3EC_XVYUV709 = 1, ++ HDMI_INFOFRAME_AVI_DB3Q_DEFAULT = 0, ++ HDMI_INFOFRAME_AVI_DB3Q_LR = 1, ++ HDMI_INFOFRAME_AVI_DB3Q_FR = 2, ++ HDMI_INFOFRAME_AVI_DB3SC_NO = 0, ++ HDMI_INFOFRAME_AVI_DB3SC_HORI = 1, ++ HDMI_INFOFRAME_AVI_DB3SC_VERT = 2, ++ HDMI_INFOFRAME_AVI_DB3SC_HORIVERT = 3, ++ HDMI_INFOFRAME_AVI_DB5PR_NO = 0, ++ HDMI_INFOFRAME_AVI_DB5PR_2 = 1, ++ HDMI_INFOFRAME_AVI_DB5PR_3 = 2, ++ HDMI_INFOFRAME_AVI_DB5PR_4 = 3, ++ HDMI_INFOFRAME_AVI_DB5PR_5 = 4, ++ HDMI_INFOFRAME_AVI_DB5PR_6 = 5, ++ HDMI_INFOFRAME_AVI_DB5PR_7 = 6, ++ HDMI_INFOFRAME_AVI_DB5PR_8 = 7, ++ HDMI_INFOFRAME_AVI_DB5PR_9 = 8, ++ HDMI_INFOFRAME_AVI_DB5PR_10 = 9, ++}; ++ ++struct hdmi_cm { ++ int code; ++ int mode; ++}; ++ ++struct hdmi_video_format { ++ enum hdmi_packing_mode packing_mode; ++ u32 y_res; /* Line per panel */ ++ u32 x_res; /* pixel per line */ ++}; ++ ++struct hdmi_config { ++ struct omap_video_timings timings; ++ struct hdmi_cm cm; ++}; ++ ++/* HDMI PLL structure */ ++struct hdmi_pll_info { ++ u16 regn; ++ u16 regm; ++ u32 regmf; ++ u16 regm2; ++ u16 regsd; ++ u16 dcofreq; ++ enum hdmi_clk_refsel refsel; ++}; ++ ++struct hdmi_audio_format { ++ enum hdmi_stereo_channels stereo_channels; ++ u8 active_chnnls_msk; ++ enum hdmi_audio_type type; ++ enum hdmi_audio_justify justification; ++ enum hdmi_audio_sample_order sample_order; ++ enum hdmi_audio_samples_perword samples_per_word; ++ enum hdmi_audio_sample_size sample_size; ++ enum hdmi_audio_blk_strt_end_sig en_sig_blk_strt_end; ++}; ++ ++struct hdmi_audio_dma { ++ u8 transfer_size; ++ u8 block_size; ++ enum hdmi_audio_transf_mode mode; ++ u16 fifo_threshold; ++}; ++ ++struct hdmi_core_audio_i2s_config { ++ u8 in_length_bits; ++ u8 justification; ++ u8 sck_edge_mode; ++ u8 vbit; ++ u8 direction; ++ u8 shift; ++ u8 active_sds; ++}; ++ ++struct hdmi_core_audio_config { ++ struct hdmi_core_audio_i2s_config i2s_cfg; ++ struct snd_aes_iec958 *iec60958_cfg; ++ bool fs_override; ++ u32 n; ++ u32 cts; ++ u32 aud_par_busclk; ++ enum hdmi_core_audio_layout layout; ++ enum hdmi_core_cts_mode cts_mode; ++ bool use_mclk; ++ enum hdmi_audio_mclk_mode mclk_mode; ++ bool en_acr_pkt; ++ bool en_dsd_audio; ++ bool en_parallel_aud_input; ++ bool en_spdif; ++}; ++ ++/* ++ * Refer to section 8.2 in HDMI 1.3 specification for ++ * details about infoframe databytes ++ */ ++struct hdmi_core_infoframe_avi { ++ /* Y0, Y1 rgb,yCbCr */ ++ u8 db1_format; ++ /* A0 Active information Present */ ++ u8 db1_active_info; ++ /* B0, B1 Bar info data valid */ ++ u8 db1_bar_info_dv; ++ /* S0, S1 scan information */ ++ u8 db1_scan_info; ++ /* C0, C1 colorimetry */ ++ u8 db2_colorimetry; ++ /* M0, M1 Aspect ratio (4:3, 16:9) */ ++ u8 db2_aspect_ratio; ++ /* R0...R3 Active format aspect ratio */ ++ u8 db2_active_fmt_ar; ++ /* ITC IT content. */ ++ u8 db3_itc; ++ /* EC0, EC1, EC2 Extended colorimetry */ ++ u8 db3_ec; ++ /* Q1, Q0 Quantization range */ ++ u8 db3_q_range; ++ /* SC1, SC0 Non-uniform picture scaling */ ++ u8 db3_nup_scaling; ++ /* VIC0..6 Video format identification */ ++ u8 db4_videocode; ++ /* PR0..PR3 Pixel repetition factor */ ++ u8 db5_pixel_repeat; ++ /* Line number end of top bar */ ++ u16 db6_7_line_eoftop; ++ /* Line number start of bottom bar */ ++ u16 db8_9_line_sofbottom; ++ /* Pixel number end of left bar */ ++ u16 db10_11_pixel_eofleft; ++ /* Pixel number start of right bar */ ++ u16 db12_13_pixel_sofright; ++}; ++ ++struct hdmi_wp_data { ++ void __iomem *base; ++}; ++ ++struct hdmi_pll_data { ++ void __iomem *base; ++ ++ struct hdmi_pll_info info; ++}; ++ ++struct hdmi_phy_data { ++ void __iomem *base; ++}; ++ ++struct hdmi_core_data { ++ void __iomem *base; ++ ++ struct hdmi_core_infoframe_avi avi_cfg; ++}; ++ ++static inline void hdmi_write_reg(void __iomem *base_addr, const u32 idx, ++ u32 val) ++{ ++ __raw_writel(val, base_addr + idx); ++} ++ ++static inline u32 hdmi_read_reg(void __iomem *base_addr, const u32 idx) ++{ ++ return __raw_readl(base_addr + idx); ++} ++ ++#define REG_FLD_MOD(base, idx, val, start, end) \ ++ hdmi_write_reg(base, idx, FLD_MOD(hdmi_read_reg(base, idx),\ ++ val, start, end)) ++#define REG_GET(base, idx, start, end) \ ++ FLD_GET(hdmi_read_reg(base, idx), start, end) ++ ++static inline int hdmi_wait_for_bit_change(void __iomem *base_addr, ++ const u32 idx, int b2, int b1, u32 val) ++{ ++ u32 t = 0, v; ++ while (val != (v = REG_GET(base_addr, idx, b2, b1))) { ++ if (t++ > 10000) ++ return v; ++ udelay(1); ++ } ++ return v; ++} ++ ++/* HDMI wrapper funcs */ ++int hdmi_wp_video_start(struct hdmi_wp_data *wp); ++void hdmi_wp_video_stop(struct hdmi_wp_data *wp); ++void hdmi_wp_dump(struct hdmi_wp_data *wp, struct seq_file *s); ++u32 hdmi_wp_get_irqstatus(struct hdmi_wp_data *wp); ++void hdmi_wp_set_irqstatus(struct hdmi_wp_data *wp, u32 irqstatus); ++void hdmi_wp_set_irqenable(struct hdmi_wp_data *wp, u32 mask); ++void hdmi_wp_clear_irqenable(struct hdmi_wp_data *wp, u32 mask); ++int hdmi_wp_set_phy_pwr(struct hdmi_wp_data *wp, enum hdmi_phy_pwr val); ++int hdmi_wp_set_pll_pwr(struct hdmi_wp_data *wp, enum hdmi_pll_pwr val); ++void hdmi_wp_video_config_format(struct hdmi_wp_data *wp, ++ struct hdmi_video_format *video_fmt); ++void hdmi_wp_video_config_interface(struct hdmi_wp_data *wp, ++ struct omap_video_timings *timings); ++void hdmi_wp_video_config_timing(struct hdmi_wp_data *wp, ++ struct omap_video_timings *timings); ++void hdmi_wp_init_vid_fmt_timings(struct hdmi_video_format *video_fmt, ++ struct omap_video_timings *timings, struct hdmi_config *param); ++int hdmi_wp_init(struct platform_device *pdev, struct hdmi_wp_data *wp); ++ ++/* HDMI PLL funcs */ ++int hdmi_pll_enable(struct hdmi_pll_data *pll, struct hdmi_wp_data *wp); ++void hdmi_pll_disable(struct hdmi_pll_data *pll, struct hdmi_wp_data *wp); ++void hdmi_pll_dump(struct hdmi_pll_data *pll, struct seq_file *s); ++void hdmi_pll_compute(struct hdmi_pll_data *pll, unsigned long clkin, int phy); ++int hdmi_pll_init(struct platform_device *pdev, struct hdmi_pll_data *pll); ++ ++/* HDMI PHY funcs */ ++int hdmi_phy_configure(struct hdmi_phy_data *phy, struct hdmi_config *cfg); ++void hdmi_phy_dump(struct hdmi_phy_data *phy, struct seq_file *s); ++int hdmi_phy_init(struct platform_device *pdev, struct hdmi_phy_data *phy); ++ ++/* HDMI common funcs */ ++const struct hdmi_config *hdmi_default_timing(void); ++const struct hdmi_config *hdmi_get_timings(int mode, int code); ++struct hdmi_cm hdmi_get_code(struct omap_video_timings *timing); ++ ++#if defined(CONFIG_OMAP4_DSS_HDMI_AUDIO) || defined(CONFIG_OMAP5_DSS_HDMI_AUDIO) ++int hdmi_compute_acr(u32 pclk, u32 sample_freq, u32 *n, u32 *cts); ++int hdmi_wp_audio_enable(struct hdmi_wp_data *wp, bool enable); ++int hdmi_wp_audio_core_req_enable(struct hdmi_wp_data *wp, bool enable); ++void hdmi_wp_audio_config_format(struct hdmi_wp_data *wp, ++ struct hdmi_audio_format *aud_fmt); ++void hdmi_wp_audio_config_dma(struct hdmi_wp_data *wp, ++ struct hdmi_audio_dma *aud_dma); ++static inline bool hdmi_mode_has_audio(int mode) ++{ ++ return mode == HDMI_HDMI ? true : false; ++} ++#endif ++#endif +--- /dev/null ++++ b/drivers/video/omap2/dss/hdmi_phy.c +@@ -0,0 +1,167 @@ ++/* ++ * HDMI PHY ++ * ++ * Copyright (C) 2013 Texas Instruments Incorporated ++ * ++ * 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/err.h> ++#include <linux/io.h> ++#include <linux/platform_device.h> ++#include <linux/slab.h> ++#include <video/omapdss.h> ++ ++#include "dss.h" ++#include "hdmi.h" ++ ++struct hdmi_phy_features { ++ bool bist_ctrl; ++ bool calc_freqout; ++ bool ldo_voltage; ++ unsigned long dcofreq_min; /* in KHz */ ++ unsigned long max_phy; /* in KHz */ ++}; ++ ++static const struct hdmi_phy_features *phy_feat; ++ ++void hdmi_phy_dump(struct hdmi_phy_data *phy, struct seq_file *s) ++{ ++#define DUMPPHY(r) seq_printf(s, "%-35s %08x\n", #r,\ ++ hdmi_read_reg(phy->base, r)) ++ ++ DUMPPHY(HDMI_TXPHY_TX_CTRL); ++ DUMPPHY(HDMI_TXPHY_DIGITAL_CTRL); ++ DUMPPHY(HDMI_TXPHY_POWER_CTRL); ++ DUMPPHY(HDMI_TXPHY_PAD_CFG_CTRL); ++ if (phy_feat->bist_ctrl) ++ DUMPPHY(HDMI_TXPHY_BIST_CONTROL); ++} ++ ++int hdmi_phy_configure(struct hdmi_phy_data *phy, struct hdmi_config *cfg) ++{ ++ u8 freqout; ++ ++ /* ++ * Read address 0 in order to get the SCP reset done completed ++ * Dummy access performed to make sure reset is done ++ */ ++ hdmi_read_reg(phy->base, HDMI_TXPHY_TX_CTRL); ++ ++ /* ++ * In OMAP5+, the HFBITCLK must be divided by 2 before issuing the ++ * HDMI_PHYPWRCMD_LDOON command. ++ */ ++ if (phy_feat->bist_ctrl) ++ REG_FLD_MOD(phy->base, HDMI_TXPHY_BIST_CONTROL, 1, 11, 11); ++ ++ if (phy_feat->calc_freqout) { ++ /* DCOCLK/10 is pixel clock, compare pclk with DCOCLK_MIN/10 */ ++ u32 dco_min = phy_feat->dcofreq_min / 10; ++ u32 pclk = cfg->timings.pixel_clock; ++ ++ if (pclk < dco_min) { ++ freqout = 0; ++ } else if ((pclk >= dco_min) && (pclk < phy_feat->max_phy)) { ++ freqout = 1; ++ } else { ++ freqout = 2; ++ } ++ } else { ++ freqout = 1; ++ } ++ ++ /* ++ * Write to phy address 0 to configure the clock ++ * use HFBITCLK write HDMI_TXPHY_TX_CONTROL_FREQOUT field ++ */ ++ REG_FLD_MOD(phy->base, HDMI_TXPHY_TX_CTRL, freqout, 31, 30); ++ ++ /* Write to phy address 1 to start HDMI line (TXVALID and TMDSCLKEN) */ ++ hdmi_write_reg(phy->base, HDMI_TXPHY_DIGITAL_CTRL, 0xF0000000); ++ ++ /* Setup max LDO voltage */ ++ if (phy_feat->ldo_voltage) ++ REG_FLD_MOD(phy->base, HDMI_TXPHY_POWER_CTRL, 0xB, 3, 0); ++ ++ /* Write to phy address 3 to change the polarity control */ ++ REG_FLD_MOD(phy->base, HDMI_TXPHY_PAD_CFG_CTRL, 0x1, 27, 27); ++ ++ return 0; ++} ++ ++static const struct hdmi_phy_features omap44xx_phy_feats = { ++ .bist_ctrl = false, ++ .calc_freqout = false, ++ .ldo_voltage = true, ++ .dcofreq_min = 500000, ++ .max_phy = 185675, ++}; ++ ++static const struct hdmi_phy_features omap54xx_phy_feats = { ++ .bist_ctrl = true, ++ .calc_freqout = true, ++ .ldo_voltage = false, ++ .dcofreq_min = 750000, ++ .max_phy = 186000, ++}; ++ ++static int hdmi_phy_init_features(struct platform_device *pdev) ++{ ++ struct hdmi_phy_features *dst; ++ const struct hdmi_phy_features *src; ++ ++ dst = devm_kzalloc(&pdev->dev, sizeof(*dst), GFP_KERNEL); ++ if (!dst) { ++ dev_err(&pdev->dev, "Failed to allocate HDMI PHY Features\n"); ++ return -ENOMEM; ++ } ++ ++ switch (omapdss_get_version()) { ++ case OMAPDSS_VER_OMAP4430_ES1: ++ case OMAPDSS_VER_OMAP4430_ES2: ++ case OMAPDSS_VER_OMAP4: ++ src = &omap44xx_phy_feats; ++ break; ++ ++ case OMAPDSS_VER_OMAP5: ++ case OMAPDSS_VER_DRA7xx: ++ src = &omap54xx_phy_feats; ++ break; ++ ++ default: ++ return -ENODEV; ++ } ++ ++ memcpy(dst, src, sizeof(*dst)); ++ phy_feat = dst; ++ ++ return 0; ++} ++ ++int hdmi_phy_init(struct platform_device *pdev, struct hdmi_phy_data *phy) ++{ ++ int r; ++ struct resource *res; ++ ++ r = hdmi_phy_init_features(pdev); ++ if (r) ++ return r; ++ ++ res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "hdmi_txphy"); ++ if (!res) { ++ DSSERR("can't get PLL CTRL IORESOURCE_MEM HDMI\n"); ++ return -EINVAL; ++ } ++ ++ phy->base = devm_request_and_ioremap(&pdev->dev, res); ++ if (!phy->base) { ++ DSSERR("can't ioremap PLL ctrl\n"); ++ return -ENOMEM; ++ } ++ ++ return 0; ++} +--- /dev/null ++++ b/drivers/video/omap2/dss/hdmi_pll.c +@@ -0,0 +1,315 @@ ++/* ++ * HDMI PLL ++ * ++ * Copyright (C) 2013 Texas Instruments Incorporated ++ * ++ * 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/err.h> ++#include <linux/io.h> ++#include <linux/platform_device.h> ++#include <video/omapdss.h> ++ ++#include "dss.h" ++#include "hdmi.h" ++ ++#define HDMI_DEFAULT_REGN 16 ++#define HDMI_DEFAULT_REGM2 1 ++ ++struct hdmi_pll_features { ++ bool sys_reset; ++ /* this is a hack, need to replace it with a better computation of M2 */ ++ bool bound_dcofreq; ++ bool ext_mux_ctrl; ++ ++ unsigned long fint_min, fint_max; ++ u16 regm_max; ++ unsigned long dcofreq_low_min, dcofreq_low_max; ++ unsigned long dcofreq_high_min, dcofreq_high_max; ++}; ++ ++static const struct hdmi_pll_features *pll_feat; ++ ++void hdmi_pll_dump(struct hdmi_pll_data *pll, struct seq_file *s) ++{ ++#define DUMPPLL(r) seq_printf(s, "%-35s %08x\n", #r,\ ++ hdmi_read_reg(pll->base, r)) ++ ++ DUMPPLL(PLLCTRL_PLL_CONTROL); ++ DUMPPLL(PLLCTRL_PLL_STATUS); ++ DUMPPLL(PLLCTRL_PLL_GO); ++ DUMPPLL(PLLCTRL_CFG1); ++ DUMPPLL(PLLCTRL_CFG2); ++ DUMPPLL(PLLCTRL_CFG3); ++ DUMPPLL(PLLCTRL_SSC_CFG1); ++ DUMPPLL(PLLCTRL_SSC_CFG2); ++ DUMPPLL(PLLCTRL_CFG4); ++} ++ ++void hdmi_pll_compute(struct hdmi_pll_data *pll, unsigned long clkin, int phy) ++{ ++ struct hdmi_pll_info *pi = &pll->info; ++ unsigned long refclk; ++ u32 mf; ++ ++ /* use our funky units */ ++ clkin /= 10000; ++ ++ /* ++ * Input clock is predivided by N + 1 ++ * out put of which is reference clk ++ */ ++ ++ pi->regn = HDMI_DEFAULT_REGN; ++ ++ refclk = clkin / pi->regn; ++ ++ /* temorary hack to make sure DCO freq isn't calculated too low */ ++ if (pll_feat->bound_dcofreq && phy <= 65000) ++ pi->regm2 = 3; ++ else ++ pi->regm2 = HDMI_DEFAULT_REGM2; ++ ++ /* ++ * multiplier is pixel_clk/ref_clk ++ * Multiplying by 100 to avoid fractional part removal ++ */ ++ pi->regm = phy * pi->regm2 / refclk; ++ ++ /* ++ * fractional multiplier is remainder of the difference between ++ * multiplier and actual phy(required pixel clock thus should be ++ * multiplied by 2^18(262144) divided by the reference clock ++ */ ++ mf = (phy - pi->regm / pi->regm2 * refclk) * 262144; ++ pi->regmf = pi->regm2 * mf / refclk; ++ ++ /* ++ * Dcofreq should be set to 1 if required pixel clock ++ * is greater than 1000MHz ++ */ ++ pi->dcofreq = phy > 1000 * 100; ++ pi->regsd = ((pi->regm * clkin / 10) / (pi->regn * 250) + 5) / 10; ++ ++ /* Set the reference clock to sysclk reference */ ++ pi->refsel = HDMI_REFSEL_SYSCLK; ++ ++ DSSDBG("M = %d Mf = %d\n", pi->regm, pi->regmf); ++ DSSDBG("range = %d sd = %d\n", pi->dcofreq, pi->regsd); ++} ++ ++ ++static int hdmi_pll_config(struct hdmi_pll_data *pll) ++{ ++ u32 r; ++ struct hdmi_pll_info *fmt = &pll->info; ++ ++ /* PLL start always use manual mode */ ++ REG_FLD_MOD(pll->base, PLLCTRL_PLL_CONTROL, 0x0, 0, 0); ++ ++ r = hdmi_read_reg(pll->base, PLLCTRL_CFG1); ++ r = FLD_MOD(r, fmt->regm, 20, 9); /* CFG1_PLL_REGM */ ++ r = FLD_MOD(r, fmt->regn - 1, 8, 1); /* CFG1_PLL_REGN */ ++ hdmi_write_reg(pll->base, PLLCTRL_CFG1, r); ++ ++ r = hdmi_read_reg(pll->base, PLLCTRL_CFG2); ++ ++ r = FLD_MOD(r, 0x0, 12, 12); /* PLL_HIGHFREQ divide by 2 */ ++ r = FLD_MOD(r, 0x1, 13, 13); /* PLL_REFEN */ ++ r = FLD_MOD(r, 0x0, 14, 14); /* PHY_CLKINEN de-assert during locking */ ++ r = FLD_MOD(r, fmt->refsel, 22, 21); /* REFSEL */ ++ ++ if (fmt->dcofreq) { ++ /* divider programming for frequency beyond 1000Mhz */ ++ REG_FLD_MOD(pll->base, PLLCTRL_CFG3, fmt->regsd, 17, 10); ++ r = FLD_MOD(r, 0x4, 3, 1); /* 1000MHz and 2000MHz */ ++ } else { ++ r = FLD_MOD(r, 0x2, 3, 1); /* 500MHz and 1000MHz */ ++ } ++ ++ hdmi_write_reg(pll->base, PLLCTRL_CFG2, r); ++ ++ r = hdmi_read_reg(pll->base, PLLCTRL_CFG4); ++ r = FLD_MOD(r, fmt->regm2, 24, 18); ++ r = FLD_MOD(r, fmt->regmf, 17, 0); ++ hdmi_write_reg(pll->base, PLLCTRL_CFG4, r); ++ ++ /* go now */ ++ REG_FLD_MOD(pll->base, PLLCTRL_PLL_GO, 0x1, 0, 0); ++ ++ /* wait for bit change */ ++ if (hdmi_wait_for_bit_change(pll->base, PLLCTRL_PLL_GO, ++ 0, 0, 1) != 1) { ++ pr_err("PLL GO bit not set\n"); ++ return -ETIMEDOUT; ++ } ++ ++ /* Wait till the lock bit is set in PLL status */ ++ if (hdmi_wait_for_bit_change(pll->base, ++ PLLCTRL_PLL_STATUS, 1, 1, 1) != 1) { ++ pr_err("cannot lock PLL\n"); ++ pr_err("CFG1 0x%x\n", ++ hdmi_read_reg(pll->base, PLLCTRL_CFG1)); ++ pr_err("CFG2 0x%x\n", ++ hdmi_read_reg(pll->base, PLLCTRL_CFG2)); ++ pr_err("CFG4 0x%x\n", ++ hdmi_read_reg(pll->base, PLLCTRL_CFG4)); ++ return -ETIMEDOUT; ++ } ++ ++ pr_debug("PLL locked!\n"); ++ ++ return 0; ++} ++ ++static int hdmi_pll_reset(struct hdmi_pll_data *pll) ++{ ++ /* SYSRESET controlled by power FSM */ ++ REG_FLD_MOD(pll->base, PLLCTRL_PLL_CONTROL, pll_feat->sys_reset, 3, 3); ++ ++ /* READ 0x0 reset is in progress */ ++ if (hdmi_wait_for_bit_change(pll->base, PLLCTRL_PLL_STATUS, 0, 0, 1) ++ != 1) { ++ pr_err("Failed to sysreset PLL\n"); ++ return -ETIMEDOUT; ++ } ++ ++ return 0; ++} ++ ++int hdmi_pll_enable(struct hdmi_pll_data *pll, struct hdmi_wp_data *wp) ++{ ++ u16 r = 0; ++ ++ if (pll_feat->ext_mux_ctrl) ++ dss_dpll_enable_ctrl(DSS_DPLL_HDMI, true); ++ ++ r = hdmi_wp_set_pll_pwr(wp, HDMI_PLLPWRCMD_ALLOFF); ++ if (r) ++ return r; ++ ++ r = hdmi_wp_set_pll_pwr(wp, HDMI_PLLPWRCMD_BOTHON_ALLCLKS); ++ if (r) ++ return r; ++ ++ r = hdmi_pll_reset(pll); ++ if (r) ++ return r; ++ ++ r = hdmi_pll_config(pll); ++ if (r) ++ return r; ++ ++ return 0; ++} ++ ++void hdmi_pll_disable(struct hdmi_pll_data *pll, struct hdmi_wp_data *wp) ++{ ++ if (pll_feat->ext_mux_ctrl) ++ dss_dpll_enable_ctrl(DSS_DPLL_HDMI, false); ++ ++ hdmi_wp_set_pll_pwr(wp, HDMI_PLLPWRCMD_ALLOFF); ++} ++ ++static const struct hdmi_pll_features omap44xx_pll_feats = { ++ .sys_reset = false, ++ .bound_dcofreq = false, ++ .ext_mux_ctrl = false, ++ .fint_min = 500000, ++ .fint_max = 2500000, ++ .regm_max = 4095, ++ .dcofreq_low_min = 500000000, ++ .dcofreq_low_max = 1000000000, ++ .dcofreq_high_min = 1000000000, ++ .dcofreq_high_max = 2000000000, ++}; ++ ++static const struct hdmi_pll_features omap54xx_pll_feats = { ++ .sys_reset = true, ++ .bound_dcofreq = true, ++ .ext_mux_ctrl = false, ++ .fint_min = 620000, ++ .fint_max = 2500000, ++ .regm_max = 2046, ++ .dcofreq_low_min = 750000000, ++ .dcofreq_low_max = 1500000000, ++ .dcofreq_high_min = 1250000000, ++ .dcofreq_high_max = 2500000000UL, ++}; ++ ++static const struct hdmi_pll_features dra7xx_pll_feats = { ++ .sys_reset = true, ++ .bound_dcofreq = true, ++ .ext_mux_ctrl = true, ++ .fint_min = 620000, ++ .fint_max = 2500000, ++ .regm_max = 2046, ++ .dcofreq_low_min = 750000000, ++ .dcofreq_low_max = 1500000000, ++ .dcofreq_high_min = 1250000000, ++ .dcofreq_high_max = 2500000000UL, ++}; ++ ++static int hdmi_pll_init_features(struct platform_device *pdev) ++{ ++ struct hdmi_pll_features *dst; ++ const struct hdmi_pll_features *src; ++ ++ dst = devm_kzalloc(&pdev->dev, sizeof(*dst), GFP_KERNEL); ++ if (!dst) { ++ dev_err(&pdev->dev, "Failed to allocate HDMI PHY Features\n"); ++ return -ENOMEM; ++ } ++ ++ switch (omapdss_get_version()) { ++ case OMAPDSS_VER_OMAP4430_ES1: ++ case OMAPDSS_VER_OMAP4430_ES2: ++ case OMAPDSS_VER_OMAP4: ++ src = &omap44xx_pll_feats; ++ break; ++ ++ case OMAPDSS_VER_OMAP5: ++ src = &omap54xx_pll_feats; ++ break; ++ case OMAPDSS_VER_DRA7xx: ++ src = &dra7xx_pll_feats; ++ break; ++ ++ default: ++ return -ENODEV; ++ } ++ ++ memcpy(dst, src, sizeof(*dst)); ++ pll_feat = dst; ++ ++ return 0; ++} ++ ++int hdmi_pll_init(struct platform_device *pdev, struct hdmi_pll_data *pll) ++{ ++ int r; ++ struct resource *res; ++ ++ r = hdmi_pll_init_features(pdev); ++ if (r) ++ return r; ++ ++ res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "hdmi_pllctrl"); ++ if (!res) { ++ DSSERR("can't get PLL CTRL IORESOURCE_MEM HDMI\n"); ++ return -EINVAL; ++ } ++ ++ pll->base = devm_request_and_ioremap(&pdev->dev, res); ++ if (!pll->base) { ++ DSSERR("can't ioremap PLL ctrl\n"); ++ return -ENOMEM; ++ } ++ ++ return 0; ++} +--- /dev/null ++++ b/drivers/video/omap2/dss/hdmi_wp.c +@@ -0,0 +1,254 @@ ++/* ++ * HDMI wrapper ++ * ++ * Copyright (C) 2013 Texas Instruments Incorporated ++ * ++ * 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/err.h> ++#include <linux/io.h> ++#include <linux/platform_device.h> ++#include <video/omapdss.h> ++ ++#include "dss.h" ++#include "hdmi.h" ++ ++void hdmi_wp_dump(struct hdmi_wp_data *wp, struct seq_file *s) ++{ ++#define DUMPREG(r) seq_printf(s, "%-35s %08x\n", #r, hdmi_read_reg(wp->base, r)) ++ ++ DUMPREG(HDMI_WP_REVISION); ++ DUMPREG(HDMI_WP_SYSCONFIG); ++ DUMPREG(HDMI_WP_IRQSTATUS_RAW); ++ DUMPREG(HDMI_WP_IRQSTATUS); ++ DUMPREG(HDMI_WP_IRQENABLE_SET); ++ DUMPREG(HDMI_WP_IRQENABLE_CLR); ++ DUMPREG(HDMI_WP_IRQWAKEEN); ++ DUMPREG(HDMI_WP_PWR_CTRL); ++ DUMPREG(HDMI_WP_DEBOUNCE); ++ DUMPREG(HDMI_WP_VIDEO_CFG); ++ DUMPREG(HDMI_WP_VIDEO_SIZE); ++ DUMPREG(HDMI_WP_VIDEO_TIMING_H); ++ DUMPREG(HDMI_WP_VIDEO_TIMING_V); ++ DUMPREG(HDMI_WP_CLK); ++ DUMPREG(HDMI_WP_AUDIO_CFG); ++ DUMPREG(HDMI_WP_AUDIO_CFG2); ++ DUMPREG(HDMI_WP_AUDIO_CTRL); ++ DUMPREG(HDMI_WP_AUDIO_DATA); ++} ++ ++u32 hdmi_wp_get_irqstatus(struct hdmi_wp_data *wp) ++{ ++ return hdmi_read_reg(wp->base, HDMI_WP_IRQSTATUS); ++} ++ ++void hdmi_wp_set_irqstatus(struct hdmi_wp_data *wp, u32 irqstatus) ++{ ++ hdmi_write_reg(wp->base, HDMI_WP_IRQSTATUS, irqstatus); ++ /* flush posted write */ ++ hdmi_read_reg(wp->base, HDMI_WP_IRQSTATUS); ++} ++ ++void hdmi_wp_set_irqenable(struct hdmi_wp_data *wp, u32 mask) ++{ ++ hdmi_write_reg(wp->base, HDMI_WP_IRQENABLE_SET, mask); ++} ++ ++void hdmi_wp_clear_irqenable(struct hdmi_wp_data *wp, u32 mask) ++{ ++ hdmi_write_reg(wp->base, HDMI_WP_IRQENABLE_CLR, mask); ++} ++ ++/* PHY_PWR_CMD */ ++int hdmi_wp_set_phy_pwr(struct hdmi_wp_data *wp, enum hdmi_phy_pwr val) ++{ ++ /* Return if already the state */ ++ if (REG_GET(wp->base, HDMI_WP_PWR_CTRL, 5, 4) == val) ++ return 0; ++ ++ /* Command for power control of HDMI PHY */ ++ REG_FLD_MOD(wp->base, HDMI_WP_PWR_CTRL, val, 7, 6); ++ ++ /* Status of the power control of HDMI PHY */ ++ if (hdmi_wait_for_bit_change(wp->base, HDMI_WP_PWR_CTRL, 5, 4, val) ++ != val) { ++ pr_err("Failed to set PHY power mode to %d\n", val); ++ return -ETIMEDOUT; ++ } ++ ++ return 0; ++} ++ ++/* PLL_PWR_CMD */ ++int hdmi_wp_set_pll_pwr(struct hdmi_wp_data *wp, enum hdmi_pll_pwr val) ++{ ++ /* Command for power control of HDMI PLL */ ++ REG_FLD_MOD(wp->base, HDMI_WP_PWR_CTRL, val, 3, 2); ++ ++ /* wait till PHY_PWR_STATUS is set */ ++ if (hdmi_wait_for_bit_change(wp->base, HDMI_WP_PWR_CTRL, 1, 0, val) ++ != val) { ++ pr_err("Failed to set PLL_PWR_STATUS\n"); ++ return -ETIMEDOUT; ++ } ++ ++ return 0; ++} ++ ++int hdmi_wp_video_start(struct hdmi_wp_data *wp) ++{ ++ REG_FLD_MOD(wp->base, HDMI_WP_VIDEO_CFG, true, 31, 31); ++ ++ return 0; ++} ++ ++void hdmi_wp_video_stop(struct hdmi_wp_data *wp) ++{ ++ REG_FLD_MOD(wp->base, HDMI_WP_VIDEO_CFG, false, 31, 31); ++} ++ ++void hdmi_wp_video_config_format(struct hdmi_wp_data *wp, ++ struct hdmi_video_format *video_fmt) ++{ ++ u32 l = 0; ++ ++ REG_FLD_MOD(wp->base, HDMI_WP_VIDEO_CFG, video_fmt->packing_mode, ++ 10, 8); ++ ++ l |= FLD_VAL(video_fmt->y_res, 31, 16); ++ l |= FLD_VAL(video_fmt->x_res, 15, 0); ++ hdmi_write_reg(wp->base, HDMI_WP_VIDEO_SIZE, l); ++} ++ ++void hdmi_wp_video_config_interface(struct hdmi_wp_data *wp, ++ struct omap_video_timings *timings) ++{ ++ u32 r; ++ bool vsync_pol, hsync_pol; ++ pr_debug("Enter hdmi_wp_video_config_interface\n"); ++ ++ vsync_pol = timings->vsync_level == OMAPDSS_SIG_ACTIVE_HIGH; ++ hsync_pol = timings->hsync_level == OMAPDSS_SIG_ACTIVE_HIGH; ++ ++ r = hdmi_read_reg(wp->base, HDMI_WP_VIDEO_CFG); ++ r = FLD_MOD(r, vsync_pol, 7, 7); ++ r = FLD_MOD(r, hsync_pol, 6, 6); ++ r = FLD_MOD(r, timings->interlace, 3, 3); ++ r = FLD_MOD(r, 1, 1, 0); /* HDMI_TIMING_MASTER_24BIT */ ++ hdmi_write_reg(wp->base, HDMI_WP_VIDEO_CFG, r); ++} ++ ++void hdmi_wp_video_config_timing(struct hdmi_wp_data *wp, ++ struct omap_video_timings *timings) ++{ ++ u32 timing_h = 0; ++ u32 timing_v = 0; ++ ++ pr_debug("Enter hdmi_wp_video_config_timing\n"); ++ ++ timing_h |= FLD_VAL(timings->hbp, 31, 20); ++ timing_h |= FLD_VAL(timings->hfp, 19, 8); ++ timing_h |= FLD_VAL(timings->hsw, 7, 0); ++ hdmi_write_reg(wp->base, HDMI_WP_VIDEO_TIMING_H, timing_h); ++ ++ timing_v |= FLD_VAL(timings->vbp, 31, 20); ++ timing_v |= FLD_VAL(timings->vfp, 19, 8); ++ timing_v |= FLD_VAL(timings->vsw, 7, 0); ++ hdmi_write_reg(wp->base, HDMI_WP_VIDEO_TIMING_V, timing_v); ++} ++ ++void hdmi_wp_init_vid_fmt_timings(struct hdmi_video_format *video_fmt, ++ struct omap_video_timings *timings, struct hdmi_config *param) ++{ ++ pr_debug("Enter hdmi_wp_video_init_format\n"); ++ ++ video_fmt->packing_mode = HDMI_PACK_10b_RGB_YUV444; ++ video_fmt->y_res = param->timings.y_res; ++ video_fmt->x_res = param->timings.x_res; ++ ++ timings->hbp = param->timings.hbp; ++ timings->hfp = param->timings.hfp; ++ timings->hsw = param->timings.hsw; ++ timings->vbp = param->timings.vbp; ++ timings->vfp = param->timings.vfp; ++ timings->vsw = param->timings.vsw; ++ timings->vsync_level = param->timings.vsync_level; ++ timings->hsync_level = param->timings.hsync_level; ++ timings->interlace = param->timings.interlace; ++} ++ ++#if defined(CONFIG_OMAP4_DSS_HDMI_AUDIO) || defined(CONFIG_OMAP5_DSS_HDMI_AUDIO) ++void hdmi_wp_audio_config_format(struct hdmi_wp_data *wp, ++ struct hdmi_audio_format *aud_fmt) ++{ ++ u32 r; ++ ++ DSSDBG("Enter hdmi_wp_audio_config_format\n"); ++ ++ r = hdmi_read_reg(wp->base, HDMI_WP_AUDIO_CFG); ++ r = FLD_MOD(r, aud_fmt->stereo_channels, 26, 24); ++ r = FLD_MOD(r, aud_fmt->active_chnnls_msk, 23, 16); ++ r = FLD_MOD(r, aud_fmt->en_sig_blk_strt_end, 5, 5); ++ r = FLD_MOD(r, aud_fmt->type, 4, 4); ++ r = FLD_MOD(r, aud_fmt->justification, 3, 3); ++ r = FLD_MOD(r, aud_fmt->sample_order, 2, 2); ++ r = FLD_MOD(r, aud_fmt->samples_per_word, 1, 1); ++ r = FLD_MOD(r, aud_fmt->sample_size, 0, 0); ++ hdmi_write_reg(wp->base, HDMI_WP_AUDIO_CFG, r); ++} ++ ++void hdmi_wp_audio_config_dma(struct hdmi_wp_data *wp, ++ struct hdmi_audio_dma *aud_dma) ++{ ++ u32 r; ++ ++ DSSDBG("Enter hdmi_wp_audio_config_dma\n"); ++ ++ r = hdmi_read_reg(wp->base, HDMI_WP_AUDIO_CFG2); ++ r = FLD_MOD(r, aud_dma->transfer_size, 15, 8); ++ r = FLD_MOD(r, aud_dma->block_size, 7, 0); ++ hdmi_write_reg(wp->base, HDMI_WP_AUDIO_CFG2, r); ++ ++ r = hdmi_read_reg(wp->base, HDMI_WP_AUDIO_CTRL); ++ r = FLD_MOD(r, aud_dma->mode, 9, 9); ++ r = FLD_MOD(r, aud_dma->fifo_threshold, 8, 0); ++ hdmi_write_reg(wp->base, HDMI_WP_AUDIO_CTRL, r); ++} ++ ++int hdmi_wp_audio_enable(struct hdmi_wp_data *wp, bool enable) ++{ ++ REG_FLD_MOD(wp->base, HDMI_WP_AUDIO_CTRL, enable, 31, 31); ++ ++ return 0; ++} ++ ++int hdmi_wp_audio_core_req_enable(struct hdmi_wp_data *wp, bool enable) ++{ ++ REG_FLD_MOD(wp->base, HDMI_WP_AUDIO_CTRL, enable, 30, 30); ++ ++ return 0; ++} ++#endif ++ ++int hdmi_wp_init(struct platform_device *pdev, struct hdmi_wp_data *wp) ++{ ++ struct resource *res; ++ ++ res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "hdmi_wp"); ++ if (!res) { ++ DSSERR("can't get WP IORESOURCE_MEM HDMI\n"); ++ return -EINVAL; ++ } ++ ++ wp->base = devm_request_and_ioremap(&pdev->dev, res); ++ if (!wp->base) { ++ DSSERR("can't ioremap HDMI wrapper\n"); ++ return -ENOMEM; ++ } ++ ++ return 0; ++} +--- a/drivers/video/omap2/dss/Kconfig ++++ b/drivers/video/omap2/dss/Kconfig +@@ -40,6 +40,12 @@ config OMAP2_DSS_DPI + help + DPI Interface. This is the Parallel Display Interface. + ++config OMAP2_DSS_DRA7XX_DPI ++ bool "DRA75X DPI support" ++ default y ++ help ++ Vayu DPI Interface. This is the Parallel Display Interface. ++ + config OMAP2_DSS_RFBI + bool "RFBI support" + depends on BROKEN +@@ -69,6 +75,18 @@ config OMAP4_DSS_HDMI + config OMAP4_DSS_HDMI_AUDIO + bool + ++config OMAP5_DSS_HDMI ++ bool "OMAP5 HDMI support" ++ default y ++ help ++ HDMI Interface for OMAP5 and similar cores. This adds the High ++ Definition Multimedia Interface. See http://www.hdmi.org/ for HDMI ++ specification. ++ ++config OMAP5_DSS_HDMI_AUDIO ++ depends on OMAP5_DSS_HDMI ++ bool ++ + config OMAP2_DSS_SDI + bool "SDI support" + default n +--- a/drivers/video/omap2/dss/Makefile ++++ b/drivers/video/omap2/dss/Makefile +@@ -1,14 +1,18 @@ + obj-$(CONFIG_OMAP2_DSS) += omapdss.o + # Core DSS files +-omapdss-y := core.o dss.o dss_features.o dispc.o dispc_coefs.o display.o \ +- output.o ++omapdss-y := core.o dss.o dss_dpll.o dss_features.o dispc.o dispc_coefs.o \ ++ display.o output.o + # DSS compat layer files + omapdss-y += manager.o manager-sysfs.o overlay.o overlay-sysfs.o apply.o \ + dispc-compat.o display-sysfs.o + omapdss-$(CONFIG_OMAP2_DSS_DPI) += dpi.o ++omapdss-$(CONFIG_OMAP2_DSS_DRA7XX_DPI) += dra7xx_dpi.o + omapdss-$(CONFIG_OMAP2_DSS_RFBI) += rfbi.o + omapdss-$(CONFIG_OMAP2_DSS_VENC) += venc.o + omapdss-$(CONFIG_OMAP2_DSS_SDI) += sdi.o + omapdss-$(CONFIG_OMAP2_DSS_DSI) += dsi.o +-omapdss-$(CONFIG_OMAP4_DSS_HDMI) += hdmi.o ti_hdmi_4xxx_ip.o ++omapdss-$(CONFIG_OMAP4_DSS_HDMI) += hdmi4.o hdmi_common.o hdmi_wp.o hdmi_pll.o \ ++ hdmi_phy.o hdmi4_core.o ++omapdss-$(CONFIG_OMAP5_DSS_HDMI) += hdmi5.o hdmi_common.o hdmi_wp.o hdmi_pll.o \ ++ hdmi_phy.o hdmi5_core.o + ccflags-$(CONFIG_OMAP2_DSS_DEBUG) += -DDEBUG +--- a/drivers/video/omap2/dss/ti_hdmi_4xxx_ip.c ++++ /dev/null +@@ -1,1427 +0,0 @@ +-/* +- * ti_hdmi_4xxx_ip.c +- * +- * HDMI TI81xx, TI38xx, TI OMAP4 etc IP driver Library +- * Copyright (C) 2010-2011 Texas Instruments Incorporated - http://www.ti.com/ +- * Authors: Yong Zhi +- * Mythri pk <mythripk@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, see <http://www.gnu.org/licenses/>. +- */ +- +-#include <linux/kernel.h> +-#include <linux/module.h> +-#include <linux/err.h> +-#include <linux/io.h> +-#include <linux/interrupt.h> +-#include <linux/mutex.h> +-#include <linux/delay.h> +-#include <linux/string.h> +-#include <linux/seq_file.h> +-#if defined(CONFIG_OMAP4_DSS_HDMI_AUDIO) +-#include <sound/asound.h> +-#include <sound/asoundef.h> +-#endif +- +-#include "ti_hdmi_4xxx_ip.h" +-#include "dss.h" +-#include "dss_features.h" +- +-#define HDMI_IRQ_LINK_CONNECT (1 << 25) +-#define HDMI_IRQ_LINK_DISCONNECT (1 << 26) +- +-static inline void hdmi_write_reg(void __iomem *base_addr, +- const u16 idx, u32 val) +-{ +- __raw_writel(val, base_addr + idx); +-} +- +-static inline u32 hdmi_read_reg(void __iomem *base_addr, +- const u16 idx) +-{ +- return __raw_readl(base_addr + idx); +-} +- +-static inline void __iomem *hdmi_wp_base(struct hdmi_ip_data *ip_data) +-{ +- return ip_data->base_wp; +-} +- +-static inline void __iomem *hdmi_phy_base(struct hdmi_ip_data *ip_data) +-{ +- return ip_data->base_wp + ip_data->phy_offset; +-} +- +-static inline void __iomem *hdmi_pll_base(struct hdmi_ip_data *ip_data) +-{ +- return ip_data->base_wp + ip_data->pll_offset; +-} +- +-static inline void __iomem *hdmi_av_base(struct hdmi_ip_data *ip_data) +-{ +- return ip_data->base_wp + ip_data->core_av_offset; +-} +- +-static inline void __iomem *hdmi_core_sys_base(struct hdmi_ip_data *ip_data) +-{ +- return ip_data->base_wp + ip_data->core_sys_offset; +-} +- +-static inline int hdmi_wait_for_bit_change(void __iomem *base_addr, +- const u16 idx, +- int b2, int b1, u32 val) +-{ +- u32 t = 0; +- while (val != REG_GET(base_addr, idx, b2, b1)) { +- udelay(1); +- if (t++ > 10000) +- return !val; +- } +- return val; +-} +- +-static int hdmi_pll_init(struct hdmi_ip_data *ip_data) +-{ +- u32 r; +- void __iomem *pll_base = hdmi_pll_base(ip_data); +- struct hdmi_pll_info *fmt = &ip_data->pll_data; +- +- /* PLL start always use manual mode */ +- REG_FLD_MOD(pll_base, PLLCTRL_PLL_CONTROL, 0x0, 0, 0); +- +- r = hdmi_read_reg(pll_base, PLLCTRL_CFG1); +- r = FLD_MOD(r, fmt->regm, 20, 9); /* CFG1_PLL_REGM */ +- r = FLD_MOD(r, fmt->regn - 1, 8, 1); /* CFG1_PLL_REGN */ +- +- hdmi_write_reg(pll_base, PLLCTRL_CFG1, r); +- +- r = hdmi_read_reg(pll_base, PLLCTRL_CFG2); +- +- r = FLD_MOD(r, 0x0, 12, 12); /* PLL_HIGHFREQ divide by 2 */ +- r = FLD_MOD(r, 0x1, 13, 13); /* PLL_REFEN */ +- r = FLD_MOD(r, 0x0, 14, 14); /* PHY_CLKINEN de-assert during locking */ +- r = FLD_MOD(r, fmt->refsel, 22, 21); /* REFSEL */ +- +- if (fmt->dcofreq) { +- /* divider programming for frequency beyond 1000Mhz */ +- REG_FLD_MOD(pll_base, PLLCTRL_CFG3, fmt->regsd, 17, 10); +- r = FLD_MOD(r, 0x4, 3, 1); /* 1000MHz and 2000MHz */ +- } else { +- r = FLD_MOD(r, 0x2, 3, 1); /* 500MHz and 1000MHz */ +- } +- +- hdmi_write_reg(pll_base, PLLCTRL_CFG2, r); +- +- r = hdmi_read_reg(pll_base, PLLCTRL_CFG4); +- r = FLD_MOD(r, fmt->regm2, 24, 18); +- r = FLD_MOD(r, fmt->regmf, 17, 0); +- +- hdmi_write_reg(pll_base, PLLCTRL_CFG4, r); +- +- /* go now */ +- REG_FLD_MOD(pll_base, PLLCTRL_PLL_GO, 0x1, 0, 0); +- +- /* wait for bit change */ +- if (hdmi_wait_for_bit_change(pll_base, PLLCTRL_PLL_GO, +- 0, 0, 1) != 1) { +- pr_err("PLL GO bit not set\n"); +- return -ETIMEDOUT; +- } +- +- /* Wait till the lock bit is set in PLL status */ +- if (hdmi_wait_for_bit_change(pll_base, +- PLLCTRL_PLL_STATUS, 1, 1, 1) != 1) { +- pr_err("cannot lock PLL\n"); +- pr_err("CFG1 0x%x\n", +- hdmi_read_reg(pll_base, PLLCTRL_CFG1)); +- pr_err("CFG2 0x%x\n", +- hdmi_read_reg(pll_base, PLLCTRL_CFG2)); +- pr_err("CFG4 0x%x\n", +- hdmi_read_reg(pll_base, PLLCTRL_CFG4)); +- return -ETIMEDOUT; +- } +- +- pr_debug("PLL locked!\n"); +- +- return 0; +-} +- +-/* PHY_PWR_CMD */ +-static int hdmi_set_phy_pwr(struct hdmi_ip_data *ip_data, enum hdmi_phy_pwr val) +-{ +- /* Return if already the state */ +- if (REG_GET(hdmi_wp_base(ip_data), HDMI_WP_PWR_CTRL, 5, 4) == val) +- return 0; +- +- /* Command for power control of HDMI PHY */ +- REG_FLD_MOD(hdmi_wp_base(ip_data), HDMI_WP_PWR_CTRL, val, 7, 6); +- +- /* Status of the power control of HDMI PHY */ +- if (hdmi_wait_for_bit_change(hdmi_wp_base(ip_data), +- HDMI_WP_PWR_CTRL, 5, 4, val) != val) { +- pr_err("Failed to set PHY power mode to %d\n", val); +- return -ETIMEDOUT; +- } +- +- return 0; +-} +- +-/* PLL_PWR_CMD */ +-static int hdmi_set_pll_pwr(struct hdmi_ip_data *ip_data, enum hdmi_pll_pwr val) +-{ +- /* Command for power control of HDMI PLL */ +- REG_FLD_MOD(hdmi_wp_base(ip_data), HDMI_WP_PWR_CTRL, val, 3, 2); +- +- /* wait till PHY_PWR_STATUS is set */ +- if (hdmi_wait_for_bit_change(hdmi_wp_base(ip_data), HDMI_WP_PWR_CTRL, +- 1, 0, val) != val) { +- pr_err("Failed to set PLL_PWR_STATUS\n"); +- return -ETIMEDOUT; +- } +- +- return 0; +-} +- +-static int hdmi_pll_reset(struct hdmi_ip_data *ip_data) +-{ +- /* SYSRESET controlled by power FSM */ +- REG_FLD_MOD(hdmi_pll_base(ip_data), PLLCTRL_PLL_CONTROL, 0x0, 3, 3); +- +- /* READ 0x0 reset is in progress */ +- if (hdmi_wait_for_bit_change(hdmi_pll_base(ip_data), +- PLLCTRL_PLL_STATUS, 0, 0, 1) != 1) { +- pr_err("Failed to sysreset PLL\n"); +- return -ETIMEDOUT; +- } +- +- return 0; +-} +- +-int ti_hdmi_4xxx_pll_enable(struct hdmi_ip_data *ip_data) +-{ +- u16 r = 0; +- +- r = hdmi_set_pll_pwr(ip_data, HDMI_PLLPWRCMD_ALLOFF); +- if (r) +- return r; +- +- r = hdmi_set_pll_pwr(ip_data, HDMI_PLLPWRCMD_BOTHON_ALLCLKS); +- if (r) +- return r; +- +- r = hdmi_pll_reset(ip_data); +- if (r) +- return r; +- +- r = hdmi_pll_init(ip_data); +- if (r) +- return r; +- +- return 0; +-} +- +-void ti_hdmi_4xxx_pll_disable(struct hdmi_ip_data *ip_data) +-{ +- hdmi_set_pll_pwr(ip_data, HDMI_PLLPWRCMD_ALLOFF); +-} +- +-static irqreturn_t hdmi_irq_handler(int irq, void *data) +-{ +- struct hdmi_ip_data *ip_data = data; +- void __iomem *wp_base = hdmi_wp_base(ip_data); +- u32 irqstatus; +- +- irqstatus = hdmi_read_reg(wp_base, HDMI_WP_IRQSTATUS); +- hdmi_write_reg(wp_base, HDMI_WP_IRQSTATUS, irqstatus); +- /* flush posted write */ +- hdmi_read_reg(wp_base, HDMI_WP_IRQSTATUS); +- +- if ((irqstatus & HDMI_IRQ_LINK_CONNECT) && +- irqstatus & HDMI_IRQ_LINK_DISCONNECT) { +- /* +- * If we get both connect and disconnect interrupts at the same +- * time, turn off the PHY, clear interrupts, and restart, which +- * raises connect interrupt if a cable is connected, or nothing +- * if cable is not connected. +- */ +- hdmi_set_phy_pwr(ip_data, HDMI_PHYPWRCMD_OFF); +- +- hdmi_write_reg(wp_base, HDMI_WP_IRQSTATUS, +- HDMI_IRQ_LINK_CONNECT | HDMI_IRQ_LINK_DISCONNECT); +- /* flush posted write */ +- hdmi_read_reg(wp_base, HDMI_WP_IRQSTATUS); +- +- hdmi_set_phy_pwr(ip_data, HDMI_PHYPWRCMD_LDOON); +- } else if (irqstatus & HDMI_IRQ_LINK_CONNECT) { +- hdmi_set_phy_pwr(ip_data, HDMI_PHYPWRCMD_TXON); +- } else if (irqstatus & HDMI_IRQ_LINK_DISCONNECT) { +- hdmi_set_phy_pwr(ip_data, HDMI_PHYPWRCMD_LDOON); +- } +- +- return IRQ_HANDLED; +-} +- +-int ti_hdmi_4xxx_phy_enable(struct hdmi_ip_data *ip_data) +-{ +- u16 r = 0; +- void __iomem *phy_base = hdmi_phy_base(ip_data); +- +- hdmi_write_reg(hdmi_wp_base(ip_data), HDMI_WP_IRQENABLE_CLR, +- 0xffffffff); +- +- hdmi_write_reg(hdmi_wp_base(ip_data), HDMI_WP_IRQSTATUS, +- HDMI_IRQ_LINK_CONNECT | HDMI_IRQ_LINK_DISCONNECT); +- +- r = hdmi_set_phy_pwr(ip_data, HDMI_PHYPWRCMD_LDOON); +- if (r) +- return r; +- +- /* +- * Read address 0 in order to get the SCP reset done completed +- * Dummy access performed to make sure reset is done +- */ +- hdmi_read_reg(phy_base, HDMI_TXPHY_TX_CTRL); +- +- /* +- * Write to phy address 0 to configure the clock +- * use HFBITCLK write HDMI_TXPHY_TX_CONTROL_FREQOUT field +- */ +- REG_FLD_MOD(phy_base, HDMI_TXPHY_TX_CTRL, 0x1, 31, 30); +- +- /* Write to phy address 1 to start HDMI line (TXVALID and TMDSCLKEN) */ +- hdmi_write_reg(phy_base, HDMI_TXPHY_DIGITAL_CTRL, 0xF0000000); +- +- /* Setup max LDO voltage */ +- REG_FLD_MOD(phy_base, HDMI_TXPHY_POWER_CTRL, 0xB, 3, 0); +- +- /* Write to phy address 3 to change the polarity control */ +- REG_FLD_MOD(phy_base, HDMI_TXPHY_PAD_CFG_CTRL, 0x1, 27, 27); +- +- r = request_threaded_irq(ip_data->irq, NULL, hdmi_irq_handler, +- IRQF_ONESHOT, "OMAP HDMI", ip_data); +- if (r) { +- DSSERR("HDMI IRQ request failed\n"); +- hdmi_set_phy_pwr(ip_data, HDMI_PHYPWRCMD_OFF); +- return r; +- } +- +- hdmi_write_reg(hdmi_wp_base(ip_data), HDMI_WP_IRQENABLE_SET, +- HDMI_IRQ_LINK_CONNECT | HDMI_IRQ_LINK_DISCONNECT); +- +- return 0; +-} +- +-void ti_hdmi_4xxx_phy_disable(struct hdmi_ip_data *ip_data) +-{ +- free_irq(ip_data->irq, ip_data); +- +- hdmi_set_phy_pwr(ip_data, HDMI_PHYPWRCMD_OFF); +-} +- +-static int hdmi_core_ddc_init(struct hdmi_ip_data *ip_data) +-{ +- void __iomem *base = hdmi_core_sys_base(ip_data); +- +- /* Turn on CLK for DDC */ +- REG_FLD_MOD(base, HDMI_CORE_AV_DPD, 0x7, 2, 0); +- +- /* IN_PROG */ +- if (REG_GET(base, HDMI_CORE_DDC_STATUS, 4, 4) == 1) { +- /* Abort transaction */ +- REG_FLD_MOD(base, HDMI_CORE_DDC_CMD, 0xf, 3, 0); +- /* IN_PROG */ +- if (hdmi_wait_for_bit_change(base, HDMI_CORE_DDC_STATUS, +- 4, 4, 0) != 0) { +- DSSERR("Timeout aborting DDC transaction\n"); +- return -ETIMEDOUT; +- } +- } +- +- /* Clk SCL Devices */ +- REG_FLD_MOD(base, HDMI_CORE_DDC_CMD, 0xA, 3, 0); +- +- /* HDMI_CORE_DDC_STATUS_IN_PROG */ +- if (hdmi_wait_for_bit_change(base, HDMI_CORE_DDC_STATUS, +- 4, 4, 0) != 0) { +- DSSERR("Timeout starting SCL clock\n"); +- return -ETIMEDOUT; +- } +- +- /* Clear FIFO */ +- REG_FLD_MOD(base, HDMI_CORE_DDC_CMD, 0x9, 3, 0); +- +- /* HDMI_CORE_DDC_STATUS_IN_PROG */ +- if (hdmi_wait_for_bit_change(base, HDMI_CORE_DDC_STATUS, +- 4, 4, 0) != 0) { +- DSSERR("Timeout clearing DDC fifo\n"); +- return -ETIMEDOUT; +- } +- +- return 0; +-} +- +-static int hdmi_core_ddc_edid(struct hdmi_ip_data *ip_data, +- u8 *pedid, int ext) +-{ +- void __iomem *base = hdmi_core_sys_base(ip_data); +- u32 i; +- char checksum; +- u32 offset = 0; +- +- /* HDMI_CORE_DDC_STATUS_IN_PROG */ +- if (hdmi_wait_for_bit_change(base, HDMI_CORE_DDC_STATUS, +- 4, 4, 0) != 0) { +- DSSERR("Timeout waiting DDC to be ready\n"); +- return -ETIMEDOUT; +- } +- +- if (ext % 2 != 0) +- offset = 0x80; +- +- /* Load Segment Address Register */ +- REG_FLD_MOD(base, HDMI_CORE_DDC_SEGM, ext / 2, 7, 0); +- +- /* Load Slave Address Register */ +- REG_FLD_MOD(base, HDMI_CORE_DDC_ADDR, 0xA0 >> 1, 7, 1); +- +- /* Load Offset Address Register */ +- REG_FLD_MOD(base, HDMI_CORE_DDC_OFFSET, offset, 7, 0); +- +- /* Load Byte Count */ +- REG_FLD_MOD(base, HDMI_CORE_DDC_COUNT1, 0x80, 7, 0); +- REG_FLD_MOD(base, HDMI_CORE_DDC_COUNT2, 0x0, 1, 0); +- +- /* Set DDC_CMD */ +- if (ext) +- REG_FLD_MOD(base, HDMI_CORE_DDC_CMD, 0x4, 3, 0); +- else +- REG_FLD_MOD(base, HDMI_CORE_DDC_CMD, 0x2, 3, 0); +- +- /* HDMI_CORE_DDC_STATUS_BUS_LOW */ +- if (REG_GET(base, HDMI_CORE_DDC_STATUS, 6, 6) == 1) { +- pr_err("I2C Bus Low?\n"); +- return -EIO; +- } +- /* HDMI_CORE_DDC_STATUS_NO_ACK */ +- if (REG_GET(base, HDMI_CORE_DDC_STATUS, 5, 5) == 1) { +- pr_err("I2C No Ack\n"); +- return -EIO; +- } +- +- for (i = 0; i < 0x80; ++i) { +- int t; +- +- /* IN_PROG */ +- if (REG_GET(base, HDMI_CORE_DDC_STATUS, 4, 4) == 0) { +- DSSERR("operation stopped when reading edid\n"); +- return -EIO; +- } +- +- t = 0; +- /* FIFO_EMPTY */ +- while (REG_GET(base, HDMI_CORE_DDC_STATUS, 2, 2) == 1) { +- if (t++ > 10000) { +- DSSERR("timeout reading edid\n"); +- return -ETIMEDOUT; +- } +- udelay(1); +- } +- +- pedid[i] = REG_GET(base, HDMI_CORE_DDC_DATA, 7, 0); +- } +- +- checksum = 0; +- for (i = 0; i < 0x80; ++i) +- checksum += pedid[i]; +- +- if (checksum != 0) { +- pr_err("E-EDID checksum failed!!\n"); +- return -EIO; +- } +- +- return 0; +-} +- +-int ti_hdmi_4xxx_read_edid(struct hdmi_ip_data *ip_data, +- u8 *edid, int len) +-{ +- int r, l; +- +- if (len < 128) +- return -EINVAL; +- +- r = hdmi_core_ddc_init(ip_data); +- if (r) +- return r; +- +- r = hdmi_core_ddc_edid(ip_data, edid, 0); +- if (r) +- return r; +- +- l = 128; +- +- if (len >= 128 * 2 && edid[0x7e] > 0) { +- r = hdmi_core_ddc_edid(ip_data, edid + 0x80, 1); +- if (r) +- return r; +- l += 128; +- } +- +- return l; +-} +- +-static void hdmi_core_init(struct hdmi_core_video_config *video_cfg, +- struct hdmi_core_infoframe_avi *avi_cfg, +- struct hdmi_core_packet_enable_repeat *repeat_cfg) +-{ +- pr_debug("Enter hdmi_core_init\n"); +- +- /* video core */ +- video_cfg->ip_bus_width = HDMI_INPUT_8BIT; +- video_cfg->op_dither_truc = HDMI_OUTPUTTRUNCATION_8BIT; +- video_cfg->deep_color_pkt = HDMI_DEEPCOLORPACKECTDISABLE; +- video_cfg->pkt_mode = HDMI_PACKETMODERESERVEDVALUE; +- video_cfg->hdmi_dvi = HDMI_DVI; +- video_cfg->tclk_sel_clkmult = HDMI_FPLL10IDCK; +- +- /* info frame */ +- avi_cfg->db1_format = 0; +- avi_cfg->db1_active_info = 0; +- avi_cfg->db1_bar_info_dv = 0; +- avi_cfg->db1_scan_info = 0; +- avi_cfg->db2_colorimetry = 0; +- avi_cfg->db2_aspect_ratio = 0; +- avi_cfg->db2_active_fmt_ar = 0; +- avi_cfg->db3_itc = 0; +- avi_cfg->db3_ec = 0; +- avi_cfg->db3_q_range = 0; +- avi_cfg->db3_nup_scaling = 0; +- avi_cfg->db4_videocode = 0; +- avi_cfg->db5_pixel_repeat = 0; +- avi_cfg->db6_7_line_eoftop = 0 ; +- avi_cfg->db8_9_line_sofbottom = 0; +- avi_cfg->db10_11_pixel_eofleft = 0; +- avi_cfg->db12_13_pixel_sofright = 0; +- +- /* packet enable and repeat */ +- repeat_cfg->audio_pkt = 0; +- repeat_cfg->audio_pkt_repeat = 0; +- repeat_cfg->avi_infoframe = 0; +- repeat_cfg->avi_infoframe_repeat = 0; +- repeat_cfg->gen_cntrl_pkt = 0; +- repeat_cfg->gen_cntrl_pkt_repeat = 0; +- repeat_cfg->generic_pkt = 0; +- repeat_cfg->generic_pkt_repeat = 0; +-} +- +-static void hdmi_core_powerdown_disable(struct hdmi_ip_data *ip_data) +-{ +- pr_debug("Enter hdmi_core_powerdown_disable\n"); +- REG_FLD_MOD(hdmi_core_sys_base(ip_data), HDMI_CORE_CTRL1, 0x0, 0, 0); +-} +- +-static void hdmi_core_swreset_release(struct hdmi_ip_data *ip_data) +-{ +- pr_debug("Enter hdmi_core_swreset_release\n"); +- REG_FLD_MOD(hdmi_core_sys_base(ip_data), HDMI_CORE_SYS_SRST, 0x0, 0, 0); +-} +- +-static void hdmi_core_swreset_assert(struct hdmi_ip_data *ip_data) +-{ +- pr_debug("Enter hdmi_core_swreset_assert\n"); +- REG_FLD_MOD(hdmi_core_sys_base(ip_data), HDMI_CORE_SYS_SRST, 0x1, 0, 0); +-} +- +-/* HDMI_CORE_VIDEO_CONFIG */ +-static void hdmi_core_video_config(struct hdmi_ip_data *ip_data, +- struct hdmi_core_video_config *cfg) +-{ +- u32 r = 0; +- void __iomem *core_sys_base = hdmi_core_sys_base(ip_data); +- +- /* sys_ctrl1 default configuration not tunable */ +- r = hdmi_read_reg(core_sys_base, HDMI_CORE_CTRL1); +- r = FLD_MOD(r, HDMI_CORE_CTRL1_VEN_FOLLOWVSYNC, 5, 5); +- r = FLD_MOD(r, HDMI_CORE_CTRL1_HEN_FOLLOWHSYNC, 4, 4); +- r = FLD_MOD(r, HDMI_CORE_CTRL1_BSEL_24BITBUS, 2, 2); +- r = FLD_MOD(r, HDMI_CORE_CTRL1_EDGE_RISINGEDGE, 1, 1); +- hdmi_write_reg(core_sys_base, HDMI_CORE_CTRL1, r); +- +- REG_FLD_MOD(core_sys_base, +- HDMI_CORE_SYS_VID_ACEN, cfg->ip_bus_width, 7, 6); +- +- /* Vid_Mode */ +- r = hdmi_read_reg(core_sys_base, HDMI_CORE_SYS_VID_MODE); +- +- /* dither truncation configuration */ +- if (cfg->op_dither_truc > HDMI_OUTPUTTRUNCATION_12BIT) { +- r = FLD_MOD(r, cfg->op_dither_truc - 3, 7, 6); +- r = FLD_MOD(r, 1, 5, 5); +- } else { +- r = FLD_MOD(r, cfg->op_dither_truc, 7, 6); +- r = FLD_MOD(r, 0, 5, 5); +- } +- hdmi_write_reg(core_sys_base, HDMI_CORE_SYS_VID_MODE, r); +- +- /* HDMI_Ctrl */ +- r = hdmi_read_reg(hdmi_av_base(ip_data), HDMI_CORE_AV_HDMI_CTRL); +- r = FLD_MOD(r, cfg->deep_color_pkt, 6, 6); +- r = FLD_MOD(r, cfg->pkt_mode, 5, 3); +- r = FLD_MOD(r, cfg->hdmi_dvi, 0, 0); +- hdmi_write_reg(hdmi_av_base(ip_data), HDMI_CORE_AV_HDMI_CTRL, r); +- +- /* TMDS_CTRL */ +- REG_FLD_MOD(core_sys_base, +- HDMI_CORE_SYS_TMDS_CTRL, cfg->tclk_sel_clkmult, 6, 5); +-} +- +-static void hdmi_core_aux_infoframe_avi_config(struct hdmi_ip_data *ip_data) +-{ +- u32 val; +- char sum = 0, checksum = 0; +- void __iomem *av_base = hdmi_av_base(ip_data); +- struct hdmi_core_infoframe_avi info_avi = ip_data->avi_cfg; +- +- sum += 0x82 + 0x002 + 0x00D; +- hdmi_write_reg(av_base, HDMI_CORE_AV_AVI_TYPE, 0x082); +- hdmi_write_reg(av_base, HDMI_CORE_AV_AVI_VERS, 0x002); +- hdmi_write_reg(av_base, HDMI_CORE_AV_AVI_LEN, 0x00D); +- +- val = (info_avi.db1_format << 5) | +- (info_avi.db1_active_info << 4) | +- (info_avi.db1_bar_info_dv << 2) | +- (info_avi.db1_scan_info); +- hdmi_write_reg(av_base, HDMI_CORE_AV_AVI_DBYTE(0), val); +- sum += val; +- +- val = (info_avi.db2_colorimetry << 6) | +- (info_avi.db2_aspect_ratio << 4) | +- (info_avi.db2_active_fmt_ar); +- hdmi_write_reg(av_base, HDMI_CORE_AV_AVI_DBYTE(1), val); +- sum += val; +- +- val = (info_avi.db3_itc << 7) | +- (info_avi.db3_ec << 4) | +- (info_avi.db3_q_range << 2) | +- (info_avi.db3_nup_scaling); +- hdmi_write_reg(av_base, HDMI_CORE_AV_AVI_DBYTE(2), val); +- sum += val; +- +- hdmi_write_reg(av_base, HDMI_CORE_AV_AVI_DBYTE(3), +- info_avi.db4_videocode); +- sum += info_avi.db4_videocode; +- +- val = info_avi.db5_pixel_repeat; +- hdmi_write_reg(av_base, HDMI_CORE_AV_AVI_DBYTE(4), val); +- sum += val; +- +- val = info_avi.db6_7_line_eoftop & 0x00FF; +- hdmi_write_reg(av_base, HDMI_CORE_AV_AVI_DBYTE(5), val); +- sum += val; +- +- val = ((info_avi.db6_7_line_eoftop >> 8) & 0x00FF); +- hdmi_write_reg(av_base, HDMI_CORE_AV_AVI_DBYTE(6), val); +- sum += val; +- +- val = info_avi.db8_9_line_sofbottom & 0x00FF; +- hdmi_write_reg(av_base, HDMI_CORE_AV_AVI_DBYTE(7), val); +- sum += val; +- +- val = ((info_avi.db8_9_line_sofbottom >> 8) & 0x00FF); +- hdmi_write_reg(av_base, HDMI_CORE_AV_AVI_DBYTE(8), val); +- sum += val; +- +- val = info_avi.db10_11_pixel_eofleft & 0x00FF; +- hdmi_write_reg(av_base, HDMI_CORE_AV_AVI_DBYTE(9), val); +- sum += val; +- +- val = ((info_avi.db10_11_pixel_eofleft >> 8) & 0x00FF); +- hdmi_write_reg(av_base, HDMI_CORE_AV_AVI_DBYTE(10), val); +- sum += val; +- +- val = info_avi.db12_13_pixel_sofright & 0x00FF; +- hdmi_write_reg(av_base, HDMI_CORE_AV_AVI_DBYTE(11), val); +- sum += val; +- +- val = ((info_avi.db12_13_pixel_sofright >> 8) & 0x00FF); +- hdmi_write_reg(av_base, HDMI_CORE_AV_AVI_DBYTE(12), val); +- sum += val; +- +- checksum = 0x100 - sum; +- hdmi_write_reg(av_base, HDMI_CORE_AV_AVI_CHSUM, checksum); +-} +- +-static void hdmi_core_av_packet_config(struct hdmi_ip_data *ip_data, +- struct hdmi_core_packet_enable_repeat repeat_cfg) +-{ +- /* enable/repeat the infoframe */ +- hdmi_write_reg(hdmi_av_base(ip_data), HDMI_CORE_AV_PB_CTRL1, +- (repeat_cfg.audio_pkt << 5) | +- (repeat_cfg.audio_pkt_repeat << 4) | +- (repeat_cfg.avi_infoframe << 1) | +- (repeat_cfg.avi_infoframe_repeat)); +- +- /* enable/repeat the packet */ +- hdmi_write_reg(hdmi_av_base(ip_data), HDMI_CORE_AV_PB_CTRL2, +- (repeat_cfg.gen_cntrl_pkt << 3) | +- (repeat_cfg.gen_cntrl_pkt_repeat << 2) | +- (repeat_cfg.generic_pkt << 1) | +- (repeat_cfg.generic_pkt_repeat)); +-} +- +-static void hdmi_wp_init(struct omap_video_timings *timings, +- struct hdmi_video_format *video_fmt) +-{ +- pr_debug("Enter hdmi_wp_init\n"); +- +- timings->hbp = 0; +- timings->hfp = 0; +- timings->hsw = 0; +- timings->vbp = 0; +- timings->vfp = 0; +- timings->vsw = 0; +- +- video_fmt->packing_mode = HDMI_PACK_10b_RGB_YUV444; +- video_fmt->y_res = 0; +- video_fmt->x_res = 0; +- +-} +- +-int ti_hdmi_4xxx_wp_video_start(struct hdmi_ip_data *ip_data) +-{ +- REG_FLD_MOD(hdmi_wp_base(ip_data), HDMI_WP_VIDEO_CFG, true, 31, 31); +- return 0; +-} +- +-void ti_hdmi_4xxx_wp_video_stop(struct hdmi_ip_data *ip_data) +-{ +- REG_FLD_MOD(hdmi_wp_base(ip_data), HDMI_WP_VIDEO_CFG, false, 31, 31); +-} +- +-static void hdmi_wp_video_init_format(struct hdmi_video_format *video_fmt, +- struct omap_video_timings *timings, struct hdmi_config *param) +-{ +- pr_debug("Enter hdmi_wp_video_init_format\n"); +- +- video_fmt->y_res = param->timings.y_res; +- video_fmt->x_res = param->timings.x_res; +- +- timings->hbp = param->timings.hbp; +- timings->hfp = param->timings.hfp; +- timings->hsw = param->timings.hsw; +- timings->vbp = param->timings.vbp; +- timings->vfp = param->timings.vfp; +- timings->vsw = param->timings.vsw; +-} +- +-static void hdmi_wp_video_config_format(struct hdmi_ip_data *ip_data, +- struct hdmi_video_format *video_fmt) +-{ +- u32 l = 0; +- +- REG_FLD_MOD(hdmi_wp_base(ip_data), HDMI_WP_VIDEO_CFG, +- video_fmt->packing_mode, 10, 8); +- +- l |= FLD_VAL(video_fmt->y_res, 31, 16); +- l |= FLD_VAL(video_fmt->x_res, 15, 0); +- hdmi_write_reg(hdmi_wp_base(ip_data), HDMI_WP_VIDEO_SIZE, l); +-} +- +-static void hdmi_wp_video_config_interface(struct hdmi_ip_data *ip_data) +-{ +- u32 r; +- bool vsync_pol, hsync_pol; +- pr_debug("Enter hdmi_wp_video_config_interface\n"); +- +- vsync_pol = ip_data->cfg.timings.vsync_level == OMAPDSS_SIG_ACTIVE_HIGH; +- hsync_pol = ip_data->cfg.timings.hsync_level == OMAPDSS_SIG_ACTIVE_HIGH; +- +- r = hdmi_read_reg(hdmi_wp_base(ip_data), HDMI_WP_VIDEO_CFG); +- r = FLD_MOD(r, vsync_pol, 7, 7); +- r = FLD_MOD(r, hsync_pol, 6, 6); +- r = FLD_MOD(r, ip_data->cfg.timings.interlace, 3, 3); +- r = FLD_MOD(r, 1, 1, 0); /* HDMI_TIMING_MASTER_24BIT */ +- hdmi_write_reg(hdmi_wp_base(ip_data), HDMI_WP_VIDEO_CFG, r); +-} +- +-static void hdmi_wp_video_config_timing(struct hdmi_ip_data *ip_data, +- struct omap_video_timings *timings) +-{ +- u32 timing_h = 0; +- u32 timing_v = 0; +- +- pr_debug("Enter hdmi_wp_video_config_timing\n"); +- +- timing_h |= FLD_VAL(timings->hbp, 31, 20); +- timing_h |= FLD_VAL(timings->hfp, 19, 8); +- timing_h |= FLD_VAL(timings->hsw, 7, 0); +- hdmi_write_reg(hdmi_wp_base(ip_data), HDMI_WP_VIDEO_TIMING_H, timing_h); +- +- timing_v |= FLD_VAL(timings->vbp, 31, 20); +- timing_v |= FLD_VAL(timings->vfp, 19, 8); +- timing_v |= FLD_VAL(timings->vsw, 7, 0); +- hdmi_write_reg(hdmi_wp_base(ip_data), HDMI_WP_VIDEO_TIMING_V, timing_v); +-} +- +-void ti_hdmi_4xxx_basic_configure(struct hdmi_ip_data *ip_data) +-{ +- /* HDMI */ +- struct omap_video_timings video_timing; +- struct hdmi_video_format video_format; +- /* HDMI core */ +- struct hdmi_core_infoframe_avi *avi_cfg = &ip_data->avi_cfg; +- struct hdmi_core_video_config v_core_cfg; +- struct hdmi_core_packet_enable_repeat repeat_cfg; +- struct hdmi_config *cfg = &ip_data->cfg; +- +- hdmi_wp_init(&video_timing, &video_format); +- +- hdmi_core_init(&v_core_cfg, avi_cfg, &repeat_cfg); +- +- hdmi_wp_video_init_format(&video_format, &video_timing, cfg); +- +- hdmi_wp_video_config_timing(ip_data, &video_timing); +- +- /* video config */ +- video_format.packing_mode = HDMI_PACK_24b_RGB_YUV444_YUV422; +- +- hdmi_wp_video_config_format(ip_data, &video_format); +- +- hdmi_wp_video_config_interface(ip_data); +- +- /* +- * configure core video part +- * set software reset in the core +- */ +- hdmi_core_swreset_assert(ip_data); +- +- /* power down off */ +- hdmi_core_powerdown_disable(ip_data); +- +- v_core_cfg.pkt_mode = HDMI_PACKETMODE24BITPERPIXEL; +- v_core_cfg.hdmi_dvi = cfg->cm.mode; +- +- hdmi_core_video_config(ip_data, &v_core_cfg); +- +- /* release software reset in the core */ +- hdmi_core_swreset_release(ip_data); +- +- /* +- * configure packet +- * info frame video see doc CEA861-D page 65 +- */ +- avi_cfg->db1_format = HDMI_INFOFRAME_AVI_DB1Y_RGB; +- avi_cfg->db1_active_info = +- HDMI_INFOFRAME_AVI_DB1A_ACTIVE_FORMAT_OFF; +- avi_cfg->db1_bar_info_dv = HDMI_INFOFRAME_AVI_DB1B_NO; +- avi_cfg->db1_scan_info = HDMI_INFOFRAME_AVI_DB1S_0; +- avi_cfg->db2_colorimetry = HDMI_INFOFRAME_AVI_DB2C_NO; +- avi_cfg->db2_aspect_ratio = HDMI_INFOFRAME_AVI_DB2M_NO; +- avi_cfg->db2_active_fmt_ar = HDMI_INFOFRAME_AVI_DB2R_SAME; +- avi_cfg->db3_itc = HDMI_INFOFRAME_AVI_DB3ITC_NO; +- avi_cfg->db3_ec = HDMI_INFOFRAME_AVI_DB3EC_XVYUV601; +- avi_cfg->db3_q_range = HDMI_INFOFRAME_AVI_DB3Q_DEFAULT; +- avi_cfg->db3_nup_scaling = HDMI_INFOFRAME_AVI_DB3SC_NO; +- avi_cfg->db4_videocode = cfg->cm.code; +- avi_cfg->db5_pixel_repeat = HDMI_INFOFRAME_AVI_DB5PR_NO; +- avi_cfg->db6_7_line_eoftop = 0; +- avi_cfg->db8_9_line_sofbottom = 0; +- avi_cfg->db10_11_pixel_eofleft = 0; +- avi_cfg->db12_13_pixel_sofright = 0; +- +- hdmi_core_aux_infoframe_avi_config(ip_data); +- +- /* enable/repeat the infoframe */ +- repeat_cfg.avi_infoframe = HDMI_PACKETENABLE; +- repeat_cfg.avi_infoframe_repeat = HDMI_PACKETREPEATON; +- /* wakeup */ +- repeat_cfg.audio_pkt = HDMI_PACKETENABLE; +- repeat_cfg.audio_pkt_repeat = HDMI_PACKETREPEATON; +- hdmi_core_av_packet_config(ip_data, repeat_cfg); +-} +- +-void ti_hdmi_4xxx_wp_dump(struct hdmi_ip_data *ip_data, struct seq_file *s) +-{ +-#define DUMPREG(r) seq_printf(s, "%-35s %08x\n", #r,\ +- hdmi_read_reg(hdmi_wp_base(ip_data), r)) +- +- DUMPREG(HDMI_WP_REVISION); +- DUMPREG(HDMI_WP_SYSCONFIG); +- DUMPREG(HDMI_WP_IRQSTATUS_RAW); +- DUMPREG(HDMI_WP_IRQSTATUS); +- DUMPREG(HDMI_WP_PWR_CTRL); +- DUMPREG(HDMI_WP_IRQENABLE_SET); +- DUMPREG(HDMI_WP_VIDEO_CFG); +- DUMPREG(HDMI_WP_VIDEO_SIZE); +- DUMPREG(HDMI_WP_VIDEO_TIMING_H); +- DUMPREG(HDMI_WP_VIDEO_TIMING_V); +- DUMPREG(HDMI_WP_WP_CLK); +- DUMPREG(HDMI_WP_AUDIO_CFG); +- DUMPREG(HDMI_WP_AUDIO_CFG2); +- DUMPREG(HDMI_WP_AUDIO_CTRL); +- DUMPREG(HDMI_WP_AUDIO_DATA); +-} +- +-void ti_hdmi_4xxx_pll_dump(struct hdmi_ip_data *ip_data, struct seq_file *s) +-{ +-#define DUMPPLL(r) seq_printf(s, "%-35s %08x\n", #r,\ +- hdmi_read_reg(hdmi_pll_base(ip_data), r)) +- +- DUMPPLL(PLLCTRL_PLL_CONTROL); +- DUMPPLL(PLLCTRL_PLL_STATUS); +- DUMPPLL(PLLCTRL_PLL_GO); +- DUMPPLL(PLLCTRL_CFG1); +- DUMPPLL(PLLCTRL_CFG2); +- DUMPPLL(PLLCTRL_CFG3); +- DUMPPLL(PLLCTRL_CFG4); +-} +- +-void ti_hdmi_4xxx_core_dump(struct hdmi_ip_data *ip_data, struct seq_file *s) +-{ +- int i; +- +-#define CORE_REG(i, name) name(i) +-#define DUMPCORE(r) seq_printf(s, "%-35s %08x\n", #r,\ +- hdmi_read_reg(hdmi_core_sys_base(ip_data), r)) +-#define DUMPCOREAV(r) seq_printf(s, "%-35s %08x\n", #r,\ +- hdmi_read_reg(hdmi_av_base(ip_data), r)) +-#define DUMPCOREAV2(i, r) seq_printf(s, "%s[%d]%*s %08x\n", #r, i, \ +- (i < 10) ? 32 - (int)strlen(#r) : 31 - (int)strlen(#r), " ", \ +- hdmi_read_reg(hdmi_av_base(ip_data), CORE_REG(i, r))) +- +- DUMPCORE(HDMI_CORE_SYS_VND_IDL); +- DUMPCORE(HDMI_CORE_SYS_DEV_IDL); +- DUMPCORE(HDMI_CORE_SYS_DEV_IDH); +- DUMPCORE(HDMI_CORE_SYS_DEV_REV); +- DUMPCORE(HDMI_CORE_SYS_SRST); +- DUMPCORE(HDMI_CORE_CTRL1); +- DUMPCORE(HDMI_CORE_SYS_SYS_STAT); +- DUMPCORE(HDMI_CORE_SYS_DE_DLY); +- DUMPCORE(HDMI_CORE_SYS_DE_CTRL); +- DUMPCORE(HDMI_CORE_SYS_DE_TOP); +- DUMPCORE(HDMI_CORE_SYS_DE_CNTL); +- DUMPCORE(HDMI_CORE_SYS_DE_CNTH); +- DUMPCORE(HDMI_CORE_SYS_DE_LINL); +- DUMPCORE(HDMI_CORE_SYS_DE_LINH_1); +- DUMPCORE(HDMI_CORE_SYS_VID_ACEN); +- DUMPCORE(HDMI_CORE_SYS_VID_MODE); +- DUMPCORE(HDMI_CORE_SYS_INTR_STATE); +- DUMPCORE(HDMI_CORE_SYS_INTR1); +- DUMPCORE(HDMI_CORE_SYS_INTR2); +- DUMPCORE(HDMI_CORE_SYS_INTR3); +- DUMPCORE(HDMI_CORE_SYS_INTR4); +- DUMPCORE(HDMI_CORE_SYS_UMASK1); +- DUMPCORE(HDMI_CORE_SYS_TMDS_CTRL); +- +- DUMPCORE(HDMI_CORE_DDC_ADDR); +- DUMPCORE(HDMI_CORE_DDC_SEGM); +- DUMPCORE(HDMI_CORE_DDC_OFFSET); +- DUMPCORE(HDMI_CORE_DDC_COUNT1); +- DUMPCORE(HDMI_CORE_DDC_COUNT2); +- DUMPCORE(HDMI_CORE_DDC_STATUS); +- DUMPCORE(HDMI_CORE_DDC_CMD); +- DUMPCORE(HDMI_CORE_DDC_DATA); +- +- DUMPCOREAV(HDMI_CORE_AV_ACR_CTRL); +- DUMPCOREAV(HDMI_CORE_AV_FREQ_SVAL); +- DUMPCOREAV(HDMI_CORE_AV_N_SVAL1); +- DUMPCOREAV(HDMI_CORE_AV_N_SVAL2); +- DUMPCOREAV(HDMI_CORE_AV_N_SVAL3); +- DUMPCOREAV(HDMI_CORE_AV_CTS_SVAL1); +- DUMPCOREAV(HDMI_CORE_AV_CTS_SVAL2); +- DUMPCOREAV(HDMI_CORE_AV_CTS_SVAL3); +- DUMPCOREAV(HDMI_CORE_AV_CTS_HVAL1); +- DUMPCOREAV(HDMI_CORE_AV_CTS_HVAL2); +- DUMPCOREAV(HDMI_CORE_AV_CTS_HVAL3); +- DUMPCOREAV(HDMI_CORE_AV_AUD_MODE); +- DUMPCOREAV(HDMI_CORE_AV_SPDIF_CTRL); +- DUMPCOREAV(HDMI_CORE_AV_HW_SPDIF_FS); +- DUMPCOREAV(HDMI_CORE_AV_SWAP_I2S); +- DUMPCOREAV(HDMI_CORE_AV_SPDIF_ERTH); +- DUMPCOREAV(HDMI_CORE_AV_I2S_IN_MAP); +- DUMPCOREAV(HDMI_CORE_AV_I2S_IN_CTRL); +- DUMPCOREAV(HDMI_CORE_AV_I2S_CHST0); +- DUMPCOREAV(HDMI_CORE_AV_I2S_CHST1); +- DUMPCOREAV(HDMI_CORE_AV_I2S_CHST2); +- DUMPCOREAV(HDMI_CORE_AV_I2S_CHST4); +- DUMPCOREAV(HDMI_CORE_AV_I2S_CHST5); +- DUMPCOREAV(HDMI_CORE_AV_ASRC); +- DUMPCOREAV(HDMI_CORE_AV_I2S_IN_LEN); +- DUMPCOREAV(HDMI_CORE_AV_HDMI_CTRL); +- DUMPCOREAV(HDMI_CORE_AV_AUDO_TXSTAT); +- DUMPCOREAV(HDMI_CORE_AV_AUD_PAR_BUSCLK_1); +- DUMPCOREAV(HDMI_CORE_AV_AUD_PAR_BUSCLK_2); +- DUMPCOREAV(HDMI_CORE_AV_AUD_PAR_BUSCLK_3); +- DUMPCOREAV(HDMI_CORE_AV_TEST_TXCTRL); +- DUMPCOREAV(HDMI_CORE_AV_DPD); +- DUMPCOREAV(HDMI_CORE_AV_PB_CTRL1); +- DUMPCOREAV(HDMI_CORE_AV_PB_CTRL2); +- DUMPCOREAV(HDMI_CORE_AV_AVI_TYPE); +- DUMPCOREAV(HDMI_CORE_AV_AVI_VERS); +- DUMPCOREAV(HDMI_CORE_AV_AVI_LEN); +- DUMPCOREAV(HDMI_CORE_AV_AVI_CHSUM); +- +- for (i = 0; i < HDMI_CORE_AV_AVI_DBYTE_NELEMS; i++) +- DUMPCOREAV2(i, HDMI_CORE_AV_AVI_DBYTE); +- +- DUMPCOREAV(HDMI_CORE_AV_SPD_TYPE); +- DUMPCOREAV(HDMI_CORE_AV_SPD_VERS); +- DUMPCOREAV(HDMI_CORE_AV_SPD_LEN); +- DUMPCOREAV(HDMI_CORE_AV_SPD_CHSUM); +- +- for (i = 0; i < HDMI_CORE_AV_SPD_DBYTE_NELEMS; i++) +- DUMPCOREAV2(i, HDMI_CORE_AV_SPD_DBYTE); +- +- DUMPCOREAV(HDMI_CORE_AV_AUDIO_TYPE); +- DUMPCOREAV(HDMI_CORE_AV_AUDIO_VERS); +- DUMPCOREAV(HDMI_CORE_AV_AUDIO_LEN); +- DUMPCOREAV(HDMI_CORE_AV_AUDIO_CHSUM); +- +- for (i = 0; i < HDMI_CORE_AV_AUD_DBYTE_NELEMS; i++) +- DUMPCOREAV2(i, HDMI_CORE_AV_AUD_DBYTE); +- +- DUMPCOREAV(HDMI_CORE_AV_MPEG_TYPE); +- DUMPCOREAV(HDMI_CORE_AV_MPEG_VERS); +- DUMPCOREAV(HDMI_CORE_AV_MPEG_LEN); +- DUMPCOREAV(HDMI_CORE_AV_MPEG_CHSUM); +- +- for (i = 0; i < HDMI_CORE_AV_MPEG_DBYTE_NELEMS; i++) +- DUMPCOREAV2(i, HDMI_CORE_AV_MPEG_DBYTE); +- +- for (i = 0; i < HDMI_CORE_AV_GEN_DBYTE_NELEMS; i++) +- DUMPCOREAV2(i, HDMI_CORE_AV_GEN_DBYTE); +- +- DUMPCOREAV(HDMI_CORE_AV_CP_BYTE1); +- +- for (i = 0; i < HDMI_CORE_AV_GEN2_DBYTE_NELEMS; i++) +- DUMPCOREAV2(i, HDMI_CORE_AV_GEN2_DBYTE); +- +- DUMPCOREAV(HDMI_CORE_AV_CEC_ADDR_ID); +-} +- +-void ti_hdmi_4xxx_phy_dump(struct hdmi_ip_data *ip_data, struct seq_file *s) +-{ +-#define DUMPPHY(r) seq_printf(s, "%-35s %08x\n", #r,\ +- hdmi_read_reg(hdmi_phy_base(ip_data), r)) +- +- DUMPPHY(HDMI_TXPHY_TX_CTRL); +- DUMPPHY(HDMI_TXPHY_DIGITAL_CTRL); +- DUMPPHY(HDMI_TXPHY_POWER_CTRL); +- DUMPPHY(HDMI_TXPHY_PAD_CFG_CTRL); +-} +- +-#if defined(CONFIG_OMAP4_DSS_HDMI_AUDIO) +-static void ti_hdmi_4xxx_wp_audio_config_format(struct hdmi_ip_data *ip_data, +- struct hdmi_audio_format *aud_fmt) +-{ +- u32 r; +- +- DSSDBG("Enter hdmi_wp_audio_config_format\n"); +- +- r = hdmi_read_reg(hdmi_wp_base(ip_data), HDMI_WP_AUDIO_CFG); +- r = FLD_MOD(r, aud_fmt->stereo_channels, 26, 24); +- r = FLD_MOD(r, aud_fmt->active_chnnls_msk, 23, 16); +- r = FLD_MOD(r, aud_fmt->en_sig_blk_strt_end, 5, 5); +- r = FLD_MOD(r, aud_fmt->type, 4, 4); +- r = FLD_MOD(r, aud_fmt->justification, 3, 3); +- r = FLD_MOD(r, aud_fmt->sample_order, 2, 2); +- r = FLD_MOD(r, aud_fmt->samples_per_word, 1, 1); +- r = FLD_MOD(r, aud_fmt->sample_size, 0, 0); +- hdmi_write_reg(hdmi_wp_base(ip_data), HDMI_WP_AUDIO_CFG, r); +-} +- +-static void ti_hdmi_4xxx_wp_audio_config_dma(struct hdmi_ip_data *ip_data, +- struct hdmi_audio_dma *aud_dma) +-{ +- u32 r; +- +- DSSDBG("Enter hdmi_wp_audio_config_dma\n"); +- +- r = hdmi_read_reg(hdmi_wp_base(ip_data), HDMI_WP_AUDIO_CFG2); +- r = FLD_MOD(r, aud_dma->transfer_size, 15, 8); +- r = FLD_MOD(r, aud_dma->block_size, 7, 0); +- hdmi_write_reg(hdmi_wp_base(ip_data), HDMI_WP_AUDIO_CFG2, r); +- +- r = hdmi_read_reg(hdmi_wp_base(ip_data), HDMI_WP_AUDIO_CTRL); +- r = FLD_MOD(r, aud_dma->mode, 9, 9); +- r = FLD_MOD(r, aud_dma->fifo_threshold, 8, 0); +- hdmi_write_reg(hdmi_wp_base(ip_data), HDMI_WP_AUDIO_CTRL, r); +-} +- +-static void ti_hdmi_4xxx_core_audio_config(struct hdmi_ip_data *ip_data, +- struct hdmi_core_audio_config *cfg) +-{ +- u32 r; +- void __iomem *av_base = hdmi_av_base(ip_data); +- +- /* +- * Parameters for generation of Audio Clock Recovery packets +- */ +- REG_FLD_MOD(av_base, HDMI_CORE_AV_N_SVAL1, cfg->n, 7, 0); +- REG_FLD_MOD(av_base, HDMI_CORE_AV_N_SVAL2, cfg->n >> 8, 7, 0); +- REG_FLD_MOD(av_base, HDMI_CORE_AV_N_SVAL3, cfg->n >> 16, 7, 0); +- +- if (cfg->cts_mode == HDMI_AUDIO_CTS_MODE_SW) { +- REG_FLD_MOD(av_base, HDMI_CORE_AV_CTS_SVAL1, cfg->cts, 7, 0); +- REG_FLD_MOD(av_base, +- HDMI_CORE_AV_CTS_SVAL2, cfg->cts >> 8, 7, 0); +- REG_FLD_MOD(av_base, +- HDMI_CORE_AV_CTS_SVAL3, cfg->cts >> 16, 7, 0); +- } else { +- REG_FLD_MOD(av_base, HDMI_CORE_AV_AUD_PAR_BUSCLK_1, +- cfg->aud_par_busclk, 7, 0); +- REG_FLD_MOD(av_base, HDMI_CORE_AV_AUD_PAR_BUSCLK_2, +- (cfg->aud_par_busclk >> 8), 7, 0); +- REG_FLD_MOD(av_base, HDMI_CORE_AV_AUD_PAR_BUSCLK_3, +- (cfg->aud_par_busclk >> 16), 7, 0); +- } +- +- /* Set ACR clock divisor */ +- REG_FLD_MOD(av_base, +- HDMI_CORE_AV_FREQ_SVAL, cfg->mclk_mode, 2, 0); +- +- r = hdmi_read_reg(av_base, HDMI_CORE_AV_ACR_CTRL); +- /* +- * Use TMDS clock for ACR packets. For devices that use +- * the MCLK, this is the first part of the MCLK initialization. +- */ +- r = FLD_MOD(r, 0, 2, 2); +- +- r = FLD_MOD(r, cfg->en_acr_pkt, 1, 1); +- r = FLD_MOD(r, cfg->cts_mode, 0, 0); +- hdmi_write_reg(av_base, HDMI_CORE_AV_ACR_CTRL, r); +- +- /* For devices using MCLK, this completes its initialization. */ +- if (cfg->use_mclk) +- REG_FLD_MOD(av_base, HDMI_CORE_AV_ACR_CTRL, 1, 2, 2); +- +- /* Override of SPDIF sample frequency with value in I2S_CHST4 */ +- REG_FLD_MOD(av_base, HDMI_CORE_AV_SPDIF_CTRL, +- cfg->fs_override, 1, 1); +- +- /* +- * Set IEC-60958-3 channel status word. It is passed to the IP +- * just as it is received. The user of the driver is responsible +- * for its contents. +- */ +- hdmi_write_reg(av_base, HDMI_CORE_AV_I2S_CHST0, +- cfg->iec60958_cfg->status[0]); +- hdmi_write_reg(av_base, HDMI_CORE_AV_I2S_CHST1, +- cfg->iec60958_cfg->status[1]); +- hdmi_write_reg(av_base, HDMI_CORE_AV_I2S_CHST2, +- cfg->iec60958_cfg->status[2]); +- /* yes, this is correct: status[3] goes to CHST4 register */ +- hdmi_write_reg(av_base, HDMI_CORE_AV_I2S_CHST4, +- cfg->iec60958_cfg->status[3]); +- /* yes, this is correct: status[4] goes to CHST5 register */ +- hdmi_write_reg(av_base, HDMI_CORE_AV_I2S_CHST5, +- cfg->iec60958_cfg->status[4]); +- +- /* set I2S parameters */ +- r = hdmi_read_reg(av_base, HDMI_CORE_AV_I2S_IN_CTRL); +- r = FLD_MOD(r, cfg->i2s_cfg.sck_edge_mode, 6, 6); +- r = FLD_MOD(r, cfg->i2s_cfg.vbit, 4, 4); +- r = FLD_MOD(r, cfg->i2s_cfg.justification, 2, 2); +- r = FLD_MOD(r, cfg->i2s_cfg.direction, 1, 1); +- r = FLD_MOD(r, cfg->i2s_cfg.shift, 0, 0); +- hdmi_write_reg(av_base, HDMI_CORE_AV_I2S_IN_CTRL, r); +- +- REG_FLD_MOD(av_base, HDMI_CORE_AV_I2S_IN_LEN, +- cfg->i2s_cfg.in_length_bits, 3, 0); +- +- /* Audio channels and mode parameters */ +- REG_FLD_MOD(av_base, HDMI_CORE_AV_HDMI_CTRL, cfg->layout, 2, 1); +- r = hdmi_read_reg(av_base, HDMI_CORE_AV_AUD_MODE); +- r = FLD_MOD(r, cfg->i2s_cfg.active_sds, 7, 4); +- r = FLD_MOD(r, cfg->en_dsd_audio, 3, 3); +- r = FLD_MOD(r, cfg->en_parallel_aud_input, 2, 2); +- r = FLD_MOD(r, cfg->en_spdif, 1, 1); +- hdmi_write_reg(av_base, HDMI_CORE_AV_AUD_MODE, r); +- +- /* Audio channel mappings */ +- /* TODO: Make channel mapping dynamic. For now, map channels +- * in the ALSA order: FL/FR/RL/RR/C/LFE/SL/SR. Remapping is needed as +- * HDMI speaker order is different. See CEA-861 Section 6.6.2. +- */ +- hdmi_write_reg(av_base, HDMI_CORE_AV_I2S_IN_MAP, 0x78); +- REG_FLD_MOD(av_base, HDMI_CORE_AV_SWAP_I2S, 1, 5, 5); +-} +- +-static void ti_hdmi_4xxx_core_audio_infoframe_cfg(struct hdmi_ip_data *ip_data, +- struct snd_cea_861_aud_if *info_aud) +-{ +- u8 sum = 0, checksum = 0; +- void __iomem *av_base = hdmi_av_base(ip_data); +- +- /* +- * Set audio info frame type, version and length as +- * described in HDMI 1.4a Section 8.2.2 specification. +- * Checksum calculation is defined in Section 5.3.5. +- */ +- hdmi_write_reg(av_base, HDMI_CORE_AV_AUDIO_TYPE, 0x84); +- hdmi_write_reg(av_base, HDMI_CORE_AV_AUDIO_VERS, 0x01); +- hdmi_write_reg(av_base, HDMI_CORE_AV_AUDIO_LEN, 0x0a); +- sum += 0x84 + 0x001 + 0x00a; +- +- hdmi_write_reg(av_base, HDMI_CORE_AV_AUD_DBYTE(0), +- info_aud->db1_ct_cc); +- sum += info_aud->db1_ct_cc; +- +- hdmi_write_reg(av_base, HDMI_CORE_AV_AUD_DBYTE(1), +- info_aud->db2_sf_ss); +- sum += info_aud->db2_sf_ss; +- +- hdmi_write_reg(av_base, HDMI_CORE_AV_AUD_DBYTE(2), info_aud->db3); +- sum += info_aud->db3; +- +- hdmi_write_reg(av_base, HDMI_CORE_AV_AUD_DBYTE(3), info_aud->db4_ca); +- sum += info_aud->db4_ca; +- +- hdmi_write_reg(av_base, HDMI_CORE_AV_AUD_DBYTE(4), +- info_aud->db5_dminh_lsv); +- sum += info_aud->db5_dminh_lsv; +- +- hdmi_write_reg(av_base, HDMI_CORE_AV_AUD_DBYTE(5), 0x00); +- hdmi_write_reg(av_base, HDMI_CORE_AV_AUD_DBYTE(6), 0x00); +- hdmi_write_reg(av_base, HDMI_CORE_AV_AUD_DBYTE(7), 0x00); +- hdmi_write_reg(av_base, HDMI_CORE_AV_AUD_DBYTE(8), 0x00); +- hdmi_write_reg(av_base, HDMI_CORE_AV_AUD_DBYTE(9), 0x00); +- +- checksum = 0x100 - sum; +- hdmi_write_reg(av_base, +- HDMI_CORE_AV_AUDIO_CHSUM, checksum); +- +- /* +- * TODO: Add MPEG and SPD enable and repeat cfg when EDID parsing +- * is available. +- */ +-} +- +-int ti_hdmi_4xxx_audio_config(struct hdmi_ip_data *ip_data, +- struct omap_dss_audio *audio) +-{ +- struct hdmi_audio_format audio_format; +- struct hdmi_audio_dma audio_dma; +- struct hdmi_core_audio_config core; +- int err, n, cts, channel_count; +- unsigned int fs_nr; +- bool word_length_16b = false; +- +- if (!audio || !audio->iec || !audio->cea || !ip_data) +- return -EINVAL; +- +- core.iec60958_cfg = audio->iec; +- /* +- * In the IEC-60958 status word, check if the audio sample word length +- * is 16-bit as several optimizations can be performed in such case. +- */ +- if (!(audio->iec->status[4] & IEC958_AES4_CON_MAX_WORDLEN_24)) +- if (audio->iec->status[4] & IEC958_AES4_CON_WORDLEN_20_16) +- word_length_16b = true; +- +- /* I2S configuration. See Phillips' specification */ +- if (word_length_16b) +- core.i2s_cfg.justification = HDMI_AUDIO_JUSTIFY_LEFT; +- else +- core.i2s_cfg.justification = HDMI_AUDIO_JUSTIFY_RIGHT; +- /* +- * The I2S input word length is twice the lenght given in the IEC-60958 +- * status word. If the word size is greater than +- * 20 bits, increment by one. +- */ +- core.i2s_cfg.in_length_bits = audio->iec->status[4] +- & IEC958_AES4_CON_WORDLEN; +- if (audio->iec->status[4] & IEC958_AES4_CON_MAX_WORDLEN_24) +- core.i2s_cfg.in_length_bits++; +- core.i2s_cfg.sck_edge_mode = HDMI_AUDIO_I2S_SCK_EDGE_RISING; +- core.i2s_cfg.vbit = HDMI_AUDIO_I2S_VBIT_FOR_PCM; +- core.i2s_cfg.direction = HDMI_AUDIO_I2S_MSB_SHIFTED_FIRST; +- core.i2s_cfg.shift = HDMI_AUDIO_I2S_FIRST_BIT_SHIFT; +- +- /* convert sample frequency to a number */ +- switch (audio->iec->status[3] & IEC958_AES3_CON_FS) { +- case IEC958_AES3_CON_FS_32000: +- fs_nr = 32000; +- break; +- case IEC958_AES3_CON_FS_44100: +- fs_nr = 44100; +- break; +- case IEC958_AES3_CON_FS_48000: +- fs_nr = 48000; +- break; +- case IEC958_AES3_CON_FS_88200: +- fs_nr = 88200; +- break; +- case IEC958_AES3_CON_FS_96000: +- fs_nr = 96000; +- break; +- case IEC958_AES3_CON_FS_176400: +- fs_nr = 176400; +- break; +- case IEC958_AES3_CON_FS_192000: +- fs_nr = 192000; +- break; +- default: +- return -EINVAL; +- } +- +- err = hdmi_compute_acr(fs_nr, &n, &cts); +- +- /* Audio clock regeneration settings */ +- core.n = n; +- core.cts = cts; +- if (dss_has_feature(FEAT_HDMI_CTS_SWMODE)) { +- core.aud_par_busclk = 0; +- core.cts_mode = HDMI_AUDIO_CTS_MODE_SW; +- core.use_mclk = dss_has_feature(FEAT_HDMI_AUDIO_USE_MCLK); +- } else { +- core.aud_par_busclk = (((128 * 31) - 1) << 8); +- core.cts_mode = HDMI_AUDIO_CTS_MODE_HW; +- core.use_mclk = true; +- } +- +- if (core.use_mclk) +- core.mclk_mode = HDMI_AUDIO_MCLK_128FS; +- +- /* Audio channels settings */ +- channel_count = (audio->cea->db1_ct_cc & +- CEA861_AUDIO_INFOFRAME_DB1CC) + 1; +- +- switch (channel_count) { +- case 2: +- audio_format.active_chnnls_msk = 0x03; +- break; +- case 3: +- audio_format.active_chnnls_msk = 0x07; +- break; +- case 4: +- audio_format.active_chnnls_msk = 0x0f; +- break; +- case 5: +- audio_format.active_chnnls_msk = 0x1f; +- break; +- case 6: +- audio_format.active_chnnls_msk = 0x3f; +- break; +- case 7: +- audio_format.active_chnnls_msk = 0x7f; +- break; +- case 8: +- audio_format.active_chnnls_msk = 0xff; +- break; +- default: +- return -EINVAL; +- } +- +- /* +- * the HDMI IP needs to enable four stereo channels when transmitting +- * more than 2 audio channels +- */ +- if (channel_count == 2) { +- audio_format.stereo_channels = HDMI_AUDIO_STEREO_ONECHANNEL; +- core.i2s_cfg.active_sds = HDMI_AUDIO_I2S_SD0_EN; +- core.layout = HDMI_AUDIO_LAYOUT_2CH; +- } else { +- audio_format.stereo_channels = HDMI_AUDIO_STEREO_FOURCHANNELS; +- core.i2s_cfg.active_sds = HDMI_AUDIO_I2S_SD0_EN | +- HDMI_AUDIO_I2S_SD1_EN | HDMI_AUDIO_I2S_SD2_EN | +- HDMI_AUDIO_I2S_SD3_EN; +- core.layout = HDMI_AUDIO_LAYOUT_8CH; +- } +- +- core.en_spdif = false; +- /* use sample frequency from channel status word */ +- core.fs_override = true; +- /* enable ACR packets */ +- core.en_acr_pkt = true; +- /* disable direct streaming digital audio */ +- core.en_dsd_audio = false; +- /* use parallel audio interface */ +- core.en_parallel_aud_input = true; +- +- /* DMA settings */ +- if (word_length_16b) +- audio_dma.transfer_size = 0x10; +- else +- audio_dma.transfer_size = 0x20; +- audio_dma.block_size = 0xC0; +- audio_dma.mode = HDMI_AUDIO_TRANSF_DMA; +- audio_dma.fifo_threshold = 0x20; /* in number of samples */ +- +- /* audio FIFO format settings */ +- if (word_length_16b) { +- audio_format.samples_per_word = HDMI_AUDIO_ONEWORD_TWOSAMPLES; +- audio_format.sample_size = HDMI_AUDIO_SAMPLE_16BITS; +- audio_format.justification = HDMI_AUDIO_JUSTIFY_LEFT; +- } else { +- audio_format.samples_per_word = HDMI_AUDIO_ONEWORD_ONESAMPLE; +- audio_format.sample_size = HDMI_AUDIO_SAMPLE_24BITS; +- audio_format.justification = HDMI_AUDIO_JUSTIFY_RIGHT; +- } +- audio_format.type = HDMI_AUDIO_TYPE_LPCM; +- audio_format.sample_order = HDMI_AUDIO_SAMPLE_LEFT_FIRST; +- /* disable start/stop signals of IEC 60958 blocks */ +- audio_format.en_sig_blk_strt_end = HDMI_AUDIO_BLOCK_SIG_STARTEND_ON; +- +- /* configure DMA and audio FIFO format*/ +- ti_hdmi_4xxx_wp_audio_config_dma(ip_data, &audio_dma); +- ti_hdmi_4xxx_wp_audio_config_format(ip_data, &audio_format); +- +- /* configure the core*/ +- ti_hdmi_4xxx_core_audio_config(ip_data, &core); +- +- /* configure CEA 861 audio infoframe*/ +- ti_hdmi_4xxx_core_audio_infoframe_cfg(ip_data, audio->cea); +- +- return 0; +-} +- +-int ti_hdmi_4xxx_wp_audio_enable(struct hdmi_ip_data *ip_data) +-{ +- REG_FLD_MOD(hdmi_wp_base(ip_data), +- HDMI_WP_AUDIO_CTRL, true, 31, 31); +- return 0; +-} +- +-void ti_hdmi_4xxx_wp_audio_disable(struct hdmi_ip_data *ip_data) +-{ +- REG_FLD_MOD(hdmi_wp_base(ip_data), +- HDMI_WP_AUDIO_CTRL, false, 31, 31); +-} +- +-int ti_hdmi_4xxx_audio_start(struct hdmi_ip_data *ip_data) +-{ +- REG_FLD_MOD(hdmi_av_base(ip_data), +- HDMI_CORE_AV_AUD_MODE, true, 0, 0); +- REG_FLD_MOD(hdmi_wp_base(ip_data), +- HDMI_WP_AUDIO_CTRL, true, 30, 30); +- return 0; +-} +- +-void ti_hdmi_4xxx_audio_stop(struct hdmi_ip_data *ip_data) +-{ +- REG_FLD_MOD(hdmi_av_base(ip_data), +- HDMI_CORE_AV_AUD_MODE, false, 0, 0); +- REG_FLD_MOD(hdmi_wp_base(ip_data), +- HDMI_WP_AUDIO_CTRL, false, 30, 30); +-} +- +-int ti_hdmi_4xxx_audio_get_dma_port(u32 *offset, u32 *size) +-{ +- if (!offset || !size) +- return -EINVAL; +- *offset = HDMI_WP_AUDIO_DATA; +- *size = 4; +- return 0; +-} +-#endif +--- a/drivers/video/omap2/dss/ti_hdmi_4xxx_ip.h ++++ /dev/null +@@ -1,437 +0,0 @@ +-/* +- * ti_hdmi_4xxx_ip.h +- * +- * HDMI header definition for DM81xx, DM38xx, TI OMAP4 etc processors. +- * +- * Copyright (C) 2010-2011 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 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, see <http://www.gnu.org/licenses/>. +- */ +- +-#ifndef _HDMI_TI_4xxx_H_ +-#define _HDMI_TI_4xxx_H_ +- +-#include <linux/string.h> +-#include <video/omapdss.h> +-#include "ti_hdmi.h" +- +-/* HDMI Wrapper */ +- +-#define HDMI_WP_REVISION 0x0 +-#define HDMI_WP_SYSCONFIG 0x10 +-#define HDMI_WP_IRQSTATUS_RAW 0x24 +-#define HDMI_WP_IRQSTATUS 0x28 +-#define HDMI_WP_PWR_CTRL 0x40 +-#define HDMI_WP_IRQENABLE_SET 0x2C +-#define HDMI_WP_IRQENABLE_CLR 0x30 +-#define HDMI_WP_VIDEO_CFG 0x50 +-#define HDMI_WP_VIDEO_SIZE 0x60 +-#define HDMI_WP_VIDEO_TIMING_H 0x68 +-#define HDMI_WP_VIDEO_TIMING_V 0x6C +-#define HDMI_WP_WP_CLK 0x70 +-#define HDMI_WP_AUDIO_CFG 0x80 +-#define HDMI_WP_AUDIO_CFG2 0x84 +-#define HDMI_WP_AUDIO_CTRL 0x88 +-#define HDMI_WP_AUDIO_DATA 0x8C +- +-/* HDMI IP Core System */ +- +-#define HDMI_CORE_SYS_VND_IDL 0x0 +-#define HDMI_CORE_SYS_DEV_IDL 0x8 +-#define HDMI_CORE_SYS_DEV_IDH 0xC +-#define HDMI_CORE_SYS_DEV_REV 0x10 +-#define HDMI_CORE_SYS_SRST 0x14 +-#define HDMI_CORE_CTRL1 0x20 +-#define HDMI_CORE_SYS_SYS_STAT 0x24 +-#define HDMI_CORE_SYS_DE_DLY 0xC8 +-#define HDMI_CORE_SYS_DE_CTRL 0xCC +-#define HDMI_CORE_SYS_DE_TOP 0xD0 +-#define HDMI_CORE_SYS_DE_CNTL 0xD8 +-#define HDMI_CORE_SYS_DE_CNTH 0xDC +-#define HDMI_CORE_SYS_DE_LINL 0xE0 +-#define HDMI_CORE_SYS_DE_LINH_1 0xE4 +-#define HDMI_CORE_SYS_VID_ACEN 0x124 +-#define HDMI_CORE_SYS_VID_MODE 0x128 +-#define HDMI_CORE_SYS_INTR_STATE 0x1C0 +-#define HDMI_CORE_SYS_INTR1 0x1C4 +-#define HDMI_CORE_SYS_INTR2 0x1C8 +-#define HDMI_CORE_SYS_INTR3 0x1CC +-#define HDMI_CORE_SYS_INTR4 0x1D0 +-#define HDMI_CORE_SYS_UMASK1 0x1D4 +-#define HDMI_CORE_SYS_TMDS_CTRL 0x208 +- +-#define HDMI_CORE_CTRL1_VEN_FOLLOWVSYNC 0x1 +-#define HDMI_CORE_CTRL1_HEN_FOLLOWHSYNC 0x1 +-#define HDMI_CORE_CTRL1_BSEL_24BITBUS 0x1 +-#define HDMI_CORE_CTRL1_EDGE_RISINGEDGE 0x1 +- +-/* HDMI DDC E-DID */ +-#define HDMI_CORE_DDC_ADDR 0x3B4 +-#define HDMI_CORE_DDC_SEGM 0x3B8 +-#define HDMI_CORE_DDC_OFFSET 0x3BC +-#define HDMI_CORE_DDC_COUNT1 0x3C0 +-#define HDMI_CORE_DDC_COUNT2 0x3C4 +-#define HDMI_CORE_DDC_STATUS 0x3C8 +-#define HDMI_CORE_DDC_CMD 0x3CC +-#define HDMI_CORE_DDC_DATA 0x3D0 +- +-/* HDMI IP Core Audio Video */ +- +-#define HDMI_CORE_AV_ACR_CTRL 0x4 +-#define HDMI_CORE_AV_FREQ_SVAL 0x8 +-#define HDMI_CORE_AV_N_SVAL1 0xC +-#define HDMI_CORE_AV_N_SVAL2 0x10 +-#define HDMI_CORE_AV_N_SVAL3 0x14 +-#define HDMI_CORE_AV_CTS_SVAL1 0x18 +-#define HDMI_CORE_AV_CTS_SVAL2 0x1C +-#define HDMI_CORE_AV_CTS_SVAL3 0x20 +-#define HDMI_CORE_AV_CTS_HVAL1 0x24 +-#define HDMI_CORE_AV_CTS_HVAL2 0x28 +-#define HDMI_CORE_AV_CTS_HVAL3 0x2C +-#define HDMI_CORE_AV_AUD_MODE 0x50 +-#define HDMI_CORE_AV_SPDIF_CTRL 0x54 +-#define HDMI_CORE_AV_HW_SPDIF_FS 0x60 +-#define HDMI_CORE_AV_SWAP_I2S 0x64 +-#define HDMI_CORE_AV_SPDIF_ERTH 0x6C +-#define HDMI_CORE_AV_I2S_IN_MAP 0x70 +-#define HDMI_CORE_AV_I2S_IN_CTRL 0x74 +-#define HDMI_CORE_AV_I2S_CHST0 0x78 +-#define HDMI_CORE_AV_I2S_CHST1 0x7C +-#define HDMI_CORE_AV_I2S_CHST2 0x80 +-#define HDMI_CORE_AV_I2S_CHST4 0x84 +-#define HDMI_CORE_AV_I2S_CHST5 0x88 +-#define HDMI_CORE_AV_ASRC 0x8C +-#define HDMI_CORE_AV_I2S_IN_LEN 0x90 +-#define HDMI_CORE_AV_HDMI_CTRL 0xBC +-#define HDMI_CORE_AV_AUDO_TXSTAT 0xC0 +-#define HDMI_CORE_AV_AUD_PAR_BUSCLK_1 0xCC +-#define HDMI_CORE_AV_AUD_PAR_BUSCLK_2 0xD0 +-#define HDMI_CORE_AV_AUD_PAR_BUSCLK_3 0xD4 +-#define HDMI_CORE_AV_TEST_TXCTRL 0xF0 +-#define HDMI_CORE_AV_DPD 0xF4 +-#define HDMI_CORE_AV_PB_CTRL1 0xF8 +-#define HDMI_CORE_AV_PB_CTRL2 0xFC +-#define HDMI_CORE_AV_AVI_TYPE 0x100 +-#define HDMI_CORE_AV_AVI_VERS 0x104 +-#define HDMI_CORE_AV_AVI_LEN 0x108 +-#define HDMI_CORE_AV_AVI_CHSUM 0x10C +-#define HDMI_CORE_AV_AVI_DBYTE(n) (n * 4 + 0x110) +-#define HDMI_CORE_AV_SPD_TYPE 0x180 +-#define HDMI_CORE_AV_SPD_VERS 0x184 +-#define HDMI_CORE_AV_SPD_LEN 0x188 +-#define HDMI_CORE_AV_SPD_CHSUM 0x18C +-#define HDMI_CORE_AV_SPD_DBYTE(n) (n * 4 + 0x190) +-#define HDMI_CORE_AV_AUDIO_TYPE 0x200 +-#define HDMI_CORE_AV_AUDIO_VERS 0x204 +-#define HDMI_CORE_AV_AUDIO_LEN 0x208 +-#define HDMI_CORE_AV_AUDIO_CHSUM 0x20C +-#define HDMI_CORE_AV_AUD_DBYTE(n) (n * 4 + 0x210) +-#define HDMI_CORE_AV_MPEG_TYPE 0x280 +-#define HDMI_CORE_AV_MPEG_VERS 0x284 +-#define HDMI_CORE_AV_MPEG_LEN 0x288 +-#define HDMI_CORE_AV_MPEG_CHSUM 0x28C +-#define HDMI_CORE_AV_MPEG_DBYTE(n) (n * 4 + 0x290) +-#define HDMI_CORE_AV_GEN_DBYTE(n) (n * 4 + 0x300) +-#define HDMI_CORE_AV_CP_BYTE1 0x37C +-#define HDMI_CORE_AV_GEN2_DBYTE(n) (n * 4 + 0x380) +-#define HDMI_CORE_AV_CEC_ADDR_ID 0x3FC +- +-#define HDMI_CORE_AV_SPD_DBYTE_ELSIZE 0x4 +-#define HDMI_CORE_AV_GEN2_DBYTE_ELSIZE 0x4 +-#define HDMI_CORE_AV_MPEG_DBYTE_ELSIZE 0x4 +-#define HDMI_CORE_AV_GEN_DBYTE_ELSIZE 0x4 +- +-#define HDMI_CORE_AV_AVI_DBYTE_NELEMS 15 +-#define HDMI_CORE_AV_SPD_DBYTE_NELEMS 27 +-#define HDMI_CORE_AV_AUD_DBYTE_NELEMS 10 +-#define HDMI_CORE_AV_MPEG_DBYTE_NELEMS 27 +-#define HDMI_CORE_AV_GEN_DBYTE_NELEMS 31 +-#define HDMI_CORE_AV_GEN2_DBYTE_NELEMS 31 +- +-/* PLL */ +- +-#define PLLCTRL_PLL_CONTROL 0x0 +-#define PLLCTRL_PLL_STATUS 0x4 +-#define PLLCTRL_PLL_GO 0x8 +-#define PLLCTRL_CFG1 0xC +-#define PLLCTRL_CFG2 0x10 +-#define PLLCTRL_CFG3 0x14 +-#define PLLCTRL_CFG4 0x20 +- +-/* HDMI PHY */ +- +-#define HDMI_TXPHY_TX_CTRL 0x0 +-#define HDMI_TXPHY_DIGITAL_CTRL 0x4 +-#define HDMI_TXPHY_POWER_CTRL 0x8 +-#define HDMI_TXPHY_PAD_CFG_CTRL 0xC +- +-#define REG_FLD_MOD(base, idx, val, start, end) \ +- hdmi_write_reg(base, idx, FLD_MOD(hdmi_read_reg(base, idx),\ +- val, start, end)) +-#define REG_GET(base, idx, start, end) \ +- FLD_GET(hdmi_read_reg(base, idx), start, end) +- +-enum hdmi_phy_pwr { +- HDMI_PHYPWRCMD_OFF = 0, +- HDMI_PHYPWRCMD_LDOON = 1, +- HDMI_PHYPWRCMD_TXON = 2 +-}; +- +-enum hdmi_core_inputbus_width { +- HDMI_INPUT_8BIT = 0, +- HDMI_INPUT_10BIT = 1, +- HDMI_INPUT_12BIT = 2 +-}; +- +-enum hdmi_core_dither_trunc { +- HDMI_OUTPUTTRUNCATION_8BIT = 0, +- HDMI_OUTPUTTRUNCATION_10BIT = 1, +- HDMI_OUTPUTTRUNCATION_12BIT = 2, +- HDMI_OUTPUTDITHER_8BIT = 3, +- HDMI_OUTPUTDITHER_10BIT = 4, +- HDMI_OUTPUTDITHER_12BIT = 5 +-}; +- +-enum hdmi_core_deepcolor_ed { +- HDMI_DEEPCOLORPACKECTDISABLE = 0, +- HDMI_DEEPCOLORPACKECTENABLE = 1 +-}; +- +-enum hdmi_core_packet_mode { +- HDMI_PACKETMODERESERVEDVALUE = 0, +- HDMI_PACKETMODE24BITPERPIXEL = 4, +- HDMI_PACKETMODE30BITPERPIXEL = 5, +- HDMI_PACKETMODE36BITPERPIXEL = 6, +- HDMI_PACKETMODE48BITPERPIXEL = 7 +-}; +- +-enum hdmi_core_tclkselclkmult { +- HDMI_FPLL05IDCK = 0, +- HDMI_FPLL10IDCK = 1, +- HDMI_FPLL20IDCK = 2, +- HDMI_FPLL40IDCK = 3 +-}; +- +-enum hdmi_core_packet_ctrl { +- HDMI_PACKETENABLE = 1, +- HDMI_PACKETDISABLE = 0, +- HDMI_PACKETREPEATON = 1, +- HDMI_PACKETREPEATOFF = 0 +-}; +- +-/* INFOFRAME_AVI_ and INFOFRAME_AUDIO_ definitions */ +-enum hdmi_core_infoframe { +- HDMI_INFOFRAME_AVI_DB1Y_RGB = 0, +- HDMI_INFOFRAME_AVI_DB1Y_YUV422 = 1, +- HDMI_INFOFRAME_AVI_DB1Y_YUV444 = 2, +- HDMI_INFOFRAME_AVI_DB1A_ACTIVE_FORMAT_OFF = 0, +- HDMI_INFOFRAME_AVI_DB1A_ACTIVE_FORMAT_ON = 1, +- HDMI_INFOFRAME_AVI_DB1B_NO = 0, +- HDMI_INFOFRAME_AVI_DB1B_VERT = 1, +- HDMI_INFOFRAME_AVI_DB1B_HORI = 2, +- HDMI_INFOFRAME_AVI_DB1B_VERTHORI = 3, +- HDMI_INFOFRAME_AVI_DB1S_0 = 0, +- HDMI_INFOFRAME_AVI_DB1S_1 = 1, +- HDMI_INFOFRAME_AVI_DB1S_2 = 2, +- HDMI_INFOFRAME_AVI_DB2C_NO = 0, +- HDMI_INFOFRAME_AVI_DB2C_ITU601 = 1, +- HDMI_INFOFRAME_AVI_DB2C_ITU709 = 2, +- HDMI_INFOFRAME_AVI_DB2C_EC_EXTENDED = 3, +- HDMI_INFOFRAME_AVI_DB2M_NO = 0, +- HDMI_INFOFRAME_AVI_DB2M_43 = 1, +- HDMI_INFOFRAME_AVI_DB2M_169 = 2, +- HDMI_INFOFRAME_AVI_DB2R_SAME = 8, +- HDMI_INFOFRAME_AVI_DB2R_43 = 9, +- HDMI_INFOFRAME_AVI_DB2R_169 = 10, +- HDMI_INFOFRAME_AVI_DB2R_149 = 11, +- HDMI_INFOFRAME_AVI_DB3ITC_NO = 0, +- HDMI_INFOFRAME_AVI_DB3ITC_YES = 1, +- HDMI_INFOFRAME_AVI_DB3EC_XVYUV601 = 0, +- HDMI_INFOFRAME_AVI_DB3EC_XVYUV709 = 1, +- HDMI_INFOFRAME_AVI_DB3Q_DEFAULT = 0, +- HDMI_INFOFRAME_AVI_DB3Q_LR = 1, +- HDMI_INFOFRAME_AVI_DB3Q_FR = 2, +- HDMI_INFOFRAME_AVI_DB3SC_NO = 0, +- HDMI_INFOFRAME_AVI_DB3SC_HORI = 1, +- HDMI_INFOFRAME_AVI_DB3SC_VERT = 2, +- HDMI_INFOFRAME_AVI_DB3SC_HORIVERT = 3, +- HDMI_INFOFRAME_AVI_DB5PR_NO = 0, +- HDMI_INFOFRAME_AVI_DB5PR_2 = 1, +- HDMI_INFOFRAME_AVI_DB5PR_3 = 2, +- HDMI_INFOFRAME_AVI_DB5PR_4 = 3, +- HDMI_INFOFRAME_AVI_DB5PR_5 = 4, +- HDMI_INFOFRAME_AVI_DB5PR_6 = 5, +- HDMI_INFOFRAME_AVI_DB5PR_7 = 6, +- HDMI_INFOFRAME_AVI_DB5PR_8 = 7, +- HDMI_INFOFRAME_AVI_DB5PR_9 = 8, +- HDMI_INFOFRAME_AVI_DB5PR_10 = 9, +-}; +- +-enum hdmi_packing_mode { +- HDMI_PACK_10b_RGB_YUV444 = 0, +- HDMI_PACK_24b_RGB_YUV444_YUV422 = 1, +- HDMI_PACK_20b_YUV422 = 2, +- HDMI_PACK_ALREADYPACKED = 7 +-}; +- +-enum hdmi_core_audio_layout { +- HDMI_AUDIO_LAYOUT_2CH = 0, +- HDMI_AUDIO_LAYOUT_8CH = 1 +-}; +- +-enum hdmi_core_cts_mode { +- HDMI_AUDIO_CTS_MODE_HW = 0, +- HDMI_AUDIO_CTS_MODE_SW = 1 +-}; +- +-enum hdmi_stereo_channels { +- HDMI_AUDIO_STEREO_NOCHANNELS = 0, +- HDMI_AUDIO_STEREO_ONECHANNEL = 1, +- HDMI_AUDIO_STEREO_TWOCHANNELS = 2, +- HDMI_AUDIO_STEREO_THREECHANNELS = 3, +- HDMI_AUDIO_STEREO_FOURCHANNELS = 4 +-}; +- +-enum hdmi_audio_type { +- HDMI_AUDIO_TYPE_LPCM = 0, +- HDMI_AUDIO_TYPE_IEC = 1 +-}; +- +-enum hdmi_audio_justify { +- HDMI_AUDIO_JUSTIFY_LEFT = 0, +- HDMI_AUDIO_JUSTIFY_RIGHT = 1 +-}; +- +-enum hdmi_audio_sample_order { +- HDMI_AUDIO_SAMPLE_RIGHT_FIRST = 0, +- HDMI_AUDIO_SAMPLE_LEFT_FIRST = 1 +-}; +- +-enum hdmi_audio_samples_perword { +- HDMI_AUDIO_ONEWORD_ONESAMPLE = 0, +- HDMI_AUDIO_ONEWORD_TWOSAMPLES = 1 +-}; +- +-enum hdmi_audio_sample_size { +- HDMI_AUDIO_SAMPLE_16BITS = 0, +- HDMI_AUDIO_SAMPLE_24BITS = 1 +-}; +- +-enum hdmi_audio_transf_mode { +- HDMI_AUDIO_TRANSF_DMA = 0, +- HDMI_AUDIO_TRANSF_IRQ = 1 +-}; +- +-enum hdmi_audio_blk_strt_end_sig { +- HDMI_AUDIO_BLOCK_SIG_STARTEND_ON = 0, +- HDMI_AUDIO_BLOCK_SIG_STARTEND_OFF = 1 +-}; +- +-enum hdmi_audio_i2s_config { +- HDMI_AUDIO_I2S_MSB_SHIFTED_FIRST = 0, +- HDMI_AUDIO_I2S_LSB_SHIFTED_FIRST = 1, +- HDMI_AUDIO_I2S_SCK_EDGE_FALLING = 0, +- HDMI_AUDIO_I2S_SCK_EDGE_RISING = 1, +- HDMI_AUDIO_I2S_VBIT_FOR_PCM = 0, +- HDMI_AUDIO_I2S_VBIT_FOR_COMPRESSED = 1, +- HDMI_AUDIO_I2S_FIRST_BIT_SHIFT = 0, +- HDMI_AUDIO_I2S_FIRST_BIT_NO_SHIFT = 1, +- HDMI_AUDIO_I2S_SD0_EN = 1, +- HDMI_AUDIO_I2S_SD1_EN = 1 << 1, +- HDMI_AUDIO_I2S_SD2_EN = 1 << 2, +- HDMI_AUDIO_I2S_SD3_EN = 1 << 3, +-}; +- +-enum hdmi_audio_mclk_mode { +- HDMI_AUDIO_MCLK_128FS = 0, +- HDMI_AUDIO_MCLK_256FS = 1, +- HDMI_AUDIO_MCLK_384FS = 2, +- HDMI_AUDIO_MCLK_512FS = 3, +- HDMI_AUDIO_MCLK_768FS = 4, +- HDMI_AUDIO_MCLK_1024FS = 5, +- HDMI_AUDIO_MCLK_1152FS = 6, +- HDMI_AUDIO_MCLK_192FS = 7 +-}; +- +-struct hdmi_core_video_config { +- enum hdmi_core_inputbus_width ip_bus_width; +- enum hdmi_core_dither_trunc op_dither_truc; +- enum hdmi_core_deepcolor_ed deep_color_pkt; +- enum hdmi_core_packet_mode pkt_mode; +- enum hdmi_core_hdmi_dvi hdmi_dvi; +- enum hdmi_core_tclkselclkmult tclk_sel_clkmult; +-}; +- +-struct hdmi_core_packet_enable_repeat { +- u32 audio_pkt; +- u32 audio_pkt_repeat; +- u32 avi_infoframe; +- u32 avi_infoframe_repeat; +- u32 gen_cntrl_pkt; +- u32 gen_cntrl_pkt_repeat; +- u32 generic_pkt; +- u32 generic_pkt_repeat; +-}; +- +-struct hdmi_video_format { +- enum hdmi_packing_mode packing_mode; +- u32 y_res; /* Line per panel */ +- u32 x_res; /* pixel per line */ +-}; +- +-struct hdmi_audio_format { +- enum hdmi_stereo_channels stereo_channels; +- u8 active_chnnls_msk; +- enum hdmi_audio_type type; +- enum hdmi_audio_justify justification; +- enum hdmi_audio_sample_order sample_order; +- enum hdmi_audio_samples_perword samples_per_word; +- enum hdmi_audio_sample_size sample_size; +- enum hdmi_audio_blk_strt_end_sig en_sig_blk_strt_end; +-}; +- +-struct hdmi_audio_dma { +- u8 transfer_size; +- u8 block_size; +- enum hdmi_audio_transf_mode mode; +- u16 fifo_threshold; +-}; +- +-struct hdmi_core_audio_i2s_config { +- u8 in_length_bits; +- u8 justification; +- u8 sck_edge_mode; +- u8 vbit; +- u8 direction; +- u8 shift; +- u8 active_sds; +-}; +- +-struct hdmi_core_audio_config { +- struct hdmi_core_audio_i2s_config i2s_cfg; +- struct snd_aes_iec958 *iec60958_cfg; +- bool fs_override; +- u32 n; +- u32 cts; +- u32 aud_par_busclk; +- enum hdmi_core_audio_layout layout; +- enum hdmi_core_cts_mode cts_mode; +- bool use_mclk; +- enum hdmi_audio_mclk_mode mclk_mode; +- bool en_acr_pkt; +- bool en_dsd_audio; +- bool en_parallel_aud_input; +- bool en_spdif; +-}; +- +-#endif +--- a/drivers/video/omap2/dss/ti_hdmi.h ++++ /dev/null +@@ -1,187 +0,0 @@ +-/* +- * ti_hdmi.h +- * +- * HDMI driver definition for TI OMAP4, DM81xx, DM38xx Processor. +- * +- * Copyright (C) 2010-2011 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 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, see <http://www.gnu.org/licenses/>. +- */ +- +-#ifndef _TI_HDMI_H +-#define _TI_HDMI_H +- +-struct hdmi_ip_data; +- +-enum hdmi_pll_pwr { +- HDMI_PLLPWRCMD_ALLOFF = 0, +- HDMI_PLLPWRCMD_PLLONLY = 1, +- HDMI_PLLPWRCMD_BOTHON_ALLCLKS = 2, +- HDMI_PLLPWRCMD_BOTHON_NOPHYCLK = 3 +-}; +- +-enum hdmi_core_hdmi_dvi { +- HDMI_DVI = 0, +- HDMI_HDMI = 1 +-}; +- +-enum hdmi_clk_refsel { +- HDMI_REFSEL_PCLK = 0, +- HDMI_REFSEL_REF1 = 1, +- HDMI_REFSEL_REF2 = 2, +- HDMI_REFSEL_SYSCLK = 3 +-}; +- +-struct hdmi_cm { +- int code; +- int mode; +-}; +- +-struct hdmi_config { +- struct omap_video_timings timings; +- struct hdmi_cm cm; +-}; +- +-/* HDMI PLL structure */ +-struct hdmi_pll_info { +- u16 regn; +- u16 regm; +- u32 regmf; +- u16 regm2; +- u16 regsd; +- u16 dcofreq; +- enum hdmi_clk_refsel refsel; +-}; +- +-struct ti_hdmi_ip_ops { +- +- void (*video_configure)(struct hdmi_ip_data *ip_data); +- +- int (*phy_enable)(struct hdmi_ip_data *ip_data); +- +- void (*phy_disable)(struct hdmi_ip_data *ip_data); +- +- int (*read_edid)(struct hdmi_ip_data *ip_data, u8 *edid, int len); +- +- int (*pll_enable)(struct hdmi_ip_data *ip_data); +- +- void (*pll_disable)(struct hdmi_ip_data *ip_data); +- +- int (*video_enable)(struct hdmi_ip_data *ip_data); +- +- void (*video_disable)(struct hdmi_ip_data *ip_data); +- +- void (*dump_wrapper)(struct hdmi_ip_data *ip_data, struct seq_file *s); +- +- void (*dump_core)(struct hdmi_ip_data *ip_data, struct seq_file *s); +- +- void (*dump_pll)(struct hdmi_ip_data *ip_data, struct seq_file *s); +- +- void (*dump_phy)(struct hdmi_ip_data *ip_data, struct seq_file *s); +- +-#if defined(CONFIG_OMAP4_DSS_HDMI_AUDIO) +- int (*audio_enable)(struct hdmi_ip_data *ip_data); +- +- void (*audio_disable)(struct hdmi_ip_data *ip_data); +- +- int (*audio_start)(struct hdmi_ip_data *ip_data); +- +- void (*audio_stop)(struct hdmi_ip_data *ip_data); +- +- int (*audio_config)(struct hdmi_ip_data *ip_data, +- struct omap_dss_audio *audio); +- +- int (*audio_get_dma_port)(u32 *offset, u32 *size); +-#endif +- +-}; +- +-/* +- * Refer to section 8.2 in HDMI 1.3 specification for +- * details about infoframe databytes +- */ +-struct hdmi_core_infoframe_avi { +- /* Y0, Y1 rgb,yCbCr */ +- u8 db1_format; +- /* A0 Active information Present */ +- u8 db1_active_info; +- /* B0, B1 Bar info data valid */ +- u8 db1_bar_info_dv; +- /* S0, S1 scan information */ +- u8 db1_scan_info; +- /* C0, C1 colorimetry */ +- u8 db2_colorimetry; +- /* M0, M1 Aspect ratio (4:3, 16:9) */ +- u8 db2_aspect_ratio; +- /* R0...R3 Active format aspect ratio */ +- u8 db2_active_fmt_ar; +- /* ITC IT content. */ +- u8 db3_itc; +- /* EC0, EC1, EC2 Extended colorimetry */ +- u8 db3_ec; +- /* Q1, Q0 Quantization range */ +- u8 db3_q_range; +- /* SC1, SC0 Non-uniform picture scaling */ +- u8 db3_nup_scaling; +- /* VIC0..6 Video format identification */ +- u8 db4_videocode; +- /* PR0..PR3 Pixel repetition factor */ +- u8 db5_pixel_repeat; +- /* Line number end of top bar */ +- u16 db6_7_line_eoftop; +- /* Line number start of bottom bar */ +- u16 db8_9_line_sofbottom; +- /* Pixel number end of left bar */ +- u16 db10_11_pixel_eofleft; +- /* Pixel number start of right bar */ +- u16 db12_13_pixel_sofright; +-}; +- +-struct hdmi_ip_data { +- void __iomem *base_wp; /* HDMI wrapper */ +- unsigned long core_sys_offset; +- unsigned long core_av_offset; +- unsigned long pll_offset; +- unsigned long phy_offset; +- int irq; +- const struct ti_hdmi_ip_ops *ops; +- struct hdmi_config cfg; +- struct hdmi_pll_info pll_data; +- struct hdmi_core_infoframe_avi avi_cfg; +- +- /* ti_hdmi_4xxx_ip private data. These should be in a separate struct */ +- struct mutex lock; +-}; +-int ti_hdmi_4xxx_phy_enable(struct hdmi_ip_data *ip_data); +-void ti_hdmi_4xxx_phy_disable(struct hdmi_ip_data *ip_data); +-int ti_hdmi_4xxx_read_edid(struct hdmi_ip_data *ip_data, u8 *edid, int len); +-int ti_hdmi_4xxx_wp_video_start(struct hdmi_ip_data *ip_data); +-void ti_hdmi_4xxx_wp_video_stop(struct hdmi_ip_data *ip_data); +-int ti_hdmi_4xxx_pll_enable(struct hdmi_ip_data *ip_data); +-void ti_hdmi_4xxx_pll_disable(struct hdmi_ip_data *ip_data); +-void ti_hdmi_4xxx_basic_configure(struct hdmi_ip_data *ip_data); +-void ti_hdmi_4xxx_wp_dump(struct hdmi_ip_data *ip_data, struct seq_file *s); +-void ti_hdmi_4xxx_pll_dump(struct hdmi_ip_data *ip_data, struct seq_file *s); +-void ti_hdmi_4xxx_core_dump(struct hdmi_ip_data *ip_data, struct seq_file *s); +-void ti_hdmi_4xxx_phy_dump(struct hdmi_ip_data *ip_data, struct seq_file *s); +-#if defined(CONFIG_OMAP4_DSS_HDMI_AUDIO) +-int hdmi_compute_acr(u32 sample_freq, u32 *n, u32 *cts); +-int ti_hdmi_4xxx_wp_audio_enable(struct hdmi_ip_data *ip_data); +-void ti_hdmi_4xxx_wp_audio_disable(struct hdmi_ip_data *ip_data); +-int ti_hdmi_4xxx_audio_start(struct hdmi_ip_data *ip_data); +-void ti_hdmi_4xxx_audio_stop(struct hdmi_ip_data *ip_data); +-int ti_hdmi_4xxx_audio_config(struct hdmi_ip_data *ip_data, +- struct omap_dss_audio *audio); +-int ti_hdmi_4xxx_audio_get_dma_port(u32 *offset, u32 *size); +-#endif +-#endif +--- a/drivers/video/omap2/dss/venc.c ++++ b/drivers/video/omap2/dss/venc.c +@@ -894,6 +894,12 @@ static const struct dev_pm_ops venc_pm_o + .runtime_resume = venc_runtime_resume, + }; + ++ ++static const struct of_device_id venc_of_match[] = { ++ { .compatible = "ti,omap3-venc", }, ++ {}, ++}; ++ + static struct platform_driver omap_venchw_driver = { + .probe = omap_venchw_probe, + .remove = __exit_p(omap_venchw_remove), +@@ -901,6 +907,7 @@ static struct platform_driver omap_vench + .name = "omapdss_venc", + .owner = THIS_MODULE, + .pm = &venc_pm_ops, ++ .of_match_table = venc_of_match, + }, + }; + +--- a/drivers/video/omap2/omapfb/omapfb-main.c ++++ b/drivers/video/omap2/omapfb/omapfb-main.c +@@ -2407,6 +2407,55 @@ static int omapfb_init_connections(struc + return 0; + } + ++static struct omap_dss_device * ++omapfb_find_default_display(struct omapfb2_device *fbdev) ++{ ++ const char *def_name; ++ int i; ++ ++ /* ++ * Search with the display name from the user or the board file, ++ * comparing to display names and aliases ++ */ ++ ++ def_name = omapdss_get_default_display_name(); ++ ++ if (def_name) { ++ for (i = 0; i < fbdev->num_displays; ++i) { ++ struct omap_dss_device *dssdev; ++ ++ dssdev = fbdev->displays[i].dssdev; ++ ++ if (dssdev->name && strcmp(def_name, dssdev->name) == 0) ++ return dssdev; ++ ++ if (strcmp(def_name, dssdev->alias) == 0) ++ return dssdev; ++ } ++ ++ /* def_name given but not found */ ++ return NULL; ++ } ++ ++ /* then look for DT alias display0 */ ++ for (i = 0; i < fbdev->num_displays; ++i) { ++ struct omap_dss_device *dssdev; ++ int id; ++ ++ dssdev = fbdev->displays[i].dssdev; ++ ++ if (dssdev->dev->of_node == NULL) ++ continue; ++ ++ id = of_alias_get_id(dssdev->dev->of_node, "display"); ++ if (id == 0) ++ return dssdev; ++ } ++ ++ /* return the first display we have in the list */ ++ return fbdev->displays[0].dssdev; ++} ++ + static int omapfb_probe(struct platform_device *pdev) + { + struct omapfb2_device *fbdev = NULL; +@@ -2484,23 +2533,7 @@ static int omapfb_probe(struct platform_ + for (i = 0; i < fbdev->num_managers; i++) + fbdev->managers[i] = omap_dss_get_overlay_manager(i); + +- def_display = NULL; +- +- for (i = 0; i < fbdev->num_displays; ++i) { +- struct omap_dss_device *dssdev; +- const char *def_name; +- +- def_name = omapdss_get_default_display_name(); +- +- dssdev = fbdev->displays[i].dssdev; +- +- if (def_name == NULL || +- (dssdev->name && strcmp(def_name, dssdev->name) == 0)) { +- def_display = dssdev; +- break; +- } +- } +- ++ def_display = omapfb_find_default_display(fbdev); + if (def_display == NULL) { + dev_err(fbdev->dev, "failed to find default display\n"); + r = -EPROBE_DEFER; +--- a/drivers/watchdog/omap_wdt.c ++++ b/drivers/watchdog/omap_wdt.c +@@ -41,7 +41,9 @@ + #include <linux/io.h> + #include <linux/slab.h> + #include <linux/pm_runtime.h> ++#include <linux/interrupt.h> + #include <linux/platform_data/omap-wd-timer.h> ++#include <linux/of.h> + + #include "omap_wdt.h" + +@@ -54,6 +56,10 @@ static unsigned timer_margin; + module_param(timer_margin, uint, 0); + MODULE_PARM_DESC(timer_margin, "initial watchdog timeout (in seconds)"); + ++static int kernelpet = 1; ++module_param(kernelpet, int, 0); ++MODULE_PARM_DESC(kernelpet, "pet watchdog in kernel via irq"); ++ + struct omap_wdt_dev { + void __iomem *base; /* physical */ + struct device *dev; +@@ -112,6 +118,7 @@ static void omap_wdt_set_timer(struct om + unsigned int timeout) + { + u32 pre_margin = GET_WLDR_VAL(timeout); ++ u32 delay_period = GET_WLDR_VAL(timeout / 2); + void __iomem *base = wdev->base; + + /* just count up at 32 KHz */ +@@ -121,6 +128,26 @@ static void omap_wdt_set_timer(struct om + __raw_writel(pre_margin, base + OMAP_WATCHDOG_LDR); + while (__raw_readl(base + OMAP_WATCHDOG_WPS) & 0x04) + cpu_relax(); ++ ++ /* Set delay interrupt to half the watchdog interval. */ ++ while (__raw_readl(base + OMAP_WATCHDOG_WPS) & 1 << 5) ++ cpu_relax(); ++ __raw_writel(delay_period, base + OMAP_WATCHDOG_WDLY); ++} ++ ++static irqreturn_t omap_wdt_interrupt(int irq, void *dev_id) ++{ ++ struct watchdog_device *wdog = dev_id; ++ struct omap_wdt_dev *wdev = watchdog_get_drvdata(wdog); ++ void __iomem *base = wdev->base; ++ u32 i; ++ ++ i = __raw_readl(base + OMAP_WATCHDOG_WIRQSTAT); ++ __raw_writel(i, base + OMAP_WATCHDOG_WIRQSTAT); ++ ++ omap_wdt_reload(wdev); ++ ++ return IRQ_HANDLED; + } + + static int omap_wdt_start(struct watchdog_device *wdog) +@@ -144,6 +171,13 @@ static int omap_wdt_start(struct watchdo + + omap_wdt_set_timer(wdev, wdog->timeout); + omap_wdt_reload(wdev); /* trigger loading of new timeout value */ ++ ++ /* Enable delay interrupt */ ++ if (kernelpet) { ++ __raw_writel(0x2, base + OMAP_WATCHDOG_WIRQENSET); ++ __raw_writel(0x2, base + OMAP_WATCHDOG_WIRQWAKEEN); ++ } ++ + omap_wdt_enable(wdev); + + mutex_unlock(&wdev->lock); +@@ -154,9 +188,16 @@ static int omap_wdt_start(struct watchdo + static int omap_wdt_stop(struct watchdog_device *wdog) + { + struct omap_wdt_dev *wdev = watchdog_get_drvdata(wdog); ++ void __iomem *base = wdev->base; + + mutex_lock(&wdev->lock); + omap_wdt_disable(wdev); ++ /* Disable delay interrupt */ ++ if (kernelpet) { ++ __raw_writel(0x0, base + OMAP_WATCHDOG_WIRQWAKEEN); ++ __raw_writel(0x2, base + OMAP_WATCHDOG_WIRQENCLR); ++ } ++ + pm_runtime_put_sync(wdev->dev); + wdev->omap_wdt_users = false; + mutex_unlock(&wdev->lock); +@@ -167,6 +208,11 @@ static int omap_wdt_ping(struct watchdog + { + struct omap_wdt_dev *wdev = watchdog_get_drvdata(wdog); + ++ if (kernelpet) { ++ pr_info("Hw ping is enabled,Skipping userspace ping\n"); ++ return 0; ++ } ++ + mutex_lock(&wdev->lock); + omap_wdt_reload(wdev); + mutex_unlock(&wdev->lock); +@@ -210,7 +256,7 @@ static int omap_wdt_probe(struct platfor + struct resource *res, *mem; + struct omap_wdt_dev *wdev; + u32 rs; +- int ret; ++ int ret, irq; + + omap_wdt = devm_kzalloc(&pdev->dev, sizeof(*omap_wdt), GFP_KERNEL); + if (!omap_wdt) +@@ -240,6 +286,23 @@ static int omap_wdt_probe(struct platfor + if (!wdev->base) + return -ENOMEM; + ++ if (pdev->dev.of_node) { ++ if (of_device_is_compatible(pdev->dev.of_node, "ti,omap3-wdt")) ++ kernelpet = 0; ++ } else { ++ if (pdata->ip_rev == WDTIMER2_IP3) ++ kernelpet = 0; ++ } ++ ++ if (kernelpet) { ++ irq = platform_get_irq(pdev, 0); ++ ret = devm_request_irq(&pdev->dev, irq, omap_wdt_interrupt, 0, ++ dev_name(&pdev->dev), omap_wdt); ++ if (ret < 0) ++ dev_err(&pdev->dev, "can't get irq %d, err %d\n", ++ irq, ret); ++ } ++ + omap_wdt->info = &omap_wdt_info; + omap_wdt->ops = &omap_wdt_ops; + omap_wdt->min_timeout = TIMER_MARGIN_MIN; +@@ -280,6 +343,12 @@ static int omap_wdt_probe(struct platfor + + pm_runtime_put_sync(wdev->dev); + ++ if (kernelpet) { ++ ret = omap_wdt_start(omap_wdt); ++ if (ret == 0) ++ set_bit(WDOG_ACTIVE, &omap_wdt->status); ++ } ++ + return 0; + } + +@@ -300,6 +369,13 @@ static int omap_wdt_remove(struct platfo + { + struct watchdog_device *wdog = platform_get_drvdata(pdev); + struct omap_wdt_dev *wdev = watchdog_get_drvdata(wdog); ++ int ret; ++ ++ if (kernelpet) { ++ ret = omap_wdt_stop(wdog); ++ if (ret == 0) ++ clear_bit(WDOG_ACTIVE, &wdog->status); ++ } + + pm_runtime_disable(wdev->dev); + watchdog_unregister_device(wdog); +@@ -352,7 +428,8 @@ static int omap_wdt_resume(struct platfo + #endif + + static const struct of_device_id omap_wdt_of_match[] = { +- { .compatible = "ti,omap3-wdt", }, ++ { .compatible = "ti,omap3-wdt" }, ++ { .compatible = "ti,omap4-wdt" }, + {}, + }; + MODULE_DEVICE_TABLE(of, omap_wdt_of_match); +--- a/drivers/watchdog/omap_wdt.h ++++ b/drivers/watchdog/omap_wdt.h +@@ -38,7 +38,12 @@ + #define OMAP_WATCHDOG_LDR (0x2c) + #define OMAP_WATCHDOG_TGR (0x30) + #define OMAP_WATCHDOG_WPS (0x34) ++#define OMAP_WATCHDOG_WDLY (0x44) + #define OMAP_WATCHDOG_SPR (0x48) ++#define OMAP_WATCHDOG_WIRQSTAT (0x58) ++#define OMAP_WATCHDOG_WIRQENSET (0x5c) ++#define OMAP_WATCHDOG_WIRQENCLR (0x60) ++#define OMAP_WATCHDOG_WIRQWAKEEN (0x64) + + /* Using the prescaler, the OMAP watchdog could go for many + * months before firing. These limits work without scaling, +--- /dev/null ++++ b/include/dt-bindings/mfd/palmas.h +@@ -0,0 +1,18 @@ ++/* ++ * This header provides macros for Palmas device bindings. ++ * ++ * Copyright (c) 2013, NVIDIA Corporation. ++ * ++ * Author: Laxman Dewangan <ldewangan@nvidia.com> ++ * ++ */ ++ ++#ifndef __DT_BINDINGS_PALMAS_H__ ++#define __DT_BINDINGS_PALMAS_H ++ ++/* External control pins */ ++#define PALMAS_EXT_CONTROL_PIN_ENABLE1 1 ++#define PALMAS_EXT_CONTROL_PIN_ENABLE2 2 ++#define PALMAS_EXT_CONTROL_PIN_NSLEEP 3 ++ ++#endif /* __DT_BINDINGS_PALMAS_H */ +--- /dev/null ++++ b/include/dt-bindings/pinctrl/am43xx.h +@@ -0,0 +1,30 @@ ++/* ++ * This header provides constants specific to AM43XX pinctrl bindings. ++ */ ++ ++#ifndef _DT_BINDINGS_PINCTRL_AM43XX_H ++#define _DT_BINDINGS_PINCTRL_AM43XX_H ++ ++#define MUX_MODE0 0 ++#define MUX_MODE1 1 ++#define MUX_MODE2 2 ++#define MUX_MODE3 3 ++#define MUX_MODE4 4 ++#define MUX_MODE5 5 ++#define MUX_MODE6 6 ++#define MUX_MODE7 7 ++ ++#define PULL_DISABLE (1 << 16) ++#define PULL_UP (1 << 17) ++#define INPUT_EN (1 << 18) ++#define SLEWCTRL_FAST (1 << 19) ++#define DS0_PULL_UP_DOWN_EN (1 << 27) ++ ++#define PIN_OUTPUT (PULL_DISABLE) ++#define PIN_OUTPUT_PULLUP (PULL_UP) ++#define PIN_OUTPUT_PULLDOWN 0 ++#define PIN_INPUT (INPUT_EN | PULL_DISABLE) ++#define PIN_INPUT_PULLUP (INPUT_EN | PULL_UP) ++#define PIN_INPUT_PULLDOWN (INPUT_EN) ++ ++#endif +--- /dev/null ++++ b/include/dt-bindings/pinctrl/dra7xx.h +@@ -0,0 +1,48 @@ ++/* ++ * Copyright (C) 2013 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 version 2 as ++ * published by the Free Software Foundation. ++ */ ++/* ++ * This header provides constants specific to DRA7XX pinctrl bindings. ++ */ ++ ++#ifndef _DT_BINDINGS_PINCTRL_DRA7XX_H_ ++#define _DT_BINDINGS_PINCTRL_DRA7XX_H_ ++ ++/* dra7xx specific mux bit defines */ ++#define MUX_MODE0 0 ++#define MUX_MODE1 1 ++#define MUX_MODE2 2 ++#define MUX_MODE3 3 ++#define MUX_MODE4 4 ++#define MUX_MODE5 5 ++#define MUX_MODE6 6 ++#define MUX_MODE7 7 ++ ++#define PULL_ENA (1 << 16) ++#define PULL_UP (1 << 17) ++#define INPUT_EN (1 << 18) ++#define SLEWCTRL_FAST (1 << 19) ++#define WAKEUP_EN (1 << 24) ++#define WAKEUP_EVENT (1 << 25) ++ ++/* Active pin states */ ++#define PIN_OUTPUT 0 ++#define PIN_OUTPUT_PULLUP (PIN_OUTPUT | PULL_ENA | PULL_UP) ++#define PIN_OUTPUT_PULLDOWN (PIN_OUTPUT | PULL_ENA) ++#define PIN_INPUT INPUT_EN ++#define PIN_INPUT_PULLUP (PULL_ENA | INPUT_EN | PULL_UP) ++#define PIN_INPUT_PULLDOWN (PULL_ENA | INPUT_EN) ++ ++/* Off mode states */ ++#define PIN_OFF_NONE 0 ++#define PIN_OFF_OUTPUT_HIGH (OFF_EN | OFFOUT_EN | OFFOUT_VAL) ++#define PIN_OFF_OUTPUT_LOW (OFF_EN | OFFOUT_EN) ++#define PIN_OFF_INPUT_PULLUP (OFF_EN | OFF_PULL_EN | OFF_PULL_UP) ++#define PIN_OFF_INPUT_PULLDOWN (OFF_EN | OFF_PULL_EN) ++#define PIN_OFF_WAKEUPENABLE WAKEUP_EN ++ ++#endif +--- /dev/null ++++ b/include/linux/clk/ti.h +@@ -0,0 +1,245 @@ ++/* ++ * TI clock drivers support ++ * ++ * Copyright (C) 2013 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 "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 __LINUX_CLK_TI_H__ ++#define __LINUX_CLK_TI_H__ ++ ++#include <linux/clkdev.h> ++ ++/** ++ * struct dpll_data - DPLL registers and integration data ++ * @mult_div1_reg: register containing the DPLL M and N bitfields ++ * @mult_mask: mask of the DPLL M bitfield in @mult_div1_reg ++ * @div1_mask: mask of the DPLL N bitfield in @mult_div1_reg ++ * @clk_bypass: struct clk pointer to the clock's bypass clock input ++ * @clk_ref: struct clk pointer to the clock's reference clock input ++ * @control_reg: register containing the DPLL mode bitfield ++ * @enable_mask: mask of the DPLL mode bitfield in @control_reg ++ * @last_rounded_rate: cache of the last rate result of omap2_dpll_round_rate() ++ * @last_rounded_m: cache of the last M result of omap2_dpll_round_rate() ++ * @last_rounded_m4xen: cache of the last M4X result of ++ * omap4_dpll_regm4xen_round_rate() ++ * @last_rounded_lpmode: cache of the last lpmode result of ++ * omap4_dpll_lpmode_recalc() ++ * @max_multiplier: maximum valid non-bypass multiplier value (actual) ++ * @last_rounded_n: cache of the last N result of omap2_dpll_round_rate() ++ * @min_divider: minimum valid non-bypass divider value (actual) ++ * @max_divider: maximum valid non-bypass divider value (actual) ++ * @modes: possible values of @enable_mask ++ * @autoidle_reg: register containing the DPLL autoidle mode bitfield ++ * @idlest_reg: register containing the DPLL idle status bitfield ++ * @autoidle_mask: mask of the DPLL autoidle mode bitfield in @autoidle_reg ++ * @freqsel_mask: mask of the DPLL jitter correction bitfield in @control_reg ++ * @idlest_mask: mask of the DPLL idle status bitfield in @idlest_reg ++ * @lpmode_mask: mask of the DPLL low-power mode bitfield in @control_reg ++ * @m4xen_mask: mask of the DPLL M4X multiplier bitfield in @control_reg ++ * @auto_recal_bit: bitshift of the driftguard enable bit in @control_reg ++ * @recal_en_bit: bitshift of the PRM_IRQENABLE_* bit for recalibration IRQs ++ * @recal_st_bit: bitshift of the PRM_IRQSTATUS_* bit for recalibration IRQs ++ * @flags: DPLL type/features (see below) ++ * ++ * Possible values for @flags: ++ * DPLL_J_TYPE: "J-type DPLL" (only some 36xx, 4xxx DPLLs) ++ * ++ * @freqsel_mask is only used on the OMAP34xx family and AM35xx. ++ * ++ * XXX Some DPLLs have multiple bypass inputs, so it's not technically ++ * correct to only have one @clk_bypass pointer. ++ * ++ * XXX The runtime-variable fields (@last_rounded_rate, @last_rounded_m, ++ * @last_rounded_n) should be separated from the runtime-fixed fields ++ * and placed into a different structure, so that the runtime-fixed data ++ * can be placed into read-only space. ++ */ ++struct dpll_data { ++ void __iomem *mult_div1_reg; ++ u32 mult_mask; ++ u32 div1_mask; ++ struct clk *clk_bypass; ++ struct clk *clk_ref; ++ void __iomem *control_reg; ++ u32 enable_mask; ++ unsigned long last_rounded_rate; ++ u16 last_rounded_m; ++ u8 last_rounded_m4xen; ++ u8 last_rounded_lpmode; ++ u16 max_multiplier; ++ u8 last_rounded_n; ++ u8 min_divider; ++ u16 max_divider; ++ u8 modes; ++ void __iomem *autoidle_reg; ++ void __iomem *idlest_reg; ++ u32 autoidle_mask; ++ u32 freqsel_mask; ++ u32 idlest_mask; ++ u32 dco_mask; ++ u32 sddiv_mask; ++ u32 lpmode_mask; ++ u32 m4xen_mask; ++ u8 auto_recal_bit; ++ u8 recal_en_bit; ++ u8 recal_st_bit; ++ u8 flags; ++}; ++ ++struct clk_hw_omap_ops; ++ ++/** ++ * struct clk_hw_omap - OMAP struct clk ++ * @node: list_head connecting this clock into the full clock list ++ * @enable_reg: register to write to enable the clock (see @enable_bit) ++ * @enable_bit: bitshift to write to enable/disable the clock (see @enable_reg) ++ * @flags: see "struct clk.flags possibilities" above ++ * @clksel_reg: for clksel clks, register va containing src/divisor select ++ * @clksel_mask: bitmask in @clksel_reg for the src/divisor selector ++ * @clksel: for clksel clks, pointer to struct clksel for this clock ++ * @dpll_data: for DPLLs, pointer to struct dpll_data for this clock ++ * @clkdm_name: clockdomain name that this clock is contained in ++ * @clkdm: pointer to struct clockdomain, resolved from @clkdm_name at runtime ++ * @rate_offset: bitshift for rate selection bitfield (OMAP1 only) ++ * @src_offset: bitshift for source selection bitfield (OMAP1 only) ++ * ++ * XXX @rate_offset, @src_offset should probably be removed and OMAP1 ++ * clock code converted to use clksel. ++ * ++ */ ++struct clk_hw_omap { ++ struct clk_hw hw; ++ struct list_head node; ++ unsigned long fixed_rate; ++ u8 fixed_div; ++ void __iomem *enable_reg; ++ u8 enable_bit; ++ u8 flags; ++ void __iomem *clksel_reg; ++ u32 clksel_mask; ++ const struct clksel *clksel; ++ struct dpll_data *dpll_data; ++ const char *clkdm_name; ++ struct clockdomain *clkdm; ++ const struct clk_hw_omap_ops *ops; ++}; ++ ++/* ++ * struct clk_hw_omap.flags possibilities ++ * ++ * XXX document the rest of the clock flags here ++ * ++ * ENABLE_REG_32BIT: (OMAP1 only) clock control register must be accessed ++ * with 32bit ops, by default OMAP1 uses 16bit ops. ++ * CLOCK_IDLE_CONTROL: (OMAP1 only) clock has autoidle support. ++ * CLOCK_NO_IDLE_PARENT: (OMAP1 only) when clock is enabled, its parent ++ * clock is put to no-idle mode. ++ * ENABLE_ON_INIT: Clock is enabled on init. ++ * INVERT_ENABLE: By default, clock enable bit behavior is '1' enable, '0' ++ * disable. This inverts the behavior making '0' enable and '1' disable. ++ * CLOCK_CLKOUTX2: (OMAP4 only) DPLL CLKOUT and CLKOUTX2 GATE_CTRL ++ * bits share the same register. This flag allows the ++ * omap4_dpllmx*() code to determine which GATE_CTRL bit field ++ * should be used. This is a temporary solution - a better approach ++ * would be to associate clock type-specific data with the clock, ++ * similar to the struct dpll_data approach. ++ */ ++#define ENABLE_REG_32BIT (1 << 0) /* Use 32-bit access */ ++#define CLOCK_IDLE_CONTROL (1 << 1) ++#define CLOCK_NO_IDLE_PARENT (1 << 2) ++#define ENABLE_ON_INIT (1 << 3) /* Enable upon framework init */ ++#define INVERT_ENABLE (1 << 4) /* 0 enables, 1 disables */ ++#define CLOCK_CLKOUTX2 (1 << 5) ++ ++/* CM_CLKEN_PLL*.EN* bit values - not all are available for every DPLL */ ++#define DPLL_LOW_POWER_STOP 0x1 ++#define DPLL_LOW_POWER_BYPASS 0x5 ++#define DPLL_LOCKED 0x7 ++ ++/* DPLL Type and DCO Selection Flags */ ++#define DPLL_J_TYPE 0x1 ++ ++/** ++ * struct omap_dt_clk - OMAP DT clock alias declarations ++ * @lk: clock lookup definition ++ * @node_name: clock DT node to map to ++ */ ++struct omap_dt_clk { ++ struct clk_lookup lk; ++ char *node_name; ++}; ++ ++#define DT_CLK(dev, con, name) \ ++ { \ ++ .lk = { \ ++ .dev_id = dev, \ ++ .con_id = con, \ ++ }, \ ++ .node_name = name, \ ++ } ++ ++#define to_clk_hw_omap(_hw) container_of(_hw, struct clk_hw_omap, hw) ++ ++void omap2_init_clk_hw_omap_clocks(struct clk *clk); ++int omap3_noncore_dpll_enable(struct clk_hw *hw); ++void omap3_noncore_dpll_disable(struct clk_hw *hw); ++int omap3_noncore_dpll_set_rate(struct clk_hw *hw, unsigned long rate, ++ unsigned long parent_rate); ++unsigned long omap4_dpll_regm4xen_recalc(struct clk_hw *hw, ++ unsigned long parent_rate); ++long omap4_dpll_regm4xen_round_rate(struct clk_hw *hw, ++ unsigned long target_rate, ++ unsigned long *parent_rate); ++u8 omap2_init_dpll_parent(struct clk_hw *hw); ++unsigned long omap3_dpll_recalc(struct clk_hw *hw, unsigned long parent_rate); ++long omap2_dpll_round_rate(struct clk_hw *hw, unsigned long target_rate, ++ unsigned long *parent_rate); ++void omap2_init_clk_clkdm(struct clk_hw *clk); ++unsigned long omap3_clkoutx2_recalc(struct clk_hw *hw, ++ unsigned long parent_rate); ++int omap2_clkops_enable_clkdm(struct clk_hw *hw); ++void omap2_clkops_disable_clkdm(struct clk_hw *hw); ++int omap2_clk_disable_autoidle_all(void); ++void omap2_clk_enable_init_clocks(const char **clk_names, u8 num_clocks); ++int omap3_dpll4_set_rate(struct clk_hw *clk, unsigned long rate, ++ unsigned long parent_rate); ++int omap2_dflt_clk_enable(struct clk_hw *hw); ++void omap2_dflt_clk_disable(struct clk_hw *hw); ++int omap2_dflt_clk_is_enabled(struct clk_hw *hw); ++void omap3_clk_lock_dpll5(void); ++ ++void omap_dt_clocks_register(struct omap_dt_clk *oclks); ++#ifdef CONFIG_OF ++void of_omap_clk_allow_autoidle_all(void); ++void of_omap_clk_deny_autoidle_all(void); ++#else ++static inline void of_omap_clk_allow_autoidle_all(void) { } ++static inline void of_omap_clk_deny_autoidle_all(void) { } ++#endif ++ ++int omap5xxx_clk_init(void); ++int dra7xx_clk_init(void); ++int am43xx_clk_init(void); ++ ++extern const struct clk_hw_omap_ops clkhwops_omap3_dpll; ++extern const struct clk_hw_omap_ops clkhwops_omap4_dpllmx; ++extern const struct clk_hw_omap_ops clkhwops_wait; ++extern const struct clk_hw_omap_ops clkhwops_omap3430es2_dss_usbhost_wait; ++extern const struct clk_hw_omap_ops clkhwops_am35xx_ipss_module_wait; ++extern const struct clk_hw_omap_ops clkhwops_am35xx_ipss_wait; ++ ++extern const struct clk_hw_omap_ops clkhwops_iclk_wait; ++extern const struct clk_hw_omap_ops clkhwops_iclk; ++extern const struct clk_hw_omap_ops clkhwops_omap3430es2_iclk_ssi_wait; ++extern const struct clk_hw_omap_ops clkhwops_omap3430es2_iclk_dss_usbhost_wait; ++extern const struct clk_hw_omap_ops clkhwops_omap3430es2_iclk_hsotgusb_wait; ++ ++#endif +--- a/include/linux/clk-private.h ++++ b/include/linux/clk-private.h +@@ -122,7 +122,7 @@ struct clk { + }, \ + .reg = _reg, \ + .shift = _shift, \ +- .width = _width, \ ++ .mask = ((1 << _width) - 1), \ + .flags = _divider_flags, \ + .table = _table, \ + .lock = _lock, \ +--- a/include/linux/clk-provider.h ++++ b/include/linux/clk-provider.h +@@ -241,6 +241,8 @@ struct clk *clk_register_gate(struct dev + void __iomem *reg, u8 bit_idx, + u8 clk_gate_flags, spinlock_t *lock); + ++void of_gate_clk_setup(struct device_node *node); ++ + struct clk_div_table { + unsigned int val; + unsigned int div; +@@ -280,7 +282,7 @@ struct clk_divider { + struct clk_hw hw; + void __iomem *reg; + u8 shift; +- u8 width; ++ u32 mask; + u8 flags; + const struct clk_div_table *table; + spinlock_t *lock; +@@ -302,6 +304,8 @@ struct clk *clk_register_divider_table(s + u8 clk_divider_flags, const struct clk_div_table *table, + spinlock_t *lock); + ++void of_divider_clk_setup(struct device_node *node); ++ + /** + * struct clk_mux - multiplexer clock + * +@@ -351,7 +355,7 @@ struct clk *clk_register_mux_table(struc + void __iomem *reg, u8 shift, u32 mask, + u8 clk_mux_flags, u32 *table, spinlock_t *lock); + +-void of_fixed_factor_clk_setup(struct device_node *node); ++void of_mux_clk_setup(struct device_node *node); + + /** + * struct clk_fixed_factor - fixed multiplier and divider clock +@@ -372,10 +376,13 @@ struct clk_fixed_factor { + }; + + extern struct clk_ops clk_fixed_factor_ops; ++ + struct clk *clk_register_fixed_factor(struct device *dev, const char *name, + const char *parent_name, unsigned long flags, + unsigned int mult, unsigned int div); + ++void of_fixed_factor_clk_setup(struct device_node *node); ++ + /*** + * struct clk_composite - aggregate clock of mux, divider and gate clocks + * +@@ -472,6 +479,7 @@ void of_clk_del_provider(struct device_n + struct clk *of_clk_src_simple_get(struct of_phandle_args *clkspec, + void *data); + struct clk *of_clk_src_onecell_get(struct of_phandle_args *clkspec, void *data); ++int of_clk_get_parent_count(struct device_node *np); + const char *of_clk_get_parent_name(struct device_node *np, int index); + + void of_clk_init(const struct of_device_id *matches); +--- /dev/null ++++ b/include/linux/crossbar.h +@@ -0,0 +1,71 @@ ++/* ++ * IRQ/DMA CROSSBAR DRIVER ++ * ++ * Copyright (C) 2013 Texas Instruments Incorporated - http://www.ti.com/ ++ * Sricharan <r.sricharan@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; either version 2 of the License, or ++ * (at your option) any later version. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this program; if not, write to the Free Software ++ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 ++ * USA ++ */ ++#include <linux/io.h> ++#include <linux/of.h> ++#include <linux/of_irq.h> ++#include <linux/of_address.h> ++#include <linux/list.h> ++#include <linux/err.h> ++#include <linux/gfp.h> ++#include <linux/platform_device.h> ++ ++/* ++ * @base: base address of the crossbar device ++ * @dev: device ptr ++ * @name: name of the crossbar device ++ * @node: list node for the crossbar devices linked list ++ * @cb_entries: list of entries that belong to the crossbar ++ * @cb_lock: mutex ++ * @regmap pointer ++ */ ++struct cb_device { ++ void __iomem *base; ++ struct device *dev; ++ const char *name; ++ struct list_head node; ++ struct list_head cb_entries; ++ struct mutex cb_lock; ++ struct regmap *cb_regmap; ++}; ++ ++/* ++ * @cb_name: name of crossbar target to which this line is mapped ++ * @dev_name: mapped device input request name ++ * @cb_no: crossbar device input number ++ * @int_no: request number to which this input should be routed ++ * @offset: register offset address ++ */ ++struct cb_line { ++ const char *cb_name; ++ const char *dev_name; ++ unsigned cb_no; ++ unsigned int_no; ++ unsigned offset; ++}; ++ ++struct cb_entry { ++ struct cb_line line; ++ struct list_head cb_list; ++}; ++ ++int crossbar_map(struct device_node *cbdev_node); ++int crossbar_unmap(struct device_node *cbdev_node, unsigned index); +--- a/include/linux/i2c/twl.h ++++ b/include/linux/i2c/twl.h +@@ -26,6 +26,7 @@ + #define __TWL_H_ + + #include <linux/types.h> ++#include <linux/phy/phy.h> + #include <linux/input/matrix_keypad.h> + + /* +@@ -615,6 +616,7 @@ enum twl4030_usb_mode { + struct twl4030_usb_data { + enum twl4030_usb_mode usb_mode; + unsigned long features; ++ struct phy_init_data *init_data; + + int (*phy_init)(struct device *dev); + int (*phy_exit)(struct device *dev); +--- a/include/linux/input/pixcir_ts.h ++++ b/include/linux/input/pixcir_ts.h +@@ -1,10 +1,63 @@ + #ifndef _PIXCIR_I2C_TS_H + #define _PIXCIR_I2C_TS_H + ++/* ++ * Register map ++ */ ++#define PIXCIR_REG_POWER_MODE 51 ++#define PIXCIR_REG_INT_MODE 52 ++ ++/* ++ * Power modes: ++ * active: max scan speed ++ * idle: lower scan speed with automatic transition to active on touch ++ * halt: datasheet says sleep but this is more like halt as the chip ++ * clocks are cut and it can only be brought out of this mode ++ * using the RESET pin. ++ */ ++enum pixcir_power_mode { ++ PIXCIR_POWER_ACTIVE, ++ PIXCIR_POWER_IDLE, ++ PIXCIR_POWER_HALT, ++}; ++ ++#define PIXCIR_POWER_MODE_MASK 0x03 ++#define PIXCIR_POWER_ALLOW_IDLE (1UL << 2) ++ ++/* ++ * Interrupt modes: ++ * periodical: interrupt is asserted periodicaly ++ * diff coordinates: interrupt is asserted when coordinates change ++ * level on touch: interrupt level asserted during touch ++ * pulse on touch: interrupt pulse asserted druing touch ++ * ++ */ ++enum pixcir_int_mode { ++ PIXCIR_INT_PERIODICAL, ++ PIXCIR_INT_DIFF_COORD, ++ PIXCIR_INT_LEVEL_TOUCH, ++ PIXCIR_INT_PULSE_TOUCH, ++}; ++ ++#define PIXCIR_INT_MODE_MASK 0x03 ++#define PIXCIR_INT_ENABLE (1UL << 3) ++#define PIXCIR_INT_POL_HIGH (1UL << 2) ++ ++/** ++ * struct pixcir_irc_chip_data - chip related data ++ * @num_report_ids: Max number of finger ids reported simultaneously. ++ * if 0 it means chip doesn't support finger id reporting ++ * and driver will resort to Type A Multi-Touch reporting. ++ */ ++struct pixcir_i2c_chip_data { ++ u8 num_report_ids; ++}; ++ + struct pixcir_ts_platform_data { +- int (*attb_read_val)(void); +- int x_max; +- int y_max; ++ unsigned int x_size; /* X axis resolution */ ++ unsigned int y_size; /* Y axis resolution */ ++ int gpio_attb; /* GPIO connected to ATTB line */ ++ struct pixcir_i2c_chip_data chip; + }; + + #endif +--- /dev/null ++++ b/include/linux/mfd/tps65218.h +@@ -0,0 +1,288 @@ ++/* ++ * linux/mfd/tps65218.h ++ * ++ * Functions to access TPS65219 power management chip. ++ * ++ * Copyright (C) 2011 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 version 2 as ++ * published by the Free Software Foundation. ++ * ++ * This program is distributed "as is" WITHOUT ANY WARRANTY of any ++ * kind, whether expressed or implied; without even the implied warranty ++ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License version 2 for more details. ++ */ ++ ++#ifndef __LINUX_MFD_TPS65218_H ++#define __LINUX_MFD_TPS65218_H ++ ++#include <linux/i2c.h> ++#include <linux/regulator/driver.h> ++#include <linux/regulator/machine.h> ++#include <linux/bitops.h> ++ ++/* TPS chip id list */ ++#define TPS65218 0xF0 ++ ++/* I2C ID for TPS65218 part */ ++#define TPS65218_I2C_ID 0x24 ++ ++/* All register addresses */ ++#define TPS65218_REG_CHIPID 0x00 ++#define TPS65218_REG_INT1 0x01 ++#define TPS65218_REG_INT2 0x02 ++#define TPS65218_REG_INT_MASK1 0x03 ++#define TPS65218_REG_INT_MASK2 0x04 ++#define TPS65218_REG_STATUS 0x05 ++#define TPS65218_REG_CONTROL 0x06 ++#define TPS65218_REG_FLAG 0x07 ++ ++#define TPS65218_REG_PASSWORD 0x10 ++#define TPS65218_REG_ENABLE1 0x11 ++#define TPS65218_REG_ENABLE2 0x12 ++#define TPS65218_REG_CONFIG1 0x13 ++#define TPS65218_REG_CONFIG2 0x14 ++#define TPS65218_REG_CONFIG3 0x15 ++#define TPS65218_REG_CONTROL_DCDC1 0x16 ++#define TPS65218_REG_CONTROL_DCDC2 0x17 ++#define TPS65218_REG_CONTROL_DCDC3 0x18 ++#define TPS65218_REG_CONTROL_DCDC4 0x19 ++#define TPS65218_REG_CONTRL_SLEW_RATE 0x1A ++#define TPS65218_REG_CONTROL_LDO1 0x1B ++#define TPS65218_REG_SEQ1 0x20 ++#define TPS65218_REG_SEQ2 0x21 ++#define TPS65218_REG_SEQ3 0x22 ++#define TPS65218_REG_SEQ4 0x23 ++#define TPS65218_REG_SEQ5 0x24 ++#define TPS65218_REG_SEQ6 0x25 ++#define TPS65218_REG_SEQ7 0x26 ++ ++/* Register field definitions */ ++#define TPS65218_CHIPID_CHIP_MASK 0xF8 ++#define TPS65218_CHIPID_REV_MASK 0x07 ++ ++#define TPS65218_INT1_VPRG BIT(5) ++#define TPS65218_INT1_AC BIT(4) ++#define TPS65218_INT1_PB BIT(3) ++#define TPS65218_INT1_HOT BIT(2) ++#define TPS65218_INT1_CC_AQC BIT(1) ++#define TPS65218_INT1_PRGC BIT(0) ++ ++#define TPS65218_INT2_LS3_F BIT(5) ++#define TPS65218_INT2_LS2_F BIT(4) ++#define TPS65218_INT2_LS1_F BIT(3) ++#define TPS65218_INT2_LS3_I BIT(2) ++#define TPS65218_INT2_LS2_I BIT(1) ++#define TPS65218_INT2_LS1_I BIT(0) ++ ++#define TPS65218_INT_MASK1_VPRG BIT(5) ++#define TPS65218_INT_MASK1_AC BIT(4) ++#define TPS65218_INT_MASK1_PB BIT(3) ++#define TPS65218_INT_MASK1_HOT BIT(2) ++#define TPS65218_INT_MASK1_CC_AQC BIT(1) ++#define TPS65218_INT_MASK1_PRGC BIT(0) ++ ++#define TPS65218_INT_MASK2_LS3_F BIT(5) ++#define TPS65218_INT_MASK2_LS2_F BIT(4) ++#define TPS65218_INT_MASK2_LS1_F BIT(3) ++#define TPS65218_INT_MASK2_LS3_I BIT(2) ++#define TPS65218_INT_MASK2_LS2_I BIT(1) ++#define TPS65218_INT_MASK2_LS1_I BIT(0) ++ ++#define TPS65218_STATUS_FSEAL BIT(7) ++#define TPS65218_STATUS_EE BIT(6) ++#define TPS65218_STATUS_AC_STATE BIT(5) ++#define TPS65218_STATUS_PB_STATE BIT(4) ++#define TPS65218_STATUS_STATE_MASK 0xC ++#define TPS65218_STATUS_CC_STAT 0x3 ++ ++#define TPS65218_CONTROL_OFFNPFO BIT(1) ++#define TPS65218_CONTROL_CC_AQ BIT(0) ++ ++#define TPS65218_FLAG_GPO3_FLG BIT(7) ++#define TPS65218_FLAG_GPO2_FLG BIT(6) ++#define TPS65218_FLAG_GPO1_FLG BIT(5) ++#define TPS65218_FLAG_LDO1_FLG BIT(4) ++#define TPS65218_FLAG_DC4_FLG BIT(3) ++#define TPS65218_FLAG_DC3_FLG BIT(2) ++#define TPS65218_FLAG_DC2_FLG BIT(1) ++#define TPS65218_FLAG_DC1_FLG BIT(0) ++ ++#define TPS65218_ENABLE1_DC6_EN BIT(5) ++#define TPS65218_ENABLE1_DC5_EN BIT(4) ++#define TPS65218_ENABLE1_DC4_EN BIT(3) ++#define TPS65218_ENABLE1_DC3_EN BIT(2) ++#define TPS65218_ENABLE1_DC2_EN BIT(1) ++#define TPS65218_ENABLE1_DC1_EN BIT(0) ++ ++#define TPS65218_ENABLE2_GPIO3 BIT(6) ++#define TPS65218_ENABLE2_GPIO2 BIT(5) ++#define TPS65218_ENABLE2_GPIO1 BIT(4) ++#define TPS65218_ENABLE2_LS3_EN BIT(3) ++#define TPS65218_ENABLE2_LS2_EN BIT(2) ++#define TPS65218_ENABLE2_LS1_EN BIT(1) ++#define TPS65218_ENABLE2_LDO1_EN BIT(0) ++ ++ ++#define TPS65218_CONFIG1_TRST BIT(7) ++#define TPS65218_CONFIG1_GPO2_BUF BIT(6) ++#define TPS65218_CONFIG1_IO1_SEL BIT(5) ++#define TPS65218_CONFIG1_PGDLY_MASK 0x18 ++#define TPS65218_CONFIG1_STRICT BIT(2) ++#define TPS65218_CONFIG1_UVLO_MASK 0x3 ++ ++#define TPS65218_CONFIG2_DC12_RST BIT(7) ++#define TPS65218_CONFIG2_UVLOHYS BIT(6) ++#define TPS65218_CONFIG2_LS3ILIM_MASK 0xC ++#define TPS65218_CONFIG2_LS2ILIM_MASK 0x3 ++ ++#define TPS65218_CONFIG3_LS3NPFO BIT(5) ++#define TPS65218_CONFIG3_LS2NPFO BIT(4) ++#define TPS65218_CONFIG3_LS1NPFO BIT(3) ++#define TPS65218_CONFIG3_LS3DCHRG BIT(2) ++#define TPS65218_CONFIG3_LS2DCHRG BIT(1) ++#define TPS65218_CONFIG3_LS1DCHRG BIT(0) ++ ++#define TPS65218_CONTROL_DCDC1_PFM BIT(7) ++#define TPS65218_CONTROL_DCDC1_MASK 0x7F ++ ++#define TPS65218_CONTROL_DCDC2_PFM BIT(7) ++#define TPS65218_CONTROL_DCDC2_MASK 0x3F ++ ++#define TPS65218_CONTROL_DCDC3_PFM BIT(7) ++#define TPS65218_CONTROL_DCDC3_MASK 0x3F ++ ++#define TPS65218_CONTROL_DCDC4_PFM BIT(7) ++#define TPS65218_CONTROL_DCDC4_MASK 0x3F ++ ++#define TPS65218_SLEW_RATE_GO BIT(7) ++#define TPS65218_SLEW_RATE_GODSBL BIT(6) ++#define TPS65218_SLEW_RATE_SLEW_MASK 0x7 ++ ++#define TPS65218_CONTROL_LDO1_MASK 0x3F ++ ++#define TPS65218_SEQ1_DLY8 BIT(7) ++#define TPS65218_SEQ1_DLY7 BIT(6) ++#define TPS65218_SEQ1_DLY6 BIT(5) ++#define TPS65218_SEQ1_DLY5 BIT(4) ++#define TPS65218_SEQ1_DLY4 BIT(3) ++#define TPS65218_SEQ1_DLY3 BIT(2) ++#define TPS65218_SEQ1_DLY2 BIT(1) ++#define TPS65218_SEQ1_DLY1 BIT(0) ++ ++#define TPS65218_SEQ2_DLYFCTR BIT(7) ++#define TPS65218_SEQ2_DLY9 BIT(0) ++ ++#define TPS65218_SEQ3_DC2_SEQ_MASK 0xF0 ++#define TPS65218_SEQ3_DC1_SEQ_MASK 0xF ++ ++#define TPS65218_SEQ4_DC4_SEQ_MASK 0xF0 ++#define TPS65218_SEQ4_DC3_SEQ_MASK 0xF ++ ++#define TPS65218_SEQ5_DC6_SEQ_MASK 0xF0 ++#define TPS65218_SEQ5_DC5_SEQ_MASK 0xF ++ ++#define TPS65218_SEQ6_LS1_SEQ_MASK 0xF0 ++#define TPS65218_SEQ6_LDO1_SEQ_MASK 0xF ++ ++#define TPS65218_SEQ7_GPO3_SEQ_MASK 0xF0 ++#define TPS65218_SEQ7_GPO1_SEQ_MASK 0xF ++#define TPS65218_PROTECT_NONE 0 ++#define TPS65218_PROTECT_L1 1 ++ ++enum tps65218_regulator_id { ++ /* DCDC's */ ++ TPS65218_DCDC_1, ++ TPS65218_DCDC_2, ++ TPS65218_DCDC_3, ++ TPS65218_DCDC_4, ++ TPS65218_DCDC_5, ++ TPS65218_DCDC_6, ++ /* LDOs */ ++ TPS65218_LDO_1, ++}; ++ ++#define TPS65218_MAX_REG_ID TPS65218_LDO_1 ++ ++/* Number of step-down converters available */ ++#define TPS65218_NUM_DCDC 6 ++/* Number of LDO voltage regulators available */ ++#define TPS65218_NUM_LDO 1 ++/* Number of total regulators available */ ++#define TPS65218_NUM_REGULATOR (TPS65218_NUM_DCDC + TPS65218_NUM_LDO) ++ ++/* Define the TPS65218 IRQ numbers */ ++enum tps65218_irqs { ++ /* INT1 registers */ ++ TPS65218_PRGC_IRQ, ++ TPS65218_CC_AQC_IRQ, ++ TPS65218_HOT_IRQ, ++ TPS65218_PB_IRQ, ++ TPS65218_AC_IRQ, ++ TPS65218_VPRG_IRQ, ++ TPS65218_INVALID1_IRQ, ++ TPS65218_INVALID2_IRQ, ++ /* INT2 registers */ ++ TPS65218_LS1_I_IRQ, ++ TPS65218_LS2_I_IRQ, ++ TPS65218_LS3_I_IRQ, ++ TPS65218_LS1_F_IRQ, ++ TPS65218_LS2_F_IRQ, ++ TPS65218_LS3_F_IRQ, ++ TPS65218_INVALID3_IRQ, ++ TPS65218_INVALID4_IRQ, ++}; ++ ++/** ++ * struct tps_info - packages regulator constraints ++ * @id: Id of the regulator ++ * @name: Voltage regulator name ++ * @min_uV: minimum micro volts ++ * @max_uV: minimum micro volts ++ * @vsel_to_uv: Function pointer to get voltage from selector ++ * @uv_to_vsel: Function pointer to get selector from voltage ++ * ++ * This data is used to check the regualtor voltage limits while setting. ++ */ ++struct tps_info { ++ int id; ++ const char *name; ++ int min_uV; ++ int max_uV; ++ int (*vsel_to_uv)(unsigned int vsel); ++ int (*uv_to_vsel)(int uV, unsigned int *vsel); ++}; ++ ++/** ++ * struct tps65218 - tps65218 sub-driver chip access routines ++ * ++ * Device data may be used to access the TPS65218 chip ++ */ ++ ++struct tps65218 { ++ struct device *dev; ++ unsigned int id; ++ ++ struct mutex tps_lock; /* lock guarding the data structure */ ++ /* IRQ Data */ ++ int irq; ++ u32 irq_mask; ++ struct regmap_irq_chip_data *irq_data; ++ struct regulator_desc desc[TPS65218_NUM_REGULATOR]; ++ struct regulator_dev *rdev[TPS65218_NUM_REGULATOR]; ++ struct tps_info *info[TPS65218_NUM_REGULATOR]; ++ struct regmap *regmap; ++}; ++ ++int tps65218_reg_read(struct tps65218 *tps, unsigned int reg, ++ unsigned int *val); ++int tps65218_reg_write(struct tps65218 *tps, unsigned int reg, ++ unsigned int val, unsigned int level); ++int tps65218_set_bits(struct tps65218 *tps, unsigned int reg, ++ unsigned int mask, unsigned int val, unsigned int level); ++int tps65218_clear_bits(struct tps65218 *tps, unsigned int reg, ++ unsigned int mask, unsigned int level); ++ ++#endif /* __LINUX_MFD_TPS65218_H */ +--- a/include/linux/mfd/twl6040.h ++++ b/include/linux/mfd/twl6040.h +@@ -28,6 +28,7 @@ + #include <linux/interrupt.h> + #include <linux/mfd/core.h> + #include <linux/regulator/consumer.h> ++#include <linux/clk.h> + + #define TWL6040_REG_ASICID 0x01 + #define TWL6040_REG_ASICREV 0x02 +@@ -222,6 +223,7 @@ struct twl6040 { + struct regmap *regmap; + struct regmap_irq_chip_data *irq_data; + struct regulator_bulk_data supplies[2]; /* supplies for vio, v2v1 */ ++ struct clk *clk32k; + struct mutex mutex; + struct mutex irq_mutex; + struct mfd_cell cells[TWL6040_CELLS]; +--- a/include/linux/omap-mailbox.h ++++ b/include/linux/omap-mailbox.h +@@ -9,20 +9,27 @@ + #ifndef OMAP_MAILBOX_H + #define OMAP_MAILBOX_H + ++/* forward declaration for clients */ + typedef u32 mbox_msg_t; + struct omap_mbox; + ++/* interrupt direction identifiers */ + typedef int __bitwise omap_mbox_irq_t; + #define IRQ_TX ((__force omap_mbox_irq_t) 1) + #define IRQ_RX ((__force omap_mbox_irq_t) 2) + ++/* client api for message transmission */ + int omap_mbox_msg_send(struct omap_mbox *, mbox_msg_t msg); + ++/* client api for acquiring and releasing a mailbox */ + struct omap_mbox *omap_mbox_get(const char *, struct notifier_block *nb); + void omap_mbox_put(struct omap_mbox *mbox, struct notifier_block *nb); + ++/* client api for saving and restoring context */ + void omap_mbox_save_ctx(struct omap_mbox *mbox); + void omap_mbox_restore_ctx(struct omap_mbox *mbox); ++ ++/* client api for manipulating mailbox interrupts */ + void omap_mbox_enable_irq(struct omap_mbox *mbox, omap_mbox_irq_t irq); + void omap_mbox_disable_irq(struct omap_mbox *mbox, omap_mbox_irq_t irq); + +--- /dev/null ++++ b/include/linux/phy/omap_control_phy.h +@@ -0,0 +1,89 @@ ++/* ++ * omap_control_phy.h - Header file for the PHY part of control module. ++ * ++ * Copyright (C) 2013 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; either version 2 of the License, or ++ * (at your option) any later version. ++ * ++ * Author: Kishon Vijay Abraham I <kishon@ti.com> ++ * ++ * 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 __OMAP_CONTROL_PHY_H__ ++#define __OMAP_CONTROL_PHY_H__ ++ ++enum omap_control_phy_type { ++ OMAP_CTRL_TYPE_OTGHS = 1, /* Mailbox OTGHS_CONTROL */ ++ OMAP_CTRL_TYPE_USB2, /* USB2_PHY, power down in CONTROL_DEV_CONF */ ++ OMAP_CTRL_TYPE_PIPE3, /* PIPE3 PHY, DPLL & seperate Rx/Tx power */ ++ OMAP_CTRL_TYPE_DRA7USB2, /* USB2 PHY, power and power_aux e.g. DRA7 */ ++ OMAP_CTRL_TYPE_AM437USB2, /* USB2 PHY, power e.g. AM437x */ ++}; ++ ++struct omap_control_phy { ++ struct device *dev; ++ ++ u32 __iomem *otghs_control; ++ u32 __iomem *power; ++ u32 __iomem *power_aux; ++ ++ struct clk *sys_clk; ++ ++ enum omap_control_phy_type type; ++}; ++ ++enum omap_control_usb_mode { ++ USB_MODE_UNDEFINED = 0, ++ USB_MODE_HOST, ++ USB_MODE_DEVICE, ++ USB_MODE_DISCONNECT, ++}; ++ ++#define OMAP_CTRL_DEV_PHY_PD BIT(0) ++ ++#define OMAP_CTRL_DEV_AVALID BIT(0) ++#define OMAP_CTRL_DEV_BVALID BIT(1) ++#define OMAP_CTRL_DEV_VBUSVALID BIT(2) ++#define OMAP_CTRL_DEV_SESSEND BIT(3) ++#define OMAP_CTRL_DEV_IDDIG BIT(4) ++ ++#define OMAP_CTRL_PIPE3_PHY_PWRCTL_CLK_CMD_MASK 0x003FC000 ++#define OMAP_CTRL_PIPE3_PHY_PWRCTL_CLK_CMD_SHIFT 0xE ++ ++#define OMAP_CTRL_PIPE3_PHY_PWRCTL_CLK_FREQ_MASK 0xFFC00000 ++#define OMAP_CTRL_PIPE3_PHY_PWRCTL_CLK_FREQ_SHIFT 0x16 ++ ++#define OMAP_CTRL_PIPE3_PHY_TX_RX_POWERON 0x3 ++#define OMAP_CTRL_PIPE3_PHY_TX_RX_POWEROFF 0x0 ++ ++#define OMAP_CTRL_USB2_PHY_PD BIT(28) ++ ++#define AM437X_CTRL_USB2_PHY_PD BIT(0) ++#define AM437X_CTRL_USB2_OTG_PD BIT(1) ++#define AM437X_CTRL_USB2_OTGVDET_EN BIT(19) ++#define AM437X_CTRL_USB2_OTGSESSEND_EN BIT(20) ++ ++#if IS_ENABLED(CONFIG_OMAP_CONTROL_PHY) ++extern void omap_control_phy_power(struct device *dev, int on); ++extern void omap_control_usb_set_mode(struct device *dev, ++ enum omap_control_usb_mode mode); ++#else ++ ++static inline void omap_control_phy_power(struct device *dev, int on) ++{ ++} ++ ++static inline void omap_control_usb_set_mode(struct device *dev, ++ enum omap_control_usb_mode mode) ++{ ++} ++#endif ++ ++#endif /* __OMAP_CONTROL_PHY_H__ */ +--- /dev/null ++++ b/include/linux/phy/omap_pipe3.h +@@ -0,0 +1,59 @@ ++/* ++ * omap_pipe3.h -- omap pipe3 phy header file ++ * ++ * Copyright (C) 2013 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; either version 2 of the License, or ++ * (at your option) any later version. ++ * ++ * Author: Kishon Vijay Abraham I <kishon@ti.com> ++ * ++ * 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 __DRIVERS_OMAP_PIPE3_H ++#define __DRIVERS_OMAP_PIPE3_H ++ ++#include <linux/io.h> ++ ++struct pipe3_dpll_params { ++ u16 m; ++ u8 n; ++ u8 freq:3; ++ u8 sd; ++ u32 mf; ++}; ++ ++struct pipe3_dpll_map { ++ unsigned long rate; ++ struct pipe3_dpll_params params; ++}; ++ ++struct omap_pipe3 { ++ void __iomem *pll_ctrl_base; ++ struct device *dev; ++ struct device *control_dev; ++ struct clk *wkupclk; ++ struct clk *sys_clk; ++ struct clk *optclk; ++ struct clk *optclk2; ++ struct pipe3_dpll_map *dpll_map; ++}; ++ ++static inline u32 omap_pipe3_readl(void __iomem *addr, unsigned offset) ++{ ++ return __raw_readl(addr + offset); ++} ++ ++static inline void omap_pipe3_writel(void __iomem *addr, unsigned offset, ++ u32 data) ++{ ++ __raw_writel(data, addr + offset); ++} ++ ++#endif /* __DRIVERS_OMAP_PIPE3_H */ +--- /dev/null ++++ b/include/linux/phy/omap_usb.h +@@ -0,0 +1,74 @@ ++/* ++ * omap_usb.h -- omap usb2 phy header file ++ * ++ * Copyright (C) 2012 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; either version 2 of the License, or ++ * (at your option) any later version. ++ * ++ * Author: Kishon Vijay Abraham I <kishon@ti.com> ++ * ++ * 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 __DRIVERS_OMAP_USB2_H ++#define __DRIVERS_OMAP_USB2_H ++ ++#include <linux/io.h> ++#include <linux/usb/otg.h> ++ ++struct usb_dpll_params { ++ u16 m; ++ u8 n; ++ u8 freq:3; ++ u8 sd; ++ u32 mf; ++}; ++ ++struct omap_usb { ++ struct usb_phy phy; ++ struct phy_companion *comparator; ++ struct device *dev; ++ struct device *control_dev; ++ struct clk *wkupclk; ++ struct clk *optclk; ++}; ++ ++struct usb_phy_data { ++ const char *label; ++ u32 flags; ++}; ++ ++enum usb_phy_data_flags { ++ OMAP_USB2_HAS_START_SRP = 1, ++ OMAP_USB2_HAS_SET_VBUS, ++}; ++ ++#define phy_to_omapusb(x) container_of((x), struct omap_usb, phy) ++ ++#if defined(CONFIG_OMAP_USB2) || defined(CONFIG_OMAP_USB2_MODULE) ++extern int omap_usb2_set_comparator(struct phy_companion *comparator); ++#else ++static inline int omap_usb2_set_comparator(struct phy_companion *comparator) ++{ ++ return -ENODEV; ++} ++#endif ++ ++static inline u32 omap_usb_readl(void __iomem *addr, unsigned offset) ++{ ++ return __raw_readl(addr + offset); ++} ++ ++static inline void omap_usb_writel(void __iomem *addr, unsigned offset, ++ u32 data) ++{ ++ __raw_writel(data, addr + offset); ++} ++ ++#endif /* __DRIVERS_OMAP_USB_H */ +--- /dev/null ++++ b/include/linux/phy/phy.h +@@ -0,0 +1,270 @@ ++/* ++ * phy.h -- generic phy header file ++ * ++ * Copyright (C) 2013 Texas Instruments Incorporated - http://www.ti.com ++ * ++ * Author: Kishon Vijay Abraham I <kishon@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; either version 2 of the License, or ++ * (at your option) any later version. ++ */ ++ ++#ifndef __DRIVERS_PHY_H ++#define __DRIVERS_PHY_H ++ ++#include <linux/err.h> ++#include <linux/of.h> ++#include <linux/device.h> ++#include <linux/pm_runtime.h> ++ ++struct phy; ++ ++/** ++ * struct phy_ops - set of function pointers for performing phy operations ++ * @init: operation to be performed for initializing phy ++ * @exit: operation to be performed while exiting ++ * @power_on: powering on the phy ++ * @power_off: powering off the phy ++ * @owner: the module owner containing the ops ++ */ ++struct phy_ops { ++ int (*init)(struct phy *phy); ++ int (*exit)(struct phy *phy); ++ int (*power_on)(struct phy *phy); ++ int (*power_off)(struct phy *phy); ++ struct module *owner; ++}; ++ ++/** ++ * struct phy - represents the phy device ++ * @dev: phy device ++ * @id: id of the phy device ++ * @ops: function pointers for performing phy operations ++ * @init_data: list of PHY consumers (non-dt only) ++ * @mutex: mutex to protect phy_ops ++ * @init_count: used to protect when the PHY is used by multiple consumers ++ * @power_count: used to protect when the PHY is used by multiple consumers ++ */ ++struct phy { ++ struct device dev; ++ int id; ++ const struct phy_ops *ops; ++ struct phy_init_data *init_data; ++ struct mutex mutex; ++ int init_count; ++ int power_count; ++}; ++ ++/** ++ * struct phy_provider - represents the phy provider ++ * @dev: phy provider device ++ * @owner: the module owner having of_xlate ++ * @of_xlate: function pointer to obtain phy instance from phy pointer ++ * @list: to maintain a linked list of PHY providers ++ */ ++struct phy_provider { ++ struct device *dev; ++ struct module *owner; ++ struct list_head list; ++ struct phy * (*of_xlate)(struct device *dev, ++ struct of_phandle_args *args); ++}; ++ ++/** ++ * struct phy_consumer - represents the phy consumer ++ * @dev_name: the device name of the controller that will use this PHY device ++ * @port: name given to the consumer port ++ */ ++struct phy_consumer { ++ const char *dev_name; ++ const char *port; ++}; ++ ++/** ++ * struct phy_init_data - contains the list of PHY consumers ++ * @num_consumers: number of consumers for this PHY device ++ * @consumers: list of PHY consumers ++ */ ++struct phy_init_data { ++ unsigned int num_consumers; ++ struct phy_consumer *consumers; ++}; ++ ++#define PHY_CONSUMER(_dev_name, _port) \ ++{ \ ++ .dev_name = _dev_name, \ ++ .port = _port, \ ++} ++ ++#define to_phy(dev) (container_of((dev), struct phy, dev)) ++ ++#define of_phy_provider_register(dev, xlate) \ ++ __of_phy_provider_register((dev), THIS_MODULE, (xlate)) ++ ++#define devm_of_phy_provider_register(dev, xlate) \ ++ __devm_of_phy_provider_register((dev), THIS_MODULE, (xlate)) ++ ++static inline void phy_set_drvdata(struct phy *phy, void *data) ++{ ++ dev_set_drvdata(&phy->dev, data); ++} ++ ++static inline void *phy_get_drvdata(struct phy *phy) ++{ ++ return dev_get_drvdata(&phy->dev); ++} ++ ++#if IS_ENABLED(CONFIG_GENERIC_PHY) ++extern int phy_pm_runtime_get(struct phy *phy); ++extern int phy_pm_runtime_get_sync(struct phy *phy); ++extern int phy_pm_runtime_put(struct phy *phy); ++extern int phy_pm_runtime_put_sync(struct phy *phy); ++extern void phy_pm_runtime_allow(struct phy *phy); ++extern void phy_pm_runtime_forbid(struct phy *phy); ++extern int phy_init(struct phy *phy); ++extern int phy_exit(struct phy *phy); ++extern int phy_power_on(struct phy *phy); ++extern int phy_power_off(struct phy *phy); ++extern struct phy *phy_get(struct device *dev, const char *string); ++extern struct phy *devm_phy_get(struct device *dev, const char *string); ++extern void phy_put(struct phy *phy); ++extern void devm_phy_put(struct device *dev, struct phy *phy); ++extern struct phy *of_phy_simple_xlate(struct device *dev, ++ struct of_phandle_args *args); ++extern struct phy *phy_create(struct device *dev, const struct phy_ops *ops, ++ struct phy_init_data *init_data); ++extern struct phy *devm_phy_create(struct device *dev, ++ const struct phy_ops *ops, struct phy_init_data *init_data); ++extern void phy_destroy(struct phy *phy); ++extern void devm_phy_destroy(struct device *dev, struct phy *phy); ++extern struct phy_provider *__of_phy_provider_register(struct device *dev, ++ struct module *owner, struct phy * (*of_xlate)(struct device *dev, ++ struct of_phandle_args *args)); ++extern struct phy_provider *__devm_of_phy_provider_register(struct device *dev, ++ struct module *owner, struct phy * (*of_xlate)(struct device *dev, ++ struct of_phandle_args *args)); ++extern void of_phy_provider_unregister(struct phy_provider *phy_provider); ++extern void devm_of_phy_provider_unregister(struct device *dev, ++ struct phy_provider *phy_provider); ++#else ++static inline int phy_pm_runtime_get(struct phy *phy) ++{ ++ return -ENOSYS; ++} ++ ++static inline int phy_pm_runtime_get_sync(struct phy *phy) ++{ ++ return -ENOSYS; ++} ++ ++static inline int phy_pm_runtime_put(struct phy *phy) ++{ ++ return -ENOSYS; ++} ++ ++static inline int phy_pm_runtime_put_sync(struct phy *phy) ++{ ++ return -ENOSYS; ++} ++ ++static inline void phy_pm_runtime_allow(struct phy *phy) ++{ ++ return; ++} ++ ++static inline void phy_pm_runtime_forbid(struct phy *phy) ++{ ++ return; ++} ++ ++static inline int phy_init(struct phy *phy) ++{ ++ return -ENOSYS; ++} ++ ++static inline int phy_exit(struct phy *phy) ++{ ++ return -ENOSYS; ++} ++ ++static inline int phy_power_on(struct phy *phy) ++{ ++ return -ENOSYS; ++} ++ ++static inline int phy_power_off(struct phy *phy) ++{ ++ return -ENOSYS; ++} ++ ++static inline struct phy *phy_get(struct device *dev, const char *string) ++{ ++ return ERR_PTR(-ENOSYS); ++} ++ ++static inline struct phy *devm_phy_get(struct device *dev, const char *string) ++{ ++ return ERR_PTR(-ENOSYS); ++} ++ ++static inline void phy_put(struct phy *phy) ++{ ++} ++ ++static inline void devm_phy_put(struct device *dev, struct phy *phy) ++{ ++} ++ ++static inline struct phy *of_phy_simple_xlate(struct device *dev, ++ struct of_phandle_args *args) ++{ ++ return ERR_PTR(-ENOSYS); ++} ++ ++static inline struct phy *phy_create(struct device *dev, ++ const struct phy_ops *ops, struct phy_init_data *init_data) ++{ ++ return ERR_PTR(-ENOSYS); ++} ++ ++static inline struct phy *devm_phy_create(struct device *dev, ++ const struct phy_ops *ops, struct phy_init_data *init_data) ++{ ++ return ERR_PTR(-ENOSYS); ++} ++ ++static inline void phy_destroy(struct phy *phy) ++{ ++} ++ ++static inline void devm_phy_destroy(struct device *dev, struct phy *phy) ++{ ++} ++ ++static inline struct phy_provider *__of_phy_provider_register( ++ struct device *dev, struct module *owner, struct phy * (*of_xlate)( ++ struct device *dev, struct of_phandle_args *args)) ++{ ++ return ERR_PTR(-ENOSYS); ++} ++ ++static inline struct phy_provider *__devm_of_phy_provider_register(struct device ++ *dev, struct module *owner, struct phy * (*of_xlate)(struct device *dev, ++ struct of_phandle_args *args)) ++{ ++ return ERR_PTR(-ENOSYS); ++} ++ ++static inline void of_phy_provider_unregister(struct phy_provider *phy_provider) ++{ ++} ++ ++static inline void devm_of_phy_provider_unregister(struct device *dev, ++ struct phy_provider *phy_provider) ++{ ++} ++#endif ++ ++#endif /* __DRIVERS_PHY_H */ +--- a/include/linux/platform_data/davinci_asp.h ++++ b/include/linux/platform_data/davinci_asp.h +@@ -84,6 +84,8 @@ struct snd_platform_data { + u8 version; + u8 txnumevt; + u8 rxnumevt; ++ int tx_dma_channel; ++ int rx_dma_channel; + }; + + enum { +--- a/include/linux/platform_data/elm.h ++++ b/include/linux/platform_data/elm.h +@@ -21,17 +21,12 @@ + enum bch_ecc { + BCH4_ECC = 0, + BCH8_ECC, ++ BCH16_ECC + }; + + /* ELM support 8 error syndrome process */ + #define ERROR_VECTOR_MAX 8 +- +-#define BCH8_ECC_OOB_BYTES 13 +-#define BCH4_ECC_OOB_BYTES 7 +-/* RBL requires 14 byte even though BCH8 uses only 13 byte */ +-#define BCH8_SIZE (BCH8_ECC_OOB_BYTES + 1) +-/* Uses 1 extra byte to handle erased pages */ +-#define BCH4_SIZE (BCH4_ECC_OOB_BYTES + 1) ++#define ELM_MAX_DETECTABLE_ERRORS 16 + + /** + * struct elm_errorvec - error vector for elm +@@ -45,10 +40,11 @@ struct elm_errorvec { + bool error_reported; + bool error_uncorrectable; + int error_count; +- int error_loc[ERROR_VECTOR_MAX]; ++ int error_loc[ELM_MAX_DETECTABLE_ERRORS]; + }; + + void elm_decode_bch_error_page(struct device *dev, u8 *ecc_calc, + struct elm_errorvec *err_vec); +-int elm_config(struct device *dev, enum bch_ecc bch_type); ++int elm_config(struct device *dev, struct mtd_info *mtd, ++ enum bch_ecc bch_type); + #endif /* __ELM_H */ +--- a/include/linux/platform_data/mtd-nand-omap2.h ++++ b/include/linux/platform_data/mtd-nand-omap2.h +@@ -23,13 +23,18 @@ enum nand_io { + }; + + enum omap_ecc { +- /* 1-bit ecc: stored at end of spare area */ +- OMAP_ECC_HAMMING_CODE_DEFAULT = 0, /* Default, s/w method */ +- OMAP_ECC_HAMMING_CODE_HW, /* gpmc to detect the error */ +- /* 1-bit ecc: stored at beginning of spare area as romcode */ +- OMAP_ECC_HAMMING_CODE_HW_ROMCODE, /* gpmc method & romcode layout */ +- OMAP_ECC_BCH4_CODE_HW, /* 4-bit BCH ecc code */ +- OMAP_ECC_BCH8_CODE_HW, /* 8-bit BCH ecc code */ ++ /* 1-bit ECC calculation by GPMC, Error detection by Software */ ++ OMAP_ECC_HAMMING_CODE_HW = 0, ++ /* 4-bit ECC calculation by GPMC, Error detection by Software */ ++ OMAP_ECC_BCH4_CODE_HW_DETECTION_SW, ++ /* 4-bit ECC calculation by GPMC, Error detection by ELM */ ++ OMAP_ECC_BCH4_CODE_HW, ++ /* 8-bit ECC calculation by GPMC, Error detection by Software */ ++ OMAP_ECC_BCH8_CODE_HW_DETECTION_SW, ++ /* 8-bit ECC calculation by GPMC, Error detection by ELM */ ++ OMAP_ECC_BCH8_CODE_HW, ++ /* 16-bit ECC calculation by GPMC, Error detection by ELM */ ++ OMAP_ECC_BCH16_CODE_HW, + }; + + struct gpmc_nand_regs { +@@ -49,6 +54,9 @@ struct gpmc_nand_regs { + void __iomem *gpmc_bch_result1[GPMC_BCH_NUM_REMAINDER]; + void __iomem *gpmc_bch_result2[GPMC_BCH_NUM_REMAINDER]; + void __iomem *gpmc_bch_result3[GPMC_BCH_NUM_REMAINDER]; ++ void __iomem *gpmc_bch_result4[GPMC_BCH_NUM_REMAINDER]; ++ void __iomem *gpmc_bch_result5[GPMC_BCH_NUM_REMAINDER]; ++ void __iomem *gpmc_bch_result6[GPMC_BCH_NUM_REMAINDER]; + }; + + struct omap_nand_platform_data { +@@ -63,5 +71,6 @@ struct omap_nand_platform_data { + + /* for passing the partitions */ + struct device_node *of_node; ++ struct device_node *elm_of_node; + }; + #endif +--- a/include/linux/platform_data/omap-wd-timer.h ++++ b/include/linux/platform_data/omap-wd-timer.h +@@ -16,6 +16,14 @@ + #include <linux/types.h> + + /* ++ * WATCHDOG IP Revisions ++ * WDTIMER2_IP3 - Used in OMAP3 ++ * WDTIMER2_IP4 - Used in OMAP4+ Soc's ++ */ ++#define WDTIMER2_IP3 1 ++#define WDTIMER2_IP4 2 ++ ++/* + * Standardized OMAP reset source bits + * + * This is a subset of the ones listed in arch/arm/mach-omap2/prm.h +@@ -33,6 +41,7 @@ + */ + struct omap_wd_timer_platform_data { + u32 (*read_reset_sources)(void); ++ u32 ip_rev; + }; + + #endif +--- /dev/null ++++ b/include/linux/platform_data/usb-rcar-gen2-phy.h +@@ -0,0 +1,22 @@ ++/* ++ * Copyright (C) 2013 Renesas Solutions Corp. ++ * Copyright (C) 2013 Cogent Embedded, 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. ++ */ ++ ++#ifndef __USB_RCAR_GEN2_PHY_H ++#define __USB_RCAR_GEN2_PHY_H ++ ++#include <linux/types.h> ++ ++struct rcar_gen2_phy_platform_data { ++ /* USB channel 0 configuration */ ++ bool chan0_pci:1; /* true: PCI USB host 0, false: USBHS */ ++ /* USB channel 2 configuration */ ++ bool chan2_pci:1; /* true: PCI USB host 2, false: USBSS */ ++}; ++ ++#endif +--- a/include/linux/regulator/driver.h ++++ b/include/linux/regulator/driver.h +@@ -316,6 +316,8 @@ struct regulator_dev { + + struct blocking_notifier_head notifier; + struct mutex mutex; /* consumer lock */ ++ struct task_struct *lock_owner; ++ int lock_count; + struct module *owner; + struct device dev; + struct regulation_constraints *constraints; +--- a/include/linux/reset-controller.h ++++ b/include/linux/reset-controller.h +@@ -17,6 +17,8 @@ struct reset_control_ops { + int (*reset)(struct reset_controller_dev *rcdev, unsigned long id); + int (*assert)(struct reset_controller_dev *rcdev, unsigned long id); + int (*deassert)(struct reset_controller_dev *rcdev, unsigned long id); ++ int (*is_reset)(struct reset_controller_dev *rcdev, unsigned long id); ++ int (*clear_reset)(struct reset_controller_dev *rcdev, unsigned long i); + }; + + struct module; +--- a/include/linux/reset.h ++++ b/include/linux/reset.h +@@ -7,6 +7,8 @@ struct reset_control; + int reset_control_reset(struct reset_control *rstc); + int reset_control_assert(struct reset_control *rstc); + int reset_control_deassert(struct reset_control *rstc); ++int reset_control_is_reset(struct reset_control *rstc); ++int reset_control_clear_reset(struct reset_control *rstc); + + struct reset_control *reset_control_get(struct device *dev, const char *id); + void reset_control_put(struct reset_control *rstc); +--- a/include/linux/spi/spi.h ++++ b/include/linux/spi/spi.h +@@ -91,6 +91,7 @@ struct spi_device { + #define SPI_TX_QUAD 0x200 /* transmit with 4 wires */ + #define SPI_RX_DUAL 0x400 /* receive with 2 wires */ + #define SPI_RX_QUAD 0x800 /* receive with 4 wires */ ++#define SPI_RX_MMAP 0x1000 /* Memory mapped Reas */ + u8 bits_per_word; + int irq; + void *controller_state; +@@ -554,6 +555,7 @@ struct spi_transfer { + u8 bits_per_word; + u16 delay_usecs; + u32 speed_hz; ++ bool memory_map; + + struct list_head transfer_list; + }; +--- /dev/null ++++ b/include/linux/ti_emif.h +@@ -0,0 +1,558 @@ ++/* ++ * Register defines for the EMIF driver ++ * ++ * Copyright (C) 2012 Texas Instruments, Inc. ++ * ++ * Benoit Cousson (b-cousson@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 __TI_EMIF_H ++#define __TI_EMIF_H ++ ++/* ++ * 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 ++ ++/* State of the core voltage */ ++#define DDR_VOLTAGE_STABLE 0 ++#define DDR_VOLTAGE_RAMPING 1 ++ ++/* Defines for timing De-rating */ ++#define EMIF_NORMAL_TIMINGS 0 ++#define EMIF_DERATED_TIMINGS 1 ++ ++/* Length of the forced read idle period in terms of cycles */ ++#define EMIF_READ_IDLE_LEN_VAL 5 ++ ++/* ++ * forced read idle interval to be used when voltage ++ * is changed as part of DVFS/DPS - 1ms ++ */ ++#define READ_IDLE_INTERVAL_DVFS (1*1000000) ++ ++/* ++ * Forced read idle interval to be used when voltage is stable ++ * 50us - or maximum value will do ++ */ ++#define READ_IDLE_INTERVAL_NORMAL (50*1000000) ++ ++/* DLL calibration interval when voltage is NOT stable - 1us */ ++#define DLL_CALIB_INTERVAL_DVFS (1*1000000) ++ ++#define DLL_CALIB_ACK_WAIT_VAL 5 ++ ++/* Interval between ZQCS commands - hw team recommended value */ ++#define EMIF_ZQCS_INTERVAL_US (50*1000) ++/* Enable ZQ Calibration on exiting Self-refresh */ ++#define ZQ_SFEXITEN_ENABLE 1 ++/* ++ * ZQ Calibration simultaneously on both chip-selects: ++ * Needs one calibration resistor per CS ++ */ ++#define ZQ_DUALCALEN_DISABLE 0 ++#define ZQ_DUALCALEN_ENABLE 1 ++ ++#define T_ZQCS_DEFAULT_NS 90 ++#define T_ZQCL_DEFAULT_NS 360 ++#define T_ZQINIT_DEFAULT_NS 1000 ++ ++/* DPD_EN */ ++#define DPD_DISABLE 0 ++#define DPD_ENABLE 1 ++ ++/* ++ * Default values for the low-power entry to be used if not provided by user. ++ * OMAP4/5 has a hw bug(i735) due to which this value can not be less than 512 ++ * Timeout values are in DDR clock 'cycles' and frequency threshold in Hz ++ */ ++#define EMIF_LP_MODE_TIMEOUT_PERFORMANCE 2048 ++#define EMIF_LP_MODE_TIMEOUT_POWER 512 ++#define EMIF_LP_MODE_FREQ_THRESHOLD 400000000 ++ ++/* DDR_PHY_CTRL_1 values for EMIF4D - ATTILA PHY combination */ ++#define EMIF_DDR_PHY_CTRL_1_BASE_VAL_ATTILAPHY 0x049FF000 ++#define EMIF_DLL_SLAVE_DLY_CTRL_400_MHZ_ATTILAPHY 0x41 ++#define EMIF_DLL_SLAVE_DLY_CTRL_200_MHZ_ATTILAPHY 0x80 ++#define EMIF_DLL_SLAVE_DLY_CTRL_100_MHZ_AND_LESS_ATTILAPHY 0xFF ++ ++/* DDR_PHY_CTRL_1 values for EMIF4D5 INTELLIPHY combination */ ++#define EMIF_DDR_PHY_CTRL_1_BASE_VAL_INTELLIPHY 0x0E084200 ++#define EMIF_PHY_TOTAL_READ_LATENCY_INTELLIPHY_PS 10000 ++ ++/* TEMP_ALERT_CONFIG - corresponding to temp gradient 5 C/s */ ++#define TEMP_ALERT_POLL_INTERVAL_DEFAULT_MS 360 ++ ++#define EMIF_T_CSTA 3 ++#define EMIF_T_PDLL_UL 128 ++ ++/* External PHY control registers magic values */ ++#define EMIF_EXT_PHY_CTRL_1_VAL 0x04020080 ++#define EMIF_EXT_PHY_CTRL_5_VAL 0x04010040 ++#define EMIF_EXT_PHY_CTRL_6_VAL 0x01004010 ++#define EMIF_EXT_PHY_CTRL_7_VAL 0x00001004 ++#define EMIF_EXT_PHY_CTRL_8_VAL 0x04010040 ++#define EMIF_EXT_PHY_CTRL_9_VAL 0x01004010 ++#define EMIF_EXT_PHY_CTRL_10_VAL 0x00001004 ++#define EMIF_EXT_PHY_CTRL_11_VAL 0x00000000 ++#define EMIF_EXT_PHY_CTRL_12_VAL 0x00000000 ++#define EMIF_EXT_PHY_CTRL_13_VAL 0x00000000 ++#define EMIF_EXT_PHY_CTRL_14_VAL 0x80080080 ++#define EMIF_EXT_PHY_CTRL_15_VAL 0x00800800 ++#define EMIF_EXT_PHY_CTRL_16_VAL 0x08102040 ++#define EMIF_EXT_PHY_CTRL_17_VAL 0x00000001 ++#define EMIF_EXT_PHY_CTRL_18_VAL 0x540A8150 ++#define EMIF_EXT_PHY_CTRL_19_VAL 0xA81502A0 ++#define EMIF_EXT_PHY_CTRL_20_VAL 0x002A0540 ++#define EMIF_EXT_PHY_CTRL_21_VAL 0x00000000 ++#define EMIF_EXT_PHY_CTRL_22_VAL 0x00000000 ++#define EMIF_EXT_PHY_CTRL_23_VAL 0x00000000 ++#define EMIF_EXT_PHY_CTRL_24_VAL 0x00000077 ++ ++#define EMIF_INTELLI_PHY_DQS_GATE_OPENING_DELAY_PS 1200 ++ ++/* Registers offset */ ++#define EMIF_MODULE_ID_AND_REVISION 0x0000 ++#define EMIF_STATUS 0x0004 ++#define EMIF_SDRAM_CONFIG 0x0008 ++#define EMIF_SDRAM_CONFIG_2 0x000c ++#define EMIF_SDRAM_REFRESH_CONTROL 0x0010 ++#define EMIF_SDRAM_REFRESH_CTRL_SHDW 0x0014 ++#define EMIF_SDRAM_TIMING_1 0x0018 ++#define EMIF_SDRAM_TIMING_1_SHDW 0x001c ++#define EMIF_SDRAM_TIMING_2 0x0020 ++#define EMIF_SDRAM_TIMING_2_SHDW 0x0024 ++#define EMIF_SDRAM_TIMING_3 0x0028 ++#define EMIF_SDRAM_TIMING_3_SHDW 0x002c ++#define EMIF_LPDDR2_NVM_TIMING 0x0030 ++#define EMIF_LPDDR2_NVM_TIMING_SHDW 0x0034 ++#define EMIF_POWER_MANAGEMENT_CONTROL 0x0038 ++#define EMIF_POWER_MANAGEMENT_CTRL_SHDW 0x003c ++#define EMIF_LPDDR2_MODE_REG_DATA 0x0040 ++#define EMIF_LPDDR2_MODE_REG_CONFIG 0x0050 ++#define EMIF_OCP_CONFIG 0x0054 ++#define EMIF_OCP_CONFIG_VALUE_1 0x0058 ++#define EMIF_OCP_CONFIG_VALUE_2 0x005c ++#define EMIF_IODFT_TEST_LOGIC_GLOBAL_CONTROL 0x0060 ++#define EMIF_IODFT_TEST_LOGIC_CTRL_MISR_RESULT 0x0064 ++#define EMIF_IODFT_TEST_LOGIC_ADDRESS_MISR_RESULT 0x0068 ++#define EMIF_IODFT_TEST_LOGIC_DATA_MISR_RESULT_1 0x006c ++#define EMIF_IODFT_TEST_LOGIC_DATA_MISR_RESULT_2 0x0070 ++#define EMIF_IODFT_TEST_LOGIC_DATA_MISR_RESULT_3 0x0074 ++#define EMIF_PERFORMANCE_COUNTER_1 0x0080 ++#define EMIF_PERFORMANCE_COUNTER_2 0x0084 ++#define EMIF_PERFORMANCE_COUNTER_CONFIG 0x0088 ++#define EMIF_PERFORMANCE_COUNTER_MASTER_REGION_SELECT 0x008c ++#define EMIF_PERFORMANCE_COUNTER_TIME 0x0090 ++#define EMIF_MISC_REG 0x0094 ++#define EMIF_DLL_CALIB_CTRL 0x0098 ++#define EMIF_DLL_CALIB_CTRL_SHDW 0x009c ++#define EMIF_END_OF_INTERRUPT 0x00a0 ++#define EMIF_SYSTEM_OCP_INTERRUPT_RAW_STATUS 0x00a4 ++#define EMIF_LL_OCP_INTERRUPT_RAW_STATUS 0x00a8 ++#define EMIF_SYSTEM_OCP_INTERRUPT_STATUS 0x00ac ++#define EMIF_LL_OCP_INTERRUPT_STATUS 0x00b0 ++#define EMIF_SYSTEM_OCP_INTERRUPT_ENABLE_SET 0x00b4 ++#define EMIF_LL_OCP_INTERRUPT_ENABLE_SET 0x00b8 ++#define EMIF_SYSTEM_OCP_INTERRUPT_ENABLE_CLEAR 0x00bc ++#define EMIF_LL_OCP_INTERRUPT_ENABLE_CLEAR 0x00c0 ++#define EMIF_SDRAM_OUTPUT_IMPEDANCE_CALIBRATION_CONFIG 0x00c8 ++#define EMIF_TEMPERATURE_ALERT_CONFIG 0x00cc ++#define EMIF_OCP_ERROR_LOG 0x00d0 ++#define EMIF_READ_WRITE_LEVELING_RAMP_WINDOW 0x00d4 ++#define EMIF_READ_WRITE_LEVELING_RAMP_CONTROL 0x00d8 ++#define EMIF_READ_WRITE_LEVELING_CONTROL 0x00dc ++#define EMIF_DDR_PHY_CTRL_1 0x00e4 ++#define EMIF_DDR_PHY_CTRL_1_SHDW 0x00e8 ++#define EMIF_DDR_PHY_CTRL_2 0x00ec ++#define EMIF_PRIORITY_TO_CLASS_OF_SERVICE_MAPPING 0x0100 ++#define EMIF_CONNECTION_ID_TO_CLASS_OF_SERVICE_1_MAPPING 0x0104 ++#define EMIF_CONNECTION_ID_TO_CLASS_OF_SERVICE_2_MAPPING 0x0108 ++#define EMIF_READ_WRITE_EXECUTION_THRESHOLD 0x0120 ++#define EMIF_COS_CONFIG 0x0124 ++#define EMIF_PHY_STATUS_1 0x0140 ++#define EMIF_PHY_STATUS_2 0x0144 ++#define EMIF_PHY_STATUS_3 0x0148 ++#define EMIF_PHY_STATUS_4 0x014c ++#define EMIF_PHY_STATUS_5 0x0150 ++#define EMIF_PHY_STATUS_6 0x0154 ++#define EMIF_PHY_STATUS_7 0x0158 ++#define EMIF_PHY_STATUS_8 0x015c ++#define EMIF_PHY_STATUS_9 0x0160 ++#define EMIF_PHY_STATUS_10 0x0164 ++#define EMIF_PHY_STATUS_11 0x0168 ++#define EMIF_PHY_STATUS_12 0x016c ++#define EMIF_PHY_STATUS_13 0x0170 ++#define EMIF_PHY_STATUS_14 0x0174 ++#define EMIF_PHY_STATUS_15 0x0178 ++#define EMIF_PHY_STATUS_16 0x017c ++#define EMIF_PHY_STATUS_17 0x0180 ++#define EMIF_PHY_STATUS_18 0x0184 ++#define EMIF_PHY_STATUS_19 0x0188 ++#define EMIF_PHY_STATUS_20 0x018c ++#define EMIF_PHY_STATUS_21 0x0190 ++#define EMIF_EXT_PHY_CTRL_1 0x0200 ++#define EMIF_EXT_PHY_CTRL_1_SHDW 0x0204 ++#define EMIF_EXT_PHY_CTRL_2 0x0208 ++#define EMIF_EXT_PHY_CTRL_2_SHDW 0x020c ++#define EMIF_EXT_PHY_CTRL_3 0x0210 ++#define EMIF_EXT_PHY_CTRL_3_SHDW 0x0214 ++#define EMIF_EXT_PHY_CTRL_4 0x0218 ++#define EMIF_EXT_PHY_CTRL_4_SHDW 0x021c ++#define EMIF_EXT_PHY_CTRL_5 0x0220 ++#define EMIF_EXT_PHY_CTRL_5_SHDW 0x0224 ++#define EMIF_EXT_PHY_CTRL_6 0x0228 ++#define EMIF_EXT_PHY_CTRL_6_SHDW 0x022c ++#define EMIF_EXT_PHY_CTRL_7 0x0230 ++#define EMIF_EXT_PHY_CTRL_7_SHDW 0x0234 ++#define EMIF_EXT_PHY_CTRL_8 0x0238 ++#define EMIF_EXT_PHY_CTRL_8_SHDW 0x023c ++#define EMIF_EXT_PHY_CTRL_9 0x0240 ++#define EMIF_EXT_PHY_CTRL_9_SHDW 0x0244 ++#define EMIF_EXT_PHY_CTRL_10 0x0248 ++#define EMIF_EXT_PHY_CTRL_10_SHDW 0x024c ++#define EMIF_EXT_PHY_CTRL_11 0x0250 ++#define EMIF_EXT_PHY_CTRL_11_SHDW 0x0254 ++#define EMIF_EXT_PHY_CTRL_12 0x0258 ++#define EMIF_EXT_PHY_CTRL_12_SHDW 0x025c ++#define EMIF_EXT_PHY_CTRL_13 0x0260 ++#define EMIF_EXT_PHY_CTRL_13_SHDW 0x0264 ++#define EMIF_EXT_PHY_CTRL_14 0x0268 ++#define EMIF_EXT_PHY_CTRL_14_SHDW 0x026c ++#define EMIF_EXT_PHY_CTRL_15 0x0270 ++#define EMIF_EXT_PHY_CTRL_15_SHDW 0x0274 ++#define EMIF_EXT_PHY_CTRL_16 0x0278 ++#define EMIF_EXT_PHY_CTRL_16_SHDW 0x027c ++#define EMIF_EXT_PHY_CTRL_17 0x0280 ++#define EMIF_EXT_PHY_CTRL_17_SHDW 0x0284 ++#define EMIF_EXT_PHY_CTRL_18 0x0288 ++#define EMIF_EXT_PHY_CTRL_18_SHDW 0x028c ++#define EMIF_EXT_PHY_CTRL_19 0x0290 ++#define EMIF_EXT_PHY_CTRL_19_SHDW 0x0294 ++#define EMIF_EXT_PHY_CTRL_20 0x0298 ++#define EMIF_EXT_PHY_CTRL_20_SHDW 0x029c ++#define EMIF_EXT_PHY_CTRL_21 0x02a0 ++#define EMIF_EXT_PHY_CTRL_21_SHDW 0x02a4 ++#define EMIF_EXT_PHY_CTRL_22 0x02a8 ++#define EMIF_EXT_PHY_CTRL_22_SHDW 0x02ac ++#define EMIF_EXT_PHY_CTRL_23 0x02b0 ++#define EMIF_EXT_PHY_CTRL_23_SHDW 0x02b4 ++#define EMIF_EXT_PHY_CTRL_24 0x02b8 ++#define EMIF_EXT_PHY_CTRL_24_SHDW 0x02bc ++#define EMIF_EXT_PHY_CTRL_25 0x02c0 ++#define EMIF_EXT_PHY_CTRL_25_SHDW 0x02c4 ++#define EMIF_EXT_PHY_CTRL_26 0x02c8 ++#define EMIF_EXT_PHY_CTRL_26_SHDW 0x02cc ++#define EMIF_EXT_PHY_CTRL_27 0x02d0 ++#define EMIF_EXT_PHY_CTRL_27_SHDW 0x02d4 ++#define EMIF_EXT_PHY_CTRL_28 0x02d8 ++#define EMIF_EXT_PHY_CTRL_28_SHDW 0x02dc ++#define EMIF_EXT_PHY_CTRL_29 0x02e0 ++#define EMIF_EXT_PHY_CTRL_29_SHDW 0x02e4 ++#define EMIF_EXT_PHY_CTRL_30 0x02e8 ++#define EMIF_EXT_PHY_CTRL_30_SHDW 0x02ec ++ ++/* Registers shifts and masks */ ++ ++/* EMIF_MODULE_ID_AND_REVISION */ ++#define SCHEME_SHIFT 30 ++#define SCHEME_MASK (0x3 << 30) ++#define MODULE_ID_SHIFT 16 ++#define MODULE_ID_MASK (0xfff << 16) ++#define RTL_VERSION_SHIFT 11 ++#define RTL_VERSION_MASK (0x1f << 11) ++#define MAJOR_REVISION_SHIFT 8 ++#define MAJOR_REVISION_MASK (0x7 << 8) ++#define MINOR_REVISION_SHIFT 0 ++#define MINOR_REVISION_MASK (0x3f << 0) ++ ++/* STATUS */ ++#define BE_SHIFT 31 ++#define BE_MASK (1 << 31) ++#define DUAL_CLK_MODE_SHIFT 30 ++#define DUAL_CLK_MODE_MASK (1 << 30) ++#define FAST_INIT_SHIFT 29 ++#define FAST_INIT_MASK (1 << 29) ++#define RDLVLGATETO_SHIFT 6 ++#define RDLVLGATETO_MASK (1 << 6) ++#define RDLVLTO_SHIFT 5 ++#define RDLVLTO_MASK (1 << 5) ++#define WRLVLTO_SHIFT 4 ++#define WRLVLTO_MASK (1 << 4) ++#define PHY_DLL_READY_SHIFT 2 ++#define PHY_DLL_READY_MASK (1 << 2) ++ ++/* SDRAM_CONFIG */ ++#define SDRAM_TYPE_SHIFT 29 ++#define SDRAM_TYPE_MASK (0x7 << 29) ++#define IBANK_POS_SHIFT 27 ++#define IBANK_POS_MASK (0x3 << 27) ++#define DDR_TERM_SHIFT 24 ++#define DDR_TERM_MASK (0x7 << 24) ++#define DDR2_DDQS_SHIFT 23 ++#define DDR2_DDQS_MASK (1 << 23) ++#define DYN_ODT_SHIFT 21 ++#define DYN_ODT_MASK (0x3 << 21) ++#define DDR_DISABLE_DLL_SHIFT 20 ++#define DDR_DISABLE_DLL_MASK (1 << 20) ++#define SDRAM_DRIVE_SHIFT 18 ++#define SDRAM_DRIVE_MASK (0x3 << 18) ++#define CWL_SHIFT 16 ++#define CWL_MASK (0x3 << 16) ++#define NARROW_MODE_SHIFT 14 ++#define NARROW_MODE_MASK (0x3 << 14) ++#define CL_SHIFT 10 ++#define CL_MASK (0xf << 10) ++#define ROWSIZE_SHIFT 7 ++#define ROWSIZE_MASK (0x7 << 7) ++#define IBANK_SHIFT 4 ++#define IBANK_MASK (0x7 << 4) ++#define EBANK_SHIFT 3 ++#define EBANK_MASK (1 << 3) ++#define PAGESIZE_SHIFT 0 ++#define PAGESIZE_MASK (0x7 << 0) ++ ++/* SDRAM_CONFIG_2 */ ++#define CS1NVMEN_SHIFT 30 ++#define CS1NVMEN_MASK (1 << 30) ++#define EBANK_POS_SHIFT 27 ++#define EBANK_POS_MASK (1 << 27) ++#define RDBNUM_SHIFT 4 ++#define RDBNUM_MASK (0x3 << 4) ++#define RDBSIZE_SHIFT 0 ++#define RDBSIZE_MASK (0x7 << 0) ++ ++/* SDRAM_REFRESH_CONTROL */ ++#define INITREF_DIS_SHIFT 31 ++#define INITREF_DIS_MASK (1 << 31) ++#define SRT_SHIFT 29 ++#define SRT_MASK (1 << 29) ++#define ASR_SHIFT 28 ++#define ASR_MASK (1 << 28) ++#define PASR_SHIFT 24 ++#define PASR_MASK (0x7 << 24) ++#define REFRESH_RATE_SHIFT 0 ++#define REFRESH_RATE_MASK (0xffff << 0) ++ ++/* SDRAM_TIMING_1 */ ++#define T_RTW_SHIFT 29 ++#define T_RTW_MASK (0x7 << 29) ++#define T_RP_SHIFT 25 ++#define T_RP_MASK (0xf << 25) ++#define T_RCD_SHIFT 21 ++#define T_RCD_MASK (0xf << 21) ++#define T_WR_SHIFT 17 ++#define T_WR_MASK (0xf << 17) ++#define T_RAS_SHIFT 12 ++#define T_RAS_MASK (0x1f << 12) ++#define T_RC_SHIFT 6 ++#define T_RC_MASK (0x3f << 6) ++#define T_RRD_SHIFT 3 ++#define T_RRD_MASK (0x7 << 3) ++#define T_WTR_SHIFT 0 ++#define T_WTR_MASK (0x7 << 0) ++ ++/* SDRAM_TIMING_2 */ ++#define T_XP_SHIFT 28 ++#define T_XP_MASK (0x7 << 28) ++#define T_ODT_SHIFT 25 ++#define T_ODT_MASK (0x7 << 25) ++#define T_XSNR_SHIFT 16 ++#define T_XSNR_MASK (0x1ff << 16) ++#define T_XSRD_SHIFT 6 ++#define T_XSRD_MASK (0x3ff << 6) ++#define T_RTP_SHIFT 3 ++#define T_RTP_MASK (0x7 << 3) ++#define T_CKE_SHIFT 0 ++#define T_CKE_MASK (0x7 << 0) ++ ++/* SDRAM_TIMING_3 */ ++#define T_PDLL_UL_SHIFT 28 ++#define T_PDLL_UL_MASK (0xf << 28) ++#define T_CSTA_SHIFT 24 ++#define T_CSTA_MASK (0xf << 24) ++#define T_CKESR_SHIFT 21 ++#define T_CKESR_MASK (0x7 << 21) ++#define ZQ_ZQCS_SHIFT 15 ++#define ZQ_ZQCS_MASK (0x3f << 15) ++#define T_TDQSCKMAX_SHIFT 13 ++#define T_TDQSCKMAX_MASK (0x3 << 13) ++#define T_RFC_SHIFT 4 ++#define T_RFC_MASK (0x1ff << 4) ++#define T_RAS_MAX_SHIFT 0 ++#define T_RAS_MAX_MASK (0xf << 0) ++ ++/* POWER_MANAGEMENT_CONTROL */ ++#define PD_TIM_SHIFT 12 ++#define PD_TIM_MASK (0xf << 12) ++#define DPD_EN_SHIFT 11 ++#define DPD_EN_MASK (1 << 11) ++#define LP_MODE_SHIFT 8 ++#define LP_MODE_MASK (0x7 << 8) ++#define SR_TIM_SHIFT 4 ++#define SR_TIM_MASK (0xf << 4) ++#define CS_TIM_SHIFT 0 ++#define CS_TIM_MASK (0xf << 0) ++ ++/* LPDDR2_MODE_REG_DATA */ ++#define VALUE_0_SHIFT 0 ++#define VALUE_0_MASK (0x7f << 0) ++ ++/* LPDDR2_MODE_REG_CONFIG */ ++#define CS_SHIFT 31 ++#define CS_MASK (1 << 31) ++#define REFRESH_EN_SHIFT 30 ++#define REFRESH_EN_MASK (1 << 30) ++#define ADDRESS_SHIFT 0 ++#define ADDRESS_MASK (0xff << 0) ++ ++/* OCP_CONFIG */ ++#define SYS_THRESH_MAX_SHIFT 24 ++#define SYS_THRESH_MAX_MASK (0xf << 24) ++#define MPU_THRESH_MAX_SHIFT 20 ++#define MPU_THRESH_MAX_MASK (0xf << 20) ++#define LL_THRESH_MAX_SHIFT 16 ++#define LL_THRESH_MAX_MASK (0xf << 16) ++ ++/* PERFORMANCE_COUNTER_1 */ ++#define COUNTER1_SHIFT 0 ++#define COUNTER1_MASK (0xffffffff << 0) ++ ++/* PERFORMANCE_COUNTER_2 */ ++#define COUNTER2_SHIFT 0 ++#define COUNTER2_MASK (0xffffffff << 0) ++ ++/* PERFORMANCE_COUNTER_CONFIG */ ++#define CNTR2_MCONNID_EN_SHIFT 31 ++#define CNTR2_MCONNID_EN_MASK (1 << 31) ++#define CNTR2_REGION_EN_SHIFT 30 ++#define CNTR2_REGION_EN_MASK (1 << 30) ++#define CNTR2_CFG_SHIFT 16 ++#define CNTR2_CFG_MASK (0xf << 16) ++#define CNTR1_MCONNID_EN_SHIFT 15 ++#define CNTR1_MCONNID_EN_MASK (1 << 15) ++#define CNTR1_REGION_EN_SHIFT 14 ++#define CNTR1_REGION_EN_MASK (1 << 14) ++#define CNTR1_CFG_SHIFT 0 ++#define CNTR1_CFG_MASK (0xf << 0) ++ ++/* PERFORMANCE_COUNTER_MASTER_REGION_SELECT */ ++#define MCONNID2_SHIFT 24 ++#define MCONNID2_MASK (0xff << 24) ++#define REGION_SEL2_SHIFT 16 ++#define REGION_SEL2_MASK (0x3 << 16) ++#define MCONNID1_SHIFT 8 ++#define MCONNID1_MASK (0xff << 8) ++#define REGION_SEL1_SHIFT 0 ++#define REGION_SEL1_MASK (0x3 << 0) ++ ++/* PERFORMANCE_COUNTER_TIME */ ++#define TOTAL_TIME_SHIFT 0 ++#define TOTAL_TIME_MASK (0xffffffff << 0) ++ ++/* DLL_CALIB_CTRL */ ++#define ACK_WAIT_SHIFT 16 ++#define ACK_WAIT_MASK (0xf << 16) ++#define DLL_CALIB_INTERVAL_SHIFT 0 ++#define DLL_CALIB_INTERVAL_MASK (0x1ff << 0) ++ ++/* END_OF_INTERRUPT */ ++#define EOI_SHIFT 0 ++#define EOI_MASK (1 << 0) ++ ++/* SYSTEM_OCP_INTERRUPT_RAW_STATUS */ ++#define DNV_SYS_SHIFT 2 ++#define DNV_SYS_MASK (1 << 2) ++#define TA_SYS_SHIFT 1 ++#define TA_SYS_MASK (1 << 1) ++#define ERR_SYS_SHIFT 0 ++#define ERR_SYS_MASK (1 << 0) ++ ++/* LOW_LATENCY_OCP_INTERRUPT_RAW_STATUS */ ++#define DNV_LL_SHIFT 2 ++#define DNV_LL_MASK (1 << 2) ++#define TA_LL_SHIFT 1 ++#define TA_LL_MASK (1 << 1) ++#define ERR_LL_SHIFT 0 ++#define ERR_LL_MASK (1 << 0) ++ ++/* SYSTEM_OCP_INTERRUPT_ENABLE_SET */ ++#define EN_DNV_SYS_SHIFT 2 ++#define EN_DNV_SYS_MASK (1 << 2) ++#define EN_TA_SYS_SHIFT 1 ++#define EN_TA_SYS_MASK (1 << 1) ++#define EN_ERR_SYS_SHIFT 0 ++#define EN_ERR_SYS_MASK (1 << 0) ++ ++/* LOW_LATENCY_OCP_INTERRUPT_ENABLE_SET */ ++#define EN_DNV_LL_SHIFT 2 ++#define EN_DNV_LL_MASK (1 << 2) ++#define EN_TA_LL_SHIFT 1 ++#define EN_TA_LL_MASK (1 << 1) ++#define EN_ERR_LL_SHIFT 0 ++#define EN_ERR_LL_MASK (1 << 0) ++ ++/* SDRAM_OUTPUT_IMPEDANCE_CALIBRATION_CONFIG */ ++#define ZQ_CS1EN_SHIFT 31 ++#define ZQ_CS1EN_MASK (1 << 31) ++#define ZQ_CS0EN_SHIFT 30 ++#define ZQ_CS0EN_MASK (1 << 30) ++#define ZQ_DUALCALEN_SHIFT 29 ++#define ZQ_DUALCALEN_MASK (1 << 29) ++#define ZQ_SFEXITEN_SHIFT 28 ++#define ZQ_SFEXITEN_MASK (1 << 28) ++#define ZQ_ZQINIT_MULT_SHIFT 18 ++#define ZQ_ZQINIT_MULT_MASK (0x3 << 18) ++#define ZQ_ZQCL_MULT_SHIFT 16 ++#define ZQ_ZQCL_MULT_MASK (0x3 << 16) ++#define ZQ_REFINTERVAL_SHIFT 0 ++#define ZQ_REFINTERVAL_MASK (0xffff << 0) ++ ++/* TEMPERATURE_ALERT_CONFIG */ ++#define TA_CS1EN_SHIFT 31 ++#define TA_CS1EN_MASK (1 << 31) ++#define TA_CS0EN_SHIFT 30 ++#define TA_CS0EN_MASK (1 << 30) ++#define TA_SFEXITEN_SHIFT 28 ++#define TA_SFEXITEN_MASK (1 << 28) ++#define TA_DEVWDT_SHIFT 26 ++#define TA_DEVWDT_MASK (0x3 << 26) ++#define TA_DEVCNT_SHIFT 24 ++#define TA_DEVCNT_MASK (0x3 << 24) ++#define TA_REFINTERVAL_SHIFT 0 ++#define TA_REFINTERVAL_MASK (0x3fffff << 0) ++ ++/* OCP_ERROR_LOG */ ++#define MADDRSPACE_SHIFT 14 ++#define MADDRSPACE_MASK (0x3 << 14) ++#define MBURSTSEQ_SHIFT 11 ++#define MBURSTSEQ_MASK (0x7 << 11) ++#define MCMD_SHIFT 8 ++#define MCMD_MASK (0x7 << 8) ++#define MCONNID_SHIFT 0 ++#define MCONNID_MASK (0xff << 0) ++ ++/* DDR_PHY_CTRL_1 - EMIF4D */ ++#define DLL_SLAVE_DLY_CTRL_SHIFT_4D 4 ++#define DLL_SLAVE_DLY_CTRL_MASK_4D (0xFF << 4) ++#define READ_LATENCY_SHIFT_4D 0 ++#define READ_LATENCY_MASK_4D (0xf << 0) ++ ++/* DDR_PHY_CTRL_1 - EMIF4D5 */ ++#define DLL_HALF_DELAY_SHIFT_4D5 21 ++#define DLL_HALF_DELAY_MASK_4D5 (1 << 21) ++#define READ_LATENCY_SHIFT_4D5 0 ++#define READ_LATENCY_MASK_4D5 (0x1f << 0) ++ ++/* DDR_PHY_CTRL_1_SHDW */ ++#define DDR_PHY_CTRL_1_SHDW_SHIFT 5 ++#define DDR_PHY_CTRL_1_SHDW_MASK (0x7ffffff << 5) ++#define READ_LATENCY_SHDW_SHIFT 0 ++#define READ_LATENCY_SHDW_MASK (0x1f << 0) ++ ++#endif /* __TI_EMIF_H */ +--- a/include/linux/usb/musb.h ++++ b/include/linux/usb/musb.h +@@ -99,8 +99,6 @@ struct musb_hdrc_platform_data { + /* MUSB_HOST, MUSB_PERIPHERAL, or MUSB_OTG */ + u8 mode; + +- u8 has_mailbox:1; +- + /* for clk_get() */ + const char *clock; + +--- a/include/linux/usb/omap_control_usb.h ++++ /dev/null +@@ -1,92 +0,0 @@ +-/* +- * omap_control_usb.h - Header file for the USB part of control module. +- * +- * Copyright (C) 2013 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; either version 2 of the License, or +- * (at your option) any later version. +- * +- * Author: Kishon Vijay Abraham I <kishon@ti.com> +- * +- * 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 __OMAP_CONTROL_USB_H__ +-#define __OMAP_CONTROL_USB_H__ +- +-struct omap_control_usb { +- struct device *dev; +- +- u32 __iomem *dev_conf; +- u32 __iomem *otghs_control; +- u32 __iomem *phy_power; +- +- struct clk *sys_clk; +- +- u32 type; +-}; +- +-struct omap_control_usb_platform_data { +- u8 type; +-}; +- +-enum omap_control_usb_mode { +- USB_MODE_UNDEFINED = 0, +- USB_MODE_HOST, +- USB_MODE_DEVICE, +- USB_MODE_DISCONNECT, +-}; +- +-/* To differentiate ctrl module IP having either mailbox or USB3 PHY power */ +-#define OMAP_CTRL_DEV_TYPE1 0x1 +-#define OMAP_CTRL_DEV_TYPE2 0x2 +- +-#define OMAP_CTRL_DEV_PHY_PD BIT(0) +- +-#define OMAP_CTRL_DEV_AVALID BIT(0) +-#define OMAP_CTRL_DEV_BVALID BIT(1) +-#define OMAP_CTRL_DEV_VBUSVALID BIT(2) +-#define OMAP_CTRL_DEV_SESSEND BIT(3) +-#define OMAP_CTRL_DEV_IDDIG BIT(4) +- +-#define OMAP_CTRL_USB_PWRCTL_CLK_CMD_MASK 0x003FC000 +-#define OMAP_CTRL_USB_PWRCTL_CLK_CMD_SHIFT 0xE +- +-#define OMAP_CTRL_USB_PWRCTL_CLK_FREQ_MASK 0xFFC00000 +-#define OMAP_CTRL_USB_PWRCTL_CLK_FREQ_SHIFT 0x16 +- +-#define OMAP_CTRL_USB3_PHY_TX_RX_POWERON 0x3 +-#define OMAP_CTRL_USB3_PHY_TX_RX_POWEROFF 0x0 +- +-#if IS_ENABLED(CONFIG_OMAP_CONTROL_USB) +-extern struct device *omap_get_control_dev(void); +-extern void omap_control_usb_phy_power(struct device *dev, int on); +-extern void omap_control_usb3_phy_power(struct device *dev, bool on); +-extern void omap_control_usb_set_mode(struct device *dev, +- enum omap_control_usb_mode mode); +-#else +-static inline struct device *omap_get_control_dev(void) +-{ +- return ERR_PTR(-ENODEV); +-} +- +-static inline void omap_control_usb_phy_power(struct device *dev, int on) +-{ +-} +- +-static inline void omap_control_usb3_phy_power(struct device *dev, int on) +-{ +-} +- +-static inline void omap_control_usb_set_mode(struct device *dev, +- enum omap_control_usb_mode mode) +-{ +-} +-#endif +- +-#endif /* __OMAP_CONTROL_USB_H__ */ +--- a/include/linux/usb/omap_usb.h ++++ /dev/null +@@ -1,67 +0,0 @@ +-/* +- * omap_usb.h -- omap usb2 phy header file +- * +- * Copyright (C) 2012 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; either version 2 of the License, or +- * (at your option) any later version. +- * +- * Author: Kishon Vijay Abraham I <kishon@ti.com> +- * +- * 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 __DRIVERS_OMAP_USB2_H +-#define __DRIVERS_OMAP_USB2_H +- +-#include <linux/io.h> +-#include <linux/usb/otg.h> +- +-struct usb_dpll_params { +- u16 m; +- u8 n; +- u8 freq:3; +- u8 sd; +- u32 mf; +-}; +- +-struct omap_usb { +- struct usb_phy phy; +- struct phy_companion *comparator; +- void __iomem *pll_ctrl_base; +- struct device *dev; +- struct device *control_dev; +- struct clk *wkupclk; +- struct clk *sys_clk; +- struct clk *optclk; +- u8 is_suspended:1; +-}; +- +-#define phy_to_omapusb(x) container_of((x), struct omap_usb, phy) +- +-#if defined(CONFIG_OMAP_USB2) || defined(CONFIG_OMAP_USB2_MODULE) +-extern int omap_usb2_set_comparator(struct phy_companion *comparator); +-#else +-static inline int omap_usb2_set_comparator(struct phy_companion *comparator) +-{ +- return -ENODEV; +-} +-#endif +- +-static inline u32 omap_usb_readl(void __iomem *addr, unsigned offset) +-{ +- return __raw_readl(addr + offset); +-} +- +-static inline void omap_usb_writel(void __iomem *addr, unsigned offset, +- u32 data) +-{ +- __raw_writel(data, addr + offset); +-} +- +-#endif /* __DRIVERS_OMAP_USB_H */ +--- a/include/linux/usb/usb_phy_gen_xceiv.h ++++ b/include/linux/usb/usb_phy_gen_xceiv.h +@@ -9,7 +9,8 @@ struct usb_phy_gen_xceiv_platform_data { + + /* if set fails with -EPROBE_DEFER if can't get regulator */ + unsigned int needs_vcc:1; +- unsigned int needs_reset:1; ++ unsigned int needs_reset:1; /* deprecated */ ++ int gpio_reset; + }; + + #if defined(CONFIG_NOP_USB_XCEIV) || (defined(CONFIG_NOP_USB_XCEIV_MODULE) && defined(MODULE)) +--- a/include/uapi/linux/v4l2-controls.h ++++ b/include/uapi/linux/v4l2-controls.h +@@ -160,6 +160,10 @@ enum v4l2_colorfx { + * of controls. Total of 16 controls is reserved for this driver */ + #define V4L2_CID_USER_SI476X_BASE (V4L2_CID_USER_BASE + 0x1040) + ++/* The base for the TI VPE driver controls. Total of 16 controls is reserved for ++ * this driver */ ++#define V4L2_CID_USER_TI_VPE_BASE (V4L2_CID_USER_BASE + 0x1050) ++ + /* MPEG-class control IDs */ + /* The MPEG controls are applicable to all codec controls + * and the 'MPEG' part of the define is historical */ +--- a/include/video/da8xx-fb.h ++++ b/include/video/da8xx-fb.h +@@ -12,6 +12,8 @@ + #ifndef DA8XX_FB_H + #define DA8XX_FB_H + ++#include <linux/fb.h> ++ + enum panel_shade { + MONOCHROME = 0, + COLOR_ACTIVE, +@@ -91,5 +93,22 @@ struct lcd_sync_arg { + /* Proprietary FB_SYNC_ flags */ + #define FB_SYNC_CLK_INVERT 0x40000000 + ++struct da8xx_encoder { ++ struct list_head list; /* internal use only */ ++ struct i2c_client *client; ++ void *priv; ++ void (*set_mode)(struct da8xx_encoder *encoder, ++ struct fb_videomode *panel); ++ struct device_node *node; ++}; ++ ++void da8xx_register_encoder(struct da8xx_encoder *encoder); ++void da8xx_unregister_encoder(struct da8xx_encoder *encoder); ++ ++ ++typedef void (*vsync_callback_t)(void *arg); ++int register_vsync_cb(vsync_callback_t handler, void *arg, int idx); ++int unregister_vsync_cb(vsync_callback_t handler, void *arg, int idx); ++ + #endif /* ifndef DA8XX_FB_H */ + +--- /dev/null ++++ b/include/video/da8xx-tda998x-hdmi.h +@@ -0,0 +1,35 @@ ++/* ++ * Header file for TI DA8XX/TDA998x Encoder Driver ++ * ++ * Copyright (C) 2013 Texas Instruments Inc ++ * ++ * This file is licensed under the terms of the GNU General Public License ++ * version 2. This program is licensed "as is" without any warranty of any ++ * kind, whether express or implied. ++ */ ++ ++#ifndef DA8XX_TDA998X_HDMI_H ++#define DA8XX_TDA998X_HDMI_H ++ ++#include <linux/fb.h> ++ ++enum tda998x_audio_format { ++ AFMT_I2S, ++ AFMT_SPDIF, ++}; ++ ++struct tda998x_encoder_params { ++ int audio_cfg; ++ int audio_clk_cfg; ++ enum tda998x_audio_format audio_format; ++ int audio_sample_rate; ++ char audio_frame[6]; ++ int swap_a, mirr_a; ++ int swap_b, mirr_b; ++ int swap_c, mirr_c; ++ int swap_d, mirr_d; ++ int swap_e, mirr_e; ++ int swap_f, mirr_f; ++}; ++ ++#endif +--- a/include/video/omapdss.h ++++ b/include/video/omapdss.h +@@ -227,6 +227,8 @@ enum omap_dss_output_id { + OMAP_DSS_OUTPUT_DSI2 = 1 << 4, + OMAP_DSS_OUTPUT_VENC = 1 << 5, + OMAP_DSS_OUTPUT_HDMI = 1 << 6, ++ OMAP_DSS_OUTPUT_DPI1 = 1 << 7, ++ OMAP_DSS_OUTPUT_DPI2 = 1 << 8, + }; + + /* RFBI */ +@@ -319,6 +321,8 @@ enum omapdss_version { + OMAPDSS_VER_OMAP4430_ES2, /* OMAP4430 ES2.0, 2.1, 2.2 */ + OMAPDSS_VER_OMAP4, /* All other OMAP4s */ + OMAPDSS_VER_OMAP5, ++ OMAPDSS_VER_DRA7xx, ++ OMAPDSS_VER_AM43xx, + }; + + /* Board specific data */ +@@ -961,6 +965,10 @@ int dispc_ovl_enable(enum omap_plane pla + bool dispc_ovl_enabled(enum omap_plane plane); + void dispc_ovl_set_channel_out(enum omap_plane plane, + enum omap_channel channel); ++void dispc_ovl_compute_fifo_thresholds(enum omap_plane plane, ++ u32 *fifo_low, u32 *fifo_high, bool use_fifomerge, ++ bool manual_update); ++void dispc_ovl_set_fifo_threshold(enum omap_plane plane, u32 low, u32 high); + int dispc_ovl_setup(enum omap_plane plane, const struct omap_overlay_info *oi, + bool replication, const struct omap_video_timings *mgr_timings, + bool mem_to_mem); +--- a/include/video/omap-panel-data.h ++++ b/include/video/omap-panel-data.h +@@ -62,6 +62,20 @@ struct encoder_tpd12s015_platform_data { + }; + + /** ++ * encoder_sil9022 platform data ++ * @name: name for this display entity ++ * @res_gpio: Gpio to switch lcd and hdmi. Used as reset for Sil9022 ++ * as a temproary solution. ++ */ ++struct encoder_sil9022_platform_data { ++ const char *name; ++ const char *source; ++ int reset_gpio; ++ int data_lines; ++}; ++ ++ ++/** + * connector_dvi platform data + * @name: name for this display entity + * @source: name of the display entity used as a video source +--- a/MAINTAINERS ++++ b/MAINTAINERS +@@ -3691,6 +3691,14 @@ S: Maintained + F: include/asm-generic/ + F: include/uapi/asm-generic/ + ++GENERIC PHY FRAMEWORK ++M: Kishon Vijay Abraham I <kishon@ti.com> ++L: linux-kernel@vger.kernel.org ++T: git git://git.kernel.org/pub/scm/linux/kernel/git/kishon/linux-phy.git ++S: Supported ++F: drivers/phy/ ++F: include/linux/phy/ ++ + GENERIC UIO DRIVER FOR PCI DEVICES + M: "Michael S. Tsirkin" <mst@redhat.com> + L: kvm@vger.kernel.org +--- a/sound/soc/davinci/davinci-evm.c ++++ b/sound/soc/davinci/davinci-evm.c +@@ -16,6 +16,7 @@ + #include <linux/platform_device.h> + #include <linux/platform_data/edma.h> + #include <linux/i2c.h> ++#include <linux/of_platform.h> + #include <sound/core.h> + #include <sound/pcm.h> + #include <sound/soc.h> +@@ -23,10 +24,16 @@ + #include <asm/dma.h> + #include <asm/mach-types.h> + ++#include <linux/edma.h> ++ + #include "davinci-pcm.h" + #include "davinci-i2s.h" + #include "davinci-mcasp.h" + ++struct snd_soc_card_drvdata_davinci { ++ unsigned sysclk; ++}; ++ + #define AUDIO_FORMAT (SND_SOC_DAIFMT_DSP_B | \ + SND_SOC_DAIFMT_CBM_CFM | SND_SOC_DAIFMT_IB_NF) + static int evm_hw_params(struct snd_pcm_substream *substream, +@@ -35,27 +42,11 @@ static int evm_hw_params(struct snd_pcm_ + struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_dai *codec_dai = rtd->codec_dai; + struct snd_soc_dai *cpu_dai = rtd->cpu_dai; ++ struct snd_soc_codec *codec = rtd->codec; ++ struct snd_soc_card *soc_card = codec->card; + int ret = 0; +- unsigned sysclk; +- +- /* ASP1 on DM355 EVM is clocked by an external oscillator */ +- if (machine_is_davinci_dm355_evm() || machine_is_davinci_dm6467_evm() || +- machine_is_davinci_dm365_evm()) +- sysclk = 27000000; +- +- /* ASP0 in DM6446 EVM is clocked by U55, as configured by +- * board-dm644x-evm.c using GPIOs from U18. There are six +- * options; here we "know" we use a 48 KHz sample rate. +- */ +- else if (machine_is_davinci_evm()) +- sysclk = 12288000; +- +- else if (machine_is_davinci_da830_evm() || +- machine_is_davinci_da850_evm()) +- sysclk = 24576000; +- +- else +- return -EINVAL; ++ unsigned sysclk = ((struct snd_soc_card_drvdata_davinci *) ++ snd_soc_card_get_drvdata(soc_card))->sysclk; + + /* set codec DAI configuration */ + ret = snd_soc_dai_set_fmt(codec_dai, AUDIO_FORMAT); +@@ -133,13 +124,22 @@ static int evm_aic3x_init(struct snd_soc + { + struct snd_soc_codec *codec = rtd->codec; + struct snd_soc_dapm_context *dapm = &codec->dapm; ++ struct device_node *np = codec->card->dev->of_node; ++ int ret; + + /* Add davinci-evm specific widgets */ + snd_soc_dapm_new_controls(dapm, aic3x_dapm_widgets, + ARRAY_SIZE(aic3x_dapm_widgets)); + +- /* Set up davinci-evm specific audio path audio_map */ +- snd_soc_dapm_add_routes(dapm, audio_map, ARRAY_SIZE(audio_map)); ++ if (np) { ++ ret = snd_soc_of_parse_audio_routing(codec->card, ++ "ti,audio-routing"); ++ if (ret) ++ return ret; ++ } else { ++ /* Set up davinci-evm specific audio path audio_map */ ++ snd_soc_dapm_add_routes(dapm, audio_map, ARRAY_SIZE(audio_map)); ++ } + + /* not connected */ + snd_soc_dapm_disable_pin(dapm, "MONO_LOUT"); +@@ -243,35 +243,65 @@ static struct snd_soc_dai_link da850_evm + }; + + /* davinci dm6446 evm audio machine driver */ ++/* ++ * ASP0 in DM6446 EVM is clocked by U55, as configured by ++ * board-dm644x-evm.c using GPIOs from U18. There are six ++ * options; here we "know" we use a 48 KHz sample rate. ++ */ ++static struct snd_soc_card_drvdata_davinci dm6446_snd_soc_card_drvdata = { ++ .sysclk = 12288000, ++}; ++ + static struct snd_soc_card dm6446_snd_soc_card_evm = { + .name = "DaVinci DM6446 EVM", + .owner = THIS_MODULE, + .dai_link = &dm6446_evm_dai, + .num_links = 1, ++ .drvdata = &dm6446_snd_soc_card_drvdata, + }; + + /* davinci dm355 evm audio machine driver */ ++/* ASP1 on DM355 EVM is clocked by an external oscillator */ ++static struct snd_soc_card_drvdata_davinci dm355_snd_soc_card_drvdata = { ++ .sysclk = 27000000, ++}; ++ + static struct snd_soc_card dm355_snd_soc_card_evm = { + .name = "DaVinci DM355 EVM", + .owner = THIS_MODULE, + .dai_link = &dm355_evm_dai, + .num_links = 1, ++ .drvdata = &dm355_snd_soc_card_drvdata, + }; + + /* davinci dm365 evm audio machine driver */ ++static struct snd_soc_card_drvdata_davinci dm365_snd_soc_card_drvdata = { ++ .sysclk = 27000000, ++}; ++ + static struct snd_soc_card dm365_snd_soc_card_evm = { + .name = "DaVinci DM365 EVM", + .owner = THIS_MODULE, + .dai_link = &dm365_evm_dai, + .num_links = 1, ++ .drvdata = &dm365_snd_soc_card_drvdata, + }; + + /* davinci dm6467 evm audio machine driver */ ++static struct snd_soc_card_drvdata_davinci dm6467_snd_soc_card_drvdata = { ++ .sysclk = 27000000, ++}; ++ + static struct snd_soc_card dm6467_snd_soc_card_evm = { + .name = "DaVinci DM6467 EVM", + .owner = THIS_MODULE, + .dai_link = dm6467_evm_dai, + .num_links = ARRAY_SIZE(dm6467_evm_dai), ++ .drvdata = &dm6467_snd_soc_card_drvdata, ++}; ++ ++static struct snd_soc_card_drvdata_davinci da830_snd_soc_card_drvdata = { ++ .sysclk = 24576000, + }; + + static struct snd_soc_card da830_snd_soc_card = { +@@ -279,6 +309,11 @@ static struct snd_soc_card da830_snd_soc + .owner = THIS_MODULE, + .dai_link = &da830_evm_dai, + .num_links = 1, ++ .drvdata = &da830_snd_soc_card_drvdata, ++}; ++ ++static struct snd_soc_card_drvdata_davinci da850_snd_soc_card_drvdata = { ++ .sysclk = 24576000, + }; + + static struct snd_soc_card da850_snd_soc_card = { +@@ -286,8 +321,101 @@ static struct snd_soc_card da850_snd_soc + .owner = THIS_MODULE, + .dai_link = &da850_evm_dai, + .num_links = 1, ++ .drvdata = &da850_snd_soc_card_drvdata, ++}; ++ ++#if defined(CONFIG_OF) ++ ++/* ++ * The struct is used as place holder. It will be completely ++ * filled with data from dt node. ++ */ ++static struct snd_soc_dai_link evm_dai_tlv320aic3x = { ++ .name = "TLV320AIC3X", ++ .stream_name = "AIC3X", ++ .codec_dai_name = "tlv320aic3x-hifi", ++ .ops = &evm_ops, ++ .init = evm_aic3x_init, ++}; ++ ++static const struct of_device_id davinci_evm_dt_ids[] = { ++ { ++ .compatible = "ti,da830-evm-audio", ++ .data = (void *) &evm_dai_tlv320aic3x, ++ }, ++ { /* sentinel */ } ++}; ++MODULE_DEVICE_TABLE(of, davinci_evm_dt_ids); ++ ++/* davinci evm audio machine driver */ ++static struct snd_soc_card evm_soc_card = { ++ .owner = THIS_MODULE, ++ .num_links = 1, + }; + ++static int davinci_evm_probe(struct platform_device *pdev) ++{ ++ struct device_node *np = pdev->dev.of_node; ++ const struct of_device_id *match = ++ of_match_device(of_match_ptr(davinci_evm_dt_ids), &pdev->dev); ++ struct snd_soc_dai_link *dai = (struct snd_soc_dai_link *) match->data; ++ struct snd_soc_card_drvdata_davinci *drvdata = NULL; ++ int ret = 0; ++ ++ evm_soc_card.dai_link = dai; ++ ++ dai->codec_of_node = of_parse_phandle(np, "ti,audio-codec", 0); ++ if (!dai->codec_of_node) ++ return -EINVAL; ++ ++ dai->cpu_of_node = of_parse_phandle(np, "ti,mcasp-controller", 0); ++ if (!dai->cpu_of_node) ++ return -EINVAL; ++ ++ dai->platform_of_node = dai->cpu_of_node; ++ ++ evm_soc_card.dev = &pdev->dev; ++ ret = snd_soc_of_parse_card_name(&evm_soc_card, "ti,model"); ++ if (ret) ++ return ret; ++ ++ drvdata = devm_kzalloc(&pdev->dev, sizeof(*drvdata), GFP_KERNEL); ++ if (!drvdata) ++ return -ENOMEM; ++ ++ ret = of_property_read_u32(np, "ti,codec-clock-rate", &drvdata->sysclk); ++ if (ret < 0) ++ return -EINVAL; ++ ++ snd_soc_card_set_drvdata(&evm_soc_card, drvdata); ++ ret = snd_soc_register_card(&evm_soc_card); ++ ++ if (ret) ++ dev_err(&pdev->dev, "snd_soc_register_card failed (%d)\n", ret); ++ ++ return ret; ++} ++ ++static int davinci_evm_remove(struct platform_device *pdev) ++{ ++ struct snd_soc_card *card = platform_get_drvdata(pdev); ++ ++ snd_soc_unregister_card(card); ++ ++ return 0; ++} ++ ++static struct platform_driver davinci_evm_driver = { ++ .probe = davinci_evm_probe, ++ .remove = davinci_evm_remove, ++ .driver = { ++ .name = "davinci_evm", ++ .owner = THIS_MODULE, ++ .of_match_table = of_match_ptr(davinci_evm_dt_ids), ++ }, ++}; ++#endif ++ + static struct platform_device *evm_snd_device; + + static int __init evm_init(void) +@@ -296,6 +424,13 @@ static int __init evm_init(void) + int index; + int ret; + ++ /* ++ * If dtb is there, the devices will be created dynamically. ++ * Only register platfrom driver structure. ++ */ ++ if (of_have_populated_dt()) ++ return platform_driver_register(&davinci_evm_driver); ++ + if (machine_is_davinci_evm()) { + evm_snd_dev_data = &dm6446_snd_soc_card_evm; + index = 0; +@@ -331,6 +466,11 @@ static int __init evm_init(void) + + static void __exit evm_exit(void) + { ++ if (of_have_populated_dt()) { ++ platform_driver_unregister(&davinci_evm_driver); ++ return; ++ } ++ + platform_device_unregister(evm_snd_device); + } + +--- a/sound/soc/davinci/davinci-mcasp.c ++++ b/sound/soc/davinci/davinci-mcasp.c +@@ -1001,18 +1001,40 @@ static const struct snd_soc_component_dr + .name = "davinci-mcasp", + }; + ++/* Some HW specific values and defaults. The rest is filled in from DT. */ ++static struct snd_platform_data dm646x_mcasp_pdata = { ++ .tx_dma_offset = 0x400, ++ .rx_dma_offset = 0x400, ++ .asp_chan_q = EVENTQ_0, ++ .version = MCASP_VERSION_1, ++}; ++ ++static struct snd_platform_data da830_mcasp_pdata = { ++ .tx_dma_offset = 0x2000, ++ .rx_dma_offset = 0x2000, ++ .asp_chan_q = EVENTQ_0, ++ .version = MCASP_VERSION_2, ++}; ++ ++static struct snd_platform_data omap2_mcasp_pdata = { ++ .tx_dma_offset = 0, ++ .rx_dma_offset = 0, ++ .asp_chan_q = EVENTQ_0, ++ .version = MCASP_VERSION_3, ++}; ++ + static const struct of_device_id mcasp_dt_ids[] = { + { + .compatible = "ti,dm646x-mcasp-audio", +- .data = (void *)MCASP_VERSION_1, ++ .data = &dm646x_mcasp_pdata, + }, + { + .compatible = "ti,da830-mcasp-audio", +- .data = (void *)MCASP_VERSION_2, ++ .data = &da830_mcasp_pdata, + }, + { + .compatible = "ti,omap2-mcasp-audio", +- .data = (void *)MCASP_VERSION_3, ++ .data = &omap2_mcasp_pdata, + }, + { /* sentinel */ } + }; +@@ -1025,9 +1047,9 @@ static struct snd_platform_data *davinci + struct snd_platform_data *pdata = NULL; + const struct of_device_id *match = + of_match_device(mcasp_dt_ids, &pdev->dev); ++ struct of_phandle_args dma_spec; + + const u32 *of_serial_dir32; +- u8 *of_serial_dir; + u32 val; + int i, ret = 0; + +@@ -1035,20 +1057,13 @@ static struct snd_platform_data *davinci + pdata = pdev->dev.platform_data; + return pdata; + } else if (match) { +- pdata = devm_kzalloc(&pdev->dev, sizeof(*pdata), GFP_KERNEL); +- if (!pdata) { +- ret = -ENOMEM; +- goto nodata; +- } ++ pdata = (struct snd_platform_data *) match->data; + } else { + /* control shouldn't reach here. something is wrong */ + ret = -EINVAL; + goto nodata; + } + +- if (match->data) +- pdata->version = (u8)((int)match->data); +- + ret = of_property_read_u32(np, "op-mode", &val); + if (ret >= 0) + pdata->op_mode = val; +@@ -1065,35 +1080,46 @@ static struct snd_platform_data *davinci + pdata->tdm_slots = val; + } + +- ret = of_property_read_u32(np, "num-serializer", &val); +- if (ret >= 0) +- pdata->num_serializer = val; +- + of_serial_dir32 = of_get_property(np, "serial-dir", &val); + val /= sizeof(u32); +- if (val != pdata->num_serializer) { +- dev_err(&pdev->dev, +- "num-serializer(%d) != serial-dir size(%d)\n", +- pdata->num_serializer, val); +- ret = -EINVAL; +- goto nodata; +- } +- + if (of_serial_dir32) { +- of_serial_dir = devm_kzalloc(&pdev->dev, +- (sizeof(*of_serial_dir) * val), +- GFP_KERNEL); ++ u8 *of_serial_dir = devm_kzalloc(&pdev->dev, ++ (sizeof(*of_serial_dir) * val), ++ GFP_KERNEL); + if (!of_serial_dir) { + ret = -ENOMEM; + goto nodata; + } + +- for (i = 0; i < pdata->num_serializer; i++) ++ for (i = 0; i < val; i++) + of_serial_dir[i] = be32_to_cpup(&of_serial_dir32[i]); + ++ pdata->num_serializer = val; + pdata->serial_dir = of_serial_dir; + } + ++ ret = of_property_match_string(np, "dma-names", "tx"); ++ if (ret < 0) ++ goto nodata; ++ ++ ret = of_parse_phandle_with_args(np, "dmas", "#dma-cells", ret, ++ &dma_spec); ++ if (ret < 0) ++ goto nodata; ++ ++ pdata->tx_dma_channel = dma_spec.args[0]; ++ ++ ret = of_property_match_string(np, "dma-names", "rx"); ++ if (ret < 0) ++ goto nodata; ++ ++ ret = of_parse_phandle_with_args(np, "dmas", "#dma-cells", ret, ++ &dma_spec); ++ if (ret < 0) ++ goto nodata; ++ ++ pdata->rx_dma_channel = dma_spec.args[0]; ++ + ret = of_property_read_u32(np, "tx-num-evt", &val); + if (ret >= 0) + pdata->txnumevt = val; +@@ -1124,7 +1150,7 @@ nodata: + static int davinci_mcasp_probe(struct platform_device *pdev) + { + struct davinci_pcm_dma_params *dma_data; +- struct resource *mem, *ioarea, *res; ++ struct resource *mem, *ioarea, *res, *dma; + struct snd_platform_data *pdata; + struct davinci_audio_dev *dev; + int ret; +@@ -1145,10 +1171,15 @@ static int davinci_mcasp_probe(struct pl + return -EINVAL; + } + +- mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); ++ mem = platform_get_resource_byname(pdev, IORESOURCE_MEM, "mpu"); + if (!mem) { +- dev_err(&pdev->dev, "no mem resource?\n"); +- return -ENODEV; ++ dev_warn(dev->dev, ++ "\"mpu\" mem resource not found, using index 0\n"); ++ mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); ++ if (!mem) { ++ dev_err(&pdev->dev, "no mem resource?\n"); ++ return -ENODEV; ++ } + } + + ioarea = devm_request_mem_region(&pdev->dev, mem->start, +@@ -1182,40 +1213,36 @@ static int davinci_mcasp_probe(struct pl + dev->rxnumevt = pdata->rxnumevt; + dev->dev = &pdev->dev; + ++ dma = platform_get_resource_byname(pdev, IORESOURCE_MEM, "dma"); ++ if (!dma) ++ dma = mem; ++ + dma_data = &dev->dma_params[SNDRV_PCM_STREAM_PLAYBACK]; + dma_data->asp_chan_q = pdata->asp_chan_q; + dma_data->ram_chan_q = pdata->ram_chan_q; + dma_data->sram_pool = pdata->sram_pool; + dma_data->sram_size = pdata->sram_size_playback; +- dma_data->dma_addr = (dma_addr_t) (pdata->tx_dma_offset + +- mem->start); ++ dma_data->dma_addr = dma->start + pdata->tx_dma_offset; + +- /* first TX, then RX */ + res = platform_get_resource(pdev, IORESOURCE_DMA, 0); +- if (!res) { +- dev_err(&pdev->dev, "no DMA resource\n"); +- ret = -ENODEV; +- goto err_release_clk; +- } +- +- dma_data->channel = res->start; ++ if (res) ++ dma_data->channel = res->start; ++ else ++ dma_data->channel = pdata->tx_dma_channel; + + dma_data = &dev->dma_params[SNDRV_PCM_STREAM_CAPTURE]; + dma_data->asp_chan_q = pdata->asp_chan_q; + dma_data->ram_chan_q = pdata->ram_chan_q; + dma_data->sram_pool = pdata->sram_pool; + dma_data->sram_size = pdata->sram_size_capture; +- dma_data->dma_addr = (dma_addr_t)(pdata->rx_dma_offset + +- mem->start); ++ dma_data->dma_addr = dma->start + pdata->rx_dma_offset; + + res = platform_get_resource(pdev, IORESOURCE_DMA, 1); +- if (!res) { +- dev_err(&pdev->dev, "no DMA resource\n"); +- ret = -ENODEV; +- goto err_release_clk; +- } ++ if (res) ++ dma_data->channel = res->start; ++ else ++ dma_data->channel = pdata->rx_dma_channel; + +- dma_data->channel = res->start; + dev_set_drvdata(&pdev->dev, dev); + ret = snd_soc_register_component(&pdev->dev, &davinci_mcasp_component, + &davinci_mcasp_dai[pdata->op_mode], 1); +@@ -1266,4 +1293,3 @@ module_platform_driver(davinci_mcasp_dri + MODULE_AUTHOR("Steve Chen"); + MODULE_DESCRIPTION("TI DAVINCI McASP SoC Interface"); + MODULE_LICENSE("GPL"); +- +--- a/sound/soc/davinci/Kconfig ++++ b/sound/soc/davinci/Kconfig +@@ -1,9 +1,10 @@ + config SND_DAVINCI_SOC +- tristate "SoC Audio for the TI DAVINCI chip" +- depends on ARCH_DAVINCI ++ tristate "SoC Audio for the TI DAVINCI or AM33XX chip" ++ depends on ARCH_DAVINCI || SOC_AM33XX + help ++ Platform driver for daVinci or AM33xx + Say Y or M if you want to add support for codecs attached to +- the DAVINCI AC97 or I2S interface. You will also need ++ the DAVINCI AC97, I2S, or McASP interface. You will also need + to select the audio interfaces to support below. + + config SND_DAVINCI_SOC_I2S +@@ -15,6 +16,17 @@ config SND_DAVINCI_SOC_MCASP + config SND_DAVINCI_SOC_VCIF + tristate + ++config SND_AM33XX_SOC_EVM ++ tristate "SoC Audio for the AM33XX chip based boards" ++ depends on SND_DAVINCI_SOC && SOC_AM33XX ++ select SND_SOC_TLV320AIC3X ++ select SND_DAVINCI_SOC_MCASP ++ help ++ Say Y or M if you want to add support for SoC audio on AM33XX ++ boards using McASP and TLV320AIC3X codec. For example AM335X-EVM, ++ AM335X-EVMSK, and BeagelBone with AudioCape boards have this ++ setup. ++ + config SND_DAVINCI_SOC_EVM + tristate "SoC Audio support for DaVinci DM6446, DM355 or DM365 EVM" + depends on SND_DAVINCI_SOC +--- a/sound/soc/davinci/Makefile ++++ b/sound/soc/davinci/Makefile +@@ -13,6 +13,7 @@ obj-$(CONFIG_SND_DAVINCI_SOC_VCIF) += sn + snd-soc-evm-objs := davinci-evm.o + + obj-$(CONFIG_SND_DAVINCI_SOC_EVM) += snd-soc-evm.o ++obj-$(CONFIG_SND_AM33XX_SOC_EVM) += snd-soc-evm.o + obj-$(CONFIG_SND_DM6467_SOC_EVM) += snd-soc-evm.o + obj-$(CONFIG_SND_DA830_SOC_EVM) += snd-soc-evm.o + obj-$(CONFIG_SND_DA850_SOC_EVM) += snd-soc-evm.o +--- a/sound/soc/omap/Kconfig ++++ b/sound/soc/omap/Kconfig +@@ -87,17 +87,19 @@ config SND_OMAP_SOC_OMAP_TWL4030 + + config SND_OMAP_SOC_OMAP_ABE_TWL6040 + tristate "SoC Audio support for OMAP boards using ABE and twl6040 codec" +- depends on TWL6040_CORE && SND_OMAP_SOC && (ARCH_OMAP4 || COMPILE_TEST) ++ depends on TWL6040_CORE && SND_OMAP_SOC && (ARCH_OMAP4 || SOC_OMAP5 || COMPILE_TEST) + select SND_OMAP_SOC_DMIC + select SND_OMAP_SOC_MCPDM + select SND_SOC_TWL6040 + select SND_SOC_DMIC ++ select COMMON_CLK_PALMAS if SOC_OMAP5 + help + Say Y if you want to add support for SoC audio on OMAP boards using + ABE and twl6040 codec. This driver currently supports: + - SDP4430/Blaze boards + - PandaBoard (4430) + - PandaBoardES (4460) ++ - omap5-uevm (5432) + + config SND_OMAP_SOC_OMAP_HDMI + tristate "SoC Audio support for Texas Instruments OMAP HDMI" |