summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorXinyu Chen <xinyu.chen@freescale.com>2012-10-09 16:47:47 +0800
committerXinyu Chen <xinyu.chen@freescale.com>2012-10-09 16:47:47 +0800
commiteba86309d9ba74153b7853cd8fb97f2484679219 (patch)
tree2eca312c9a1dde28c0e376156e5cad1704de08c9
parent58d8257e51439a6c1ac2c95441f7ec119568dd5b (diff)
parent45c27e3123e45eb27f3e5933862936e9beda38cd (diff)
Merge remote branch 'fsl-linux-sdk/imx_3.0.35' into imx_3.0.35_android
Conflicts: arch/arm/configs/imx6s_updater_defconfig arch/arm/include/asm/hardware/coresight.h arch/arm/kernel/etm.c arch/arm/mach-mx6/board-mx6q_sabresd.c arch/arm/mach-mx6/cpu_op-mx6.c arch/arm/mach-mx6/mx6_suspend.S arch/arm/mach-mx6/pm.c arch/arm/mach-mx6/system.c arch/arm/plat-mxc/cpufreq.c drivers/mfd/mxc-hdmi-core.c drivers/power/sabresd_battery.c drivers/video/mxc/mxc_ipuv3_fb.c drivers/video/mxc_hdmi.c include/linux/mfd/mxc-hdmi-core.h
-rw-r--r--arch/arm/configs/imx6_defconfig2
-rw-r--r--arch/arm/configs/imx6s_defconfig57
-rw-r--r--arch/arm/configs/imx6s_updater_defconfig27
-rw-r--r--arch/arm/include/asm/hardware/coresight.h26
-rw-r--r--arch/arm/kernel/etm.c231
-rwxr-xr-xarch/arm/mach-mx5/devices-imx50.h6
-rw-r--r--arch/arm/mach-mx6/Kconfig2
-rw-r--r--arch/arm/mach-mx6/Makefile2
-rw-r--r--arch/arm/mach-mx6/board-mx6q_sabreauto.c36
-rw-r--r--arch/arm/mach-mx6/board-mx6q_sabreauto.h4
-rwxr-xr-xarch/arm/mach-mx6/board-mx6sl_arm2.c2
-rw-r--r--arch/arm/mach-mx6/board-mx6sl_common.h46
-rw-r--r--arch/arm/mach-mx6/board-mx6sl_evk.c263
-rw-r--r--arch/arm/mach-mx6/board-mx6solo_sabreauto.h4
-rw-r--r--arch/arm/mach-mx6/bus_freq.c6
-rw-r--r--arch/arm/mach-mx6/clock.c3
-rwxr-xr-xarch/arm/mach-mx6/clock_mx6sl.c10
-rw-r--r--arch/arm/mach-mx6/cpu.c8
-rw-r--r--arch/arm/mach-mx6/cpu_op-mx6.c12
-rw-r--r--arch/arm/mach-mx6/cpu_regulator-mx6.c18
-rw-r--r--arch/arm/mach-mx6/devices-imx6q.h12
-rw-r--r--arch/arm/mach-mx6/etm.c110
-rw-r--r--arch/arm/mach-mx6/mx6_anatop_regulator.c140
-rw-r--r--arch/arm/mach-mx6/mx6_suspend.S547
-rw-r--r--arch/arm/mach-mx6/mx6sl_arm2_pmic_pfuze100.c6
-rw-r--r--arch/arm/mach-mx6/mx6sl_evk_pmic_pfuze100.c8
-rw-r--r--arch/arm/mach-mx6/mx6sl_wfi.S163
-rw-r--r--arch/arm/mach-mx6/pm.c133
-rw-r--r--arch/arm/mach-mx6/system.c128
-rw-r--r--arch/arm/mach-mx6/usb.h3
-rw-r--r--arch/arm/mach-mx6/usb_dr.c27
-rw-r--r--arch/arm/mach-mx6/usb_h1.c21
-rwxr-xr-xarch/arm/plat-mxc/cpufreq.c20
-rwxr-xr-xarch/arm/plat-mxc/devices/Kconfig3
-rwxr-xr-xarch/arm/plat-mxc/devices/Makefile1
-rw-r--r--arch/arm/plat-mxc/devices/platform-dma.c8
-rw-r--r--arch/arm/plat-mxc/devices/platform-imx-fsl-csi.c55
-rw-r--r--arch/arm/plat-mxc/devices/platform-imx-uart.c12
-rwxr-xr-xarch/arm/plat-mxc/include/mach/devices-common.h12
-rwxr-xr-xarch/arm/plat-mxc/include/mach/iomux-mx6sl.h9
-rw-r--r--arch/arm/plat-mxc/include/mach/mx6.h17
-rwxr-xr-xarch/arm/plat-mxc/include/mach/mxc.h4
-rwxr-xr-xarch/arm/plat-mxc/usb_common.c37
-rw-r--r--drivers/dma/pxp/pxp_dma_v2.c5
-rw-r--r--drivers/media/video/mxc/capture/Kconfig2
-rw-r--r--drivers/media/video/mxc/capture/csi_v4l2_capture.c223
-rw-r--r--drivers/media/video/mxc/capture/fsl_csi.c58
-rw-r--r--drivers/media/video/mxc/capture/fsl_csi.h35
-rw-r--r--drivers/media/video/mxc/capture/mt9v111.c4
-rw-r--r--drivers/media/video/mxc/capture/mxc_v4l2_capture.h18
-rw-r--r--drivers/media/video/mxc/capture/ov2640.c4
-rw-r--r--drivers/media/video/mxc/capture/sensor_clock.c28
-rw-r--r--drivers/media/video/mxc/output/mxc_vout.c45
-rw-r--r--drivers/mfd/mxc-hdmi-core.c12
-rw-r--r--drivers/mmc/core/sdio.c6
-rw-r--r--drivers/mtd/nand/gpmi-nand/gpmi-nand.c35
-rw-r--r--drivers/mtd/nand/nand_base.c60
-rw-r--r--drivers/mxc/gpu-viv/arch/XAQ2/hal/kernel/gc_hal_kernel_hardware.c2
-rw-r--r--drivers/mxc/gpu-viv/hal/kernel/gc_hal_kernel_command.c21
-rw-r--r--drivers/mxc/gpu-viv/hal/os/linux/kernel/gc_hal_kernel_device.c9
-rw-r--r--drivers/mxc/gpu-viv/hal/os/linux/kernel/gc_hal_kernel_device.h3
-rw-r--r--drivers/mxc/gpu-viv/hal/os/linux/kernel/gc_hal_kernel_linux.h1
-rw-r--r--drivers/mxc/gpu-viv/hal/os/linux/kernel/gc_hal_kernel_os.c12
-rw-r--r--drivers/mxc/ipu3/ipu_device.c24
-rw-r--r--drivers/mxc/thermal/cooling.c3
-rw-r--r--drivers/mxc/vpu/mxc_vpu.c30
-rwxr-xr-xdrivers/net/fec.c14
-rwxr-xr-xdrivers/power/Kconfig1
-rwxr-xr-xdrivers/power/sabresd_battery.c178
-rwxr-xr-xdrivers/usb/gadget/arcotg_udc.c7
-rwxr-xr-xdrivers/usb/host/ehci-arc.c3
-rw-r--r--drivers/video/mxc/Kconfig6
-rw-r--r--drivers/video/mxc/Makefile7
-rw-r--r--drivers/video/mxc/mxc_elcdif_fb.c134
-rw-r--r--drivers/video/mxc/mxc_epdc_fb.c311
-rw-r--r--drivers/video/mxc/mxcfb_sii902x_elcdif.c560
-rw-r--r--include/linux/fsl_devices.h1
-rw-r--r--include/linux/mfd/mxc-hdmi-core.h1
-rw-r--r--include/linux/mtd/nand.h11
-rw-r--r--include/linux/mxcfb.h11
-rw-r--r--include/linux/power/sabresd_battery.h1
-rw-r--r--sound/soc/codecs/wm8962.c2
-rw-r--r--sound/soc/imx/imx-hdmi-dma.c2
-rw-r--r--sound/soc/imx/imx-spdif.c7
-rw-r--r--tools/perf/util/include/linux/compiler.h2
85 files changed, 3443 insertions, 697 deletions
diff --git a/arch/arm/configs/imx6_defconfig b/arch/arm/configs/imx6_defconfig
index f9a4eacce42b..173fcc874cd1 100644
--- a/arch/arm/configs/imx6_defconfig
+++ b/arch/arm/configs/imx6_defconfig
@@ -2305,7 +2305,7 @@ CONFIG_MXC_MLB150=m
#
# MXC Vivante GPU support
#
-CONFIG_MXC_GPU_VIV=m
+CONFIG_MXC_GPU_VIV=y
#
# ANATOP_THERMAL
diff --git a/arch/arm/configs/imx6s_defconfig b/arch/arm/configs/imx6s_defconfig
index f03e456d7386..ac7afdfdf5ff 100644
--- a/arch/arm/configs/imx6s_defconfig
+++ b/arch/arm/configs/imx6s_defconfig
@@ -294,6 +294,7 @@ CONFIG_IMX_HAVE_PLATFORM_IMX_MIPI_DSI=y
CONFIG_IMX_HAVE_PLATFORM_IMX_MIPI_CSI2=y
CONFIG_IMX_HAVE_PLATFORM_IMX_VDOA=y
CONFIG_IMX_HAVE_PLATFORM_IMX_PCIE=y
+CONFIG_IMX_HAVE_PLATFORM_IMX_FSL_CSI=y
#
# Freescale MXC Implementations
@@ -384,6 +385,7 @@ CONFIG_ARM_GIC=y
#
# Bus support
#
+CONFIG_ARM_AMBA=y
# CONFIG_PCI_SYSCALL is not set
# CONFIG_ARCH_SUPPORTS_MSI is not set
# CONFIG_PCCARD is not set
@@ -1104,6 +1106,7 @@ CONFIG_INPUT_ISL29023=y
#
CONFIG_SERIO=y
CONFIG_SERIO_SERPORT=y
+# CONFIG_SERIO_AMBAKMI is not set
CONFIG_SERIO_LIBPS2=y
# CONFIG_SERIO_RAW is not set
# CONFIG_SERIO_ALTERA_PS2 is not set
@@ -1135,6 +1138,8 @@ CONFIG_DEVKMEM=y
#
# Non-8250 serial port support
#
+# CONFIG_SERIAL_AMBA_PL010 is not set
+# CONFIG_SERIAL_AMBA_PL011 is not set
# CONFIG_SERIAL_MAX3100 is not set
# CONFIG_SERIAL_MAX3107 is not set
CONFIG_SERIAL_IMX=y
@@ -1208,6 +1213,7 @@ CONFIG_SPI_BITBANG=y
CONFIG_SPI_IMX_VER_2_3=y
CONFIG_SPI_IMX=y
# CONFIG_SPI_OC_TINY is not set
+# CONFIG_SPI_PL022 is not set
# CONFIG_SPI_PXA2XX_PCI is not set
# CONFIG_SPI_XILINX is not set
# CONFIG_SPI_DESIGNWARE is not set
@@ -1243,6 +1249,7 @@ CONFIG_GPIO_SYSFS=y
#
# CONFIG_GPIO_BASIC_MMIO is not set
# CONFIG_GPIO_IT8761E is not set
+# CONFIG_GPIO_PL061 is not set
#
# I2C GPIO expanders:
@@ -1287,7 +1294,8 @@ CONFIG_POWER_SUPPLY=y
# CONFIG_BATTERY_MAX17040 is not set
# CONFIG_BATTERY_MAX17042 is not set
# CONFIG_CHARGER_ISP1704 is not set
-CONFIG_CHARGER_MAX8903=y
+# CONFIG_CHARGER_MAX8903 is not set
+CONFIG_SABRESD_MAX8903=y
# CONFIG_CHARGER_GPIO is not set
CONFIG_HWMON=y
# CONFIG_HWMON_VID is not set
@@ -1393,6 +1401,7 @@ CONFIG_WATCHDOG_NOWAYOUT=y
# Watchdog Device Drivers
#
# CONFIG_SOFT_WATCHDOG is not set
+# CONFIG_ARM_SP805_WATCHDOG is not set
# CONFIG_MAX63XX_WATCHDOG is not set
CONFIG_IMX2_WDT=y
@@ -1595,10 +1604,23 @@ CONFIG_VIDEO_CAPTURE_DRIVERS=y
# CONFIG_VIDEO_THS7303 is not set
# CONFIG_VIDEO_M52790 is not set
# CONFIG_VIDEO_VIVI is not set
-# CONFIG_VIDEO_MXC_CAMERA is not set
+CONFIG_VIDEO_MXC_CAMERA=y
+
+#
+# MXC Camera/V4L2 PRP Features support
+#
+CONFIG_VIDEO_MXC_CSI_CAMERA=y
+# CONFIG_MXC_CAMERA_MICRON111 is not set
+# CONFIG_MXC_CAMERA_OV2640 is not set
+# CONFIG_MXC_CAMERA_OV3640 is not set
+CONFIG_MXC_CAMERA_OV5640=y
+# CONFIG_MXC_CAMERA_OV8820_MIPI is not set
+# CONFIG_MXC_CAMERA_OV5642 is not set
+# CONFIG_MXC_TVIN_ADV7180 is not set
+# CONFIG_MXC_CAMERA_OV5640_MIPI is not set
+CONFIG_MXC_CAMERA_SENSOR_CLK=y
CONFIG_VIDEO_MXC_OUTPUT=y
-CONFIG_VIDEO_MXC_IPU_OUTPUT=y
-# CONFIG_VIDEO_MXC_IPUV1_WVGA_OUTPUT is not set
+# CONFIG_VIDEO_MXC_PXP_V4L2 is not set
# CONFIG_VIDEO_MXC_OPL is not set
# CONFIG_VIDEO_CPIA2 is not set
# CONFIG_VIDEO_TIMBERDALE is not set
@@ -1694,6 +1716,7 @@ CONFIG_FB_MODE_HELPERS=y
#
# Frame buffer hardware drivers
#
+# CONFIG_FB_ARMCLCD is not set
# CONFIG_FB_UVESA is not set
# CONFIG_FB_S1D13XXX is not set
# CONFIG_FB_TMIO is not set
@@ -1717,20 +1740,18 @@ CONFIG_FB_MXC=y
CONFIG_FB_MXC_EDID=y
CONFIG_FB_MXC_SYNC_PANEL=y
# CONFIG_FB_MXC_EPSON_VGA_SYNC_PANEL is not set
-CONFIG_FB_MXC_LDB=y
-CONFIG_FB_MXC_MIPI_DSI=y
-CONFIG_FB_MXC_TRULY_WVGA_SYNC_PANEL=y
# CONFIG_FB_MXC_CLAA_WVGA_SYNC_PANEL is not set
-# CONFIG_FB_MXC_SEIKO_WVGA_SYNC_PANEL is not set
+CONFIG_FB_MXC_SEIKO_WVGA_SYNC_PANEL=y
# CONFIG_FB_MXC_SII902X is not set
+CONFIG_FB_MXC_SII902X_ELCDIF=y
# CONFIG_FB_MXC_CH7026 is not set
# CONFIG_FB_MXC_TVOUT_CH7024 is not set
# CONFIG_FB_MXC_ASYNC_PANEL is not set
CONFIG_FB_MXC_EINK_PANEL=y
# CONFIG_FB_MXC_EINK_AUTO_UPDATE_MODE is not set
# CONFIG_FB_MXC_SIPIX_PANEL is not set
-# CONFIG_FB_MXC_ELCDIF_FB is not set
-CONFIG_FB_MXC_HDMI=y
+CONFIG_FB_MXC_ELCDIF_FB=y
+# CONFIG_FB_MXC_HDMI is not set
#
# Console display driver support
@@ -1783,6 +1804,7 @@ CONFIG_SND_DRIVERS=y
# CONFIG_SND_SERIAL_U16550 is not set
# CONFIG_SND_MPU401 is not set
CONFIG_SND_ARM=y
+# CONFIG_SND_ARMAACI is not set
CONFIG_SND_SPI=y
CONFIG_SND_USB=y
CONFIG_SND_USB_AUDIO=y
@@ -1995,7 +2017,7 @@ CONFIG_USB_GADGET=y
CONFIG_USB_GADGET_VBUS_DRAW=2
CONFIG_USB_GADGET_SELECTED=y
CONFIG_USB_GADGET_ARC=y
-CONFIG_IMX_USB_CHARGER=y
+# CONFIG_IMX_USB_CHARGER is not set
CONFIG_USB_ARC=y
# CONFIG_USB_GADGET_FSL_USB2 is not set
# CONFIG_USB_GADGET_FUSB300 is not set
@@ -2050,6 +2072,7 @@ CONFIG_MMC_BLOCK_BOUNCE=y
#
# MMC/SD/SDIO Host Controller Drivers
#
+# CONFIG_MMC_ARMMMCI is not set
CONFIG_MMC_SDHCI=y
CONFIG_MMC_SDHCI_IO_ACCESSORS=y
CONFIG_MMC_SDHCI_PLTFM=y
@@ -2161,12 +2184,15 @@ CONFIG_RTC_DRV_SNVS=y
#
# on-CPU RTC drivers
#
+# CONFIG_RTC_DRV_PL030 is not set
+# CONFIG_RTC_DRV_PL031 is not set
CONFIG_DMADEVICES=y
# CONFIG_DMADEVICES_DEBUG is not set
#
# DMA Devices
#
+# CONFIG_AMBA_PL08X is not set
# CONFIG_DW_DMAC is not set
CONFIG_MXC_PXP_V2=y
CONFIG_MXC_PXP_CLIENT_DEVICE=y
@@ -2190,9 +2216,7 @@ CONFIG_CLKSRC_MMIO=y
#
# MXC support drivers
#
-CONFIG_MXC_IPU=y
-CONFIG_MXC_IPU_V3=y
-CONFIG_MXC_IPU_V3H=y
+# CONFIG_MXC_IPU is not set
#
# MXC SSI support
@@ -2234,6 +2258,7 @@ CONFIG_MXC_IPU_V3H=y
#
CONFIG_MXC_VPU=y
# CONFIG_MXC_VPU_DEBUG is not set
+# CONFIG_MX6_VPU_352M is not set
#
# MXC Asynchronous Sample Rate Converter support
@@ -2262,7 +2287,7 @@ CONFIG_MXC_MLB150=m
#
# MXC Vivante GPU support
#
-CONFIG_MXC_GPU_VIV=m
+CONFIG_MXC_GPU_VIV=y
#
# ANATOP_THERMAL
@@ -2507,7 +2532,7 @@ CONFIG_HAVE_ARCH_KGDB=y
# CONFIG_STRICT_DEVMEM is not set
CONFIG_ARM_UNWIND=y
# CONFIG_DEBUG_USER is not set
-# CONFIG_OC_ETM is not set
+CONFIG_OC_ETM=y
#
# Security options
diff --git a/arch/arm/configs/imx6s_updater_defconfig b/arch/arm/configs/imx6s_updater_defconfig
index 0bd3bcaac829..bd227b39c4e5 100644
--- a/arch/arm/configs/imx6s_updater_defconfig
+++ b/arch/arm/configs/imx6s_updater_defconfig
@@ -299,6 +299,7 @@ CONFIG_IMX_HAVE_PLATFORM_IMX_MIPI_DSI=y
CONFIG_IMX_HAVE_PLATFORM_IMX_MIPI_CSI2=y
CONFIG_IMX_HAVE_PLATFORM_IMX_VDOA=y
CONFIG_IMX_HAVE_PLATFORM_IMX_PCIE=y
+CONFIG_IMX_HAVE_PLATFORM_IMX_FSL_CSI=y
#
# Freescale MXC Implementations
@@ -388,6 +389,7 @@ CONFIG_ARM_GIC=y
#
# Bus support
#
+CONFIG_ARM_AMBA=y
# CONFIG_PCI_SYSCALL is not set
# CONFIG_ARCH_SUPPORTS_MSI is not set
# CONFIG_PCCARD is not set
@@ -1040,6 +1042,8 @@ CONFIG_DEVKMEM=y
#
# Non-8250 serial port support
#
+# CONFIG_SERIAL_AMBA_PL010 is not set
+# CONFIG_SERIAL_AMBA_PL011 is not set
# CONFIG_SERIAL_MAX3100 is not set
# CONFIG_SERIAL_MAX3107 is not set
CONFIG_SERIAL_IMX=y
@@ -1113,6 +1117,7 @@ CONFIG_SPI_BITBANG=y
CONFIG_SPI_IMX_VER_2_3=y
CONFIG_SPI_IMX=y
# CONFIG_SPI_OC_TINY is not set
+# CONFIG_SPI_PL022 is not set
# CONFIG_SPI_PXA2XX_PCI is not set
# CONFIG_SPI_XILINX is not set
# CONFIG_SPI_DESIGNWARE is not set
@@ -1148,6 +1153,7 @@ CONFIG_GPIOLIB=y
#
# CONFIG_GPIO_BASIC_MMIO is not set
# CONFIG_GPIO_IT8761E is not set
+# CONFIG_GPIO_PL061 is not set
#
# I2C GPIO expanders:
@@ -1192,6 +1198,7 @@ CONFIG_POWER_SUPPLY=y
# CONFIG_BATTERY_MAX17042 is not set
# CONFIG_CHARGER_ISP1704 is not set
# CONFIG_CHARGER_MAX8903 is not set
+# CONFIG_SABRESD_MAX8903 is not set
# CONFIG_CHARGER_GPIO is not set
# CONFIG_HWMON is not set
CONFIG_THERMAL=y
@@ -1202,6 +1209,7 @@ CONFIG_WATCHDOG_NOWAYOUT=y
# Watchdog Device Drivers
#
# CONFIG_SOFT_WATCHDOG is not set
+# CONFIG_ARM_SP805_WATCHDOG is not set
# CONFIG_MAX63XX_WATCHDOG is not set
CONFIG_IMX2_WDT=y
@@ -1405,8 +1413,6 @@ CONFIG_VIDEO_CAPTURE_DRIVERS=y
# CONFIG_VIDEO_VIVI is not set
# CONFIG_VIDEO_MXC_CAMERA is not set
CONFIG_VIDEO_MXC_OUTPUT=y
-CONFIG_VIDEO_MXC_IPU_OUTPUT=y
-# CONFIG_VIDEO_MXC_IPUV1_WVGA_OUTPUT is not set
# CONFIG_VIDEO_MXC_PXP_V4L2 is not set
# CONFIG_VIDEO_MXC_OPL is not set
# CONFIG_VIDEO_CPIA2 is not set
@@ -1447,6 +1453,7 @@ CONFIG_FB_MODE_HELPERS=y
#
# Frame buffer hardware drivers
#
+# CONFIG_FB_ARMCLCD is not set
# CONFIG_FB_UVESA is not set
# CONFIG_FB_S1D13XXX is not set
# CONFIG_FB_TMIO is not set
@@ -1464,18 +1471,17 @@ CONFIG_FB_MXC=y
CONFIG_FB_MXC_EDID=y
CONFIG_FB_MXC_SYNC_PANEL=y
# CONFIG_FB_MXC_EPSON_VGA_SYNC_PANEL is not set
-CONFIG_FB_MXC_LDB=y
-# CONFIG_FB_MXC_MIPI_DSI is not set
# CONFIG_FB_MXC_CLAA_WVGA_SYNC_PANEL is not set
# CONFIG_FB_MXC_SEIKO_WVGA_SYNC_PANEL is not set
# CONFIG_FB_MXC_SII902X is not set
+# CONFIG_FB_MXC_SII902X_ELCDIF is not set
# CONFIG_FB_MXC_CH7026 is not set
# CONFIG_FB_MXC_TVOUT_CH7024 is not set
# CONFIG_FB_MXC_ASYNC_PANEL is not set
# CONFIG_FB_MXC_EINK_PANEL is not set
# CONFIG_FB_MXC_SIPIX_PANEL is not set
# CONFIG_FB_MXC_ELCDIF_FB is not set
-CONFIG_FB_MXC_HDMI=y
+# CONFIG_FB_MXC_HDMI is not set
#
# Console display driver support
@@ -1526,6 +1532,7 @@ CONFIG_SND_DRIVERS=y
# CONFIG_SND_SERIAL_U16550 is not set
# CONFIG_SND_MPU401 is not set
CONFIG_SND_ARM=y
+# CONFIG_SND_ARMAACI is not set
CONFIG_SND_SPI=y
CONFIG_SND_USB=y
# CONFIG_SND_USB_AUDIO is not set
@@ -1774,6 +1781,7 @@ CONFIG_MMC_BLOCK_BOUNCE=y
#
# MMC/SD/SDIO Host Controller Drivers
#
+# CONFIG_MMC_ARMMMCI is not set
CONFIG_MMC_SDHCI=y
CONFIG_MMC_SDHCI_IO_ACCESSORS=y
CONFIG_MMC_SDHCI_PLTFM=y
@@ -1859,12 +1867,15 @@ CONFIG_RTC_DRV_SNVS=y
#
# on-CPU RTC drivers
#
+# CONFIG_RTC_DRV_PL030 is not set
+# CONFIG_RTC_DRV_PL031 is not set
CONFIG_DMADEVICES=y
# CONFIG_DMADEVICES_DEBUG is not set
#
# DMA Devices
#
+# CONFIG_AMBA_PL08X is not set
# CONFIG_DW_DMAC is not set
# CONFIG_MXC_PXP_V2 is not set
# CONFIG_TIMB_DMA is not set
@@ -1917,9 +1928,7 @@ CONFIG_CLKSRC_MMIO=y
#
# MXC support drivers
#
-CONFIG_MXC_IPU=y
-CONFIG_MXC_IPU_V3=y
-CONFIG_MXC_IPU_V3H=y
+# CONFIG_MXC_IPU is not set
#
# MXC SSI support
@@ -2234,7 +2243,7 @@ CONFIG_HAVE_ARCH_KGDB=y
# CONFIG_STRICT_DEVMEM is not set
CONFIG_ARM_UNWIND=y
# CONFIG_DEBUG_USER is not set
-# CONFIG_OC_ETM is not set
+CONFIG_OC_ETM=y
#
# Security options
diff --git a/arch/arm/include/asm/hardware/coresight.h b/arch/arm/include/asm/hardware/coresight.h
index 6643d6c4f35e..0b21c331bb04 100644
--- a/arch/arm/include/asm/hardware/coresight.h
+++ b/arch/arm/include/asm/hardware/coresight.h
@@ -18,10 +18,16 @@
#define TRACER_RUNNING_BIT 1
#define TRACER_CYCLE_ACC_BIT 2
#define TRACER_TRACE_DATA_BIT 3
+#define TRACER_TIMESTAMP_BIT 4
+#define TRACER_BRANCHOUTPUT_BIT 5
+#define TRACER_RETURN_STACK_BIT 6
#define TRACER_ACCESSED BIT(TRACER_ACCESSED_BIT)
#define TRACER_RUNNING BIT(TRACER_RUNNING_BIT)
#define TRACER_CYCLE_ACC BIT(TRACER_CYCLE_ACC_BIT)
#define TRACER_TRACE_DATA BIT(TRACER_TRACE_DATA_BIT)
+#define TRACER_TIMESTAMP BIT(TRACER_TIMESTAMP_BIT)
+#define TRACER_BRANCHOUTPUT BIT(TRACER_BRANCHOUTPUT_BIT)
+#define TRACER_RETURN_STACK BIT(TRACER_RETURN_STACK_BIT)
#define TRACER_TIMEOUT 10000
@@ -45,7 +51,7 @@
#define ETMCTRL_POWERDOWN 1
#define ETMCTRL_PROGRAM (1 << 10)
#define ETMCTRL_PORTSEL (1 << 11)
-#define ETMCTRL_DO_CONTEXTID (3 << 14)
+#define ETMCTRL_CONTEXTIDSIZE(x) (((x) & 3) << 14)
#define ETMCTRL_PORTMASK1 (7 << 4)
#define ETMCTRL_PORTMASK2 (1 << 21)
#define ETMCTRL_PORTMASK (ETMCTRL_PORTMASK1 | ETMCTRL_PORTMASK2)
@@ -57,9 +63,12 @@
#define ETMCTRL_DATA_DO_BOTH (ETMCTRL_DATA_DO_DATA | ETMCTRL_DATA_DO_ADDR)
#define ETMCTRL_BRANCH_OUTPUT (1 << 8)
#define ETMCTRL_CYCLEACCURATE (1 << 12)
+#define ETMCTRL_TIMESTAMP_EN (1 << 28)
+#define ETMCTRL_RETURN_STACK_EN (1 << 29)
/* ETM configuration code register */
#define ETMR_CONFCODE (0x04)
+#define ETMCCR_ETMIDR_PRESENT BIT(31)
/* ETM trace start/stop resource control register */
#define ETMR_TRACESSCTRL (0x18)
@@ -122,9 +131,18 @@
#define ETMR_VIEWDATACTRL3 0x3c
#define ETMVDC3_EXCLONLY BIT(16)
-#define ETMCTRL_OPTS (ETMCTRL_DO_CPRT | \
- ETMCTRL_BRANCH_OUTPUT | \
- ETMCTRL_DO_CONTEXTID)
+#define ETMCTRL_OPTS (ETMCTRL_DO_CPRT)
+
+#define ETMR_ID 0x1e4
+#define ETMIDR_VERSION(x) (((x) >> 4) & 0xff)
+#define ETMIDR_VERSION_3_1 0x21
+#define ETMIDR_VERSION_PFT_1_0 0x30
+
+#define ETMR_CCE 0x1e8
+#define ETMCCER_RETURN_STACK_IMPLEMENTED BIT(23)
+#define ETMCCER_TIMESTAMPING_IMPLEMENTED BIT(22)
+
+#define ETMR_TRACEIDR 0x200
#define ETMR_TRACEIDR 0x200
diff --git a/arch/arm/kernel/etm.c b/arch/arm/kernel/etm.c
index 496b8b84e455..93d06ba0fb60 100644
--- a/arch/arm/kernel/etm.c
+++ b/arch/arm/kernel/etm.c
@@ -42,6 +42,7 @@ struct tracectx {
unsigned long flags;
int ncmppairs;
int etm_portsz;
+ int etm_contextid_size;
u32 etb_fc;
unsigned long range_start;
unsigned long range_end;
@@ -108,13 +109,23 @@ static int trace_start_etm(struct tracectx *t, int id)
unsigned long timeout = TRACER_TIMEOUT;
v = ETMCTRL_OPTS | ETMCTRL_PROGRAM | ETMCTRL_PORTSIZE(t->etm_portsz);
+ v |= ETMCTRL_CONTEXTIDSIZE(t->etm_contextid_size);
if (t->flags & TRACER_CYCLE_ACC)
v |= ETMCTRL_CYCLEACCURATE;
+ if (t->flags & TRACER_BRANCHOUTPUT)
+ v |= ETMCTRL_BRANCH_OUTPUT;
+
if (t->flags & TRACER_TRACE_DATA)
v |= ETMCTRL_DATA_DO_ADDR;
+ if (t->flags & TRACER_TIMESTAMP)
+ v |= ETMCTRL_TIMESTAMP_EN;
+
+ if (t->flags & TRACER_RETURN_STACK)
+ v |= ETMCTRL_RETURN_STACK_EN;
+
etm_unlock(t, id);
etm_writel(t, id, v, ETMR_CTRL);
@@ -199,15 +210,36 @@ static int trace_stop_etm(struct tracectx *t, int id)
etm_unlock(t, id);
- etm_writel(t, id, 0x441, ETMR_CTRL);
+ etm_writel(t, id, 0x440, ETMR_CTRL);
while (!(etm_readl(t, id, ETMR_CTRL) & ETMCTRL_PROGRAM) && --timeout)
;
if (!timeout) {
- dev_dbg(t->dev, "Waiting for progbit to assert timed out\n");
+ dev_err(t->dev,
+ "etm%d: Waiting for progbit to assert timed out\n",
+ id);
+ etm_lock(t, id);
+ return -EFAULT;
+ }
+
+ etm_lock(t, id);
+ return 0;
+}
+
+static int trace_power_down_etm(struct tracectx *t, int id)
+{
+ unsigned long timeout = TRACER_TIMEOUT;
+ etm_unlock(t, id);
+ while (!(etm_readl(t, id, ETMR_STATUS) & ETMST_PROGBIT) && --timeout)
+ ;
+ if (!timeout) {
+ dev_err(t->dev, "etm%d: Waiting for status progbit to assert timed out\n",
+ id);
etm_lock(t, id);
return -EFAULT;
}
+ etm_writel(t, id, 0x441, ETMR_CTRL);
+
etm_lock(t, id);
return 0;
}
@@ -215,15 +247,14 @@ static int trace_stop_etm(struct tracectx *t, int id)
static int trace_stop(struct tracectx *t)
{
int id;
- int ret;
unsigned long timeout = TRACER_TIMEOUT;
u32 etb_fc = t->etb_fc;
- for (id = 0; id < t->etm_regs_count; id++) {
- ret = trace_stop_etm(t, id);
- if (ret)
- return ret;
- }
+ for (id = 0; id < t->etm_regs_count; id++)
+ trace_stop_etm(t, id);
+
+ for (id = 0; id < t->etm_regs_count; id++)
+ trace_power_down_etm(t, id);
etb_unlock(t);
if (etb_fc) {
@@ -626,6 +657,133 @@ static ssize_t trace_mode_store(struct kobject *kobj,
static struct kobj_attribute trace_mode_attr =
__ATTR(trace_mode, 0644, trace_mode_show, trace_mode_store);
+static ssize_t trace_contextid_size_show(struct kobject *kobj,
+ struct kobj_attribute *attr,
+ char *buf)
+{
+ /* 0: No context id tracing, 1: One byte, 2: Two bytes, 3: Four bytes */
+ return sprintf(buf, "%d\n", (1 << tracer.etm_contextid_size) >> 1);
+}
+
+static ssize_t trace_contextid_size_store(struct kobject *kobj,
+ struct kobj_attribute *attr,
+ const char *buf, size_t n)
+{
+ unsigned int contextid_size;
+
+ if (sscanf(buf, "%u", &contextid_size) != 1)
+ return -EINVAL;
+
+ if (contextid_size == 3 || contextid_size > 4)
+ return -EINVAL;
+
+ mutex_lock(&tracer.mutex);
+ tracer.etm_contextid_size = fls(contextid_size);
+ mutex_unlock(&tracer.mutex);
+
+ return n;
+}
+
+static struct kobj_attribute trace_contextid_size_attr =
+ __ATTR(trace_contextid_size, 0644,
+ trace_contextid_size_show, trace_contextid_size_store);
+
+static ssize_t trace_branch_output_show(struct kobject *kobj,
+ struct kobj_attribute *attr,
+ char *buf)
+{
+ return sprintf(buf, "%d\n", !!(tracer.flags & TRACER_BRANCHOUTPUT));
+}
+
+static ssize_t trace_branch_output_store(struct kobject *kobj,
+ struct kobj_attribute *attr,
+ const char *buf, size_t n)
+{
+ unsigned int branch_output;
+
+ if (sscanf(buf, "%u", &branch_output) != 1)
+ return -EINVAL;
+
+ mutex_lock(&tracer.mutex);
+ if (branch_output) {
+ tracer.flags |= TRACER_BRANCHOUTPUT;
+ /* Branch broadcasting is incompatible with the return stack */
+ tracer.flags &= ~TRACER_RETURN_STACK;
+ } else {
+ tracer.flags &= ~TRACER_BRANCHOUTPUT;
+ }
+ mutex_unlock(&tracer.mutex);
+
+ return n;
+}
+
+static struct kobj_attribute trace_branch_output_attr =
+ __ATTR(trace_branch_output, 0644,
+ trace_branch_output_show, trace_branch_output_store);
+
+static ssize_t trace_return_stack_show(struct kobject *kobj,
+ struct kobj_attribute *attr,
+ char *buf)
+{
+ return sprintf(buf, "%d\n", !!(tracer.flags & TRACER_RETURN_STACK));
+}
+
+static ssize_t trace_return_stack_store(struct kobject *kobj,
+ struct kobj_attribute *attr,
+ const char *buf, size_t n)
+{
+ unsigned int return_stack;
+
+ if (sscanf(buf, "%u", &return_stack) != 1)
+ return -EINVAL;
+
+ mutex_lock(&tracer.mutex);
+ if (return_stack) {
+ tracer.flags |= TRACER_RETURN_STACK;
+ /* Return stack is incompatible with branch broadcasting */
+ tracer.flags &= ~TRACER_BRANCHOUTPUT;
+ } else {
+ tracer.flags &= ~TRACER_RETURN_STACK;
+ }
+ mutex_unlock(&tracer.mutex);
+
+ return n;
+}
+
+static struct kobj_attribute trace_return_stack_attr =
+ __ATTR(trace_return_stack, 0644,
+ trace_return_stack_show, trace_return_stack_store);
+
+static ssize_t trace_timestamp_show(struct kobject *kobj,
+ struct kobj_attribute *attr,
+ char *buf)
+{
+ return sprintf(buf, "%d\n", !!(tracer.flags & TRACER_TIMESTAMP));
+}
+
+static ssize_t trace_timestamp_store(struct kobject *kobj,
+ struct kobj_attribute *attr,
+ const char *buf, size_t n)
+{
+ unsigned int timestamp;
+
+ if (sscanf(buf, "%u", &timestamp) != 1)
+ return -EINVAL;
+
+ mutex_lock(&tracer.mutex);
+ if (timestamp)
+ tracer.flags |= TRACER_TIMESTAMP;
+ else
+ tracer.flags &= ~TRACER_TIMESTAMP;
+ mutex_unlock(&tracer.mutex);
+
+ return n;
+}
+
+static struct kobj_attribute trace_timestamp_attr =
+ __ATTR(trace_timestamp, 0644,
+ trace_timestamp_show, trace_timestamp_store);
+
static ssize_t trace_range_show(struct kobject *kobj,
struct kobj_attribute *attr,
char *buf)
@@ -703,6 +861,10 @@ static int __devinit etm_probe(struct amba_device *dev, const struct amba_id *id
int ret = 0;
void __iomem **new_regs;
int new_count;
+ u32 etmccr;
+ u32 etmidr;
+ u32 etmccer = 0;
+ u8 etm_version = 0;
mutex_lock(&t->mutex);
new_count = t->etm_regs_count + 1;
@@ -729,15 +891,23 @@ static int __devinit etm_probe(struct amba_device *dev, const struct amba_id *id
amba_set_drvdata(dev, t->etm_regs[t->etm_regs_count]);
- t->flags = TRACER_CYCLE_ACC | TRACER_TRACE_DATA;
+ t->flags = TRACER_CYCLE_ACC | TRACER_TRACE_DATA | TRACER_BRANCHOUTPUT;
t->etm_portsz = 1;
+ t->etm_contextid_size = 3;
etm_unlock(t, t->etm_regs_count);
(void)etm_readl(t, t->etm_regs_count, ETMMR_PDSR);
/* dummy first read */
(void)etm_readl(&tracer, t->etm_regs_count, ETMMR_OSSRR);
- t->ncmppairs = etm_readl(t, t->etm_regs_count, ETMR_CONFCODE) & 0xf;
+ etmccr = etm_readl(t, t->etm_regs_count, ETMR_CONFCODE);
+ t->ncmppairs = etmccr & 0xf;
+ if (etmccr & ETMCCR_ETMIDR_PRESENT) {
+ etmidr = etm_readl(t, t->etm_regs_count, ETMR_ID);
+ etm_version = ETMIDR_VERSION(etmidr);
+ if (etm_version >= ETMIDR_VERSION_3_1)
+ etmccer = etm_readl(t, t->etm_regs_count, ETMR_CCE);
+ }
etm_writel(t, t->etm_regs_count, 0x441, ETMR_CTRL);
etm_writel(t, t->etm_regs_count, new_count, ETMR_TRACEIDR);
etm_lock(t, t->etm_regs_count);
@@ -756,14 +926,47 @@ static int __devinit etm_probe(struct amba_device *dev, const struct amba_id *id
if (ret)
dev_dbg(&dev->dev, "Failed to create trace_mode in sysfs\n");
- ret = sysfs_create_file(&dev->dev.kobj, &trace_range_attr.attr);
+ ret = sysfs_create_file(&dev->dev.kobj,
+ &trace_contextid_size_attr.attr);
if (ret)
- dev_dbg(&dev->dev, "Failed to create trace_range in sysfs\n");
+ dev_dbg(&dev->dev,
+ "Failed to create trace_contextid_size in sysfs\n");
- ret = sysfs_create_file(&dev->dev.kobj, &trace_data_range_attr.attr);
+ ret = sysfs_create_file(&dev->dev.kobj,
+ &trace_branch_output_attr.attr);
if (ret)
dev_dbg(&dev->dev,
- "Failed to create trace_data_range in sysfs\n");
+ "Failed to create trace_branch_output in sysfs\n");
+
+ if (etmccer & ETMCCER_RETURN_STACK_IMPLEMENTED) {
+ ret = sysfs_create_file(&dev->dev.kobj,
+ &trace_return_stack_attr.attr);
+ if (ret)
+ dev_dbg(&dev->dev,
+ "Failed to create trace_return_stack in sysfs\n");
+ }
+
+ if (etmccer & ETMCCER_TIMESTAMPING_IMPLEMENTED) {
+ ret = sysfs_create_file(&dev->dev.kobj,
+ &trace_timestamp_attr.attr);
+ if (ret)
+ dev_dbg(&dev->dev,
+ "Failed to create trace_timestamp in sysfs\n");
+ }
+
+ ret = sysfs_create_file(&dev->dev.kobj, &trace_range_attr.attr);
+ if (ret)
+ dev_dbg(&dev->dev, "Failed to create trace_range in sysfs\n");
+
+ if (etm_version < ETMIDR_VERSION_PFT_1_0) {
+ ret = sysfs_create_file(&dev->dev.kobj,
+ &trace_data_range_attr.attr);
+ if (ret)
+ dev_dbg(&dev->dev,
+ "Failed to create trace_data_range in sysfs\n");
+ } else {
+ tracer.flags &= ~TRACER_TRACE_DATA;
+ }
dev_dbg(&dev->dev, "ETM AMBA driver initialized.\n");
diff --git a/arch/arm/mach-mx5/devices-imx50.h b/arch/arm/mach-mx5/devices-imx50.h
index bdaf32213c21..8cba79c489ec 100755
--- a/arch/arm/mach-mx5/devices-imx50.h
+++ b/arch/arm/mach-mx5/devices-imx50.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2010-2011 Freescale Semiconductor, Inc. All Rights Reserved.
+ * Copyright (C) 2010-2012 Freescale Semiconductor, Inc. All Rights Reserved.
*/
/*
@@ -29,8 +29,8 @@ extern const struct imx_srtc_data imx50_imx_srtc_data __initconst;
#define imx50_add_srtc() \
imx_add_srtc(&imx50_imx_srtc_data)
-extern const struct imx_dma_data imx50_dma_data __initconst;
-#define imx50_add_dma() imx_add_dma(&imx50_dma_data);
+extern const struct imx_dma_res_data imx50_dma_res_data __initconst;
+#define imx50_add_dma() imx_add_dma(&imx50_dma_res_data);
extern const struct imx_fec_data imx50_fec_data;
#define imx50_add_fec(pdata) \
diff --git a/arch/arm/mach-mx6/Kconfig b/arch/arm/mach-mx6/Kconfig
index d50f1a795a09..97262dced063 100644
--- a/arch/arm/mach-mx6/Kconfig
+++ b/arch/arm/mach-mx6/Kconfig
@@ -7,6 +7,7 @@ config ARCH_MX6Q
select ARCH_MXC_AUDMUX_V2
select ARM_GIC
select ARCH_HAS_CPUFREQ
+ select OC_ETM
select IMX_HAVE_PLATFORM_IMX_UART
select IMX_HAVE_PLATFORM_FEC
select IMX_HAVE_PLATFORM_IMX_ANATOP_THERMAL
@@ -136,6 +137,7 @@ config MACH_MX6SL_EVK
select IMX_HAVE_PLATFORM_IMX_EPDC
select IMX_HAVE_PLATFORM_IMX_SPDC
select IMX_HAVE_PLATFORM_IMX_PXP
+ select IMX_HAVE_PLATFORM_IMX_FSL_CSI
select IMX_HAVE_PLATFORM_IMX_KEYPAD
select IMX_HAVE_PLATFORM_IMX_DCP
select IMX_HAVE_PLATFORM_RANDOM_RNGC
diff --git a/arch/arm/mach-mx6/Makefile b/arch/arm/mach-mx6/Makefile
index 49b5f86a6920..05dc62dac468 100644
--- a/arch/arm/mach-mx6/Makefile
+++ b/arch/arm/mach-mx6/Makefile
@@ -5,7 +5,7 @@
# Object file lists.
obj-y := cpu.o mm.o system.o devices.o dummy_gpio.o irq.o bus_freq.o usb_dr.o usb_h2.o usb_h3.o\
pm.o cpu_op-mx6.o mx6_wfi.o mx6_fec.o mx6_anatop_regulator.o cpu_regulator-mx6.o \
-mx6_mmdc.o mx6_ddr_freq.o mx6sl_ddr.o mx6sl_wfi.o
+mx6_mmdc.o mx6_ddr_freq.o mx6sl_ddr.o mx6sl_wfi.o etm.o
obj-$(CONFIG_ARCH_MX6) += clock.o mx6_suspend.o clock_mx6sl.o
obj-$(CONFIG_MACH_MX6Q_ARM2) += board-mx6q_arm2.o
diff --git a/arch/arm/mach-mx6/board-mx6q_sabreauto.c b/arch/arm/mach-mx6/board-mx6q_sabreauto.c
index 61d595cddb79..a15daef0c4bb 100644
--- a/arch/arm/mach-mx6/board-mx6q_sabreauto.c
+++ b/arch/arm/mach-mx6/board-mx6q_sabreauto.c
@@ -103,7 +103,6 @@
#define SABREAUTO_DISP0_PWR IMX_GPIO_NR(3, 24)
#define SABREAUTO_DISP0_I2C_EN IMX_GPIO_NR(3, 28)
#define SABREAUTO_DISP0_DET_INT IMX_GPIO_NR(3, 31)
-#define SABREAUTO_CSI0_RST IMX_GPIO_NR(4, 5)
#define SABREAUTO_DISP0_RESET IMX_GPIO_NR(5, 0)
#define SABREAUTO_I2C3_STEER IMX_GPIO_NR(5, 4)
#define SABREAUTO_WEIM_NOR_WDOG1 IMX_GPIO_NR(4, 29)
@@ -111,7 +110,6 @@
#define SABREAUTO_PMIC_INT IMX_GPIO_NR(5, 16)
#define SABREAUTO_ALS_INT IMX_GPIO_NR(5, 17)
#define SABREAUTO_SD1_WP IMX_GPIO_NR(5, 20)
-#define SABREAUTO_CSI0_PWN IMX_GPIO_NR(5, 23)
#define SABREAUTO_USB_HOST1_OC IMX_GPIO_NR(5, 0)
#define SABREAUTO_SD3_CD IMX_GPIO_NR(6, 15)
@@ -603,18 +601,6 @@ static struct pca953x_platform_data max7310_u43_platdata = {
.setup = max7310_u43_setup,
};
-static struct fsl_mxc_camera_platform_data camera_data = {
- .analog_regulator = "DA9052_LDO7",
- .core_regulator = "DA9052_LDO9",
- .mclk = 24000000,
- .csi = 0,
-};
-
-static struct fsl_mxc_camera_platform_data ov5640_mipi_data = {
- .mclk = 24000000,
- .csi = 0,
-};
-
static void adv7180_pwdn(int pwdn)
{
int status = -1;
@@ -672,10 +658,6 @@ static struct i2c_board_info mxc_i2c2_board_info[] __initdata = {
I2C_BOARD_INFO("adv7180", 0x21),
.platform_data = (void *)&adv7180_data,
}, {
- I2C_BOARD_INFO("ov3640", 0x3c),
- .platform_data = (void *)&camera_data,
- },
- {
I2C_BOARD_INFO("isl29023", 0x44),
.irq = gpio_to_irq(SABREAUTO_ALS_INT),
.platform_data = &ls_data,
@@ -693,17 +675,13 @@ static struct i2c_board_info mxc_i2c1_board_info[] __initdata = {
}, {
I2C_BOARD_INFO("mxc_hdmi_i2c", 0x50),
}, {
- I2C_BOARD_INFO("ov5640_mipi", 0x3c),
- .platform_data = (void *)&ov5640_mipi_data,
- }, {
I2C_BOARD_INFO("cs42888", 0x48),
.platform_data = (void *)&cs42888_data,
- },
- {
+ }, {
I2C_BOARD_INFO("si4763_i2c", 0x63),
},
-
};
+
struct platform_device mxc_si4763_audio_device = {
.name = "imx-tuner-si4763",
.id = 0,
@@ -1316,16 +1294,6 @@ early_param("can0", early_enable_can0);
static inline void __init mx6q_csi0_io_init(void)
{
- /* Camera reset */
- gpio_request(SABREAUTO_CSI0_RST, "cam-reset");
- gpio_direction_output(SABREAUTO_CSI0_RST, 1);
-
- /* Camera power down */
- gpio_request(SABREAUTO_CSI0_PWN, "cam-pwdn");
- gpio_direction_output(SABREAUTO_CSI0_PWN, 1);
- msleep(1);
- gpio_set_value(SABREAUTO_CSI0_PWN, 0);
-
if (cpu_is_mx6q())
mxc_iomux_set_gpr_register(1, 19, 1, 1);
else if (cpu_is_mx6dl())
diff --git a/arch/arm/mach-mx6/board-mx6q_sabreauto.h b/arch/arm/mach-mx6/board-mx6q_sabreauto.h
index c087de6fb789..9b5af3c2a68c 100644
--- a/arch/arm/mach-mx6/board-mx6q_sabreauto.h
+++ b/arch/arm/mach-mx6/board-mx6q_sabreauto.h
@@ -207,10 +207,6 @@ static iomux_v3_cfg_t mx6q_sabreauto_pads[] = {
/* HDMI */
MX6Q_PAD_EIM_A25__HDMI_TX_CEC_LINE,
- /* camera reset */
- MX6Q_PAD_GPIO_19__GPIO_4_5,
- MX6Q_PAD_EIM_D24__GPIO_3_24,
-
/* MLB150 */
MX6Q_PAD_ENET_TXD1__MLB_MLBCLK,
MX6Q_PAD_GPIO_6__MLB_MLBSIG,
diff --git a/arch/arm/mach-mx6/board-mx6sl_arm2.c b/arch/arm/mach-mx6/board-mx6sl_arm2.c
index 419b2447e215..2959d0de6263 100755
--- a/arch/arm/mach-mx6/board-mx6sl_arm2.c
+++ b/arch/arm/mach-mx6/board-mx6sl_arm2.c
@@ -610,7 +610,7 @@ static struct mxc_dvfs_platform_data mx6sl_arm2_dvfscore_data = {
};
static struct viv_gpu_platform_data imx6q_gpu_pdata __initdata = {
- .reserved_mem_size = SZ_128M,
+ .reserved_mem_size = SZ_32M,
};
void __init early_console_setup(unsigned long base, struct clk *clk);
diff --git a/arch/arm/mach-mx6/board-mx6sl_common.h b/arch/arm/mach-mx6/board-mx6sl_common.h
index d005e02cb6ac..4a04cbea0694 100644
--- a/arch/arm/mach-mx6/board-mx6sl_common.h
+++ b/arch/arm/mach-mx6/board-mx6sl_common.h
@@ -20,6 +20,8 @@
#define _BOARD_MX6SL_COMMON_H
#include <mach/iomux-mx6sl.h>
+#define MX6_BRD_LCD_RESET IMX_GPIO_NR(2, 19) /* LCD_REST */
+
#define MX6_BRD_USBOTG1_PWR IMX_GPIO_NR(4, 0) /* KEY_COL4 */
#define MX6_BRD_USBOTG2_PWR IMX_GPIO_NR(4, 2) /* KEY_COL5 */
#define MX6_BRD_LCD_PWR_EN IMX_GPIO_NR(4, 3) /* KEY_ROW5 */
@@ -31,6 +33,10 @@
#define MX6_BRD_SD2_CD IMX_GPIO_NR(5, 0) /* SD2_DAT7 */
#define MX6_BRD_SD3_CD IMX_GPIO_NR(3, 22) /* REF_CLK_32K */
#define MX6_BRD_FEC_PWR_EN IMX_GPIO_NR(4, 21) /* FEC_TX_CLK */
+#define MX6_BRD_CHG_FLT IMX_GPIO_NR(4, 14) /* ECSPI2_MISO */
+#define MX6_BRD_CHG_UOK IMX_GPIO_NR(4, 13) /* ECSPI2_MOSI */
+#define MX6_BRD_CHG_DOK IMX_GPIO_NR(4, 13) /* ECSPI2_MOSI */
+#define MX6_BRD_CHG_STATUS IMX_GPIO_NR(4, 15) /* ECSPI2_SS0 */
/* EPDC GPIO pins */
#define MX6SL_BRD_EPDC_SDDO_0 IMX_GPIO_NR(1, 7)
@@ -76,6 +82,9 @@
#define MX6SL_BRD_ELAN_CE IMX_GPIO_NR(2, 9)
#define MX6SL_BRD_ELAN_INT IMX_GPIO_NR(2, 10)
#define MX6SL_BRD_ELAN_RST IMX_GPIO_NR(4, 4)
+/* CSI */
+#define MX6SL_BRD_CSI_PWDN IMX_GPIO_NR(1, 25)
+#define MX6SL_BRD_CSI_RST IMX_GPIO_NR(1, 26)
static iomux_v3_cfg_t mx6sl_brd_pads[] = {
@@ -89,6 +98,9 @@ static iomux_v3_cfg_t mx6sl_brd_pads[] = {
/* Audio Codec */
MX6SL_PAD_FEC_RX_ER__GPIO_4_19, /* HEADPHONE_DET */
+ /* SPDIF TX */
+ MX6SL_PAD_SD2_DAT4__SPDIF_OUT1,
+
/* UART1 */
MX6SL_PAD_UART1_RXD__UART1_RXD,
MX6SL_PAD_UART1_TXD__UART1_TXD,
@@ -213,6 +225,11 @@ static iomux_v3_cfg_t mx6sl_brd_pads[] = {
/* WDOG */
MX6SL_PAD_WDOG_B__WDOG1_WDOG_B,
+
+ /* Charge */
+ MX6SL_PAD_ECSPI2_MISO__GPIO_4_14, /* CHG_FLT */
+ MX6SL_PAD_ECSPI2_SS0__GPIO_4_15, /* CHG_STATUS */
+ MX6SL_PAD_ECSPI2_MOSI__GPIO_4_13, /* CHG_UOK ,CHG_DOK*/
};
static iomux_v3_cfg_t mx6sl_brd_epdc_enable_pads[] = {
@@ -372,11 +389,40 @@ static iomux_v3_cfg_t mx6sl_brd_spdc_disable_pads[] = {
MX6SL_PAD_EPDC_PWRWAKEUP__GPIO_2_14,
};
+static iomux_v3_cfg_t mx6sl_brd_csi_enable_pads[] = {
+ MX6SL_PAD_EPDC_GDRL__CSI_MCLK,
+ MX6SL_PAD_EPDC_SDCE3__I2C3_SDA,
+ MX6SL_PAD_EPDC_SDCE2__I2C3_SCL,
+ MX6SL_PAD_EPDC_GDCLK__CSI_PIXCLK,
+ MX6SL_PAD_EPDC_GDSP__CSI_VSYNC,
+ MX6SL_PAD_EPDC_GDOE__CSI_HSYNC,
+ MX6SL_PAD_EPDC_SDLE__CSI_D_9,
+ MX6SL_PAD_EPDC_SDCLK__CSI_D_8,
+ MX6SL_PAD_EPDC_D7__CSI_D_7,
+ MX6SL_PAD_EPDC_D6__CSI_D_6,
+ MX6SL_PAD_EPDC_D5__CSI_D_5,
+ MX6SL_PAD_EPDC_D4__CSI_D_4,
+ MX6SL_PAD_EPDC_D3__CSI_D_3,
+ MX6SL_PAD_EPDC_D2__CSI_D_2,
+ MX6SL_PAD_EPDC_D1__CSI_D_1,
+ MX6SL_PAD_EPDC_D0__CSI_D_0,
+
+ MX6SL_PAD_EPDC_SDSHR__GPIO_1_26, /* CMOS_RESET_B GPIO */
+ MX6SL_PAD_EPDC_SDOE__GPIO_1_25, /* CMOS_PWDN GPIO */
+};
+
static iomux_v3_cfg_t mx6sl_brd_elan_pads[] = {
MX6SL_PAD_EPDC_PWRCTRL3__GPIO_2_10, /* INT */
MX6SL_PAD_EPDC_PWRCTRL2__GPIO_2_9, /* CE */
MX6SL_PAD_KEY_COL6__GPIO_4_4, /* RST */
};
+ /* uart2 pins */
+static iomux_v3_cfg_t mx6sl_uart2_pads[] = {
+ MX6SL_PAD_SD2_DAT5__UART2_TXD,
+ MX6SL_PAD_SD2_DAT4__UART2_RXD,
+ MX6SL_PAD_SD2_DAT6__UART2_RTS,
+ MX6SL_PAD_SD2_DAT7__UART2_CTS,
+};
#define MX6SL_USDHC_8BIT_PAD_SETTING(id, speed) \
mx6sl_sd##id##_##speed##mhz[] = { \
diff --git a/arch/arm/mach-mx6/board-mx6sl_evk.c b/arch/arm/mach-mx6/board-mx6sl_evk.c
index 81654a0c99fd..e656638c31d6 100644
--- a/arch/arm/mach-mx6/board-mx6sl_evk.c
+++ b/arch/arm/mach-mx6/board-mx6sl_evk.c
@@ -52,6 +52,7 @@
#include <linux/mfd/max17135.h>
#include <sound/wm8962.h>
#include <sound/pcm.h>
+#include <linux/power/sabresd_battery.h>
#include <mach/common.h>
#include <mach/hardware.h>
@@ -83,12 +84,21 @@ extern char *soc_reg_id;
extern char *pu_reg_id;
extern int __init mx6sl_evk_init_pfuze100(u32 int_gpio);
+static int csi_enabled;
+
enum sd_pad_mode {
SD_PAD_MODE_LOW_SPEED,
SD_PAD_MODE_MED_SPEED,
SD_PAD_MODE_HIGH_SPEED,
};
+static int __init csi_setup(char *__unused)
+{
+ csi_enabled = 1;
+ return 1;
+}
+__setup("csi", csi_setup);
+
static int plt_sd_pad_change(unsigned int index, int clock)
{
/* LOW speed is the default state of SD pads */
@@ -556,6 +566,115 @@ static int __init imx6q_init_audio(void)
return 0;
}
+static int spdif_clk_set_rate(struct clk *clk, unsigned long rate)
+{
+ unsigned long rate_actual;
+ rate_actual = clk_round_rate(clk, rate);
+ clk_set_rate(clk, rate_actual);
+ return 0;
+}
+
+static struct mxc_spdif_platform_data mxc_spdif_data = {
+ .spdif_tx = 1,
+ .spdif_rx = 0,
+ .spdif_clk_44100 = 1,
+ .spdif_clk_48000 = -1,
+ .spdif_div_44100 = 23,
+ .spdif_clk_set_rate = spdif_clk_set_rate,
+ .spdif_clk = NULL,
+};
+
+int hdmi_enabled;
+static int __init hdmi_setup(char *__unused)
+{
+ hdmi_enabled = 1;
+ return 1;
+}
+__setup("hdmi", hdmi_setup);
+
+static iomux_v3_cfg_t mx6sl_sii902x_hdmi_pads_enabled[] = {
+ MX6SL_PAD_LCD_RESET__GPIO_2_19,
+ MX6SL_PAD_EPDC_PWRCTRL3__GPIO_2_10,
+};
+
+static int sii902x_get_pins(void)
+{
+ /* Sii902x HDMI controller */
+ mxc_iomux_v3_setup_multiple_pads(mx6sl_sii902x_hdmi_pads_enabled, \
+ ARRAY_SIZE(mx6sl_sii902x_hdmi_pads_enabled));
+
+ /* Reset Pin */
+ gpio_request(MX6_BRD_LCD_RESET, "disp0-reset");
+ gpio_direction_output(MX6_BRD_LCD_RESET, 1);
+
+ /* Interrupter pin GPIO */
+ gpio_request(MX6SL_BRD_EPDC_PWRCTRL3, "disp0-detect");
+ gpio_direction_input(MX6SL_BRD_EPDC_PWRCTRL3);
+ return 1;
+}
+
+static void sii902x_put_pins(void)
+{
+ gpio_free(MX6_BRD_LCD_RESET);
+ gpio_free(MX6SL_BRD_EPDC_PWRCTRL3);
+}
+
+static void sii902x_hdmi_reset(void)
+{
+ gpio_set_value(MX6_BRD_LCD_RESET, 0);
+ msleep(10);
+ gpio_set_value(MX6_BRD_LCD_RESET, 1);
+ msleep(10);
+}
+
+static struct fsl_mxc_lcd_platform_data sii902x_hdmi_data = {
+ .ipu_id = 0,
+ .disp_id = 0,
+ .reset = sii902x_hdmi_reset,
+ .get_pins = sii902x_get_pins,
+ .put_pins = sii902x_put_pins,
+};
+
+static void mx6sl_csi_io_init(void)
+{
+ mxc_iomux_v3_setup_multiple_pads(mx6sl_brd_csi_enable_pads, \
+ ARRAY_SIZE(mx6sl_brd_csi_enable_pads));
+
+ /* Camera reset */
+ gpio_request(MX6SL_BRD_CSI_RST, "cam-reset");
+ gpio_direction_output(MX6SL_BRD_CSI_RST, 1);
+
+ /* Camera power down */
+ gpio_request(MX6SL_BRD_CSI_PWDN, "cam-pwdn");
+ gpio_direction_output(MX6SL_BRD_CSI_PWDN, 1);
+ msleep(5);
+ gpio_set_value(MX6SL_BRD_CSI_PWDN, 0);
+ msleep(5);
+ gpio_set_value(MX6SL_BRD_CSI_RST, 0);
+ msleep(1);
+ gpio_set_value(MX6SL_BRD_CSI_RST, 1);
+ msleep(5);
+ gpio_set_value(MX6SL_BRD_CSI_PWDN, 1);
+}
+
+static void mx6sl_csi_cam_powerdown(int powerdown)
+{
+ if (powerdown)
+ gpio_set_value(MX6SL_BRD_CSI_PWDN, 1);
+ else
+ gpio_set_value(MX6SL_BRD_CSI_PWDN, 0);
+
+ msleep(2);
+}
+
+static struct fsl_mxc_camera_platform_data camera_data = {
+ .mclk = 24000000,
+ .io_init = mx6sl_csi_io_init,
+ .pwdn = mx6sl_csi_cam_powerdown,
+ .core_regulator = "VGEN2_1V5",
+ .analog_regulator = "VGEN6_2V8",
+};
+
static struct imxi2c_platform_data mx6_evk_i2c0_data = {
.bitrate = 100000,
};
@@ -565,7 +684,7 @@ static struct imxi2c_platform_data mx6_evk_i2c1_data = {
};
static struct imxi2c_platform_data mx6_evk_i2c2_data = {
- .bitrate = 400000,
+ .bitrate = 100000,
};
static struct i2c_board_info mxc_i2c0_board_info[] __initdata = {
@@ -585,10 +704,17 @@ static struct i2c_board_info mxc_i2c1_board_info[] __initdata = {
I2C_BOARD_INFO("wm8962", 0x1a),
.platform_data = &wm8962_config_data,
},
+ {
+ I2C_BOARD_INFO("sii902x", 0),
+ .platform_data = &sii902x_hdmi_data,
+ .irq = gpio_to_irq(MX6SL_BRD_EPDC_PWRCTRL3)
+ },
};
static struct i2c_board_info mxc_i2c2_board_info[] __initdata = {
{
+ I2C_BOARD_INFO("ov5640", 0x3c),
+ .platform_data = (void *)&camera_data,
},
};
@@ -623,11 +749,17 @@ static struct mxc_dvfs_platform_data mx6sl_evk_dvfscore_data = {
};
static struct viv_gpu_platform_data imx6q_gpu_pdata __initdata = {
- .reserved_mem_size = SZ_128M,
+ .reserved_mem_size = SZ_32M,
};
void __init early_console_setup(unsigned long base, struct clk *clk);
+static const struct imxuart_platform_data mx6sl_evk_uart1_data __initconst = {
+ .flags = IMXUART_HAVE_RTSCTS | IMXUART_SDMA,
+ .dma_req_rx = MX6Q_DMA_REQ_UART2_RX,
+ .dma_req_tx = MX6Q_DMA_REQ_UART2_TX,
+};
+
static inline void mx6_evk_init_uart(void)
{
imx6q_add_imx_uart(0, NULL); /* DEBUG UART1 */
@@ -1105,7 +1237,7 @@ static struct platform_pwm_backlight_data mx6_evk_pwm_backlight_data = {
.dft_brightness = 128,
.pwm_period_ns = 50000,
};
-static struct fb_videomode video_modes[] = {
+static struct fb_videomode wvga_video_modes[] = {
{
/* 800x480 @ 57 Hz , pixel clk @ 32MHz */
"SEIKO-WVGA", 60, 800, 480, 29850, 99, 164, 33, 10, 10, 10,
@@ -1114,12 +1246,12 @@ static struct fb_videomode video_modes[] = {
0,},
};
-static struct mxc_fb_platform_data fb_data[] = {
+static struct mxc_fb_platform_data wvga_fb_data[] = {
{
.interface_pix_fmt = V4L2_PIX_FMT_RGB24,
.mode_str = "SEIKO-WVGA",
- .mode = video_modes,
- .num_modes = ARRAY_SIZE(video_modes),
+ .mode = wvga_video_modes,
+ .num_modes = ARRAY_SIZE(wvga_video_modes),
},
};
@@ -1127,6 +1259,24 @@ static struct platform_device lcd_wvga_device = {
.name = "lcd_seiko",
};
+static struct fb_videomode hdmi_video_modes[] = {
+ {
+ /* 1920x1080 @ 60 Hz , pixel clk @ 148MHz */
+ "sii9022x_1080p60", 60, 1920, 1080, 6734, 148, 88, 36, 4, 44, 5,
+ FB_SYNC_CLK_LAT_FALL,
+ FB_VMODE_NONINTERLACED,
+ 0,},
+};
+
+static struct mxc_fb_platform_data hdmi_fb_data[] = {
+ {
+ .interface_pix_fmt = V4L2_PIX_FMT_RGB24,
+ .mode_str = "1920x1080M@60",
+ .mode = hdmi_video_modes,
+ .num_modes = ARRAY_SIZE(hdmi_video_modes),
+ },
+};
+
static int mx6sl_evk_keymap[] = {
KEY(0, 0, KEY_SELECT),
KEY(0, 1, KEY_BACK),
@@ -1174,6 +1324,33 @@ static void __init elan_ts_init(void)
gpio_direction_output(MX6SL_BRD_ELAN_CE, 1);
}
+/*
+ *Usually UOK and DOK should have separate
+ *line to differentiate its behaviour (with different
+ * GPIO irq),because connect max8903 pin UOK to
+ *pin DOK from hardware design,cause software cannot
+ *process and distinguish two interrupt, so default
+ *enable dc_valid for ac charger
+ */
+static struct max8903_pdata charger1_data = {
+ .dok = MX6_BRD_CHG_DOK,
+ .uok = MX6_BRD_CHG_UOK,
+ .chg = MX6_BRD_CHG_STATUS,
+ .flt = MX6_BRD_CHG_FLT,
+ .dcm_always_high = true,
+ .dc_valid = true,
+ .usb_valid = false,
+ .feature_flag = 1,
+};
+
+static struct platform_device evk_max8903_charger_1 = {
+ .name = "max8903-charger",
+ .dev = {
+ .platform_data = &charger1_data,
+ },
+};
+
+
#define SNVS_LPCR 0x38
static void mx6_snvs_poweroff(void)
{
@@ -1185,11 +1362,27 @@ static void mx6_snvs_poweroff(void)
writel(value | 0x60, mx6_snvs_base + SNVS_LPCR);
}
+static int uart2_enabled;
+static int __init uart2_setup(char * __unused)
+{
+ uart2_enabled = 1;
+ return 1;
+}
+__setup("bluetooth", uart2_setup);
+
+static void __init uart2_init(void)
+{
+ mxc_iomux_v3_setup_multiple_pads(mx6sl_uart2_pads,
+ ARRAY_SIZE(mx6sl_uart2_pads));
+ imx6sl_add_imx_uart(1, &mx6sl_evk_uart1_data);
+}
/*!
* Board specific initialization.
*/
static void __init mx6_evk_init(void)
{
+ u32 i;
+
mxc_iomux_v3_setup_multiple_pads(mx6sl_brd_pads,
ARRAY_SIZE(mx6sl_brd_pads));
@@ -1211,11 +1404,25 @@ static void __init mx6_evk_init(void)
imx6q_add_imx_i2c(1, &mx6_evk_i2c1_data);
i2c_register_board_info(0, mxc_i2c0_board_info,
ARRAY_SIZE(mxc_i2c0_board_info));
+
+ /* setting sii902x address when hdmi enabled */
+ if (hdmi_enabled) {
+ for (i = 0; i < ARRAY_SIZE(mxc_i2c1_board_info); i++) {
+ if (!strcmp(mxc_i2c1_board_info[i].type, "sii902x")) {
+ mxc_i2c1_board_info[i].addr = 0x39;
+ break;
+ }
+ }
+ }
+
i2c_register_board_info(1, mxc_i2c1_board_info,
ARRAY_SIZE(mxc_i2c1_board_info));
- imx6q_add_imx_i2c(2, &mx6_evk_i2c2_data);
- i2c_register_board_info(2, mxc_i2c2_board_info,
- ARRAY_SIZE(mxc_i2c2_board_info));
+ /* only camera on I2C3, that's why we can do so */
+ if (csi_enabled == 1) {
+ imx6q_add_imx_i2c(2, &mx6_evk_i2c2_data);
+ i2c_register_board_info(2, mxc_i2c2_board_info,
+ ARRAY_SIZE(mxc_i2c2_board_info));
+ }
/* SPI */
imx6q_add_ecspi(0, &mx6_evk_spi_data);
@@ -1243,24 +1450,37 @@ static void __init mx6_evk_init(void)
imx6q_add_otp();
imx6q_add_mxc_pwm(0);
imx6q_add_mxc_pwm_backlight(0, &mx6_evk_pwm_backlight_data);
- imx6dl_add_imx_elcdif(&fb_data[0]);
- gpio_request(MX6_BRD_LCD_PWR_EN, "elcdif-power-on");
- gpio_direction_output(MX6_BRD_LCD_PWR_EN, 1);
- mxc_register_device(&lcd_wvga_device, NULL);
+ if (hdmi_enabled) {
+ imx6dl_add_imx_elcdif(&hdmi_fb_data[0]);
+ } else {
+ imx6dl_add_imx_elcdif(&wvga_fb_data[0]);
+
+ gpio_request(MX6_BRD_LCD_PWR_EN, "elcdif-power-on");
+ gpio_direction_output(MX6_BRD_LCD_PWR_EN, 1);
+ mxc_register_device(&lcd_wvga_device, NULL);
+ }
imx6dl_add_imx_pxp();
imx6dl_add_imx_pxp_client();
mxc_register_device(&max17135_sensor_device, NULL);
setup_spdc();
- if (!spdc_sel)
- imx6dl_add_imx_epdc(&epdc_data);
- else
- imx6sl_add_imx_spdc(&spdc_data);
+ if (csi_enabled) {
+ imx6sl_add_fsl_csi();
+ } else {
+ if (!spdc_sel)
+ imx6dl_add_imx_epdc(&epdc_data);
+ else
+ imx6sl_add_imx_spdc(&spdc_data);
+ }
imx6q_add_dvfs_core(&mx6sl_evk_dvfscore_data);
imx6q_init_audio();
+ /* uart2 for bluetooth */
+ if (uart2_enabled)
+ uart2_init();
+
imx6q_add_viim();
imx6q_add_imx2_wdt(0, NULL);
@@ -1271,10 +1491,17 @@ static void __init mx6_evk_init(void)
imx6sl_add_rngb();
imx6sl_add_imx_pxp_v4l2();
+ mxc_spdif_data.spdif_core_clk = clk_get_sys("mxc_spdif.0", NULL);
+ clk_put(mxc_spdif_data.spdif_core_clk);
+ imx6q_add_spdif(&mxc_spdif_data);
+ imx6q_add_spdif_dai();
+ imx6q_add_spdif_audio_device();
+
imx6q_add_perfmon(0);
imx6q_add_perfmon(1);
imx6q_add_perfmon(2);
-
+ /* Register charger chips */
+ platform_device_register(&evk_max8903_charger_1);
pm_power_off = mx6_snvs_poweroff;
}
diff --git a/arch/arm/mach-mx6/board-mx6solo_sabreauto.h b/arch/arm/mach-mx6/board-mx6solo_sabreauto.h
index 9111e6bc9b19..b752faae33ba 100644
--- a/arch/arm/mach-mx6/board-mx6solo_sabreauto.h
+++ b/arch/arm/mach-mx6/board-mx6solo_sabreauto.h
@@ -207,10 +207,6 @@ static iomux_v3_cfg_t mx6dl_sabreauto_pads[] = {
/* HDMI */
MX6DL_PAD_EIM_A25__HDMI_TX_CEC_LINE,
- /* camera reset */
- MX6DL_PAD_GPIO_19__GPIO_4_5,
- MX6DL_PAD_EIM_D24__GPIO_3_24,
-
/* MLB150 */
MX6DL_PAD_ENET_TXD1__MLB_MLBCLK,
MX6DL_PAD_GPIO_6__MLB_MLBSIG,
diff --git a/arch/arm/mach-mx6/bus_freq.c b/arch/arm/mach-mx6/bus_freq.c
index 9d18423c85c5..d96ac6a1e928 100644
--- a/arch/arm/mach-mx6/bus_freq.c
+++ b/arch/arm/mach-mx6/bus_freq.c
@@ -412,7 +412,7 @@ void bus_freq_update(struct clk *clk, bool flag)
*/
high_cpu_freq = 1;
if (low_bus_freq_mode || audio_bus_freq_mode)
- set_high_bus_freq(0);
+ set_high_bus_freq(1);
} else {
/* Update count */
if (clk->flags & AHB_HIGH_SET_POINT)
@@ -471,7 +471,7 @@ void bus_freq_update(struct clk *clk, bool flag)
/* Set to either high or
* medium setpoint.
*/
- set_high_bus_freq(0);
+ set_high_bus_freq(1);
}
}
}
@@ -506,7 +506,7 @@ static ssize_t bus_freq_scaling_enable_store(struct device *dev,
#else
bus_freq_scaling_is_active = 1;
#endif
- set_high_bus_freq(0);
+ set_high_bus_freq(1);
/* Make sure system can enter low bus mode if it should be in
low bus mode */
if (low_freq_bus_used() && !low_bus_freq_mode)
diff --git a/arch/arm/mach-mx6/clock.c b/arch/arm/mach-mx6/clock.c
index 5c3f053ce5fd..0c05c37f81d5 100644
--- a/arch/arm/mach-mx6/clock.c
+++ b/arch/arm/mach-mx6/clock.c
@@ -4854,7 +4854,7 @@ static struct clk usboh3_clk[] = {
.enable_shift = MXC_CCM_CCGRx_CG0_OFFSET,
.disable = _clk_disable,
.secondary = &usboh3_clk[1],
- .flags = AHB_MED_SET_POINT | CPU_FREQ_TRIG_UPDATE,
+ .flags = AHB_HIGH_SET_POINT | CPU_FREQ_TRIG_UPDATE,
},
{
.parent = &mmdc_ch0_axi_clk[0],
@@ -5304,6 +5304,7 @@ static struct clk_lookup lookups[] = {
_REGISTER_CLOCK(NULL, "mlb150_clk", mlb150_clk),
_REGISTER_CLOCK(NULL, "anaclk_1", anaclk_1),
_REGISTER_CLOCK(NULL, "anaclk_2", anaclk_2),
+ _REGISTER_CLOCK(NULL, "apb_pclk", dummy_clk),
};
static void clk_tree_init(void)
diff --git a/arch/arm/mach-mx6/clock_mx6sl.c b/arch/arm/mach-mx6/clock_mx6sl.c
index 616099180008..6de15622eede 100755
--- a/arch/arm/mach-mx6/clock_mx6sl.c
+++ b/arch/arm/mach-mx6/clock_mx6sl.c
@@ -1945,8 +1945,8 @@ static unsigned long _clk_ipu_round_rate(struct clk *clk,
}
static struct clk ipu1_clk = {
- __INIT_CLK_DEBUG(ipu1_clk)
- .parent = &pll2_pfd2_400M,
+ __INIT_CLK_DEBUG(csi_clk)
+ .parent = &osc_clk,
.enable_reg = MXC_CCM_CCGR3,
.enable_shift = MXC_CCM_CCGRx_CG0_OFFSET,
.enable = _clk_enable,
@@ -4065,9 +4065,9 @@ int __init mx6sl_clocks_init(unsigned long ckil, unsigned long osc,
3 << MXC_CCM_CCGRx_CG11_OFFSET, MXC_CCM_CCGR1);
__raw_writel(1 << MXC_CCM_CCGRx_CG12_OFFSET |
1 << MXC_CCM_CCGRx_CG11_OFFSET |
- 1 << MXC_CCM_CCGRx_CG10_OFFSET |
- 1 << MXC_CCM_CCGRx_CG9_OFFSET |
- 1 << MXC_CCM_CCGRx_CG8_OFFSET, MXC_CCM_CCGR2);
+ 3 << MXC_CCM_CCGRx_CG10_OFFSET |
+ 3 << MXC_CCM_CCGRx_CG9_OFFSET |
+ 3 << MXC_CCM_CCGRx_CG8_OFFSET, MXC_CCM_CCGR2);
__raw_writel(1 << MXC_CCM_CCGRx_CG14_OFFSET |
3 << MXC_CCM_CCGRx_CG13_OFFSET |
3 << MXC_CCM_CCGRx_CG12_OFFSET |
diff --git a/arch/arm/mach-mx6/cpu.c b/arch/arm/mach-mx6/cpu.c
index be5011aeab34..fbb3827668e0 100644
--- a/arch/arm/mach-mx6/cpu.c
+++ b/arch/arm/mach-mx6/cpu.c
@@ -119,8 +119,14 @@ static int __init post_cpu_init(void)
{
unsigned int reg;
void __iomem *base;
+ u32 iram_size;
- iram_init(MX6Q_IRAM_BASE_ADDR, MX6Q_IRAM_SIZE);
+ if (cpu_is_mx6q())
+ iram_size = MX6Q_IRAM_SIZE;
+ else
+ iram_size = MX6DL_MX6SL_IRAM_SIZE;
+
+ iram_init(MX6Q_IRAM_BASE_ADDR, iram_size);
base = ioremap(AIPS1_ON_BASE_ADDR, PAGE_SIZE);
__raw_writel(0x0, base + 0x40);
diff --git a/arch/arm/mach-mx6/cpu_op-mx6.c b/arch/arm/mach-mx6/cpu_op-mx6.c
index 7e054c1d743c..99336d873756 100644
--- a/arch/arm/mach-mx6/cpu_op-mx6.c
+++ b/arch/arm/mach-mx6/cpu_op-mx6.c
@@ -162,7 +162,7 @@ static struct cpu_op mx6dl_cpu_op_1_2G[] = {
.cpu_podf = 0,
.pu_voltage = 1175000,
.soc_voltage = 1175000,
- .cpu_voltage = 1150000,},
+ .cpu_voltage = 1175000,},
{
.pll_rate = 396000000,
.cpu_rate = 396000000,
@@ -177,16 +177,16 @@ static struct cpu_op mx6dl_cpu_op_1G[] = {
.pll_rate = 996000000,
.cpu_rate = 996000000,
.cpu_podf = 0,
- .pu_voltage = 1250000,
- .soc_voltage = 1250000,
- .cpu_voltage = 1250000,},
+ .pu_voltage = 1275000,
+ .soc_voltage = 1275000,
+ .cpu_voltage = 1275000,},
{
.pll_rate = 792000000,
.cpu_rate = 792000000,
.cpu_podf = 0,
.pu_voltage = 1175000,
.soc_voltage = 1175000,
- .cpu_voltage = 1150000,},
+ .cpu_voltage = 1175000,},
{
.pll_rate = 396000000,
.cpu_rate = 396000000,
@@ -202,7 +202,7 @@ static struct cpu_op mx6dl_cpu_op[] = {
.cpu_podf = 0,
.pu_voltage = 1175000,
.soc_voltage = 1175000,
- .cpu_voltage = 1150000,},
+ .cpu_voltage = 1175000,},
{
.pll_rate = 396000000,
.cpu_rate = 396000000,
diff --git a/arch/arm/mach-mx6/cpu_regulator-mx6.c b/arch/arm/mach-mx6/cpu_regulator-mx6.c
index cb08cad48204..5019f8bedff2 100644
--- a/arch/arm/mach-mx6/cpu_regulator-mx6.c
+++ b/arch/arm/mach-mx6/cpu_regulator-mx6.c
@@ -37,6 +37,7 @@ static struct cpu_op *cpu_op_tbl;
extern struct cpu_op *(*get_cpu_op)(int *op);
extern unsigned long loops_per_jiffy;
+int external_pureg;
static inline unsigned long mx6_cpu_jiffies(unsigned long old, u_int div,
u_int mult)
@@ -62,6 +63,7 @@ void mx6_cpu_regulator_init(void)
int cpu;
u32 curr_cpu = 0;
+ external_pureg = 0;
cpu_regulator = regulator_get(NULL, gp_reg_id);
if (IS_ERR(cpu_regulator))
printk(KERN_ERR "%s: failed to get cpu regulator\n", __func__);
@@ -108,5 +110,21 @@ void mx6_cpu_regulator_init(void)
pu_regulator = regulator_get(NULL, pu_reg_id);
if (IS_ERR(pu_regulator))
printk(KERN_ERR "%s: failed to get pu regulator\n", __func__);
+ /*If enable CONFIG_MX6_INTER_LDO_BYPASS and VDDPU_IN is single supplied
+ *by external pmic, it means VDDPU_IN can be turned off if GPU/VPU driver
+ *not running.In this case we should set external_pureg which can be used
+ *in pu_enable/pu_disable of arch/arm/mach-mx6/mx6_anatop_regulator.c to
+ *enable or disable external VDDPU regulator from pmic. But for FSL
+ *reference boards, VDDSOC_IN connect with VDDPU_IN, so we didn't set
+ *pu_reg_id to the external pmic regulator supply name in the board file.
+ *In this case external_pureg should be 0 and can't turn off extern pmic
+ *regulator, but can turn off VDDPU by internal anatop power gate.
+ *
+ *If disable CONFIG_MX6_INTER_LDO_BYPASS, external_pureg will be 0, and
+ *VDDPU can be turned off by internal anatop anatop power gate.
+ *
+ */
+ else if (!IS_ERR(pu_regulator) && strcmp(pu_reg_id, "cpu_vddvpu"))
+ external_pureg = 1;
}
diff --git a/arch/arm/mach-mx6/devices-imx6q.h b/arch/arm/mach-mx6/devices-imx6q.h
index bd948cecbcd2..4525e29a472a 100644
--- a/arch/arm/mach-mx6/devices-imx6q.h
+++ b/arch/arm/mach-mx6/devices-imx6q.h
@@ -23,6 +23,10 @@ extern const struct imx_imx_uart_1irq_data imx6q_imx_uart_data[] __initconst;
#define imx6q_add_imx_uart(id, pdata) \
imx_add_imx_uart_1irq(&imx6q_imx_uart_data[id], pdata)
+extern const struct imx_imx_uart_1irq_data imx6sl_imx_uart_data[] __initconst;
+#define imx6sl_add_imx_uart(id, pdata) \
+ imx_add_imx_uart_1irq(&imx6sl_imx_uart_data[id], pdata)
+
extern const struct imx_snvs_rtc_data imx6q_imx_snvs_rtc_data __initconst;
#define imx6q_add_imx_snvs_rtc() \
imx_add_snvs_rtc(&imx6q_imx_snvs_rtc_data)
@@ -36,8 +40,8 @@ imx6q_anatop_thermal_imx_data __initconst;
#define imx6q_add_anatop_thermal_imx(id, pdata) \
imx_add_anatop_thermal_imx(&imx6q_anatop_thermal_imx_data, pdata)
-extern const struct imx_dma_data imx6q_dma_data __initconst;
-#define imx6q_add_dma() imx_add_dma(&imx6q_dma_data);
+extern const struct imx_dma_res_data imx6q_dma_res_data __initconst;
+#define imx6q_add_dma() imx_add_dma(&imx6q_dma_res_data);
#define imx6q_add_gpmi(platform_data) imx_add_gpmi(platform_data);
@@ -219,6 +223,10 @@ extern const struct imx_pxp_data imx6dl_pxp_data __initconst;
#define imx6sl_add_imx_pxp_v4l2() \
imx_add_imx_pxp_v4l2()
+extern const struct imx_fsl_csi_data imx6sl_csi_data __initconst;
+#define imx6sl_add_fsl_csi() \
+ imx_add_fsl_csi(&imx6sl_csi_data)
+
extern const struct imx_epdc_data imx6dl_epdc_data __initconst;
#define imx6dl_add_imx_epdc(pdata) \
imx_add_imx_epdc(&imx6dl_epdc_data, pdata)
diff --git a/arch/arm/mach-mx6/etm.c b/arch/arm/mach-mx6/etm.c
new file mode 100644
index 000000000000..8f328608ebfd
--- /dev/null
+++ b/arch/arm/mach-mx6/etm.c
@@ -0,0 +1,110 @@
+/*
+ * Copyright (C) 2012 Freescale Semiconductor, Inc. All Rights Reserved.
+ *
+ * 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.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#include <linux/types.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/clk.h>
+#include <linux/module.h>
+#include <linux/iram_alloc.h>
+#include <linux/delay.h>
+#include <linux/amba/bus.h>
+
+#include <mach/hardware.h>
+#include <asm/io.h>
+#include <asm/mach/map.h>
+#include <asm/hardware/coresight.h>
+
+static struct __init amba_device mx6_etb_device = {
+ .dev = {
+ .init_name = "etb",
+ },
+ .res = {
+ .start = MX6Q_ETB_BASE_ADDR,
+ .end = MX6Q_ETB_BASE_ADDR + SZ_4K - 1,
+ .flags = IORESOURCE_MEM,
+ },
+ .periphid = 0x3bb907,
+};
+
+static struct __init amba_device mx6_etm_device[] = {
+ {
+ .dev = {
+ .init_name = "etm.0",
+ },
+ .res = {
+ .start = MX6Q_PTM0_BASE_ADDR,
+ .end = MX6Q_PTM0_BASE_ADDR + SZ_4K - 1,
+ },
+ .periphid = 0x1bb950,
+ },
+ {
+ .dev = {
+ .init_name = "etm.1",
+ },
+ .res = {
+ .start = MX6Q_PTM1_BASE_ADDR,
+ .end = MX6Q_PTM1_BASE_ADDR + SZ_4K - 1,
+ },
+ .periphid = 0x1bb950,
+ },
+ {
+ .dev = {
+ .init_name = "etm.2",
+ },
+ .res = {
+ .start = MX6Q_PTM2_BASE_ADDR,
+ .end = MX6Q_PTM2_BASE_ADDR + SZ_4K - 1,
+ },
+ .periphid = 0x1bb950,
+ },
+ {
+ .dev = {
+ .init_name = "etm.3",
+ },
+ .res = {
+ .start = MX6Q_PTM3_BASE_ADDR,
+ .end = MX6Q_PTM3_BASE_ADDR + SZ_4K - 1,
+ },
+ .periphid = 0x1bb950,
+ },
+};
+
+#define FUNNEL_CTL 0
+static int __init etm_init(void)
+{
+ int i;
+ __iomem void *base;
+ base = ioremap(0x02144000, SZ_4K);
+ /*Unlock Funnel*/
+ __raw_writel(UNLOCK_MAGIC, base + CSMR_LOCKACCESS);
+ /*Enable all funnel port*/
+ __raw_writel(__raw_readl(base + FUNNEL_CTL) | 0xFF,
+ base + FUNNEL_CTL);
+ /*Lock Funnel*/
+ __raw_writel(0, base + CSMR_LOCKACCESS);
+ iounmap(base);
+
+ amba_device_register(&mx6_etb_device, &iomem_resource);
+ for (i = 0; i < num_possible_cpus(); i++)
+ amba_device_register(mx6_etm_device + i, &iomem_resource);
+
+ return 0;
+}
+
+subsys_initcall(etm_init);
diff --git a/arch/arm/mach-mx6/mx6_anatop_regulator.c b/arch/arm/mach-mx6/mx6_anatop_regulator.c
index 945adbdb759a..f2c2ebf600b3 100644
--- a/arch/arm/mach-mx6/mx6_anatop_regulator.c
+++ b/arch/arm/mach-mx6/mx6_anatop_regulator.c
@@ -22,6 +22,7 @@
* mx6_anatop_regulator.c -- i.MX6 Driver for Anatop regulators
*/
#include <linux/device.h>
+#include <linux/err.h>
#include <linux/delay.h>
#include <linux/platform_device.h>
#include <linux/regulator/anatop-regulator.h>
@@ -30,6 +31,9 @@
#include <linux/io.h>
#include <linux/slab.h>
#include <linux/gpio.h>
+#include <linux/clk.h>
+
+#include <mach/clock.h>
#include "crm_regs.h"
#include "regs-anadig.h"
@@ -41,8 +45,17 @@ extern struct platform_device sgtl5000_vdda_reg_devices;
extern struct platform_device sgtl5000_vddio_reg_devices;
extern struct platform_device sgtl5000_vddd_reg_devices;
extern void __iomem *gpc_base;
-/* Default PU voltage value set to 1.1V */
-static unsigned int org_ldo = 0x2000;
+/* we use the below flag to keep PU regulator state, because enable/disable
+of PU regulator share with the same register as voltage set of PU regulator.
+PU voltage set by cpufreq driver if the flag is set, and enable/disable by
+GPU/VPU driver*/
+static unsigned int pu_is_enabled;
+static unsigned int get_clk;
+static struct clk *gpu3d_clk, *gpu3d_shade_clk, *gpu2d_clk, *gpu2d_axi_clk;
+static struct clk *openvg_axi_clk, *vpu_clk;
+extern int external_pureg;
+extern struct regulator *pu_regulator;
+
static int get_voltage(struct anatop_regulator *sreg)
{
@@ -90,17 +103,56 @@ static int set_voltage(struct anatop_regulator *sreg, int uv)
static int pu_enable(struct anatop_regulator *sreg)
{
- unsigned int reg;
+ unsigned int reg, vddsoc;
+ int ret = 0;
+ /*get PU related clk to finish PU regulator power up*/
+ if (!get_clk) {
+ if (!cpu_is_mx6sl()) {
+ gpu3d_clk = clk_get(NULL, "gpu3d_clk");
+ if (IS_ERR(gpu3d_clk))
+ printk(KERN_ERR "%s: failed to get gpu3d_clk!\n"
+ , __func__);
+ gpu3d_shade_clk = clk_get(NULL, "gpu3d_shader_clk");
+ if (IS_ERR(gpu3d_shade_clk))
+ printk(KERN_ERR "%s: failed to get shade_clk!\n"
+ , __func__);
+ if (IS_ERR(vpu_clk))
+ printk(KERN_ERR "%s: failed to get vpu_clk!\n",
+ __func__);
+ }
+ gpu2d_clk = clk_get(NULL, "gpu2d_clk");
+ if (IS_ERR(gpu2d_clk))
+ printk(KERN_ERR "%s: failed to get gpu2d_clk!\n",
+ __func__);
+ gpu2d_axi_clk = clk_get(NULL, "gpu2d_axi_clk");
+ if (IS_ERR(gpu2d_axi_clk))
+ printk(KERN_ERR "%s: failed to get gpu2d_axi_clk!\n",
+ __func__);
+ openvg_axi_clk = clk_get(NULL, "openvg_axi_clk");
+ if (IS_ERR(openvg_axi_clk))
+ printk(KERN_ERR "%s: failed to get openvg_axi_clk!\n",
+ __func__);
+ get_clk = 1;
- /* Do not enable PU LDO if it is already enabled */
- reg = __raw_readl(ANADIG_REG_CORE) & (ANADIG_REG_TARGET_MASK
- << ANADIG_REG1_PU_TARGET_OFFSET);
- if (reg != 0)
- return 0;
-
- /* Set the voltage of VDDPU as in normal mode. */
- __raw_writel(org_ldo | (__raw_readl(ANADIG_REG_CORE) &
- (~(ANADIG_REG_TARGET_MASK << ANADIG_REG1_PU_TARGET_OFFSET))), ANADIG_REG_CORE);
+ }
+ if (external_pureg) {
+ /*enable extern PU regulator*/
+ ret = regulator_enable(pu_regulator);
+ if (ret < 0)
+ printk(KERN_ERR "%s: enable pu error!\n", __func__);
+ } else {
+ /*Track the voltage of VDDPU with VDDSOC if use internal PU
+ *regulator.
+ */
+ reg = __raw_readl(ANADIG_REG_CORE);
+ vddsoc = reg & (ANADIG_REG_TARGET_MASK <<
+ ANADIG_REG2_SOC_TARGET_OFFSET);
+ reg &= ~(ANADIG_REG_TARGET_MASK <<
+ ANADIG_REG1_PU_TARGET_OFFSET);
+ reg |= vddsoc >> (ANADIG_REG2_SOC_TARGET_OFFSET
+ -ANADIG_REG1_PU_TARGET_OFFSET);
+ __raw_writel(reg, ANADIG_REG_CORE);
+ }
/* Need to wait for the regulator to come back up */
/*
@@ -109,7 +161,17 @@ static int pu_enable(struct anatop_regulator *sreg)
* 25mV step.
*/
udelay(150);
-
+ /*enable gpu clock to powerup GPU right.*/
+ if (get_clk) {
+ if (!cpu_is_mx6sl()) {
+ clk_enable(gpu3d_clk);
+ clk_enable(gpu3d_shade_clk);
+ clk_enable(vpu_clk);
+ }
+ clk_enable(gpu2d_clk);
+ clk_enable(gpu2d_axi_clk);
+ clk_enable(openvg_axi_clk);
+ }
/* enable power up request */
reg = __raw_readl(gpc_base + GPC_PGC_GPU_PGCR_OFFSET);
__raw_writel(reg | 0x1, gpc_base + GPC_PGC_GPU_PGCR_OFFSET);
@@ -119,7 +181,6 @@ static int pu_enable(struct anatop_regulator *sreg)
/* Wait for the power up bit to clear */
while (__raw_readl(gpc_base + GPC_CNTR_OFFSET) & 0x2)
;
-
/* Enable the Brown Out detection. */
reg = __raw_readl(ANA_MISC2_BASE_ADDR);
reg |= ANADIG_ANA_MISC2_REG1_BO_EN;
@@ -131,19 +192,24 @@ static int pu_enable(struct anatop_regulator *sreg)
reg &= ~0x80000000;
__raw_writel(reg, gpc_base + 0x14);
#endif
-
+ pu_is_enabled = 1;
+ if (get_clk) {
+ if (!cpu_is_mx6sl()) {
+ clk_disable(gpu3d_clk);
+ clk_disable(gpu3d_shade_clk);
+ clk_disable(vpu_clk);
+ }
+ clk_disable(gpu2d_clk);
+ clk_disable(gpu2d_axi_clk);
+ clk_disable(openvg_axi_clk);
+ }
return 0;
}
static int pu_disable(struct anatop_regulator *sreg)
{
unsigned int reg;
-
- /* Do not disable PU LDO if it is not enabled */
- reg = __raw_readl(ANADIG_REG_CORE) & (ANADIG_REG_TARGET_MASK
- << ANADIG_REG1_PU_TARGET_OFFSET);
- if (reg == 0)
- return 0;
+ int ret = 0;
/* Disable the brown out detection since we are going to be
* disabling the LDO.
@@ -163,7 +229,6 @@ static int pu_disable(struct anatop_regulator *sreg)
/* Wait for power down to complete. */
while (__raw_readl(gpc_base + GPC_CNTR_OFFSET) & 0x1)
;
-
#ifndef CONFIG_MX6_INTER_LDO_BYPASS
/* Mask the ANATOP brown out interrupt in the GPC. */
reg = __raw_readl(gpc_base + 0x14);
@@ -171,12 +236,19 @@ static int pu_disable(struct anatop_regulator *sreg)
__raw_writel(reg, gpc_base + 0x14);
#endif
- /* PU power gating. */
- reg = __raw_readl(ANADIG_REG_CORE);
- org_ldo = reg & (ANADIG_REG_TARGET_MASK << ANADIG_REG1_PU_TARGET_OFFSET);
- reg &= ~(ANADIG_REG_TARGET_MASK << ANADIG_REG1_PU_TARGET_OFFSET);
- __raw_writel(reg, ANADIG_REG_CORE);
-
+ if (external_pureg) {
+ /*disable extern PU regulator*/
+ ret = regulator_disable(pu_regulator);
+ if (ret < 0)
+ printk(KERN_ERR "%s: disable pu error!\n", __func__);
+ } else {
+ /* PU power gating. */
+ reg = __raw_readl(ANADIG_REG_CORE);
+ reg &= ~(ANADIG_REG_TARGET_MASK <<
+ ANADIG_REG1_PU_TARGET_OFFSET);
+ __raw_writel(reg, ANADIG_REG_CORE);
+ }
+ pu_is_enabled = 0;
/* Clear the BO interrupt in the ANATOP. */
reg = __raw_readl(ANADIG_MISC1_REG);
reg |= 0x80000000;
@@ -185,14 +257,7 @@ static int pu_disable(struct anatop_regulator *sreg)
}
static int is_pu_enabled(struct anatop_regulator *sreg)
{
- unsigned int reg;
-
- reg = __raw_readl(ANADIG_REG_CORE) & (ANADIG_REG_TARGET_MASK
- << ANADIG_REG1_PU_TARGET_OFFSET);
- if (reg == 0)
- return 0;
- else
- return 1;
+ return pu_is_enabled;
}
static int enable(struct anatop_regulator *sreg)
{
@@ -447,6 +512,9 @@ static int __init regulators_init(void)
anatop_register_regulator(&vdd1p1_reg, ANATOP_VDD1P1, &vdd1p1_init);
anatop_register_regulator(&vdd3p0_reg, ANATOP_VDD3P0, &vdd3p0_init);
+ /* clear flag in boot*/
+ pu_is_enabled = 0;
+ get_clk = 0;
return 0;
}
postcore_initcall(regulators_init);
diff --git a/arch/arm/mach-mx6/mx6_suspend.S b/arch/arm/mach-mx6/mx6_suspend.S
index 0533ad1b20ef..e8fd2b259aae 100644
--- a/arch/arm/mach-mx6/mx6_suspend.S
+++ b/arch/arm/mach-mx6/mx6_suspend.S
@@ -32,7 +32,7 @@
#define MMDC_MAPSR_OFFSET 0x404
#define MMDC_MAPSR_PSS (1 << 4)
#define MMDC_MAPSR_PSD (1 << 0)
-#define IRAM_SUSPEND_SIZE (1 << 12)
+#define IRAM_SUSPEND_SIZE (1 << 13)
/*************************************************************
mx6_suspend:
@@ -50,6 +50,333 @@ see define in include/linux/suspend.h
r1: iram_paddr
r2: suspend_iram_base
*************************************************************/
+ .macro mx6sl_standy_saving_set
+
+ /* Move periph_clk to OSC_CLK. */
+ ldr r1, =CCM_BASE_ADDR
+ add r1, r1, #PERIPBASE_VIRT
+
+ /* Ensure the periph_clk2_sel to OSC clk. */
+ ldr r0, [r1, #0x18]
+ bic r0, r0, #0x3000
+ orr r0, r0, #0x1000
+ str r0, [r1, #0x18]
+
+ ldr r0, [r1, #0x14]
+ orr r0, r0, #0x2000000
+ str r0, [r1, #0x14]
+
+periph_clk_switch:
+ ldr r0, [r1, #0x48]
+ cmp r0, #0
+ bne periph_clk_switch
+
+ /* Set the divider to divider by 8 */
+ ldr r0, [r1, #0x14]
+ orr r0, r0, #0x70000
+ orr r0, r0, #0x1c00
+ str r0, [r1, #0x14]
+
+ahb_podf:
+ ldr r0, [r1, #0x48]
+ cmp r0, #0
+ bne ahb_podf
+
+ /* Move DDR clk to PLL3 clock.
+ */
+ /* First set the divider to 2. */
+ ldr r0, [r1, #0x14]
+ orr r0, r0, #0x1
+ str r0, [r1, #0x14]
+
+ ldr r0, [r1, #0x18]
+ bic r0, r0, #0x100000
+ str r0, [r1, #0x18]
+
+ ldr r0, [r1, #0x14]
+ orr r0, r0, #0x4000000
+ str r0, [r1, #0x14]
+
+ddr_switch:
+ ldr r0, [r1, #0x48]
+ cmp r0, #0
+ bne ddr_switch
+
+ /* Set DDR clock to divide by 8. */
+ ldr r0, [r1, #0x14]
+ orr r0, r0, #0x38
+ str r0, [r1, #0x14]
+
+mmdc_div:
+ ldr r0, [r1, #0x48]
+ cmp r0, #0
+ bne mmdc_div
+
+ /* Now Switch ARM to run from
+ * step_clk sourced from OSC.
+ */
+ ldr r0, [r1, #0xc]
+ bic r0, r1, #0x100
+ str r0, [r1, #0x0c]
+
+ /* Now switch PLL1_SW_CLK to step_clk. */
+ ldr r0, [r1, #0x0c]
+ orr r0, r0, #0x4
+ str r0, [r1, #0x0c]
+
+ ldr r1, =ANATOP_BASE_ADDR
+ add r1, r1, #PERIPBASE_VIRT
+
+ /* Need to clock gate the 528 PFDs before
+ * powering down PLL2.
+ * Only the PLL2_PFD2_400M should be ON
+ * as it feeds the MMDC/AHB
+ */
+ ldr r0, [r1, #0x100]
+ orr r0, r0, #0x800000
+ str r0, [r1, #0x100]
+
+ /* Now bypass PLL1 and PLL2. */
+ ldr r0, =0x10000
+ str r0, [r1, #0x4]
+ str r0, [r1, #0x34]
+
+ /* Now do all the analog savings. */
+
+ /* Disable 1p1 brown out. */
+ ldr r0, [r1, #0x110]
+ bic r0, r0, #0x2
+ str r0, [r1, #0x110]
+
+ /* Enable the weak 2P5 */
+ ldr r0, [r1, #0x130]
+ orr r0, r0, #0x40000
+ str r0, [r1, #0x130]
+
+ /*Disable main 2p5. */
+ ldr r0, [r1, #0x130]
+ bic r0, r0, #0x1
+ str r0, [r1, #0x130]
+
+
+ /* Set the OSC bias current to -37.5%
+ * to drop the power on VDDHIGH.
+ */
+ ldr r0, [r1, #0x150]
+ orr r0, r0, #0xC000
+ str r0, [r1, #0x150]
+ .endm
+
+ .macro mx6sl_standby_savings_restore
+
+ /* Set the OSC bias current to max
+ * value for normal operation.
+ */
+ ldr r6, [r1, #0x150]
+ bic r6, r6, #0xC000
+ str r6, [r1, #0x150]
+
+ /*Enable main 2p5. */
+ ldr r6, [r1, #0x130]
+ orr r6, r6, #0x1
+ str r6, [r1, #0x130]
+
+ /* Ensure the 2P5 is up. */
+loop_2p5:
+ ldr r6, [r1, #0x130]
+ and r6, r6, #0x20000
+ cmp r6, #0x20000
+ bne loop_2p5
+
+ /* Disable the weak 2P5 */
+ ldr r6, [r1, #0x130]
+ bic r6, r6, #0x40000
+ str r6, [r1, #0x130]
+
+ /* Enable 1p1 brown out. */
+ ldr r6, [r1, #0x110]
+ orr r6, r6, #0x2
+ str r6, [r1, #0x110]
+
+ /* Unbypass PLLs and
+ * wait for relock.
+ */
+ ldr r6, =(1 << 16)
+ str r6, [r1, #0x08]
+ str r6, [r1, #0x38]
+
+wait_for_pll_lock:
+ ldr r6, [r1, #0x0]
+ and r6, r6, #0x80000000
+ cmp r6, #0x80000000
+ bne wait_for_pll_lock
+
+ /* Set PLL1_sw_clk back to PLL1. */
+ ldr r6, [r3, #0x0c]
+ bic r6, r6, #0x4
+ str r6, [r3, #0xc]
+
+ /* Need to enable the 528 PFDs after
+ * powering up PLL2.
+ * Only the PLL2_PFD2_400M should be ON
+ * as it feeds the MMDC. Rest should have
+ * been managed by clock code.
+ */
+ ldr r6, [r1, #0x100]
+ bic r6, r6, #0x800000
+ str r6, [r1, #0x100]
+
+ /* Move periph_clk back
+ * to PLL2_PFD2_400.
+ */
+ ldr r6, [r3, #0x14]
+ bic r6, r6, #0x2000000
+ str r6, [r3, #0x14]
+
+ /* Set the dividers to default value. */
+ ldr r6, [r3, #0x14]
+ bic r6, r6, #0x70000
+ bic r6, r6, #0x1c00
+ orr r6, r6, #0x10800
+ str r6, [r3, #0x14]
+
+ahb_podf1:
+ ldr r0, [r3, #0x48]
+ cmp r0, #0
+ bne ahb_podf1
+
+periph_clk_switch1:
+ ldr r6, [r3, #0x48]
+ cmp r6, #0
+ bne periph_clk_switch1
+
+ /* Move MMDC back to PLL2_PFD2_400 */
+ ldr r6, [r3, #0x14]
+ bic r6, r6, #0x4000000
+ str r6, [r3, #0x14]
+
+mmdc_loop2:
+ ldr r6, [r3, #0x48]
+ cmp r6, #0
+ bne mmdc_loop2
+
+ /* Set DDR clock to divide by 1. */
+ ldr r6, [r3, #0x14]
+ bic r6, r0, #0x38
+ str r6, [r3, #0x14]
+
+mmdc_div1:
+ ldr r6, [r3, #0x48]
+ cmp r6, #0
+ bne mmdc_div1
+
+ .endm
+
+ .macro mx6sl_standby_pg_savings_restore
+
+ /* Set the OSC bias current to max
+ * value for normal operation.
+ */
+ ldr r6, [r1, #0x150]
+ bic r6, r6, #0xC000
+ str r6, [r1, #0x150]
+
+ /*Enable main 2p5. */
+ ldr r6, [r1, #0x130]
+ orr r6, r6, #0x1
+ str r6, [r1, #0x130]
+
+ /* Ensure the 2P5 is up. */
+loop_2p5_1:
+ ldr r6, [r1, #0x130]
+ and r6, r6, #0x20000
+ cmp r6, #0x20000
+ bne loop_2p5_1
+
+ /* Disable the weak 2P5 */
+ ldr r6, [r1, #0x130]
+ bic r6, r6, #0x40000
+ str r6, [r1, #0x130]
+
+ /* Enable 1p1 brown out. */
+ ldr r6, [r1, #0x110]
+ orr r6, r6, #0x2
+ str r6, [r1, #0x110]
+
+ /* Unbypass PLLs and
+ * wait for relock.
+ */
+ ldr r6, =(1 << 16)
+ str r6, [r1, #0x08]
+ str r6, [r1, #0x38]
+
+wait_for_pll_lock1:
+ ldr r6, [r1, #0x0]
+ and r6, r6, #0x80000000
+ cmp r6, #0x80000000
+ bne wait_for_pll_lock1
+
+ /* Set PLL1_sw_clk back to PLL1. */
+ ldr r6, [r3, #0x0c]
+ bic r6, r6, #0x4
+ str r6, [r3, #0xc]
+
+ /* Need to enable the 528 PFDs after
+ * powering up PLL2.
+ * Only the PLL2_PFD2_400M should be ON
+ * as it feeds the MMDC. Rest should have
+ * been managed by clock code.
+ */
+ ldr r6, [r1, #0x100]
+ bic r6, r6, #0x800000
+ str r6, [r1, #0x100]
+
+ /* Move DDR clock back to PLL2_PFD2_400 */
+ ldr r6, [r3, #0x14]
+ bic r6, r6, #0x4000000
+ str r6, [r3, #0x14]
+
+mmdc_loop3:
+ ldr r6, [r3, #0x48]
+ cmp r6, #0
+ bne mmdc_loop3
+
+ /* Set DDR clock to divide by 1. */
+ ldr r6, [r3, #0x14]
+ bic r6, r6, #0x38
+ str r6, [r3, #0x14]
+
+mmdc_div2:
+ ldr r6, [r3, #0x48]
+ cmp r6, #0
+ bne mmdc_div2
+
+ /* Move periph_clk back
+ * to PLL2_PFD2_400.
+ */
+ ldr r6, [r3, #0x14]
+ bic r6, r6, #0x2000000
+ str r6, [r3, #0x14]
+
+periph_clk_switch2:
+ ldr r6, [r3, #0x48]
+ cmp r6, #0
+ bne periph_clk_switch2
+
+ /* Set the dividers to default value. */
+ ldr r6, [r3, #0x14]
+ bic r6, r6, #0x70000
+ bic r6, r6, #0x1c00
+ orr r6, r6, #0x10800
+ str r6, [r3, #0x14]
+
+ahb_podf2:
+ ldr r6, [r3, #0x48]
+ cmp r6, #0
+ bne ahb_podf2
+
+ .endm
+
.macro sl_ddr_io_save
ldr r4, [r1, #0x30c] /* DRAM_DQM0 */
@@ -58,12 +385,6 @@ r2: suspend_iram_base
ldr r7, [r1, #0x318] /* DRAM_DQM3 */
stmfd r0!, {r4-r7}
- ldr r4, [r1, #0x344] /* DRAM_SDQS0 */
- ldr r5, [r1, #0x348] /* DRAM_SDQS1 */
- ldr r6, [r1, #0x34c] /* DRAM_SDQS2 */
- ldr r7, [r1, #0x350] /* DRAM_SDQS3 */
- stmfd r0!, {r4-r7}
-
ldr r4, [r1, #0x5c4] /* GPR_B0DS */
ldr r5, [r1, #0x5cc] /* GPR_B1DS */
ldr r6, [r1, #0x5d4] /* GPR_B2DS */
@@ -73,7 +394,7 @@ r2: suspend_iram_base
ldr r4, [r1, #0x300] /* DRAM_CAS */
ldr r5, [r1, #0x31c] /* DRAM_RAS */
ldr r6, [r1, #0x338] /* DRAM_SDCLK_0 */
- ldr r7, [r1, #0x5ac] /* GPR_ADDS*/
+ ldr r7, [r1, #0x5ac] /* GPR_ADDS*/
stmfd r0!, {r4-r7}
ldr r4, [r1, #0x5b0] /* DDRMODE_CTL */
@@ -98,22 +419,16 @@ r2: suspend_iram_base
str r7, [r1, #0x318] /* DRAM_DQM3 */
ldmea r0!, {r4-r7}
- str r4, [r1, #0x344] /* DRAM_SDQS0 */
- str r5, [r1, #0x348] /* DRAM_SDQS1 */
- str r6, [r1, #0x34c] /* DRAM_SDQS2 */
- str r7, [r1, #0x350] /* DRAM_SDQS3 */
-
- ldmea r0!, {r4-r7}
str r4, [r1, #0x5c4] /* GPR_B0DS */
str r5, [r1, #0x5cc] /* GPR_B1DS */
- str r6, [r1, #0x5d4] /* GPR_B2DS */
- str r7, [r1, #0x5d8] /* GPR_B3DS */
+ str r6, [r1, #0x5d4] /* GPR_B2DS */
+ str r7, [r1, #0x5d8] /* GPR_B3DS */
ldmea r0!, {r4-r7}
str r4, [r1, #0x300] /* DRAM_CAS */
str r5, [r1, #0x31c] /* DRAM_RAS */
str r6, [r1, #0x338] /* DRAM_SDCLK_0 */
- str r7, [r1, #0x5ac] /* GPR_ADDS*/
+ str r7, [r1, #0x5ac] /* GPR_ADDS*/
ldmea r0!, {r4-r7}
str r4, [r1, #0x5b0] /* DDRMODE_CTL */
@@ -136,27 +451,15 @@ r2: suspend_iram_base
str r0, [r1, #0x314] /* DRAM_DQM2 */
str r0, [r1, #0x318] /* DRAM_DQM3 */
- /* Make sure the Pull Ups are enabled.
- * So only reduce the drive stength, but
- * leave the pull-ups in the original state.
- * This is required for LPDDR2.
- */
- ldr r0, [r1, #0x344]
- orr r0, r0, #0x3000
- str r0, [r1, #0x344] /* DRAM_SDQS0 */
- str r0, [r1, #0x348] /* DRAM_SDQS1 */
- str r0, [r1, #0x34c] /* DRAM_SDQS2 */
- str r0, [r1, #0x350] /* DRAM_SDQS3 */
-
str r0, [r1, #0x5c4] /* GPR_B0DS */
str r0, [r1, #0x5cc] /* GPR_B1DS */
- str r0, [r1, #0x5d4] /* GPR_B2DS */
- str r0, [r1, #0x5d8] /* GPR_B3DS */
+ str r0, [r1, #0x5d4] /* GPR_B2DS */
+ str r0, [r1, #0x5d8] /* GPR_B3DS */
str r0, [r1, #0x300] /* DRAM_CAS */
str r0, [r1, #0x31c] /* DRAM_RAS */
str r0, [r1, #0x338] /* DRAM_SDCLK_0 */
- str r0, [r1, #0x5ac] /* GPR_ADDS*/
+ str r0, [r1, #0x5ac] /* GPR_ADDS*/
str r0, [r1, #0x5b0] /* DDRMODE_CTL */
str r0, [r1, #0x5c0] /* DDRMODE */
@@ -617,6 +920,10 @@ ENTRY(mx6_suspend)
suspend mode entry
*************************************************************/
mov r12, r3 /* Save CPU type to r12*/
+ mov r11, r0 /* Save the state in r11 */
+
+ cmp r12, #MXC_CPU_MX6SL
+ beq dormant
cmp r0, #0x1
bne dormant /* dormant mode */
@@ -666,14 +973,17 @@ suspend mode entry
never run to here
************************************************************/
b out /* exit standby */
-
+ /* Place the literal pool here so that
+ * literals are within 4KB range
+ */
+ .ltorg
/************************************************************
dormant entry, data save in stack, save sp in the src_gpr2
************************************************************/
dormant:
mov r3, r1
mov r0, r1
- add r0, r0, #IRAM_SUSPEND_SIZE /* 4K */
+ add r0, r0, #IRAM_SUSPEND_SIZE /* 8K */
ldr r4, =SRC_BASE_ADDR
add r4, r4, #PERIPBASE_VIRT
str r0, [r4, #SRC_GPR2_OFFSET] /* set src_gpr2 */
@@ -701,10 +1011,12 @@ saved register and context as below:
iram_suspend base */
mov r0, r2 /* get suspend_iram_base */
- add r0, r0, #IRAM_SUSPEND_SIZE /* 4K */
+ add r0, r0, #IRAM_SUSPEND_SIZE /* 8K */
mov r4, r12 @ Store cpu type
stmfd r0!, {r4}
+ mov r4, r11 @ Store state entered
+ stmfd r0!, {r4}
ldr r1, =MX6Q_IOMUXC_BASE_ADDR
add r1, r1, #PERIPBASE_VIRT
@@ -784,6 +1096,9 @@ set ddr iomux to low power mode
ldr r1, =SRC_BASE_ADDR
add r1, r1, #PERIPBASE_VIRT
ldr r0, [r1]
+ ldr r1, =CCM_BASE_ADDR
+ add r1, r1, #PERIPBASE_VIRT
+ ldr r0, [r1]
#ifdef CONFIG_MX6_INTER_LDO_BYPASS
ldr r1, =ANATOP_BASE_ADDR
add r1, r1, #PERIPBASE_VIRT
@@ -795,14 +1110,23 @@ set ddr iomux to low power mode
ldr r1, =MMDC_P0_BASE_ADDR
add r1, r1, #PERIPBASE_VIRT
- ldr r0, [r1, #MMDC_MAPSR_OFFSET]
- bic r0, #MMDC_MAPSR_PSD /* enable lpm */
- str r0, [r1, #MMDC_MAPSR_OFFSET]
-refresh:
- ldr r0, [r1, #MMDC_MAPSR_OFFSET] /* MMDC_MAPSR */
- and r0, r0, #MMDC_MAPSR_PSS /* PSS bit */
- cmp r0, #0
- beq refresh
+
+ /* Put DDR explicitly into self-refresh. */
+ /* Disable Automatic power savings. */
+ ldr r0, [r1, #0x404]
+ orr r0, r0, #0x01
+ str r0, [r1, #0x404]
+
+ /* Make the DDR explicitly enter self-refresh. */
+ ldr r0, [r1, #0x404]
+ orr r0, r0, #0x200000
+ str r0, [r1, #0x404]
+
+ poll_dvfs_set_1:
+ ldr r0, [r1, #0x404]
+ and r0, r0, #0x2000000
+ cmp r0, #0x2000000
+ bne poll_dvfs_set_1
/* set mmdc iomux to low power mode */
ldr r1, =MX6Q_IOMUXC_BASE_ADDR
@@ -822,6 +1146,22 @@ sl_io_set_lpm:
ddr_io_set_lpm_done:
+ /* Do Analog Power Optimizations
+ * for MX6SL in standby mode.
+ */
+ cmp r12, #MXC_CPU_MX6SL
+ bne no_analog_savings
+ cmp r11, #1
+ bne no_analog_savings
+
+ /* We are here because on
+ * MX6SL, we want to lower
+ * the power in Standby mode.
+ */
+ mx6sl_standy_saving_set
+
+no_analog_savings:
+
/****************************************************************
save resume pointer into SRC_GPR1
****************************************************************/
@@ -832,13 +1172,14 @@ save resume pointer into SRC_GPR1
ldr r1, =SRC_BASE_ADDR
add r1, r1, #PERIPBASE_VIRT
str r3, [r1, #SRC_GPR1_OFFSET]
+
#ifdef CONFIG_MX6_INTER_LDO_BYPASS
ldr r1, =ANATOP_BASE_ADDR
add r1, r1, #PERIPBASE_VIRT
- ldr r3, [r1, #0x140]
- bic r3, r3, #0x1f
- orr r3, r3, #0x1e
- str r3, [r1, #0x140]
+ ldr r4, [r1, #0x140]
+ bic r4, r4, #0x1f
+ orr r4, r4, #0x1e
+ str r4, [r1, #0x140]
#endif
/****************************************************************
execute a wfi instruction to let SOC go into stop mode.
@@ -863,11 +1204,26 @@ system immediately.
#endif
mov r0, r2 /* get suspend_iram_base */
- add r0, r0, #IRAM_SUSPEND_SIZE /* 4K */
+ add r0, r0, #IRAM_SUSPEND_SIZE /* 8K */
ldmea r0!, {r12} @ get cpu type to make ddr io
@ offset right
+ ldmea r0!, {r11} @ standby or mem
+
+ cmp r12, #MXC_CPU_MX6SL
+ bne no_analog_restore
+
+ cmp r11, #0x1
+ bne no_analog_restore
+
+ ldr r3, =CCM_BASE_ADDR
+ add r3, r3, #PERIPBASE_VIRT
+
+ /* Restore the analog settings. */
+ mx6sl_standby_savings_restore
+
+no_analog_restore:
ldr r1, =MX6Q_IOMUXC_BASE_ADDR
add r1, r1, #PERIPBASE_VIRT
@@ -882,8 +1238,46 @@ dl_io_restore:
b ddr_io_restore_done
sl_io_restore:
sl_ddr_io_restore
+ ldr r1, =MMDC_P0_BASE_ADDR
+ add r1, r1, #PERIPBASE_VIRT
+ /* reset read FIFO, RST_RD_FIFO */
+ ldr r7, =0x83c
+ ldr r6, [r1, r7]
+ orr r6, r6, #0x80000000
+ str r6, [r1, r7]
+fifo_reset1_wait:
+ ldr r6, [r1, r7]
+ and r6, r6, #0x80000000
+ cmp r6, #0
+ bne fifo_reset1_wait
+
+ /* reset FIFO a second time */
+ ldr r6, [r1, r7]
+ orr r6, r6, #0x80000000
+ str r6, [r1, r7]
+fifo_reset2_wait:
+ ldr r6, [r1, r7]
+ and r6, r6, #0x80000000
+ cmp r6, #0
+ bne fifo_reset2_wait
ddr_io_restore_done:
+ /* Ensure DDR exits self-refresh. */
+ ldr r6, [r1, #0x404]
+ bic r6, r6, #0x200000
+ str r6, [r1, #0x404]
+
+poll_dvfs_clear_1:
+ ldr r6, [r1, #0x404]
+ and r6, r6, #0x2000000
+ cmp r6, #0x2000000
+ beq poll_dvfs_clear_1
+
+ /* Enable Automatic power savings. */
+ ldr r6, [r1, #0x404]
+ bic r6, r6, #0x01
+ str r6, [r1, #0x404]
+
/* Add enough nops so that the
* prefetcher will not get instructions
* from DDR before its IO pads
@@ -930,6 +1324,7 @@ when SOC exit stop mode, arm core restart from here, currently
are running with MMU off.
****************************************************************/
resume:
+
#ifdef CONFIG_MX6_INTER_LDO_BYPASS
ldr r1, =ANATOP_BASE_ADDR
ldr r3, [r1, #0x140]
@@ -954,6 +1349,22 @@ resume:
ldmea r0!, {r12} @ get cpu type
+ ldmea r0!, {r11} @ standby or mem
+
+
+ cmp r12, #MXC_CPU_MX6SL
+ bne no_analog_restore1
+
+ cmp r11, #0x1
+ bne no_analog_restore1
+
+ ldr r1, =ANATOP_BASE_ADDR
+ ldr r3, =CCM_BASE_ADDR
+
+ /* Restore the analog settings. */
+ mx6sl_standby_pg_savings_restore
+
+no_analog_restore1:
/* Restore DDR IO */
ldr r1, =MX6Q_IOMUXC_BASE_ADDR
@@ -968,8 +1379,44 @@ dl_io_dsm_restore:
b ddr_io_restore_dsm_done
sl_io_dsm_restore:
sl_ddr_io_restore
+ ldr r1, =MMDC_P0_BASE_ADDR
+ /* reset read FIFO, RST_RD_FIFO */
+ ldr r7, =0x83c
+ ldr r6, [r1, r7]
+ orr r6, r6, #0x80000000
+ str r6, [r1, r7]
+dsm_fifo_reset1_wait:
+ ldr r6, [r1, r7]
+ and r6, r6, #0x80000000
+ cmp r6, #0
+ bne dsm_fifo_reset1_wait
+
+ /* reset FIFO a second time */
+ ldr r6, [r1, r7]
+ orr r6, r6, #0x80000000
+ str r6, [r1, r7]
+dsm_fifo_reset2_wait:
+ ldr r6, [r1, r7]
+ and r6, r6, #0x80000000
+ cmp r6, #0
+ bne dsm_fifo_reset2_wait
ddr_io_restore_dsm_done:
+ /* Ensure DDR exits self-refresh. */
+ ldr r6, [r1, #0x404]
+ bic r6, r6, #0x200000
+ str r6, [r1, #0x404]
+
+poll_dvfs_clear_2:
+ ldr r6, [r1, #0x404]
+ and r6, r6, #0x2000000
+ cmp r6, #0x2000000
+ beq poll_dvfs_clear_2
+
+ /* Enable Automatic power savings. */
+ ldr r6, [r1, #0x404]
+ bic r6, r6, #0x01
+ str r6, [r1, #0x404]
#ifdef CONFIG_CACHE_L2X0
ldr r2, =L2_BASE_ADDR
@@ -1084,11 +1531,11 @@ restore control register to enable cache
#endif
mov r8, lr
- push {r0}
+ push {r0-r12}
/* Set up the per-CPU stacks */
bl cpu_init
- pop {r0}
+ pop {r0-r12}
/*
* Restore the MMU table entry that was modified for
diff --git a/arch/arm/mach-mx6/mx6sl_arm2_pmic_pfuze100.c b/arch/arm/mach-mx6/mx6sl_arm2_pmic_pfuze100.c
index 134700a6d200..5cf34073bdc1 100644
--- a/arch/arm/mach-mx6/mx6sl_arm2_pmic_pfuze100.c
+++ b/arch/arm/mach-mx6/mx6sl_arm2_pmic_pfuze100.c
@@ -40,13 +40,13 @@
#define PFUZE100_I2C_ADDR (0x08)
/*SWBST*/
#define PFUZE100_SW1ASTANDBY 33
-#define PFUZE100_SW1ASTANDBY_STBY_VAL (0x16)
+#define PFUZE100_SW1ASTANDBY_STBY_VAL (0x19) /* 925mV */
#define PFUZE100_SW1ASTANDBY_STBY_M (0x3f<<0)
#define PFUZE100_SW1BSTANDBY 40
-#define PFUZE100_SW1BSTANDBY_STBY_VAL (0x16)
+#define PFUZE100_SW1BSTANDBY_STBY_VAL (0x19) /* 925mV */
#define PFUZE100_SW1BSTANDBY_STBY_M (0x3f<<0)
#define PFUZE100_SW1CSTANDBY 47
-#define PFUZE100_SW1CSTANDBY_STBY_VAL (0x16)
+#define PFUZE100_SW1CSTANDBY_STBY_VAL (0x19) /* 925mV */
#define PFUZE100_SW1CSTANDBY_STBY_M (0x3f<<0)
#define PFUZE100_SW2STANDBY 54
#define PFUZE100_SW2STANDBY_STBY_VAL 0x0
diff --git a/arch/arm/mach-mx6/mx6sl_evk_pmic_pfuze100.c b/arch/arm/mach-mx6/mx6sl_evk_pmic_pfuze100.c
index ee66541f8bff..981d149d7aee 100644
--- a/arch/arm/mach-mx6/mx6sl_evk_pmic_pfuze100.c
+++ b/arch/arm/mach-mx6/mx6sl_evk_pmic_pfuze100.c
@@ -40,13 +40,13 @@
#define PFUZE100_I2C_ADDR (0x08)
/*SWBST*/
#define PFUZE100_SW1ASTANDBY 33
-#define PFUZE100_SW1ASTANDBY_STBY_VAL (0x16)
+#define PFUZE100_SW1ASTANDBY_STBY_VAL (0x19) /* 925mv */
#define PFUZE100_SW1ASTANDBY_STBY_M (0x3f<<0)
#define PFUZE100_SW1BSTANDBY 40
-#define PFUZE100_SW1BSTANDBY_STBY_VAL (0x16)
+#define PFUZE100_SW1BSTANDBY_STBY_VAL (0x19) /* 925mv */
#define PFUZE100_SW1BSTANDBY_STBY_M (0x3f<<0)
#define PFUZE100_SW1CSTANDBY 47
-#define PFUZE100_SW1CSTANDBY_STBY_VAL (0x16)
+#define PFUZE100_SW1CSTANDBY_STBY_VAL (0x19) /* 925mv */
#define PFUZE100_SW1CSTANDBY_STBY_M (0x3f<<0)
#define PFUZE100_SW2STANDBY 54
#define PFUZE100_SW2STANDBY_STBY_VAL 0x0
@@ -143,7 +143,7 @@ static struct regulator_consumer_supply vgen5_consumers[] = {
};
static struct regulator_consumer_supply vgen6_consumers[] = {
{
- .supply = "VGEN6_3V3",
+ .supply = "VGEN6_2V8",
}
};
diff --git a/arch/arm/mach-mx6/mx6sl_wfi.S b/arch/arm/mach-mx6/mx6sl_wfi.S
index 89fe4e292352..dc4107dff7e8 100644
--- a/arch/arm/mach-mx6/mx6sl_wfi.S
+++ b/arch/arm/mach-mx6/mx6sl_wfi.S
@@ -235,15 +235,53 @@ mmdc_podf:
/* Set the DDR IO in LPM state. */
sl_ddr_io_set_lpm
- /* Set AHB to 8MHz., AXI to 3MHz */
- /* We want to ensure IPG_PERCLK to AHB
- * clk ratio is 1:2.5
+ /* Check if none of the PLLs are
+ * locked, except PLL1 which will get
+ * bypassed below.
+ * We should not be here if PLL2 is not
+ * bypassed.
*/
- /* Store the AXI/AHB podfs. */
+ ldr r7, =1
+ /* USB1 PLL3 */
+ ldr r6, [r3, #0x10]
+ and r6, r6, #0x80000000
+ cmp r6, #0x80000000
+ beq no_analog_saving
+
+ /* USB2 PLL7 */
+ ldr r6, [r3, #0x20]
+ and r6, r6, #0x80000000
+ cmp r6, #0x80000000
+ beq no_analog_saving
+
+ /* Audio PLL4 */
+ ldr r6, [r3, #0x70]
+ and r6, r6, #0x80000000
+ cmp r6, #0x80000000
+ beq no_analog_saving
+
+ /* Video PLL5 */
+ ldr r6, [r3, #0xA0]
+ and r6, r6, #0x80000000
+ cmp r6, #0x80000000
+ beq no_analog_saving
+
+ /* ENET PLL8 */
+ ldr r6, [r3, #0xE0]
+ and r6, r6, #0x80000000
+ cmp r6, #0x80000000
+ beq no_analog_saving
+
+ b cont
+
+no_analog_saving:
+ ldr r7, =0
+
+cont:
+ /*Set the AHB to 3MHz. AXI to 3MHz. */
ldr r9, [r2, #0x14]
mov r6, r9
- bic r6, r6, #0x1c00
- orr r6, r6, #0x800
+ orr r6, r6, #0x1c00
orr r6, r6, #0x70000
str r6, [r2, #0x14]
@@ -271,7 +309,7 @@ ahb_podf:
str r6, [r3, #0x04]
/* Set the ARM PODF to divide by 8. */
- /* IPG is at 4MHz here, we need ARM to
+ /* IPG is at 1.5MHz here, we need ARM to
* run at the 12:5 ratio (WAIT mode issue).
*/
ldr r6, =0x7
@@ -283,9 +321,62 @@ podf_loop:
cmp r6, #0x0
bne podf_loop
- /* Now do WFI. */
- dsb
+ /* Check if we can save some
+ * in the Analog section.
+ */
+ cmp r7, #0x1
+ bne do_wfi
+
+ /* Disable 1p1 brown out. */
+ ldr r6, [r3, #0x110]
+ bic r6, r6, #0x2
+ str r6, [r3, #0x110]
+
+ /* Enable the weak 2P5 */
+ ldr r6, [r3, #0x130]
+ orr r6, r6, #0x40000
+ str r6, [r3, #0x130]
+
+ /*Disable main 2p5. */
+ ldr r6, [r3, #0x130]
+ bic r6, r6, #0x1
+ str r6, [r3, #0x130]
+
+ /* Set the OSC bias current to -37.5%
+ * to drop the power on VDDHIGH.
+ */
+ ldr r6, [r3, #0x150]
+ orr r6, r6, #0xC000
+ str r6, [r3, #0x150]
+
+ /* Enable low power bandgap */
+ ldr r6, [r3, #0x260]
+ orr r6, r6, #0x20
+ str r6, [r3, #0x260]
+
+ /* turn off the bias current
+ * from the regular bandgap.
+ */
+ ldr r6, [r3, #0x260]
+ orr r6, r6, #0x80
+ str r6, [r3, #0x260]
+
+ /* Clear the REFTOP_SELFBIASOFF,
+ * self-bias circuit of the band gap.
+ * Per RM, should be cleared when
+ * band gap is powered down.
+ */
+ ldr r6, [r3, #0x150]
+ bic r6, r6, #0x8
+ str r6, [r3, #0x150]
+
+ /*Power down the regular bandgap. */
+ ldr r6, [r3, #0x150]
+ orr r6, r6, #0x1
+ str r6, [r3, #0x150]
+do_wfi:
+ /* Now do WFI. */
wfi
/* Set original ARM PODF back. */
@@ -297,6 +388,60 @@ podf_loop1:
cmp r6, #0x0
bne podf_loop1
+ /* Check if powered down
+ * analog components.
+ */
+ cmp r7, #0x1
+ bne skip_analog_restore
+
+ /*Power up the regular bandgap. */
+ ldr r6, [r3, #0x150]
+ bic r6, r6, #0x1
+ str r6, [r3, #0x150]
+
+ /* turn on the bias current
+ * from the regular bandgap.
+ */
+ ldr r6, [r3, #0x260]
+ bic r6, r6, #0x80
+ str r6, [r3, #0x260]
+
+ /* Disable the low power bandgap */
+ ldr r6, [r3, #0x260]
+ bic r6, r6, #0x20
+ str r6, [r3, #0x260]
+
+ /* Set the OSC bias current to max
+ * value for normal operation.
+ */
+ ldr r6, [r3, #0x150]
+ bic r6, r6, #0xC000
+ str r6, [r3, #0x150]
+
+ /*Enable main 2p5. */
+ ldr r6, [r3, #0x130]
+ orr r6, r6, #0x1
+ str r6, [r3, #0x130]
+
+ /* Ensure the 2P5 is up. */
+loop_2p5:
+ ldr r6, [r3, #0x130]
+ and r6, r6, #0x20000
+ cmp r6, #0x20000
+ bne loop_2p5
+
+ /* Disable the weak 2P5 */
+ ldr r6, [r3, #0x130]
+ bic r6, r6, #0x40000
+ str r6, [r3, #0x130]
+
+ /* Enable 1p1 brown out. */
+ ldr r6, [r3, #0x110]
+ orr r6, r6, #0x2
+ str r6, [r3, #0x110]
+
+skip_analog_restore:
+
/* Power up PLL1 and un-bypass it. */
ldr r6, =(1 << 12)
str r6, [r3, #0x08]
diff --git a/arch/arm/mach-mx6/pm.c b/arch/arm/mach-mx6/pm.c
index 45b2e6fffbeb..faf1a59ec2d6 100644
--- a/arch/arm/mach-mx6/pm.c
+++ b/arch/arm/mach-mx6/pm.c
@@ -73,7 +73,6 @@ static struct clk *cpu_clk;
static struct clk *axi_clk;
static struct clk *periph_clk;
static struct clk *axi_org_parent;
-static struct clk *gpu2d_core_clk;
static struct clk *pll3_usb_otg_main_clk;
static struct pm_platform_data *pm_data;
@@ -114,7 +113,6 @@ static u32 ccm_analog_pll3_480;
static u32 ccm_anadig_ana_misc2;
static bool usb_vbus_wakeup_enabled;
-
/*
* The USB VBUS wakeup should be disabled to avoid vbus wake system
* up due to vbus comparator is closed at weak 2p5 mode.
@@ -178,85 +176,6 @@ static void usb_power_up_handler(void)
}
}
-static void gpu_power_down(void)
-{
- int reg;
-
- /* enable power down request */
- reg = __raw_readl(gpc_base + GPC_PGC_GPU_PGCR_OFFSET);
- __raw_writel(reg | 0x1, gpc_base + GPC_PGC_GPU_PGCR_OFFSET);
- /* power down request */
- reg = __raw_readl(gpc_base + GPC_CNTR_OFFSET);
- __raw_writel(reg | 0x1, gpc_base + GPC_CNTR_OFFSET);
- /* disable clocks */
- __raw_writel(ccgr1 &
- ~MXC_CCM_CCGRx_CG12_MASK &
- ~MXC_CCM_CCGRx_CG13_MASK, MXC_CCM_CCGR1);
- __raw_writel(ccgr3 & ~MXC_CCM_CCGRx_CG15_MASK, MXC_CCM_CCGR3);
- __raw_writel(ccgr6 & ~MXC_CCM_CCGRx_CG7_MASK, MXC_CCM_CCGR6);
- /* power off pu */
- reg = __raw_readl(anatop_base + ANATOP_REG_CORE_OFFSET);
- reg &= ~0x0003fe00;
- __raw_writel(reg, anatop_base + ANATOP_REG_CORE_OFFSET);
-}
-
-static void gpu_power_up(void)
-{
- int reg;
- int i;
- /* power on pu */
- reg = __raw_readl(anatop_base + ANATOP_REG_CORE_OFFSET);
- reg &= ~0x0003fe00;
- reg |= 0x10 << 9; /* 1.1v */
- __raw_writel(reg, anatop_base + ANATOP_REG_CORE_OFFSET);
- mdelay(10);
-
- /* enable clocks */
- /* PLL2 PFD0 and PFD1 clock enable */
- __raw_writel(ccm_analog_pfd528 &
- ~ANADIG_PFD0_CLKGATE &
- ~ANADIG_PFD1_CLKGATE, PFD_528_BASE_ADDR);
-
- /* PLL3 480M clock enable which may be used by gpu2d*/
- if (clk_get_parent(gpu2d_core_clk) == pll3_usb_otg_main_clk) {
- __raw_writel(ccm_analog_pll3_480 |
- ANADIG_PLL_POWER_DOWN, PLL3_480_USB1_BASE_ADDR);
- __raw_writel(ccm_anadig_ana_misc2 &
- (~BM_ANADIG_ANA_MISC2_CONTROL0),
- MXC_PLL_BASE + HW_ANADIG_ANA_MISC2);
- for (i = 0; i < 100; i++) {
- if (!(__raw_readl(PLL3_480_USB1_BASE_ADDR) & ANADIG_PLL_LOCK))
- udelay(1);
- else
- break;
- }
- __raw_writel((ccm_analog_pll3_480 & (~ANADIG_PLL_BYPASS)) |
- ANADIG_PLL_ENABLE | ANADIG_PLL_POWER_DOWN,
- PLL3_480_USB1_BASE_ADDR);
- }
- /* gpu3d and gpu2d clock enable */
- __raw_writel(ccgr1 |
- MXC_CCM_CCGRx_CG12_MASK |
- MXC_CCM_CCGRx_CG13_MASK, MXC_CCM_CCGR1);
- /* tzasrc1 clock enable for gpu3d core clock */
- __raw_writel(ccgr2 | MXC_CCM_CCGRx_CG11_MASK, MXC_CCM_CCGR2);
- /* openvgaxi clock enable, mmdc_core_ipg_clk_p0 clock and
- mmdc_core_aclk_fast_core_p0 clock enable for gpu3d core clock */
- __raw_writel(ccgr3 |
- MXC_CCM_CCGRx_CG15_MASK |
- MXC_CCM_CCGRx_CG12_MASK |
- MXC_CCM_CCGRx_CG10_MASK, MXC_CCM_CCGR3);
- /* vpu clock enable */
- __raw_writel(ccgr6 | MXC_CCM_CCGRx_CG7_MASK, MXC_CCM_CCGR6);
-
- /* enable power up request */
- reg = __raw_readl(gpc_base + GPC_PGC_GPU_PGCR_OFFSET);
- __raw_writel(reg | 0x1, gpc_base + GPC_PGC_GPU_PGCR_OFFSET);
- /* power up request */
- reg = __raw_readl(gpc_base + GPC_CNTR_OFFSET);
- __raw_writel(reg | 0x2, gpc_base + GPC_CNTR_OFFSET);
- udelay(10);
-}
static void disp_power_down(void)
{
@@ -266,12 +185,32 @@ static void disp_power_down(void)
__raw_writel(0x1, gpc_base + GPC_PGC_DISP_PGCR_OFFSET);
__raw_writel(0x10, gpc_base + GPC_CNTR_OFFSET);
+
+ /* Disable EPDC/LCDIF pix clock, and EPDC/LCDIF/PXP axi clock */
+ __raw_writel(ccgr3 &
+ ~MXC_CCM_CCGRx_CG5_MASK &
+ ~MXC_CCM_CCGRx_CG4_MASK &
+ ~MXC_CCM_CCGRx_CG3_MASK &
+ ~MXC_CCM_CCGRx_CG2_MASK &
+ ~MXC_CCM_CCGRx_CG1_MASK, MXC_CCM_CCGR3);
+
}
}
static void disp_power_up(void)
{
if (cpu_is_mx6sl()) {
+ /*
+ * Need to enable EPDC/LCDIF pix clock, and
+ * EPDC/LCDIF/PXP axi clock before power up.
+ */
+ __raw_writel(ccgr3 |
+ MXC_CCM_CCGRx_CG5_MASK |
+ MXC_CCM_CCGRx_CG4_MASK |
+ MXC_CCM_CCGRx_CG3_MASK |
+ MXC_CCM_CCGRx_CG2_MASK |
+ MXC_CCM_CCGRx_CG1_MASK, MXC_CCM_CCGR3);
+
__raw_writel(0x0, gpc_base + GPC_PGC_DISP_PGCR_OFFSET);
__raw_writel(0x20, gpc_base + GPC_CNTR_OFFSET);
__raw_writel(0x1, gpc_base + GPC_PGC_DISP_SR_OFFSET);
@@ -343,6 +282,7 @@ static int mx6_suspend_enter(suspend_state_t state)
unsigned int cpu_type;
struct gic_dist_state gds;
struct gic_cpu_state gcs;
+ bool arm_pg = false;
if (cpu_is_mx6q())
cpu_type = MXC_CPU_MX6Q;
@@ -377,13 +317,19 @@ static int mx6_suspend_enter(suspend_state_t state)
switch (state) {
case PM_SUSPEND_MEM:
- gpu_power_down();
disp_power_down();
usb_power_down_handler();
mxc_cpu_lp_set(ARM_POWER_OFF);
+ arm_pg = true;
break;
case PM_SUSPEND_STANDBY:
- mxc_cpu_lp_set(STOP_POWER_OFF);
+ if (cpu_is_mx6sl()) {
+ disp_power_down();
+ usb_power_down_handler();
+ mxc_cpu_lp_set(STOP_XTAL_ON);
+ arm_pg = true;
+ } else
+ mxc_cpu_lp_set(STOP_POWER_OFF);
break;
default:
return -EINVAL;
@@ -399,7 +345,7 @@ static int mx6_suspend_enter(suspend_state_t state)
local_flush_tlb_all();
flush_cache_all();
- if (state == PM_SUSPEND_MEM) {
+ if (arm_pg) {
/* preserve gic state */
save_gic_dist_state(0, &gds);
save_gic_cpu_state(0, &gcs);
@@ -408,17 +354,21 @@ static int mx6_suspend_enter(suspend_state_t state)
suspend_in_iram(state, (unsigned long)iram_paddr,
(unsigned long)suspend_iram_base, cpu_type);
- if (state == PM_SUSPEND_MEM) {
+ if (arm_pg) {
/* restore gic registers */
restore_gic_dist_state(0, &gds);
restore_gic_cpu_state(0, &gcs);
+ }
+ if (state == PM_SUSPEND_MEM || (cpu_is_mx6sl())) {
usb_power_up_handler();
disp_power_up();
- gpu_power_up();
}
mx6_suspend_restore();
+ __raw_writel(BM_ANADIG_ANA_MISC0_STOP_MODE_CONFIG,
+ anatop_base + HW_ANADIG_ANA_MISC0_CLR);
+
if (pm_data && pm_data->suspend_exit)
pm_data->suspend_exit();
} else {
@@ -517,10 +467,10 @@ static int __init pm_init(void)
suspend_set_ops(&mx6_suspend_ops);
/* Move suspend routine into iRAM */
- cpaddr = (unsigned long)iram_alloc(SZ_4K, &iram_paddr);
+ cpaddr = (unsigned long)iram_alloc(SZ_8K, &iram_paddr);
/* Need to remap the area here since we want the memory region
to be executable. */
- suspend_iram_base = __arm_ioremap(iram_paddr, SZ_4K,
+ suspend_iram_base = __arm_ioremap(iram_paddr, SZ_8K,
MT_MEMORY_NONCACHED);
pr_info("cpaddr = %x suspend_iram_base=%x\n",
(unsigned int)cpaddr, (unsigned int)suspend_iram_base);
@@ -529,7 +479,7 @@ static int __init pm_init(void)
* Need to run the suspend code from IRAM as the DDR needs
* to be put into low power mode manually.
*/
- memcpy((void *)cpaddr, mx6_suspend, SZ_4K);
+ memcpy((void *)cpaddr, mx6_suspend, SZ_8K);
suspend_in_iram = (void *)suspend_iram_base;
@@ -548,11 +498,6 @@ static int __init pm_init(void)
printk(KERN_DEBUG "%s: failed to get periph_clk\n", __func__);
return PTR_ERR(periph_clk);
}
- gpu2d_core_clk = clk_get(NULL, "gpu2d_clk");
- if (IS_ERR(gpu2d_core_clk)) {
- printk(KERN_DEBUG "%s: failed to get gpu2d_clk\n", __func__);
- return PTR_ERR(periph_clk);
- }
pll3_usb_otg_main_clk = clk_get(NULL, "pll3_main_clk");
if (IS_ERR(pll3_usb_otg_main_clk)) {
printk(KERN_DEBUG "%s: failed to get pll3_main_clk\n", __func__);
diff --git a/arch/arm/mach-mx6/system.c b/arch/arm/mach-mx6/system.c
index 800c7cc4e8bd..533d4f5dbfab 100644
--- a/arch/arm/mach-mx6/system.c
+++ b/arch/arm/mach-mx6/system.c
@@ -51,6 +51,7 @@
extern unsigned int gpc_wake_irq[4];
static void __iomem *gpc_base = IO_ADDRESS(GPC_BASE_ADDR);
+static struct clk *ddr_clk;
volatile unsigned int num_cpu_idle;
volatile unsigned int num_cpu_idle_lock = 0x0;
@@ -132,8 +133,16 @@ void mxc_cpu_lp_set(enum mxc_cpu_pwr_mode mode)
stop_mode = 2;
}
break;
- case STOP_POWER_ON:
+ case STOP_XTAL_ON:
ccm_clpcr |= 0x2 << MXC_CCM_CLPCR_LPM_OFFSET;
+ ccm_clpcr |= MXC_CCM_CLPCR_VSTBY;
+ ccm_clpcr &= ~MXC_CCM_CLPCR_SBYOS;
+ if (cpu_is_mx6sl()) {
+ ccm_clpcr |= MXC_CCM_CLPCR_BYP_MMDC_CH0_LPM_HS;
+ ccm_clpcr |= MXC_CCM_CLPCR_BYPASS_PMIC_VFUNC_READY;
+ } else
+ ccm_clpcr |= MXC_CCM_CLPCR_BYP_MMDC_CH1_LPM_HS;
+ stop_mode = 3;
break;
default:
@@ -146,7 +155,7 @@ void mxc_cpu_lp_set(enum mxc_cpu_pwr_mode mode)
/* Power down and power up sequence */
__raw_writel(0xFFFFFFFF, gpc_base + GPC_PGC_CPU_PUPSCR_OFFSET);
__raw_writel(0xFFFFFFFF, gpc_base + GPC_PGC_CPU_PDNSCR_OFFSET);
- if (stop_mode == 2) {
+ if (stop_mode >= 2) {
/* dormant mode, need to power off the arm core */
__raw_writel(0x1, gpc_base + GPC_PGC_CPU_PDN_OFFSET);
if (cpu_is_mx6q() || cpu_is_mx6dl()) {
@@ -171,38 +180,48 @@ void mxc_cpu_lp_set(enum mxc_cpu_pwr_mode mode)
HW_ANADIG_REG_CORE);
}
} else {
- /* Disable VDDHIGH_IN to VDDSNVS_IN power path,
- * only used when VDDSNVS_IN is powered by dedicated
- * power rail */
- anatop_val = __raw_readl(anatop_base +
- HW_ANADIG_ANA_MISC0);
- anatop_val |= BM_ANADIG_ANA_MISC0_RTC_RINGOSC_EN;
- __raw_writel(anatop_val, anatop_base +
- HW_ANADIG_ANA_MISC0);
- /* We need to allow the memories to be clock gated
- * in STOP mode, else the power consumption will
- * be very high. */
- reg = __raw_readl(MXC_CCM_CGPR);
- reg |= MXC_CCM_CGPR_MEM_IPG_STOP_MASK;
- __raw_writel(reg, MXC_CCM_CGPR);
+ if (stop_mode == 2) {
+ /* Disable VDDHIGH_IN to VDDSNVS_IN
+ * power path, only used when VDDSNVS_IN
+ * is powered by dedicated
+ * power rail */
+ anatop_val = __raw_readl(anatop_base +
+ HW_ANADIG_ANA_MISC0);
+ anatop_val |= BM_ANADIG_ANA_MISC0_RTC_RINGOSC_EN;
+ __raw_writel(anatop_val, anatop_base +
+ HW_ANADIG_ANA_MISC0);
+ /* Need to enable pull down if 2P5 is disabled */
+ anatop_val = __raw_readl(anatop_base +
+ HW_ANADIG_REG_2P5);
+ anatop_val |= BM_ANADIG_REG_2P5_ENABLE_PULLDOWN;
+ __raw_writel(anatop_val, anatop_base +
+ HW_ANADIG_REG_2P5);
+ }
}
/* DL's TO1.0 can't support DSM mode due to ipg glitch */
- if (mx6dl_revision() != IMX_CHIP_REVISION_1_0)
+ if ((mx6dl_revision() != IMX_CHIP_REVISION_1_0)
+ && stop_mode != 3)
__raw_writel(__raw_readl(MXC_CCM_CCR) |
MXC_CCM_CCR_RBC_EN, MXC_CCM_CCR);
- /* Make sure we clear WB_COUNT and re-config it */
- __raw_writel(__raw_readl(MXC_CCM_CCR) &
- (~MXC_CCM_CCR_WB_COUNT_MASK) &
- (~MXC_CCM_CCR_REG_BYPASS_CNT_MASK), MXC_CCM_CCR);
- udelay(80);
- /* Reconfigurate WB and RBC counter */
- __raw_writel(__raw_readl(MXC_CCM_CCR) |
- (0x1 << MXC_CCM_CCR_WB_COUNT_OFFSET) |
- (0x20 << MXC_CCM_CCR_REG_BYPASS_CNT_OFFSET), MXC_CCM_CCR);
-
- /* Set WB_PER enable */
- ccm_clpcr |= MXC_CCM_CLPCR_WB_PER_AT_LPM;
+ if (stop_mode != 3) {
+ /* Make sure we clear WB_COUNT
+ * and re-config it.
+ */
+ __raw_writel(__raw_readl(MXC_CCM_CCR) &
+ (~MXC_CCM_CCR_WB_COUNT_MASK) &
+ (~MXC_CCM_CCR_REG_BYPASS_CNT_MASK), MXC_CCM_CCR);
+ udelay(80);
+ /* Reconfigurate WB and RBC counter, need to set WB counter
+ * to 0x7 to make sure it work normally */
+ __raw_writel(__raw_readl(MXC_CCM_CCR) |
+ (0x7 << MXC_CCM_CCR_WB_COUNT_OFFSET) |
+ (0x20 << MXC_CCM_CCR_REG_BYPASS_CNT_OFFSET),
+ MXC_CCM_CCR);
+
+ /* Set WB_PER enable */
+ ccm_clpcr |= MXC_CCM_CLPCR_WB_PER_AT_LPM;
+ }
}
if (cpu_is_mx6sl() ||
(mx6q_revision() > IMX_CHIP_REVISION_1_1) ||
@@ -253,7 +272,14 @@ void arch_idle_single_core(void)
ca9_do_idle();
} else {
if (low_bus_freq_mode || audio_bus_freq_mode) {
- if (cpu_is_mx6sl() && low_bus_freq_mode) {
+ u32 ddr_usecount;
+ if (ddr_clk == NULL)
+ ddr_clk = clk_get(NULL ,
+ "mmdc_ch0_axi");
+ ddr_usecount = clk_get_usecount(ddr_clk);
+
+ if (cpu_is_mx6sl() && low_bus_freq_mode
+ && ddr_usecount == 1) {
/* In this mode PLL2 i already in bypass,
* ARM is sourced from PLL1. The code in IRAM
* will set ARM to be sourced from STEP_CLK
@@ -272,17 +298,41 @@ void arch_idle_single_core(void)
* is at 12MHz. This is valid for audio mode on
* MX6SL, and all low power modes on MX6DLS.
*/
- /* PLL1_SW_CLK is sourced from PLL2_PFD2400MHz
- * at this point. Move it to bypassed PLL1.
- */
- reg = __raw_readl(MXC_CCM_CCSR);
- reg &= ~MXC_CCM_CCSR_PLL1_SW_CLK_SEL;
- __raw_writel(reg, MXC_CCM_CCSR);
-
+ if (cpu_is_mx6sl() && low_bus_freq_mode) {
+ /* ARM is from PLL1, need to switch to
+ * STEP_CLK sourced from 24MHz.
+ */
+ /* Swtich STEP_CLK to 24MHz. */
+ reg = __raw_readl(MXC_CCM_CCSR);
+ reg &= ~MXC_CCM_CCSR_STEP_SEL;
+ __raw_writel(reg, MXC_CCM_CCSR);
+ /* Set PLL1_SW_CLK to be from
+ *STEP_CLK.
+ */
+ reg = __raw_readl(MXC_CCM_CCSR);
+ reg |= MXC_CCM_CCSR_PLL1_SW_CLK_SEL;
+ __raw_writel(reg, MXC_CCM_CCSR);
+
+ } else {
+ /* PLL1_SW_CLK is sourced from
+ * PLL2_PFD2_400MHz at this point.
+ * Move it to bypassed PLL1.
+ */
+ reg = __raw_readl(MXC_CCM_CCSR);
+ reg &= ~MXC_CCM_CCSR_PLL1_SW_CLK_SEL;
+ __raw_writel(reg, MXC_CCM_CCSR);
+ }
ca9_do_idle();
- reg |= MXC_CCM_CCSR_PLL1_SW_CLK_SEL;
- __raw_writel(reg, MXC_CCM_CCSR);
+ if (cpu_is_mx6sl() && low_bus_freq_mode) {
+ /* Set PLL1_SW_CLK to be from PLL1 */
+ reg = __raw_readl(MXC_CCM_CCSR);
+ reg &= ~MXC_CCM_CCSR_PLL1_SW_CLK_SEL;
+ __raw_writel(reg, MXC_CCM_CCSR);
+ } else {
+ reg |= MXC_CCM_CCSR_PLL1_SW_CLK_SEL;
+ __raw_writel(reg, MXC_CCM_CCSR);
+ }
}
} else {
/*
diff --git a/arch/arm/mach-mx6/usb.h b/arch/arm/mach-mx6/usb.h
index 6914246826f6..f796e7dad87c 100644
--- a/arch/arm/mach-mx6/usb.h
+++ b/arch/arm/mach-mx6/usb.h
@@ -30,9 +30,6 @@ extern void gpio_usbotg_utmi_inactive(void);
extern void __init mx6_usb_dr_init(void);
extern bool usb_icbug_swfix_need(void);
-extern int usb_stop_mode_refcount(bool enable);
-extern void usb_stop_mode_lock(void);
-extern void usb_stop_mode_unlock(void);
extern void __init mx6_usb_h2_init(void);
extern void __init mx6_usb_h3_init(void);
diff --git a/arch/arm/mach-mx6/usb_dr.c b/arch/arm/mach-mx6/usb_dr.c
index 8fe9700a658f..7b79d98c7d5c 100644
--- a/arch/arm/mach-mx6/usb_dr.c
+++ b/arch/arm/mach-mx6/usb_dr.c
@@ -173,9 +173,6 @@ static int usb_phy_enable(struct fsl_usb2_platform_data *pdata)
static int usbotg_init_ext(struct platform_device *pdev)
{
struct clk *usb_clk;
-#ifdef CONFIG_USB_EHCI_ARC_OTG
- void __iomem *anatop_base_addr = MX6_IO_ADDRESS(ANATOP_BASE_ADDR);
-#endif
u32 ret;
/* at mx6q: this clock is AHB clock for usb core */
@@ -201,12 +198,6 @@ static int usbotg_init_ext(struct platform_device *pdev)
mdelay(3);
}
otg_used++;
-#ifdef CONFIG_USB_EHCI_ARC_OTG
- usb_stop_mode_lock();
- if (usb_stop_mode_refcount(true) == 1)
- __raw_writel(BM_ANADIG_ANA_MISC0_STOP_MODE_CONFIG, anatop_base_addr + HW_ANADIG_ANA_MISC0_SET);
- usb_stop_mode_unlock();
-#endif
return ret;
}
@@ -214,9 +205,6 @@ static int usbotg_init_ext(struct platform_device *pdev)
static void usbotg_uninit_ext(struct platform_device *pdev)
{
struct fsl_usb2_platform_data *pdata = pdev->dev.platform_data;
-#ifdef CONFIG_USB_EHCI_ARC_OTG
- void __iomem *anatop_base_addr = MX6_IO_ADDRESS(ANATOP_BASE_ADDR);
-#endif
clk_disable(usb_phy1_clk);
clk_put(usb_phy1_clk);
@@ -226,12 +214,6 @@ static void usbotg_uninit_ext(struct platform_device *pdev)
usbotg_uninit(pdata);
otg_used--;
-#ifdef CONFIG_USB_EHCI_ARC_OTG
- usb_stop_mode_lock();
- if (usb_stop_mode_refcount(false) == 0)
- __raw_writel(BM_ANADIG_ANA_MISC0_STOP_MODE_CONFIG, anatop_base_addr + HW_ANADIG_ANA_MISC0_CLR);
- usb_stop_mode_unlock();
-#endif
}
static void usbotg_clock_gate(bool on)
@@ -247,6 +229,13 @@ static void usbotg_clock_gate(bool on)
pr_debug("usb_oh3_clk:%d, usb_phy_clk1_ref_count:%d\n", clk_get_usecount(usb_oh3_clk), clk_get_usecount(usb_phy1_clk));
}
+static void dr_platform_phy_power_on(void)
+{
+ void __iomem *anatop_base_addr = MX6_IO_ADDRESS(ANATOP_BASE_ADDR);
+ __raw_writel(BM_ANADIG_ANA_MISC0_STOP_MODE_CONFIG,
+ anatop_base_addr + HW_ANADIG_ANA_MISC0_SET);
+}
+
void mx6_set_otghost_vbus_func(driver_vbus_func driver_vbus)
{
dr_utmi_config.platform_driver_vbus = driver_vbus;
@@ -643,6 +632,7 @@ void __init mx6_usb_dr_init(void)
dr_utmi_config.is_wakeup_event = _is_host_wakeup;
dr_utmi_config.wakeup_pdata = &dr_wakeup_config;
dr_utmi_config.wakeup_handler = host_wakeup_handler;
+ dr_utmi_config.platform_phy_power_on = dr_platform_phy_power_on;
pdev = imx6q_add_fsl_ehci_otg(&dr_utmi_config);
dr_wakeup_config.usb_pdata[1] = pdev->dev.platform_data;
#endif
@@ -657,6 +647,7 @@ void __init mx6_usb_dr_init(void)
dr_utmi_config.wakeup_pdata = &dr_wakeup_config;
dr_utmi_config.wakeup_handler = device_wakeup_handler;
dr_utmi_config.charger_base_addr = anatop_base_addr;
+ dr_utmi_config.platform_phy_power_on = dr_platform_phy_power_on;
pdev = imx6q_add_fsl_usb2_udc(&dr_utmi_config);
dr_wakeup_config.usb_pdata[2] = pdev->dev.platform_data;
#endif
diff --git a/arch/arm/mach-mx6/usb_h1.c b/arch/arm/mach-mx6/usb_h1.c
index bece29f7d44b..f86a4f42b0bd 100644
--- a/arch/arm/mach-mx6/usb_h1.c
+++ b/arch/arm/mach-mx6/usb_h1.c
@@ -90,6 +90,13 @@ static void usbh1_internal_phy_clock_gate(bool on)
}
}
+static void usbh1_platform_phy_power_on(void)
+{
+ void __iomem *anatop_base_addr = MX6_IO_ADDRESS(ANATOP_BASE_ADDR);
+ __raw_writel(BM_ANADIG_ANA_MISC0_STOP_MODE_CONFIG,
+ anatop_base_addr + HW_ANADIG_ANA_MISC0_SET);
+}
+
static int usb_phy_enable(struct fsl_usb2_platform_data *pdata)
{
u32 tmp;
@@ -134,7 +141,6 @@ static int fsl_usb_host_init_ext(struct platform_device *pdev)
{
int ret;
struct clk *usb_clk;
- void __iomem *anatop_base_addr = MX6_IO_ADDRESS(ANATOP_BASE_ADDR);
usb_clk = clk_get(NULL, "usboh3_clk");
clk_enable(usb_clk);
usb_oh3_clk = usb_clk;
@@ -146,25 +152,19 @@ static int fsl_usb_host_init_ext(struct platform_device *pdev)
}
usbh1_internal_phy_clock_gate(true);
usb_phy_enable(pdev->dev.platform_data);
- usb_stop_mode_lock();
- if (usb_stop_mode_refcount(true) == 1)
- __raw_writel(BM_ANADIG_ANA_MISC0_STOP_MODE_CONFIG, anatop_base_addr + HW_ANADIG_ANA_MISC0_SET);
- usb_stop_mode_unlock();
+
return 0;
}
static void fsl_usb_host_uninit_ext(struct platform_device *pdev)
{
struct fsl_usb2_platform_data *pdata = pdev->dev.platform_data;
- void __iomem *anatop_base_addr = MX6_IO_ADDRESS(ANATOP_BASE_ADDR);
+
fsl_usb_host_uninit(pdata);
clk_disable(usb_oh3_clk);
clk_put(usb_oh3_clk);
- usb_stop_mode_lock();
- if (usb_stop_mode_refcount(false) == 0)
- __raw_writel(BM_ANADIG_ANA_MISC0_STOP_MODE_CONFIG, anatop_base_addr + HW_ANADIG_ANA_MISC0_CLR);
- usb_stop_mode_unlock();
+
}
static void usbh1_clock_gate(bool on)
@@ -374,6 +374,7 @@ static struct fsl_usb2_platform_data usbh1_config = {
.phy_lowpower_suspend = _phy_lowpower_suspend,
.is_wakeup_event = _is_usbh1_wakeup,
.wakeup_handler = h1_wakeup_handler,
+ .platform_phy_power_on = usbh1_platform_phy_power_on,
.transceiver = "utmi",
.phy_regs = USB_PHY1_BASE_ADDR,
};
diff --git a/arch/arm/plat-mxc/cpufreq.c b/arch/arm/plat-mxc/cpufreq.c
index e7278d9501a5..cc26b7adbc76 100755
--- a/arch/arm/plat-mxc/cpufreq.c
+++ b/arch/arm/plat-mxc/cpufreq.c
@@ -95,15 +95,19 @@ int set_cpu_freq(int freq)
ret = regulator_set_voltage(soc_regulator, soc_volt,
soc_volt);
if (ret < 0) {
- printk(KERN_DEBUG "COULD NOT SET SOC VOLTAGE!!!!\n");
+ printk(KERN_DEBUG
+ "COULD NOT SET SOC VOLTAGE!!!!\n");
return ret;
}
}
- if (!IS_ERR(pu_regulator)) {
+ /*if pu_regulator is enabled, it will be tracked with VDDARM*/
+ if (!IS_ERR(pu_regulator) &&
+ regulator_is_enabled(pu_regulator)) {
ret = regulator_set_voltage(pu_regulator, pu_volt,
pu_volt);
if (ret < 0) {
- printk(KERN_DEBUG "COULD NOT SET PU VOLTAGE!!!!\n");
+ printk(KERN_DEBUG
+ "COULD NOT SET PU VOLTAGE!!!!\n");
return ret;
}
}
@@ -132,15 +136,19 @@ int set_cpu_freq(int freq)
ret = regulator_set_voltage(soc_regulator, soc_volt,
soc_volt);
if (ret < 0) {
- printk(KERN_DEBUG "COULD NOT SET SOC VOLTAGE BACK!!!!\n");
+ printk(KERN_DEBUG
+ "COULD NOT SET SOC VOLTAGE BACK!!!!\n");
return ret;
}
}
- if (!IS_ERR(pu_regulator)) {
+ /*if pu_regulator is enabled, it will be tracked with VDDARM*/
+ if (!IS_ERR(pu_regulator) &&
+ regulator_is_enabled(pu_regulator)) {
ret = regulator_set_voltage(pu_regulator, pu_volt,
pu_volt);
if (ret < 0) {
- printk(KERN_DEBUG "COULD NOT SET PU VOLTAGE!!!!\n");
+ printk(KERN_DEBUG
+ "COULD NOT SET PU VOLTAGE!!!!\n");
return ret;
}
}
diff --git a/arch/arm/plat-mxc/devices/Kconfig b/arch/arm/plat-mxc/devices/Kconfig
index bdea66b7a1f4..2e666bac3afd 100755
--- a/arch/arm/plat-mxc/devices/Kconfig
+++ b/arch/arm/plat-mxc/devices/Kconfig
@@ -185,3 +185,6 @@ config IMX_HAVE_PLATFORM_IMX_VDOA
config IMX_HAVE_PLATFORM_IMX_PCIE
bool
+
+config IMX_HAVE_PLATFORM_IMX_FSL_CSI
+ bool
diff --git a/arch/arm/plat-mxc/devices/Makefile b/arch/arm/plat-mxc/devices/Makefile
index 41287783cb80..102eeaaff38b 100755
--- a/arch/arm/plat-mxc/devices/Makefile
+++ b/arch/arm/plat-mxc/devices/Makefile
@@ -66,4 +66,5 @@ obj-$(CONFIG_IMX_HAVE_PLATFORM_IMX_MIPI_DSI) += platform-imx-mipi_dsi.o
obj-$(CONFIG_IMX_HAVE_PLATFORM_IMX_MIPI_CSI2) += platform-imx-mipi_csi2.o
obj-$(CONFIG_IMX_HAVE_PLATFORM_IMX_VDOA) += platform-imx-vdoa.o
obj-$(CONFIG_IMX_HAVE_PLATFORM_IMX_PCIE) += platform-imx-pcie.o
+obj-$(CONFIG_IMX_HAVE_PLATFORM_IMX_FSL_CSI) += platform-imx-fsl-csi.o
obj-y += platform-imx-pmu.o
diff --git a/arch/arm/plat-mxc/devices/platform-dma.c b/arch/arm/plat-mxc/devices/platform-dma.c
index b2cba3db6d6d..7f731954192e 100644
--- a/arch/arm/plat-mxc/devices/platform-dma.c
+++ b/arch/arm/plat-mxc/devices/platform-dma.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2011 Freescale Semiconductor, Inc. All Rights Reserved.
+ * Copyright (C) 2011-2012 Freescale Semiconductor, Inc. All Rights Reserved.
*
* 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
@@ -13,19 +13,19 @@
#include <mach/devices-common.h>
#ifdef CONFIG_SOC_IMX50
-const struct imx_dma_data imx50_dma_data __initconst = {
+const struct imx_dma_res_data imx50_dma_res_data __initconst = {
.iobase = MX50_APBHDMA_BASE_ADDR,
};
#endif
#ifdef CONFIG_SOC_IMX6Q
-const struct imx_dma_data imx6q_dma_data __initconst = {
+const struct imx_dma_res_data imx6q_dma_res_data __initconst = {
.iobase = APBH_DMA_ARB_BASE_ADDR,
};
#endif
struct platform_device *__init imx_add_dma(
- const struct imx_dma_data *data)
+ const struct imx_dma_res_data *data)
{
struct resource res[] = {
{
diff --git a/arch/arm/plat-mxc/devices/platform-imx-fsl-csi.c b/arch/arm/plat-mxc/devices/platform-imx-fsl-csi.c
new file mode 100644
index 000000000000..8b6601ccc5a0
--- /dev/null
+++ b/arch/arm/plat-mxc/devices/platform-imx-fsl-csi.c
@@ -0,0 +1,55 @@
+/*
+ * Copyright (C) 2012 Freescale Semiconductor, Inc. All Rights Reserved.
+ */
+
+/*
+ * 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.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#include <asm/sizes.h>
+#include <mach/hardware.h>
+#include <mach/devices-common.h>
+
+#define imx_fsl_csi_data_entry_single(soc, size) \
+ { \
+ .iobase = soc ## _CSI_BASE_ADDR, \
+ .irq = soc ## _INT_CSI, \
+ .iosize = size, \
+ }
+
+#ifdef CONFIG_SOC_IMX6SL
+const struct imx_fsl_csi_data imx6sl_csi_data __initconst =
+ imx_fsl_csi_data_entry_single(MX6SL, SZ_16K);
+#endif
+
+struct platform_device *__init imx_add_fsl_csi(
+ const struct imx_fsl_csi_data *data)
+{
+ struct resource res[] = {
+ {
+ .start = data->iobase,
+ .end = data->iobase + data->iosize - 1,
+ .flags = IORESOURCE_MEM,
+ }, {
+ .start = data->irq,
+ .end = data->irq,
+ .flags = IORESOURCE_IRQ,
+ },
+ };
+
+ return imx_add_platform_device("fsl_csi", -1,
+ res, ARRAY_SIZE(res), NULL, 0);
+}
+
diff --git a/arch/arm/plat-mxc/devices/platform-imx-uart.c b/arch/arm/plat-mxc/devices/platform-imx-uart.c
index ecfadc3060ea..7f70dc9f8e07 100644
--- a/arch/arm/plat-mxc/devices/platform-imx-uart.c
+++ b/arch/arm/plat-mxc/devices/platform-imx-uart.c
@@ -137,6 +137,18 @@ const struct imx_imx_uart_1irq_data imx6q_imx_uart_data[] __initconst = {
};
#endif /* ifdef CONFIG_SOC_IMX6Q */
+#ifdef CONFIG_SOC_IMX6SL
+const struct imx_imx_uart_1irq_data imx6sl_imx_uart_data[] __initconst = {
+#define imx6sl_imx_uart_data_entry(_id, _hwid) \
+ imx_imx_uart_1irq_data_entry(MX6SL, _id, _hwid, SZ_4K)
+ imx6sl_imx_uart_data_entry(0, 1),
+ imx6sl_imx_uart_data_entry(1, 2),
+ imx6sl_imx_uart_data_entry(2, 3),
+ imx6sl_imx_uart_data_entry(3, 4),
+ imx6sl_imx_uart_data_entry(4, 5),
+};
+#endif /* ifdef CONFIG_SOC_IMX6SL */
+
struct platform_device *__init imx_add_imx_uart_3irq(
const struct imx_imx_uart_3irq_data *data,
const struct imxuart_platform_data *pdata)
diff --git a/arch/arm/plat-mxc/include/mach/devices-common.h b/arch/arm/plat-mxc/include/mach/devices-common.h
index 99ef8abee1e3..1ff68bd8b6dd 100755
--- a/arch/arm/plat-mxc/include/mach/devices-common.h
+++ b/arch/arm/plat-mxc/include/mach/devices-common.h
@@ -25,10 +25,10 @@ static inline struct platform_device *imx_add_platform_device(
name, id, res, num_resources, data, size_data, 0);
}
-struct imx_dma_data {
+struct imx_dma_res_data {
resource_size_t iobase;
};
-struct platform_device *__init imx_add_dma(const struct imx_dma_data *data);
+struct platform_device *__init imx_add_dma(const struct imx_dma_res_data *data);
#include <linux/fec.h>
struct imx_fec_data {
@@ -690,3 +690,11 @@ struct platform_device *__init imx_add_pcie(
const struct imx_pcie_platform_data *pdata);
void __init imx_add_imx_armpmu(void);
+
+struct imx_fsl_csi_data {
+ resource_size_t iobase;
+ resource_size_t iosize;
+ resource_size_t irq;
+};
+struct platform_device *__init imx_add_fsl_csi(
+ const struct imx_fsl_csi_data *data);
diff --git a/arch/arm/plat-mxc/include/mach/iomux-mx6sl.h b/arch/arm/plat-mxc/include/mach/iomux-mx6sl.h
index 296df42d3ef7..90de1dd8f4fb 100755
--- a/arch/arm/plat-mxc/include/mach/iomux-mx6sl.h
+++ b/arch/arm/plat-mxc/include/mach/iomux-mx6sl.h
@@ -77,6 +77,9 @@
#define MX6SL_ADU_PAD_CTRL (PAD_CTL_PKE | PAD_CTL_PUE | \
PAD_CTL_DSE_40ohm | PAD_CTL_PUS_100K_DOWN | \
PAD_CTL_HYS | PAD_CTL_SPEED_MED)
+#define MX6SL_CHG_PAD_CTRL (PAD_CTL_HYS | PAD_CTL_PKE | PAD_CTL_PUE | \
+ PAD_CTL_PUS_47K_UP)
+
#define MX6SL_PAD_AUD_MCLK 0x02A4
#define MX6SL_PAD_AUD_RXD 0x02AC
@@ -510,7 +513,7 @@
IOMUX_PAD(0x0364, 0x0074, 7, 0x0000, 0, NO_PAD_CTRL)
#define MX6SL_PAD_ECSPI2_MISO__GPIO_4_14 \
- IOMUX_PAD(0x0368, 0x0078, 5, 0x0000, 0, NO_PAD_CTRL)
+ IOMUX_PAD(0x0368, 0x0078, 5, 0x0000, 0, MX6SL_CHG_PAD_CTRL)
#define MX6SL_PAD_ECSPI2_MISO__USB_USBOTG1_OC \
IOMUX_PAD(0x0368, 0x0078, 6, 0x0824, 0, NO_PAD_CTRL)
#define MX6SL_PAD_ECSPI2_MISO__TPSMP_HDATA_23 \
@@ -541,7 +544,7 @@
#define MX6SL_PAD_ECSPI2_MOSI__USDHC1_VSELECT \
IOMUX_PAD(0x036C, 0x007C, 4, 0x0000, 0, MX6SL_USDHC_PAD_CTRL)
#define MX6SL_PAD_ECSPI2_MOSI__GPIO_4_13 \
- IOMUX_PAD(0x036C, 0x007C, 5, 0x0000, 0, NO_PAD_CTRL)
+ IOMUX_PAD(0x036C, 0x007C, 5, 0x0000, 0, MX6SL_CHG_PAD_CTRL)
#define MX6SL_PAD_ECSPI2_MOSI__ANATOP_ANATOP_TESTO_1 \
IOMUX_PAD(0x036C, 0x007C, 6, 0x0000, 0, NO_PAD_CTRL)
#define MX6SL_PAD_ECSPI2_MOSI__TPSMP_HDATA_22 \
@@ -579,7 +582,7 @@
#define MX6SL_PAD_ECSPI2_SS0__USDHC1_CD \
IOMUX_PAD(0x0374, 0x0084, 4, 0x0828, 0, MX6SL_USDHC_PAD_CTRL)
#define MX6SL_PAD_ECSPI2_SS0__GPIO_4_15 \
- IOMUX_PAD(0x0374, 0x0084, 5, 0x0000, 0, NO_PAD_CTRL)
+ IOMUX_PAD(0x0374, 0x0084, 5, 0x0000, 0, MX6SL_CHG_PAD_CTRL)
#define MX6SL_PAD_ECSPI2_SS0__USB_USBOTG1_PWR \
IOMUX_PAD(0x0374, 0x0084, 6, 0x0000, 0, NO_PAD_CTRL)
#define MX6SL_PAD_ECSPI2_SS0__PL301_SIM_MX6SL_PER1_HADDR_24 \
diff --git a/arch/arm/plat-mxc/include/mach/mx6.h b/arch/arm/plat-mxc/include/mach/mx6.h
index aaf8b998ca63..dfb3f6489cc1 100644
--- a/arch/arm/plat-mxc/include/mach/mx6.h
+++ b/arch/arm/plat-mxc/include/mach/mx6.h
@@ -77,7 +77,7 @@
#define MX6Q_IRAM_BASE_ADDR IRAM_BASE_ADDR
/* The last 4K is for cpu hotplug to workaround wdog issue*/
#define MX6Q_IRAM_SIZE (SZ_256K - SZ_4K)
-#define MX6DL_IRAM_SIZE (SZ_128K - SZ_4K)
+#define MX6DL_MX6SL_IRAM_SIZE (SZ_128K - SZ_4K)
/* Blocks connected via pl301periph */
#define ROMCP_ARB_BASE_ADDR 0x00000000
@@ -145,6 +145,7 @@
#define MX6SL_UART5_BASE_ADDR (ATZ1_BASE_ADDR + 0x18000) /* MX6SL */
#define UART1_BASE_ADDR (ATZ1_BASE_ADDR + 0x20000) /* slot 8 */
#define ESAI1_BASE_ADDR (ATZ1_BASE_ADDR + 0x24000) /* slot 9 */
+#define MX6SL_UART1_BASE_ADDR (ATZ1_BASE_ADDR + 0x20000) /* MX6SL */
#define MX6SL_UART2_BASE_ADDR (ATZ1_BASE_ADDR + 0x24000) /* MX6SL */
#define MX6Q_SSI1_BASE_ADDR (ATZ1_BASE_ADDR + 0x28000) /* slot 10 */
#define MX6Q_SSI2_BASE_ADDR (ATZ1_BASE_ADDR + 0x2C000) /* slot 11 */
@@ -215,6 +216,14 @@
/* ARM Cortex A9 MPCore Platform */
#define MX6Q_A9_PLATFRM_BASE (ARM_BASE_ADDR + 0x20000)
+/* ARM Cortex A9 PTM */
+#define MX6Q_PTM0_BASE_ADDR 0x0215C000
+#define MX6Q_PTM1_BASE_ADDR 0x0215D000
+#define MX6Q_PTM2_BASE_ADDR 0x0215E000
+#define MX6Q_PTM3_BASE_ADDR 0x0215F000
+#define MX6Q_FUNNEL_BASE_ADDR 0x02144000
+#define MX6Q_ETB_BASE_ADDR 0x02141000
+
#define MX6Q_PL301_BASE_ADDR (AIPS2_OFF_BASE_ADDR + 0x0000)
#define MX6Q_USB_OTG_BASE_ADDR (AIPS2_OFF_BASE_ADDR + 0x4000)
#define MX6Q_USB_HS1_BASE_ADDR (AIPS2_OFF_BASE_ADDR + 0x4200)
@@ -327,6 +336,7 @@
#define MX6SL_INT_SPDC 38
#define MX6Q_INT_IPU2_ERR 39
#define MX6DL_INT_CSI 39
+#define MX6SL_INT_CSI 39
#define MX6Q_INT_IPU2_SYN 40
#define MXC_INT_GPU3D_IRQ 41
#define MXC_INT_GPU2D_IRQ 42
@@ -474,6 +484,11 @@
#define MX6Q_INT_UART2 MXC_INT_UART2_ANDED
#define MX6Q_INT_UART3 MXC_INT_UART3_ANDED
#define MX6Q_INT_UART4 MXC_INT_UART4_ANDED
+#define MX6SL_INT_UART1 MXC_INT_UART1_ANDED
+#define MX6SL_INT_UART2 MXC_INT_UART2_ANDED
+#define MX6SL_INT_UART3 MXC_INT_UART3_ANDED
+#define MX6SL_INT_UART4 MXC_INT_UART4_ANDED
+#define MX6SL_INT_UART5 MXC_INT_UART5_ANDED
#define MX6Q_INT_FEC MXC_INT_ENET1
#define MX6Q_INT_DSI MXC_INT_DSI
diff --git a/arch/arm/plat-mxc/include/mach/mxc.h b/arch/arm/plat-mxc/include/mach/mxc.h
index 23159090ace8..4260d4a25c2c 100755
--- a/arch/arm/plat-mxc/include/mach/mxc.h
+++ b/arch/arm/plat-mxc/include/mach/mxc.h
@@ -266,8 +266,8 @@ enum mxc_cpu_pwr_mode {
WAIT_CLOCKED, /* wfi only */
WAIT_UNCLOCKED, /* WAIT */
WAIT_UNCLOCKED_POWER_OFF, /* WAIT + SRPG */
- STOP_POWER_ON, /* just STOP */
- STOP_POWER_OFF, /* STOP + SRPG */
+ STOP_XTAL_ON, /* STOP + SRPG + XTAL_ON*/
+ STOP_POWER_OFF, /* STOP + XTAL_OFF */
ARM_POWER_OFF, /* STOP + SRPG + ARM power off */
};
diff --git a/arch/arm/plat-mxc/usb_common.c b/arch/arm/plat-mxc/usb_common.c
index d85d8d663571..97d963a54a54 100755
--- a/arch/arm/plat-mxc/usb_common.c
+++ b/arch/arm/plat-mxc/usb_common.c
@@ -53,9 +53,7 @@ typedef void (*driver_vbus_func)(bool);
void __iomem *imx_otg_base;
static driver_vbus_func s_driver_vbus;
-static int stop_mode_refcount;
-DEFINE_MUTEX(usb_common_mutex);
EXPORT_SYMBOL(imx_otg_base);
#define MXC_NUMBER_USB_TRANSCEIVER 6
@@ -73,41 +71,6 @@ bool usb_icbug_swfix_need(void)
}
EXPORT_SYMBOL(usb_icbug_swfix_need);
-/*
- * The Mx6 phy sometimes work abnormally after system suspend/resume if the 1V1 is off.
- * So we should keep the 1V1 active during the system suspend if any USB host enabled.
- * Set stop_mode_config when any USB host enabled by default, it will impact on system power.
- * #define DISABLE_STOP_MODE will disable the feature.
- */
-#ifndef DISABLE_STOP_MODE
-int usb_stop_mode_refcount(bool enable)
-{
- if (enable)
- stop_mode_refcount++;
- else
- stop_mode_refcount--;
- return stop_mode_refcount;
-}
-#else
-int usb_stop_mode_refcount(bool enable)
-{
- return 0;
-}
-#endif
-EXPORT_SYMBOL(usb_stop_mode_refcount);
-
-void usb_stop_mode_lock(void)
-{
- mutex_lock(&usb_common_mutex);
-}
-EXPORT_SYMBOL(usb_stop_mode_lock);
-
-void usb_stop_mode_unlock(void)
-{
- mutex_unlock(&usb_common_mutex);
-}
-EXPORT_SYMBOL(usb_stop_mode_unlock);
-
void mx6_set_host1_vbus_func(driver_vbus_func driver_vbus)
{
s_driver_vbus = driver_vbus;
diff --git a/drivers/dma/pxp/pxp_dma_v2.c b/drivers/dma/pxp/pxp_dma_v2.c
index 87b8f558ae8c..b74f62cac032 100644
--- a/drivers/dma/pxp/pxp_dma_v2.c
+++ b/drivers/dma/pxp/pxp_dma_v2.c
@@ -264,6 +264,9 @@ static void pxp_set_ctrl(struct pxps *pxp)
case PXP_PIX_FMT_YUV422P:
fmt_ctrl = BV_PXP_PS_CTRL_FORMAT__YUV422;
break;
+ case PXP_PIX_FMT_UYVY:
+ fmt_ctrl = BV_PXP_PS_CTRL_FORMAT__UYVY1P422;
+ break;
default:
fmt_ctrl = 0;
}
@@ -654,7 +657,7 @@ static void pxp_set_csc(struct pxps *pxp)
/* CSC1 - YUV->RGB */
__raw_writel(0x84ab01f0, pxp->base + HW_PXP_CSC1_COEF0);
- __raw_writel(0x01230204, pxp->base + HW_PXP_CSC1_COEF1);
+ __raw_writel(0x01980204, pxp->base + HW_PXP_CSC1_COEF1);
__raw_writel(0x0730079c, pxp->base + HW_PXP_CSC1_COEF2);
/* CSC2 - Bypass */
diff --git a/drivers/media/video/mxc/capture/Kconfig b/drivers/media/video/mxc/capture/Kconfig
index a7b14cb23b9b..febe9d874fb8 100644
--- a/drivers/media/video/mxc/capture/Kconfig
+++ b/drivers/media/video/mxc/capture/Kconfig
@@ -13,7 +13,7 @@ config VIDEO_MXC_EMMA_CAMERA
default y
config VIDEO_MXC_CSI_CAMERA
- tristate "MX25 CSI camera support"
+ tristate "CSI camera support"
depends on !VIDEO_MXC_EMMA_CAMERA
config VIDEO_MXC_CSI_DMA
diff --git a/drivers/media/video/mxc/capture/csi_v4l2_capture.c b/drivers/media/video/mxc/capture/csi_v4l2_capture.c
index eb824ddf5eb3..ada6d5e8afbd 100644
--- a/drivers/media/video/mxc/capture/csi_v4l2_capture.c
+++ b/drivers/media/video/mxc/capture/csi_v4l2_capture.c
@@ -1,5 +1,5 @@
/*
- * Copyright 2009-2011 Freescale Semiconductor, Inc. All Rights Reserved.
+ * Copyright 2009-2012 Freescale Semiconductor, Inc. All Rights Reserved.
*/
/*
@@ -15,7 +15,7 @@
* @file drivers/media/video/mxc/capture/csi_v4l2_capture.c
* This file is derived from mxc_v4l2_capture.c
*
- * @brief MX25 Video For Linux 2 driver
+ * @brief Video For Linux 2 capture driver
*
* @ingroup MXC_V4L2_CAPTURE
*/
@@ -61,6 +61,198 @@ static struct v4l2_int_device csi_v4l2_int_device = {
},
};
+/* Callback function triggered after PxP receives an EOF interrupt */
+static void pxp_dma_done(void *arg)
+{
+ struct pxp_tx_desc *tx_desc = to_tx_desc(arg);
+ struct dma_chan *chan = tx_desc->txd.chan;
+ struct pxp_channel *pxp_chan = to_pxp_channel(chan);
+ cam_data *cam = pxp_chan->client;
+
+ /* This call will signal wait_for_completion_timeout() */
+ complete(&cam->pxp_tx_cmpl);
+}
+
+static bool chan_filter(struct dma_chan *chan, void *arg)
+{
+ if (imx_dma_is_pxp(chan))
+ return true;
+ else
+ return false;
+}
+
+/* Function to request PXP DMA channel */
+static int pxp_chan_init(cam_data *cam)
+{
+ dma_cap_mask_t mask;
+ struct dma_chan *chan;
+
+ /* Request a free channel */
+ dma_cap_zero(mask);
+ dma_cap_set(DMA_SLAVE, mask);
+ dma_cap_set(DMA_PRIVATE, mask);
+ chan = dma_request_channel(mask, chan_filter, NULL);
+ if (!chan) {
+ pr_err("Unsuccessfully request channel!\n");
+ return -EBUSY;
+ }
+
+ cam->pxp_chan = to_pxp_channel(chan);
+ cam->pxp_chan->client = cam;
+
+ init_completion(&cam->pxp_tx_cmpl);
+
+ return 0;
+}
+
+/*
+ * Function to call PxP DMA driver and send our new V4L2 buffer
+ * through the PxP and PxP will process this buffer in place.
+ * Note: This is a blocking call, so upon return the PxP tx should be complete.
+ */
+static int pxp_process_update(cam_data *cam)
+{
+ dma_cookie_t cookie;
+ struct scatterlist *sg = cam->sg;
+ struct dma_chan *dma_chan;
+ struct pxp_tx_desc *desc;
+ struct dma_async_tx_descriptor *txd;
+ struct pxp_config_data *pxp_conf = &cam->pxp_conf;
+ struct pxp_proc_data *proc_data = &cam->pxp_conf.proc_data;
+ int i, ret;
+ int length;
+
+ pr_debug("Starting PxP Send Buffer\n");
+
+ /* First, check to see that we have acquired a PxP Channel object */
+ if (cam->pxp_chan == NULL) {
+ /*
+ * PxP Channel has not yet been created and initialized,
+ * so let's go ahead and try
+ */
+ ret = pxp_chan_init(cam);
+ if (ret) {
+ /*
+ * PxP channel init failed, and we can't use the
+ * PxP until the PxP DMA driver has loaded, so we abort
+ */
+ pr_err("PxP chan init failed\n");
+ return -ENODEV;
+ }
+ }
+
+ /*
+ * Init completion, so that we can be properly informed of
+ * the completion of the PxP task when it is done.
+ */
+ init_completion(&cam->pxp_tx_cmpl);
+
+ dma_chan = &cam->pxp_chan->dma_chan;
+
+ txd = dma_chan->device->device_prep_slave_sg(dma_chan, sg, 2,
+ DMA_TO_DEVICE,
+ DMA_PREP_INTERRUPT);
+ if (!txd) {
+ pr_err("Error preparing a DMA transaction descriptor.\n");
+ return -EIO;
+ }
+
+ txd->callback_param = txd;
+ txd->callback = pxp_dma_done;
+
+ /*
+ * Configure PxP for processing of new v4l2 buf
+ */
+ pxp_conf->s0_param.pixel_fmt = PXP_PIX_FMT_UYVY;
+ pxp_conf->s0_param.color_key = -1;
+ pxp_conf->s0_param.color_key_enable = false;
+ pxp_conf->s0_param.width = cam->v2f.fmt.pix.width;
+ pxp_conf->s0_param.height = cam->v2f.fmt.pix.height;
+
+ pxp_conf->ol_param[0].combine_enable = false;
+
+ proc_data->srect.top = 0;
+ proc_data->srect.left = 0;
+ proc_data->srect.width = pxp_conf->s0_param.width;
+ proc_data->srect.height = pxp_conf->s0_param.height;
+
+ proc_data->drect.top = 0;
+ proc_data->drect.left = 0;
+ proc_data->drect.width = proc_data->srect.width;
+ proc_data->drect.height = proc_data->srect.height;
+ proc_data->scaling = 0;
+ proc_data->hflip = 0;
+ proc_data->vflip = 0;
+ proc_data->rotate = 0;
+ proc_data->bgcolor = 0;
+
+ pxp_conf->out_param.pixel_fmt = PXP_PIX_FMT_RGB565;
+ pxp_conf->out_param.width = proc_data->drect.width;
+ pxp_conf->out_param.height = proc_data->drect.height;
+
+ if (cam->rotation >= IPU_ROTATE_90_RIGHT)
+ pxp_conf->out_param.stride = pxp_conf->out_param.height;
+ else
+ pxp_conf->out_param.stride = pxp_conf->out_param.width;
+
+ desc = to_tx_desc(txd);
+ length = desc->len;
+ for (i = 0; i < length; i++) {
+ if (i == 0) {/* S0 */
+ memcpy(&desc->proc_data, proc_data,
+ sizeof(struct pxp_proc_data));
+ pxp_conf->s0_param.paddr = sg_dma_address(&sg[0]);
+ memcpy(&desc->layer_param.s0_param, &pxp_conf->s0_param,
+ sizeof(struct pxp_layer_param));
+ } else if (i == 1) {
+ pxp_conf->out_param.paddr = sg_dma_address(&sg[1]);
+ memcpy(&desc->layer_param.out_param,
+ &pxp_conf->out_param,
+ sizeof(struct pxp_layer_param));
+ }
+
+ desc = desc->next;
+ }
+
+ /* Submitting our TX starts the PxP processing task */
+ cookie = txd->tx_submit(txd);
+ if (cookie < 0) {
+ pr_err("Error sending FB through PxP\n");
+ return -EIO;
+ }
+
+ cam->txd = txd;
+
+ /* trigger PxP */
+ dma_async_issue_pending(dma_chan);
+
+ return 0;
+}
+
+static int pxp_complete_update(cam_data *cam)
+{
+ int ret;
+ /*
+ * Wait for completion event, which will be set
+ * through our TX callback function.
+ */
+ ret = wait_for_completion_timeout(&cam->pxp_tx_cmpl, HZ / 10);
+ if (ret <= 0) {
+ pr_warning("PxP operation failed due to %s\n",
+ ret < 0 ? "user interrupt" : "timeout");
+ dma_release_channel(&cam->pxp_chan->dma_chan);
+ cam->pxp_chan = NULL;
+ return ret ? : -ETIMEDOUT;
+ }
+
+ dma_release_channel(&cam->pxp_chan->dma_chan);
+ cam->pxp_chan = NULL;
+
+ pr_debug("TX completed\n");
+
+ return 0;
+}
+
/*!
* Camera V4l2 callback function.
*
@@ -666,6 +858,23 @@ static int csi_v4l_dqueue(cam_data *cam, struct v4l2_buffer *buf)
buf->flags = frame->buffer.flags;
buf->m = cam->frame[frame->index].buffer.m;
+ /*
+ * Note:
+ * If want to do preview on LCD, use PxP CSC to convert from UYVY
+ * to RGB565; but for encoding, usually we don't use RGB format.
+ */
+ if (cam->v2f.fmt.pix.pixelformat == V4L2_PIX_FMT_RGB565) {
+ /* PxP processes it in place */
+ sg_dma_address(&cam->sg[0]) = buf->m.offset;
+ sg_dma_address(&cam->sg[1]) = buf->m.offset;
+ retval = pxp_process_update(cam);
+ if (retval) {
+ pr_err("Unable to submit PxP update task.\n");
+ return retval;
+ }
+ pxp_complete_update(cam);
+ }
+
return retval;
}
@@ -1186,8 +1395,8 @@ static void init_camera_struct(cam_data *cam)
/* Default everything to 0 */
memset(cam, 0, sizeof(cam_data));
- init_MUTEX(&cam->param_lock);
- init_MUTEX(&cam->busy_lock);
+ sema_init(&cam->param_lock, 1);
+ sema_init(&cam->busy_lock, 1);
cam->video_dev = video_device_alloc();
if (cam->video_dev == NULL)
@@ -1382,6 +1591,7 @@ static void csi_v4l2_master_detach(struct v4l2_int_device *slave)
*/
static __init int camera_init(void)
{
+ struct scatterlist *sg;
u8 err = 0;
/* Register the device driver structure. */
@@ -1430,6 +1640,11 @@ static __init int camera_init(void)
pr_debug(" Video device registered: %s #%d\n",
g_cam->video_dev->name, g_cam->video_dev->minor);
+ g_cam->pxp_chan = NULL;
+ /* Initialize Scatter-gather list containing 2 buffer addresses. */
+ sg = g_cam->sg;
+ sg_init_table(sg, 2);
+
return err;
}
diff --git a/drivers/media/video/mxc/capture/fsl_csi.c b/drivers/media/video/mxc/capture/fsl_csi.c
index dba35c4499e2..33a82242e95e 100644
--- a/drivers/media/video/mxc/capture/fsl_csi.c
+++ b/drivers/media/video/mxc/capture/fsl_csi.c
@@ -1,5 +1,5 @@
/*
- * Copyright 2009-2011 Freescale Semiconductor, Inc. All Rights Reserved.
+ * Copyright 2009-2012 Freescale Semiconductor, Inc. All Rights Reserved.
*/
/*
@@ -20,6 +20,7 @@
*/
#include <linux/types.h>
#include <linux/init.h>
+#include <linux/platform_device.h>
#include <linux/device.h>
#include <linux/err.h>
#include <linux/interrupt.h>
@@ -27,11 +28,14 @@
#include <linux/delay.h>
#include <linux/module.h>
#include <linux/clk.h>
+#include <linux/sched.h>
#include <mach/clock.h>
#include "mxc_v4l2_capture.h"
#include "fsl_csi.h"
+void __iomem *csi_regbase;
+static int irq_nr;
static bool g_csi_mclk_on;
static csi_irq_callback_t g_callback;
static void *g_callback_data;
@@ -164,7 +168,7 @@ void csi_start_callback(void *data)
{
cam_data *cam = (cam_data *) data;
- if (request_irq(MXC_INT_CSI, csi_irq_handler, 0, "csi", cam) < 0)
+ if (request_irq(irq_nr, csi_irq_handler, 0, "csi", cam) < 0)
pr_debug("CSI error: irq request fail\n");
}
@@ -174,7 +178,7 @@ void csi_stop_callback(void *data)
{
cam_data *cam = (cam_data *) data;
- free_irq(MXC_INT_CSI, cam);
+ free_irq(irq_nr, cam);
}
EXPORT_SYMBOL(csi_stop_callback);
@@ -254,10 +258,32 @@ void csi_mclk_disable(void)
__raw_writel(__raw_readl(CSI_CSICR1) & ~BIT_MCLKEN, CSI_CSICR1);
}
-int32_t __init csi_init_module(void)
+static int __devinit csi_probe(struct platform_device *pdev)
{
int ret = 0;
struct clk *per_clk;
+ struct resource *res;
+
+ res = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
+ if (!res) {
+ dev_err(&pdev->dev, "No csi irq found.\n");
+ ret = -ENODEV;
+ goto err;
+ }
+ irq_nr = res->start;
+
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ if (!res) {
+ dev_err(&pdev->dev, "No csi base address found.\n");
+ ret = -ENODEV;
+ goto err;
+ }
+ csi_regbase = ioremap(res->start, resource_size(res));
+ if (!csi_regbase) {
+ dev_err(&pdev->dev, "ioremap failed with csi base\n");
+ ret = -ENOMEM;
+ goto err;
+ }
csihw_reset();
csi_init_interface();
@@ -271,12 +297,34 @@ int32_t __init csi_init_module(void)
clk_enable(per_clk);
csi_mclk_recalc(&csi_mclk);
+err:
return ret;
}
-void __exit csi_cleanup_module(void)
+static int __devexit csi_remove(struct platform_device *pdev)
{
clk_disable(&csi_mclk);
+ iounmap(csi_regbase);
+
+ return 0;
+}
+
+static struct platform_driver csi_driver = {
+ .driver = {
+ .name = "fsl_csi",
+ },
+ .probe = csi_probe,
+ .remove = __devexit_p(csi_remove),
+};
+
+int32_t __init csi_init_module(void)
+{
+ return platform_driver_register(&csi_driver);
+}
+
+void __exit csi_cleanup_module(void)
+{
+ platform_driver_unregister(&csi_driver);
}
module_init(csi_init_module);
diff --git a/drivers/media/video/mxc/capture/fsl_csi.h b/drivers/media/video/mxc/capture/fsl_csi.h
index 00c389892224..8dfce286fe53 100644
--- a/drivers/media/video/mxc/capture/fsl_csi.h
+++ b/drivers/media/video/mxc/capture/fsl_csi.h
@@ -1,5 +1,5 @@
/*
- * Copyright 2009-2011 Freescale Semiconductor, Inc. All Rights Reserved.
+ * Copyright 2009-2012 Freescale Semiconductor, Inc. All Rights Reserved.
*/
/*
@@ -102,23 +102,22 @@
#define CSI_MCLK_I2C 8
#endif
-#define CSI_CSICR1 (IO_ADDRESS(CSI_BASE_ADDR))
-#define CSI_CSICR2 (IO_ADDRESS(CSI_BASE_ADDR + 0x4))
-#define CSI_CSICR3 (IO_ADDRESS(CSI_BASE_ADDR + 0x8))
-#define CSI_STATFIFO (IO_ADDRESS(CSI_BASE_ADDR + 0xC))
-#define CSI_CSIRXFIFO (IO_ADDRESS(CSI_BASE_ADDR + 0x10))
-#define CSI_CSIRXCNT (IO_ADDRESS(CSI_BASE_ADDR + 0x14))
-#define CSI_CSISR (IO_ADDRESS(CSI_BASE_ADDR + 0x18))
-
-#define CSI_CSIDBG (IO_ADDRESS(CSI_BASE_ADDR + 0x1C))
-#define CSI_CSIDMASA_STATFIFO (IO_ADDRESS(CSI_BASE_ADDR + 0x20))
-#define CSI_CSIDMATS_STATFIFO (IO_ADDRESS(CSI_BASE_ADDR + 0x24))
-#define CSI_CSIDMASA_FB1 (IO_ADDRESS(CSI_BASE_ADDR + 0x28))
-#define CSI_CSIDMASA_FB2 (IO_ADDRESS(CSI_BASE_ADDR + 0x2C))
-#define CSI_CSIFBUF_PARA (IO_ADDRESS(CSI_BASE_ADDR + 0x30))
-#define CSI_CSIIMAG_PARA (IO_ADDRESS(CSI_BASE_ADDR + 0x34))
-
-#define CSI_CSIRXFIFO_PHYADDR (CSI_BASE_ADDR + 0x10)
+extern void __iomem *csi_regbase;
+#define CSI_CSICR1 (csi_regbase)
+#define CSI_CSICR2 (csi_regbase + 0x4)
+#define CSI_CSICR3 (csi_regbase + 0x8)
+#define CSI_STATFIFO (csi_regbase + 0xC)
+#define CSI_CSIRXFIFO (csi_regbase + 0x10)
+#define CSI_CSIRXCNT (csi_regbase + 0x14)
+#define CSI_CSISR (csi_regbase + 0x18)
+
+#define CSI_CSIDBG (csi_regbase + 0x1C)
+#define CSI_CSIDMASA_STATFIFO (csi_regbase + 0x20)
+#define CSI_CSIDMATS_STATFIFO (csi_regbase + 0x24)
+#define CSI_CSIDMASA_FB1 (csi_regbase + 0x28)
+#define CSI_CSIDMASA_FB2 (csi_regbase + 0x2C)
+#define CSI_CSIFBUF_PARA (csi_regbase + 0x30)
+#define CSI_CSIIMAG_PARA (csi_regbase + 0x34)
static inline void csi_clear_status(unsigned long status)
{
diff --git a/drivers/media/video/mxc/capture/mt9v111.c b/drivers/media/video/mxc/capture/mt9v111.c
index 4305c56c82d9..3ae65db04486 100644
--- a/drivers/media/video/mxc/capture/mt9v111.c
+++ b/drivers/media/video/mxc/capture/mt9v111.c
@@ -1,5 +1,5 @@
/*
- * Copyright 2004-2011 Freescale Semiconductor, Inc. All Rights Reserved.
+ * Copyright 2004-2012 Freescale Semiconductor, Inc. All Rights Reserved.
*/
/*
@@ -879,7 +879,7 @@ static int ioctl_dev_init(struct v4l2_int_device *s)
gpio_sensor_active();
- set_mclk_rate(&clock_rate);
+ set_mclk_rate(&clock_rate, 0);
mt9v111_rate_cal(&reset_frame_rate, clock_rate);
mt9v111_sensor_lib(mt9v111_device.coreReg, mt9v111_device.ifpReg);
diff --git a/drivers/media/video/mxc/capture/mxc_v4l2_capture.h b/drivers/media/video/mxc/capture/mxc_v4l2_capture.h
index 27f8a78a93b3..034fd168290f 100644
--- a/drivers/media/video/mxc/capture/mxc_v4l2_capture.h
+++ b/drivers/media/video/mxc/capture/mxc_v4l2_capture.h
@@ -31,6 +31,10 @@
#include <linux/list.h>
#include <linux/ipu.h>
#include <linux/mxc_v4l2.h>
+#include <linux/completion.h>
+#include <linux/dmaengine.h>
+#include <linux/pxp_dma.h>
+#include <mach/dma.h>
#include <mach/ipu-v3.h>
#include <media/v4l2-dev.h>
@@ -205,6 +209,14 @@ typedef struct _cam_data {
struct v4l2_int_device *self;
int sensor_index;
void *ipu;
+
+ /* v4l2 buf elements related to PxP DMA */
+ struct completion pxp_tx_cmpl;
+ struct pxp_channel *pxp_chan;
+ struct pxp_config_data pxp_conf;
+ struct dma_async_tx_descriptor *txd;
+ dma_cookie_t cookie;
+ struct scatterlist sg[2];
} cam_data;
struct sensor_data {
@@ -232,11 +244,5 @@ struct sensor_data {
void (*io_init)(void);
};
-#if defined(CONFIG_MXC_IPU_V1) || defined(CONFIG_VIDEO_MXC_EMMA_CAMERA) \
- || defined(CONFIG_VIDEO_MXC_CSI_CAMERA_MODULE) \
- || defined(CONFIG_VIDEO_MXC_CSI_CAMERA)
-void set_mclk_rate(uint32_t *p_mclk_freq);
-#else
void set_mclk_rate(uint32_t *p_mclk_freq, uint32_t csi);
-#endif
#endif /* __MXC_V4L2_CAPTURE_H__ */
diff --git a/drivers/media/video/mxc/capture/ov2640.c b/drivers/media/video/mxc/capture/ov2640.c
index a0a050bca2e9..24ebd5027ff1 100644
--- a/drivers/media/video/mxc/capture/ov2640.c
+++ b/drivers/media/video/mxc/capture/ov2640.c
@@ -1,5 +1,5 @@
/*
- * Copyright 2005-2011 Freescale Semiconductor, Inc. All Rights Reserved.
+ * Copyright 2005-2012 Freescale Semiconductor, Inc. All Rights Reserved.
*/
/*
@@ -801,7 +801,7 @@ static int ioctl_dev_init(struct v4l2_int_device *s)
pr_debug(" Setting mclk to %d MHz\n",
tgt_xclk / 1000000);
- set_mclk_rate(&ov2640_data.mclk);
+ set_mclk_rate(&ov2640_data.mclk, 0);
return ov2640_init_mode(sensor);
}
diff --git a/drivers/media/video/mxc/capture/sensor_clock.c b/drivers/media/video/mxc/capture/sensor_clock.c
index 8004aeee5dc2..150659fa5dc0 100644
--- a/drivers/media/video/mxc/capture/sensor_clock.c
+++ b/drivers/media/video/mxc/capture/sensor_clock.c
@@ -26,31 +26,6 @@
#include <mach/hardware.h>
#include <asm/mach-types.h>
-#if defined(CONFIG_MXC_IPU_V1) || defined(CONFIG_VIDEO_MXC_EMMA_CAMERA) \
- || defined(CONFIG_VIDEO_MXC_CSI_CAMERA_MODULE) \
- || defined(CONFIG_VIDEO_MXC_CSI_CAMERA)
-/*
- * set_mclk_rate
- *
- * @param p_mclk_freq mclk frequence
- *
- */
-void set_mclk_rate(uint32_t *p_mclk_freq)
-{
- struct clk *clk;
- uint32_t freq = 0;
-
- clk = clk_get(NULL, "csi_clk");
-
- freq = clk_round_rate(clk, *p_mclk_freq);
- clk_set_rate(clk, freq);
-
- *p_mclk_freq = freq;
-
- clk_put(clk);
- pr_debug("mclk frequency = %d\n", *p_mclk_freq);
-}
-#else
/*
* set_mclk_rate
*
@@ -81,6 +56,8 @@ void set_mclk_rate(uint32_t *p_mclk_freq, uint32_t csi)
pr_err("invalid csi num %d\n", csi);
return;
};
+ } else if (cpu_is_mx25() || cpu_is_mx6sl()) { /* only has CSI0 */
+ mclk = "csi_clk";
} else {
if (csi == 0) {
mclk = "csi_mclk1";
@@ -102,7 +79,6 @@ void set_mclk_rate(uint32_t *p_mclk_freq, uint32_t csi)
clk_put(clk);
pr_debug("%s frequency = %d\n", mclk, *p_mclk_freq);
}
-#endif
/* Exported symbols for modules. */
EXPORT_SYMBOL(set_mclk_rate);
diff --git a/drivers/media/video/mxc/output/mxc_vout.c b/drivers/media/video/mxc/output/mxc_vout.c
index 366d27a92286..388c4b39570f 100644
--- a/drivers/media/video/mxc/output/mxc_vout.c
+++ b/drivers/media/video/mxc/output/mxc_vout.c
@@ -861,6 +861,7 @@ static int mxc_vout_open(struct file *file)
vout->win_pos.x = 0;
vout->win_pos.y = 0;
+ vout->release = true;
}
file->private_data = vout;
@@ -973,6 +974,7 @@ static inline int vdoaipu_try_task(struct mxc_vout_output *vout)
int is_1080p_stream;
size_t size;
struct ipu_task *ipu_task = &vout->task;
+ struct ipu_crop *icrop = &ipu_task->input.crop;
struct ipu_task *vdoa_task = &vout->vdoa_task;
u32 deinterlace = 0;
u32 in_fmt;
@@ -981,15 +983,23 @@ static inline int vdoaipu_try_task(struct mxc_vout_output *vout)
deinterlace = 1;
memset(vdoa_task, 0, sizeof(*vdoa_task));
- memcpy(&vdoa_task->input, &ipu_task->input, sizeof(ipu_task->input));
vdoa_task->output.format = IPU_PIX_FMT_NV12;
- vdoa_task->output.width = ipu_task->input.crop.w;
- vdoa_task->output.height = ipu_task->input.crop.h;
- vdoa_task->output.crop.w = ipu_task->input.crop.w;
- vdoa_task->output.crop.h = ipu_task->input.crop.h;
-
- size = PAGE_ALIGN(ipu_task->input.crop.w *
- ipu_task->input.crop.h *
+ memcpy(&vdoa_task->input, &ipu_task->input,
+ sizeof(ipu_task->input));
+ if ((icrop->w % IPU_PIX_FMT_TILED_NV12_MBALIGN) ||
+ (icrop->h % IPU_PIX_FMT_TILED_NV12_MBALIGN)) {
+ vdoa_task->input.crop.w =
+ ALIGN(icrop->w, IPU_PIX_FMT_TILED_NV12_MBALIGN);
+ vdoa_task->input.crop.h =
+ ALIGN(icrop->h, IPU_PIX_FMT_TILED_NV12_MBALIGN);
+ }
+ vdoa_task->output.width = vdoa_task->input.crop.w;
+ vdoa_task->output.height = vdoa_task->input.crop.h;
+ vdoa_task->output.crop.w = vdoa_task->input.crop.w;
+ vdoa_task->output.crop.h = vdoa_task->input.crop.h;
+
+ size = PAGE_ALIGN(vdoa_task->input.crop.w *
+ vdoa_task->input.crop.h *
fmt_to_bpp(vdoa_task->output.format)/8);
if (size > vout->vdoa_work.size) {
if (vout->vdoa_work.vaddr)
@@ -1029,6 +1039,7 @@ static int mxc_vout_try_task(struct mxc_vout_output *vout)
u32 o_height = 0;
u32 ocrop_h = 0;
bool tiled_fmt = false;
+ bool tiled_need_pp = false;
vout->vdoa_1080p = CHECK_TILED_1080P_DISPLAY(vout);
if (vout->vdoa_1080p) {
@@ -1041,10 +1052,17 @@ static int mxc_vout_try_task(struct mxc_vout_output *vout)
if ((IPU_PIX_FMT_TILED_NV12 == input->format) ||
(IPU_PIX_FMT_TILED_NV12F == input->format)) {
- crop->w -= crop->w % IPU_PIX_FMT_TILED_NV12_MBALIGN;
- crop->h -= crop->h % IPU_PIX_FMT_TILED_NV12_MBALIGN;
- crop->pos.x -= crop->pos.x % IPU_PIX_FMT_TILED_NV12_MBALIGN;
- crop->pos.y -= crop->pos.y % IPU_PIX_FMT_TILED_NV12_MBALIGN;
+ if ((input->width % IPU_PIX_FMT_TILED_NV12_MBALIGN) ||
+ (input->height % IPU_PIX_FMT_TILED_NV12_MBALIGN) ||
+ (crop->pos.x % IPU_PIX_FMT_TILED_NV12_MBALIGN) ||
+ (crop->pos.y % IPU_PIX_FMT_TILED_NV12_MBALIGN)) {
+ v4l2_err(vout->vfd->v4l2_dev,
+ "ERR: tiled fmt needs 16 pixel align.\n");
+ return -EINVAL;
+ }
+ if ((crop->w % IPU_PIX_FMT_TILED_NV12_MBALIGN) ||
+ (crop->h % IPU_PIX_FMT_TILED_NV12_MBALIGN))
+ tiled_need_pp = true;
} else {
crop->w -= crop->w % 8;
crop->h -= crop->h % 8;
@@ -1072,7 +1090,8 @@ static int mxc_vout_try_task(struct mxc_vout_output *vout)
if ((IPU_PIX_FMT_TILED_NV12 == input->format) ||
(IPU_PIX_FMT_TILED_NV12F == input->format)) {
/* check resize/rotate/flip, or csc task */
- if (!((IPU_ROTATE_NONE != output->rotate) ||
+ if (!(tiled_need_pp ||
+ (IPU_ROTATE_NONE != output->rotate) ||
(input->crop.w != output->crop.w) ||
(input->crop.h != output->crop.h) ||
(!vout->disp_support_csc &&
diff --git a/drivers/mfd/mxc-hdmi-core.c b/drivers/mfd/mxc-hdmi-core.c
index e9322477ff6d..a07db1b0c070 100644
--- a/drivers/mfd/mxc-hdmi-core.c
+++ b/drivers/mfd/mxc-hdmi-core.c
@@ -41,6 +41,7 @@
#include <linux/mfd/mxc-hdmi-core.h>
#include <linux/fsl_devices.h>
#include <mach/hardware.h>
+#include <linux/mfd/mxc-hdmi-core.h>
struct mxc_hdmi_data {
struct platform_device *pdev;
@@ -72,22 +73,29 @@ static spinlock_t hdmi_audio_lock, hdmi_blank_state_lock, hdmi_cable_state_lock;
unsigned int hdmi_set_cable_state(unsigned int state)
{
unsigned long flags;
+ struct snd_pcm_substream *substream = hdmi_audio_stream_playback;
spin_lock_irqsave(&hdmi_cable_state_lock, flags);
hdmi_cable_state = state;
spin_unlock_irqrestore(&hdmi_cable_state_lock, flags);
+ if (check_hdmi_state() && substream)
+ substream->ops->trigger(substream, SNDRV_PCM_TRIGGER_START);
return 0;
}
unsigned int hdmi_set_blank_state(unsigned int state)
{
unsigned long flags;
+ struct snd_pcm_substream *substream = hdmi_audio_stream_playback;
spin_lock_irqsave(&hdmi_blank_state_lock, flags);
hdmi_blank_state = state;
spin_unlock_irqrestore(&hdmi_blank_state_lock, flags);
+ if (check_hdmi_state() && substream)
+ substream->ops->trigger(substream, SNDRV_PCM_TRIGGER_START);
+
return 0;
}
@@ -98,7 +106,7 @@ static void hdmi_audio_abort_stream(struct snd_pcm_substream *substream)
snd_pcm_stream_lock_irqsave(substream, flags);
if (snd_pcm_running(substream))
- snd_pcm_stop(substream, SNDRV_PCM_STATE_DISCONNECTED);
+ substream->ops->trigger(substream, SNDRV_PCM_TRIGGER_STOP);
snd_pcm_stream_unlock_irqrestore(substream, flags);
}
@@ -114,7 +122,7 @@ int mxc_hdmi_abort_stream(void)
return 0;
}
-static int check_hdmi_state(void)
+int check_hdmi_state(void)
{
unsigned long flags1, flags2;
unsigned int ret;
diff --git a/drivers/mmc/core/sdio.c b/drivers/mmc/core/sdio.c
index e4cd11b97c24..9db650f00734 100644
--- a/drivers/mmc/core/sdio.c
+++ b/drivers/mmc/core/sdio.c
@@ -658,6 +658,9 @@ static int mmc_sdio_suspend(struct mmc_host *host)
mmc_release_host(host);
}
+ if (!err)
+ mmc_claim_host(host);
+
return err;
}
@@ -668,9 +671,6 @@ static int mmc_sdio_resume(struct mmc_host *host)
BUG_ON(!host);
BUG_ON(!host->card);
- /* Basic card reinitialization. */
- mmc_claim_host(host);
-
/* No need to reinitialize powered-resumed nonremovable cards */
if (mmc_card_is_removable(host) && !mmc_card_keep_power(host))
err = mmc_sdio_init_card(host, host->ocr, host->card,
diff --git a/drivers/mtd/nand/gpmi-nand/gpmi-nand.c b/drivers/mtd/nand/gpmi-nand/gpmi-nand.c
index f25b7c27b101..cc353ce5ae7e 100644
--- a/drivers/mtd/nand/gpmi-nand/gpmi-nand.c
+++ b/drivers/mtd/nand/gpmi-nand/gpmi-nand.c
@@ -873,7 +873,7 @@ static void block_mark_swapping(struct gpmi_nand_data *this,
}
static int gpmi_ecc_read_page(struct mtd_info *mtd, struct nand_chip *chip,
- uint8_t *buf, int page)
+ uint8_t *buf, int oob_required, int page)
{
struct gpmi_nand_data *this = chip->priv;
struct bch_geometry *nfc_geo = &this->bch_geometry;
@@ -939,17 +939,20 @@ static int gpmi_ecc_read_page(struct mtd_info *mtd, struct nand_chip *chip,
mtd->ecc_stats.corrected += corrected;
}
- /*
- * It's time to deliver the OOB bytes. See gpmi_ecc_read_oob() for
- * details about our policy for delivering the OOB.
- *
- * We fill the caller's buffer with set bits, and then copy the block
- * mark to th caller's buffer. Note that, if block mark swapping was
- * necessary, it has already been done, so we can rely on the first
- * byte of the auxiliary buffer to contain the block mark.
- */
- memset(chip->oob_poi, ~0, mtd->oobsize);
- chip->oob_poi[0] = ((uint8_t *) auxiliary_virt)[0];
+ if (oob_required) {
+ /*
+ * It's time to deliver the OOB bytes. See gpmi_ecc_read_oob()
+ * for details about our policy for delivering the OOB.
+ *
+ * We fill the caller's buffer with set bits, and then copy the
+ * block mark to th caller's buffer. Note that, if block mark
+ * swapping was necessary, it has already been done, so we can
+ * rely on the first byte of the auxiliary buffer to contain
+ * the block mark.
+ */
+ memset(chip->oob_poi, ~0, mtd->oobsize);
+ chip->oob_poi[0] = ((uint8_t *) auxiliary_virt)[0];
+ }
read_page_swap_end(this, buf, mtd->writesize,
this->payload_virt, this->payload_phys,
@@ -959,8 +962,8 @@ exit_nfc:
return ret;
}
-static void gpmi_ecc_write_page(struct mtd_info *mtd,
- struct nand_chip *chip, const uint8_t *buf)
+static void gpmi_ecc_write_page(struct mtd_info *mtd, struct nand_chip *chip,
+ const uint8_t *buf, int oob_required)
{
struct gpmi_nand_data *this = chip->priv;
struct bch_geometry *nfc_geo = &this->bch_geometry;
@@ -1040,7 +1043,7 @@ static int gpmi_verify_buf(struct mtd_info *mtd, const uint8_t * buf, int len)
{
struct nand_chip *nand = mtd->priv;
- gpmi_ecc_read_page(mtd, nand, verify_buf, len);
+ gpmi_ecc_read_page(mtd, nand, verify_buf, 0, len);
if (memcmp(buf, verify_buf, len))
return -EFAULT;
return 0;
@@ -1353,7 +1356,7 @@ static int __devinit mx23_write_transcription_stamp(struct gpmi_nand_data *this)
/* Write the first page of the current stride. */
dev_dbg(dev, "Writing an NCB fingerprint in page 0x%x\n", page);
chip->cmdfunc(mtd, NAND_CMD_SEQIN, 0x00, page);
- chip->ecc.write_page_raw(mtd, chip, buffer);
+ chip->ecc.write_page_raw(mtd, chip, buffer, 0);
chip->cmdfunc(mtd, NAND_CMD_PAGEPROG, -1, -1);
/* Wait for the write to finish. */
diff --git a/drivers/mtd/nand/nand_base.c b/drivers/mtd/nand/nand_base.c
index e14f8284e79f..6367eac4461b 100644
--- a/drivers/mtd/nand/nand_base.c
+++ b/drivers/mtd/nand/nand_base.c
@@ -1051,12 +1051,13 @@ EXPORT_SYMBOL(nand_lock);
* @mtd: mtd info structure
* @chip: nand chip info structure
* @buf: buffer to store read data
+ * @oob_required: caller requires OOB data read to chip->oob_poi
* @page: page number to read
*
* Not for syndrome calculating ecc controllers, which use a special oob layout
*/
static int nand_read_page_raw(struct mtd_info *mtd, struct nand_chip *chip,
- uint8_t *buf, int page)
+ uint8_t *buf, int oob_required, int page)
{
chip->read_buf(mtd, buf, mtd->writesize);
chip->read_buf(mtd, chip->oob_poi, mtd->oobsize);
@@ -1068,13 +1069,14 @@ static int nand_read_page_raw(struct mtd_info *mtd, struct nand_chip *chip,
* @mtd: mtd info structure
* @chip: nand chip info structure
* @buf: buffer to store read data
+ * @oob_required: caller requires OOB data read to chip->oob_poi
* @page: page number to read
*
* We need a special oob layout and handling even when OOB isn't used.
*/
static int nand_read_page_raw_syndrome(struct mtd_info *mtd,
- struct nand_chip *chip,
- uint8_t *buf, int page)
+ struct nand_chip *chip, uint8_t *buf,
+ int oob_required, int page)
{
int eccsize = chip->ecc.size;
int eccbytes = chip->ecc.bytes;
@@ -1111,10 +1113,11 @@ static int nand_read_page_raw_syndrome(struct mtd_info *mtd,
* @mtd: mtd info structure
* @chip: nand chip info structure
* @buf: buffer to store read data
+ * @oob_required: caller requires OOB data read to chip->oob_poi
* @page: page number to read
*/
static int nand_read_page_swecc(struct mtd_info *mtd, struct nand_chip *chip,
- uint8_t *buf, int page)
+ uint8_t *buf, int oob_required, int page)
{
int i, eccsize = chip->ecc.size;
int eccbytes = chip->ecc.bytes;
@@ -1124,7 +1127,7 @@ static int nand_read_page_swecc(struct mtd_info *mtd, struct nand_chip *chip,
uint8_t *ecc_code = chip->buffers->ecccode;
uint32_t *eccpos = chip->ecc.layout->eccpos;
- chip->ecc.read_page_raw(mtd, chip, buf, page);
+ chip->ecc.read_page_raw(mtd, chip, buf, 1, page);
for (i = 0; eccsteps; eccsteps--, i += eccbytes, p += eccsize)
chip->ecc.calculate(mtd, p, &ecc_calc[i]);
@@ -1239,12 +1242,13 @@ static int nand_read_subpage(struct mtd_info *mtd, struct nand_chip *chip,
* @mtd: mtd info structure
* @chip: nand chip info structure
* @buf: buffer to store read data
+ * @oob_required: caller requires OOB data read to chip->oob_poi
* @page: page number to read
*
* Not for syndrome calculating ecc controllers which need a special oob layout
*/
static int nand_read_page_hwecc(struct mtd_info *mtd, struct nand_chip *chip,
- uint8_t *buf, int page)
+ uint8_t *buf, int oob_required, int page)
{
int i, eccsize = chip->ecc.size;
int eccbytes = chip->ecc.bytes;
@@ -1284,6 +1288,7 @@ static int nand_read_page_hwecc(struct mtd_info *mtd, struct nand_chip *chip,
* @mtd: mtd info structure
* @chip: nand chip info structure
* @buf: buffer to store read data
+ * @oob_required: caller requires OOB data read to chip->oob_poi
* @page: page number to read
*
* Hardware ECC for large page chips, require OOB to be read first.
@@ -1294,7 +1299,7 @@ static int nand_read_page_hwecc(struct mtd_info *mtd, struct nand_chip *chip,
* overwriting the NAND manufacturer bad block markings.
*/
static int nand_read_page_hwecc_oob_first(struct mtd_info *mtd,
- struct nand_chip *chip, uint8_t *buf, int page)
+ struct nand_chip *chip, uint8_t *buf, int oob_required, int page)
{
int i, eccsize = chip->ecc.size;
int eccbytes = chip->ecc.bytes;
@@ -1333,13 +1338,14 @@ static int nand_read_page_hwecc_oob_first(struct mtd_info *mtd,
* @mtd: mtd info structure
* @chip: nand chip info structure
* @buf: buffer to store read data
+ * @oob_required: caller requires OOB data read to chip->oob_poi
* @page: page number to read
*
* The hw generator calculates the error syndrome automatically. Therefor
* we need a special oob layout and handling.
*/
static int nand_read_page_syndrome(struct mtd_info *mtd, struct nand_chip *chip,
- uint8_t *buf, int page)
+ uint8_t *buf, int oob_required, int page)
{
int i, eccsize = chip->ecc.size;
int eccbytes = chip->ecc.bytes;
@@ -1443,7 +1449,7 @@ static uint8_t *nand_transfer_oob(struct nand_chip *chip, uint8_t *oob,
int nand_do_read_ops(struct mtd_info *mtd, loff_t from,
struct mtd_oob_ops *ops)
{
- int chipnr, page, realpage, col, bytes, aligned;
+ int chipnr, page, realpage, col, bytes, aligned, oob_required;
struct nand_chip *chip = mtd->priv;
struct mtd_ecc_stats stats;
int blkcheck = (1 << (chip->phys_erase_shift - chip->page_shift)) - 1;
@@ -1468,6 +1474,7 @@ int nand_do_read_ops(struct mtd_info *mtd, loff_t from,
buf = ops->datbuf;
oob = ops->oobbuf;
+ oob_required = oob ? 1 : 0;
while (1) {
bytes = min(mtd->writesize - col, readlen);
@@ -1485,13 +1492,15 @@ int nand_do_read_ops(struct mtd_info *mtd, loff_t from,
/* Now read the page into the buffer */
if (unlikely(ops->mode == MTD_OOB_RAW))
ret = chip->ecc.read_page_raw(mtd, chip,
- bufpoi, page);
+ bufpoi,
+ oob_required,
+ page);
else if (!aligned && NAND_SUBPAGE_READ(chip) && !oob)
ret = chip->ecc.read_subpage(mtd, chip,
col, bytes, bufpoi);
else
ret = chip->ecc.read_page(mtd, chip, bufpoi,
- page);
+ oob_required, page);
if (ret < 0)
break;
@@ -1893,11 +1902,12 @@ out:
* @mtd: mtd info structure
* @chip: nand chip info structure
* @buf: data buffer
+ * @oob_required: must write chip->oob_poi to OOB
*
* Not for syndrome calculating ecc controllers, which use a special oob layout
*/
static void nand_write_page_raw(struct mtd_info *mtd, struct nand_chip *chip,
- const uint8_t *buf)
+ const uint8_t *buf, int oob_required)
{
chip->write_buf(mtd, buf, mtd->writesize);
chip->write_buf(mtd, chip->oob_poi, mtd->oobsize);
@@ -1908,12 +1918,13 @@ static void nand_write_page_raw(struct mtd_info *mtd, struct nand_chip *chip,
* @mtd: mtd info structure
* @chip: nand chip info structure
* @buf: data buffer
+ * @oob_required: must write chip->oob_poi to OOB
*
* We need a special oob layout and handling even when ECC isn't checked.
*/
static void nand_write_page_raw_syndrome(struct mtd_info *mtd,
struct nand_chip *chip,
- const uint8_t *buf)
+ const uint8_t *buf, int oob_required)
{
int eccsize = chip->ecc.size;
int eccbytes = chip->ecc.bytes;
@@ -1947,9 +1958,10 @@ static void nand_write_page_raw_syndrome(struct mtd_info *mtd,
* @mtd: mtd info structure
* @chip: nand chip info structure
* @buf: data buffer
+ * @oob_required: must write chip->oob_poi to OOB
*/
static void nand_write_page_swecc(struct mtd_info *mtd, struct nand_chip *chip,
- const uint8_t *buf)
+ const uint8_t *buf, int oob_required)
{
int i, eccsize = chip->ecc.size;
int eccbytes = chip->ecc.bytes;
@@ -1965,7 +1977,7 @@ static void nand_write_page_swecc(struct mtd_info *mtd, struct nand_chip *chip,
for (i = 0; i < chip->ecc.total; i++)
chip->oob_poi[eccpos[i]] = ecc_calc[i];
- chip->ecc.write_page_raw(mtd, chip, buf);
+ chip->ecc.write_page_raw(mtd, chip, buf, 1);
}
/**
@@ -1973,9 +1985,10 @@ static void nand_write_page_swecc(struct mtd_info *mtd, struct nand_chip *chip,
* @mtd: mtd info structure
* @chip: nand chip info structure
* @buf: data buffer
+ * @oob_required: must write chip->oob_poi to OOB
*/
static void nand_write_page_hwecc(struct mtd_info *mtd, struct nand_chip *chip,
- const uint8_t *buf)
+ const uint8_t *buf, int oob_required)
{
int i, eccsize = chip->ecc.size;
int eccbytes = chip->ecc.bytes;
@@ -2001,12 +2014,14 @@ static void nand_write_page_hwecc(struct mtd_info *mtd, struct nand_chip *chip,
* @mtd: mtd info structure
* @chip: nand chip info structure
* @buf: data buffer
+ * @oob_required: must write chip->oob_poi to OOB
*
* The hw generator calculates the error syndrome automatically. Therefor
* we need a special oob layout and handling.
*/
static void nand_write_page_syndrome(struct mtd_info *mtd,
- struct nand_chip *chip, const uint8_t *buf)
+ struct nand_chip *chip,
+ const uint8_t *buf, int oob_required)
{
int i, eccsize = chip->ecc.size;
int eccbytes = chip->ecc.bytes;
@@ -2045,21 +2060,23 @@ static void nand_write_page_syndrome(struct mtd_info *mtd,
* @mtd: MTD device structure
* @chip: NAND chip descriptor
* @buf: the data to write
+ * @oob_required: must write chip->oob_poi to OOB
* @page: page number to write
* @cached: cached programming
* @raw: use _raw version of write_page
*/
static int nand_write_page(struct mtd_info *mtd, struct nand_chip *chip,
- const uint8_t *buf, int page, int cached, int raw)
+ const uint8_t *buf, int oob_required, int page,
+ int cached, int raw)
{
int status;
chip->cmdfunc(mtd, NAND_CMD_SEQIN, 0x00, page);
if (unlikely(raw))
- chip->ecc.write_page_raw(mtd, chip, buf);
+ chip->ecc.write_page_raw(mtd, chip, buf, oob_required);
else
- chip->ecc.write_page(mtd, chip, buf);
+ chip->ecc.write_page(mtd, chip, buf, oob_required);
/*
* Cached progamming disabled for now, Not sure if its worth the
@@ -2176,6 +2193,7 @@ int nand_do_write_ops(struct mtd_info *mtd, loff_t to,
uint8_t *oob = ops->oobbuf;
uint8_t *buf = ops->datbuf;
int ret, subpage;
+ int oob_required = oob ? 1 : 0;
ops->retlen = 0;
if (!writelen)
@@ -2238,7 +2256,7 @@ int nand_do_write_ops(struct mtd_info *mtd, loff_t to,
memset(chip->oob_poi, 0xff, mtd->oobsize);
}
- ret = chip->write_page(mtd, chip, wbuf, page, cached,
+ ret = chip->write_page(mtd, chip, wbuf, oob_required, page, cached,
(ops->mode == MTD_OOB_RAW));
if (ret)
break;
diff --git a/drivers/mxc/gpu-viv/arch/XAQ2/hal/kernel/gc_hal_kernel_hardware.c b/drivers/mxc/gpu-viv/arch/XAQ2/hal/kernel/gc_hal_kernel_hardware.c
index e09a46b3d7b5..36b7bcfab997 100644
--- a/drivers/mxc/gpu-viv/arch/XAQ2/hal/kernel/gc_hal_kernel_hardware.c
+++ b/drivers/mxc/gpu-viv/arch/XAQ2/hal/kernel/gc_hal_kernel_hardware.c
@@ -4282,7 +4282,7 @@ gckHARDWARE_SetFscaleValue(
gctUINT32 clock;
gctBOOL acquired = gcvFALSE;
- gcmkHEADER_ARG("Hardware=0x%x FscaleVal=%d", Hardware, FscaleVal);
+ gcmkHEADER_ARG("Hardware=0x%x FscaleValue=%d", Hardware, FscaleValue);
gcmkVERIFY_ARGUMENT(FscaleValue > 0 && FscaleValue <= 64);
diff --git a/drivers/mxc/gpu-viv/hal/kernel/gc_hal_kernel_command.c b/drivers/mxc/gpu-viv/hal/kernel/gc_hal_kernel_command.c
index 8cf0509cfd92..e05a143f41c3 100644
--- a/drivers/mxc/gpu-viv/hal/kernel/gc_hal_kernel_command.c
+++ b/drivers/mxc/gpu-viv/hal/kernel/gc_hal_kernel_command.c
@@ -30,6 +30,9 @@
#define _GC_OBJ_ZONE gcvZONE_COMMAND
+#if gcdENABLE_FSCALE_VAL_ADJUST
+extern int thermal_hot;
+#endif
/******************************************************************************\
********************************* Support Code *********************************
\******************************************************************************/
@@ -1080,6 +1083,24 @@ gckCOMMAND_Commit(
/* Extract the gckHARDWARE and gckEVENT objects. */
hardware = Command->kernel->hardware;
+#if gcdENABLE_FSCALE_VAL_ADJUST
+ if(hardware->core == gcvCORE_MAJOR){
+ static gctUINT orgFscale,minFscale,maxFscale;
+ static gctBOOL bAlreadyTooHot = gcvFALSE;
+ if((thermal_hot > 0) && (!bAlreadyTooHot)) {
+ gckHARDWARE_GetFscaleValue(hardware,&orgFscale,&minFscale, &maxFscale);
+ gckHARDWARE_SetFscaleValue(hardware, minFscale);
+ bAlreadyTooHot = gcvTRUE;
+ gckOS_Print("System is too hot. GPU3D will work at %d/64 clock.\n", minFscale);
+ } else if((!(thermal_hot > 0)) && bAlreadyTooHot) {
+ gckHARDWARE_SetFscaleValue(hardware, orgFscale);
+ gckOS_Print("Hot alarm is canceled. GPU3D clock will return to %d/64\n", orgFscale);
+ bAlreadyTooHot = gcvFALSE;
+ }
+
+ }
+#endif
+
/* Check wehther we need to copy the structures or not. */
gcmkONERROR(gckOS_QueryNeedCopy(Command->os, ProcessID, &needCopy));
diff --git a/drivers/mxc/gpu-viv/hal/os/linux/kernel/gc_hal_kernel_device.c b/drivers/mxc/gpu-viv/hal/os/linux/kernel/gc_hal_kernel_device.c
index 890d13e17c50..eba81b64be92 100644
--- a/drivers/mxc/gpu-viv/hal/os/linux/kernel/gc_hal_kernel_device.c
+++ b/drivers/mxc/gpu-viv/hal/os/linux/kernel/gc_hal_kernel_device.c
@@ -358,6 +358,15 @@ gckGALDEVICE_Construct(
gckDebugFileSystemSetCurrentNode(device->dbgnode);
}
}
+ /*get gpu regulator*/
+ device->gpu_regulator = regulator_get(NULL, "cpu_vddgpu");
+ if (IS_ERR(device->gpu_regulator)) {
+ gcmkTRACE_ZONE(gcvLEVEL_ERROR, gcvZONE_DRIVER,
+ "%s(%d): Failed to get gpu regulator %s/%s \n",
+ __FUNCTION__, __LINE__,
+ PARENT_FILE, DEBUG_FILE);
+ gcmkONERROR(gcvSTATUS_NOT_FOUND);
+ }
/*Initialize the clock structure*/
if (IrqLine != -1) {
diff --git a/drivers/mxc/gpu-viv/hal/os/linux/kernel/gc_hal_kernel_device.h b/drivers/mxc/gpu-viv/hal/os/linux/kernel/gc_hal_kernel_device.h
index 03f7f9b2201e..c15989894600 100644
--- a/drivers/mxc/gpu-viv/hal/os/linux/kernel/gc_hal_kernel_device.h
+++ b/drivers/mxc/gpu-viv/hal/os/linux/kernel/gc_hal_kernel_device.h
@@ -89,6 +89,9 @@ typedef struct _gckGALDEVICE
struct clk *clk_2d_axi;
struct clk *clk_vg_axi;
+ /*Power management.*/
+ struct regulator *gpu_regulator;
+
}
* gckGALDEVICE;
diff --git a/drivers/mxc/gpu-viv/hal/os/linux/kernel/gc_hal_kernel_linux.h b/drivers/mxc/gpu-viv/hal/os/linux/kernel/gc_hal_kernel_linux.h
index 30fb13596dda..a6ed03ffc0f9 100644
--- a/drivers/mxc/gpu-viv/hal/os/linux/kernel/gc_hal_kernel_linux.h
+++ b/drivers/mxc/gpu-viv/hal/os/linux/kernel/gc_hal_kernel_linux.h
@@ -47,6 +47,7 @@
#if ENABLE_GPU_CLOCK_BY_DRIVER && LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,28)
#include <linux/clk.h>
+#include <linux/regulator/consumer.h>
#endif
#define NTSTRSAFE_NO_CCH_FUNCTIONS
diff --git a/drivers/mxc/gpu-viv/hal/os/linux/kernel/gc_hal_kernel_os.c b/drivers/mxc/gpu-viv/hal/os/linux/kernel/gc_hal_kernel_os.c
index 4d1a71dfa91a..4091ccdb61d4 100644
--- a/drivers/mxc/gpu-viv/hal/os/linux/kernel/gc_hal_kernel_os.c
+++ b/drivers/mxc/gpu-viv/hal/os/linux/kernel/gc_hal_kernel_os.c
@@ -6947,6 +6947,7 @@ gckOS_SetGPUPower(
struct clk *clk_vg_axi = Os->device->clk_vg_axi;
gctBOOL oldClockState = gcvFALSE;
+ gctBOOL oldPowerState = gcvFALSE;
gcmkHEADER_ARG("Os=0x%X Core=%d Clock=%d Power=%d", Os, Core, Clock, Power);
@@ -6956,15 +6957,20 @@ gckOS_SetGPUPower(
if (Core == gcvCORE_VG)
{
oldClockState = Os->device->kernels[Core]->vg->hardware->clockState;
+ oldPowerState = Os->device->kernels[Core]->vg->hardware->powerState;
}
else
{
#endif
oldClockState = Os->device->kernels[Core]->hardware->clockState;
+ oldPowerState = Os->device->kernels[Core]->hardware->powerState;
#if gcdENABLE_VG
}
#endif
}
+ if((Power == gcvTRUE) && (oldPowerState == gcvFALSE) &&
+ !IS_ERR(Os->device->gpu_regulator))
+ regulator_enable(Os->device->gpu_regulator);
if (Clock == gcvTRUE) {
if (oldClockState == gcvFALSE) {
@@ -7007,8 +7013,10 @@ gckOS_SetGPUPower(
}
}
}
-
-
+ if((Power == gcvFALSE) && (oldPowerState == gcvTRUE) &&
+ !IS_ERR(Os->device->gpu_regulator))
+ regulator_disable(Os->device->gpu_regulator);
+ /* TODO: Put your code here. */
gcmkFOOTER_NO();
return gcvSTATUS_OK;
}
diff --git a/drivers/mxc/ipu3/ipu_device.c b/drivers/mxc/ipu3/ipu_device.c
index d12ffdfc7847..be1725129ce2 100644
--- a/drivers/mxc/ipu3/ipu_device.c
+++ b/drivers/mxc/ipu3/ipu_device.c
@@ -340,6 +340,7 @@ struct ipu_alloc_list {
dma_addr_t phy_addr;
void *cpu_addr;
u32 size;
+ void *file_index;
};
static LIST_HEAD(ipu_alloc_list);
@@ -350,6 +351,7 @@ static DEFINE_SPINLOCK(ipu_task_list_lock);
static DECLARE_WAIT_QUEUE_HEAD(thread_waitq);
static DECLARE_WAIT_QUEUE_HEAD(res_waitq);
static atomic_t req_cnt;
+static atomic_t file_index = ATOMIC_INIT(1);
static int major;
static int max_ipu_no;
static int thread_id;
@@ -3274,6 +3276,7 @@ EXPORT_SYMBOL_GPL(ipu_queue_task);
static int mxc_ipu_open(struct inode *inode, struct file *file)
{
+ file->private_data = (void *)atomic_inc_return(&file_index);
return 0;
}
@@ -3330,6 +3333,7 @@ static long mxc_ipu_ioctl(struct file *file,
kfree(mem);
return -ENOMEM;
}
+ mem->file_index = file->private_data;
mutex_lock(&ipu_alloc_lock);
list_add(&mem->list, &ipu_alloc_list);
mutex_unlock(&ipu_alloc_lock);
@@ -3413,6 +3417,26 @@ static int mxc_ipu_mmap(struct file *file, struct vm_area_struct *vma)
static int mxc_ipu_release(struct inode *inode, struct file *file)
{
+ struct ipu_alloc_list *mem;
+ struct ipu_alloc_list *n;
+
+ mutex_lock(&ipu_alloc_lock);
+ list_for_each_entry_safe(mem, n, &ipu_alloc_list, list) {
+ if ((mem->cpu_addr != 0) &&
+ (file->private_data == mem->file_index)) {
+ list_del(&mem->list);
+ dma_free_coherent(ipu_dev,
+ mem->size,
+ mem->cpu_addr,
+ mem->phy_addr);
+ dev_dbg(ipu_dev, "rel-free %d bytes @ 0x%08X\n",
+ mem->size, mem->phy_addr);
+ kfree(mem);
+ }
+ }
+ mutex_unlock(&ipu_alloc_lock);
+ atomic_dec(&file_index);
+
return 0;
}
diff --git a/drivers/mxc/thermal/cooling.c b/drivers/mxc/thermal/cooling.c
index 0feefeaa6008..7019d9949c8a 100644
--- a/drivers/mxc/thermal/cooling.c
+++ b/drivers/mxc/thermal/cooling.c
@@ -57,6 +57,7 @@ cpufreq, it minor 1, and when we promote cpufreq, it add 1, so
if it is 0, mean we didn't change the cpufreq */
static int cpufreq_change_count;
+extern int thermal_hot;
int anatop_thermal_get_cpufreq_cur(void)
{
int ret = -EINVAL;
@@ -237,6 +238,7 @@ imx_processor_set_cur_state(struct thermal_cooling_device *cdev,
secondary CPUs that detached by thermal driver */
if (cooling_cpuhotplug) {
if (!state) {
+ thermal_hot = 0;
for (i = 1; i < 4; i++) {
if (cpu_mask && (0x1 << i)) {
anatop_thermal_cpu_hotplug(true);
@@ -247,6 +249,7 @@ imx_processor_set_cur_state(struct thermal_cooling_device *cdev,
}
} else {
if (!state) {
+ thermal_hot = 0;
if (cpufreq_change_count < 0)
anatop_thermal_cpufreq_up();
else if (cpufreq_change_count > 0)
diff --git a/drivers/mxc/vpu/mxc_vpu.c b/drivers/mxc/vpu/mxc_vpu.c
index 92a1d0dc98c7..8178824ab80a 100644
--- a/drivers/mxc/vpu/mxc_vpu.c
+++ b/drivers/mxc/vpu/mxc_vpu.c
@@ -39,6 +39,7 @@
#include <linux/workqueue.h>
#include <linux/sched.h>
#include <linux/vmalloc.h>
+#include <linux/regulator/consumer.h>
#include <linux/page-flags.h>
#include <linux/mm_types.h>
#include <linux/types.h>
@@ -110,6 +111,7 @@ static int vpu_jpu_irq;
#endif
static unsigned int regBk[64];
+static struct regulator *vpu_regulator;
#define READ_REG(x) __raw_readl(vpu_base + x)
#define WRITE_REG(val, x) __raw_writel(val, vpu_base + x)
@@ -245,8 +247,12 @@ bool vpu_is_valid_phy_memory(u32 paddr)
*/
static int vpu_open(struct inode *inode, struct file *filp)
{
+
mutex_lock(&vpu_data.lock);
- open_count++;
+
+ if (open_count++ == 0 && !IS_ERR(vpu_regulator))
+ regulator_enable(vpu_regulator);
+
filp->private_data = (void *)(&vpu_data);
mutex_unlock(&vpu_data.lock);
return 0;
@@ -531,6 +537,9 @@ static int vpu_release(struct inode *inode, struct file *filp)
mutex_lock(&vpu_data.lock);
if (open_count > 0 && !(--open_count)) {
+ if (!IS_ERR(vpu_regulator))
+ regulator_disable(vpu_regulator);
+
vpu_free_buffers();
/* Free shared memory when vpu device is idle */
@@ -705,6 +714,12 @@ static int vpu_dev_probe(struct platform_device *pdev)
(void *)(&vpu_data));
if (err)
goto err_out_class;
+ vpu_regulator = regulator_get(NULL, "cpu_vddvpu");
+ if (IS_ERR(vpu_regulator)) {
+ printk(KERN_ERR
+ "%s: failed to get vpu regulator\n", __func__);
+ goto err_out_class;
+ }
#ifdef MXC_VPU_HAS_JPU
vpu_jpu_irq = platform_get_irq_byname(pdev, "vpu_jpu_irq");
@@ -752,7 +767,8 @@ static int vpu_dev_remove(struct platform_device *pdev)
iounmap(vpu_base);
if (vpu_plat && vpu_plat->iram_enable && vpu_plat->iram_size)
iram_free(iram.start, vpu_plat->iram_size);
-
+ if (!IS_ERR(vpu_regulator))
+ regulator_put(vpu_regulator);
return 0;
}
@@ -762,6 +778,8 @@ static int vpu_suspend(struct platform_device *pdev, pm_message_t state)
int i;
unsigned long timeout;
+ if (!IS_ERR(vpu_regulator))
+ regulator_enable(vpu_regulator);
/* Wait for vpu go to idle state, suspect vpu cannot be changed
to idle state after about 1 sec */
if (open_count > 0) {
@@ -794,10 +812,14 @@ static int vpu_suspend(struct platform_device *pdev, pm_message_t state)
if (vpu_plat->pg)
vpu_plat->pg(1);
+ if (!IS_ERR(vpu_regulator))
+ regulator_disable(vpu_regulator);
return 0;
out:
clk_disable(vpu_clk);
+ if (!IS_ERR(vpu_regulator))
+ regulator_disable(vpu_regulator);
return -EAGAIN;
}
@@ -809,6 +831,8 @@ static int vpu_resume(struct platform_device *pdev)
if (cpu_is_mx53())
goto recover_clk;
+ if (!IS_ERR(vpu_regulator))
+ regulator_enable(vpu_regulator);
if (vpu_plat->pg)
vpu_plat->pg(0);
@@ -869,6 +893,8 @@ recover_clk:
/* Recover vpu clock */
for (i = 0; i < vpu_clk_usercount; i++)
clk_enable(vpu_clk);
+ if (!IS_ERR(vpu_regulator))
+ regulator_disable(vpu_regulator);
return 0;
}
diff --git a/drivers/net/fec.c b/drivers/net/fec.c
index 5af378f391ee..86e4ea3404b3 100755
--- a/drivers/net/fec.c
+++ b/drivers/net/fec.c
@@ -397,7 +397,12 @@ fec_timeout(struct net_device *ndev)
ndev->stats.tx_errors++;
+ netif_device_detach(ndev);
+ fec_stop(ndev);
+
fec_restart(ndev, fep->full_duplex);
+ netif_device_attach(ndev);
+ ndev->trans_start = jiffies; /* prevent tx timeout */
if (fep->link && !fep->tx_full)
netif_wake_queue(ndev);
}
@@ -1320,10 +1325,7 @@ fec_enet_close(struct net_device *ndev)
{
struct fec_enet_private *fep = netdev_priv(ndev);
- /* Don't know what to do yet. */
fep->opened = 0;
- netif_stop_queue(ndev);
- netif_carrier_off(ndev);
if (fep->use_napi)
napi_disable(&fep->napi);
@@ -1760,7 +1762,10 @@ fec_stop(struct net_device *dev)
if (fep->ptimer_present)
fec_ptp_stop(fep->ptp_priv);
writel(FEC_DEFAULT_IMASK, fep->hwp + FEC_IMASK);
- netif_stop_queue(dev);
+
+ if (netif_running(dev))
+ netif_stop_queue(dev);
+ netif_carrier_off(dev); /* prevent tx timeout */
fep->link = 0;
}
@@ -1921,7 +1926,6 @@ fec_suspend(struct device *dev)
if (netif_running(ndev)) {
netif_device_detach(ndev);
fec_stop(ndev);
- netif_carrier_off(ndev);
clk_disable(fep->clk);
}
diff --git a/drivers/power/Kconfig b/drivers/power/Kconfig
index 6e53cce3c7fd..a24653787d1d 100755
--- a/drivers/power/Kconfig
+++ b/drivers/power/Kconfig
@@ -222,7 +222,6 @@ config CHARGER_MAX8903
config SABRESD_MAX8903
tristate "Sabresd Board Battery DC-DC Charger for USB and Adapter Power"
depends on GENERIC_HARDIRQS
- depends on TOUCHSCREEN_MAX11801
help
Say Y to enable support for the MAX8903 DC-DC charger and sysfs on
sabresd board.The driver supports controlling charger and battery
diff --git a/drivers/power/sabresd_battery.c b/drivers/power/sabresd_battery.c
index c7318a6eb02c..648922139790 100755
--- a/drivers/power/sabresd_battery.c
+++ b/drivers/power/sabresd_battery.c
@@ -65,13 +65,11 @@ typedef struct {
u32 voltage;
u32 percent;
} battery_capacity , *pbattery_capacity;
-
static int cpu_type_flag;
static int offset_discharger;
static int offset_charger;
static int offset_usb_charger;
-
static battery_capacity chargingTable[] = {
{4050, 99},
{4040, 98},
@@ -188,9 +186,9 @@ static enum power_supply_property max8903_battery_props[] = {
POWER_SUPPLY_PROP_HEALTH,
POWER_SUPPLY_PROP_CAPACITY_LEVEL,
};
-
+#ifdef CONFIG_TOUCHSCREEN_MAX11801
extern u32 max11801_read_adc(void);
-
+#endif
static void max8903_charger_update_status(struct max8903_data *data)
{
if (data->usb_in || data->ta_in) {
@@ -205,26 +203,35 @@ static void max8903_charger_update_status(struct max8903_data *data)
}
if (data->charger_online == 0 && data->usb_charger_online == 0) {
data->battery_status = POWER_SUPPLY_STATUS_DISCHARGING;
- } else {
- if (gpio_get_value(data->pdata->chg) == 0) {
- data->battery_status = POWER_SUPPLY_STATUS_CHARGING;
- } else if (data->ta_in &&
- gpio_get_value(data->pdata->chg) == 1) {
- if (data->percent >= 99)
- data->battery_status = POWER_SUPPLY_STATUS_FULL;
- else
- data->battery_status = POWER_SUPPLY_STATUS_NOT_CHARGING;
- }
- else if (data->usb_in &&
- gpio_get_value(data->pdata->chg) == 1) {
- if (data->percent >= 99)
- data->battery_status = POWER_SUPPLY_STATUS_FULL;
- else
- data->battery_status = POWER_SUPPLY_STATUS_NOT_CHARGING;
- }
+ } else {
+ if (gpio_get_value(data->pdata->chg) == 0) {
+ data->battery_status = POWER_SUPPLY_STATUS_CHARGING;
+ } else if (data->ta_in && gpio_get_value(data->pdata->chg) == 1) {
+ if (!data->pdata->feature_flag) {
+ if (data->percent >= 99)
+ data->battery_status = POWER_SUPPLY_STATUS_FULL;
+ else
+ data->battery_status = POWER_SUPPLY_STATUS_NOT_CHARGING;
+ } else {
+ data->battery_status = POWER_SUPPLY_STATUS_FULL;
+ }
+ } else if (data->usb_in && gpio_get_value(data->pdata->chg) == 1) {
+ if (!data->pdata->feature_flag) {
+ if (data->percent >= 99)
+ data->battery_status = POWER_SUPPLY_STATUS_FULL;
+ else
+ data->battery_status = POWER_SUPPLY_STATUS_NOT_CHARGING;
+ } else {
+ data->battery_status = POWER_SUPPLY_STATUS_FULL;
+ }
}
- pr_debug("chg: %d \n", gpio_get_value(data->pdata->chg));
+ }
+ pr_debug("chg: %d\n", gpio_get_value(data->pdata->chg));
+ pr_debug("dc: %d\n", gpio_get_value(data->pdata->dok));
+ pr_debug("flt: %d\n", gpio_get_value(data->pdata->flt));
}
+
+#ifdef CONFIG_TOUCHSCREEN_MAX11801
static int cmp_func(const void *_a, const void *_b)
{
const int *a = _a, *b = _b;
@@ -235,6 +242,7 @@ static int cmp_func(const void *_a, const void *_b)
return -1;
return 0;
}
+
u32 calibration_voltage(struct max8903_data *data)
{
int volt[ADC_SAMPLE_COUNT];
@@ -275,51 +283,54 @@ u32 calibration_voltage(struct max8903_data *data)
voltage_data = (volt[2] + volt[ADC_SAMPLE_COUNT - 3]) / 2;
return voltage_data;
}
-
+#endif
static void max8903_battery_update_status(struct max8903_data *data)
{
- int temp;
+ int temp = 0;
static int temp_last;
bool changed_flag;
changed_flag = false;
mutex_lock(&data->work_lock);
- temp = calibration_voltage(data);
- if (temp_last == 0) {
- data->voltage_uV = temp;
- temp_last = temp;
- }
- if (data->charger_online == 0 && temp_last != 0) {
- if (temp < temp_last) {
- temp_last = temp;
- data->voltage_uV = temp;
- } else {
- data->voltage_uV = temp_last;
+ if (!data->pdata->feature_flag) {
+#ifdef CONFIG_TOUCHSCREEN_MAX11801
+ temp = calibration_voltage(data);
+#endif
+ if (temp_last == 0) {
+ data->voltage_uV = temp;
+ temp_last = temp;
+ }
+ if (data->charger_online == 0 && temp_last != 0) {
+ if (temp < temp_last) {
+ temp_last = temp;
+ data->voltage_uV = temp;
+ } else {
+ data->voltage_uV = temp_last;
+ }
+ }
+ if (data->charger_online == 1 || data->usb_charger_online == 1) {
+ data->voltage_uV = temp;
+ temp_last = temp;
+ }
+ data->percent = calibrate_battery_capability_percent(data);
+ if (data->percent != data->old_percent) {
+ data->old_percent = data->percent;
+ changed_flag = true;
+ }
+ if (changed_flag) {
+ changed_flag = false;
+ power_supply_changed(&data->bat);
+ }
+ /*
+ *because boot time gap between led framwork and charger
+ *framwork,when system boots with charger attatched,
+ *charger led framwork loses the first charger online event,
+ *add once extra power_supply_changed can fix this issure
+ */
+ if (data->first_delay_count < 200) {
+ data->first_delay_count = data->first_delay_count + 1 ;
+ power_supply_changed(&data->bat);
}
}
- if (data->charger_online == 1 || data->usb_charger_online == 1) {
- data->voltage_uV = temp;
- temp_last = temp;
- }
- data->percent = calibrate_battery_capability_percent(data);
- if (data->percent != data->old_percent) {
- data->old_percent = data->percent;
- changed_flag = true;
- }
- if (changed_flag) {
- changed_flag = false;
- power_supply_changed(&data->bat);
- }
- /*
- because boot time gap between led framwork and charger
- framwork,when system boots with charger attatched, charger
- led framwork loses the first charger online event,add once extra
- power_supply_changed can fix this issure
- */
- if (data->first_delay_count < 200) {
- data->first_delay_count = data->first_delay_count + 1 ;
- power_supply_changed(&data->bat);
- }
-
mutex_unlock(&data->work_lock);
}
@@ -332,22 +343,27 @@ static int max8903_battery_get_property(struct power_supply *bat,
switch (psp) {
case POWER_SUPPLY_PROP_STATUS:
val->intval = POWER_SUPPLY_STATUS_UNKNOWN;
- if (gpio_get_value(di->pdata->chg) == 0) {
- di->battery_status = POWER_SUPPLY_STATUS_CHARGING;
- } else if (di->ta_in &&
- gpio_get_value(di->pdata->chg) == 1) {
+ if (gpio_get_value(di->pdata->chg) == 0) {
+ di->battery_status = POWER_SUPPLY_STATUS_CHARGING;
+ } else if (di->ta_in && gpio_get_value(di->pdata->chg) == 1) {
+ if (!di->pdata->feature_flag) {
if (di->percent >= 99)
di->battery_status = POWER_SUPPLY_STATUS_FULL;
else
di->battery_status = POWER_SUPPLY_STATUS_NOT_CHARGING;
+ } else {
+ di->battery_status = POWER_SUPPLY_STATUS_FULL;
}
- else if (di->usb_in &&
- gpio_get_value(di->pdata->chg) == 1) {
+ } else if (di->usb_in && gpio_get_value(di->pdata->chg) == 1) {
+ if (!di->pdata->feature_flag) {
if (di->percent >= 99)
di->battery_status = POWER_SUPPLY_STATUS_FULL;
else
- di->battery_status = POWER_SUPPLY_STATUS_NOT_CHARGING;
+ di->battery_status = POWER_SUPPLY_STATUS_NOT_CHARGING;
+ } else {
+ di->battery_status = POWER_SUPPLY_STATUS_FULL;
}
+ }
val->intval = di->battery_status;
return 0;
default:
@@ -795,14 +811,13 @@ static __devinit int max8903_probe(struct platform_device *pdev)
ret = request_threaded_irq(gpio_to_irq(pdata->chg),
NULL, max8903_chg,
IRQF_TRIGGER_FALLING | IRQF_TRIGGER_RISING,
- "MAX8903 Fault", data);
+ "MAX8903 Status", data);
if (ret) {
- dev_err(dev, "Cannot request irq %d for Fault (%d)\n",
+ dev_err(dev, "Cannot request irq %d for Status (%d)\n",
gpio_to_irq(pdata->flt), ret);
goto err_chg_irq;
}
}
-
ret = device_create_file(&pdev->dev, &max8903_discharger_dev_attr);
if (ret)
dev_err(&pdev->dev, "create device file failed!\n");
@@ -822,7 +837,6 @@ static __devinit int max8903_probe(struct platform_device *pdev)
offset_charger = 1485;
offset_usb_charger = 1285;
}
-
max8903_charger_update_status(data);
max8903_battery_update_status(data);
return 0;
@@ -888,10 +902,14 @@ static int max8903_suspend(struct platform_device *pdev,
if (data) {
struct max8903_pdata *pdata = data->pdata;
if (pdata) {
- irq = gpio_to_irq(pdata->dok);
- enable_irq_wake(irq);
- irq = gpio_to_irq(pdata->uok);
- enable_irq_wake(irq);
+ if (pdata->dc_valid) {
+ irq = gpio_to_irq(pdata->dok);
+ enable_irq_wake(irq);
+ }
+ if (pdata->usb_valid) {
+ irq = gpio_to_irq(pdata->uok);
+ enable_irq_wake(irq);
+ }
cancel_delayed_work(&data->work);
}
}
@@ -923,10 +941,14 @@ static int max8903_resume(struct platform_device *pdev)
max8903_charger_update_status(data);
power_supply_changed(&data->usb);
}
- irq = gpio_to_irq(pdata->dok);
- disable_irq_wake(irq);
- irq = gpio_to_irq(pdata->uok);
- disable_irq_wake(irq);
+ if (pdata->dc_valid) {
+ irq = gpio_to_irq(pdata->dok);
+ disable_irq_wake(irq);
+ }
+ if (pdata->usb_valid) {
+ irq = gpio_to_irq(pdata->uok);
+ disable_irq_wake(irq);
+ }
schedule_delayed_work(&data->work, BATTERY_UPDATE_INTERVAL);
}
}
diff --git a/drivers/usb/gadget/arcotg_udc.c b/drivers/usb/gadget/arcotg_udc.c
index c3a48307c918..b91cf9f82543 100755
--- a/drivers/usb/gadget/arcotg_udc.c
+++ b/drivers/usb/gadget/arcotg_udc.c
@@ -3323,10 +3323,13 @@ static int udc_suspend(struct fsl_udc *udc)
* charge using usb
*/
if (pdata->pmflags == 0) {
- if (!udc_can_wakeup_system())
+ if (!udc_can_wakeup_system()) {
dr_wake_up_enable(udc, false);
- else
+ } else {
+ if (pdata->platform_phy_power_on)
+ pdata->platform_phy_power_on();
dr_wake_up_enable(udc, true);
+ }
}
/*
diff --git a/drivers/usb/host/ehci-arc.c b/drivers/usb/host/ehci-arc.c
index b872d94b3fc3..e09f4dfd05d9 100755
--- a/drivers/usb/host/ehci-arc.c
+++ b/drivers/usb/host/ehci-arc.c
@@ -678,6 +678,9 @@ static int ehci_fsl_drv_suspend(struct platform_device *pdev,
usb_host_set_wakeup(hcd->self.controller, false);
fsl_usb_clk_gate(hcd->self.controller->platform_data, false);
+ } else {
+ if (pdata->platform_phy_power_on)
+ pdata->platform_phy_power_on();
}
printk(KERN_DEBUG "host suspend ends\n");
diff --git a/drivers/video/mxc/Kconfig b/drivers/video/mxc/Kconfig
index f0afddc95bd3..8a4a0792724f 100644
--- a/drivers/video/mxc/Kconfig
+++ b/drivers/video/mxc/Kconfig
@@ -1,6 +1,6 @@
config FB_MXC
tristate "MXC Framebuffer support"
- depends on FB && (MXC_IPU || ARCH_MX21 || ARCH_MX27 || ARCH_MX25)
+ depends on FB && (MXC_IPU || ARCH_MX21 || ARCH_MX27 || ARCH_MX25 || ARCH_MX6)
select FB_CFB_FILLRECT
select FB_CFB_COPYAREA
select FB_CFB_IMAGEBLIT
@@ -60,6 +60,10 @@ config FB_MXC_SII902X
depends on FB_MXC_SYNC_PANEL && I2C
tristate "Si Image SII9022 DVI/HDMI Interface Chip"
+config FB_MXC_SII902X_ELCDIF
+ depends on FB_MXC_SYNC_PANEL && I2C
+ tristate "Si Image SII9022 DVI/HDMI Interface Chip for ELCDIF FB"
+
config FB_MXC_CH7026
depends on FB_MXC_SYNC_PANEL
tristate "Chrontel CH7026 VGA Interface Chip"
diff --git a/drivers/video/mxc/Makefile b/drivers/video/mxc/Makefile
index 21aef052ecd6..092d0aacba27 100644
--- a/drivers/video/mxc/Makefile
+++ b/drivers/video/mxc/Makefile
@@ -1,9 +1,10 @@
obj-$(CONFIG_FB_MXC_TVOUT_TVE) += tve.o
obj-$(CONFIG_FB_MXC_SII902X) += mxcfb_sii902x.o
+obj-$(CONFIG_FB_MXC_SII902X_ELCDIF) += mxcfb_sii902x_elcdif.o
obj-$(CONFIG_FB_MXC_LDB) += ldb.o
obj-$(CONFIG_FB_MXC_MIPI_DSI) += mipi_dsi.o
obj-$(CONFIG_FB_MXC_TRULY_WVGA_SYNC_PANEL) += mxcfb_hx8369_wvga.o
-obj-$(CONFIG_FB_MXC_EDID) += mxc_edid.o mxc_dvi.o
+obj-$(CONFIG_FB_MXC_EDID) += mxc_edid.o
ifeq ($(CONFIG_ARCH_MX21)$(CONFIG_ARCH_MX27)$(CONFIG_ARCH_MX25),y)
obj-$(CONFIG_FB_MXC_TVOUT) += fs453.o
obj-$(CONFIG_FB_MXC_SYNC_PANEL) += mx2fb.o mxcfb_modedb.o
@@ -11,8 +12,10 @@ ifeq ($(CONFIG_ARCH_MX21)$(CONFIG_ARCH_MX27)$(CONFIG_ARCH_MX25),y)
else
ifeq ($(CONFIG_MXC_IPU_V1),y)
obj-$(CONFIG_FB_MXC_SYNC_PANEL) += mxcfb.o mxcfb_modedb.o
-else
+endif
+ifeq ($(CONFIG_MXC_IPU_V3),y)
obj-$(CONFIG_FB_MXC_SYNC_PANEL) += mxc_dispdrv.o mxc_lcdif.o mxc_ipuv3_fb.o
+ obj-$(CONFIG_FB_MXC_EDID) += mxc_dvi.o
endif
obj-$(CONFIG_FB_MXC_EPSON_PANEL) += mxcfb_epson.o
obj-$(CONFIG_FB_MXC_EPSON_QVGA_PANEL) += mxcfb_epson_qvga.o
diff --git a/drivers/video/mxc/mxc_elcdif_fb.c b/drivers/video/mxc/mxc_elcdif_fb.c
index 9c3b7b99a411..be521ddbdf9d 100644
--- a/drivers/video/mxc/mxc_elcdif_fb.c
+++ b/drivers/video/mxc/mxc_elcdif_fb.c
@@ -86,6 +86,12 @@ struct elcdif_signal_cfg {
unsigned Vsync_pol:1; /* true = active high */
};
+struct mxcfb_mode {
+ int dev_mode;
+ int num_modes;
+ struct fb_videomode *mode;
+};
+
static int mxc_elcdif_fb_blank(int blank, struct fb_info *info);
static int mxc_elcdif_fb_map_video_memory(struct fb_info *info);
static int mxc_elcdif_fb_unmap_video_memory(struct fb_info *info);
@@ -97,6 +103,15 @@ static bool g_elcdif_axi_clk_enable;
static bool g_elcdif_pix_clk_enable;
static struct clk *g_elcdif_axi_clk;
static struct clk *g_elcdif_pix_clk;
+static struct mxcfb_mode mxc_disp_mode;
+
+static void dump_fb_videomode(struct fb_videomode *m)
+{
+ pr_debug("fb_videomode = %d %d %d %d %d %d %d %d %d %d %d %d %d\n",
+ m->refresh, m->xres, m->yres, m->pixclock, m->left_margin,
+ m->right_margin, m->upper_margin, m->lower_margin,
+ m->hsync_len, m->vsync_len, m->sync, m->vmode, m->flag);
+}
static inline void setup_dotclk_panel(u32 pixel_clk,
u16 v_pulse_width,
@@ -113,16 +128,39 @@ static inline void setup_dotclk_panel(u32 pixel_clk,
int enable_present)
{
u32 val, rounded_pixel_clk;
+ u32 rounded_parent_clk;
+ struct clk *clk_parent;
if (!g_elcdif_axi_clk_enable) {
clk_enable(g_elcdif_axi_clk);
g_elcdif_axi_clk_enable = true;
}
+ /* Init clocking */
dev_dbg(g_elcdif_dev, "pixel clk = %d\n", pixel_clk);
- rounded_pixel_clk = clk_round_rate(g_elcdif_pix_clk, pixel_clk);
+
+ clk_parent = clk_get_parent(g_elcdif_pix_clk);
+ if (clk_parent == NULL)
+ dev_err(g_elcdif_dev, "%s Failed get clk parent\n", __func__);
+
+ rounded_pixel_clk = pixel_clk * 2;
+
+ rounded_parent_clk = clk_round_rate(clk_parent,
+ rounded_pixel_clk);
+
+ while (rounded_pixel_clk < rounded_parent_clk) {
+ /* the max divider from parent to di is 8 */
+ if (rounded_parent_clk / pixel_clk < 8)
+ rounded_pixel_clk += pixel_clk * 2;
+ }
+
+ clk_set_rate(clk_parent, rounded_pixel_clk);
+ rounded_pixel_clk =
+ clk_round_rate(g_elcdif_pix_clk, pixel_clk);
clk_set_rate(g_elcdif_pix_clk, rounded_pixel_clk);
+ msleep(5);
+
__raw_writel(BM_ELCDIF_CTRL_DATA_SHIFT_DIR,
elcdif_base + HW_ELCDIF_CTRL_CLR);
@@ -519,6 +557,35 @@ static inline void mxc_init_elcdif(void)
return;
}
+void mxcfb_elcdif_register_mode(const struct fb_videomode *modedb,
+ int num_modes, int dev_mode)
+{
+ struct fb_videomode *mode;
+
+ mode = kzalloc(num_modes * sizeof(struct fb_videomode), GFP_KERNEL);
+
+ if (!mode) {
+ dev_err(g_elcdif_dev, "%s Failed to allocate mode data\n", __func__);
+ return;
+ }
+
+ if (mxc_disp_mode.num_modes)
+ memcpy(mode, mxc_disp_mode.mode,
+ mxc_disp_mode.num_modes * sizeof(struct fb_videomode));
+ if (modedb)
+ memcpy(mode + mxc_disp_mode.num_modes, modedb,
+ num_modes * sizeof(struct fb_videomode));
+
+ if (mxc_disp_mode.num_modes)
+ kfree(mxc_disp_mode.mode);
+
+ mxc_disp_mode.mode = mode;
+ mxc_disp_mode.num_modes += num_modes;
+ mxc_disp_mode.dev_mode = dev_mode;
+
+ return;
+}
+
int mxc_elcdif_frame_addr_setup(dma_addr_t phys)
{
int ret = 0;
@@ -1236,6 +1303,9 @@ static int mxc_elcdif_fb_probe(struct platform_device *pdev)
struct resource *res;
struct fb_info *fbi;
struct mxc_fb_platform_data *pdata = pdev->dev.platform_data;
+ const struct fb_videomode *mode;
+ struct fb_videomode m;
+ int num;
fbi = framebuffer_alloc(sizeof(struct mxc_elcdif_fb_data), &pdev->dev);
if (fbi == NULL) {
@@ -1296,20 +1366,63 @@ static int mxc_elcdif_fb_probe(struct platform_device *pdev)
if (pdata && !data->output_pix_fmt)
data->output_pix_fmt = pdata->interface_pix_fmt;
+ INIT_LIST_HEAD(&fbi->modelist);
+
if (pdata && pdata->mode && pdata->num_modes)
fb_videomode_to_modelist(pdata->mode, pdata->num_modes,
&fbi->modelist);
+ if (mxc_disp_mode.num_modes) {
+ int i;
+ mode = mxc_disp_mode.mode;
+ num = mxc_disp_mode.num_modes;
+
+ for (i = 0; i < num; i++) {
+ /*
+ * FIXME now we do not support interlaced
+ * mode for ddc mode
+ */
+ if ((mxc_disp_mode.dev_mode
+ & MXC_DISP_DDC_DEV) &&
+ (mode[i].vmode & FB_VMODE_INTERLACED))
+ continue;
+ else {
+ dev_dbg(&pdev->dev, "Added mode %d:", i);
+ dev_dbg(&pdev->dev,
+ "xres = %d, yres = %d, freq = %d, vmode = %d, flag = %d\n",
+ mode[i].xres, mode[i].yres, mode[i].refresh, mode[i].vmode,
+ mode[i].flag);
+ fb_add_videomode(&mode[i], &fbi->modelist);
+ }
+ }
+ }
+
if (!fb_mode && pdata && pdata->mode_str)
fb_mode = pdata->mode_str;
if (fb_mode) {
+ dev_dbg(&pdev->dev, "default video mode %s\n", fb_mode);
ret = fb_find_mode(&fbi->var, fbi, fb_mode, NULL, 0, NULL,
default_bpp);
- if ((!ret || (ret > 2)) && pdata && pdata->mode &&
- pdata->num_modes)
- fb_find_mode(&fbi->var, fbi, fb_mode, pdata->mode,
+ if ((ret == 1) || (ret == 2)) {
+ fb_var_to_videomode(&m, &fbi->var);
+ dump_fb_videomode(&m);
+ mode = fb_find_nearest_mode(&m,
+ &fbi->modelist);
+ fb_videomode_to_var(&fbi->var, mode);
+ } else if (pdata && pdata->mode && pdata->num_modes) {
+ ret = fb_find_mode(&fbi->var, fbi, fb_mode, pdata->mode,
pdata->num_modes, NULL, default_bpp);
+ if (!ret) {
+ dev_err(fbi->device,
+ "No valid video mode found");
+ goto err2;
+ }
+ } else {
+ dev_err(fbi->device,
+ "No valid video mode found");
+ goto err2;
+ }
}
mxc_elcdif_fb_check_var(&fbi->var, fbi);
@@ -1343,6 +1456,19 @@ static int mxc_elcdif_fb_probe(struct platform_device *pdev)
*/
clk_set_rate(g_elcdif_pix_clk, 25000000);
+ fbi->var.activate |= FB_ACTIVATE_FORCE;
+ console_lock();
+ fbi->flags |= FBINFO_MISC_USEREVENT;
+ ret = fb_set_var(fbi, &fbi->var);
+ fbi->flags &= ~FBINFO_MISC_USEREVENT;
+ console_unlock();
+
+ if (data->cur_blank == FB_BLANK_UNBLANK) {
+ console_lock();
+ fb_blank(fbi, FB_BLANK_UNBLANK);
+ console_unlock();
+ }
+
ret = register_framebuffer(fbi);
if (ret)
goto err3;
diff --git a/drivers/video/mxc/mxc_epdc_fb.c b/drivers/video/mxc/mxc_epdc_fb.c
index 0b3923c2cea6..b702788ae823 100644
--- a/drivers/video/mxc/mxc_epdc_fb.c
+++ b/drivers/video/mxc/mxc_epdc_fb.c
@@ -50,6 +50,7 @@
#include <linux/bitops.h>
#include <mach/epdc.h>
#include <mach/dma.h>
+#include <asm/cacheflush.h>
#include "epdc_regs.h"
@@ -69,6 +70,10 @@
#define INVALID_LUT (-1)
#define DRY_RUN_NO_LUT 100
+/* Maximum update buffer image width due to v2.0 and v2.1 errata ERR005313. */
+#define EPDC_V2_MAX_UPDATE_WIDTH 2047
+#define EPDC_V2_ROTATION_ALIGNMENT 8
+
#define DEFAULT_TEMP_INDEX 0
#define DEFAULT_TEMP 20 /* room temp in deg Celsius */
@@ -202,6 +207,8 @@ struct mxc_epdc_fb_data {
bool updates_active;
int pwrdown_delay;
unsigned long tce_prevent;
+ bool restrict_width; /* work around rev >=2.0 width and
+ stride restriction */
/* FB elements related to PxP DMA */
struct completion pxp_tx_cmpl;
@@ -262,6 +269,16 @@ static int pxp_complete_update(struct mxc_epdc_fb_data *fb_data, u32 *hist_stat)
static void draw_mode0(struct mxc_epdc_fb_data *fb_data);
static bool is_free_list_full(struct mxc_epdc_fb_data *fb_data);
+static void do_dithering_processing_Y1_v1_0(
+ unsigned char *update_region_ptr,
+ struct mxcfb_rect *update_region,
+ unsigned long update_region_stride,
+ int *err_dist);
+static void do_dithering_processing_Y4_v1_0(
+ unsigned char *update_region_ptr,
+ struct mxcfb_rect *update_region,
+ unsigned long update_region_stride,
+ int *err_dist);
#ifdef DEBUG
static void dump_pxp_config(struct mxc_epdc_fb_data *fb_data,
@@ -1930,10 +1947,10 @@ static int epdc_process_update(struct update_data_list *upd_data_list,
* to copybuf in addition to the PxP structures */
mutex_lock(&fb_data->pxp_mutex);
- if ((((width_unaligned || height_unaligned || input_unaligned) &&
+ if (((((width_unaligned || height_unaligned || input_unaligned) &&
(upd_desc_list->upd_data.waveform_mode == WAVEFORM_MODE_AUTO))
- || line_overflow) && (fb_data->rev < 20)) {
-
+ || line_overflow) && (fb_data->rev < 20)) ||
+ fb_data->restrict_width) {
dev_dbg(fb_data->dev, "Copying update before processing.\n");
/* Update to reflect what the new source buffer will be */
@@ -2137,7 +2154,8 @@ static int epdc_process_update(struct update_data_list *upd_data_list,
}
static int epdc_submit_merge(struct update_desc_list *upd_desc_list,
- struct update_desc_list *update_to_merge)
+ struct update_desc_list *update_to_merge,
+ struct mxc_epdc_fb_data *fb_data)
{
struct mxcfb_update_data *a, *b;
struct mxcfb_rect *arect, *brect;
@@ -2195,6 +2213,19 @@ static int epdc_submit_merge(struct update_desc_list *upd_desc_list,
(arect->top + arect->height - combine.top) :
(brect->top + brect->height - combine.top);
+ /* Don't merge if combined width exceeds max width */
+ if (fb_data->restrict_width) {
+ u32 max_width = EPDC_V2_MAX_UPDATE_WIDTH;
+ u32 combined_width = combine.width;
+ if (fb_data->epdc_fb_var.rotate != FB_ROTATE_UR)
+ max_width -= EPDC_V2_ROTATION_ALIGNMENT;
+ if ((fb_data->epdc_fb_var.rotate == FB_ROTATE_CW) ||
+ (fb_data->epdc_fb_var.rotate == FB_ROTATE_CCW))
+ combined_width = combine.height;
+ if (combined_width > max_width)
+ return MERGE_FAIL;
+ }
+
*arect = combine;
/* Use flags of the later update */
@@ -2226,6 +2257,7 @@ static void epdc_submit_work_func(struct work_struct *work)
bool end_merge = false;
bool is_transform;
u32 update_addr;
+ int *err_dist;
int ret;
/* Protect access to buffer queues and to update HW */
@@ -2260,7 +2292,8 @@ static void epdc_submit_work_func(struct work_struct *work)
break;
} else {
switch (epdc_submit_merge(upd_data_list->update_desc,
- next_update->update_desc)) {
+ next_update->update_desc,
+ fb_data)) {
case MERGE_OK:
dev_dbg(fb_data->dev,
"Update merged [collision]\n");
@@ -2330,7 +2363,7 @@ static void epdc_submit_work_func(struct work_struct *work)
break;
} else {
switch (epdc_submit_merge(upd_data_list->update_desc,
- next_desc)) {
+ next_desc, fb_data)) {
case MERGE_OK:
dev_dbg(fb_data->dev,
"Update merged [queue]\n");
@@ -2371,12 +2404,14 @@ static void epdc_submit_work_func(struct work_struct *work)
* PxP in versions 2.0 and earlier of EPDC.
*/
is_transform = upd_data_list->update_desc->upd_data.flags &
- (EPDC_FLAG_ENABLE_INVERSION |
- EPDC_FLAG_FORCE_MONOCHROME | EPDC_FLAG_USE_CMAP) ?
- true : false;
+ (EPDC_FLAG_ENABLE_INVERSION | EPDC_FLAG_USE_DITHERING_Y1 |
+ EPDC_FLAG_USE_DITHERING_Y4 | EPDC_FLAG_FORCE_MONOCHROME |
+ EPDC_FLAG_USE_CMAP) ? true : false;
+
if ((fb_data->epdc_fb_var.rotate == FB_ROTATE_UR) &&
(fb_data->epdc_fb_var.grayscale == GRAYSCALE_8BIT) &&
- !is_transform && (fb_data->rev > 20)) {
+ !is_transform && (fb_data->rev > 20) &&
+ !fb_data->restrict_width) {
/* If needed, enable EPDC HW while ePxP is processing */
if ((fb_data->power_state == POWER_STATE_OFF)
@@ -2391,7 +2426,6 @@ static void epdc_submit_work_func(struct work_struct *work)
update_addr = fb_data->info.fix.smem_start +
((upd_region->top * fb_data->info.var.xres_virtual) +
upd_region->left) * fb_data->info.var.bits_per_pixel/8;
-
upd_data_list->update_desc->epdc_stride =
fb_data->info.var.xres_virtual *
fb_data->info.var.bits_per_pixel/8;
@@ -2457,6 +2491,45 @@ static void epdc_submit_work_func(struct work_struct *work)
}
/*
+ * Dithering Processing (Version 1.0 - for i.MX508 and i.MX6SL)
+ */
+ if (upd_data_list->update_desc->upd_data.flags &
+ EPDC_FLAG_USE_DITHERING_Y1) {
+
+ err_dist = kzalloc((fb_data->info.var.xres_virtual + 3) * 3
+ * sizeof(int), GFP_KERNEL);
+
+ /* Dithering Y8 -> Y1 */
+ do_dithering_processing_Y1_v1_0(
+ (uint8_t *)(upd_data_list->virt_addr +
+ upd_data_list->update_desc->epdc_offs),
+ &adj_update_region,
+ (fb_data->rev < 20) ?
+ ALIGN(adj_update_region.width, 8) :
+ adj_update_region.width,
+ err_dist);
+
+ kfree(err_dist);
+ } else if (upd_data_list->update_desc->upd_data.flags &
+ EPDC_FLAG_USE_DITHERING_Y4) {
+
+ err_dist = kzalloc((fb_data->info.var.xres_virtual + 3) * 3
+ * sizeof(int), GFP_KERNEL);
+
+ /* Dithering Y8 -> Y1 */
+ do_dithering_processing_Y4_v1_0(
+ (uint8_t *)(upd_data_list->virt_addr +
+ upd_data_list->update_desc->epdc_offs),
+ &adj_update_region,
+ (fb_data->rev < 20) ?
+ ALIGN(adj_update_region.width, 8) :
+ adj_update_region.width,
+ err_dist);
+
+ kfree(err_dist);
+ }
+
+ /*
* If there are no LUTs available,
* then we must wait for the resource to become free.
* The IST will signal this event.
@@ -2572,8 +2645,7 @@ static void epdc_submit_work_func(struct work_struct *work)
mutex_unlock(&fb_data->queue_mutex);
}
-
-int mxc_epdc_fb_send_update(struct mxcfb_update_data *upd_data,
+static int mxc_epdc_fb_send_single_update(struct mxcfb_update_data *upd_data,
struct fb_info *info)
{
struct mxc_epdc_fb_data *fb_data = info ?
@@ -2868,6 +2940,63 @@ int mxc_epdc_fb_send_update(struct mxcfb_update_data *upd_data,
mutex_unlock(&fb_data->queue_mutex);
return 0;
}
+
+int mxc_epdc_fb_send_update(struct mxcfb_update_data *upd_data,
+ struct fb_info *info)
+{
+ struct mxc_epdc_fb_data *fb_data = info ?
+ (struct mxc_epdc_fb_data *)info:g_fb_data;
+
+ if (!fb_data->restrict_width) {
+ /* No width restriction, send entire update region */
+ return mxc_epdc_fb_send_single_update(upd_data, info);
+ } else {
+ int ret;
+ __u32 width, left;
+ __u32 marker;
+ __u32 *region_width, *region_left;
+ u32 max_upd_width = EPDC_V2_MAX_UPDATE_WIDTH;
+
+ /* Further restrict max width due to pxp rotation
+ * alignment requirement
+ */
+ if (fb_data->epdc_fb_var.rotate != FB_ROTATE_UR)
+ max_upd_width -= EPDC_V2_ROTATION_ALIGNMENT;
+
+ /* Select split of width or height based on rotation */
+ if ((fb_data->epdc_fb_var.rotate == FB_ROTATE_UR) ||
+ (fb_data->epdc_fb_var.rotate == FB_ROTATE_UD)) {
+ region_width = &upd_data->update_region.width;
+ region_left = &upd_data->update_region.left;
+ } else {
+ region_width = &upd_data->update_region.height;
+ region_left = &upd_data->update_region.top;
+ }
+
+ if (*region_width <= max_upd_width)
+ return mxc_epdc_fb_send_single_update(upd_data, info);
+
+ width = *region_width;
+ left = *region_left;
+ marker = upd_data->update_marker;
+ upd_data->update_marker = 0;
+
+ do {
+ *region_width = max_upd_width;
+ *region_left = left;
+ ret = mxc_epdc_fb_send_single_update(upd_data, info);
+ if (ret)
+ return ret;
+ width -= max_upd_width;
+ left += max_upd_width;
+ } while (width > max_upd_width);
+
+ *region_width = width;
+ *region_left = left;
+ upd_data->update_marker = marker;
+ return mxc_epdc_fb_send_single_update(upd_data, info);
+ }
+}
EXPORT_SYMBOL(mxc_epdc_fb_send_update);
int mxc_epdc_fb_wait_update_complete(struct mxcfb_update_marker_data *marker_data,
@@ -3041,6 +3170,25 @@ static int mxc_epdc_fb_ioctl(struct fb_info *info, unsigned int cmd,
ret = 0;
break;
}
+
+ case MXCFB_GET_WORK_BUFFER:
+ {
+ /* copy the epdc working buffer to the user space */
+ struct mxc_epdc_fb_data *fb_data = info ?
+ (struct mxc_epdc_fb_data *)info:g_fb_data;
+ flush_cache_all();
+ outer_flush_all();
+ if (copy_to_user((void __user *)arg,
+ (const void *) fb_data->working_buffer_virt,
+ fb_data->working_buffer_size))
+ ret = -EFAULT;
+ else
+ ret = 0;
+ flush_cache_all();
+ outer_flush_all();
+ break;
+ }
+
default:
break;
}
@@ -4076,7 +4224,8 @@ static void mxc_epdc_fb_fw_handler(const struct firmware *fw,
&fb_data->info);
if (ret < 0)
dev_err(fb_data->dev,
- "Wait for update complete failed. Error = 0x%x", ret);
+ "Wait for initial update complete failed."
+ " Error = 0x%x", ret);
}
static int mxc_epdc_fb_init_hw(struct fb_info *info)
@@ -4417,6 +4566,8 @@ int __devinit mxc_epdc_fb_probe(struct platform_device *pdev)
} else {
fb_data->num_luts = EPDC_V2_NUM_LUTS;
fb_data->max_num_updates = EPDC_V2_MAX_NUM_UPDATES;
+ if (vmode->xres > EPDC_V2_MAX_UPDATE_WIDTH)
+ fb_data->restrict_width = true;
}
fb_data->max_num_buffers = EPDC_MAX_NUM_BUFFERS;
@@ -4454,8 +4605,9 @@ int __devinit mxc_epdc_fb_probe(struct platform_device *pdev)
* be as big as the full-screen frame buffer
*/
fb_data->virt_addr_updbuf[i] =
- dma_alloc_coherent(fb_data->info.device, fb_data->max_pix_size,
- &fb_data->phys_addr_updbuf[i], GFP_DMA);
+ kmalloc(fb_data->max_pix_size, GFP_KERNEL);
+ fb_data->phys_addr_updbuf[i] =
+ virt_to_phys(fb_data->virt_addr_updbuf[i]);
if (fb_data->virt_addr_updbuf[i] == NULL) {
ret = -ENOMEM;
goto out_upd_buffers;
@@ -4737,10 +4889,7 @@ out_copybuffer:
out_upd_buffers:
for (i = 0; i < fb_data->max_num_buffers; i++)
if (fb_data->virt_addr_updbuf[i] != NULL)
- dma_free_writecombine(&pdev->dev,
- fb_data->max_pix_size,
- fb_data->virt_addr_updbuf[i],
- fb_data->phys_addr_updbuf[i]);
+ kfree(fb_data->virt_addr_updbuf[i]);
if (fb_data->virt_addr_updbuf != NULL)
kfree(fb_data->virt_addr_updbuf);
if (fb_data->phys_addr_updbuf != NULL)
@@ -4785,9 +4934,7 @@ static int mxc_epdc_fb_remove(struct platform_device *pdev)
for (i = 0; i < fb_data->max_num_buffers; i++)
if (fb_data->virt_addr_updbuf[i] != NULL)
- dma_free_writecombine(&pdev->dev, fb_data->max_pix_size,
- fb_data->virt_addr_updbuf[i],
- fb_data->phys_addr_updbuf[i]);
+ kfree(fb_data->virt_addr_updbuf[i]);
if (fb_data->virt_addr_updbuf != NULL)
kfree(fb_data->virt_addr_updbuf);
if (fb_data->phys_addr_updbuf != NULL)
@@ -5082,6 +5229,124 @@ static int pxp_complete_update(struct mxc_epdc_fb_data *fb_data, u32 *hist_stat)
return 0;
}
+/*
+ * Different dithering algorithm can be used. We chose
+ * to implement Bill Atkinson's algorithm as an example
+ * Thanks Bill Atkinson for his dithering algorithm.
+ */
+
+/*
+ * Dithering algorithm implementation - Y8->Y1 version 1.0 for i.MX
+ */
+static void do_dithering_processing_Y1_v1_0(
+ unsigned char *update_region_ptr,
+ struct mxcfb_rect *update_region,
+ unsigned long update_region_stride,
+ int *err_dist)
+{
+
+ /* create a temp error distribution array */
+ int bwPix;
+ int y;
+ int col;
+ int *err_dist_l0, *err_dist_l1, *err_dist_l2, distrib_error;
+ int width_3 = update_region->width + 3;
+ char *y8buf;
+ int x_offset = 0;
+
+ /* prime a few elements the error distribution array */
+ for (y = 0; y < update_region->height; y++) {
+ /* Dithering the Y8 in sbuf to BW suitable for A2 waveform */
+ err_dist_l0 = err_dist + (width_3) * (y % 3);
+ err_dist_l1 = err_dist + (width_3) * ((y + 1) % 3);
+ err_dist_l2 = err_dist + (width_3) * ((y + 2) % 3);
+
+ y8buf = update_region_ptr + x_offset;
+
+ /* scan the line and convert the Y8 to BW */
+ for (col = 1; col <= update_region->width; col++) {
+ bwPix = *(err_dist_l0 + col) + *y8buf;
+
+ if (bwPix >= 128) {
+ *y8buf++ = 0xff;
+ distrib_error = (bwPix - 255) >> 3;
+ } else {
+ *y8buf++ = 0;
+ distrib_error = bwPix >> 3;
+ }
+
+ /* modify the error distribution buffer */
+ *(err_dist_l0 + col + 2) += distrib_error;
+ *(err_dist_l1 + col + 1) += distrib_error;
+ *(err_dist_l0 + col + 1) += distrib_error;
+ *(err_dist_l1 + col - 1) += distrib_error;
+ *(err_dist_l1 + col) += distrib_error;
+ *(err_dist_l2 + col) = distrib_error;
+ }
+ x_offset += update_region_stride;
+ }
+
+ flush_cache_all();
+ outer_flush_all();
+}
+
+/*
+ * Dithering algorithm implementation - Y8->Y4 version 1.0 for i.MX
+ */
+
+static void do_dithering_processing_Y4_v1_0(
+ unsigned char *update_region_ptr,
+ struct mxcfb_rect *update_region,
+ unsigned long update_region_stride,
+ int *err_dist)
+{
+
+ /* create a temp error distribution array */
+ int gcPix;
+ int y;
+ int col;
+ int *err_dist_l0, *err_dist_l1, *err_dist_l2, distrib_error;
+ int width_3 = update_region->width + 3;
+ char *y8buf;
+ int x_offset = 0;
+
+ /* prime a few elements the error distribution array */
+ for (y = 0; y < update_region->height; y++) {
+ /* Dithering the Y8 in sbuf to Y4 */
+ err_dist_l0 = err_dist + (width_3) * (y % 3);
+ err_dist_l1 = err_dist + (width_3) * ((y + 1) % 3);
+ err_dist_l2 = err_dist + (width_3) * ((y + 2) % 3);
+
+ y8buf = update_region_ptr + x_offset;
+
+ /* scan the line and convert the Y8 to Y4 */
+ for (col = 1; col <= update_region->width; col++) {
+ gcPix = *(err_dist_l0 + col) + *y8buf;
+
+ if (gcPix > 255)
+ gcPix = 255;
+ else if (gcPix < 0)
+ gcPix = 0;
+
+ distrib_error = (*y8buf - (gcPix & 0xf0)) >> 3;
+
+ *y8buf++ = gcPix & 0xf0;
+
+ /* modify the error distribution buffer */
+ *(err_dist_l0 + col + 2) += distrib_error;
+ *(err_dist_l1 + col + 1) += distrib_error;
+ *(err_dist_l0 + col + 1) += distrib_error;
+ *(err_dist_l1 + col - 1) += distrib_error;
+ *(err_dist_l1 + col) += distrib_error;
+ *(err_dist_l2 + col) = distrib_error;
+ }
+ x_offset += update_region_stride;
+ }
+
+ flush_cache_all();
+ outer_flush_all();
+}
+
static int __init mxc_epdc_fb_init(void)
{
return platform_driver_register(&mxc_epdc_fb_driver);
diff --git a/drivers/video/mxc/mxcfb_sii902x_elcdif.c b/drivers/video/mxc/mxcfb_sii902x_elcdif.c
new file mode 100644
index 000000000000..ceab3e66e91c
--- /dev/null
+++ b/drivers/video/mxc/mxcfb_sii902x_elcdif.c
@@ -0,0 +1,560 @@
+/*
+ * Copyright (C) 2010-2012 Freescale Semiconductor, Inc. All Rights Reserved.
+ */
+
+/*
+ * 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.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+/*!
+ * @defgroup Framebuffer Framebuffer Driver for SDC and ADC.
+ */
+
+/*!
+ * @file mxcfb_sii902x_elcdif.c
+ *
+ * @brief MXC ELCDIF Frame buffer driver for SII902x
+ *
+ * @ingroup Framebuffer
+ */
+
+/*!
+ * Include files
+ */
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/console.h>
+#include <linux/delay.h>
+#include <linux/errno.h>
+#include <linux/fb.h>
+#include <linux/init.h>
+#include <linux/platform_device.h>
+#include <linux/regulator/consumer.h>
+#include <linux/i2c.h>
+#include <linux/mxcfb.h>
+#include <linux/fsl_devices.h>
+#include <linux/interrupt.h>
+#include <asm/mach-types.h>
+#include <mach/hardware.h>
+#include <mach/mxc_edid.h>
+
+#define SII_EDID_LEN 512
+#define MXC_ENABLE 1
+#define MXC_DISABLE 2
+
+struct sii902x_data {
+ struct platform_device *pdev;
+ struct i2c_client *client;
+ struct delayed_work det_work;
+ struct fb_info *fbi;
+ struct mxc_edid_cfg edid_cfg;
+ u8 cable_plugin;
+ u8 edid[SII_EDID_LEN];
+ bool waiting_for_fb;
+} sii902x;
+
+static void sii902x_poweron(void);
+static void sii902x_poweroff(void);
+static void (*sii902x_reset) (void);
+
+#ifdef DEBUG
+static void dump_fb_videomode(struct fb_videomode *m)
+{
+ pr_debug("fb_videomode = %d %d %d %d %d %d %d %d %d %d %d %d %d\n",
+ m->refresh, m->xres, m->yres, m->pixclock, m->left_margin,
+ m->right_margin, m->upper_margin, m->lower_margin,
+ m->hsync_len, m->vsync_len, m->sync, m->vmode, m->flag);
+}
+#else
+static void dump_fb_videomode(struct fb_videomode *m)
+{}
+#endif
+
+static __attribute__ ((unused)) void dump_regs(u8 reg, int len)
+{
+ u8 buf[50];
+ int i;
+
+ i2c_smbus_read_i2c_block_data(sii902x.client, reg, len, buf);
+ for (i = 0; i < len; i++)
+ dev_dbg(&sii902x.client->dev, "reg[0x%02X]: 0x%02X\n",
+ i+reg, buf[i]);
+}
+
+static ssize_t sii902x_show_name(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ strcpy(buf, sii902x.fbi->fix.id);
+ sprintf(buf+strlen(buf), "\n");
+
+ return strlen(buf);
+}
+
+static DEVICE_ATTR(fb_name, S_IRUGO, sii902x_show_name, NULL);
+
+static ssize_t sii902x_show_state(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ if (sii902x.cable_plugin == 0)
+ strcpy(buf, "plugout\n");
+ else
+ strcpy(buf, "plugin\n");
+
+ return strlen(buf);
+}
+
+static DEVICE_ATTR(cable_state, S_IRUGO, sii902x_show_state, NULL);
+
+static ssize_t sii902x_show_edid(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ int i, j, len = 0;
+
+ for (j = 0; j < SII_EDID_LEN/16; j++) {
+ for (i = 0; i < 16; i++)
+ len += sprintf(buf+len, "0x%02X ",
+ sii902x.edid[j*16 + i]);
+ len += sprintf(buf+len, "\n");
+ }
+
+ return len;
+}
+
+static DEVICE_ATTR(edid, S_IRUGO, sii902x_show_edid, NULL);
+
+static void sii902x_setup(struct fb_info *fbi)
+{
+ u16 data[4];
+ u32 refresh;
+ u8 *tmp;
+ int i;
+
+ dev_dbg(&sii902x.client->dev, "Sii902x: setup..\n");
+
+ /* Power up */
+ i2c_smbus_write_byte_data(sii902x.client, 0x1E, 0x00);
+
+ /* set TPI video mode */
+ data[0] = PICOS2KHZ(fbi->var.pixclock) / 10;
+ data[2] = fbi->var.hsync_len + fbi->var.left_margin +
+ fbi->var.xres + fbi->var.right_margin;
+ data[3] = fbi->var.vsync_len + fbi->var.upper_margin +
+ fbi->var.yres + fbi->var.lower_margin;
+ refresh = data[2] * data[3];
+ refresh = (PICOS2KHZ(fbi->var.pixclock) * 1000) / refresh;
+ data[1] = refresh * 100;
+ tmp = (u8 *)data;
+ for (i = 0; i < 8; i++)
+ i2c_smbus_write_byte_data(sii902x.client, i, tmp[i]);
+
+ /* input bus/pixel: full pixel wide (24bit), rising edge */
+ i2c_smbus_write_byte_data(sii902x.client, 0x08, 0x70);
+ /* Set input format to RGB */
+ i2c_smbus_write_byte_data(sii902x.client, 0x09, 0x00);
+ /* set output format to RGB */
+ i2c_smbus_write_byte_data(sii902x.client, 0x0A, 0x00);
+ /* audio setup */
+ i2c_smbus_write_byte_data(sii902x.client, 0x25, 0x00);
+ i2c_smbus_write_byte_data(sii902x.client, 0x26, 0x40);
+ i2c_smbus_write_byte_data(sii902x.client, 0x27, 0x00);
+}
+
+#ifdef CONFIG_FB_MODE_HELPERS
+static int sii902x_read_edid(struct fb_info *fbi)
+{
+ int old, dat, ret, cnt = 100;
+ unsigned short addr = 0x50;
+
+ dev_dbg(&sii902x.pdev->dev, "%s\n", __func__);
+
+ old = i2c_smbus_read_byte_data(sii902x.client, 0x1A);
+
+ i2c_smbus_write_byte_data(sii902x.client, 0x1A, old | 0x4);
+ do {
+ cnt--;
+ msleep(10);
+ dat = i2c_smbus_read_byte_data(sii902x.client, 0x1A);
+ } while ((!(dat & 0x2)) && cnt);
+
+ if (!cnt) {
+ ret = -1;
+ goto done;
+ }
+
+ i2c_smbus_write_byte_data(sii902x.client, 0x1A, old | 0x06);
+
+ /* edid reading */
+ ret = mxc_edid_read(sii902x.client->adapter, addr,
+ sii902x.edid, &sii902x.edid_cfg, fbi);
+
+ cnt = 100;
+ do {
+ cnt--;
+ i2c_smbus_write_byte_data(sii902x.client, 0x1A, old & ~0x6);
+ msleep(10);
+ dat = i2c_smbus_read_byte_data(sii902x.client, 0x1A);
+ } while ((dat & 0x6) && cnt);
+
+ if (!cnt)
+ ret = -1;
+
+done:
+
+ i2c_smbus_write_byte_data(sii902x.client, 0x1A, old);
+ return ret;
+}
+#else
+static int sii902x_read_edid(struct fb_info *fbi)
+{
+ return -1;
+}
+#endif
+
+static void det_worker(struct work_struct *work)
+{
+ int dat;
+ char event_string[16];
+ char *envp[] = { event_string, NULL };
+
+ dev_dbg(&sii902x.pdev->dev, "%s\n", __func__);
+
+ dat = i2c_smbus_read_byte_data(sii902x.client, 0x3D);
+ if (dat & 0x1) {
+ /* cable connection changes */
+ if (dat & 0x4) {
+ sii902x.cable_plugin = 1;
+ dev_dbg(&sii902x.pdev->dev, "EVENT=plugin\n");
+ sprintf(event_string, "EVENT=plugin");
+
+ /* make sure fb is powerdown */
+ console_lock();
+ fb_blank(sii902x.fbi, FB_BLANK_POWERDOWN);
+ console_unlock();
+
+ if (sii902x_read_edid(sii902x.fbi) < 0)
+ dev_err(&sii902x.client->dev,
+ "Sii902x: read edid fail\n");
+ else {
+ if (sii902x.fbi->monspecs.modedb_len > 0) {
+
+ int i;
+ const struct fb_videomode *mode;
+ struct fb_videomode m;
+
+ fb_destroy_modelist(&sii902x.fbi->modelist);
+
+ for (i = 0; i < sii902x.fbi->monspecs.modedb_len; i++) {
+ /*FIXME now we do not support interlaced mode */
+ mode = &sii902x.fbi->monspecs.modedb[i];
+
+ if (!(mode->vmode & FB_VMODE_INTERLACED)) {
+
+ dev_dbg(&sii902x.pdev->dev, "Added mode %d:", i);
+ dev_dbg(&sii902x.pdev->dev,
+ "xres = %d, yres = %d, freq = %d, vmode = %d, flag = %d\n",
+ mode->xres, mode->yres, mode->refresh,
+ mode->vmode, mode->flag);
+
+ fb_add_videomode(mode, &sii902x.fbi->modelist);
+ }
+ }
+
+ fb_var_to_videomode(&m, &sii902x.fbi->var);
+ dump_fb_videomode(&m);
+
+ mode = fb_find_nearest_mode(&m,
+ &sii902x.fbi->modelist);
+
+ fb_videomode_to_var(&sii902x.fbi->var, mode);
+
+ sii902x.fbi->var.activate |= FB_ACTIVATE_FORCE;
+ console_lock();
+ sii902x.fbi->flags |= FBINFO_MISC_USEREVENT;
+ fb_set_var(sii902x.fbi, &sii902x.fbi->var);
+ sii902x.fbi->flags &= ~FBINFO_MISC_USEREVENT;
+ console_unlock();
+ }
+
+ console_lock();
+ fb_blank(sii902x.fbi, FB_BLANK_UNBLANK);
+ console_unlock();
+ }
+ } else {
+ sii902x.cable_plugin = 0;
+ dev_dbg(&sii902x.pdev->dev, "EVENT=plugout\n");
+ sprintf(event_string, "EVENT=plugout");
+ console_lock();
+ fb_blank(sii902x.fbi, FB_BLANK_POWERDOWN);
+ console_unlock();
+ }
+ kobject_uevent_env(&sii902x.pdev->dev.kobj, KOBJ_CHANGE, envp);
+ }
+ i2c_smbus_write_byte_data(sii902x.client, 0x3D, dat);
+
+ dev_dbg(&sii902x.pdev->dev, "exit %s\n", __func__);
+
+}
+
+static irqreturn_t sii902x_detect_handler(int irq, void *data)
+{
+ if (sii902x.fbi)
+ schedule_delayed_work(&(sii902x.det_work), msecs_to_jiffies(20));
+ else
+ sii902x.waiting_for_fb = true;
+
+ return IRQ_HANDLED;
+}
+
+static int sii902x_fb_event(struct notifier_block *nb, unsigned long val, void *v)
+{
+ struct fb_event *event = v;
+ struct fb_info *fbi = event->info;
+
+ dev_dbg(&sii902x.pdev->dev, "%s\n", __func__);
+
+ switch (val) {
+ case FB_EVENT_FB_REGISTERED:
+ if (sii902x.fbi == NULL) {
+ sii902x.fbi = fbi;
+ if (sii902x.waiting_for_fb)
+ det_worker(NULL);
+ }
+ fb_show_logo(fbi, 0);
+ break;
+ case FB_EVENT_MODE_CHANGE:
+ sii902x_setup(fbi);
+ break;
+ case FB_EVENT_BLANK:
+ if (*((int *)event->data) == FB_BLANK_UNBLANK) {
+ dev_dbg(&sii902x.pdev->dev, "FB_BLANK_UNBLANK\n");
+ sii902x_poweron();
+ } else {
+ dev_dbg(&sii902x.pdev->dev, "FB_BLANK_BLANK\n");
+ sii902x_poweroff();
+ }
+ break;
+ }
+ return 0;
+}
+
+static struct notifier_block nb = {
+ .notifier_call = sii902x_fb_event,
+};
+
+static int __devinit sii902x_probe(struct i2c_client *client,
+ const struct i2c_device_id *id)
+{
+ int i, dat, ret;
+ struct fsl_mxc_lcd_platform_data *plat = client->dev.platform_data;
+ struct fb_info edid_fbi;
+
+ dev_dbg(&sii902x.pdev->dev, "%s\n", __func__);;
+
+ sii902x.client = client;
+
+ /* Claim HDMI pins */
+ if (plat->get_pins)
+ if (!plat->get_pins())
+ return -EACCES;
+
+ if (plat->reset) {
+ sii902x_reset = plat->reset;
+ sii902x_reset();
+ }
+
+ /* Set 902x in hardware TPI mode on and jump out of D3 state */
+ if (i2c_smbus_write_byte_data(sii902x.client, 0xc7, 0x00) < 0) {
+ dev_err(&sii902x.client->dev,
+ "Sii902x: cound not find device\n");
+ return -ENODEV;
+ }
+
+ /* read device ID */
+ for (i = 10; i > 0; i--) {
+ dat = i2c_smbus_read_byte_data(sii902x.client, 0x1B);
+ printk(KERN_DEBUG "Sii902x: read id = 0x%02X", dat);
+ if (dat == 0xb0) {
+ dat = i2c_smbus_read_byte_data(sii902x.client, 0x1C);
+ printk(KERN_DEBUG "-0x%02X", dat);
+ dat = i2c_smbus_read_byte_data(sii902x.client, 0x1D);
+ printk(KERN_DEBUG "-0x%02X", dat);
+ dat = i2c_smbus_read_byte_data(sii902x.client, 0x30);
+ printk(KERN_DEBUG "-0x%02X\n", dat);
+ break;
+ }
+ }
+ if (i == 0) {
+ dev_err(&sii902x.client->dev,
+ "Sii902x: cound not find device\n");
+ return -ENODEV;
+ }
+
+ /* try to read edid */
+ ret = sii902x_read_edid(&edid_fbi);
+ if (ret < 0)
+ dev_warn(&sii902x.client->dev, "Can not read edid\n");
+
+ if (ret >= 0)
+ mxcfb_elcdif_register_mode(edid_fbi.monspecs.modedb,
+ edid_fbi.monspecs.modedb_len, MXC_DISP_DDC_DEV);
+
+ if (sii902x.client->irq) {
+ ret = request_irq(sii902x.client->irq, sii902x_detect_handler,
+ IRQF_TRIGGER_FALLING,
+ "SII902x_det", &sii902x);
+ if (ret < 0)
+ dev_warn(&sii902x.client->dev,
+ "Sii902x: cound not request det irq %d\n",
+ sii902x.client->irq);
+ else {
+ /*enable cable hot plug irq*/
+ i2c_smbus_write_byte_data(sii902x.client, 0x3c, 0x01);
+ INIT_DELAYED_WORK(&(sii902x.det_work), det_worker);
+ }
+ ret = device_create_file(&sii902x.pdev->dev, &dev_attr_fb_name);
+ if (ret < 0)
+ dev_warn(&sii902x.client->dev,
+ "Sii902x: cound not create sys node for fb name\n");
+ ret = device_create_file(&sii902x.pdev->dev, &dev_attr_cable_state);
+ if (ret < 0)
+ dev_warn(&sii902x.client->dev,
+ "Sii902x: cound not create sys node for cable state\n");
+ ret = device_create_file(&sii902x.pdev->dev, &dev_attr_edid);
+ if (ret < 0)
+ dev_warn(&sii902x.client->dev,
+ "Sii902x: cound not create sys node for edid\n");
+
+ }
+
+ fb_register_client(&nb);
+
+ dev_dbg(&sii902x.pdev->dev, "%s exit\n", __func__);;
+
+ return 0;
+}
+
+static int __devexit sii902x_remove(struct i2c_client *client)
+{
+ struct fsl_mxc_lcd_platform_data *plat = sii902x.client->dev.platform_data;
+
+ dev_dbg(&sii902x.pdev->dev, "%s\n", __func__);
+
+ fb_unregister_client(&nb);
+ sii902x_poweroff();
+
+ /* Release HDMI pins */
+ if (plat->put_pins)
+ plat->put_pins();
+
+ return 0;
+}
+
+static int sii902x_suspend(struct i2c_client *client, pm_message_t message)
+{
+ /*TODO*/
+ return 0;
+}
+
+static int sii902x_resume(struct i2c_client *client)
+{
+ /*TODO*/
+ return 0;
+}
+
+static void sii902x_poweron(void)
+{
+ struct fsl_mxc_lcd_platform_data *plat = sii902x.client->dev.platform_data;
+
+ dev_dbg(&sii902x.pdev->dev, "%s\n", __func__);
+
+ /* Enable pins to HDMI */
+ if (plat->enable_pins)
+ plat->enable_pins();
+
+ /* Turn on DVI or HDMI */
+ if (sii902x.edid_cfg.hdmi_cap)
+ i2c_smbus_write_byte_data(sii902x.client, 0x1A, 0x01);
+ else
+ i2c_smbus_write_byte_data(sii902x.client, 0x1A, 0x00);
+ return;
+}
+
+static void sii902x_poweroff(void)
+{
+ struct fsl_mxc_lcd_platform_data *plat = sii902x.client->dev.platform_data;
+
+ dev_dbg(&sii902x.pdev->dev, "%s\n", __func__);
+
+ /* disable tmds before changing resolution */
+ if (sii902x.edid_cfg.hdmi_cap)
+ i2c_smbus_write_byte_data(sii902x.client, 0x1A, 0x11);
+ else
+ i2c_smbus_write_byte_data(sii902x.client, 0x1A, 0x10);
+
+ /* Disable pins to HDMI */
+ if (plat->disable_pins)
+ plat->disable_pins();
+
+ return;
+}
+
+static const struct i2c_device_id sii902x_id[] = {
+ { "sii902x", 0 },
+ {},
+};
+MODULE_DEVICE_TABLE(i2c, sii902x_id);
+
+static struct i2c_driver sii902x_i2c_driver = {
+ .driver = {
+ .name = "sii902x",
+ },
+ .probe = sii902x_probe,
+ .remove = sii902x_remove,
+ .suspend = sii902x_suspend,
+ .resume = sii902x_resume,
+ .id_table = sii902x_id,
+};
+
+static int __init sii902x_init(void)
+{
+ int ret;
+
+ memset(&sii902x, 0, sizeof(sii902x));
+
+ sii902x.pdev = platform_device_register_simple("sii902x", 0, NULL, 0);
+ if (IS_ERR(sii902x.pdev)) {
+ printk(KERN_ERR
+ "Unable to register Sii902x as a platform device\n");
+ ret = PTR_ERR(sii902x.pdev);
+ goto err;
+ }
+
+ return i2c_add_driver(&sii902x_i2c_driver);
+err:
+ return ret;
+}
+
+static void __exit sii902x_exit(void)
+{
+ i2c_del_driver(&sii902x_i2c_driver);
+ platform_device_unregister(sii902x.pdev);
+}
+
+module_init(sii902x_init);
+module_exit(sii902x_exit);
+
+MODULE_AUTHOR("Freescale Semiconductor, Inc.");
+MODULE_DESCRIPTION("SII902x DVI/HDMI driver");
+MODULE_LICENSE("GPL");
diff --git a/include/linux/fsl_devices.h b/include/linux/fsl_devices.h
index 2a9557307643..ab22c4a9472e 100644
--- a/include/linux/fsl_devices.h
+++ b/include/linux/fsl_devices.h
@@ -135,6 +135,7 @@ struct fsl_usb2_platform_data {
void (*platform_rh_suspend)(struct fsl_usb2_platform_data *);
void (*platform_rh_resume)(struct fsl_usb2_platform_data *);
void (*platform_set_disconnect_det)(struct fsl_usb2_platform_data *, bool);
+ void (*platform_phy_power_on)(void);
struct fsl_usb2_wakeup_platform_data *wakeup_pdata;
struct platform_device *pdev;
diff --git a/include/linux/mfd/mxc-hdmi-core.h b/include/linux/mfd/mxc-hdmi-core.h
index f16b11cb5cf4..26fa47d09abf 100644
--- a/include/linux/mfd/mxc-hdmi-core.h
+++ b/include/linux/mfd/mxc-hdmi-core.h
@@ -60,5 +60,6 @@ int mxc_hdmi_register_audio(struct snd_pcm_substream *substream);
void mxc_hdmi_unregister_audio(struct snd_pcm_substream *substream);
unsigned int hdmi_set_cable_state(unsigned int state);
unsigned int hdmi_set_blank_state(unsigned int state);
+int check_hdmi_state(void);
#endif
diff --git a/include/linux/mtd/nand.h b/include/linux/mtd/nand.h
index 1cd6d901dcd4..57aac193a943 100644
--- a/include/linux/mtd/nand.h
+++ b/include/linux/mtd/nand.h
@@ -373,15 +373,15 @@ struct nand_ecc_ctrl {
int (*correct)(struct mtd_info *mtd, uint8_t *dat, uint8_t *read_ecc,
uint8_t *calc_ecc);
int (*read_page_raw)(struct mtd_info *mtd, struct nand_chip *chip,
- uint8_t *buf, int page);
+ uint8_t *buf, int oob_required, int page);
void (*write_page_raw)(struct mtd_info *mtd, struct nand_chip *chip,
- const uint8_t *buf);
+ const uint8_t *buf, int oob_required);
int (*read_page)(struct mtd_info *mtd, struct nand_chip *chip,
- uint8_t *buf, int page);
+ uint8_t *buf, int oob_required, int page);
int (*read_subpage)(struct mtd_info *mtd, struct nand_chip *chip,
uint32_t offs, uint32_t len, uint8_t *buf);
void (*write_page)(struct mtd_info *mtd, struct nand_chip *chip,
- const uint8_t *buf);
+ const uint8_t *buf, int oob_required);
int (*read_oob)(struct mtd_info *mtd, struct nand_chip *chip, int page,
int sndcmd);
int (*write_oob)(struct mtd_info *mtd, struct nand_chip *chip,
@@ -507,7 +507,8 @@ struct nand_chip {
int (*errstat)(struct mtd_info *mtd, struct nand_chip *this, int state,
int status, int page);
int (*write_page)(struct mtd_info *mtd, struct nand_chip *chip,
- const uint8_t *buf, int page, int cached, int raw);
+ const uint8_t *buf, int oob_required, int page,
+ int cached, int raw);
int chip_delay;
unsigned int options;
diff --git a/include/linux/mxcfb.h b/include/linux/mxcfb.h
index 7588d9d09d16..962aa6072b82 100644
--- a/include/linux/mxcfb.h
+++ b/include/linux/mxcfb.h
@@ -92,6 +92,8 @@ struct mxcfb_rect {
#define EPDC_FLAG_USE_ALT_BUFFER 0x100
#define EPDC_FLAG_TEST_COLLISION 0x200
#define EPDC_FLAG_GROUP_UPDATE 0x400
+#define EPDC_FLAG_USE_DITHERING_Y1 0x2000
+#define EPDC_FLAG_USE_DITHERING_Y4 0x4000
#define FB_POWERDOWN_DISABLE -1
@@ -153,6 +155,7 @@ struct mxcfb_waveform_modes {
#define MXCFB_SET_PWRDOWN_DELAY _IOW('F', 0x30, int32_t)
#define MXCFB_GET_PWRDOWN_DELAY _IOR('F', 0x31, int32_t)
#define MXCFB_SET_UPDATE_SCHEME _IOW('F', 0x32, __u32)
+#define MXCFB_GET_WORK_BUFFER _IOWR('F', 0x34, unsigned long)
#ifdef __KERNEL__
@@ -160,6 +163,11 @@ extern struct fb_videomode mxcfb_modedb[];
extern int mxcfb_modedb_sz;
enum {
+ MXC_DISP_SPEC_DEV = 0,
+ MXC_DISP_DDC_DEV = 1,
+};
+
+enum {
MXCFB_REFRESH_OFF,
MXCFB_REFRESH_AUTO,
MXCFB_REFRESH_PARTIAL,
@@ -168,5 +176,8 @@ enum {
int mxcfb_set_refresh_mode(struct fb_info *fbi, int mode,
struct mxcfb_rect *update_region);
int mxc_elcdif_frame_addr_setup(dma_addr_t phys);
+void mxcfb_elcdif_register_mode(const struct fb_videomode *modedb,
+ int num_modes, int dev_mode);
+
#endif /* __KERNEL__ */
#endif
diff --git a/include/linux/power/sabresd_battery.h b/include/linux/power/sabresd_battery.h
index c251a748a0db..463fa90afdb6 100644
--- a/include/linux/power/sabresd_battery.h
+++ b/include/linux/power/sabresd_battery.h
@@ -38,6 +38,7 @@ struct max8903_pdata {
int flt; /* Fault output */
int dcm; /* Current-Limit Mode input (1: DC, 2: USB) */
int usus; /* USB Suspend Input (1: suspended) */
+ int feature_flag;/*battery capacity feature(0:enable, 1:disable)*/
/* DCM wired to Logic High
Set this true when DCM pin connect to Logic high.*/
diff --git a/sound/soc/codecs/wm8962.c b/sound/soc/codecs/wm8962.c
index b14531157067..784b5957e37a 100644
--- a/sound/soc/codecs/wm8962.c
+++ b/sound/soc/codecs/wm8962.c
@@ -2218,8 +2218,6 @@ SOC_ENUM("Capture LHPF Mode", cap_lhpf_mode),
SOC_DOUBLE_R_TLV("Sidetone Volume", WM8962_DAC_DSP_MIXING_1,
WM8962_DAC_DSP_MIXING_2, 4, 12, 0, st_tlv),
-SOC_DOUBLE_R_TLV("Digital Playback Volume", WM8962_LEFT_DAC_VOLUME,
- WM8962_RIGHT_DAC_VOLUME, 1, 127, 0, digital_tlv),
SOC_SINGLE("DAC High Performance Switch", WM8962_ADC_DAC_CONTROL_2, 0, 1, 0),
SOC_SINGLE("ADC High Performance Switch", WM8962_ADDITIONAL_CONTROL_1,
diff --git a/sound/soc/imx/imx-hdmi-dma.c b/sound/soc/imx/imx-hdmi-dma.c
index 8ada80e0cc74..342f9c85f481 100644
--- a/sound/soc/imx/imx-hdmi-dma.c
+++ b/sound/soc/imx/imx-hdmi-dma.c
@@ -1116,6 +1116,8 @@ static int hdmi_dma_trigger(struct snd_pcm_substream *substream, int cmd)
case SNDRV_PCM_TRIGGER_START:
case SNDRV_PCM_TRIGGER_RESUME:
case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
+ if (!check_hdmi_state())
+ return 0;
rtd->frame_idx = 0;
if (runtime->access == SNDRV_PCM_ACCESS_MMAP_INTERLEAVED) {
appl_bytes = frames_to_bytes(runtime,
diff --git a/sound/soc/imx/imx-spdif.c b/sound/soc/imx/imx-spdif.c
index efee7696bfbb..13c97aeb0622 100644
--- a/sound/soc/imx/imx-spdif.c
+++ b/sound/soc/imx/imx-spdif.c
@@ -1,7 +1,7 @@
/*
* ASoC S/PDIF driver for IMX development boards
*
- * Copyright (C) 2008-2011 Freescale Semiconductor, Inc.
+ * Copyright (C) 2008-2012 Freescale Semiconductor, Inc.
*
* based on stmp3780_devb_spdif.c
*
@@ -119,6 +119,11 @@ static int __init imx_spdif_init(void)
return -ENOMEM;
}
+ if (machine_is_mx6sl_evk()) {
+ imx_spdif_dai_link.name = "HDMI-Audio";
+ imx_spdif_dai_link.stream_name = "HDMI-Audio";
+ }
+
platform_set_drvdata(imx_spdif_snd_device, &snd_soc_card_imx_spdif);
ret = platform_device_add(imx_spdif_snd_device);
diff --git a/tools/perf/util/include/linux/compiler.h b/tools/perf/util/include/linux/compiler.h
index 791f9dd27ebf..547628e97f3d 100644
--- a/tools/perf/util/include/linux/compiler.h
+++ b/tools/perf/util/include/linux/compiler.h
@@ -5,7 +5,9 @@
#define __always_inline inline
#endif
#define __user
+#ifndef __attribute_const__
#define __attribute_const__
+#endif
#define __used __attribute__((__unused__))