summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndrey Konovalov <andrey.konovalov@linaro.org>2013-08-05 19:20:53 +0400
committerAndrey Konovalov <andrey.konovalov@linaro.org>2013-08-05 19:20:53 +0400
commit931c65c6889402ffd6c6a3b6eaab792e27710f9d (patch)
treefeb5bd598fc475e074091b8fb7a1ca9d2f68df60
parentc3a931b72aef510081d0e6882bc261f9130f6b7b (diff)
parentb0b0adb3f5cc0b585b2c045318303f028f57c8a6 (diff)
Merge branch 'tracking-samslt-all' into merge-linux-linaroll-20130805.0
-rw-r--r--Documentation/devicetree/bindings/clock/exynos5250-clock.txt14
-rw-r--r--Documentation/devicetree/bindings/i2c/i2c-s3c2410.txt2
-rw-r--r--Documentation/kernel-parameters.txt4
-rw-r--r--Makefile5
-rw-r--r--arch/arm/Kconfig2
-rw-r--r--arch/arm/boot/dts/exynos5250-arndale.dts31
-rw-r--r--arch/arm/boot/dts/exynos5250.dtsi33
-rw-r--r--arch/arm/configs/arndale_android_defconfig139
-rw-r--r--arch/arm/configs/arndale_ubuntu_defconfig208
-rw-r--r--arch/arm/mach-exynos/headsmp.S114
-rw-r--r--arch/arm/mach-exynos/hotplug.c8
-rw-r--r--arch/arm/mach-exynos/include/mach/map.h4
-rw-r--r--arch/arm/mach-exynos/include/mach/regs-pmu.h3
-rw-r--r--drivers/ata/Kconfig22
-rw-r--r--drivers/ata/Makefile2
-rw-r--r--drivers/ata/sata_exynos.c307
-rw-r--r--drivers/ata/sata_exynos_phy.c296
-rw-r--r--drivers/ata/sata_exynos_phy.h32
-rw-r--r--drivers/ata/sata_phy.c147
-rw-r--r--drivers/ata/sata_phy.h30
-rw-r--r--drivers/clk/samsung/clk-exynos5250.c20
-rw-r--r--drivers/clocksource/exynos_mct.c6
-rw-r--r--drivers/cpufreq/exynos-cpufreq.c38
-rw-r--r--drivers/gpu/drm/exynos/exynos_drm_drv.c3
-rw-r--r--drivers/gpu/drm/exynos/exynos_hdmi.c104
-rw-r--r--drivers/gpu/drm/exynos/exynos_mixer.c32
-rw-r--r--drivers/gpu/drm/exynos/regs-hdmi.h4
-rw-r--r--drivers/i2c/busses/i2c-s3c2410.c68
-rw-r--r--drivers/media/platform/s5p-mfc/s5p_mfc_dec.c16
-rw-r--r--drivers/media/platform/s5p-mfc/s5p_mfc_opr.h1
-rw-r--r--drivers/media/platform/s5p-mfc/s5p_mfc_opr_v5.c9
-rw-r--r--drivers/media/v4l2-core/v4l2-ctrls.c7
-rw-r--r--drivers/net/usb/asix_devices.c32
-rw-r--r--drivers/tty/serial/samsung.c29
-rw-r--r--firmware/edid-1920x1080.fwbin0 -> 128 bytes
-rw-r--r--include/linux/printk.h1
-rw-r--r--include/linux/scatterlist.h2
-rw-r--r--include/uapi/linux/v4l2-controls.h4
-rw-r--r--init/main.c1
-rw-r--r--init/version.c3
-rw-r--r--linaro/configs/arndale.conf11
41 files changed, 1735 insertions, 59 deletions
diff --git a/Documentation/devicetree/bindings/clock/exynos5250-clock.txt b/Documentation/devicetree/bindings/clock/exynos5250-clock.txt
index 781a6276adf7..84e098ff8f25 100644
--- a/Documentation/devicetree/bindings/clock/exynos5250-clock.txt
+++ b/Documentation/devicetree/bindings/clock/exynos5250-clock.txt
@@ -59,6 +59,9 @@ clock which they consume.
sclk_spi0 154
sclk_spi1 155
sclk_spi2 156
+ div_i2s1 157
+ div_i2s2 158
+ sclk_hdmiphy 159
[Peripheral Clock Gates]
@@ -154,7 +157,16 @@ clock which they consume.
dsim0 341
dp 342
mixer 343
- hdmi 345
+ hdmi 344
+ smmu_mixer 345
+
+
+ [Clock Muxes]
+
+ Clock ID
+ ----------------------------
+ mout_hdmi 1024
+
Example 1: An example of a clock controller node is listed below.
diff --git a/Documentation/devicetree/bindings/i2c/i2c-s3c2410.txt b/Documentation/devicetree/bindings/i2c/i2c-s3c2410.txt
index 296eb4536129..278de8e64bbf 100644
--- a/Documentation/devicetree/bindings/i2c/i2c-s3c2410.txt
+++ b/Documentation/devicetree/bindings/i2c/i2c-s3c2410.txt
@@ -10,6 +10,8 @@ Required properties:
inside HDMIPHY block found on several samsung SoCs
(d) "samsung, exynos5440-i2c", for s3c2440-like i2c used
on EXYNOS5440 which does not need GPIO configuration.
+ (e) "samsung, exynos5-sata-phy-i2c", for s3c2440-like i2c used as
+ a host to SATA PHY controller on an internal bus.
- reg: physical base address of the controller and length of memory mapped
region.
- interrupts: interrupt number to the cpu.
diff --git a/Documentation/kernel-parameters.txt b/Documentation/kernel-parameters.txt
index 15356aca938c..b4de7138c7dd 100644
--- a/Documentation/kernel-parameters.txt
+++ b/Documentation/kernel-parameters.txt
@@ -1540,6 +1540,10 @@ bytes respectively. Such letter suffixes can also be entirely omitted.
ltpc= [NET]
Format: <io>,<irq>,<dma>
+ mac= [NET]
+ Used ASIX drivers.
+ Example: mac=12:34:56:78:ab:cd
+
machvec= [IA-64] Force the use of a particular machine-vector
(machvec) in a generic kernel.
Example: machvec=hpzx1_swiotlb
diff --git a/Makefile b/Makefile
index 95a8e55feceb..eba27b239da7 100644
--- a/Makefile
+++ b/Makefile
@@ -799,7 +799,6 @@ include/config/kernel.release: include/config/auto.conf FORCE
$(Q)rm -f $@
$(Q)echo "$(KERNELVERSION)$$($(CONFIG_SHELL) $(srctree)/scripts/setlocalversion $(srctree))" > $@
-
# Things we need to do before we recursively start building the kernel
# or the modules are listed in "prepare".
# A multi level approach is used. prepareN is processed before prepareN-1.
@@ -849,7 +848,9 @@ define filechk_utsrelease.h
echo '"$(KERNELRELEASE)" exceeds $(uts_len) characters' >&2; \
exit 1; \
fi; \
- (echo \#define UTS_RELEASE \"$(KERNELRELEASE)\";)
+ (echo \#define UTS_RELEASE \"$(KERNELRELEASE)\"; \
+ echo \#define KERNEL_GIT_ID \"$(shell \
+ git rev-parse --verify --short HEAD 2>/dev/null)\";)
endef
define filechk_version.h
diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig
index c5c29daa73da..1064b36f74d1 100644
--- a/arch/arm/Kconfig
+++ b/arch/arm/Kconfig
@@ -1788,7 +1788,7 @@ config FORCE_MAX_ZONEORDER
range 11 64 if ARCH_SHMOBILE
default "12" if SOC_AM33XX
default "9" if SA1111
- default "11"
+ default "14" if ARCH_EXYNOS5
help
The kernel memory allocator divides physically contiguous memory
blocks into "zones", where each zone is a power of two number of
diff --git a/arch/arm/boot/dts/exynos5250-arndale.dts b/arch/arm/boot/dts/exynos5250-arndale.dts
index 3937993b95f3..b3134245732b 100644
--- a/arch/arm/boot/dts/exynos5250-arndale.dts
+++ b/arch/arm/boot/dts/exynos5250-arndale.dts
@@ -291,7 +291,13 @@
};
i2c@12C80000 {
- status = "disabled";
+ samsung,i2c-sda-delay = <100>;
+ samsung,i2c-max-bus-freq = <66000>;
+
+ hdmiddc@50 {
+ compatible = "samsung,exynos5-hdmiddc";
+ reg = <0x50>;
+ };
};
i2c@12C90000 {
@@ -314,10 +320,31 @@
status = "disabled";
};
+ i2c@12CE0000 {
+ samsung,i2c-sda-delay = <100>;
+ samsung,i2c-max-bus-freq = <66000>;
+
+ hdmiphy@38 {
+ compatible = "samsung,exynos5-hdmiphy";
+ reg = <0x38>;
+ };
+ };
+
i2c@121D0000 {
- status = "disabled";
+ samsung,i2c-sda-delay = <100>;
+ samsung,i2c-max-bus-freq = <40000>;
+ samsung,i2c-slave-addr = <0x38>;
+
+ sata-phy {
+ compatible = "samsung,sata-phy";
+ reg = <0x38>;
+ };
};
+ sata@122F0000 {
+ samsung,sata-freq = <66>;
+ };
+
dwmmc_0: dwmmc0@12200000 {
num-slots = <1>;
supports-highspeed;
diff --git a/arch/arm/boot/dts/exynos5250.dtsi b/arch/arm/boot/dts/exynos5250.dtsi
index ef57277fc38f..654b33d8ac98 100644
--- a/arch/arm/boot/dts/exynos5250.dtsi
+++ b/arch/arm/boot/dts/exynos5250.dtsi
@@ -186,34 +186,51 @@
serial@12C00000 {
clocks = <&clock 289>, <&clock 146>;
clock-names = "uart", "clk_uart_baud0";
+ pinctrl-names = "default";
+ pinctrl-0 = <&uart0_data &uart0_fctl>;
};
serial@12C10000 {
clocks = <&clock 290>, <&clock 147>;
clock-names = "uart", "clk_uart_baud0";
+ pinctrl-names = "default";
+ pinctrl-0 = <&uart1_data &uart1_fctl>;
};
serial@12C20000 {
clocks = <&clock 291>, <&clock 148>;
clock-names = "uart", "clk_uart_baud0";
+ pinctrl-names = "default";
+ pinctrl-0 = <&uart2_data &uart2_fctl>;
};
serial@12C30000 {
clocks = <&clock 292>, <&clock 149>;
clock-names = "uart", "clk_uart_baud0";
+ pinctrl-names = "default";
+ pinctrl-0 = <&uart3_data>;
};
sata@122F0000 {
compatible = "samsung,exynos5-sata-ahci";
+ samsung,exynos-sata-phy = <&phy0>;
reg = <0x122F0000 0x1ff>;
interrupts = <0 115 0>;
clocks = <&clock 277>, <&clock 143>;
clock-names = "sata", "sclk_sata";
};
- sata-phy@12170000 {
+ phy0:sata-phy@12170000 {
compatible = "samsung,exynos5-sata-phy";
reg = <0x12170000 0x1ff>;
+ clocks = <&clock 287>;
+ clock-names = "sata_phyctrl";
+ #address-cells = <1>;
+ #size-cells = <1>;
+ ranges;
+ sataphy-pmu {
+ reg = <0x10040724 0x4>;
+ };
};
i2c_0: i2c@12C60000 {
@@ -602,16 +619,24 @@
compatible = "samsung,exynos4212-hdmi";
reg = <0x14530000 0x70000>;
interrupts = <0 95 0>;
- clocks = <&clock 333>, <&clock 136>, <&clock 137>,
- <&clock 333>, <&clock 333>;
+ clocks = <&clock 344>, <&clock 136>, <&clock 137>,
+ <&clock 159>, <&clock 1024>;
clock-names = "hdmi", "sclk_hdmi", "sclk_pixel",
- "sclk_hdmiphy", "hdmiphy";
+ "sclk_hdmiphy", "mout_hdmi";
+ #address-cells = <1>;
+ #size-cells = <1>;
+
+ phy-power-control {
+ reg = <0x10040700 0x04>;
+ };
};
mixer {
compatible = "samsung,exynos5250-mixer";
reg = <0x14450000 0x10000>;
interrupts = <0 94 0>;
+ clocks = <&clock 343>, <&clock 136>;
+ clock-names = "mixer", "sclk_hdmi";
};
dp-controller {
diff --git a/arch/arm/configs/arndale_android_defconfig b/arch/arm/configs/arndale_android_defconfig
new file mode 100644
index 000000000000..60f627e0eca9
--- /dev/null
+++ b/arch/arm/configs/arndale_android_defconfig
@@ -0,0 +1,139 @@
+CONFIG_EXPERIMENTAL=y
+CONFIG_SYSVIPC=y
+CONFIG_NO_HZ=y
+CONFIG_HIGH_RES_TIMERS=y
+CONFIG_BLK_DEV_INITRD=y
+CONFIG_KALLSYMS_ALL=y
+CONFIG_MODULES=y
+CONFIG_MODULE_UNLOAD=y
+# CONFIG_BLK_DEV_BSG is not set
+CONFIG_PARTITION_ADVANCED=y
+CONFIG_BSD_DISKLABEL=y
+CONFIG_SOLARIS_X86_PARTITION=y
+# CONFIG_EFI_PARTITION is not set
+CONFIG_ARCH_EXYNOS=y
+CONFIG_S3C_LOWLEVEL_UART_PORT=2
+# CONFIG_ARCH_EXYNOS4 is not set
+CONFIG_ARCH_EXYNOS5=y
+CONFIG_NUMA=y
+CONFIG_NODES_SHIFT=2
+CONFIG_SMP=y
+CONFIG_NR_CPUS=2
+CONFIG_PREEMPT=y
+CONFIG_AEABI=y
+CONFIG_HIGHMEM=y
+CONFIG_TRANSPARENT_HUGEPAGE=y
+CONFIG_ARM_APPENDED_DTB=y
+CONFIG_ARM_ATAG_DTB_COMPAT=y
+CONFIG_CMDLINE="root=/dev/ram0 rw ramdisk=8192 initrd=0x41000000,8M console=ttySAC1,115200 init= mem=256M"
+CONFIG_CPU_FREQ=y
+CONFIG_CPU_FREQ_DEFAULT_GOV_ONDEMAND=y
+CONFIG_CPU_FREQ_GOV_USERSPACE=y
+CONFIG_CPU_IDLE=y
+CONFIG_VFP=y
+CONFIG_NEON=y
+CONFIG_NET=y
+CONFIG_PACKET=y
+CONFIG_UNIX=y
+CONFIG_INET=y
+CONFIG_IP_MULTICAST=y
+CONFIG_IPV6=y
+CONFIG_INET6_XFRM_MODE_TRANSPORT=m
+CONFIG_INET6_XFRM_MODE_TUNNEL=m
+CONFIG_INET6_XFRM_MODE_BEET=m
+CONFIG_IPV6_SIT=m
+CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
+CONFIG_BLK_DEV_LOOP=y
+CONFIG_BLK_DEV_RAM=y
+CONFIG_BLK_DEV_RAM_SIZE=8192
+CONFIG_BLK_DEV_SD=y
+CONFIG_CHR_DEV_SG=y
+CONFIG_SCSI_MULTI_LUN=y
+CONFIG_ATA=y
+CONFIG_SATA_AHCI_PLATFORM=y
+CONFIG_SATA_EXYNOS=y
+CONFIG_NETDEVICES=y
+CONFIG_AX88796=y
+CONFIG_AX88796_93CX6=y
+CONFIG_SMC91X=y
+CONFIG_SMC911X=y
+CONFIG_SMSC911X=y
+CONFIG_USB_USBNET=y
+CONFIG_INPUT_EVDEV=y
+# CONFIG_INPUT_KEYBOARD is not set
+# CONFIG_INPUT_MOUSE is not set
+CONFIG_INPUT_TOUCHSCREEN=y
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_SAMSUNG=y
+CONFIG_SERIAL_SAMSUNG_CONSOLE=y
+CONFIG_HW_RANDOM=y
+CONFIG_I2C_GPIO=y
+# CONFIG_HWMON is not set
+CONFIG_THERMAL=y
+CONFIG_CPU_THERMAL=y
+CONFIG_EXYNOS_THERMAL=y
+CONFIG_MFD_SEC_CORE=y
+CONFIG_REGULATOR=y
+CONFIG_REGULATOR_S5M8767=y
+CONFIG_HID_LOGITECH_DJ=m
+CONFIG_USB=y
+CONFIG_USB_ANNOUNCE_NEW_DEVICES=y
+CONFIG_USB_DWC3=y
+CONFIG_USB_XHCI_HCD=y
+CONFIG_USB_EHCI_HCD=y
+# CONFIG_USB_EHCI_TT_NEWSCHED is not set
+CONFIG_USB_EHCI_S5P=y
+CONFIG_USB_OHCI_HCD=y
+CONFIG_USB_OHCI_EXYNOS=y
+CONFIG_USB_STORAGE=y
+CONFIG_SAMSUNG_USBPHY=y
+CONFIG_USB_GADGET=y
+CONFIG_MMC=y
+CONFIG_MMC_DW=y
+CONFIG_MMC_DW_IDMAC=y
+CONFIG_MMC_DW_EXYNOS=y
+CONFIG_STAGING=y
+CONFIG_ANDROID=y
+CONFIG_ANDROID_BINDER_IPC=y
+CONFIG_ASHMEM=y
+CONFIG_ANDROID_LOGGER=y
+CONFIG_ANDROID_RAM_CONSOLE=y
+CONFIG_PERSISTENT_TRACER=y
+CONFIG_ANDROID_TIMED_GPIO=y
+CONFIG_ANDROID_LOW_MEMORY_KILLER=y
+CONFIG_ANDROID_SWITCH=y
+CONFIG_EXT2_FS=y
+CONFIG_EXT2_FS_XATTR=y
+CONFIG_EXT2_FS_POSIX_ACL=y
+CONFIG_EXT2_FS_SECURITY=y
+CONFIG_EXT2_FS_XIP=y
+CONFIG_EXT3_FS=y
+CONFIG_EXT3_FS_POSIX_ACL=y
+CONFIG_EXT3_FS_SECURITY=y
+CONFIG_EXT4_FS=y
+CONFIG_EXT4_FS_POSIX_ACL=y
+CONFIG_EXT4_FS_SECURITY=y
+CONFIG_EXT4_DEBUG=y
+CONFIG_MSDOS_FS=y
+CONFIG_VFAT_FS=y
+CONFIG_TMPFS=y
+CONFIG_TMPFS_POSIX_ACL=y
+CONFIG_HUGETLBFS=y
+CONFIG_CRAMFS=y
+CONFIG_ROMFS_FS=y
+CONFIG_NLS_CODEPAGE_437=y
+CONFIG_NLS_ASCII=y
+CONFIG_NLS_ISO8859_1=y
+CONFIG_PRINTK_TIME=y
+CONFIG_MAGIC_SYSRQ=y
+CONFIG_DEBUG_KERNEL=y
+CONFIG_DETECT_HUNG_TASK=y
+CONFIG_DEBUG_RT_MUTEXES=y
+CONFIG_DEBUG_SPINLOCK=y
+CONFIG_DEBUG_MUTEXES=y
+CONFIG_DEBUG_INFO=y
+CONFIG_DEBUG_USER=y
+CONFIG_DEBUG_LL=y
+CONFIG_DEBUG_S3C_UART2=y
+CONFIG_EARLY_PRINTK=y
+CONFIG_CRC_CCITT=y
diff --git a/arch/arm/configs/arndale_ubuntu_defconfig b/arch/arm/configs/arndale_ubuntu_defconfig
new file mode 100644
index 000000000000..269ecf2fac70
--- /dev/null
+++ b/arch/arm/configs/arndale_ubuntu_defconfig
@@ -0,0 +1,208 @@
+# CONFIG_LOCALVERSION_AUTO is not set
+CONFIG_SYSVIPC=y
+CONFIG_POSIX_MQUEUE=y
+CONFIG_NO_HZ=y
+CONFIG_HIGH_RES_TIMERS=y
+CONFIG_BSD_PROCESS_ACCT=y
+CONFIG_IKCONFIG=y
+CONFIG_IKCONFIG_PROC=y
+CONFIG_LOG_BUF_SHIFT=16
+CONFIG_CGROUPS=y
+CONFIG_BLK_DEV_INITRD=y
+CONFIG_KALLSYMS_ALL=y
+CONFIG_EMBEDDED=y
+# CONFIG_COMPAT_BRK is not set
+CONFIG_SLAB=y
+CONFIG_PROFILING=y
+CONFIG_OPROFILE=y
+CONFIG_MODULES=y
+CONFIG_MODULE_UNLOAD=y
+CONFIG_PARTITION_ADVANCED=y
+CONFIG_BSD_DISKLABEL=y
+CONFIG_SOLARIS_X86_PARTITION=y
+CONFIG_ARCH_EXYNOS=y
+CONFIG_S3C_LOWLEVEL_UART_PORT=2
+CONFIG_ARCH_EXYNOS5=y
+CONFIG_ARM_LPAE=y
+CONFIG_SMP=y
+CONFIG_SCHED_MC=y
+CONFIG_SCHED_SMT=y
+CONFIG_VMSPLIT_2G=y
+CONFIG_NR_CPUS=2
+CONFIG_THUMB2_KERNEL=y
+CONFIG_HIGHMEM=y
+# CONFIG_COMPACTION is not set
+CONFIG_DEFAULT_MMAP_MIN_ADDR=32768
+CONFIG_SECCOMP=y
+CONFIG_CC_STACKPROTECTOR=y
+CONFIG_ARM_APPENDED_DTB=y
+CONFIG_ARM_ATAG_DTB_COMPAT=y
+CONFIG_CMDLINE="root=/dev/ram0 rw ramdisk=8192 initrd=0x41000000,8M console=ttySAC1,115200 init= mem=256M"
+CONFIG_CPU_FREQ=y
+CONFIG_CPU_FREQ_DEFAULT_GOV_ONDEMAND=y
+CONFIG_CPU_FREQ_GOV_USERSPACE=y
+CONFIG_CPU_IDLE=y
+CONFIG_VFP=y
+CONFIG_NEON=y
+CONFIG_BINFMT_MISC=y
+CONFIG_PM_RUNTIME=y
+CONFIG_NET=y
+CONFIG_PACKET=y
+CONFIG_UNIX=y
+CONFIG_XFRM_USER=y
+CONFIG_NET_KEY=y
+CONFIG_NET_KEY_MIGRATE=y
+CONFIG_INET=y
+CONFIG_IP_MULTICAST=y
+CONFIG_IP_PNP=y
+CONFIG_IP_PNP_DHCP=y
+CONFIG_IP_PNP_BOOTP=y
+CONFIG_IP_PNP_RARP=y
+CONFIG_SYN_COOKIES=y
+# CONFIG_INET_LRO is not set
+CONFIG_IPV6=y
+CONFIG_NETFILTER=y
+CONFIG_NF_CONNTRACK=m
+CONFIG_NETFILTER_XT_MARK=m
+CONFIG_NETFILTER_XT_CONNMARK=m
+CONFIG_NETFILTER_XT_TARGET_CHECKSUM=m
+CONFIG_NF_CONNTRACK_IPV4=m
+CONFIG_IP_NF_IPTABLES=m
+CONFIG_IP_NF_FILTER=m
+CONFIG_NF_NAT_IPV4=m
+CONFIG_IP_NF_MANGLE=m
+CONFIG_NF_CONNTRACK_IPV6=m
+CONFIG_IP6_NF_IPTABLES=m
+CONFIG_IP6_NF_FILTER=m
+CONFIG_IP6_NF_MANGLE=m
+CONFIG_NF_NAT_IPV6=m
+CONFIG_BRIDGE_NF_EBTABLES=m
+CONFIG_BRIDGE_EBT_MARK_T=m
+CONFIG_BRIDGE=m
+CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
+CONFIG_DEVTMPFS=y
+CONFIG_DEVTMPFS_MOUNT=y
+CONFIG_EXTRA_FIRMWARE="edid-1920x1080.fw"
+CONFIG_CONNECTOR=y
+CONFIG_MTD=y
+CONFIG_MTD_CMDLINE_PARTS=y
+CONFIG_MTD_BLOCK=y
+CONFIG_MTD_OOPS=y
+CONFIG_MTD_CFI=y
+CONFIG_MTD_CFI_INTELEXT=y
+CONFIG_MTD_NAND=y
+CONFIG_PROC_DEVICETREE=y
+CONFIG_BLK_DEV_LOOP=y
+CONFIG_BLK_DEV_NBD=m
+CONFIG_BLK_DEV_RAM=y
+CONFIG_BLK_DEV_RAM_SIZE=65536
+CONFIG_BLK_DEV_SD=y
+CONFIG_CHR_DEV_SG=y
+CONFIG_ATA=y
+CONFIG_SATA_AHCI_PLATFORM=y
+CONFIG_SATA_EXYNOS=y
+CONFIG_MD=y
+CONFIG_BLK_DEV_DM=y
+CONFIG_NETDEVICES=y
+CONFIG_TUN=y
+CONFIG_AX88796=y
+CONFIG_AX88796_93CX6=y
+CONFIG_USB_USBNET=y
+CONFIG_USB_NET_DM9601=y
+CONFIG_USB_NET_MCS7830=y
+CONFIG_INPUT_EVDEV=y
+CONFIG_KEYBOARD_GPIO=y
+CONFIG_INPUT_TOUCHSCREEN=y
+CONFIG_INPUT_MISC=y
+CONFIG_INPUT_UINPUT=y
+# CONFIG_DEVKMEM is not set
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_SAMSUNG=y
+CONFIG_SERIAL_SAMSUNG_CONSOLE=y
+CONFIG_HW_RANDOM=y
+CONFIG_THERMAL=y
+CONFIG_CPU_THERMAL=y
+CONFIG_EXYNOS_THERMAL=y
+CONFIG_MFD_SEC_CORE=y
+CONFIG_REGULATOR=y
+CONFIG_REGULATOR_FIXED_VOLTAGE=y
+CONFIG_REGULATOR_S5M8767=y
+CONFIG_DRM=y
+CONFIG_DRM_LOAD_EDID_FIRMWARE=y
+CONFIG_DRM_EXYNOS=y
+CONFIG_DRM_EXYNOS_DMABUF=y
+CONFIG_DRM_EXYNOS_HDMI=y
+CONFIG_FRAMEBUFFER_CONSOLE=y
+CONFIG_LOGO=y
+CONFIG_USB=y
+CONFIG_USB_ANNOUNCE_NEW_DEVICES=y
+CONFIG_USB_XHCI_HCD=y
+CONFIG_USB_EHCI_HCD=y
+CONFIG_USB_EHCI_ROOT_HUB_TT=y
+CONFIG_USB_EHCI_S5P=y
+CONFIG_USB_OHCI_HCD=y
+CONFIG_USB_OHCI_EXYNOS=y
+CONFIG_USB_STORAGE=y
+CONFIG_USB_DWC3=y
+CONFIG_USB_PHY=y
+CONFIG_SAMSUNG_USB2PHY=y
+CONFIG_SAMSUNG_USB3PHY=y
+CONFIG_USB_GADGET=y
+CONFIG_MMC=y
+CONFIG_MMC_UNSAFE_RESUME=y
+CONFIG_MMC_DW=y
+CONFIG_MMC_DW_IDMAC=y
+CONFIG_MMC_DW_EXYNOS=y
+CONFIG_RTC_CLASS=y
+CONFIG_RTC_DRV_S3C=y
+CONFIG_EXT2_FS=y
+CONFIG_EXT3_FS=y
+CONFIG_EXT4_FS=y
+CONFIG_BTRFS_FS=y
+CONFIG_QUOTA=y
+CONFIG_QFMT_V2=y
+CONFIG_AUTOFS4_FS=y
+CONFIG_MSDOS_FS=y
+CONFIG_VFAT_FS=y
+CONFIG_TMPFS=y
+CONFIG_TMPFS_POSIX_ACL=y
+CONFIG_ECRYPT_FS=y
+CONFIG_JFFS2_FS=y
+CONFIG_JFFS2_SUMMARY=y
+CONFIG_JFFS2_FS_XATTR=y
+CONFIG_JFFS2_COMPRESSION_OPTIONS=y
+CONFIG_JFFS2_LZO=y
+CONFIG_JFFS2_RUBIN=y
+CONFIG_CRAMFS=y
+CONFIG_NFS_FS=y
+# CONFIG_NFS_V2 is not set
+CONFIG_NFS_V3_ACL=y
+CONFIG_NFS_V4=y
+CONFIG_ROOT_NFS=y
+CONFIG_NLS_CODEPAGE_437=y
+CONFIG_NLS_ISO8859_1=y
+CONFIG_PRINTK_TIME=y
+CONFIG_DEBUG_INFO=y
+CONFIG_MAGIC_SYSRQ=y
+CONFIG_DETECT_HUNG_TASK=y
+CONFIG_SCHEDSTATS=y
+CONFIG_TIMER_STATS=y
+CONFIG_DEBUG_RT_MUTEXES=y
+CONFIG_DEBUG_SPINLOCK=y
+CONFIG_RCU_CPU_STALL_TIMEOUT=60
+CONFIG_FUNCTION_TRACER=y
+CONFIG_STRICT_DEVMEM=y
+CONFIG_DEBUG_USER=y
+CONFIG_SECURITY=y
+CONFIG_LSM_MMAP_MIN_ADDR=0
+CONFIG_SECURITY_SELINUX=y
+CONFIG_SECURITY_SMACK=y
+CONFIG_SECURITY_APPARMOR=y
+CONFIG_DEFAULT_SECURITY_APPARMOR=y
+CONFIG_CRYPTO_MICHAEL_MIC=y
+CONFIG_CRC_CCITT=y
+CONFIG_CRC_T10DIF=y
+CONFIG_CRC_ITU_T=y
+CONFIG_CRC7=y
+CONFIG_VIRTUALIZATION=y
+CONFIG_KVM=y
diff --git a/arch/arm/mach-exynos/headsmp.S b/arch/arm/mach-exynos/headsmp.S
index cdd9d91e9933..348c61509e62 100644
--- a/arch/arm/mach-exynos/headsmp.S
+++ b/arch/arm/mach-exynos/headsmp.S
@@ -12,12 +12,105 @@
*/
#include <linux/linkage.h>
#include <linux/init.h>
+#include <asm/assembler.h>
/*
* exynos4 specific entry point for secondary CPUs. This provides
* a "holding pen" into which all secondary cores are held until we're
* ready for them to initialise.
*/
+
+.arch_extension sec
+.arch_extension virt
+.text
+
+.align 5
+/* We use the same vector table for Hyp and Monitor mode, since
+ * we will only use each once and they don't overlap.
+ */
+mon_vectors:
+ W(b) . /* reset */
+ W(b) . /* undef */
+ W(b) 2f /* smc */
+ W(b) . /* pabt */
+ W(b) . /* dabt */
+ W(b) 1f /* hyp */
+ W(b) . /* irq */
+ W(b) . /* fiq */
+
+/* Return directly back to the caller without leaving Hyp mode: */
+1: mrs lr, elr_hyp
+ mov pc, lr
+
+/* In monitor mode, set up HVBAR and SCR then return to caller in NS-SVC. */
+2:
+ mrc p15, 0, r1, c1, c1, 0 @ SCR
+ /*
+ * Set SCR.NS=1(needed for setting HVBAR and also returning to NS state)
+ * .IRQ,FIQ,EA=0 (don't take aborts/exceptions to Monitor mode)
+ * .FW,AW=1 (CPSR.A,F modifiable in NS state)
+ * .nET=0 (early termination OK)
+ * .SCD=0 (SMC in NS mode OK, so we can call secure firmware)
+ * .HCE=1 (HVC does Hyp call)
+ */
+ bic r1, r1, #0x07f
+ ldr r2, =0x131
+ orr r1, r1, r2
+ mcr p15, 0, r2, c1, c1, 0 @ SCR
+ isb
+ ldr r2, =mon_vectors
+
+
+ adr r4, 1f
+ ldmia r4, {r5}
+ sub r4, r4, r5
+ add r2, r2, r4
+
+ mcr p15, 4, r2, c12, c0, 0 @ set HVBAR
+
+ THUMB( mrc p15, 4, r2, c1, c0, 0 ) @ ctrl register
+ THUMB( orr r2, r2, #1 << 30 ) @ HSCTLR.TE (Thumb exceptions)
+ THUMB( mcr p15, 4, r2, c1, c0, 0 )
+ THUMB( isb)
+
+ /* ...and return to calling code in NS state */
+ movs pc, lr
+
+
+ .globl monitor_init
+monitor_init:
+ ldr ip, =mon_vectors
+
+ adr r4, 1f
+ ldmia r4, {r5}
+ sub r4, r4, r5
+ add ip, ip, r4
+ mcr p15, 0, ip, c12, c0, 1
+
+ THUMB( mrc p15, 0, r1, c1, c0, 0 ) @ ctrl register
+ THUMB( orr r1, r1, #1 << 30 ) @ SCTLR.TE (Thumb exceptions)
+ THUMB( mcr p15, 0, r1, c1, c0, 0 )
+ THUMB( isb )
+
+ mov pc, lr
+
+ /* Try to go into NS-SVC: void enter_ns(void); */
+ .globl enter_ns
+enter_ns:
+ smc #0
+ mov pc, lr
+
+ /* void enter_hyp(void); */
+ .globl enter_hyp
+enter_hyp:
+ /* Now we're in NS-SVC, make a Hyp call to get into Hyp mode */
+ mov r0, lr
+ mov r1, sp
+ hvc #0
+ /* We will end up here in NS-Hyp. */
+ mov sp, r1
+ mov pc, r0
+
ENTRY(exynos4_secondary_startup)
mrc p15, 0, r0, c0, c0, 5
and r0, r0, #15
@@ -29,6 +122,27 @@ pen: ldr r7, [r6]
cmp r7, r0
bne pen
+ ldr r1, =__boot_cpu_mode
+ add r1, r1, r4
+ ldr r2, [r1]
+ mrs r0, cpsr
+ ands r0, r0, #MODE_MASK
+ subs r1, r0, r2
+ beq 3f
+ subs r2, r2, #HYP_MODE
+ bne 3f
+
+ /* Setting NSACR to allow coprocessor access from non-secure mode */
+ mrc p15, 0, r0, c1, c1, 2
+ movw r1, #0x3fff
+ orr r0, r0, r1
+ mcr p15, 0, r0, c1, c1, 2
+5:
+ bl monitor_init
+ bl enter_ns
+ bl enter_hyp
+
+3:
/*
* we've been released from the holding pen: secondary_stack
* should now contain the SVC stack for this core
diff --git a/arch/arm/mach-exynos/hotplug.c b/arch/arm/mach-exynos/hotplug.c
index af90cfa2f826..cce2b0d960e7 100644
--- a/arch/arm/mach-exynos/hotplug.c
+++ b/arch/arm/mach-exynos/hotplug.c
@@ -98,13 +98,7 @@ static inline void platform_do_lowpower(unsigned int cpu, int *spurious)
if (cpu == 1)
__raw_writel(0, S5P_ARM_CORE1_CONFIGURATION);
- /*
- * here's the WFI
- */
- asm(".word 0xe320f003\n"
- :
- :
- : "memory", "cc");
+ wfi();
if (pen_release == cpu_logical_map(cpu)) {
/*
diff --git a/arch/arm/mach-exynos/include/mach/map.h b/arch/arm/mach-exynos/include/mach/map.h
index 7b046b59d9ec..a5df67b15718 100644
--- a/arch/arm/mach-exynos/include/mach/map.h
+++ b/arch/arm/mach-exynos/include/mach/map.h
@@ -60,6 +60,10 @@
#define EXYNOS4_PA_COREPERI 0x10500000
#define EXYNOS4_PA_L2CC 0x10502000
+#define EXYNOS5_PA_SATA_PHY_CTRL 0x12170000
+#define EXYNOS5_PA_SATA_PHY_I2C 0x121D0000
+#define EXYNOS5_PA_SATA_BASE 0x122F0000
+
#define EXYNOS4_PA_SROMC 0x12570000
#define EXYNOS5_PA_SROMC 0x12250000
diff --git a/arch/arm/mach-exynos/include/mach/regs-pmu.h b/arch/arm/mach-exynos/include/mach/regs-pmu.h
index 57344b7e98ce..66ffff8069f1 100644
--- a/arch/arm/mach-exynos/include/mach/regs-pmu.h
+++ b/arch/arm/mach-exynos/include/mach/regs-pmu.h
@@ -370,4 +370,7 @@
#define EXYNOS5_OPTION_USE_RETENTION (1 << 4)
+/* Only for EXYNOS5250 */
+#define EXYNOS5_SATA_PHY_CONTROL S5P_PMUREG(0x0724)
+
#endif /* __ASM_ARCH_REGS_PMU_H */
diff --git a/drivers/ata/Kconfig b/drivers/ata/Kconfig
index 4e737728aee2..c81fe31b3da6 100644
--- a/drivers/ata/Kconfig
+++ b/drivers/ata/Kconfig
@@ -97,6 +97,28 @@ config SATA_AHCI_PLATFORM
If unsure, say N.
+config SATA_PHY
+ bool "SATA PHY Framework"
+ default n
+ help
+ This option enables the SATA PHY utility framework APIs.
+ The framework acts as an interface between the SATA device
+ and the PHY device. The SATA PHY device registers itself
+ with the framework through the APIs provided and the SATA
+ device finds and requests for an appropriate PHY device.
+
+config SATA_EXYNOS
+ bool "Exynos SATA AHCI support"
+ select I2C
+ select HAVE_S3C2410_I2C
+ select I2C_S3C2410
+ select SATA_PHY
+ help
+ This option enables support for Exynos AHCI Serial ATA
+ controllers.
+
+ If unsure, say N.
+
config AHCI_IMX
tristate "Freescale i.MX AHCI SATA support"
depends on SATA_AHCI_PLATFORM && MFD_SYSCON
diff --git a/drivers/ata/Makefile b/drivers/ata/Makefile
index 46518c622460..a4e5cf56d475 100644
--- a/drivers/ata/Makefile
+++ b/drivers/ata/Makefile
@@ -10,6 +10,8 @@ obj-$(CONFIG_SATA_INIC162X) += sata_inic162x.o
obj-$(CONFIG_SATA_SIL24) += sata_sil24.o
obj-$(CONFIG_SATA_DWC) += sata_dwc_460ex.o
obj-$(CONFIG_SATA_HIGHBANK) += sata_highbank.o libahci.o
+obj-$(CONFIG_SATA_PHY) += sata_phy.o
+obj-$(CONFIG_SATA_EXYNOS) += sata_exynos.o sata_exynos_phy.o libahci.o
obj-$(CONFIG_AHCI_IMX) += ahci_imx.o
# SFF w/ custom DMA
diff --git a/drivers/ata/sata_exynos.c b/drivers/ata/sata_exynos.c
new file mode 100644
index 000000000000..1dcfb2c8d0de
--- /dev/null
+++ b/drivers/ata/sata_exynos.c
@@ -0,0 +1,307 @@
+/*
+ * Copyright (c) 2010-2012 Samsung Electronics Co., Ltd.
+ * http://www.samsung.com
+ *
+ * EXYNOS - SATA controller platform driver wrapper
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+*/
+
+#include <linux/kernel.h>
+#include <linux/gfp.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/device.h>
+#include <linux/platform_device.h>
+#include <linux/libata.h>
+#include <linux/ahci_platform.h>
+#include <linux/clk.h>
+#include <linux/slab.h>
+#include <linux/of.h>
+#include <linux/of_irq.h>
+#include <linux/of_address.h>
+
+#include "ahci.h"
+#include "sata_phy.h"
+
+#define MHZ (1000 * 1000)
+#define DEFERED 1
+#define NO_PORT 0
+
+static const struct ata_port_info ahci_port_info = {
+ .flags = AHCI_FLAG_COMMON,
+ .pio_mask = ATA_PIO4,
+ .udma_mask = ATA_UDMA6,
+ .port_ops = &ahci_ops,
+};
+
+static struct scsi_host_template ahci_platform_sht = {
+ AHCI_SHT("ahci_platform"),
+};
+
+struct exynos_sata {
+ struct clk *sclk;
+ struct clk *clk;
+ int irq;
+ unsigned int freq;
+ struct sata_phy *phy[];
+};
+
+static int exynos_sata_parse_dt(struct device_node *np,
+ struct exynos_sata *sata)
+{
+ if (!np)
+ return -EINVAL;
+
+ return of_property_read_u32(np, "samsung,sata-freq",
+ &sata->freq);
+}
+
+static int exynos_sata_probe(struct platform_device *pdev)
+{
+ struct device *dev = &pdev->dev;
+ struct ata_port_info pi = ahci_port_info;
+ const struct ata_port_info *ppi[] = { &pi, NULL };
+ struct ahci_host_priv *hpriv;
+ struct exynos_sata *sata;
+ struct ata_host *host;
+ struct device_node *of_node_phy = NULL;
+ static int flag = 0, port_init = NO_PORT;
+ int n_ports, i, ret;
+
+ sata = devm_kzalloc(dev, sizeof(*sata), GFP_KERNEL);
+ if (!sata) {
+ dev_err(dev, "can't alloc sata\n");
+ return -ENOMEM;
+ }
+
+ hpriv = devm_kzalloc(dev, sizeof(*hpriv), GFP_KERNEL);
+ if (!hpriv) {
+ dev_err(dev, "can't alloc ahci_host_priv\n");
+ return -ENOMEM;
+ }
+
+ hpriv->flags |= (unsigned long)pi.private_data;
+
+ sata->irq = irq_of_parse_and_map(dev->of_node, 0);
+ if (sata->irq <= 0) {
+ dev_err(dev, "irq not specified\n");
+ return -EINVAL;
+ }
+
+ hpriv->mmio = of_iomap(dev->of_node, 0);
+ if (!hpriv->mmio) {
+ dev_err(dev, "failed to map IO\n");
+ return -ENOMEM;
+ }
+
+ ret = exynos_sata_parse_dt(dev->of_node, sata);
+ if (ret < 0) {
+ dev_err(dev, "failed to get frequency for sata ctrl\n");
+ goto err_iomap;
+ }
+
+ sata->sclk = devm_clk_get(dev, "sclk_sata");
+ if (IS_ERR(sata->sclk)) {
+ dev_err(dev, "failed to get sclk_sata\n");
+ ret = PTR_ERR(sata->sclk);
+ goto err_iomap;
+ }
+
+ ret = clk_prepare_enable(sata->sclk);
+ if (ret < 0) {
+ dev_err(dev, "failed to enable source clk\n");
+ goto err_iomap;
+ }
+
+ ret = clk_set_rate(sata->sclk, sata->freq * MHZ);
+ if (ret < 0) {
+ dev_err(dev, "failed to set clk frequency\n");
+ goto err_clkstrt;
+ }
+
+ sata->clk = devm_clk_get(dev, "sata");
+ if (IS_ERR(sata->clk)) {
+ dev_err(dev, "failed to get sata clock\n");
+ ret = PTR_ERR(sata->clk);
+ goto err_clkstrt;
+ }
+
+ ret = clk_prepare_enable(sata->clk);
+ if (ret < 0) {
+ dev_err(dev, "failed to enable source clk\n");
+ goto err_clkstrt;
+ }
+
+ ahci_save_initial_config(dev, hpriv, 0, 0);
+
+ /* prepare host */
+ if (hpriv->cap & HOST_CAP_NCQ)
+ pi.flags |= ATA_FLAG_NCQ;
+
+ if (hpriv->cap & HOST_CAP_PMP)
+ pi.flags |= ATA_FLAG_PMP;
+
+ ahci_set_em_messages(hpriv, &pi);
+
+ /* CAP.NP sometimes indicate the index of the last enabled
+ * port, at other times, that of the last possible port, so
+ * determining the maximum port number requires looking at
+ * both CAP.NP and port_map.
+ */
+ n_ports = max(ahci_nr_ports(hpriv->cap), fls(hpriv->port_map));
+
+ host = ata_host_alloc_pinfo(dev, ppi, n_ports);
+ if (!host) {
+ ret = -ENOMEM;
+ goto err_clken;
+ }
+
+ host->private_data = hpriv;
+
+ if (!(hpriv->cap & HOST_CAP_SSS) || ahci_ignore_sss)
+ host->flags |= ATA_HOST_PARALLEL_SCAN;
+ else
+ pr_info(KERN_INFO
+ "ahci: SSS flag set, parallel bus scan disabled\n");
+
+ if (pi.flags & ATA_FLAG_EM)
+ ahci_reset_em(host);
+
+ for (i = 0; i < host->n_ports; i++) {
+ struct ata_port *ap = host->ports[i];
+ of_node_phy = of_parse_phandle(dev->of_node,
+ "samsung,exynos-sata-phy", i);
+ if (!of_node_phy) {
+ dev_err(dev,
+ "phandle of phy not found for port %d\n", i);
+ break;
+ }
+
+ sata->phy[i] = sata_get_phy(of_node_phy);
+ if (IS_ERR(sata->phy[i])) {
+ if (PTR_ERR(sata->phy[i]) == -EBUSY)
+ continue;
+ dev_err(dev,
+ "failed to get sata phy for port %d\n", i);
+ if (flag != DEFERED) {
+ flag = DEFERED ;
+ return -EPROBE_DEFER;
+ } else
+ continue;
+
+ }
+ /* Initialize the PHY */
+ ret = sata_init_phy(sata->phy[i]);
+ if (ret < 0) {
+ if (ret == -EPROBE_DEFER) {
+ if (flag != DEFERED) {
+ flag = DEFERED ;
+ sata_put_phy(sata->phy[i]);
+ return -EPROBE_DEFER;
+ } else {
+ continue;
+ }
+ } else {
+ dev_err(dev,
+ "failed to initialize sata phy for port %d\n",
+ i);
+ sata_put_phy(sata->phy[i]);
+ }
+
+ }
+
+ /* set enclosure management message type */
+ if (ap->flags & ATA_FLAG_EM)
+ ap->em_message_type = hpriv->em_msg_type;
+
+ /* disabled/not-implemented port */
+ if (!(hpriv->port_map & (1 << i)))
+ ap->ops = &ata_dummy_port_ops;
+
+ port_init++;
+ }
+
+ if (port_init == NO_PORT)
+ goto err_initphy;
+
+ ret = ahci_reset_controller(host);
+ if (ret)
+ goto err_rst;
+
+ ahci_init_controller(host);
+ ahci_print_info(host, "platform");
+
+ ret = ata_host_activate(host, sata->irq, ahci_interrupt, IRQF_SHARED,
+ &ahci_platform_sht);
+ if (ret)
+ goto err_rst;
+
+ platform_set_drvdata(pdev, sata);
+
+ return 0;
+
+ err_rst:
+ for (i = 0; i < host->n_ports; i++)
+ sata_shutdown_phy(sata->phy[i]);
+
+ err_initphy:
+ for (i = 0; i < host->n_ports; i++)
+ sata_put_phy(sata->phy[i]);
+
+ err_clken:
+ clk_disable_unprepare(sata->clk);
+
+ err_clkstrt:
+ clk_disable_unprepare(sata->sclk);
+
+ err_iomap:
+ iounmap(hpriv->mmio);
+
+ return ret;
+}
+
+static int exynos_sata_remove(struct platform_device *pdev)
+{
+ unsigned int i;
+ struct device *dev = &pdev->dev;
+ struct ata_host *host = dev_get_drvdata(dev);
+ struct exynos_sata *sata = platform_get_drvdata(pdev);
+ struct ahci_host_priv *hpriv =
+ (struct ahci_host_priv *)host->private_data;
+
+ ata_host_detach(host);
+
+ for (i = 0; i < host->n_ports; i++) {
+ sata_shutdown_phy(sata->phy[i]);
+ sata_put_phy(sata->phy[i]);
+ }
+ iounmap(hpriv->mmio);
+
+ return 0;
+}
+
+static const struct of_device_id ahci_of_match[] = {
+ { .compatible = "samsung,exynos5-sata-ahci", },
+};
+
+MODULE_DEVICE_TABLE(of, ahci_of_match);
+
+static struct platform_driver exynos_sata_driver = {
+ .probe = exynos_sata_probe,
+ .remove = exynos_sata_remove,
+ .driver = {
+ .name = "exynos-sata",
+ .owner = THIS_MODULE,
+ .of_match_table = ahci_of_match,
+ },
+};
+
+module_platform_driver(exynos_sata_driver);
+
+MODULE_DESCRIPTION("EXYNOS SATA DRIVER");
+MODULE_AUTHOR("Vasanth Ananthan, <vasanth.a@samsung.com>");
+MODULE_LICENSE("GPL");
diff --git a/drivers/ata/sata_exynos_phy.c b/drivers/ata/sata_exynos_phy.c
new file mode 100644
index 000000000000..e9417097ffb2
--- /dev/null
+++ b/drivers/ata/sata_exynos_phy.c
@@ -0,0 +1,296 @@
+/*
+ * Copyright (c) 2010-2012 Samsung Electronics Co., Ltd.
+ * http://www.samsung.com
+ *
+ * EXYNOS - SATA PHY controller driver
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+*/
+
+#include <linux/module.h>
+#include <linux/device.h>
+#include <linux/platform_device.h>
+#include <linux/i2c.h>
+#include <linux/clk.h>
+#include <linux/delay.h>
+#include <linux/dma-mapping.h>
+#include <linux/ahci_platform.h>
+#include <linux/kernel.h>
+#include <linux/slab.h>
+#include <linux/list.h>
+#include <linux/io.h>
+#include <linux/of_address.h>
+
+#include <plat/cpu.h>
+#include <plat/irqs.h>
+
+#include <mach/map.h>
+#include <mach/regs-pmu.h>
+
+#include "sata_phy.h"
+#include "sata_exynos_phy.h"
+
+#define SATA_TIME_LIMIT 1000
+
+static struct i2c_client *i2c_client;
+
+static struct i2c_driver sataphy_i2c_driver;
+
+struct exynos_sata_phy {
+ void __iomem *mmio;
+ void __iomem *pmureg;
+ struct clk *clk;
+ struct device *dev;
+ struct sata_phy phy;
+};
+
+static bool sata_is_reg(void __iomem *base, u32 reg, u32 checkbit, u32 status)
+{
+ if ((readl(base + reg) & checkbit) == status)
+ return true;
+ else
+ return false;
+}
+
+static bool wait_for_reg_status(void __iomem *base, u32 reg, u32 checkbit,
+ u32 status)
+{
+ unsigned long timeout = jiffies + usecs_to_jiffies(1000);
+
+ while (time_before(jiffies, timeout)) {
+ if (sata_is_reg(base, reg, checkbit, status))
+ return true;
+ }
+
+ return false;
+}
+
+static int exynos_sataphy_parse_dt(struct device *dev,
+ struct exynos_sata_phy *phy)
+{
+ struct device_node *sataphy_pmu;
+
+ sataphy_pmu = of_get_child_by_name(dev->of_node, "sataphy-pmu");
+ if (!sataphy_pmu) {
+ dev_err(dev,
+ "PMU control register for sata-phy not specified\n");
+ return -ENODEV;
+ }
+
+ phy->pmureg = of_iomap(sataphy_pmu, 0);
+
+ of_node_put(sataphy_pmu);
+
+ if (!phy->pmureg) {
+ dev_err(dev, "Can't get sata-phy pmu control register\n");
+ return -EADDRNOTAVAIL;
+ }
+
+ return 0;
+}
+
+static int exynos_sataphy_init(struct sata_phy *phy)
+{
+ int ret;
+ u32 val;
+
+ /* Values to be written to enable 40 bits interface */
+ u8 buf[] = { 0x3A, 0x0B };
+
+ struct exynos_sata_phy *sata_phy;
+
+ if (!i2c_client)
+ return -EPROBE_DEFER;
+
+ sata_phy = container_of(phy, struct exynos_sata_phy, phy);
+
+ ret = clk_prepare_enable(sata_phy->clk);
+ if (ret < 0) {
+ dev_err(phy->dev, "failed to enable source clk\n");
+ return ret;
+ }
+
+ if (sata_is_reg(sata_phy->mmio , EXYNOS5_SATA_CTRL0,
+ CTRL0_P0_PHY_CALIBRATED, CTRL0_P0_PHY_CALIBRATED))
+ return 0;
+
+ writel(SATA_PHY_PMU_EN, sata_phy->pmureg);
+
+ val = 0;
+ writel(val, sata_phy->mmio + EXYNOS5_SATA_RESET);
+
+ val = readl(sata_phy->mmio + EXYNOS5_SATA_RESET);
+ val |= 0xFF;
+ writel(val, sata_phy->mmio + EXYNOS5_SATA_RESET);
+
+ val = readl(sata_phy->mmio + EXYNOS5_SATA_RESET);
+ val |= LINK_RESET;
+ writel(val, sata_phy->mmio + EXYNOS5_SATA_RESET);
+
+ val = readl(sata_phy->mmio + EXYNOS5_SATA_RESET);
+ val |= RESET_CMN_RST_N;
+ writel(val, sata_phy->mmio + EXYNOS5_SATA_RESET);
+
+ val = readl(sata_phy->mmio + EXYNOS5_SATA_PHSATA_CTRLM);
+ val &= ~PHCTRLM_REF_RATE;
+ writel(val, sata_phy->mmio + EXYNOS5_SATA_PHSATA_CTRLM);
+
+ /* High speed enable for Gen3 */
+ val = readl(sata_phy->mmio + EXYNOS5_SATA_PHSATA_CTRLM);
+ val |= PHCTRLM_HIGH_SPEED;
+ writel(val, sata_phy->mmio + EXYNOS5_SATA_PHSATA_CTRLM);
+
+ val = readl(sata_phy->mmio + EXYNOS5_SATA_CTRL0);
+ val |= CTRL0_P0_PHY_CALIBRATED_SEL | CTRL0_P0_PHY_CALIBRATED;
+ writel(val, sata_phy->mmio + EXYNOS5_SATA_CTRL0);
+
+ writel(0x2, sata_phy->mmio + EXYNOS5_SATA_MODE0);
+
+ ret = i2c_master_send(i2c_client, buf, sizeof(buf));
+ if (ret < 0)
+ return -ENXIO;
+
+ /* release cmu reset */
+ val = readl(sata_phy->mmio + EXYNOS5_SATA_RESET);
+ val &= ~RESET_CMN_RST_N;
+ writel(val, sata_phy->mmio + EXYNOS5_SATA_RESET);
+
+ val = readl(sata_phy->mmio + EXYNOS5_SATA_RESET);
+ val |= RESET_CMN_RST_N;
+ writel(val, sata_phy->mmio + EXYNOS5_SATA_RESET);
+
+ if (wait_for_reg_status(sata_phy->mmio, EXYNOS5_SATA_PHSATA_STATM,
+ PHSTATM_PLL_LOCKED, 1)) {
+ return 0;
+ }
+ return -EINVAL;
+}
+
+static int exynos_sataphy_shutdown(struct sata_phy *phy)
+{
+
+ struct exynos_sata_phy *sata_phy;
+
+ sata_phy = container_of(phy, struct exynos_sata_phy, phy);
+ clk_disable_unprepare(sata_phy->clk);
+
+ return 0;
+}
+
+static int exynos_sata_i2c_probe(struct i2c_client *client,
+ const struct i2c_device_id *i2c_id)
+{
+ i2c_client = client;
+ return 0;
+}
+
+static int exynos_sata_phy_probe(struct platform_device *pdev)
+{
+ struct exynos_sata_phy *sataphy;
+ struct device *dev = &pdev->dev;
+ int ret = 0;
+ sataphy = devm_kzalloc(dev, sizeof(struct exynos_sata_phy), GFP_KERNEL);
+ if (!sataphy) {
+ dev_err(dev, "failed to allocate memory\n");
+ return -ENOMEM;
+ }
+
+ sataphy->mmio = of_iomap(dev->of_node, 0);
+ if (!sataphy->mmio) {
+ dev_err(dev, "failed to remap IO\n");
+ return -EADDRNOTAVAIL;
+ }
+
+ ret = exynos_sataphy_parse_dt(dev, sataphy);
+ if (ret != 0)
+ goto err_iomap;
+
+ sataphy->clk = devm_clk_get(dev, "sata_phyctrl");
+ if (IS_ERR(sataphy->clk)) {
+ dev_err(dev, "failed to get clk for PHY\n");
+ ret = PTR_ERR(sataphy->clk);
+ goto err_pmu;
+ }
+
+ sataphy->phy.init = exynos_sataphy_init;
+ sataphy->phy.shutdown = exynos_sataphy_shutdown;
+ sataphy->phy.dev = dev;
+
+ ret = sata_add_phy(&sataphy->phy);
+ if (ret < 0) {
+ dev_err(dev, "PHY not registered with framework\n");
+ goto err_iomap;
+ }
+
+ ret = i2c_add_driver(&sataphy_i2c_driver);
+ if (ret < 0)
+ goto err_phy;
+
+ platform_set_drvdata(pdev, sataphy);
+
+ return ret;
+
+ err_phy:
+ sata_remove_phy(&sataphy->phy);
+
+ err_pmu:
+ iounmap(sataphy->pmureg);
+
+ err_iomap:
+ iounmap(sataphy->mmio);
+
+ return ret;
+}
+
+static int exynos_sata_phy_remove(struct platform_device *pdev)
+{
+ struct exynos_sata_phy *sataphy;
+
+ sataphy = platform_get_drvdata(pdev);
+ iounmap(sataphy->mmio);
+ i2c_del_driver(&sataphy_i2c_driver);
+ sata_remove_phy(&sataphy->phy);
+
+ return 0;
+}
+
+static const struct of_device_id sata_phy_of_match[] = {
+ { .compatible = "samsung,exynos5-sata-phy", },
+ {},
+};
+
+MODULE_DEVICE_TABLE(of, sata_phy_of_match);
+
+static const struct i2c_device_id phy_i2c_device_match[] = {
+ { "sata-phy", 0 },
+};
+
+MODULE_DEVICE_TABLE(of, phy_i2c_device_match);
+
+static struct platform_driver sata_phy_driver = {
+ .probe = exynos_sata_phy_probe,
+ .remove = exynos_sata_phy_remove,
+ .driver = {
+ .name = "sata-phy",
+ .owner = THIS_MODULE,
+ .of_match_table = sata_phy_of_match,
+ },
+};
+
+static struct i2c_driver sataphy_i2c_driver = {
+ .driver = {
+ .name = "sata-phy-i2c",
+ .owner = THIS_MODULE,
+ .of_match_table = (void *)phy_i2c_device_match,
+ },
+ .probe = exynos_sata_i2c_probe,
+ .id_table = phy_i2c_device_match,
+};
+
+module_platform_driver(sata_phy_driver);
+
+MODULE_DESCRIPTION("EXYNOS SATA PHY DRIVER");
+MODULE_AUTHOR("Vasanth Ananthan, <vasanth.a@samsung.com>");
+MODULE_LICENSE("GPL");
diff --git a/drivers/ata/sata_exynos_phy.h b/drivers/ata/sata_exynos_phy.h
new file mode 100644
index 000000000000..f9889ccd9abc
--- /dev/null
+++ b/drivers/ata/sata_exynos_phy.h
@@ -0,0 +1,32 @@
+/*
+ * Copyright (c) 2010-2012 Samsung Electronics Co., Ltd.
+ * http://www.samsung.com
+ *
+ * EXYNOS - SATA PHY controller definition
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+*/
+
+#define EXYNOS5_SATA_RESET 0x4
+#define RESET_CMN_RST_N (1 << 1)
+#define LINK_RESET 0xF0000
+
+#define EXYNOS5_SATA_MODE0 0x10
+
+#define EXYNOS5_SATA_CTRL0 0x14
+#define CTRL0_P0_PHY_CALIBRATED_SEL (1 << 9)
+#define CTRL0_P0_PHY_CALIBRATED (1 << 8)
+
+#define EXYNOS5_SATA_PHSATA_CTRLM 0xE0
+#define PHCTRLM_REF_RATE (1 << 1)
+#define PHCTRLM_HIGH_SPEED (1 << 0)
+
+#define EXYNOS5_SATA_PHSATA_STATM 0xF0
+#define PHSTATM_PLL_LOCKED (1 << 0)
+
+#define SATA_PHY_CON_RESET 0xF003F
+
+#define SATA_PHY_PMU_EN 0x1
+
diff --git a/drivers/ata/sata_phy.c b/drivers/ata/sata_phy.c
new file mode 100644
index 000000000000..53d441775d74
--- /dev/null
+++ b/drivers/ata/sata_phy.c
@@ -0,0 +1,147 @@
+/*
+ * Copyright (c) 2010-2012 Samsung Electronics Co., Ltd.
+ * http://www.samsung.com
+ *
+ * SATA PHY framework.
+ *
+ * This file provides a set of functions/interfaces for establishing
+ * communication between SATA controller and the PHY controller. A
+ * PHY controller driver registers call backs for its initialization and
+ * shutdown. The SATA controller driver finds the appropriate PHYs for
+ * its implemented ports and initialize/shutdown PHYs through the
+ * call backs provided.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+*/
+
+#include <linux/kernel.h>
+#include <linux/export.h>
+#include <linux/err.h>
+#include <linux/device.h>
+#include <linux/slab.h>
+#include <linux/list.h>
+#include "sata_phy.h"
+
+static LIST_HEAD(phy_list);
+static DEFINE_SPINLOCK(phy_lock);
+
+struct sata_phy *sata_get_phy(struct device_node *phy_np)
+{
+ struct sata_phy *phy;
+ unsigned long flag;
+
+ spin_lock_irqsave(&phy_lock, flag);
+
+ if (list_empty(&phy_list)) {
+ spin_unlock_irqrestore(&phy_lock, flag);
+ return ERR_PTR(-ENODEV);
+ }
+
+ list_for_each_entry(phy, &phy_list, head) {
+ if (phy->dev->of_node == phy_np) {
+ if (phy->status == IN_USE) {
+ pr_info(KERN_INFO
+ "PHY already in use\n");
+ spin_unlock_irqrestore(&phy_lock, flag);
+ return ERR_PTR(-EBUSY);
+ }
+
+ get_device(phy->dev);
+ phy->status = IN_USE;
+ spin_unlock_irqrestore(&phy_lock, flag);
+ return phy;
+ }
+ }
+
+ spin_unlock_irqrestore(&phy_lock, flag);
+ return ERR_PTR(-ENODEV);
+}
+EXPORT_SYMBOL(sata_get_phy);
+
+int sata_add_phy(struct sata_phy *sataphy)
+{
+ unsigned long flag;
+ unsigned int ret = -EINVAL;
+ struct sata_phy *phy;
+
+ if (!sataphy)
+ return ret;
+
+ spin_lock_irqsave(&phy_lock, flag);
+
+ list_for_each_entry(phy, &phy_list, head) {
+ if (phy->dev->of_node == sataphy->dev->of_node) {
+ dev_err(sataphy->dev, "PHY already exists in the list\n");
+ goto out;
+ }
+ }
+
+ sataphy->status = NOT_IN_USE;
+ list_add_tail(&sataphy->head, &phy_list);
+ ret = 0;
+
+ out:
+ spin_unlock_irqrestore(&phy_lock, flag);
+ return ret;
+}
+EXPORT_SYMBOL(sata_add_phy);
+
+void sata_remove_phy(struct sata_phy *sataphy)
+{
+ unsigned long flag;
+ struct sata_phy *phy;
+
+ if (!sataphy)
+ return;
+
+ if (sataphy->status == IN_USE) {
+ pr_info(KERN_INFO
+ "PHY in use, cannot be removed\n");
+ return;
+ }
+
+ spin_lock_irqsave(&phy_lock, flag);
+
+ list_for_each_entry(phy, &phy_list, head) {
+ if (phy->dev->of_node == sataphy->dev->of_node)
+ list_del(&phy->head);
+ }
+
+ spin_unlock_irqrestore(&phy_lock, flag);
+}
+EXPORT_SYMBOL(sata_remove_phy);
+
+void sata_put_phy(struct sata_phy *sataphy)
+{
+ unsigned long flag;
+
+ if (!sataphy)
+ return;
+
+ spin_lock_irqsave(&phy_lock, flag);
+
+ put_device(sataphy->dev);
+ sataphy->status = NOT_IN_USE;
+
+ spin_unlock_irqrestore(&phy_lock, flag);
+}
+EXPORT_SYMBOL(sata_put_phy);
+
+int sata_init_phy(struct sata_phy *sataphy)
+{
+ if (sataphy && sataphy->init)
+ return sataphy->init(sataphy);
+
+ return -EINVAL;
+}
+EXPORT_SYMBOL(sata_init_phy);
+
+void sata_shutdown_phy(struct sata_phy *sataphy)
+{
+ if (sataphy && sataphy->shutdown)
+ sataphy->shutdown(sataphy);
+}
+EXPORT_SYMBOL(sata_shutdown_phy);
+
diff --git a/drivers/ata/sata_phy.h b/drivers/ata/sata_phy.h
new file mode 100644
index 000000000000..9ed1dbed5a11
--- /dev/null
+++ b/drivers/ata/sata_phy.h
@@ -0,0 +1,30 @@
+/*
+ * Copyright (c) 2010-2012 Samsung Electronics Co., Ltd.
+ * http://www.samsung.com
+ *
+ * SATA utility framework definitions.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+*/
+
+#define IN_USE 1
+#define NOT_IN_USE 0
+
+struct sata_phy {
+ int (*init) (struct sata_phy *);
+ int (*shutdown) (struct sata_phy *);
+ struct device *dev;
+ void *priv_data;
+ struct list_head head;
+ unsigned char status;
+};
+
+struct sata_phy *sata_get_phy(struct device_node *);
+int sata_add_phy(struct sata_phy *);
+void sata_remove_phy(struct sata_phy *);
+void sata_put_phy(struct sata_phy *);
+int sata_init_phy(struct sata_phy *);
+void sata_shutdown_phy(struct sata_phy *);
+
diff --git a/drivers/clk/samsung/clk-exynos5250.c b/drivers/clk/samsung/clk-exynos5250.c
index 6f767c515ec7..24a66b36dcd9 100644
--- a/drivers/clk/samsung/clk-exynos5250.c
+++ b/drivers/clk/samsung/clk-exynos5250.c
@@ -24,6 +24,7 @@
#define SRC_CORE1 0x4204
#define SRC_TOP0 0x10210
#define SRC_TOP2 0x10218
+#define SRC_TOP3 0x1021C
#define SRC_GSCL 0x10220
#define SRC_DISP1_0 0x1022c
#define SRC_MAU 0x10240
@@ -87,7 +88,7 @@ enum exynos5250_clks {
sclk_mmc0, sclk_mmc1, sclk_mmc2, sclk_mmc3, sclk_sata, sclk_usb3,
sclk_jpeg, sclk_uart0, sclk_uart1, sclk_uart2, sclk_uart3, sclk_pwm,
sclk_audio1, sclk_audio2, sclk_spdif, sclk_spi0, sclk_spi1, sclk_spi2,
- div_i2s1, div_i2s2,
+ div_i2s1, div_i2s2, sclk_hdmiphy,
/* gate clocks */
gscl0 = 256, gscl1, gscl2, gscl3, gscl_wa, gscl_wb, smmu_gscl0,
@@ -99,7 +100,10 @@ enum exynos5250_clks {
spi2, i2s1, i2s2, pcm1, pcm2, pwm, spdif, ac97, hsi2c0, hsi2c1, hsi2c2,
hsi2c3, chipid, sysreg, pmu, cmu_top, cmu_core, cmu_mem, tzpc0, tzpc1,
tzpc2, tzpc3, tzpc4, tzpc5, tzpc6, tzpc7, tzpc8, tzpc9, hdmi_cec, mct,
- wdt, rtc, tmu, fimd1, mie1, dsim0, dp, mixer, hdmi,
+ wdt, rtc, tmu, fimd1, mie1, dsim0, dp, mixer, hdmi, smmu_mixer,
+
+ /* mux clocks */
+ mout_hdmi = 1024,
nr_clks,
};
@@ -169,6 +173,7 @@ PNAME(mout_mpll_user_p) = { "fin_pll", "sclk_mpll" };
PNAME(mout_bpll_user_p) = { "fin_pll", "sclk_bpll" };
PNAME(mout_aclk166_p) = { "sclk_cpll", "sclk_mpll_user" };
PNAME(mout_aclk200_p) = { "sclk_mpll_user", "sclk_bpll_user" };
+PNAME(mout_aclk200_disp1_sub_p) = { "fin_pll", "aclk200" };
PNAME(mout_hdmi_p) = { "div_hdmi_pixel", "sclk_hdmiphy" };
PNAME(mout_usb3_p) = { "sclk_mpll_user", "sclk_cpll" };
PNAME(mout_group1_p) = { "fin_pll", "fin_pll", "sclk_hdmi27m",
@@ -197,7 +202,7 @@ struct samsung_fixed_rate_clock exynos5250_fixed_rate_ext_clks[] __initdata = {
/* fixed rate clocks generated inside the soc */
struct samsung_fixed_rate_clock exynos5250_fixed_rate_clks[] __initdata = {
- FRATE(none, "sclk_hdmiphy", NULL, CLK_IS_ROOT, 24000000),
+ FRATE(sclk_hdmiphy, "sclk_hdmiphy", NULL, CLK_IS_ROOT, 24000000),
FRATE(none, "sclk_hdmi27m", NULL, CLK_IS_ROOT, 27000000),
FRATE(none, "sclk_dptxphy", NULL, CLK_IS_ROOT, 24000000),
FRATE(none, "sclk_uhostphy", NULL, CLK_IS_ROOT, 48000000),
@@ -224,6 +229,8 @@ struct samsung_mux_clock exynos5250_mux_clks[] __initdata = {
MUX(none, "mout_aclk166", mout_aclk166_p, SRC_TOP0, 8, 1),
MUX(none, "mout_aclk333", mout_aclk166_p, SRC_TOP0, 16, 1),
MUX(none, "mout_aclk200", mout_aclk200_p, SRC_TOP0, 12, 1),
+ MUX(none, "mout_aclk200_disp1", mout_aclk200_disp1_sub_p,
+ SRC_TOP3, 4, 1),
MUX(none, "mout_cam_bayer", mout_group1_p, SRC_GSCL, 12, 4),
MUX(none, "mout_cam0", mout_group1_p, SRC_GSCL, 16, 4),
MUX(none, "mout_cam1", mout_group1_p, SRC_GSCL, 20, 4),
@@ -232,7 +239,7 @@ struct samsung_mux_clock exynos5250_mux_clks[] __initdata = {
MUX(none, "mout_fimd1", mout_group1_p, SRC_DISP1_0, 0, 4),
MUX(none, "mout_mipi1", mout_group1_p, SRC_DISP1_0, 12, 4),
MUX(none, "mout_dp", mout_group1_p, SRC_DISP1_0, 16, 4),
- MUX(none, "mout_hdmi", mout_hdmi_p, SRC_DISP1_0, 20, 1),
+ MUX(mout_hdmi, "mout_hdmi", mout_hdmi_p, SRC_DISP1_0, 20, 1),
MUX(none, "mout_audio0", mout_audio0_p, SRC_MAU, 0, 4),
MUX(none, "mout_mmc0", mout_group1_p, SRC_FSYS, 0, 4),
MUX(none, "mout_mmc1", mout_group1_p, SRC_FSYS, 4, 4),
@@ -325,6 +332,7 @@ struct samsung_gate_clock exynos5250_gate_clks[] __initdata = {
GATE(smmu_gscl1, "smmu_gscl1", "aclk266", GATE_IP_GSCL, 8, 0, 0),
GATE(smmu_gscl2, "smmu_gscl2", "aclk266", GATE_IP_GSCL, 9, 0, 0),
GATE(smmu_gscl3, "smmu_gscl3", "aclk266", GATE_IP_GSCL, 10, 0, 0),
+ GATE(smmu_mixer, "smmu_mixer", "mout_aclk200_disp1", GATE_IP_DISP1, 9, 0, 0),
GATE(mfc, "mfc", "aclk333", GATE_IP_MFC, 0, 0, 0),
GATE(smmu_mfcl, "smmu_mfcl", "aclk333", GATE_IP_MFC, 1, 0, 0),
GATE(smmu_mfcr, "smmu_mfcr", "aclk333", GATE_IP_MFC, 2, 0, 0),
@@ -461,8 +469,8 @@ struct samsung_gate_clock exynos5250_gate_clks[] __initdata = {
GATE(mie1, "mie1", "aclk200", GATE_IP_DISP1, 1, 0, 0),
GATE(dsim0, "dsim0", "aclk200", GATE_IP_DISP1, 3, 0, 0),
GATE(dp, "dp", "aclk200", GATE_IP_DISP1, 4, 0, 0),
- GATE(mixer, "mixer", "aclk200", GATE_IP_DISP1, 5, 0, 0),
- GATE(hdmi, "hdmi", "aclk200", GATE_IP_DISP1, 6, 0, 0),
+ GATE(mixer, "mixer", "mout_aclk200_disp1", GATE_IP_DISP1, 5, 0, 0),
+ GATE(hdmi, "hdmi", "mout_aclk200_disp1", GATE_IP_DISP1, 6, 0, 0),
};
static __initdata struct of_device_id ext_clk_match[] = {
diff --git a/drivers/clocksource/exynos_mct.c b/drivers/clocksource/exynos_mct.c
index b2bbc415f120..23d318267da8 100644
--- a/drivers/clocksource/exynos_mct.c
+++ b/drivers/clocksource/exynos_mct.c
@@ -27,6 +27,8 @@
#include <asm/localtimer.h>
#include <asm/mach/time.h>
+#include <plat/cpu.h>
+
#define EXYNOS4_MCTREG(x) (x)
#define EXYNOS4_MCT_G_CNT_L EXYNOS4_MCTREG(0x100)
#define EXYNOS4_MCT_G_CNT_U EXYNOS4_MCTREG(0x104)
@@ -194,6 +196,10 @@ static void __init exynos4_clocksource_init(void)
{
exynos4_mct_frc_start(0, 0);
+ if (soc_is_exynos5250()) {
+ mct_frc.rating = 399;
+ }
+
if (clocksource_register_hz(&mct_frc, clk_rate))
panic("%s: can't register clocksource\n", mct_frc.name);
}
diff --git a/drivers/cpufreq/exynos-cpufreq.c b/drivers/cpufreq/exynos-cpufreq.c
index 0d32f02ef4d6..630b503736e0 100644
--- a/drivers/cpufreq/exynos-cpufreq.c
+++ b/drivers/cpufreq/exynos-cpufreq.c
@@ -17,6 +17,8 @@
#include <linux/regulator/consumer.h>
#include <linux/cpufreq.h>
#include <linux/suspend.h>
+#include <linux/notifier.h>
+#include <linux/reboot.h>
#include <plat/cpu.h>
@@ -245,8 +247,35 @@ static struct notifier_block exynos_cpufreq_nb = {
.notifier_call = exynos_cpufreq_pm_notifier,
};
+static int exynos_cpufreq_reboot_notifier(struct notifier_block *this,
+ unsigned long code, void *_cmd)
+{
+ struct cpufreq_policy *policy = cpufreq_cpu_get(0); /* boot CPU */
+ mutex_lock(&cpufreq_lock);
+
+ if (frequency_locked)
+ goto out;
+ frequency_locked = true;
+
+ if (locking_frequency) {
+ mutex_unlock(&cpufreq_lock);
+ exynos_target(policy, locking_frequency, CPUFREQ_RELATION_H);
+ mutex_lock(&cpufreq_lock);
+ }
+
+out:
+ mutex_unlock(&cpufreq_lock);
+ return NOTIFY_DONE;
+}
+
+static struct notifier_block exynos_cpufreq_reboot_nb = {
+ .notifier_call = exynos_cpufreq_reboot_notifier,
+};
+
static int exynos_cpufreq_cpu_init(struct cpufreq_policy *policy)
{
+ int ret;
+
policy->cur = policy->min = policy->max = exynos_getspeed(policy->cpu);
cpufreq_frequency_table_get_attr(exynos_info->freq_table, policy->cpu);
@@ -256,7 +285,13 @@ static int exynos_cpufreq_cpu_init(struct cpufreq_policy *policy)
cpumask_setall(policy->cpus);
- return cpufreq_frequency_table_cpuinfo(policy, exynos_info->freq_table);
+ ret = cpufreq_frequency_table_cpuinfo(policy, exynos_info->freq_table);
+ if (ret)
+ return ret;
+
+ cpufreq_frequency_table_get_attr(exynos_info->freq_table, policy->cpu);
+ return 0;
+
}
static int exynos_cpufreq_cpu_exit(struct cpufreq_policy *policy)
@@ -319,6 +354,7 @@ static int __init exynos_cpufreq_init(void)
locking_frequency = exynos_getspeed(0);
register_pm_notifier(&exynos_cpufreq_nb);
+ register_reboot_notifier(&exynos_cpufreq_reboot_nb);
if (cpufreq_register_driver(&exynos_driver)) {
pr_err("%s: failed to register cpufreq driver\n", __func__);
diff --git a/drivers/gpu/drm/exynos/exynos_drm_drv.c b/drivers/gpu/drm/exynos/exynos_drm_drv.c
index ca2729a85129..812178df0ee2 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_drv.c
+++ b/drivers/gpu/drm/exynos/exynos_drm_drv.c
@@ -287,7 +287,8 @@ static struct drm_driver exynos_drm_driver = {
static int exynos_drm_platform_probe(struct platform_device *pdev)
{
- pdev->dev.coherent_dma_mask = DMA_BIT_MASK(32);
+ if (!pdev->dev.coherent_dma_mask)
+ pdev->dev.coherent_dma_mask = DMA_BIT_MASK(32);
exynos_drm_driver.num_ioctls = DRM_ARRAY_SIZE(exynos_ioctls);
return drm_platform_init(&exynos_drm_driver, pdev);
diff --git a/drivers/gpu/drm/exynos/exynos_hdmi.c b/drivers/gpu/drm/exynos/exynos_hdmi.c
index 62ef5971ac3c..3ba7dd9db389 100644
--- a/drivers/gpu/drm/exynos/exynos_hdmi.c
+++ b/drivers/gpu/drm/exynos/exynos_hdmi.c
@@ -34,6 +34,7 @@
#include <linux/regulator/consumer.h>
#include <linux/io.h>
#include <linux/of_gpio.h>
+#include <linux/of_address.h>
#include <drm/exynos_drm.h>
@@ -82,7 +83,6 @@ struct hdmi_resources {
struct clk *sclk_hdmi;
struct clk *sclk_pixel;
struct clk *sclk_hdmiphy;
- struct clk *hdmiphy;
struct clk *mout_hdmi;
struct regulator_bulk_data *regul_bulk;
int regul_count;
@@ -189,6 +189,7 @@ struct hdmi_context {
struct mutex hdmi_mutex;
void __iomem *regs;
+ void __iomem *phy_pow_ctrl_reg;
void *parent_ctx;
int irq;
@@ -404,6 +405,14 @@ static inline void hdmi_reg_writemask(struct hdmi_context *hdata,
writel(value, hdata->regs + reg_id);
}
+static inline void hdmi_phy_pow_ctrl_reg_writemask(struct hdmi_context *hdata,
+ u32 value, u32 mask)
+{
+ u32 old = readl(hdata->phy_pow_ctrl_reg);
+ value = (value & mask) | (old & ~mask);
+ writel(value, hdata->phy_pow_ctrl_reg);
+}
+
static void hdmi_v13_regs_dump(struct hdmi_context *hdata, char *prefix)
{
#define DUMPREG(reg_id) \
@@ -1686,7 +1695,8 @@ static void hdmi_poweron(struct hdmi_context *hdata)
if (regulator_bulk_enable(res->regul_count, res->regul_bulk))
DRM_DEBUG_KMS("failed to enable regulator bulk\n");
- clk_prepare_enable(res->hdmiphy);
+ hdmi_phy_pow_ctrl_reg_writemask(hdata, PMU_HDMI_PHY_ENABLE,
+ PMU_HDMI_PHY_CONTROL_MASK);
clk_prepare_enable(res->hdmi);
clk_prepare_enable(res->sclk_hdmi);
@@ -1711,7 +1721,8 @@ static void hdmi_poweroff(struct hdmi_context *hdata)
clk_disable_unprepare(res->sclk_hdmi);
clk_disable_unprepare(res->hdmi);
- clk_disable_unprepare(res->hdmiphy);
+ hdmi_phy_pow_ctrl_reg_writemask(hdata, PMU_HDMI_PHY_DISABLE,
+ PMU_HDMI_PHY_CONTROL_MASK);
regulator_bulk_disable(res->regul_count, res->regul_bulk);
mutex_lock(&hdata->hdmi_mutex);
@@ -1764,7 +1775,7 @@ static irqreturn_t hdmi_irq_thread(int irq, void *arg)
struct hdmi_context *hdata = ctx->ctx;
mutex_lock(&hdata->hdmi_mutex);
- hdata->hpd = gpio_get_value(hdata->hpd_gpio);
+ hdata->hpd = true; /* gpio_get_value(hdata->hpd_gpio); */
mutex_unlock(&hdata->hdmi_mutex);
if (ctx->drm_dev)
@@ -1810,11 +1821,6 @@ static int hdmi_resources_init(struct hdmi_context *hdata)
DRM_ERROR("failed to get clock 'sclk_hdmiphy'\n");
goto fail;
}
- res->hdmiphy = devm_clk_get(dev, "hdmiphy");
- if (IS_ERR(res->hdmiphy)) {
- DRM_ERROR("failed to get clock 'hdmiphy'\n");
- goto fail;
- }
res->mout_hdmi = devm_clk_get(dev, "mout_hdmi");
if (IS_ERR(res->mout_hdmi)) {
DRM_ERROR("failed to get clock 'mout_hdmi'\n");
@@ -1840,6 +1846,13 @@ static int hdmi_resources_init(struct hdmi_context *hdata)
}
res->regul_count = ARRAY_SIZE(supply);
+ clk_prepare(res->hdmi);
+ clk_prepare(res->sclk_hdmi);
+ clk_prepare(res->sclk_pixel);
+ clk_prepare(res->sclk_hdmiphy);
+
+ clk_set_parent(res->sclk_hdmi, res->sclk_pixel);
+
return 0;
fail:
DRM_ERROR("HDMI resource init - failed\n");
@@ -1886,12 +1899,52 @@ static struct s5p_hdmi_platform_data *drm_hdmi_dt_parse_pdata
err_data:
return NULL;
}
+
+static int drm_hdmi_dt_parse_phy_pow_control(struct hdmi_context *hdata)
+{
+ struct device_node *phy_pow_ctrl_node;
+ u32 buf[2];
+ int ret = 0;
+
+ phy_pow_ctrl_node = of_find_node_by_name(NULL, "phy-power-control");
+ if (!phy_pow_ctrl_node) {
+ DRM_ERROR("Failed to find phy power control node\n");
+ ret = -ENODEV;
+ goto fail;
+ }
+
+ /* reg property holds two informations: addr of pmu register, size */
+ if (of_property_read_u32_array(phy_pow_ctrl_node, "reg",
+ (u32 *)&buf, 2)) {
+ DRM_ERROR("faild to get phy power control reg\n");
+ ret = -EINVAL;
+ goto fail;
+ }
+
+ hdata->phy_pow_ctrl_reg = devm_ioremap(hdata->dev, buf[0], buf[1]);
+ if (!hdata->phy_pow_ctrl_reg) {
+ DRM_ERROR("failed to ioremap phy pmu reg\n");
+ ret = -ENOMEM;
+ goto fail;
+ }
+
+fail:
+ of_node_put(phy_pow_ctrl_node);
+ return ret;
+}
+
#else
static struct s5p_hdmi_platform_data *drm_hdmi_dt_parse_pdata
(struct device *dev)
{
return NULL;
}
+
+static int drm_hdmi_dt_parse_phy_pow_control(struct hdmi_context *hdata)
+{
+ return 0;
+}
+
#endif
static struct platform_device_id hdmi_driver_types[] = {
@@ -1994,20 +2047,30 @@ static int hdmi_probe(struct platform_device *pdev)
}
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
- hdata->regs = devm_ioremap_resource(dev, res);
- if (IS_ERR(hdata->regs))
- return PTR_ERR(hdata->regs);
+ hdata->regs = devm_ioremap_resource(&pdev->dev, res);
+ if (IS_ERR(hdata->regs)) {
+ ret = PTR_ERR(hdata->regs);
+ goto err_clk_res;
+ }
ret = devm_gpio_request(dev, hdata->hpd_gpio, "HPD");
if (ret) {
DRM_ERROR("failed to request HPD gpio\n");
+ goto err_clk_res;
+ }
+
+ /* map hdmiphy power control reg */
+ ret = drm_hdmi_dt_parse_phy_pow_control(hdata);
+ if (ret) {
+ DRM_ERROR("failed to map phy power control registers\n");
return ret;
}
/* DDC i2c driver */
if (i2c_add_driver(&ddc_driver)) {
DRM_ERROR("failed to register ddc i2c driver\n");
- return -ENOENT;
+ ret = -ENOENT;
+ goto err_clk_res;
}
hdata->ddc_port = hdmi_ddc;
@@ -2028,7 +2091,7 @@ static int hdmi_probe(struct platform_device *pdev)
goto err_hdmiphy;
}
- hdata->hpd = gpio_get_value(hdata->hpd_gpio);
+ hdata->hpd = true; /* gpio_get_value(hdata->hpd_gpio); */
ret = devm_request_threaded_irq(dev, hdata->irq, NULL,
hdmi_irq_thread, IRQF_TRIGGER_RISING |
@@ -2053,12 +2116,19 @@ err_hdmiphy:
i2c_del_driver(&hdmiphy_driver);
err_ddc:
i2c_del_driver(&ddc_driver);
+err_clk_res:
+ clk_unprepare(hdata->res.hdmi);
+ clk_unprepare(hdata->res.sclk_hdmi);
+ clk_unprepare(hdata->res.sclk_pixel);
+ clk_unprepare(hdata->res.sclk_hdmiphy);
return ret;
}
static int hdmi_remove(struct platform_device *pdev)
{
struct device *dev = &pdev->dev;
+ struct exynos_drm_hdmi_context *ctx = get_hdmi_context(dev);
+ struct hdmi_context *hdata = ctx->ctx;
pm_runtime_disable(dev);
@@ -2067,6 +2137,10 @@ static int hdmi_remove(struct platform_device *pdev)
/* DDC i2c driver */
i2c_del_driver(&ddc_driver);
+ clk_unprepare(hdata->res.hdmi);
+ clk_unprepare(hdata->res.sclk_hdmi);
+ clk_unprepare(hdata->res.sclk_pixel);
+ clk_unprepare(hdata->res.sclk_hdmiphy);
return 0;
}
@@ -2097,7 +2171,7 @@ static int hdmi_resume(struct device *dev)
struct exynos_drm_hdmi_context *ctx = get_hdmi_context(dev);
struct hdmi_context *hdata = ctx->ctx;
- hdata->hpd = gpio_get_value(hdata->hpd_gpio);
+ hdata->hpd = true; /* gpio_get_value(hdata->hpd_gpio); */
enable_irq(hdata->irq);
diff --git a/drivers/gpu/drm/exynos/exynos_mixer.c b/drivers/gpu/drm/exynos/exynos_mixer.c
index 42ffb71c63bc..143b58cb7c8f 100644
--- a/drivers/gpu/drm/exynos/exynos_mixer.c
+++ b/drivers/gpu/drm/exynos/exynos_mixer.c
@@ -1086,6 +1086,9 @@ static int mixer_resources_init(struct exynos_drm_hdmi_context *ctx,
}
mixer_res->irq = res->start;
+ clk_prepare(mixer_res->mixer);
+ clk_prepare(mixer_res->sclk_hdmi);
+
return 0;
}
@@ -1113,9 +1116,6 @@ static int vp_resources_init(struct exynos_drm_hdmi_context *ctx,
return -ENODEV;
}
- if (mixer_res->sclk_hdmi)
- clk_set_parent(mixer_res->sclk_mixer, mixer_res->sclk_hdmi);
-
res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
if (res == NULL) {
dev_err(dev, "get memory resource failed.\n");
@@ -1129,6 +1129,13 @@ static int vp_resources_init(struct exynos_drm_hdmi_context *ctx,
return -ENXIO;
}
+ clk_prepare(mixer_res->vp);
+ clk_prepare(mixer_res->sclk_mixer);
+ clk_prepare(mixer_res->sclk_dac);
+
+ if (mixer_res->sclk_hdmi)
+ clk_set_parent(mixer_res->sclk_mixer, mixer_res->sclk_hdmi);
+
return 0;
}
@@ -1230,7 +1237,7 @@ static int mixer_probe(struct platform_device *pdev)
ret = vp_resources_init(drm_hdmi_ctx, pdev);
if (ret) {
DRM_ERROR("vp_resources_init failed\n");
- goto fail;
+ goto out_vp;
}
}
@@ -1244,7 +1251,9 @@ static int mixer_probe(struct platform_device *pdev)
return 0;
-
+out_vp:
+ clk_unprepare(ctx->mixer_res.sclk_hdmi);
+ clk_unprepare(ctx->mixer_res.mixer);
fail:
dev_info(dev, "probe failed\n");
return ret;
@@ -1252,10 +1261,23 @@ fail:
static int mixer_remove(struct platform_device *pdev)
{
+ struct exynos_drm_hdmi_context *drm_hdmi_ctx =
+ get_mixer_context(&pdev->dev);
+ struct mixer_context *ctx = drm_hdmi_ctx->ctx;
+
dev_info(&pdev->dev, "remove successful\n");
pm_runtime_disable(&pdev->dev);
+ clk_unprepare(ctx->mixer_res.mixer);
+ clk_unprepare(ctx->mixer_res.sclk_hdmi);
+
+ if (ctx->vp_enabled) {
+ clk_unprepare(ctx->mixer_res.vp);
+ clk_unprepare(ctx->mixer_res.sclk_mixer);
+ clk_unprepare(ctx->mixer_res.sclk_dac);
+ }
+
return 0;
}
diff --git a/drivers/gpu/drm/exynos/regs-hdmi.h b/drivers/gpu/drm/exynos/regs-hdmi.h
index ef1b3eb3ba6e..8d9ca2543ed8 100644
--- a/drivers/gpu/drm/exynos/regs-hdmi.h
+++ b/drivers/gpu/drm/exynos/regs-hdmi.h
@@ -578,4 +578,8 @@
#define HDMI_TG_VACT_ST4_H HDMI_TG_BASE(0x0074)
#define HDMI_TG_3D HDMI_TG_BASE(0x00F0)
+#define PMU_HDMI_PHY_CONTROL_MASK (1 << 0)
+#define PMU_HDMI_PHY_ENABLE (1)
+#define PMU_HDMI_PHY_DISABLE (0)
+
#endif /* SAMSUNG_REGS_HDMI_H */
diff --git a/drivers/i2c/busses/i2c-s3c2410.c b/drivers/i2c/busses/i2c-s3c2410.c
index cab1c91b75a3..4b166bce60c2 100644
--- a/drivers/i2c/busses/i2c-s3c2410.c
+++ b/drivers/i2c/busses/i2c-s3c2410.c
@@ -86,6 +86,7 @@
#define QUIRK_S3C2440 (1 << 0)
#define QUIRK_HDMIPHY (1 << 1)
#define QUIRK_NO_GPIO (1 << 2)
+#define QUIRK_POLL (1 << 3)
/* Max time to wait for bus to become idle after a xfer (in us) */
#define S3C2410_IDLE_TIMEOUT 5000
@@ -142,6 +143,8 @@ static struct platform_device_id s3c24xx_driver_ids[] = {
};
MODULE_DEVICE_TABLE(platform, s3c24xx_driver_ids);
+static int i2c_s3c_irq_nextbyte(struct s3c24xx_i2c *i2c, unsigned long iicstat);
+
#ifdef CONFIG_OF
static const struct of_device_id s3c24xx_i2c_match[] = {
{ .compatible = "samsung,s3c2410-i2c", .data = (void *)0 },
@@ -150,6 +153,8 @@ static const struct of_device_id s3c24xx_i2c_match[] = {
.data = (void *)(QUIRK_S3C2440 | QUIRK_HDMIPHY | QUIRK_NO_GPIO) },
{ .compatible = "samsung,exynos5440-i2c",
.data = (void *)(QUIRK_S3C2440 | QUIRK_NO_GPIO) },
+ { .compatible = "samsung,exynos5-sata-phy-i2c",
+ .data = (void *)(QUIRK_S3C2440 | QUIRK_POLL | QUIRK_NO_GPIO) },
{},
};
MODULE_DEVICE_TABLE(of, s3c24xx_i2c_match);
@@ -188,7 +193,8 @@ static inline void s3c24xx_i2c_master_complete(struct s3c24xx_i2c *i2c, int ret)
if (ret)
i2c->msg_idx = ret;
- wake_up(&i2c->wait);
+ if (!(i2c->quirks & QUIRK_POLL))
+ wake_up(&i2c->wait);
}
static inline void s3c24xx_i2c_disable_ack(struct s3c24xx_i2c *i2c)
@@ -225,6 +231,22 @@ static inline void s3c24xx_i2c_enable_irq(struct s3c24xx_i2c *i2c)
writel(tmp | S3C2410_IICCON_IRQEN, i2c->regs + S3C2410_IICCON);
}
+static bool is_ack(struct s3c24xx_i2c *i2c)
+{
+ u32 time_out = i2c->tx_setup;
+
+ while (--time_out) {
+ if (readl(i2c->regs + S3C2410_IICCON)
+ & S3C2410_IICCON_IRQPEND) {
+ if (!(readl(i2c->regs + S3C2410_IICSTAT)
+ & S3C2410_IICSTAT_LASTBIT))
+ return true;
+ }
+ udelay(time_out);
+ }
+
+ return false;
+}
/* s3c24xx_i2c_message_start
*
@@ -269,6 +291,16 @@ static void s3c24xx_i2c_message_start(struct s3c24xx_i2c *i2c,
stat |= S3C2410_IICSTAT_START;
writel(stat, i2c->regs + S3C2410_IICSTAT);
+
+ if (i2c->quirks & QUIRK_POLL) {
+ while ((i2c->msg_num != 0) && is_ack(i2c)) {
+ i2c_s3c_irq_nextbyte(i2c, stat);
+ stat = readl(i2c->regs + S3C2410_IICSTAT);
+
+ if (stat & S3C2410_IICSTAT_ARBITR)
+ dev_err(i2c->dev, "deal with arbitration loss\n");
+ }
+ }
}
static inline void s3c24xx_i2c_stop(struct s3c24xx_i2c *i2c, int ret)
@@ -676,6 +708,15 @@ static int s3c24xx_i2c_doxfer(struct s3c24xx_i2c *i2c,
s3c24xx_i2c_enable_irq(i2c);
s3c24xx_i2c_message_start(i2c, msgs);
+ if (i2c->quirks & QUIRK_POLL) {
+ ret = i2c->msg_idx;
+
+ if (ret != num)
+ dev_dbg(i2c->dev, "incomplete xfer (%d)\n", ret);
+
+ goto out;
+ }
+
timeout = wait_event_timeout(i2c->wait, i2c->msg_num == 0, HZ * 5);
ret = i2c->msg_idx;
@@ -821,6 +862,9 @@ static int s3c24xx_i2c_clockrate(struct s3c24xx_i2c *i2c, unsigned int *got)
if (div1 == 512)
iiccon |= S3C2410_IICCON_TXDIV_512;
+ if (i2c->quirks & QUIRK_POLL)
+ iiccon |= S3C2410_IICCON_SCALE(2);
+
writel(iiccon, i2c->regs + S3C2410_IICCON);
if (i2c->quirks & QUIRK_S3C2440) {
@@ -1118,18 +1162,20 @@ static int s3c24xx_i2c_probe(struct platform_device *pdev)
* ensure no current IRQs pending
*/
- i2c->irq = ret = platform_get_irq(pdev, 0);
- if (ret <= 0) {
- dev_err(&pdev->dev, "cannot find IRQ\n");
- return ret;
- }
+ if (!(i2c->quirks & QUIRK_POLL)) {
+ i2c->irq = ret = platform_get_irq(pdev, 0);
+ if (ret <= 0) {
+ dev_err(&pdev->dev, "cannot find IRQ\n");
+ return ret;
+ }
- ret = devm_request_irq(&pdev->dev, i2c->irq, s3c24xx_i2c_irq, 0,
- dev_name(&pdev->dev), i2c);
+ ret = devm_request_irq(&pdev->dev, i2c->irq, s3c24xx_i2c_irq, 0,
+ dev_name(&pdev->dev), i2c);
- if (ret != 0) {
- dev_err(&pdev->dev, "cannot claim IRQ %d\n", i2c->irq);
- return ret;
+ if (ret != 0) {
+ dev_err(&pdev->dev, "cannot claim IRQ %d\n", i2c->irq);
+ return ret;
+ }
}
ret = s3c24xx_i2c_register_cpufreq(i2c);
diff --git a/drivers/media/platform/s5p-mfc/s5p_mfc_dec.c b/drivers/media/platform/s5p-mfc/s5p_mfc_dec.c
index 5296385153d5..38c17e2977ad 100644
--- a/drivers/media/platform/s5p-mfc/s5p_mfc_dec.c
+++ b/drivers/media/platform/s5p-mfc/s5p_mfc_dec.c
@@ -197,6 +197,16 @@ static struct mfc_control controls[] = {
.default_value = 1,
.is_volatile = 1,
},
+ {
+ .id = V4L2_CID_CODEC_FRAME_TAG,
+ .type = V4L2_CTRL_TYPE_INTEGER,
+ .name = "Frame Tag",
+ .minimum = 0,
+ .maximum = INT_MAX,
+ .step = 1,
+ .default_value = 0,
+ .is_volatile = 1,
+ },
};
#define NUM_CTRLS ARRAY_SIZE(controls)
@@ -735,6 +745,9 @@ static int s5p_mfc_dec_s_ctrl(struct v4l2_ctrl *ctrl)
case V4L2_CID_MPEG_VIDEO_DECODER_SLICE_INTERFACE:
ctx->slice_interface = ctrl->val;
break;
+ case V4L2_CID_CODEC_FRAME_TAG:
+ ctx->frame_tag = ctrl->val;
+ break;
default:
mfc_err("Invalid control 0x%08x\n", ctrl->id);
return -EINVAL;
@@ -769,6 +782,9 @@ static int s5p_mfc_dec_g_v_ctrl(struct v4l2_ctrl *ctrl)
return -EINVAL;
}
break;
+ case V4L2_CID_CODEC_FRAME_TAG:
+ ctrl->val = s5p_mfc_hw_call(dev->mfc_ops, get_frame_tag, ctx);
+ break;
}
return 0;
}
diff --git a/drivers/media/platform/s5p-mfc/s5p_mfc_opr.h b/drivers/media/platform/s5p-mfc/s5p_mfc_opr.h
index 754c540e7a7e..498ff09a8158 100644
--- a/drivers/media/platform/s5p-mfc/s5p_mfc_opr.h
+++ b/drivers/media/platform/s5p-mfc/s5p_mfc_opr.h
@@ -77,6 +77,7 @@ struct s5p_mfc_hw_ops {
unsigned int (*get_pic_type_bot)(struct s5p_mfc_ctx *ctx);
unsigned int (*get_crop_info_h)(struct s5p_mfc_ctx *ctx);
unsigned int (*get_crop_info_v)(struct s5p_mfc_ctx *ctx);
+ unsigned int (*get_frame_tag)(struct s5p_mfc_ctx *ctx);
};
void s5p_mfc_init_hw_ops(struct s5p_mfc_dev *dev);
diff --git a/drivers/media/platform/s5p-mfc/s5p_mfc_opr_v5.c b/drivers/media/platform/s5p-mfc/s5p_mfc_opr_v5.c
index 368582b091bf..c7408bcffa6f 100644
--- a/drivers/media/platform/s5p-mfc/s5p_mfc_opr_v5.c
+++ b/drivers/media/platform/s5p-mfc/s5p_mfc_opr_v5.c
@@ -1075,6 +1075,9 @@ static void s5p_mfc_set_flush(struct s5p_mfc_ctx *ctx, int flush)
dpb = mfc_read(dev, S5P_FIMV_SI_CH0_DPB_CONF_CTRL) &
~(S5P_FIMV_DPB_FLUSH_MASK << S5P_FIMV_DPB_FLUSH_SHIFT);
mfc_write(dev, dpb, S5P_FIMV_SI_CH0_DPB_CONF_CTRL);
+
+ s5p_mfc_write_info_v5(ctx, ctx->frame_tag,
+ S5P_FIMV_SHARED_SET_FRAME_TAG);
}
/* Decode a single frame */
@@ -1682,6 +1685,11 @@ static unsigned int s5p_mfc_get_crop_info_v_v5(struct s5p_mfc_ctx *ctx)
return s5p_mfc_read_info_v5(ctx, CROP_INFO_V);
}
+unsigned int s5p_mfc_get_frame_tag(struct s5p_mfc_ctx *ctx)
+{
+ return s5p_mfc_read_info_v5(ctx, GET_FRAME_TAG_TOP);
+}
+
/* Initialize opr function pointers for MFC v5 */
static struct s5p_mfc_hw_ops s5p_mfc_ops_v5 = {
.alloc_dec_temp_buffers = s5p_mfc_alloc_dec_temp_buffers_v5,
@@ -1735,6 +1743,7 @@ static struct s5p_mfc_hw_ops s5p_mfc_ops_v5 = {
.get_pic_type_bot = s5p_mfc_get_pic_type_bot_v5,
.get_crop_info_h = s5p_mfc_get_crop_info_h_v5,
.get_crop_info_v = s5p_mfc_get_crop_info_v_v5,
+ .get_frame_tag = s5p_mfc_get_frame_tag,
};
struct s5p_mfc_hw_ops *s5p_mfc_init_hw_ops_v5(void)
diff --git a/drivers/media/v4l2-core/v4l2-ctrls.c b/drivers/media/v4l2-core/v4l2-ctrls.c
index fccd08b66d1a..1294b215c42c 100644
--- a/drivers/media/v4l2-core/v4l2-ctrls.c
+++ b/drivers/media/v4l2-core/v4l2-ctrls.c
@@ -699,6 +699,7 @@ const char *v4l2_ctrl_get_name(u32 id)
case V4L2_CID_MPEG_VIDEO_DEC_FRAME: return "Video Decoder Frame Count";
case V4L2_CID_MPEG_VIDEO_VBV_DELAY: return "Initial Delay for VBV Control";
case V4L2_CID_MPEG_VIDEO_REPEAT_SEQ_HEADER: return "Repeat Sequence Header";
+ case V4L2_CID_CODEC_FRAME_TAG: return "Video Decoder Frame Tag";
/* CAMERA controls */
/* Keep the order of the 'case's the same as in videodev2.h! */
@@ -973,6 +974,12 @@ void v4l2_ctrl_fill(u32 id, const char **name, enum v4l2_ctrl_type *type,
*flags |= V4L2_CTRL_FLAG_READ_ONLY;
*min = *max = *step = *def = 0;
break;
+ case V4L2_CID_CODEC_FRAME_TAG:
+ *type = V4L2_CTRL_TYPE_INTEGER;
+ *step = 1;
+ *min = 0;
+ *max = INT_MAX;
+ break;
default:
*type = V4L2_CTRL_TYPE_INTEGER;
break;
diff --git a/drivers/net/usb/asix_devices.c b/drivers/net/usb/asix_devices.c
index ad5d1e4384db..defda0e64bde 100644
--- a/drivers/net/usb/asix_devices.c
+++ b/drivers/net/usb/asix_devices.c
@@ -44,6 +44,35 @@ struct ax88172_int_data {
__le16 res3;
} __packed;
+static char asix_mac_addr[6];
+static int __init asix_setup_mac(char *macstr)
+{
+ int i, h, l;
+
+ if (!macstr)
+ return 0;
+
+ for (i = 0; i < 6; i++) {
+ if (i != 5 && *(macstr + 2) != ':')
+ return 0;
+
+ h = hex_to_bin(*macstr++);
+ if (h == -1)
+ return 0;
+
+ l = hex_to_bin(*macstr++);
+ if (l == -1)
+ return 0;
+
+ macstr++;
+ asix_mac_addr[i] = (h << 4) + l;
+ }
+
+ return 0;
+}
+
+__setup("mac=", asix_setup_mac);
+
static void asix_status(struct usbnet *dev, struct urb *urb)
{
struct ax88172_int_data *event;
@@ -62,6 +91,9 @@ static void asix_status(struct usbnet *dev, struct urb *urb)
static void asix_set_netdev_dev_addr(struct usbnet *dev, u8 *addr)
{
+ if (!is_valid_ether_addr(addr))
+ memcpy(addr, asix_mac_addr, ETH_ALEN);
+
if (is_valid_ether_addr(addr)) {
memcpy(dev->net->dev_addr, addr, ETH_ALEN);
} else {
diff --git a/drivers/tty/serial/samsung.c b/drivers/tty/serial/samsung.c
index 376079b9bd75..85d7d8c94905 100644
--- a/drivers/tty/serial/samsung.c
+++ b/drivers/tty/serial/samsung.c
@@ -528,6 +528,28 @@ static int s3c64xx_serial_startup(struct uart_port *port)
return ret;
}
+static void s3c64xx_serial_shutdown(struct uart_port *port)
+{
+ struct s3c24xx_uart_port *ourport = to_ourport(port);
+
+ if (ourport->tx_claimed) {
+ free_irq(port->irq, ourport);
+ tx_enabled(port) = 0;
+ ourport->tx_claimed = 0;
+ }
+
+ if (ourport->rx_claimed) {
+ ourport->rx_claimed = 0;
+ rx_enabled(port) = 0;
+ }
+
+ /* Clear pending interrupts and mask all interrupts */
+ if (s3c24xx_serial_has_interrupt_mask(port)) {
+ wr_regl(port, S3C64XX_UINTP, 0xf);
+ wr_regl(port, S3C64XX_UINTM, 0xf);
+ }
+}
+
/* power power management control */
static void s3c24xx_serial_pm(struct uart_port *port, unsigned int level,
@@ -1013,6 +1035,9 @@ static void s3c24xx_serial_resetport(struct uart_port *port,
wr_regl(port, S3C2410_UFCON, cfg->ufcon | S3C2410_UFCON_RESETBOTH);
wr_regl(port, S3C2410_UFCON, cfg->ufcon);
+ wr_regl(port, S3C64XX_UINTM, 0xf);
+ wr_regl(port, S3C64XX_UINTP, 0xf);
+
/* some delay is required after fifo reset */
udelay(1);
}
@@ -1125,8 +1150,10 @@ static int s3c24xx_serial_init_port(struct s3c24xx_uart_port *ourport,
port->dev = &platdev->dev;
/* Startup sequence is different for s3c64xx and higher SoC's */
- if (s3c24xx_serial_has_interrupt_mask(port))
+ if (s3c24xx_serial_has_interrupt_mask(port)) {
s3c24xx_serial_ops.startup = s3c64xx_serial_startup;
+ s3c24xx_serial_ops.shutdown = s3c64xx_serial_shutdown;
+ }
port->uartclk = 1;
diff --git a/firmware/edid-1920x1080.fw b/firmware/edid-1920x1080.fw
new file mode 100644
index 000000000000..e90256c4fd2c
--- /dev/null
+++ b/firmware/edid-1920x1080.fw
Binary files differ
diff --git a/include/linux/printk.h b/include/linux/printk.h
index 22c7052e9372..b62c76703532 100644
--- a/include/linux/printk.h
+++ b/include/linux/printk.h
@@ -8,6 +8,7 @@
extern const char linux_banner[];
extern const char linux_proc_banner[];
+extern const char linux_scm_version_banner[];
static inline int printk_get_level(const char *buffer)
{
diff --git a/include/linux/scatterlist.h b/include/linux/scatterlist.h
index adae88f5b0ab..ebf28027b53a 100644
--- a/include/linux/scatterlist.h
+++ b/include/linux/scatterlist.h
@@ -253,7 +253,7 @@ size_t sg_pcopy_to_buffer(struct scatterlist *sgl, unsigned int nents,
* Maximum number of entries that will be allocated in one piece, if
* a list larger than this is required then chaining will be utilized.
*/
-#define SG_MAX_SINGLE_ALLOC (PAGE_SIZE / sizeof(struct scatterlist))
+#define SG_MAX_SINGLE_ALLOC ((PAGE_SIZE<<4) / sizeof(struct scatterlist))
/*
* sg page iterator
diff --git a/include/uapi/linux/v4l2-controls.h b/include/uapi/linux/v4l2-controls.h
index e90a88a8708f..f81a7e9000e4 100644
--- a/include/uapi/linux/v4l2-controls.h
+++ b/include/uapi/linux/v4l2-controls.h
@@ -138,8 +138,10 @@ enum v4l2_colorfx {
#define V4L2_CID_ALPHA_COMPONENT (V4L2_CID_BASE+41)
#define V4L2_CID_COLORFX_CBCR (V4L2_CID_BASE+42)
+#define V4L2_CID_CODEC_FRAME_TAG (V4L2_CID_BASE+43)
+
/* last CID + 1 */
-#define V4L2_CID_LASTP1 (V4L2_CID_BASE+43)
+#define V4L2_CID_LASTP1 (V4L2_CID_BASE+44)
/* USER-class private control IDs */
diff --git a/init/main.c b/init/main.c
index d03d2ec2eacf..aa84693fa67b 100644
--- a/init/main.c
+++ b/init/main.c
@@ -499,6 +499,7 @@ asmlinkage void __init start_kernel(void)
boot_cpu_init();
page_address_init();
pr_notice("%s", linux_banner);
+ pr_notice("%s", linux_scm_version_banner);
setup_arch(&command_line);
mm_init_owner(&init_mm, &init_task);
mm_init_cpumask(&init_mm);
diff --git a/init/version.c b/init/version.c
index 1a4718e500fe..3978f0298c98 100644
--- a/init/version.c
+++ b/init/version.c
@@ -48,3 +48,6 @@ const char linux_proc_banner[] =
"%s version %s"
" (" LINUX_COMPILE_BY "@" LINUX_COMPILE_HOST ")"
" (" LINUX_COMPILER ") %s\n";
+
+const char linux_scm_version_banner [] =
+ "Kernel was built at commit id '" KERNEL_GIT_ID "'\n";
diff --git a/linaro/configs/arndale.conf b/linaro/configs/arndale.conf
index f4b022498b15..ee23bccb2f3d 100644
--- a/linaro/configs/arndale.conf
+++ b/linaro/configs/arndale.conf
@@ -18,11 +18,13 @@ CONFIG_CPU_FREQ_GOV_USERSPACE=y
CONFIG_VFP=y
CONFIG_NEON=y
CONFIG_PM_RUNTIME=y
+CONFIG_EXTRA_FIRMWARE="edid-1920x1080.fw"
CONFIG_BLK_DEV_LOOP=y
CONFIG_BLK_DEV_SD=y
CONFIG_CHR_DEV_SG=y
CONFIG_ATA=y
CONFIG_SATA_AHCI_PLATFORM=y
+CONFIG_SATA_EXYNOS=y
CONFIG_AX88796=y
CONFIG_AX88796_93CX6=y
CONFIG_USB_USBNET=y
@@ -44,6 +46,13 @@ CONFIG_MFD_SEC_CORE=y
CONFIG_REGULATOR=y
CONFIG_REGULATOR_FIXED_VOLTAGE=y
CONFIG_REGULATOR_S5M8767=y
+CONFIG_DRM=y
+CONFIG_DRM_LOAD_EDID_FIRMWARE=y
+CONFIG_DRM_EXYNOS=y
+CONFIG_DRM_EXYNOS_DMABUF=y
+CONFIG_DRM_EXYNOS_HDMI=y
+CONFIG_FRAMEBUFFER_CONSOLE=y
+CONFIG_LOGO=y
CONFIG_USB=y
CONFIG_USB_ANNOUNCE_NEW_DEVICES=y
CONFIG_USB_DWC3=y
@@ -65,6 +74,8 @@ CONFIG_MMC_UNSAFE_RESUME=y
CONFIG_MMC_DW=y
CONFIG_MMC_DW_IDMAC=y
CONFIG_MMC_DW_EXYNOS=y
+CONFIG_RTC_CLASS=y
+CONFIG_RTC_DRV_S3C=y
CONFIG_DEBUG_KERNEL=y
CONFIG_DETECT_HUNG_TASK=y
CONFIG_DEBUG_RT_MUTEXES=y