Merge changes Ib6aa000e,I81885d33 into msm-3.0
* changes:
usb: msm72k_udc: Delete prime timer after active status bit clear
usb: msm7k_udc: Add delay upon request dequeue failure
diff --git a/arch/arm/boot/dts/msmcopper.dts b/arch/arm/boot/dts/msmcopper.dts
index e72f4dc..6561c71 100644
--- a/arch/arm/boot/dts/msmcopper.dts
+++ b/arch/arm/boot/dts/msmcopper.dts
@@ -15,15 +15,20 @@
<0xF9002000 0x1000>;
};
- serial@F9684000 {
+ timer {
+ compatible = "qcom,msm-qtimer";
+ interrupts = <18>;
+ };
+
+ serial@F991F000 {
compatible = "qcom,msm-lsuart-v14";
- reg = <0xF9684000 0x1000>;
+ reg = <0xF991F000 0x1000>;
interrupts = <109>;
};
- usb@F9690000 {
+ usb@F9A55000 {
compatible = "qcom,hsusb-otg";
- reg = <0xF9690000 0x400>;
+ reg = <0xF9A55000 0x400>;
interrupts = <134>;
qcom,hsusb-otg-phy-type = <2>;
@@ -31,10 +36,10 @@
qcom,hsusb-otg-otg-control = <1>;
};
- qcom,sdcc@F9600000 {
+ qcom,sdcc@F980B000 {
cell-index = <1>;
compatible = "qcom,msm-sdcc";
- reg = <0xF9600000 0x1000>;
+ reg = <0xF980B000 0x1000>;
interrupts = <123>;
qcom,sdcc-clk-rates = <400000 24000000 48000000>;
@@ -44,10 +49,10 @@
qcom,sdcc-disable_cmd23;
};
- qcom,sdcc@F9620000 {
+ qcom,sdcc@F984B000 {
cell-index = <3>;
compatible = "qcom,msm-sdcc";
- reg = <0xF9620000 0x1000>;
+ reg = <0xF984B000 0x1000>;
interrupts = <127>;
qcom,sdcc-clk-rates = <400000 24000000 48000000>;
@@ -55,4 +60,14 @@
qcom,sdcc-bus-width = <4>;
qcom,sdcc-disable_cmd23;
};
+
+ qcom,sps@F9980000 {
+ compatible = "qcom,msm_sps";
+ reg = <0xF9984000 0x15000>,
+ <0xF9999000 0xB000>;
+ interrupts = <94>;
+
+ qcom,bam-dma-res-pipes = <6>;
+ };
+
};
diff --git a/arch/arm/common/Makefile b/arch/arm/common/Makefile
index 3ab5d76..6f25cf2 100644
--- a/arch/arm/common/Makefile
+++ b/arch/arm/common/Makefile
@@ -19,3 +19,4 @@
obj-$(CONFIG_ARM_TIMER_SP804) += timer-sp.o
obj-$(CONFIG_FIQ_GLUE) += fiq_glue.o fiq_glue_setup.o
obj-$(CONFIG_FIQ_DEBUGGER) += fiq_debugger.o
+obj-$(CONFIG_CP_ACCESS) += cpaccess.o
diff --git a/arch/arm/common/cpaccess.c b/arch/arm/common/cpaccess.c
index d3d0537..e71e318 100644
--- a/arch/arm/common/cpaccess.c
+++ b/arch/arm/common/cpaccess.c
@@ -29,6 +29,7 @@
#include <linux/smp.h>
#include <asm/cacheflush.h>
#include <asm/smp_plat.h>
+#include <asm/mmu_writeable.h>
#ifdef CONFIG_ARCH_MSM_KRAIT
#include <mach/msm-krait-l2-accessors.h>
@@ -191,16 +192,11 @@
(per_cpu(cp_param.cp, cpu) << 8);
/*
- * Grab address of the Dummy function, insert MRC/MCR
- * instruction and a return instruction ("bx lr"). Do
- * a D cache clean and I cache invalidate after inserting
- * new code.
+ * Grab address of the Dummy function, write the MRC/MCR
+ * instruction, ensuring cache coherency.
*/
p_opcode = (unsigned long *)&cpaccess_dummy;
- *p_opcode++ = opcode;
- *p_opcode-- = 0xE12FFF1E;
- __cpuc_coherent_kern_range((unsigned long)p_opcode,
- ((unsigned long)p_opcode + (sizeof(long) * 2)));
+ mem_text_write_kernel_word(p_opcode, opcode);
#ifdef CONFIG_SMP
/*
diff --git a/arch/arm/common/gic.c b/arch/arm/common/gic.c
index 2b7b749..7fcf9dc 100644
--- a/arch/arm/common/gic.c
+++ b/arch/arm/common/gic.c
@@ -35,7 +35,7 @@
#include <asm/hardware/gic.h>
#include <asm/system.h>
-static DEFINE_SPINLOCK(irq_controller_lock);
+static DEFINE_RAW_SPINLOCK(irq_controller_lock);
/* Address of GIC 0 CPU interface */
void __iomem *gic_cpu_base_addr __read_mostly;
@@ -85,23 +85,22 @@
{
u32 mask = 1 << (d->irq % 32);
- spin_lock(&irq_controller_lock);
+ raw_spin_lock(&irq_controller_lock);
writel_relaxed(mask, gic_dist_base(d) + GIC_DIST_ENABLE_CLEAR + (gic_irq(d) / 32) * 4);
if (gic_arch_extn.irq_mask)
gic_arch_extn.irq_mask(d);
- spin_unlock(&irq_controller_lock);
-
+ raw_spin_unlock(&irq_controller_lock);
}
static void gic_unmask_irq(struct irq_data *d)
{
u32 mask = 1 << (d->irq % 32);
- spin_lock(&irq_controller_lock);
+ raw_spin_lock(&irq_controller_lock);
if (gic_arch_extn.irq_unmask)
gic_arch_extn.irq_unmask(d);
writel_relaxed(mask, gic_dist_base(d) + GIC_DIST_ENABLE_SET + (gic_irq(d) / 32) * 4);
- spin_unlock(&irq_controller_lock);
+ raw_spin_unlock(&irq_controller_lock);
}
static void gic_disable_irq(struct irq_data *d)
@@ -149,13 +148,13 @@
if (!msm_show_resume_irq_mask)
return;
- spin_lock(&irq_controller_lock);
+ raw_spin_lock(&irq_controller_lock);
for (i = 0; i * 32 < gic->max_irq; i++) {
enabled = readl_relaxed(base + GIC_DIST_ENABLE_CLEAR + i * 4);
pending[i] = readl_relaxed(base + GIC_DIST_PENDING_SET + i * 4);
pending[i] &= enabled;
}
- spin_unlock(&irq_controller_lock);
+ raw_spin_unlock(&irq_controller_lock);
for (i = find_first_bit(pending, gic->max_irq);
i < gic->max_irq;
@@ -205,9 +204,9 @@
static void gic_eoi_irq(struct irq_data *d)
{
if (gic_arch_extn.irq_eoi) {
- spin_lock(&irq_controller_lock);
+ raw_spin_lock(&irq_controller_lock);
gic_arch_extn.irq_eoi(d);
- spin_unlock(&irq_controller_lock);
+ raw_spin_unlock(&irq_controller_lock);
}
writel_relaxed(gic_irq(d), gic_cpu_base(d) + GIC_CPU_EOI);
@@ -231,7 +230,7 @@
if (type != IRQ_TYPE_LEVEL_HIGH && type != IRQ_TYPE_EDGE_RISING)
return -EINVAL;
- spin_lock(&irq_controller_lock);
+ raw_spin_lock(&irq_controller_lock);
if (gic_arch_extn.irq_set_type)
gic_arch_extn.irq_set_type(d, type);
@@ -256,7 +255,7 @@
if (enabled)
writel_relaxed(enablemask, base + GIC_DIST_ENABLE_SET + enableoff);
- spin_unlock(&irq_controller_lock);
+ raw_spin_unlock(&irq_controller_lock);
return 0;
}
@@ -276,22 +275,21 @@
{
void __iomem *reg = gic_dist_base(d) + GIC_DIST_TARGET + (gic_irq(d) & ~3);
unsigned int shift = (d->irq % 4) * 8;
- unsigned int cpu = cpumask_first(mask_val);
+ unsigned int cpu = cpumask_any_and(mask_val, cpu_online_mask);
u32 val, mask, bit;
- if (cpu >= 8)
+ if (cpu >= 8 || cpu >= nr_cpu_ids)
return -EINVAL;
mask = 0xff << shift;
bit = 1 << (cpu + shift);
- spin_lock(&irq_controller_lock);
- d->node = cpu;
+ raw_spin_lock(&irq_controller_lock);
val = readl_relaxed(reg) & ~mask;
writel_relaxed(val | bit, reg);
- spin_unlock(&irq_controller_lock);
+ raw_spin_unlock(&irq_controller_lock);
- return 0;
+ return IRQ_SET_MASK_OK;
}
#endif
@@ -336,9 +334,9 @@
chained_irq_enter(chip, desc);
- spin_lock(&irq_controller_lock);
+ raw_spin_lock(&irq_controller_lock);
status = readl_relaxed(chip_data->cpu_base + GIC_CPU_INTACK);
- spin_unlock(&irq_controller_lock);
+ raw_spin_unlock(&irq_controller_lock);
gic_irq = (status & 0x3ff);
if (gic_irq == 1023)
@@ -531,7 +529,7 @@
u32 mask, val;
WARN_ON(!irqs_disabled());
- spin_lock(&irq_controller_lock);
+ raw_spin_lock(&irq_controller_lock);
mask = 1 << (gic_irq(d) % 32);
val = readl(gic_dist_base(d) +
GIC_DIST_ENABLE_SET + (gic_irq(d) / 32) * 4);
@@ -539,7 +537,7 @@
WARN_ON(val & mask);
val = readl(gic_dist_base(d) +
GIC_DIST_PENDING_SET + (gic_irq(d) / 32) * 4);
- spin_unlock(&irq_controller_lock);
+ raw_spin_unlock(&irq_controller_lock);
return (bool) (val & mask);
}
@@ -552,7 +550,7 @@
u32 mask, val;
WARN_ON(!irqs_disabled());
- spin_lock(&irq_controller_lock);
+ raw_spin_lock(&irq_controller_lock);
mask = 1 << (gic_irq(d) % 32);
val = readl(gic_dist_base(d) +
GIC_DIST_ENABLE_SET + (gic_irq(d) / 32) * 4);
@@ -560,5 +558,5 @@
WARN_ON(val & mask);
writel(mask, gic_dist_base(d) +
GIC_DIST_PENDING_CLEAR + (gic_irq(d) / 32) * 4);
- spin_unlock(&irq_controller_lock);
+ raw_spin_unlock(&irq_controller_lock);
}
diff --git a/arch/arm/configs/msm-copper_defconfig b/arch/arm/configs/msm-copper_defconfig
index f617aff..4d4c27f 100644
--- a/arch/arm/configs/msm-copper_defconfig
+++ b/arch/arm/configs/msm-copper_defconfig
@@ -44,6 +44,7 @@
CONFIG_HIGH_RES_TIMERS=y
CONFIG_SMP=y
# CONFIG_SMP_ON_UP is not set
+CONFIG_ARM_ARCH_TIMER=y
CONFIG_PREEMPT=y
CONFIG_AEABI=y
CONFIG_HIGHMEM=y
@@ -121,6 +122,9 @@
CONFIG_ANDROID_TIMED_GPIO=y
CONFIG_ANDROID_LOW_MEMORY_KILLER=y
CONFIG_MSM_SSBI=y
+CONFIG_SPS=y
+CONFIG_SPS_SUPPORT_BAMDMA=y
+CONFIG_SPS_SUPPORT_NDP_BAM=y
CONFIG_EXT2_FS=y
CONFIG_EXT2_FS_XATTR=y
CONFIG_EXT3_FS=y
diff --git a/arch/arm/configs/msm7627-perf_defconfig b/arch/arm/configs/msm7627-perf_defconfig
index 78eeadd..0f2ffc1 100644
--- a/arch/arm/configs/msm7627-perf_defconfig
+++ b/arch/arm/configs/msm7627-perf_defconfig
@@ -255,6 +255,7 @@
CONFIG_MMC=y
CONFIG_MMC_PERF_PROFILING=y
CONFIG_MMC_UNSAFE_RESUME=y
+CONFIG_MMC_CLKGATE=y
CONFIG_MMC_PARANOID_SD_INIT=y
CONFIG_MMC_BLOCK_MINORS=32
# CONFIG_MMC_BLOCK_BOUNCE is not set
diff --git a/arch/arm/configs/msm7627_defconfig b/arch/arm/configs/msm7627_defconfig
index 4aabe08..d1d0e66 100644
--- a/arch/arm/configs/msm7627_defconfig
+++ b/arch/arm/configs/msm7627_defconfig
@@ -253,6 +253,7 @@
CONFIG_MMC=y
CONFIG_MMC_PERF_PROFILING=y
CONFIG_MMC_UNSAFE_RESUME=y
+CONFIG_MMC_CLKGATE=y
CONFIG_MMC_PARANOID_SD_INIT=y
CONFIG_MMC_BLOCK_MINORS=32
# CONFIG_MMC_BLOCK_BOUNCE is not set
@@ -291,16 +292,13 @@
CONFIG_LOCKUP_DETECTOR=y
CONFIG_DETECT_HUNG_TASK=y
CONFIG_TIMER_STATS=y
-CONFIG_SLUB_DEBUG_ON=y
-CONFIG_DEBUG_MUTEXES=y
-CONFIG_DEBUG_SPINLOCK_SLEEP=y
-CONFIG_DEBUG_STACK_USAGE=y
CONFIG_DEBUG_SPINLOCK=y
CONFIG_DEBUG_MUTEXES=y
CONFIG_DEBUG_SPINLOCK_SLEEP=y
+CONFIG_DEBUG_STACK_USAGE=y
CONFIG_DEBUG_INFO=y
-CONFIG_LATENCYTOP=y
CONFIG_DEBUG_LIST=y
+CONFIG_LATENCYTOP=y
CONFIG_DEBUG_PAGEALLOC=y
CONFIG_DYNAMIC_DEBUG=y
CONFIG_DEBUG_USER=y
diff --git a/arch/arm/configs/msm7627a-perf_defconfig b/arch/arm/configs/msm7627a-perf_defconfig
index f81cc3d..342aad6 100644
--- a/arch/arm/configs/msm7627a-perf_defconfig
+++ b/arch/arm/configs/msm7627a-perf_defconfig
@@ -104,6 +104,7 @@
CONFIG_NF_CONNTRACK_SIP=y
CONFIG_NF_CONNTRACK_TFTP=y
CONFIG_NF_CT_NETLINK=y
+CONFIG_NETFILTER_TPROXY=y
CONFIG_NETFILTER_XT_TARGET_CLASSIFY=y
CONFIG_NETFILTER_XT_TARGET_CONNMARK=y
CONFIG_NETFILTER_XT_TARGET_MARK=y
@@ -119,10 +120,11 @@
CONFIG_NETFILTER_XT_MATCH_LIMIT=y
CONFIG_NETFILTER_XT_MATCH_MAC=y
CONFIG_NETFILTER_XT_MATCH_MARK=y
-CONFIG_NETFILTER_XT_MATCH_OWNER=y
CONFIG_NETFILTER_XT_MATCH_POLICY=y
CONFIG_NETFILTER_XT_MATCH_PKTTYPE=y
+CONFIG_NETFILTER_XT_MATCH_QTAGUID=y
CONFIG_NETFILTER_XT_MATCH_QUOTA=y
+CONFIG_NETFILTER_XT_MATCH_SOCKET=y
CONFIG_NETFILTER_XT_MATCH_STATE=y
CONFIG_NETFILTER_XT_MATCH_STATISTIC=y
CONFIG_NETFILTER_XT_MATCH_STRING=y
@@ -140,9 +142,11 @@
CONFIG_IP_NF_TARGET_MASQUERADE=y
CONFIG_IP_NF_TARGET_NETMAP=y
CONFIG_IP_NF_TARGET_REDIRECT=y
+CONFIG_IP_NF_MANGLE=y
CONFIG_IP_NF_ARPTABLES=y
CONFIG_IP_NF_ARPFILTER=y
CONFIG_IP_NF_ARP_MANGLE=y
+CONFIG_IP6_NF_IPTABLES=y
CONFIG_BT=y
CONFIG_BT_L2CAP=y
CONFIG_BT_SCO=y
@@ -160,6 +164,8 @@
CONFIG_CFG80211=y
# CONFIG_CFG80211_WEXT is not set
CONFIG_RFKILL=y
+CONFIG_GENLOCK=y
+CONFIG_GENLOCK_MISCDEVICE=y
CONFIG_MTD=y
CONFIG_MTD_TESTS=m
CONFIG_MTD_CMDLINE_PARTS=y
@@ -230,8 +236,6 @@
CONFIG_MSM_CAMERA_FLASH_SC628A=y
CONFIG_IMX072=y
CONFIG_RADIO_TAVARUA=y
-CONFIG_GENLOCK=y
-CONFIG_GENLOCK_MISCDEVICE=y
CONFIG_MSM_KGSL=y
CONFIG_FB=y
CONFIG_FB_MSM=y
@@ -314,9 +318,6 @@
CONFIG_DEBUG_SHIRQ=y
# CONFIG_SCHED_DEBUG is not set
CONFIG_TIMER_STATS=y
-CONFIG_DEBUG_SPINLOCK=y
-CONFIG_DEBUG_MUTEXES=y
-CONFIG_DEBUG_SPINLOCK_SLEEP=y
CONFIG_DEBUG_STACK_USAGE=y
CONFIG_DEBUG_INFO=y
# CONFIG_FTRACE is not set
diff --git a/arch/arm/configs/msm7627a_defconfig b/arch/arm/configs/msm7627a_defconfig
index 4836af0..c524759 100644
--- a/arch/arm/configs/msm7627a_defconfig
+++ b/arch/arm/configs/msm7627a_defconfig
@@ -102,6 +102,7 @@
CONFIG_NF_CONNTRACK_SIP=y
CONFIG_NF_CONNTRACK_TFTP=y
CONFIG_NF_CT_NETLINK=y
+CONFIG_NETFILTER_TPROXY=y
CONFIG_NETFILTER_XT_TARGET_CLASSIFY=y
CONFIG_NETFILTER_XT_TARGET_CONNMARK=y
CONFIG_NETFILTER_XT_TARGET_MARK=y
@@ -117,10 +118,11 @@
CONFIG_NETFILTER_XT_MATCH_LIMIT=y
CONFIG_NETFILTER_XT_MATCH_MAC=y
CONFIG_NETFILTER_XT_MATCH_MARK=y
-CONFIG_NETFILTER_XT_MATCH_OWNER=y
CONFIG_NETFILTER_XT_MATCH_POLICY=y
CONFIG_NETFILTER_XT_MATCH_PKTTYPE=y
+CONFIG_NETFILTER_XT_MATCH_QTAGUID=y
CONFIG_NETFILTER_XT_MATCH_QUOTA=y
+CONFIG_NETFILTER_XT_MATCH_SOCKET=y
CONFIG_NETFILTER_XT_MATCH_STATE=y
CONFIG_NETFILTER_XT_MATCH_STATISTIC=y
CONFIG_NETFILTER_XT_MATCH_STRING=y
@@ -138,9 +140,11 @@
CONFIG_IP_NF_TARGET_MASQUERADE=y
CONFIG_IP_NF_TARGET_NETMAP=y
CONFIG_IP_NF_TARGET_REDIRECT=y
+CONFIG_IP_NF_MANGLE=y
CONFIG_IP_NF_ARPTABLES=y
CONFIG_IP_NF_ARPFILTER=y
CONFIG_IP_NF_ARP_MANGLE=y
+CONFIG_IP6_NF_IPTABLES=y
CONFIG_BT=y
CONFIG_BT_L2CAP=y
CONFIG_BT_SCO=y
@@ -158,6 +162,8 @@
CONFIG_CFG80211=y
# CONFIG_CFG80211_WEXT is not set
CONFIG_RFKILL=y
+CONFIG_GENLOCK=y
+CONFIG_GENLOCK_MISCDEVICE=y
CONFIG_MTD=y
CONFIG_MTD_TESTS=m
CONFIG_MTD_CMDLINE_PARTS=y
@@ -228,8 +234,6 @@
CONFIG_MSM_CAMERA_FLASH_SC628A=y
CONFIG_IMX072=y
CONFIG_RADIO_TAVARUA=y
-CONFIG_GENLOCK=y
-CONFIG_GENLOCK_MISCDEVICE=y
CONFIG_MSM_KGSL=y
CONFIG_FB=y
CONFIG_FB_MSM=y
@@ -306,20 +310,17 @@
CONFIG_MAGIC_SYSRQ=y
CONFIG_DEBUG_FS=y
CONFIG_DEBUG_KERNEL=y
-CONFIG_LOCKUP_DETECTOR=y
CONFIG_DEBUG_SHIRQ=y
+CONFIG_LOCKUP_DETECTOR=y
CONFIG_DETECT_HUNG_TASK=y
CONFIG_TIMER_STATS=y
-CONFIG_SLUB_DEBUG_ON=y
CONFIG_DEBUG_SPINLOCK=y
CONFIG_DEBUG_MUTEXES=y
CONFIG_DEBUG_SPINLOCK_SLEEP=y
CONFIG_DEBUG_STACK_USAGE=y
CONFIG_DEBUG_INFO=y
-CONFIG_LATENCYTOP=y
-CONFIG_DEBUG_MUTEXES=y
-CONFIG_DEBUG_SPINLOCK_SLEEP=y
CONFIG_DEBUG_LIST=y
+CONFIG_LATENCYTOP=y
CONFIG_DEBUG_PAGEALLOC=y
# CONFIG_FTRACE is not set
CONFIG_DYNAMIC_DEBUG=y
diff --git a/arch/arm/configs/msm7630-perf_defconfig b/arch/arm/configs/msm7630-perf_defconfig
index 3791d0e..e5fec35 100644
--- a/arch/arm/configs/msm7630-perf_defconfig
+++ b/arch/arm/configs/msm7630-perf_defconfig
@@ -99,6 +99,7 @@
CONFIG_NF_CONNTRACK_SIP=y
CONFIG_NF_CONNTRACK_TFTP=y
CONFIG_NF_CT_NETLINK=y
+CONFIG_NETFILTER_TPROXY=y
CONFIG_NETFILTER_XT_TARGET_CLASSIFY=y
CONFIG_NETFILTER_XT_TARGET_CONNMARK=y
CONFIG_NETFILTER_XT_TARGET_MARK=y
@@ -115,10 +116,11 @@
CONFIG_NETFILTER_XT_MATCH_MAC=y
CONFIG_NETFILTER_XT_MATCH_MARK=y
CONFIG_NETFILTER_XT_MATCH_MULTIPORT=y
-CONFIG_NETFILTER_XT_MATCH_OWNER=y
CONFIG_NETFILTER_XT_MATCH_POLICY=y
CONFIG_NETFILTER_XT_MATCH_PKTTYPE=y
+CONFIG_NETFILTER_XT_MATCH_QTAGUID=y
CONFIG_NETFILTER_XT_MATCH_QUOTA=y
+CONFIG_NETFILTER_XT_MATCH_SOCKET=y
CONFIG_NETFILTER_XT_MATCH_STATE=y
CONFIG_NETFILTER_XT_MATCH_STATISTIC=y
CONFIG_NETFILTER_XT_MATCH_STRING=y
@@ -176,6 +178,8 @@
# CONFIG_CFG80211_WEXT is not set
# CONFIG_WIRELESS_EXT_SYSFS is not set
CONFIG_RFKILL=y
+CONFIG_GENLOCK=y
+CONFIG_GENLOCK_MISCDEVICE=y
CONFIG_MTD=y
CONFIG_MTD_TESTS=m
CONFIG_MTD_CMDLINE_PARTS=y
@@ -262,8 +266,6 @@
CONFIG_MT9E013=y
CONFIG_MSM_GEMINI=y
CONFIG_RADIO_TAVARUA=y
-CONFIG_GENLOCK=y
-CONFIG_GENLOCK_MISCDEVICE=y
CONFIG_MSM_KGSL=y
CONFIG_VIDEO_OUTPUT_CONTROL=y
CONFIG_FB=y
@@ -321,6 +323,7 @@
CONFIG_MMC=y
CONFIG_MMC_PERF_PROFILING=y
CONFIG_MMC_UNSAFE_RESUME=y
+CONFIG_MMC_CLKGATE=y
CONFIG_MMC_PARANOID_SD_INIT=y
CONFIG_MMC_BLOCK_MINORS=32
# CONFIG_MMC_BLOCK_BOUNCE is not set
diff --git a/arch/arm/configs/msm7630_defconfig b/arch/arm/configs/msm7630_defconfig
index bd60092..6e3290b 100644
--- a/arch/arm/configs/msm7630_defconfig
+++ b/arch/arm/configs/msm7630_defconfig
@@ -98,6 +98,7 @@
CONFIG_NF_CONNTRACK_SIP=y
CONFIG_NF_CONNTRACK_TFTP=y
CONFIG_NF_CT_NETLINK=y
+CONFIG_NETFILTER_TPROXY=y
CONFIG_NETFILTER_XT_TARGET_CLASSIFY=y
CONFIG_NETFILTER_XT_TARGET_CONNMARK=y
CONFIG_NETFILTER_XT_TARGET_MARK=y
@@ -114,10 +115,11 @@
CONFIG_NETFILTER_XT_MATCH_MAC=y
CONFIG_NETFILTER_XT_MATCH_MARK=y
CONFIG_NETFILTER_XT_MATCH_MULTIPORT=y
-CONFIG_NETFILTER_XT_MATCH_OWNER=y
CONFIG_NETFILTER_XT_MATCH_POLICY=y
CONFIG_NETFILTER_XT_MATCH_PKTTYPE=y
+CONFIG_NETFILTER_XT_MATCH_QTAGUID=y
CONFIG_NETFILTER_XT_MATCH_QUOTA=y
+CONFIG_NETFILTER_XT_MATCH_SOCKET=y
CONFIG_NETFILTER_XT_MATCH_STATE=y
CONFIG_NETFILTER_XT_MATCH_STATISTIC=y
CONFIG_NETFILTER_XT_MATCH_STRING=y
@@ -175,6 +177,8 @@
# CONFIG_CFG80211_WEXT is not set
# CONFIG_WIRELESS_EXT_SYSFS is not set
CONFIG_RFKILL=y
+CONFIG_GENLOCK=y
+CONFIG_GENLOCK_MISCDEVICE=y
CONFIG_MTD=y
CONFIG_MTD_TESTS=m
CONFIG_MTD_CMDLINE_PARTS=y
@@ -253,8 +257,6 @@
# CONFIG_MFD_PM8XXX_DEBUG is not set
# CONFIG_MFD_PM8XXX_PWM is not set
# CONFIG_MFD_PM8XXX_MISC is not set
-CONFIG_GENLOCK=y
-CONFIG_GENLOCK_MISCDEVICE=y
CONFIG_MSM_KGSL=y
CONFIG_VIDEO_OUTPUT_CONTROL=y
CONFIG_FB=y
@@ -307,6 +309,7 @@
CONFIG_MMC=y
CONFIG_MMC_PERF_PROFILING=y
CONFIG_MMC_UNSAFE_RESUME=y
+CONFIG_MMC_CLKGATE=y
CONFIG_MMC_PARANOID_SD_INIT=y
CONFIG_MMC_BLOCK_MINORS=32
# CONFIG_MMC_BLOCK_BOUNCE is not set
@@ -352,10 +355,7 @@
CONFIG_DETECT_HUNG_TASK=y
CONFIG_SCHEDSTATS=y
CONFIG_TIMER_STATS=y
-CONFIG_SLUB_DEBUG_ON=y
# CONFIG_DEBUG_PREEMPT is not set
-CONFIG_DEBUG_SPINLOCK=y
-CONFIG_DEBUG_MUTEXES=y
CONFIG_PROVE_LOCKING=y
CONFIG_DEBUG_SPINLOCK_SLEEP=y
CONFIG_DEBUG_STACK_USAGE=y
diff --git a/arch/arm/configs/msm8660-perf_defconfig b/arch/arm/configs/msm8660-perf_defconfig
index ca64436..01150aa 100644
--- a/arch/arm/configs/msm8660-perf_defconfig
+++ b/arch/arm/configs/msm8660-perf_defconfig
@@ -133,6 +133,7 @@
CONFIG_NF_CONNTRACK_SIP=y
CONFIG_NF_CONNTRACK_TFTP=y
CONFIG_NF_CT_NETLINK=y
+CONFIG_NETFILTER_TPROXY=y
CONFIG_NETFILTER_XT_TARGET_CLASSIFY=y
CONFIG_NETFILTER_XT_TARGET_CONNMARK=y
CONFIG_NETFILTER_XT_TARGET_MARK=y
@@ -150,10 +151,11 @@
CONFIG_NETFILTER_XT_MATCH_MAC=y
CONFIG_NETFILTER_XT_MATCH_MARK=y
CONFIG_NETFILTER_XT_MATCH_MULTIPORT=y
-CONFIG_NETFILTER_XT_MATCH_OWNER=y
CONFIG_NETFILTER_XT_MATCH_POLICY=y
CONFIG_NETFILTER_XT_MATCH_PKTTYPE=y
+CONFIG_NETFILTER_XT_MATCH_QTAGUID=y
CONFIG_NETFILTER_XT_MATCH_QUOTA=y
+CONFIG_NETFILTER_XT_MATCH_SOCKET=y
CONFIG_NETFILTER_XT_MATCH_STATE=y
CONFIG_NETFILTER_XT_MATCH_STATISTIC=y
CONFIG_NETFILTER_XT_MATCH_STRING=y
@@ -216,6 +218,8 @@
# CONFIG_CFG80211_WEXT is not set
# CONFIG_WIRELESS_EXT_SYSFS is not set
CONFIG_RFKILL=y
+CONFIG_GENLOCK=y
+CONFIG_GENLOCK_MISCDEVICE=y
CONFIG_BLK_DEV_LOOP=y
CONFIG_BLK_DEV_RAM=y
CONFIG_MISC_DEVICES=y
@@ -320,8 +324,6 @@
CONFIG_RADIO_TAVARUA=y
CONFIG_ION=y
CONFIG_ION_MSM=y
-CONFIG_GENLOCK=y
-CONFIG_GENLOCK_MISCDEVICE=y
CONFIG_MSM_KGSL=y
CONFIG_KGSL_PER_PROCESS_PAGE_TABLE=y
CONFIG_VIDEO_OUTPUT_CONTROL=y
@@ -331,7 +333,6 @@
CONFIG_FB_MSM_TRIPLE_BUFFER=y
CONFIG_FB_MSM_MDP40=y
CONFIG_FB_MSM_OVERLAY=y
-CONFIG_FB_MSM_OVERLAY_WRITEBACK=y
CONFIG_FB_MSM_LCDC_MIPI_PANEL_AUTO_DETECT=y
CONFIG_FB_MSM_HDMI_MSM_PANEL=y
CONFIG_BACKLIGHT_LCD_SUPPORT=y
@@ -371,6 +372,7 @@
CONFIG_MMC=y
CONFIG_MMC_PERF_PROFILING=y
CONFIG_MMC_UNSAFE_RESUME=y
+CONFIG_MMC_CLKGATE=y
CONFIG_MMC_EMBEDDED_SDIO=y
CONFIG_MMC_PARANOID_SD_INIT=y
CONFIG_MMC_BLOCK_MINORS=32
diff --git a/arch/arm/configs/msm8660_defconfig b/arch/arm/configs/msm8660_defconfig
index f78ed74..7b2fede 100644
--- a/arch/arm/configs/msm8660_defconfig
+++ b/arch/arm/configs/msm8660_defconfig
@@ -123,6 +123,7 @@
CONFIG_NF_CONNTRACK_SIP=y
CONFIG_NF_CONNTRACK_TFTP=y
CONFIG_NF_CT_NETLINK=y
+CONFIG_NETFILTER_TPROXY=y
CONFIG_NETFILTER_XT_TARGET_CLASSIFY=y
CONFIG_NETFILTER_XT_TARGET_CONNMARK=y
CONFIG_NETFILTER_XT_TARGET_MARK=y
@@ -140,10 +141,11 @@
CONFIG_NETFILTER_XT_MATCH_MAC=y
CONFIG_NETFILTER_XT_MATCH_MARK=y
CONFIG_NETFILTER_XT_MATCH_MULTIPORT=y
-CONFIG_NETFILTER_XT_MATCH_OWNER=y
CONFIG_NETFILTER_XT_MATCH_POLICY=y
CONFIG_NETFILTER_XT_MATCH_PKTTYPE=y
+CONFIG_NETFILTER_XT_MATCH_QTAGUID=y
CONFIG_NETFILTER_XT_MATCH_QUOTA=y
+CONFIG_NETFILTER_XT_MATCH_SOCKET=y
CONFIG_NETFILTER_XT_MATCH_STATE=y
CONFIG_NETFILTER_XT_MATCH_STATISTIC=y
CONFIG_NETFILTER_XT_MATCH_STRING=y
@@ -206,10 +208,11 @@
# CONFIG_CFG80211_WEXT is not set
# CONFIG_WIRELESS_EXT_SYSFS is not set
CONFIG_RFKILL=y
+CONFIG_GENLOCK=y
+CONFIG_GENLOCK_MISCDEVICE=y
CONFIG_BLK_DEV_LOOP=y
CONFIG_BLK_DEV_RAM=y
CONFIG_MISC_DEVICES=y
-CONFIG_KERNEL_DEBUGGER_CORE=y
CONFIG_UID_STAT=y
CONFIG_TSIF=m
CONFIG_TSIF_CHRDEV=m
@@ -308,8 +311,6 @@
CONFIG_MT9E013=y
CONFIG_MSM_GEMINI=y
CONFIG_RADIO_TAVARUA=y
-CONFIG_GENLOCK=y
-CONFIG_GENLOCK_MISCDEVICE=y
CONFIG_MSM_KGSL=y
CONFIG_KGSL_PER_PROCESS_PAGE_TABLE=y
CONFIG_VIDEO_OUTPUT_CONTROL=y
@@ -319,7 +320,6 @@
CONFIG_FB_MSM_TRIPLE_BUFFER=y
CONFIG_FB_MSM_MDP40=y
CONFIG_FB_MSM_OVERLAY=y
-CONFIG_FB_MSM_OVERLAY_WRITEBACK=y
CONFIG_FB_MSM_LCDC_MIPI_PANEL_AUTO_DETECT=y
CONFIG_FB_MSM_HDMI_MSM_PANEL=y
CONFIG_BACKLIGHT_LCD_SUPPORT=y
@@ -357,6 +357,7 @@
CONFIG_MMC=y
CONFIG_MMC_PERF_PROFILING=y
CONFIG_MMC_UNSAFE_RESUME=y
+CONFIG_MMC_CLKGATE=y
CONFIG_MMC_EMBEDDED_SDIO=y
CONFIG_MMC_PARANOID_SD_INIT=y
CONFIG_MMC_BLOCK_MINORS=32
@@ -416,16 +417,14 @@
CONFIG_TIMER_STATS=y
CONFIG_SLUB_DEBUG_ON=y
# CONFIG_DEBUG_PREEMPT is not set
-CONFIG_DEBUG_SPINLOCK=y
-CONFIG_DEBUG_MUTEXES=y
CONFIG_PROVE_LOCKING=y
CONFIG_DEBUG_SPINLOCK_SLEEP=y
CONFIG_DEBUG_STACK_USAGE=y
CONFIG_DEBUG_INFO=y
CONFIG_DEBUG_VM=y
CONFIG_DEBUG_MEMORY_INIT=y
-CONFIG_DEBUG_SG=y
CONFIG_DEBUG_LIST=y
+CONFIG_DEBUG_SG=y
CONFIG_DEBUG_PAGEALLOC=y
CONFIG_DYNAMIC_DEBUG=y
CONFIG_DEBUG_USER=y
diff --git a/arch/arm/configs/msm8960_defconfig b/arch/arm/configs/msm8960_defconfig
index e136a0a..83d012c 100644
--- a/arch/arm/configs/msm8960_defconfig
+++ b/arch/arm/configs/msm8960_defconfig
@@ -26,6 +26,7 @@
CONFIG_EMBEDDED=y
CONFIG_PROFILING=y
CONFIG_OPROFILE=y
+CONFIG_KPROBES=y
CONFIG_MODULES=y
CONFIG_MODULE_UNLOAD=y
CONFIG_MODULE_FORCE_UNLOAD=y
@@ -44,26 +45,28 @@
CONFIG_MACH_MSM8930_CDP=y
CONFIG_MACH_MSM8930_MTP=y
CONFIG_MACH_MSM8930_FLUID=y
+CONFIG_MACH_MSM8627_CDP=y
+CONFIG_MACH_MSM8627_MTP=y
CONFIG_MACH_APQ8064_SIM=y
CONFIG_MACH_APQ8064_RUMI3=y
# CONFIG_MSM_STACKED_MEMORY is not set
CONFIG_KERNEL_PMEM_EBI_REGION=y
-# CONFIG_MSM_JTAG_V7 is not set
# CONFIG_MSM_FIQ_SUPPORT is not set
# CONFIG_MSM_PROC_COMM is not set
CONFIG_MSM_SMD=y
CONFIG_MSM_SMD_PKG4=y
-CONFIG_MSM_IPC_ROUTER_SMD_XPRT=y
CONFIG_MSM_BAM_DMUX=y
CONFIG_MSM_DSPS=y
CONFIG_MSM_IPC_ROUTER=y
+CONFIG_MSM_IPC_ROUTER_SMD_XPRT=y
# CONFIG_MSM_HW3D is not set
+CONFIG_MSM_PIL_QDSP6V4=y
CONFIG_MSM_SUBSYSTEM_RESTART=y
CONFIG_MSM_MODEM_8960=y
CONFIG_MSM_LPASS_8960=y
CONFIG_MSM_WCNSS_SSR_8960=y
-CONFIG_MSM_RPM_LOG=y
CONFIG_MSM_TZ_LOG=y
+CONFIG_MSM_RPM_LOG=y
CONFIG_MSM_RPM_STATS_LOG=y
CONFIG_MSM_BUS_SCALING=y
CONFIG_MSM_BUS_RPM_MULTI_TIER_ENABLED=y
@@ -80,6 +83,7 @@
CONFIG_AEABI=y
CONFIG_HIGHMEM=y
CONFIG_VMALLOC_RESERVE=0x19000000
+CONFIG_CP_ACCESS=y
CONFIG_CPU_FREQ=y
CONFIG_CPU_FREQ_GOV_POWERSAVE=y
CONFIG_CPU_FREQ_GOV_USERSPACE=y
@@ -103,7 +107,6 @@
# CONFIG_INET_XFRM_MODE_TUNNEL is not set
# CONFIG_INET_XFRM_MODE_BEET is not set
# CONFIG_INET_LRO is not set
-CONFIG_INET_DIAG=y
CONFIG_IPV6=y
CONFIG_IPV6_PRIVACY=y
CONFIG_IPV6_ROUTER_PREF=y
@@ -132,6 +135,7 @@
CONFIG_NF_CONNTRACK_SIP=y
CONFIG_NF_CONNTRACK_TFTP=y
CONFIG_NF_CT_NETLINK=y
+CONFIG_NETFILTER_TPROXY=y
CONFIG_NETFILTER_XT_TARGET_CLASSIFY=y
CONFIG_NETFILTER_XT_TARGET_CONNMARK=y
CONFIG_NETFILTER_XT_TARGET_MARK=y
@@ -148,10 +152,11 @@
CONFIG_NETFILTER_XT_MATCH_MAC=y
CONFIG_NETFILTER_XT_MATCH_MARK=y
CONFIG_NETFILTER_XT_MATCH_MULTIPORT=y
-CONFIG_NETFILTER_XT_MATCH_OWNER=y
CONFIG_NETFILTER_XT_MATCH_POLICY=y
CONFIG_NETFILTER_XT_MATCH_PKTTYPE=y
+CONFIG_NETFILTER_XT_MATCH_QTAGUID=y
CONFIG_NETFILTER_XT_MATCH_QUOTA=y
+CONFIG_NETFILTER_XT_MATCH_SOCKET=y
CONFIG_NETFILTER_XT_MATCH_STATE=y
CONFIG_NETFILTER_XT_MATCH_STATISTIC=y
CONFIG_NETFILTER_XT_MATCH_STRING=y
@@ -198,11 +203,13 @@
CONFIG_BT_BNEP_PROTO_FILTER=y
CONFIG_BT_HIDP=y
CONFIG_BT_HCISMD=y
+CONFIG_CFG80211=y
+# CONFIG_CFG80211_WEXT is not set
CONFIG_RFKILL=y
-CONFIG_RFKILL_PM=y
+CONFIG_GENLOCK=y
+CONFIG_GENLOCK_MISCDEVICE=y
CONFIG_BLK_DEV_LOOP=y
CONFIG_BLK_DEV_RAM=y
-CONFIG_MISC_DEVICES=y
CONFIG_HAPTIC_ISA1200=y
CONFIG_PMIC8XXX_VIBRATOR=y
CONFIG_TZCOM=y
@@ -228,8 +235,7 @@
# CONFIG_NETDEV_1000 is not set
# CONFIG_NETDEV_10000 is not set
CONFIG_WCNSS_CORE=m
-CONFIG_CFG80211=y
-CONFIG_CFG80211_WEXT=n
+CONFIG_USB_USBNET=y
CONFIG_SLIP=y
CONFIG_SLIP_COMPRESSED=y
CONFIG_SLIP_MODE_SLIP6=y
@@ -292,8 +298,6 @@
CONFIG_RADIO_IRIS_TRANSPORT=m
CONFIG_ION=y
CONFIG_ION_MSM=y
-CONFIG_GENLOCK=y
-CONFIG_GENLOCK_MISCDEVICE=y
CONFIG_MSM_KGSL=y
CONFIG_KGSL_PER_PROCESS_PAGE_TABLE=y
CONFIG_FB=y
@@ -303,7 +307,6 @@
CONFIG_FB_MSM_TRIPLE_BUFFER=y
CONFIG_FB_MSM_MDP40=y
CONFIG_FB_MSM_OVERLAY=y
-CONFIG_FB_MSM_OVERLAY_WRITEBACK=y
CONFIG_FB_MSM_MIPI_PANEL_DETECT=y
CONFIG_FB_MSM_HDMI_MSM_PANEL=y
CONFIG_BACKLIGHT_LCD_SUPPORT=y
@@ -362,7 +365,6 @@
CONFIG_MMC_MSM_SDC3_WP_SUPPORT=y
CONFIG_MMC_MSM_SPS_SUPPORT=y
CONFIG_LEDS_PM8XXX=y
-# CONFIG_LEDS_MSM_PMIC is not set
CONFIG_LEDS_TRIGGERS=y
CONFIG_LEDS_TRIGGER_HEARTBEAT=y
CONFIG_SWITCH=y
@@ -399,7 +401,6 @@
CONFIG_NLS_ISO8859_1=y
CONFIG_PRINTK_TIME=y
CONFIG_MAGIC_SYSRQ=y
-CONFIG_DEBUG_FS=y
CONFIG_DEBUG_KERNEL=y
CONFIG_LOCKUP_DETECTOR=y
# CONFIG_SCHED_DEBUG is not set
@@ -413,6 +414,7 @@
CONFIG_DEBUG_MEMORY_INIT=y
CONFIG_DEBUG_LIST=y
CONFIG_DEBUG_PAGEALLOC=y
+CONFIG_ENABLE_DEFAULT_TRACERS=y
CONFIG_DYNAMIC_DEBUG=y
CONFIG_DEBUG_USER=y
CONFIG_CRYPTO_SHA256=y
diff --git a/arch/arm/configs/msm9615_defconfig b/arch/arm/configs/msm9615_defconfig
index e1b45e1..003f9c1 100644
--- a/arch/arm/configs/msm9615_defconfig
+++ b/arch/arm/configs/msm9615_defconfig
@@ -48,6 +48,8 @@
CONFIG_MSM_MODEM_8960=y
CONFIG_MSM_LPASS_8960=y
CONFIG_MSM_DIRECT_SCLK_ACCESS=y
+CONFIG_MSM_BUS_SCALING=y
+CONFIG_MSM_BUS_RPM_MULTI_TIER_ENABLED=y
CONFIG_MSM_WATCHDOG=y
CONFIG_MSM_DLOAD_MODE=y
# CONFIG_MSM_JTAG_V7 is not set
@@ -92,6 +94,15 @@
CONFIG_BLK_DEV_RAM=y
CONFIG_MISC_DEVICES=y
# CONFIG_ANDROID_PMEM is not set
+CONFIG_SCSI=y
+CONFIG_SCSI_TGT=y
+CONFIG_BLK_DEV_SD=y
+CONFIG_CHR_DEV_SG=y
+CONFIG_CHR_DEV_SCH=y
+CONFIG_SCSI_MULTI_LUN=y
+CONFIG_SCSI_CONSTANTS=y
+CONFIG_SCSI_LOGGING=y
+CONFIG_SCSI_SCAN_ASYNC=y
CONFIG_NETDEVICES=y
CONFIG_HOSTAP=y
# CONFIG_MSM_RMNET is not set
@@ -119,8 +130,6 @@
CONFIG_I2C_CHARDEV=y
# CONFIG_I2C_MSM is not set
CONFIG_I2C_QUP=y
-CONFIG_MSM_BUS_SCALING=y
-CONFIG_MSM_BUS_RPM_MULTI_TIER_ENABLED=y
CONFIG_SPI=y
CONFIG_SPI_QUP=y
CONFIG_SPI_SPIDEV=m
@@ -135,7 +144,6 @@
# CONFIG_HID_SUPPORT is not set
CONFIG_USB=y
CONFIG_USB_ANNOUNCE_NEW_DEVICES=y
-CONFIG_USB_SUSPEND=y
CONFIG_USB_EHCI_HCD=y
CONFIG_USB_EHCI_EHSET=y
CONFIG_USB_EHCI_MSM=y
@@ -158,15 +166,6 @@
CONFIG_USB_G_ANDROID=y
CONFIG_RMNET_SMD_CTL_CHANNEL="DATA36_CNTL"
CONFIG_RMNET_SMD_DATA_CHANNEL="DATA36"
-CONFIG_SCSI=y
-CONFIG_SCSI_TGT=y
-CONFIG_BLK_DEV_SD=y
-CONFIG_CHR_DEV_SG=y
-CONFIG_CHR_DEV_SCH=y
-CONFIG_SCSI_MULTI_LUN=y
-CONFIG_SCSI_CONSTANTS=y
-CONFIG_SCSI_LOGGING=y
-CONFIG_SCSI_SCAN_ASYNC=y
CONFIG_MMC=y
CONFIG_MMC_PERF_PROFILING=y
CONFIG_MMC_UNSAFE_RESUME=y
@@ -217,8 +216,6 @@
CONFIG_CRYPTO_MD5=y
CONFIG_CRYPTO_SHA1=y
CONFIG_CRYPTO_SHA256=y
-CONFIG_CRYPTO_AES=y
-CONFIG_CRYPTO_ARC4=y
CONFIG_CRYPTO_DES=y
CONFIG_CRYPTO_TWOFISH=y
CONFIG_CRYPTO_DEFLATE=y
diff --git a/arch/arm/include/asm/dma.h b/arch/arm/include/asm/dma.h
index 4200554..8a54b7d 100644
--- a/arch/arm/include/asm/dma.h
+++ b/arch/arm/include/asm/dma.h
@@ -33,18 +33,18 @@
#define DMA_MODE_CASCADE 0xc0
#define DMA_AUTOINIT 0x10
-extern spinlock_t dma_spin_lock;
+extern raw_spinlock_t dma_spin_lock;
static inline unsigned long claim_dma_lock(void)
{
unsigned long flags;
- spin_lock_irqsave(&dma_spin_lock, flags);
+ raw_spin_lock_irqsave(&dma_spin_lock, flags);
return flags;
}
static inline void release_dma_lock(unsigned long flags)
{
- spin_unlock_irqrestore(&dma_spin_lock, flags);
+ raw_spin_unlock_irqrestore(&dma_spin_lock, flags);
}
/* Clear the 'DMA Pointer Flip Flop'.
diff --git a/arch/arm/include/asm/mmu.h b/arch/arm/include/asm/mmu.h
index b4ffe9d..1496565 100644
--- a/arch/arm/include/asm/mmu.h
+++ b/arch/arm/include/asm/mmu.h
@@ -6,7 +6,7 @@
typedef struct {
#ifdef CONFIG_CPU_HAS_ASID
unsigned int id;
- spinlock_t id_lock;
+ raw_spinlock_t id_lock;
#endif
unsigned int kvm_seq;
} mm_context_t;
@@ -16,7 +16,7 @@
/* init_mm.context.id_lock should be initialized. */
#define INIT_MM_CONTEXT(name) \
- .context.id_lock = __SPIN_LOCK_UNLOCKED(name.context.id_lock),
+ .context.id_lock = __RAW_SPIN_LOCK_UNLOCKED(name.context.id_lock),
#else
#define ASID(mm) (0)
#endif
diff --git a/arch/arm/include/asm/mmu_writeable.h b/arch/arm/include/asm/mmu_writeable.h
index b3ce39b..96d348c 100644
--- a/arch/arm/include/asm/mmu_writeable.h
+++ b/arch/arm/include/asm/mmu_writeable.h
@@ -26,4 +26,6 @@
static inline void mem_text_writeable_spinunlock(unsigned long *flags) {};
#endif
+void mem_text_write_kernel_word(unsigned long *addr, unsigned long word);
+
#endif
diff --git a/arch/arm/include/asm/pgtable.h b/arch/arm/include/asm/pgtable.h
index cbb2f45..9693d47 100644
--- a/arch/arm/include/asm/pgtable.h
+++ b/arch/arm/include/asm/pgtable.h
@@ -485,15 +485,8 @@
* remap a physical page `pfn' of size `size' with page protection `prot'
* into virtual address `from'
*/
-#ifndef HAS_ARCH_IO_REMAP_PFN_RANGE
#define io_remap_pfn_range(vma,from,pfn,size,prot) \
remap_pfn_range(vma,from,pfn,size,prot)
-#else
-extern int arch_io_remap_pfn_range(struct vm_area_struct *vma, unsigned long addr, unsigned long pfn, unsigned long size, pgprot_t prot);
-#define io_remap_pfn_range(vma,from,pfn,size,prot) \
- arch_io_remap_pfn_range(vma,from,pfn,size,prot)
-#endif
-
#define pgtable_cache_init() do { } while (0)
diff --git a/arch/arm/kernel/arch_timer.c b/arch/arm/kernel/arch_timer.c
index 5b76911..a920c5f 100644
--- a/arch/arm/kernel/arch_timer.c
+++ b/arch/arm/kernel/arch_timer.c
@@ -11,6 +11,7 @@
#include <linux/init.h>
#include <linux/kernel.h>
#include <linux/delay.h>
+#include <linux/timex.h>
#include <linux/device.h>
#include <linux/smp.h>
#include <linux/cpu.h>
@@ -18,10 +19,13 @@
#include <linux/clockchips.h>
#include <linux/interrupt.h>
#include <linux/io.h>
+#include <linux/irq.h>
#include <asm/cputype.h>
+#include <asm/sched_clock.h>
#include <asm/hardware/gic.h>
+static struct irqaction arch_irqaction[2];
static unsigned long arch_timer_rate;
static int arch_timer_ppi;
static int arch_timer_ppi2;
@@ -77,13 +81,14 @@
static irqreturn_t arch_timer_handler(int irq, void *dev_id)
{
- struct clock_event_device *evt = dev_id;
+ struct clock_event_device *evt;
unsigned long ctrl;
ctrl = arch_timer_reg_read(ARCH_TIMER_REG_CTRL);
if (ctrl & 0x4) {
ctrl |= ARCH_TIMER_CTRL_IT_MASK;
arch_timer_reg_write(ARCH_TIMER_REG_CTRL, ctrl);
+ evt = per_cpu_ptr(arch_timer_evt, smp_processor_id());
evt->event_handler(evt);
return IRQ_HANDLED;
}
@@ -122,8 +127,8 @@
ctrl |= ARCH_TIMER_CTRL_ENABLE;
ctrl &= ~ARCH_TIMER_CTRL_IT_MASK;
- arch_timer_reg_write(ARCH_TIMER_REG_TVAL, evt);
arch_timer_reg_write(ARCH_TIMER_REG_CTRL, ctrl);
+ arch_timer_reg_write(ARCH_TIMER_REG_TVAL, evt);
return 0;
}
@@ -131,7 +136,6 @@
static void __cpuinit arch_timer_setup(void *data)
{
struct clock_event_device *clk = data;
- int err;
/* Be safe... */
arch_timer_stop();
@@ -147,20 +151,9 @@
clockevents_config_and_register(clk, arch_timer_rate,
0xf, 0x7fffffff);
- err = gic_request_ppi(clk->irq, arch_timer_handler, clk);
- if (err) {
- pr_err("%s: can't register interrupt %d on cpu %d (%d)\n",
- clk->name, clk->irq, smp_processor_id(), err);
- return;
- }
-
- if (arch_timer_ppi2 >= 0) {
- err = gic_request_ppi(arch_timer_ppi2, arch_timer_handler, clk);
- if (err) {
- pr_warn("%s: can't register interrupt %d on cpu %d (%d)\n",
- clk->name, arch_timer_ppi2, smp_processor_id(), err);
- }
- }
+ gic_enable_ppi(arch_timer_ppi);
+ if (arch_timer_ppi2 > 0)
+ gic_enable_ppi(arch_timer_ppi2);
}
/* Is the optional system timer available? */
@@ -218,6 +211,14 @@
return arch_counter_get_cntpct();
}
+#ifdef ARCH_HAS_READ_CURRENT_TIMER
+int read_current_timer(unsigned long *timer_val)
+{
+ *timer_val = (unsigned long)arch_counter_get_cntpct();
+ return 0;
+}
+#endif
+
static struct clocksource clocksource_counter = {
.name = "arch_sys_counter",
.rating = 400,
@@ -240,7 +241,7 @@
return (u32)(cntvct & (u32)~0);
}
-DEFINE_SCHED_CLOCK_FUNC(arch_timer_sched_clock)
+unsigned long long notrace sched_clock(void)
{
return cyc_to_sched_clock(&cd, arch_counter_get_cntvct32(), (u32)~0);
}
@@ -255,9 +256,11 @@
struct clock_event_device *clk = data;
pr_debug("arch_timer_teardown disable IRQ%d cpu #%d\n",
clk->irq, smp_processor_id());
- gic_free_ppi(clk->irq, clk);
- if (arch_timer_ppi2 >= 0)
- gic_free_ppi(arch_timer_ppi2, clk);
+ if (!smp_processor_id()) {
+ remove_irq(arch_timer_ppi, &arch_irqaction[0]);
+ if (arch_timer_ppi2 > 0)
+ remove_irq(arch_timer_ppi2, &arch_irqaction[1]);
+ }
arch_timer_set_mode(CLOCK_EVT_MODE_UNUSED, clk);
}
@@ -288,6 +291,8 @@
int arch_timer_register(struct resource *res, int res_nr)
{
+ struct irqaction *irqa;
+ unsigned int cpu = smp_processor_id();
int err;
if (!res_nr || res[0].start < 0 || !(res[0].flags & IORESOURCE_IRQ))
@@ -307,11 +312,41 @@
clocksource_register_hz(&clocksource_counter, arch_timer_rate);
- init_arch_sched_clock(&cd, arch_timer_update_sched_clock,
- arch_timer_sched_clock, 32, arch_timer_rate);
+ init_sched_clock(&cd, arch_timer_update_sched_clock, 32,
+ arch_timer_rate);
+
+#ifdef ARCH_HAS_READ_CURRENT_TIMER
+ set_delay_fn(read_current_timer_delay_loop);
+#endif
+
+ irqa = &arch_irqaction[0];
+ irqa->name = "arch_sys_timer";
+ irqa->flags = IRQF_DISABLED | IRQF_TIMER | IRQF_TRIGGER_HIGH;
+ irqa->handler = arch_timer_handler;
+ irqa->dev_id = per_cpu_ptr(arch_timer_evt, cpu);
+ irqa->irq = arch_timer_ppi;
+ err = setup_irq(arch_timer_ppi, irqa);
+ if (err) {
+ pr_err("%s: can't register interrupt %d (%d)\n",
+ irqa->name, irqa->irq, err);
+ return err;
+ }
+
+ if (arch_timer_ppi2 > 0) {
+ irqa = &arch_irqaction[1];
+ irqa->name = "arch_sys_timer";
+ irqa->flags = IRQF_DISABLED | IRQF_TIMER | IRQF_TRIGGER_HIGH;
+ irqa->handler = arch_timer_handler;
+ irqa->dev_id = per_cpu_ptr(arch_timer_evt, cpu);
+ irqa->irq = arch_timer_ppi2;
+ err = setup_irq(arch_timer_ppi2, irqa);
+ if (err)
+ pr_warn("%s: can't register interrupt %d (%d)\n",
+ irqa->name, irqa->irq, err);
+ }
/* Immediately configure the timer on the boot CPU */
- arch_timer_setup(per_cpu_ptr(arch_timer_evt, smp_processor_id()));
+ arch_timer_setup(per_cpu_ptr(arch_timer_evt, cpu));
register_cpu_notifier(&arch_timer_cpu_nb);
diff --git a/arch/arm/kernel/dma.c b/arch/arm/kernel/dma.c
index 2c4a185..7b829d9 100644
--- a/arch/arm/kernel/dma.c
+++ b/arch/arm/kernel/dma.c
@@ -23,7 +23,7 @@
#include <asm/mach/dma.h>
-DEFINE_SPINLOCK(dma_spin_lock);
+DEFINE_RAW_SPINLOCK(dma_spin_lock);
EXPORT_SYMBOL(dma_spin_lock);
static dma_t *dma_chan[MAX_DMA_CHANNELS];
diff --git a/arch/arm/kernel/irq.c b/arch/arm/kernel/irq.c
index 4ef97a0..5bd484f 100644
--- a/arch/arm/kernel/irq.c
+++ b/arch/arm/kernel/irq.c
@@ -144,54 +144,63 @@
#ifdef CONFIG_HOTPLUG_CPU
-static bool migrate_one_irq(struct irq_data *d)
+static bool migrate_one_irq(struct irq_desc *desc)
{
- unsigned int cpu = cpumask_any_and(d->affinity, cpu_online_mask);
+ struct irq_data *d = irq_desc_get_irq_data(desc);
+ const struct cpumask *affinity = d->affinity;
+ struct irq_chip *c;
bool ret = false;
- if (cpu >= nr_cpu_ids) {
- cpu = cpumask_any(cpu_online_mask);
+ /*
+ * If this is a per-CPU interrupt, or the affinity does not
+ * include this CPU, then we have nothing to do.
+ */
+ if (irqd_is_per_cpu(d) || !cpumask_test_cpu(smp_processor_id(), affinity))
+ return false;
+
+ if (cpumask_any_and(affinity, cpu_online_mask) >= nr_cpu_ids) {
+ affinity = cpu_online_mask;
ret = true;
}
- pr_debug("IRQ%u: moving from cpu%u to cpu%u\n", d->irq, d->node, cpu);
-
- d->chip->irq_set_affinity(d, cpumask_of(cpu), true);
+ c = irq_data_get_irq_chip(d);
+ if (c->irq_set_affinity)
+ c->irq_set_affinity(d, affinity, true);
+ else
+ pr_debug("IRQ%u: unable to set affinity\n", d->irq);
return ret;
}
/*
- * The CPU has been marked offline. Migrate IRQs off this CPU. If
- * the affinity settings do not allow other CPUs, force them onto any
+ * The current CPU has been marked offline. Migrate IRQs off this CPU.
+ * If the affinity settings do not allow other CPUs, force them onto any
* available CPU.
+ *
+ * Note: we must iterate over all IRQs, whether they have an attached
+ * action structure or not, as we need to get chained interrupts too.
*/
void migrate_irqs(void)
{
- unsigned int i, cpu = smp_processor_id();
+ unsigned int i;
struct irq_desc *desc;
unsigned long flags;
local_irq_save(flags);
for_each_irq_desc(i, desc) {
- struct irq_data *d = &desc->irq_data;
bool affinity_broken = false;
+ if (!desc)
+ continue;
+
raw_spin_lock(&desc->lock);
- do {
- if (desc->action == NULL)
- break;
-
- if (d->node != cpu)
- break;
-
- affinity_broken = migrate_one_irq(d);
- } while (0);
+ affinity_broken = migrate_one_irq(desc);
raw_spin_unlock(&desc->lock);
if (affinity_broken && printk_ratelimit())
- pr_warning("IRQ%u no longer affine to CPU%u\n", i, cpu);
+ pr_warning("IRQ%u no longer affine to CPU%u\n", i,
+ smp_processor_id());
}
local_irq_restore(flags);
diff --git a/arch/arm/kernel/perf_event_msm_krait_l2.c b/arch/arm/kernel/perf_event_msm_krait_l2.c
index 0512e64..c8b48a8 100644
--- a/arch/arm/kernel/perf_event_msm_krait_l2.c
+++ b/arch/arm/kernel/perf_event_msm_krait_l2.c
@@ -584,10 +584,15 @@
return err;
}
- hwc->config_base = event->attr.config;
hwc->config = 0;
hwc->event_base = 0;
+ /* Check if we came via perf default syms */
+ if (event->attr.config == PERF_COUNT_HW_L2_CYCLES)
+ hwc->config_base = L2CYCLE_CTR_RAW_CODE;
+ else
+ hwc->config_base = event->attr.config;
+
/* Only one CPU can control the cycle counter */
if (hwc->config_base == L2CYCLE_CTR_RAW_CODE) {
/* Check if its already running */
diff --git a/arch/arm/kernel/perf_event_msm_l2.c b/arch/arm/kernel/perf_event_msm_l2.c
index 3cb251b..33fb5bf 100644
--- a/arch/arm/kernel/perf_event_msm_l2.c
+++ b/arch/arm/kernel/perf_event_msm_l2.c
@@ -10,7 +10,7 @@
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*/
-#ifdef CONFIG_ARCH_MSM8x60
+#ifdef CONFIG_ARCH_MSM8X60
#include <linux/irq.h>
@@ -20,6 +20,8 @@
#define BB_L2CYCLE_CTR_EVENT_IDX 4
#define BB_L2CYCLE_CTR_RAW_CODE 0xfe
#define SCORPIONL2_PMNC_E (1 << 0) /* Enable all counters */
+#define SCORPION_L2_EVT_PREFIX 3
+#define SCORPION_MAX_L2_REG 4
/*
* Lock to protect r/m/w sequences to the L2 PMU.
@@ -365,6 +367,26 @@
struct bb_l2_scorp_evt *evtinfo)
{
u32 idx;
+ u8 prefix;
+ u8 reg;
+ u8 code;
+ u8 group;
+
+ prefix = (evt_type & 0xF0000) >> 16;
+ if (prefix == SCORPION_L2_EVT_PREFIX) {
+ reg = (evt_type & 0x0F000) >> 12;
+ code = (evt_type & 0x00FF0) >> 4;
+ group = evt_type & 0x0000F;
+
+ if ((group > 3) || (reg > SCORPION_MAX_L2_REG))
+ return BB_L2_INV_EVTYPE;
+
+ evtinfo->val = 0x80000000 | (code << (group * 8));
+ evtinfo->grp = reg;
+ evtinfo->evt_type_act = group | (reg << 2);
+ return evtinfo->evt_type_act;
+ }
+
if (evt_type < BB_L2_EVT_START_IDX || evt_type >= BB_L2_MAX_EVT)
return BB_L2_INV_EVTYPE;
idx = evt_type - BB_L2_EVT_START_IDX;
@@ -911,10 +933,15 @@
return err;
}
- hwc->config_base = event->attr.config & 0xff;
hwc->config = 0;
hwc->event_base = 0;
+ /* Check if we came via perf default syms */
+ if (event->attr.config == PERF_COUNT_HW_L2_CYCLES)
+ hwc->config_base = BB_L2CYCLE_CTR_RAW_CODE;
+ else
+ hwc->config_base = event->attr.config;
+
/* Only one CPU can control the cycle counter */
if (hwc->config_base == BB_L2CYCLE_CTR_RAW_CODE) {
/* Check if its already running */
diff --git a/arch/arm/kernel/smp.c b/arch/arm/kernel/smp.c
index 9e217ad..8aa7dcb 100644
--- a/arch/arm/kernel/smp.c
+++ b/arch/arm/kernel/smp.c
@@ -216,7 +216,7 @@
pr_err("CPU%u: cpu didn't die\n", cpu);
return;
}
- printk(KERN_NOTICE "CPU%u: shutdown\n", cpu);
+ pr_debug("CPU%u: shutdown\n", cpu);
if (!platform_cpu_kill(cpu))
printk("CPU%u: unable to kill\n", cpu);
@@ -281,7 +281,7 @@
struct mm_struct *mm = &init_mm;
unsigned int cpu = smp_processor_id();
- printk("CPU%u: Booted secondary processor\n", cpu);
+ pr_debug("CPU%u: Booted secondary processor\n", cpu);
/*
* All kernel threads share the same mm context; grab a
@@ -535,7 +535,7 @@
}
#endif
-static DEFINE_SPINLOCK(stop_lock);
+static DEFINE_RAW_SPINLOCK(stop_lock);
/*
* ipi_cpu_stop - handle IPI from smp_send_stop()
@@ -544,10 +544,10 @@
{
if (system_state == SYSTEM_BOOTING ||
system_state == SYSTEM_RUNNING) {
- spin_lock(&stop_lock);
+ raw_spin_lock(&stop_lock);
printk(KERN_CRIT "CPU%u: stopping\n", cpu);
dump_stack();
- spin_unlock(&stop_lock);
+ raw_spin_unlock(&stop_lock);
}
set_cpu_online(cpu, false);
diff --git a/arch/arm/kernel/swp_emulate.c b/arch/arm/kernel/swp_emulate.c
index 40ee7e5..7669848 100644
--- a/arch/arm/kernel/swp_emulate.c
+++ b/arch/arm/kernel/swp_emulate.c
@@ -173,6 +173,57 @@
return res;
}
+static int check_condition(struct pt_regs *regs, unsigned int insn)
+{
+ unsigned int base_cond, neg, cond = 0;
+ unsigned int cpsr_z, cpsr_c, cpsr_n, cpsr_v;
+
+ cpsr_n = (regs->ARM_cpsr & PSR_N_BIT) ? 1 : 0;
+ cpsr_z = (regs->ARM_cpsr & PSR_Z_BIT) ? 1 : 0;
+ cpsr_c = (regs->ARM_cpsr & PSR_C_BIT) ? 1 : 0;
+ cpsr_v = (regs->ARM_cpsr & PSR_V_BIT) ? 1 : 0;
+
+ /* Upper 3 bits indicate condition, lower bit incicates negation */
+ base_cond = insn >> 29;
+ neg = insn & BIT(28) ? 1 : 0;
+
+ switch (base_cond) {
+ case 0x0: /* equal */
+ cond = cpsr_z;
+ break;
+
+ case 0x1: /* carry set */
+ cond = cpsr_c;
+ break;
+
+ case 0x2: /* minus / negative */
+ cond = cpsr_n;
+ break;
+
+ case 0x3: /* overflow */
+ cond = cpsr_v;
+ break;
+
+ case 0x4: /* unsigned higher */
+ cond = (cpsr_c == 1) && (cpsr_z == 0);
+ break;
+
+ case 0x5: /* signed greater / equal */
+ cond = (cpsr_n == cpsr_v);
+ break;
+
+ case 0x6: /* signed greater */
+ cond = (cpsr_z == 0) && (cpsr_n == cpsr_v);
+ break;
+
+ case 0x7: /* always */
+ cond = 1;
+ break;
+ };
+
+ return cond && !neg;
+}
+
/*
* swp_handler logs the id of calling process, dissects the instruction, sanity
* checks the memory location, calls emulate_swpX for the actual operation and
@@ -191,6 +242,12 @@
previous_pid = current->pid;
}
+ /* Ignore the instruction if it fails its condition code check */
+ if (!check_condition(regs, instr)) {
+ regs->ARM_pc += 4;
+ return 0;
+ }
+
address = regs->uregs[EXTRACT_REG_NUM(instr, RN_OFFSET)];
data = regs->uregs[EXTRACT_REG_NUM(instr, RT2_OFFSET)];
destreg = EXTRACT_REG_NUM(instr, RT_OFFSET);
diff --git a/arch/arm/kernel/traps.c b/arch/arm/kernel/traps.c
index aaca029..c063c56 100644
--- a/arch/arm/kernel/traps.c
+++ b/arch/arm/kernel/traps.c
@@ -255,7 +255,7 @@
return ret;
}
-static DEFINE_SPINLOCK(die_lock);
+static DEFINE_RAW_SPINLOCK(die_lock);
/*
* This function is protected against re-entrancy.
@@ -267,7 +267,7 @@
oops_enter();
- spin_lock_irq(&die_lock);
+ raw_spin_lock_irq(&die_lock);
console_verbose();
bust_spinlocks(1);
ret = __die(str, err, thread, regs);
@@ -277,7 +277,7 @@
bust_spinlocks(0);
add_taint(TAINT_DIE);
- spin_unlock_irq(&die_lock);
+ raw_spin_unlock_irq(&die_lock);
oops_exit();
if (in_interrupt())
@@ -302,24 +302,24 @@
}
static LIST_HEAD(undef_hook);
-static DEFINE_SPINLOCK(undef_lock);
+static DEFINE_RAW_SPINLOCK(undef_lock);
void register_undef_hook(struct undef_hook *hook)
{
unsigned long flags;
- spin_lock_irqsave(&undef_lock, flags);
+ raw_spin_lock_irqsave(&undef_lock, flags);
list_add(&hook->node, &undef_hook);
- spin_unlock_irqrestore(&undef_lock, flags);
+ raw_spin_unlock_irqrestore(&undef_lock, flags);
}
void unregister_undef_hook(struct undef_hook *hook)
{
unsigned long flags;
- spin_lock_irqsave(&undef_lock, flags);
+ raw_spin_lock_irqsave(&undef_lock, flags);
list_del(&hook->node);
- spin_unlock_irqrestore(&undef_lock, flags);
+ raw_spin_unlock_irqrestore(&undef_lock, flags);
}
static int call_undef_hook(struct pt_regs *regs, unsigned int instr)
@@ -328,12 +328,12 @@
unsigned long flags;
int (*fn)(struct pt_regs *regs, unsigned int instr) = NULL;
- spin_lock_irqsave(&undef_lock, flags);
+ raw_spin_lock_irqsave(&undef_lock, flags);
list_for_each_entry(hook, &undef_hook, node)
if ((instr & hook->instr_mask) == hook->instr_val &&
(regs->ARM_cpsr & hook->cpsr_mask) == hook->cpsr_val)
fn = hook->fn;
- spin_unlock_irqrestore(&undef_lock, flags);
+ raw_spin_unlock_irqrestore(&undef_lock, flags);
return fn ? fn(regs, instr) : 1;
}
diff --git a/arch/arm/mach-footbridge/include/mach/hardware.h b/arch/arm/mach-footbridge/include/mach/hardware.h
index b6fdf23..14db5a0 100644
--- a/arch/arm/mach-footbridge/include/mach/hardware.h
+++ b/arch/arm/mach-footbridge/include/mach/hardware.h
@@ -93,7 +93,7 @@
#define CPLD_FLASH_WR_ENABLE 1
#ifndef __ASSEMBLY__
-extern spinlock_t nw_gpio_lock;
+extern raw_spinlock_t nw_gpio_lock;
extern void nw_gpio_modify_op(unsigned int mask, unsigned int set);
extern void nw_gpio_modify_io(unsigned int mask, unsigned int in);
extern unsigned int nw_gpio_read(void);
diff --git a/arch/arm/mach-footbridge/netwinder-hw.c b/arch/arm/mach-footbridge/netwinder-hw.c
index 06e514f..5b73190 100644
--- a/arch/arm/mach-footbridge/netwinder-hw.c
+++ b/arch/arm/mach-footbridge/netwinder-hw.c
@@ -68,7 +68,7 @@
/*
* This is a lock for accessing ports GP1_IO_BASE and GP2_IO_BASE
*/
-DEFINE_SPINLOCK(nw_gpio_lock);
+DEFINE_RAW_SPINLOCK(nw_gpio_lock);
EXPORT_SYMBOL(nw_gpio_lock);
static unsigned int current_gpio_op;
@@ -327,9 +327,9 @@
/*
* Set Group1/Group2 outputs
*/
- spin_lock_irqsave(&nw_gpio_lock, flags);
+ raw_spin_lock_irqsave(&nw_gpio_lock, flags);
nw_gpio_modify_op(-1, GPIO_RED_LED | GPIO_FAN);
- spin_unlock_irqrestore(&nw_gpio_lock, flags);
+ raw_spin_unlock_irqrestore(&nw_gpio_lock, flags);
}
/*
@@ -390,9 +390,9 @@
{
unsigned long flags;
- spin_lock_irqsave(&nw_gpio_lock, flags);
+ raw_spin_lock_irqsave(&nw_gpio_lock, flags);
nw_cpld_modify(-1, CPLD_UNMUTE | CPLD_7111_DISABLE);
- spin_unlock_irqrestore(&nw_gpio_lock, flags);
+ raw_spin_unlock_irqrestore(&nw_gpio_lock, flags);
}
static unsigned char rwa_unlock[] __initdata =
@@ -616,9 +616,9 @@
cpld_init();
rwa010_init();
- spin_lock_irqsave(&nw_gpio_lock, flags);
+ raw_spin_lock_irqsave(&nw_gpio_lock, flags);
nw_gpio_modify_op(GPIO_RED_LED|GPIO_GREEN_LED, DEFAULT_LEDS);
- spin_unlock_irqrestore(&nw_gpio_lock, flags);
+ raw_spin_unlock_irqrestore(&nw_gpio_lock, flags);
}
return 0;
}
diff --git a/arch/arm/mach-footbridge/netwinder-leds.c b/arch/arm/mach-footbridge/netwinder-leds.c
index 00269fe..e57102e 100644
--- a/arch/arm/mach-footbridge/netwinder-leds.c
+++ b/arch/arm/mach-footbridge/netwinder-leds.c
@@ -31,13 +31,13 @@
static char led_state;
static char hw_led_state;
-static DEFINE_SPINLOCK(leds_lock);
+static DEFINE_RAW_SPINLOCK(leds_lock);
static void netwinder_leds_event(led_event_t evt)
{
unsigned long flags;
- spin_lock_irqsave(&leds_lock, flags);
+ raw_spin_lock_irqsave(&leds_lock, flags);
switch (evt) {
case led_start:
@@ -117,12 +117,12 @@
break;
}
- spin_unlock_irqrestore(&leds_lock, flags);
+ raw_spin_unlock_irqrestore(&leds_lock, flags);
if (led_state & LED_STATE_ENABLED) {
- spin_lock_irqsave(&nw_gpio_lock, flags);
+ raw_spin_lock_irqsave(&nw_gpio_lock, flags);
nw_gpio_modify_op(GPIO_RED_LED | GPIO_GREEN_LED, hw_led_state);
- spin_unlock_irqrestore(&nw_gpio_lock, flags);
+ raw_spin_unlock_irqrestore(&nw_gpio_lock, flags);
}
}
diff --git a/arch/arm/mach-integrator/core.c b/arch/arm/mach-integrator/core.c
index 77315b9..0c20cf6 100644
--- a/arch/arm/mach-integrator/core.c
+++ b/arch/arm/mach-integrator/core.c
@@ -205,7 +205,7 @@
#define CM_CTRL IO_ADDRESS(INTEGRATOR_HDR_CTRL)
-static DEFINE_SPINLOCK(cm_lock);
+static DEFINE_RAW_SPINLOCK(cm_lock);
/**
* cm_control - update the CM_CTRL register.
@@ -217,10 +217,10 @@
unsigned long flags;
u32 val;
- spin_lock_irqsave(&cm_lock, flags);
+ raw_spin_lock_irqsave(&cm_lock, flags);
val = readl(CM_CTRL) & ~mask;
writel(val | set, CM_CTRL);
- spin_unlock_irqrestore(&cm_lock, flags);
+ raw_spin_unlock_irqrestore(&cm_lock, flags);
}
EXPORT_SYMBOL(cm_control);
diff --git a/arch/arm/mach-integrator/pci_v3.c b/arch/arm/mach-integrator/pci_v3.c
index 6467d99..a9b90a0 100644
--- a/arch/arm/mach-integrator/pci_v3.c
+++ b/arch/arm/mach-integrator/pci_v3.c
@@ -163,7 +163,7 @@
* 7:2 register number
*
*/
-static DEFINE_SPINLOCK(v3_lock);
+static DEFINE_RAW_SPINLOCK(v3_lock);
#define PCI_BUS_NONMEM_START 0x00000000
#define PCI_BUS_NONMEM_SIZE SZ_256M
@@ -284,7 +284,7 @@
unsigned long flags;
u32 v;
- spin_lock_irqsave(&v3_lock, flags);
+ raw_spin_lock_irqsave(&v3_lock, flags);
addr = v3_open_config_window(bus, devfn, where);
switch (size) {
@@ -302,7 +302,7 @@
}
v3_close_config_window();
- spin_unlock_irqrestore(&v3_lock, flags);
+ raw_spin_unlock_irqrestore(&v3_lock, flags);
*val = v;
return PCIBIOS_SUCCESSFUL;
@@ -314,7 +314,7 @@
unsigned long addr;
unsigned long flags;
- spin_lock_irqsave(&v3_lock, flags);
+ raw_spin_lock_irqsave(&v3_lock, flags);
addr = v3_open_config_window(bus, devfn, where);
switch (size) {
@@ -335,7 +335,7 @@
}
v3_close_config_window();
- spin_unlock_irqrestore(&v3_lock, flags);
+ raw_spin_unlock_irqrestore(&v3_lock, flags);
return PCIBIOS_SUCCESSFUL;
}
@@ -510,7 +510,7 @@
hook_fault_code(8, v3_pci_fault, SIGBUS, 0, "external abort on non-linefetch");
hook_fault_code(10, v3_pci_fault, SIGBUS, 0, "external abort on non-linefetch");
- spin_lock_irqsave(&v3_lock, flags);
+ raw_spin_lock_irqsave(&v3_lock, flags);
/*
* Unlock V3 registers, but only if they were previously locked.
@@ -583,7 +583,7 @@
printk(KERN_ERR "PCI: unable to grab PCI error "
"interrupt: %d\n", ret);
- spin_unlock_irqrestore(&v3_lock, flags);
+ raw_spin_unlock_irqrestore(&v3_lock, flags);
}
void __init pci_v3_postinit(void)
diff --git a/arch/arm/mach-ixp4xx/common-pci.c b/arch/arm/mach-ixp4xx/common-pci.c
index e9a5893..ab19445 100644
--- a/arch/arm/mach-ixp4xx/common-pci.c
+++ b/arch/arm/mach-ixp4xx/common-pci.c
@@ -54,7 +54,7 @@
* these transactions are atomic or we will end up
* with corrupt data on the bus or in a driver.
*/
-static DEFINE_SPINLOCK(ixp4xx_pci_lock);
+static DEFINE_RAW_SPINLOCK(ixp4xx_pci_lock);
/*
* Read from PCI config space
@@ -62,10 +62,10 @@
static void crp_read(u32 ad_cbe, u32 *data)
{
unsigned long flags;
- spin_lock_irqsave(&ixp4xx_pci_lock, flags);
+ raw_spin_lock_irqsave(&ixp4xx_pci_lock, flags);
*PCI_CRP_AD_CBE = ad_cbe;
*data = *PCI_CRP_RDATA;
- spin_unlock_irqrestore(&ixp4xx_pci_lock, flags);
+ raw_spin_unlock_irqrestore(&ixp4xx_pci_lock, flags);
}
/*
@@ -74,10 +74,10 @@
static void crp_write(u32 ad_cbe, u32 data)
{
unsigned long flags;
- spin_lock_irqsave(&ixp4xx_pci_lock, flags);
+ raw_spin_lock_irqsave(&ixp4xx_pci_lock, flags);
*PCI_CRP_AD_CBE = CRP_AD_CBE_WRITE | ad_cbe;
*PCI_CRP_WDATA = data;
- spin_unlock_irqrestore(&ixp4xx_pci_lock, flags);
+ raw_spin_unlock_irqrestore(&ixp4xx_pci_lock, flags);
}
static inline int check_master_abort(void)
@@ -101,7 +101,7 @@
int retval = 0;
int i;
- spin_lock_irqsave(&ixp4xx_pci_lock, flags);
+ raw_spin_lock_irqsave(&ixp4xx_pci_lock, flags);
*PCI_NP_AD = addr;
@@ -118,7 +118,7 @@
if(check_master_abort())
retval = 1;
- spin_unlock_irqrestore(&ixp4xx_pci_lock, flags);
+ raw_spin_unlock_irqrestore(&ixp4xx_pci_lock, flags);
return retval;
}
@@ -127,7 +127,7 @@
unsigned long flags;
int retval = 0;
- spin_lock_irqsave(&ixp4xx_pci_lock, flags);
+ raw_spin_lock_irqsave(&ixp4xx_pci_lock, flags);
*PCI_NP_AD = addr;
@@ -140,7 +140,7 @@
if(check_master_abort())
retval = 1;
- spin_unlock_irqrestore(&ixp4xx_pci_lock, flags);
+ raw_spin_unlock_irqrestore(&ixp4xx_pci_lock, flags);
return retval;
}
@@ -149,7 +149,7 @@
unsigned long flags;
int retval = 0;
- spin_lock_irqsave(&ixp4xx_pci_lock, flags);
+ raw_spin_lock_irqsave(&ixp4xx_pci_lock, flags);
*PCI_NP_AD = addr;
@@ -162,7 +162,7 @@
if(check_master_abort())
retval = 1;
- spin_unlock_irqrestore(&ixp4xx_pci_lock, flags);
+ raw_spin_unlock_irqrestore(&ixp4xx_pci_lock, flags);
return retval;
}
diff --git a/arch/arm/mach-msm/Kconfig b/arch/arm/mach-msm/Kconfig
index fc27feb..0078ebc 100644
--- a/arch/arm/mach-msm/Kconfig
+++ b/arch/arm/mach-msm/Kconfig
@@ -146,7 +146,7 @@
select MIGRATION
select ARCH_MEMORY_PROBE
select ARCH_MEMORY_REMOVE
- select DONT_RESERVE_FROM_MOVABLE_ZONE
+ select FIX_MOVABLE_ZONE
config ARCH_MSM8930
bool "MSM8930"
@@ -177,7 +177,7 @@
select MIGRATION
select ARCH_MEMORY_PROBE
select ARCH_MEMORY_REMOVE
- select DONT_RESERVE_FROM_MOVABLE_ZONE
+ select FIX_MOVABLE_ZONE
select MSM_ULTRASOUND
config ARCH_APQ8064
@@ -190,6 +190,9 @@
select MSM_SCM if SMP
select MSM_GPIOMUX
select MSM_REMOTE_SPINLOCK_SFPB
+ select MSM_PIL
+ select MSM_QDSP6_APR
+ select MSM_AUDIO_QDSP6 if SND_SOC
config ARCH_MSMCOPPER
bool "MSM Copper"
@@ -252,6 +255,7 @@
config ARCH_MSM_KRAIT
bool
+ select ARM_L1_CACHE_SHIFT_6
config MSM_SMP
bool
@@ -604,6 +608,18 @@
help
Support for the Qualcomm MSM8930 FLUID device.
+config MACH_MSM8627_CDP
+ depends on ARCH_MSM8930
+ bool "MSM8627 CDP"
+ help
+ Support for the Qualcomm MSM8627 CDP device.
+
+config MACH_MSM8627_MTP
+ depends on ARCH_MSM8930
+ bool "MSM8627 MTP"
+ help
+ Support for the Qualcomm MSM8627 MTP device.
+
config MACH_MSM9615_CDP
depends on ARCH_MSM9615
bool "MSM9615 CDP"
@@ -1558,6 +1574,14 @@
Say yes to support these devices.
+config MSM_PIL_QDSP6V4
+ tristate "QDSP6v4 (Hexagon) Boot Support"
+ depends on MSM_PIL
+ help
+ Support for booting and shutting down QDSP6v4 processors (hexagon).
+ The QDSP6 is a low power DSP used in audio, modem firmware, and modem
+ software applications.
+
config MSM_SCM
bool "Secure Channel Manager (SCM) support"
default n
diff --git a/arch/arm/mach-msm/Makefile b/arch/arm/mach-msm/Makefile
index bccc05b..05f4ab4 100644
--- a/arch/arm/mach-msm/Makefile
+++ b/arch/arm/mach-msm/Makefile
@@ -1,4 +1,7 @@
-obj-y += io.o dma.o memory.o timer.o
+obj-y += io.o dma.o memory.o
+ifndef CONFIG_ARM_ARCH_TIMER
+obj-y += timer.o
+endif
obj-y += clock.o clock-voter.o clock-dummy.o
obj-y += modem_notifier.o subsystem_map.o
obj-$(CONFIG_CPU_FREQ_MSM) += cpufreq.o
@@ -68,6 +71,7 @@
obj-$(CONFIG_ARCH_MSM8X60) += peripheral-reset.o
obj-$(CONFIG_ARCH_MSM8960) += peripheral-reset-8960.o
endif
+obj-$(CONFIG_MSM_PIL_QDSP6V4) += pil-q6v4.o
obj-$(CONFIG_ARCH_QSD8X50) += sirc.o
obj-$(CONFIG_ARCH_FSM9XXX) += sirc-fsm9xxx.o
obj-$(CONFIG_MSM_FIQ_SUPPORT) += fiq_glue.o
@@ -99,7 +103,7 @@
endif
endif
endif
-obj-$(CONFIG_MSM_SDIO_TTY) += sdio_tty.o sdio_tty_ciq.o
+obj-$(CONFIG_MSM_SDIO_TTY) += sdio_tty.o
obj-$(CONFIG_MSM_SMD_TTY) += smd_tty.o
obj-$(CONFIG_MSM_SMD_QMI) += smd_qmi.o
obj-$(CONFIG_MSM_SMD_PKT) += smd_pkt.o
@@ -223,16 +227,22 @@
obj-$(CONFIG_ARCH_MSM8960) += acpuclock-8960.o
obj-$(CONFIG_ARCH_MSM8960) += memory_topology.o
obj-$(CONFIG_ARCH_MSM8960) += saw-regulator.o rpm-regulator.o rpm-regulator-8960.o
-obj-$(CONFIG_MACH_MSM8960_SIM) += board-msm8960.o devices-8960.o board-msm8960-regulator.o
-obj-$(CONFIG_MACH_MSM8960_RUMI3) += board-msm8960.o devices-8960.o board-msm8960-regulator.o
-obj-$(CONFIG_MACH_MSM8960_CDP) += board-msm8960.o devices-8960.o board-msm8960-regulator.o
-obj-$(CONFIG_MACH_MSM8960_MTP) += board-msm8960.o devices-8960.o board-msm8960-regulator.o
-obj-$(CONFIG_MACH_MSM8960_FLUID) += board-msm8960.o devices-8960.o board-msm8960-regulator.o
-obj-$(CONFIG_MACH_MSM8930_CDP) += board-msm8960.o devices-8960.o board-msm8960-regulator.o
-obj-$(CONFIG_MACH_MSM8930_MTP) += board-msm8960.o devices-8960.o board-msm8960-regulator.o
-obj-$(CONFIG_MACH_MSM8930_FLUID) += board-msm8960.o devices-8960.o board-msm8960-regulator.o
+obj-$(CONFIG_ARCH_MSM8960) += devices-8960.o
+obj-$(CONFIG_ARCH_APQ8064) += devices-8960.o devices-8064.o
+board-8960-all-objs += board-8960.o board-8960-camera.o board-8960-display.o board-8960-pmic.o board-8960-storage.o board-8960-gpiomux.o
+board-8930-all-objs += board-8930.o board-8930-camera.o board-8930-display.o board-8930-pmic.o board-8930-storage.o board-8930-gpiomux.o
+board-8064-all-objs += board-8064.o board-8064-storage.o
+obj-$(CONFIG_MACH_MSM8960_SIM) += board-8960-all.o board-8960-regulator.o
+obj-$(CONFIG_MACH_MSM8960_RUMI3) += board-8960-all.o board-8960-regulator.o
+obj-$(CONFIG_MACH_MSM8960_CDP) += board-8960-all.o board-8960-regulator.o
+obj-$(CONFIG_MACH_MSM8960_MTP) += board-8960-all.o board-8960-regulator.o
+obj-$(CONFIG_MACH_MSM8960_FLUID) += board-8960-all.o board-8960-regulator.o
+obj-$(CONFIG_MACH_MSM8930_CDP) += board-8930-all.o board-8960-regulator.o
+obj-$(CONFIG_MACH_MSM8930_MTP) += board-8930-all.o board-8960-regulator.o
+obj-$(CONFIG_MACH_MSM8930_FLUID) += board-8930-all.o board-8960-regulator.o
obj-$(CONFIG_ARCH_MSM8960) += bms-batterydata.o
-obj-$(CONFIG_ARCH_APQ8064) += board-apq8064.o devices-8064.o board-apq8064-regulator.o
+obj-$(CONFIG_MACH_APQ8064_SIM) += board-8064-all.o board-8064-regulator.o
+obj-$(CONFIG_MACH_APQ8064_RUMI3) += board-8064-all.o board-8064-regulator.o
obj-$(CONFIG_ARCH_MSM9615) += board-9615.o devices-9615.o board-9615-regulator.o
obj-$(CONFIG_ARCH_MSM9615) += clock-local.o clock-9615.o acpuclock-9615.o clock-rpm.o
obj-$(CONFIG_ARCH_MSM9615) += rpm-regulator.o rpm-regulator-9615.o
diff --git a/arch/arm/mach-msm/acpuclock-8960.c b/arch/arm/mach-msm/acpuclock-8960.c
index 659c292..143fb86 100644
--- a/arch/arm/mach-msm/acpuclock-8960.c
+++ b/arch/arm/mach-msm/acpuclock-8960.c
@@ -140,7 +140,7 @@
.hfpll_base = MSM_HFPLL_BASE + 0x200,
.aux_clk_sel = MSM_ACC0_BASE + 0x014,
.l2cpmr_iaddr = L2CPUCPMR_IADDR,
- .vreg[VREG_CORE] = { "krait0", 1150000 },
+ .vreg[VREG_CORE] = { "krait0", 1300000 },
.vreg[VREG_MEM] = { "krait0_mem", 1150000,
RPM_VREG_VOTER1,
RPM_VREG_ID_PM8921_L24 },
@@ -158,7 +158,7 @@
.hfpll_base = MSM_HFPLL_BASE + 0x300,
.aux_clk_sel = MSM_ACC1_BASE + 0x014,
.l2cpmr_iaddr = L2CPUCPMR_IADDR,
- .vreg[VREG_CORE] = { "krait1", 1150000 },
+ .vreg[VREG_CORE] = { "krait1", 1300000 },
.vreg[VREG_MEM] = { "krait0_mem", 1150000,
RPM_VREG_VOTER2,
RPM_VREG_ID_PM8921_L24 },
@@ -287,8 +287,8 @@
static uint32_t bus_perf_client;
/* TODO: Update vdd_dig and vdd_mem when voltage data is available. */
-#define L2(x) (&l2_freq_tbl_8960[(x)])
-static struct l2_level l2_freq_tbl_8960[] = {
+#define L2(x) (&l2_freq_tbl_8960_kraitv1[(x)])
+static struct l2_level l2_freq_tbl_8960_kraitv1[] = {
[0] = { {STBY_KHZ, QSB, 0, 0, 0x00 }, 1050000, 1050000, 0 },
[1] = { { 384000, PLL_8, 0, 2, 0x00 }, 1050000, 1050000, 1 },
[2] = { { 432000, HFPLL, 2, 0, 0x20 }, 1050000, 1050000, 1 },
@@ -303,7 +303,7 @@
[11] = { { 918000, HFPLL, 1, 0, 0x22 }, 1150000, 1150000, 3 },
};
-static struct acpu_level acpu_freq_tbl_8960[] = {
+static struct acpu_level acpu_freq_tbl_8960_kraitv1[] = {
{ 0, {STBY_KHZ, QSB, 0, 0, 0x00 }, L2(0), 950000 },
{ 1, { 384000, PLL_8, 0, 2, 0x00 }, L2(1), 950000 },
{ 1, { 432000, HFPLL, 2, 0, 0x20 }, L2(6), 950000 },
@@ -319,6 +319,55 @@
{ 0, { 0 } }
};
+#undef L2
+#define L2(x) (&l2_freq_tbl_8960_kraitv2[(x)])
+static struct l2_level l2_freq_tbl_8960_kraitv2[] = {
+ [0] = { {STBY_KHZ, QSB, 0, 0, 0x00 }, 1050000, 1050000, 0 },
+ [1] = { { 384000, PLL_8, 0, 2, 0x00 }, 1050000, 1050000, 1 },
+ [2] = { { 432000, HFPLL, 2, 0, 0x20 }, 1050000, 1050000, 1 },
+ [3] = { { 486000, HFPLL, 2, 0, 0x24 }, 1050000, 1050000, 1 },
+ [4] = { { 540000, HFPLL, 2, 0, 0x28 }, 1050000, 1050000, 1 },
+ [5] = { { 594000, HFPLL, 1, 0, 0x16 }, 1050000, 1050000, 2 },
+ [6] = { { 648000, HFPLL, 1, 0, 0x18 }, 1050000, 1050000, 2 },
+ [7] = { { 702000, HFPLL, 1, 0, 0x1A }, 1050000, 1050000, 2 },
+ [8] = { { 756000, HFPLL, 1, 0, 0x1C }, 1150000, 1150000, 2 },
+ [9] = { { 810000, HFPLL, 1, 0, 0x1E }, 1150000, 1150000, 3 },
+ [10] = { { 864000, HFPLL, 1, 0, 0x20 }, 1150000, 1150000, 3 },
+ [11] = { { 918000, HFPLL, 1, 0, 0x22 }, 1150000, 1150000, 3 },
+ [12] = { { 972000, HFPLL, 1, 0, 0x24 }, 1150000, 1150000, 4 },
+ [13] = { { 1026000, HFPLL, 1, 0, 0x26 }, 1150000, 1150000, 4 },
+ [14] = { { 1080000, HFPLL, 1, 0, 0x28 }, 1150000, 1150000, 4 },
+ [15] = { { 1134000, HFPLL, 1, 0, 0x2A }, 1150000, 1150000, 4 },
+ [16] = { { 1188000, HFPLL, 1, 0, 0x2C }, 1150000, 1150000, 4 },
+};
+
+static struct acpu_level acpu_freq_tbl_8960_kraitv2[] = {
+ { 0, { STBY_KHZ, QSB, 0, 0, 0x00 }, L2(0), 950000 },
+ { 1, { 384000, PLL_8, 0, 2, 0x00 }, L2(1), 950000 },
+ { 1, { 432000, HFPLL, 2, 0, 0x20 }, L2(6), 950000 },
+ { 1, { 486000, HFPLL, 2, 0, 0x24 }, L2(6), 962500 },
+ { 1, { 540000, HFPLL, 2, 0, 0x28 }, L2(6), 962500 },
+ { 1, { 594000, HFPLL, 1, 0, 0x16 }, L2(6), 987500 },
+ { 1, { 648000, HFPLL, 1, 0, 0x18 }, L2(6), 1000000 },
+ { 1, { 702000, HFPLL, 1, 0, 0x1A }, L2(6), 1025000 },
+ { 1, { 756000, HFPLL, 1, 0, 0x1C }, L2(11), 1050000 },
+ { 1, { 810000, HFPLL, 1, 0, 0x1E }, L2(11), 1087500 },
+ { 1, { 864000, HFPLL, 1, 0, 0x20 }, L2(11), 1125000 },
+ { 1, { 918000, HFPLL, 1, 0, 0x22 }, L2(11), 1137500 },
+ { 1, { 972000, HFPLL, 1, 0, 0x24 }, L2(16), 1300000 },
+ { 1, { 1026000, HFPLL, 1, 0, 0x26 }, L2(16), 1300000 },
+ { 1, { 1080000, HFPLL, 1, 0, 0x28 }, L2(16), 1300000 },
+ { 1, { 1134000, HFPLL, 1, 0, 0x2A }, L2(16), 1300000 },
+ { 1, { 1188000, HFPLL, 1, 0, 0x2C }, L2(16), 1300000 },
+ { 1, { 1242000, HFPLL, 1, 0, 0x2E }, L2(16), 1300000 },
+ { 1, { 1296000, HFPLL, 1, 0, 0x30 }, L2(16), 1300000 },
+ { 1, { 1350000, HFPLL, 1, 0, 0x32 }, L2(16), 1300000 },
+ { 1, { 1404000, HFPLL, 1, 0, 0x34 }, L2(16), 1300000 },
+ { 1, { 1458000, HFPLL, 1, 0, 0x36 }, L2(16), 1300000 },
+ { 1, { 1512000, HFPLL, 1, 0, 0x38 }, L2(16), 1300000 },
+ { 0, { 0 } }
+};
+
/* TODO: Update vdd_dig and vdd_mem when voltage data is available. */
#undef L2
#define L2(x) (&l2_freq_tbl_8064[(x)])
@@ -1051,9 +1100,15 @@
/* TODO: Select tables based on PVS data. */
scalable = scalable_8960;
- acpu_freq_tbl = acpu_freq_tbl_8960;
- l2_freq_tbl = l2_freq_tbl_8960;
- l2_freq_tbl_size = ARRAY_SIZE(l2_freq_tbl_8960);
+ if (cpu_is_krait_v1()) {
+ acpu_freq_tbl = acpu_freq_tbl_8960_kraitv1;
+ l2_freq_tbl = l2_freq_tbl_8960_kraitv1;
+ l2_freq_tbl_size = ARRAY_SIZE(l2_freq_tbl_8960_kraitv1);
+ } else {
+ acpu_freq_tbl = acpu_freq_tbl_8960_kraitv2;
+ l2_freq_tbl = l2_freq_tbl_8960_kraitv2;
+ l2_freq_tbl_size = ARRAY_SIZE(l2_freq_tbl_8960_kraitv2);
+ }
} else if (cpu_is_apq8064()) {
scalable = scalable_8064;
acpu_freq_tbl = acpu_freq_tbl_8064;
diff --git a/arch/arm/mach-msm/bam_dmux.c b/arch/arm/mach-msm/bam_dmux.c
index ede298d..0041f0d 100644
--- a/arch/arm/mach-msm/bam_dmux.c
+++ b/arch/arm/mach-msm/bam_dmux.c
@@ -45,6 +45,8 @@
#define POLLING_MAX_SLEEP 1050 /* 1.05 ms */
#define POLLING_INACTIVITY 40 /* cycles before switch to intr mode */
+#define LOW_WATERMARK 2
+#define HIGH_WATERMARK 4
static int msm_bam_dmux_debug_enable;
module_param_named(debug_enable, msm_bam_dmux_debug_enable,
@@ -104,6 +106,8 @@
spinlock_t lock;
struct platform_device *pdev;
char name[BAM_DMUX_CH_NAME_MAX_LEN];
+ int num_tx_pkts;
+ int use_wm;
};
struct tx_pkt_info {
@@ -318,6 +322,7 @@
case BAM_MUX_HDR_CMD_OPEN:
spin_lock_irqsave(&bam_ch[rx_hdr->ch_id].lock, flags);
bam_ch[rx_hdr->ch_id].status |= BAM_CH_REMOTE_OPEN;
+ bam_ch[rx_hdr->ch_id].num_tx_pkts = 0;
spin_unlock_irqrestore(&bam_ch[rx_hdr->ch_id].lock, flags);
queue_rx();
ret = platform_device_add(bam_ch[rx_hdr->ch_id].pdev);
@@ -355,6 +360,7 @@
int rc;
struct tx_pkt_info *pkt;
dma_addr_t dma_address;
+ unsigned long flags;
pkt = kmalloc(sizeof(struct tx_pkt_info), GFP_ATOMIC);
if (pkt == NULL) {
@@ -375,17 +381,17 @@
pkt->dma_address = dma_address;
pkt->is_cmd = 1;
INIT_WORK(&pkt->work, bam_mux_write_done);
- spin_lock(&bam_tx_pool_spinlock);
+ spin_lock_irqsave(&bam_tx_pool_spinlock, flags);
list_add_tail(&pkt->list_node, &bam_tx_pool);
- spin_unlock(&bam_tx_pool_spinlock);
+ spin_unlock_irqrestore(&bam_tx_pool_spinlock, flags);
rc = sps_transfer_one(bam_tx_pipe, dma_address, len,
pkt, SPS_IOVEC_FLAG_INT | SPS_IOVEC_FLAG_EOT);
if (rc) {
DBG("%s sps_transfer_one failed rc=%d\n", __func__, rc);
- spin_lock(&bam_tx_pool_spinlock);
+ spin_lock_irqsave(&bam_tx_pool_spinlock, flags);
list_del(&pkt->list_node);
DBG_INC_TX_SPS_FAILURE_CNT();
- spin_unlock(&bam_tx_pool_spinlock);
+ spin_unlock_irqrestore(&bam_tx_pool_spinlock, flags);
kfree(pkt);
}
@@ -400,13 +406,14 @@
struct tx_pkt_info *info;
unsigned long event_data;
struct list_head *node;
+ unsigned long flags;
if (in_global_reset)
return;
- spin_lock(&bam_tx_pool_spinlock);
+ spin_lock_irqsave(&bam_tx_pool_spinlock, flags);
node = bam_tx_pool.next;
list_del(node);
- spin_unlock(&bam_tx_pool_spinlock);
+ spin_unlock_irqrestore(&bam_tx_pool_spinlock, flags);
info = container_of(work, struct tx_pkt_info, work);
if (info->is_cmd) {
kfree(info->skb);
@@ -418,6 +425,9 @@
hdr = (struct bam_mux_hdr *)skb->data;
DBG_INC_WRITE_CNT(skb->data_len);
event_data = (unsigned long)(skb);
+ spin_lock_irqsave(&bam_ch[hdr->ch_id].lock, flags);
+ bam_ch[hdr->ch_id].num_tx_pkts--;
+ spin_unlock_irqrestore(&bam_ch[hdr->ch_id].lock, flags);
if (bam_ch[hdr->ch_id].notify)
bam_ch[hdr->ch_id].notify(
bam_ch[hdr->ch_id].priv, BAM_DMUX_WRITE_DONE,
@@ -449,6 +459,13 @@
pr_err("%s: port not open: %d\n", __func__, bam_ch[id].status);
return -ENODEV;
}
+
+ if (bam_ch[id].use_wm &&
+ (bam_ch[id].num_tx_pkts >= HIGH_WATERMARK)) {
+ spin_unlock_irqrestore(&bam_ch[id].lock, flags);
+ pr_err("%s: watermark exceeded: %d\n", __func__, id);
+ return -EAGAIN;
+ }
spin_unlock_irqrestore(&bam_ch[id].lock, flags);
read_lock(&ul_wakeup_lock);
@@ -508,18 +525,24 @@
pkt->dma_address = dma_address;
pkt->is_cmd = 0;
INIT_WORK(&pkt->work, bam_mux_write_done);
- spin_lock(&bam_tx_pool_spinlock);
+ spin_lock_irqsave(&bam_tx_pool_spinlock, flags);
list_add_tail(&pkt->list_node, &bam_tx_pool);
- spin_unlock(&bam_tx_pool_spinlock);
+ spin_unlock_irqrestore(&bam_tx_pool_spinlock, flags);
rc = sps_transfer_one(bam_tx_pipe, dma_address, skb->len,
pkt, SPS_IOVEC_FLAG_INT | SPS_IOVEC_FLAG_EOT);
if (rc) {
DBG("%s sps_transfer_one failed rc=%d\n", __func__, rc);
- spin_lock(&bam_tx_pool_spinlock);
+ spin_lock_irqsave(&bam_tx_pool_spinlock, flags);
list_del(&pkt->list_node);
DBG_INC_TX_SPS_FAILURE_CNT();
- spin_unlock(&bam_tx_pool_spinlock);
+ spin_unlock_irqrestore(&bam_tx_pool_spinlock, flags);
kfree(pkt);
+ if (new_skb)
+ dev_kfree_skb_any(new_skb);
+ } else {
+ spin_lock_irqsave(&bam_ch[id].lock, flags);
+ bam_ch[id].num_tx_pkts++;
+ spin_unlock_irqrestore(&bam_ch[id].lock, flags);
}
ul_packet_written = 1;
read_unlock(&ul_wakeup_lock);
@@ -578,6 +601,8 @@
bam_ch[id].notify = notify;
bam_ch[id].priv = priv;
bam_ch[id].status |= BAM_CH_LOCAL_OPEN;
+ bam_ch[id].num_tx_pkts = 0;
+ bam_ch[id].use_wm = 0;
spin_unlock_irqrestore(&bam_ch[id].lock, flags);
read_lock(&ul_wakeup_lock);
@@ -655,6 +680,47 @@
return rc;
}
+int msm_bam_dmux_is_ch_full(uint32_t id)
+{
+ unsigned long flags;
+ int ret;
+
+ if (id >= BAM_DMUX_NUM_CHANNELS)
+ return -EINVAL;
+
+ spin_lock_irqsave(&bam_ch[id].lock, flags);
+ bam_ch[id].use_wm = 1;
+ ret = bam_ch[id].num_tx_pkts >= HIGH_WATERMARK;
+ DBG("%s: ch %d num tx pkts=%d, HWM=%d\n", __func__,
+ id, bam_ch[id].num_tx_pkts, ret);
+ if (!bam_ch_is_local_open(id)) {
+ ret = -ENODEV;
+ pr_err("%s: port not open: %d\n", __func__, bam_ch[id].status);
+ }
+ spin_unlock_irqrestore(&bam_ch[id].lock, flags);
+
+ return ret;
+}
+
+int msm_bam_dmux_is_ch_low(uint32_t id)
+{
+ int ret;
+
+ if (id >= BAM_DMUX_NUM_CHANNELS)
+ return -EINVAL;
+
+ bam_ch[id].use_wm = 1;
+ ret = bam_ch[id].num_tx_pkts <= LOW_WATERMARK;
+ DBG("%s: ch %d num tx pkts=%d, LWM=%d\n", __func__,
+ id, bam_ch[id].num_tx_pkts, ret);
+ if (!bam_ch_is_local_open(id)) {
+ ret = -ENODEV;
+ pr_err("%s: port not open: %d\n", __func__, bam_ch[id].status);
+ }
+
+ return ret;
+}
+
static void rx_timer_work_func(struct work_struct *work)
{
struct sps_iovec iov;
@@ -781,15 +847,7 @@
" not disabled\n", __func__);
break;
}
- rx_register_event.options = 0;
- ret = sps_register_event(bam_rx_pipe,
- &rx_register_event);
- if (ret) {
- pr_err("%s: sps_register_event ret = %d\n",
- __func__, ret);
- break;
- }
- cur_rx_conn.options = SPS_O_AUTO_ENABLE | SPS_O_EOT |
+ cur_rx_conn.options = SPS_O_AUTO_ENABLE |
SPS_O_ACK_TRANSFERS | SPS_O_POLL;
ret = sps_set_config(bam_rx_pipe, &cur_rx_conn);
if (ret) {
@@ -1026,6 +1084,7 @@
struct list_head *node;
struct tx_pkt_info *info;
int temp_remote_status;
+ unsigned long flags;
if (code != SUBSYS_AFTER_SHUTDOWN)
return NOTIFY_DONE;
@@ -1034,6 +1093,7 @@
for (i = 0; i < BAM_DMUX_NUM_CHANNELS; ++i) {
temp_remote_status = bam_ch_is_remote_open(i);
bam_ch[i].status &= ~BAM_CH_REMOTE_OPEN;
+ bam_ch[i].num_tx_pkts = 0;
if (bam_ch_is_local_open(i))
bam_ch[i].status |= BAM_CH_IN_RESET;
if (temp_remote_status) {
@@ -1043,7 +1103,7 @@
}
}
/*cleanup UL*/
- spin_lock(&bam_tx_pool_spinlock);
+ spin_lock_irqsave(&bam_tx_pool_spinlock, flags);
while (!list_empty(&bam_tx_pool)) {
node = bam_tx_pool.next;
list_del(node);
@@ -1062,7 +1122,7 @@
}
kfree(info);
}
- spin_unlock(&bam_tx_pool_spinlock);
+ spin_unlock_irqrestore(&bam_tx_pool_spinlock, flags);
smsm_change_state(SMSM_APPS_STATE, SMSM_A2_POWER_CONTROL, 0);
return NOTIFY_DONE;
diff --git a/arch/arm/mach-msm/board-apq8064-regulator.c b/arch/arm/mach-msm/board-8064-regulator.c
similarity index 97%
rename from arch/arm/mach-msm/board-apq8064-regulator.c
rename to arch/arm/mach-msm/board-8064-regulator.c
index 8448600..4873258 100644
--- a/arch/arm/mach-msm/board-apq8064-regulator.c
+++ b/arch/arm/mach-msm/board-8064-regulator.c
@@ -13,7 +13,7 @@
#include <linux/regulator/pm8921-regulator.h>
-#include "board-apq8064.h"
+#include "board-8064.h"
#define VREG_CONSUMERS(_id) \
static struct regulator_consumer_supply vreg_consumers_##_id[]
@@ -93,6 +93,8 @@
};
VREG_CONSUMERS(L25) = {
REGULATOR_SUPPLY("8921_l25", NULL),
+ REGULATOR_SUPPLY("VDDD_CDC_D", "tabla-slim"),
+ REGULATOR_SUPPLY("CDC_VDDA_A_1P2V", "tabla-slim"),
};
VREG_CONSUMERS(L26) = {
REGULATOR_SUPPLY("8921_l26", NULL),
@@ -118,6 +120,10 @@
VREG_CONSUMERS(S4) = {
REGULATOR_SUPPLY("8921_s4", NULL),
REGULATOR_SUPPLY("sdc_vccq", "msm_sdcc.1"),
+ REGULATOR_SUPPLY("VDDIO_CDC", "tabla-slim"),
+ REGULATOR_SUPPLY("CDC_VDD_CP", "tabla-slim"),
+ REGULATOR_SUPPLY("CDC_VDDA_TX", "tabla-slim"),
+ REGULATOR_SUPPLY("CDC_VDDA_RX", "tabla-slim"),
};
VREG_CONSUMERS(S5) = {
REGULATOR_SUPPLY("8921_s5", NULL),
diff --git a/arch/arm/mach-msm/board-8064-storage.c b/arch/arm/mach-msm/board-8064-storage.c
new file mode 100644
index 0000000..8a3b958
--- /dev/null
+++ b/arch/arm/mach-msm/board-8064-storage.c
@@ -0,0 +1,257 @@
+/* Copyright (c) 2011, Code Aurora Forum. 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 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#include <linux/init.h>
+#include <linux/ioport.h>
+#include <linux/platform_device.h>
+#include <linux/bootmem.h>
+#include <asm/mach-types.h>
+#include <asm/mach/mmc.h>
+#include <mach/msm_bus_board.h>
+#include <mach/board.h>
+#include <mach/gpio.h>
+#include <mach/gpiomux.h>
+#include "devices.h"
+#include "board-8064.h"
+
+
+/* APQ8064 has 4 SDCC controllers */
+enum sdcc_controllers {
+ SDCC1,
+ SDCC2,
+ SDCC3,
+ SDCC4,
+ MAX_SDCC_CONTROLLER
+};
+
+/* All SDCC controllers require VDD/VCC voltage */
+static struct msm_mmc_reg_data mmc_vdd_reg_data[MAX_SDCC_CONTROLLER] = {
+ /* SDCC1 : eMMC card connected */
+ [SDCC1] = {
+ .name = "sdc_vdd",
+ .high_vol_level = 2950000,
+ .low_vol_level = 2950000,
+ .always_on = 1,
+ .lpm_sup = 1,
+ .lpm_uA = 9000,
+ .hpm_uA = 200000, /* 200mA */
+ },
+ /* SDCC3 : External card slot connected */
+ [SDCC3] = {
+ .name = "sdc_vdd",
+ .high_vol_level = 2950000,
+ .low_vol_level = 2950000,
+ .hpm_uA = 600000, /* 600mA */
+ }
+};
+
+/* Only slots having eMMC card will require VCCQ voltage */
+static struct msm_mmc_reg_data mmc_vccq_reg_data[1] = {
+ /* SDCC1 : eMMC card connected */
+ [SDCC1] = {
+ .name = "sdc_vccq",
+ .always_on = 1,
+ .high_vol_level = 1800000,
+ .low_vol_level = 1800000,
+ .hpm_uA = 200000, /* 200mA */
+ }
+};
+
+/* All SDCC controllers may require voting for VDD PAD voltage */
+static struct msm_mmc_reg_data mmc_vddp_reg_data[MAX_SDCC_CONTROLLER] = {
+ /* SDCC3 : External card slot connected */
+ [SDCC3] = {
+ .name = "sdc_vddp",
+ .high_vol_level = 2950000,
+ .low_vol_level = 1850000,
+ .always_on = 1,
+ .lpm_sup = 1,
+ /* Max. Active current required is 16 mA */
+ .hpm_uA = 16000,
+ /*
+ * Sleep current required is ~300 uA. But min. vote can be
+ * in terms of mA (min. 1 mA). So let's vote for 2 mA
+ * during sleep.
+ */
+ .lpm_uA = 2000,
+ }
+};
+
+static struct msm_mmc_slot_reg_data mmc_slot_vreg_data[MAX_SDCC_CONTROLLER] = {
+ /* SDCC1 : eMMC card connected */
+ [SDCC1] = {
+ .vdd_data = &mmc_vdd_reg_data[SDCC1],
+ .vccq_data = &mmc_vccq_reg_data[SDCC1],
+ },
+ /* SDCC3 : External card slot connected */
+ [SDCC3] = {
+ .vdd_data = &mmc_vdd_reg_data[SDCC3],
+ .vddp_data = &mmc_vddp_reg_data[SDCC3],
+ }
+};
+
+/* SDC1 pad data */
+static struct msm_mmc_pad_drv sdc1_pad_drv_on_cfg[] = {
+ {TLMM_HDRV_SDC1_CLK, GPIO_CFG_16MA},
+ {TLMM_HDRV_SDC1_CMD, GPIO_CFG_10MA},
+ {TLMM_HDRV_SDC1_DATA, GPIO_CFG_10MA}
+};
+
+static struct msm_mmc_pad_drv sdc1_pad_drv_off_cfg[] = {
+ {TLMM_HDRV_SDC1_CLK, GPIO_CFG_2MA},
+ {TLMM_HDRV_SDC1_CMD, GPIO_CFG_2MA},
+ {TLMM_HDRV_SDC1_DATA, GPIO_CFG_2MA}
+};
+
+static struct msm_mmc_pad_pull sdc1_pad_pull_on_cfg[] = {
+ {TLMM_PULL_SDC1_CLK, GPIO_CFG_NO_PULL},
+ {TLMM_PULL_SDC1_CMD, GPIO_CFG_PULL_UP},
+ {TLMM_PULL_SDC1_DATA, GPIO_CFG_PULL_UP}
+};
+
+static struct msm_mmc_pad_pull sdc1_pad_pull_off_cfg[] = {
+ {TLMM_PULL_SDC1_CLK, GPIO_CFG_NO_PULL},
+ {TLMM_PULL_SDC1_CMD, GPIO_CFG_PULL_DOWN},
+ {TLMM_PULL_SDC1_DATA, GPIO_CFG_PULL_DOWN}
+};
+
+/* SDC3 pad data */
+static struct msm_mmc_pad_drv sdc3_pad_drv_on_cfg[] = {
+ {TLMM_HDRV_SDC3_CLK, GPIO_CFG_8MA},
+ {TLMM_HDRV_SDC3_CMD, GPIO_CFG_8MA},
+ {TLMM_HDRV_SDC3_DATA, GPIO_CFG_8MA}
+};
+
+static struct msm_mmc_pad_drv sdc3_pad_drv_off_cfg[] = {
+ {TLMM_HDRV_SDC3_CLK, GPIO_CFG_2MA},
+ {TLMM_HDRV_SDC3_CMD, GPIO_CFG_2MA},
+ {TLMM_HDRV_SDC3_DATA, GPIO_CFG_2MA}
+};
+
+static struct msm_mmc_pad_pull sdc3_pad_pull_on_cfg[] = {
+ {TLMM_PULL_SDC3_CLK, GPIO_CFG_NO_PULL},
+ {TLMM_PULL_SDC3_CMD, GPIO_CFG_PULL_UP},
+ {TLMM_PULL_SDC3_DATA, GPIO_CFG_PULL_UP}
+};
+
+static struct msm_mmc_pad_pull sdc3_pad_pull_off_cfg[] = {
+ {TLMM_PULL_SDC3_CLK, GPIO_CFG_NO_PULL},
+ {TLMM_PULL_SDC3_CMD, GPIO_CFG_PULL_DOWN},
+ {TLMM_PULL_SDC3_DATA, GPIO_CFG_PULL_DOWN}
+};
+
+static struct msm_mmc_pad_pull_data mmc_pad_pull_data[MAX_SDCC_CONTROLLER] = {
+ [SDCC1] = {
+ .on = sdc1_pad_pull_on_cfg,
+ .off = sdc1_pad_pull_off_cfg,
+ .size = ARRAY_SIZE(sdc1_pad_pull_on_cfg)
+ },
+ [SDCC3] = {
+ .on = sdc3_pad_pull_on_cfg,
+ .off = sdc3_pad_pull_off_cfg,
+ .size = ARRAY_SIZE(sdc3_pad_pull_on_cfg)
+ },
+};
+
+static struct msm_mmc_pad_drv_data mmc_pad_drv_data[MAX_SDCC_CONTROLLER] = {
+ [SDCC1] = {
+ .on = sdc1_pad_drv_on_cfg,
+ .off = sdc1_pad_drv_off_cfg,
+ .size = ARRAY_SIZE(sdc1_pad_drv_on_cfg)
+ },
+ [SDCC3] = {
+ .on = sdc3_pad_drv_on_cfg,
+ .off = sdc3_pad_drv_off_cfg,
+ .size = ARRAY_SIZE(sdc3_pad_drv_on_cfg)
+ },
+};
+
+static struct msm_mmc_pad_data mmc_pad_data[MAX_SDCC_CONTROLLER] = {
+ [SDCC1] = {
+ .pull = &mmc_pad_pull_data[SDCC1],
+ .drv = &mmc_pad_drv_data[SDCC1]
+ },
+ [SDCC3] = {
+ .pull = &mmc_pad_pull_data[SDCC3],
+ .drv = &mmc_pad_drv_data[SDCC3]
+ },
+};
+
+static struct msm_mmc_pin_data mmc_slot_pin_data[MAX_SDCC_CONTROLLER] = {
+ [SDCC1] = {
+ .pad_data = &mmc_pad_data[SDCC1],
+ },
+ [SDCC3] = {
+ .pad_data = &mmc_pad_data[SDCC3],
+ },
+};
+
+#ifdef CONFIG_MMC_MSM_SDC1_SUPPORT
+static unsigned int sdc1_sup_clk_rates[] = {
+ 400000, 24000000, 48000000, 96000000
+};
+
+static struct mmc_platform_data sdc1_data = {
+ .ocr_mask = MMC_VDD_27_28 | MMC_VDD_28_29,
+#ifdef CONFIG_MMC_MSM_SDC1_8_BIT_SUPPORT
+ .mmc_bus_width = MMC_CAP_8_BIT_DATA,
+#else
+ .mmc_bus_width = MMC_CAP_4_BIT_DATA,
+#endif
+ .sup_clk_table = sdc1_sup_clk_rates,
+ .sup_clk_cnt = ARRAY_SIZE(sdc1_sup_clk_rates),
+ .pin_data = &mmc_slot_pin_data[SDCC1],
+ .vreg_data = &mmc_slot_vreg_data[SDCC1],
+};
+static struct mmc_platform_data *apq8064_sdc1_pdata = &sdc1_data;
+#else
+static struct mmc_platform_data *apq8064_sdc1_pdata;
+#endif
+
+#ifdef CONFIG_MMC_MSM_SDC3_SUPPORT
+static unsigned int sdc3_sup_clk_rates[] = {
+ 400000, 24000000, 48000000, 96000000
+};
+
+static struct mmc_platform_data sdc3_data = {
+ .ocr_mask = MMC_VDD_27_28 | MMC_VDD_28_29,
+ .mmc_bus_width = MMC_CAP_4_BIT_DATA,
+ .sup_clk_table = sdc3_sup_clk_rates,
+ .sup_clk_cnt = ARRAY_SIZE(sdc3_sup_clk_rates),
+ .pin_data = &mmc_slot_pin_data[SDCC3],
+ .vreg_data = &mmc_slot_vreg_data[SDCC3],
+};
+static struct mmc_platform_data *apq8064_sdc3_pdata = &sdc3_data;
+#else
+static struct mmc_platform_data *apq8064_sdc3_pdata;
+#endif
+
+void __init apq8064_init_mmc(void)
+{
+ if ((machine_is_apq8064_rumi3()) || machine_is_apq8064_sim()) {
+ if (apq8064_sdc1_pdata) {
+ if (machine_is_apq8064_sim())
+ apq8064_sdc1_pdata->disable_bam = true;
+ apq8064_sdc1_pdata->disable_runtime_pm = true;
+ apq8064_sdc1_pdata->disable_cmd23 = true;
+ }
+ if (apq8064_sdc3_pdata) {
+ if (machine_is_apq8064_sim())
+ apq8064_sdc3_pdata->disable_bam = true;
+ apq8064_sdc3_pdata->disable_runtime_pm = true;
+ apq8064_sdc3_pdata->disable_cmd23 = true;
+ }
+ }
+ apq8064_add_sdcc(1, apq8064_sdc1_pdata);
+ apq8064_add_sdcc(3, apq8064_sdc3_pdata);
+}
diff --git a/arch/arm/mach-msm/board-apq8064.c b/arch/arm/mach-msm/board-8064.c
similarity index 73%
rename from arch/arm/mach-msm/board-apq8064.c
rename to arch/arm/mach-msm/board-8064.c
index 53c290e..6e2c044 100644
--- a/arch/arm/mach-msm/board-apq8064.c
+++ b/arch/arm/mach-msm/board-8064.c
@@ -16,6 +16,8 @@
#include <linux/irq.h>
#include <linux/i2c.h>
#include <linux/slimbus/slimbus.h>
+#include <linux/mfd/wcd9310/core.h>
+#include <linux/mfd/wcd9310/pdata.h>
#include <linux/msm_ssbi.h>
#include <linux/spi/spi.h>
#include <linux/dma-mapping.h>
@@ -42,7 +44,7 @@
#include <mach/dma.h>
#include "msm_watchdog.h"
-#include "board-apq8064.h"
+#include "board-8064.h"
#define MSM_PMEM_KERNEL_EBI1_SIZE 0x600000
#define MSM_PMEM_ADSP_SIZE 0x3800000
@@ -217,237 +219,46 @@
.pclk_src_name = "dfab_usb_hs_clk",
};
-/* APQ8064 has 4 SDCC controllers */
-enum sdcc_controllers {
- SDCC1,
- SDCC2,
- SDCC3,
- SDCC4,
- MAX_SDCC_CONTROLLER
-};
+#define TABLA_INTERRUPT_BASE (NR_MSM_IRQS + NR_GPIO_IRQS + NR_PM8921_IRQS)
-/* All SDCC controllers require VDD/VCC voltage */
-static struct msm_mmc_reg_data mmc_vdd_reg_data[MAX_SDCC_CONTROLLER] = {
- /* SDCC1 : eMMC card connected */
- [SDCC1] = {
- .name = "sdc_vdd",
- .high_vol_level = 2950000,
- .low_vol_level = 2950000,
- .always_on = 1,
- .lpm_sup = 1,
- .lpm_uA = 9000,
- .hpm_uA = 200000, /* 200mA */
+/* Micbias setting is based on 8660 CDP/MTP/FLUID requirement
+ * 4 micbiases are used to power various analog and digital
+ * microphones operating at 1800 mV. Technically, all micbiases
+ * can source from single cfilter since all microphones operate
+ * at the same voltage level. The arrangement below is to make
+ * sure all cfilters are exercised. LDO_H regulator ouput level
+ * does not need to be as high as 2.85V. It is choosen for
+ * microphone sensitivity purpose.
+ */
+static struct tabla_pdata apq8064_tabla_platform_data = {
+ .slimbus_slave_device = {
+ .name = "tabla-slave",
+ .e_addr = {0, 0, 0x10, 0, 0x17, 2},
},
- /* SDCC3 : External card slot connected */
- [SDCC3] = {
- .name = "sdc_vdd",
- .high_vol_level = 2950000,
- .low_vol_level = 2950000,
- .hpm_uA = 600000, /* 600mA */
+ .irq = MSM_GPIO_TO_INT(62),
+ .irq_base = TABLA_INTERRUPT_BASE,
+ .num_irqs = NR_TABLA_IRQS,
+ .reset_gpio = PM8921_GPIO_PM_TO_SYS(34),
+ .micbias = {
+ .ldoh_v = TABLA_LDOH_2P85_V,
+ .cfilt1_mv = 1800,
+ .cfilt2_mv = 1800,
+ .cfilt3_mv = 1800,
+ .bias1_cfilt_sel = TABLA_CFILT1_SEL,
+ .bias2_cfilt_sel = TABLA_CFILT2_SEL,
+ .bias3_cfilt_sel = TABLA_CFILT3_SEL,
+ .bias4_cfilt_sel = TABLA_CFILT3_SEL,
}
};
-/* Only slots having eMMC card will require VCCQ voltage */
-static struct msm_mmc_reg_data mmc_vccq_reg_data[1] = {
- /* SDCC1 : eMMC card connected */
- [SDCC1] = {
- .name = "sdc_vccq",
- .always_on = 1,
- .high_vol_level = 1800000,
- .low_vol_level = 1800000,
- .hpm_uA = 200000, /* 200mA */
- }
-};
-
-/* All SDCC controllers may require voting for VDD PAD voltage */
-static struct msm_mmc_reg_data mmc_vddp_reg_data[MAX_SDCC_CONTROLLER] = {
- /* SDCC3 : External card slot connected */
- [SDCC3] = {
- .name = "sdc_vddp",
- .high_vol_level = 2950000,
- .low_vol_level = 1850000,
- .always_on = 1,
- .lpm_sup = 1,
- /* Max. Active current required is 16 mA */
- .hpm_uA = 16000,
- /*
- * Sleep current required is ~300 uA. But min. vote can be
- * in terms of mA (min. 1 mA). So let's vote for 2 mA
- * during sleep.
- */
- .lpm_uA = 2000,
- }
-};
-
-static struct msm_mmc_slot_reg_data mmc_slot_vreg_data[MAX_SDCC_CONTROLLER] = {
- /* SDCC1 : eMMC card connected */
- [SDCC1] = {
- .vdd_data = &mmc_vdd_reg_data[SDCC1],
- .vccq_data = &mmc_vccq_reg_data[SDCC1],
- },
- /* SDCC3 : External card slot connected */
- [SDCC3] = {
- .vdd_data = &mmc_vdd_reg_data[SDCC3],
- .vddp_data = &mmc_vddp_reg_data[SDCC3],
- }
-};
-
-/* SDC1 pad data */
-static struct msm_mmc_pad_drv sdc1_pad_drv_on_cfg[] = {
- {TLMM_HDRV_SDC1_CLK, GPIO_CFG_16MA},
- {TLMM_HDRV_SDC1_CMD, GPIO_CFG_10MA},
- {TLMM_HDRV_SDC1_DATA, GPIO_CFG_10MA}
-};
-
-static struct msm_mmc_pad_drv sdc1_pad_drv_off_cfg[] = {
- {TLMM_HDRV_SDC1_CLK, GPIO_CFG_2MA},
- {TLMM_HDRV_SDC1_CMD, GPIO_CFG_2MA},
- {TLMM_HDRV_SDC1_DATA, GPIO_CFG_2MA}
-};
-
-static struct msm_mmc_pad_pull sdc1_pad_pull_on_cfg[] = {
- {TLMM_PULL_SDC1_CLK, GPIO_CFG_NO_PULL},
- {TLMM_PULL_SDC1_CMD, GPIO_CFG_PULL_UP},
- {TLMM_PULL_SDC1_DATA, GPIO_CFG_PULL_UP}
-};
-
-static struct msm_mmc_pad_pull sdc1_pad_pull_off_cfg[] = {
- {TLMM_PULL_SDC1_CLK, GPIO_CFG_NO_PULL},
- {TLMM_PULL_SDC1_CMD, GPIO_CFG_PULL_DOWN},
- {TLMM_PULL_SDC1_DATA, GPIO_CFG_PULL_DOWN}
-};
-
-/* SDC3 pad data */
-static struct msm_mmc_pad_drv sdc3_pad_drv_on_cfg[] = {
- {TLMM_HDRV_SDC3_CLK, GPIO_CFG_8MA},
- {TLMM_HDRV_SDC3_CMD, GPIO_CFG_8MA},
- {TLMM_HDRV_SDC3_DATA, GPIO_CFG_8MA}
-};
-
-static struct msm_mmc_pad_drv sdc3_pad_drv_off_cfg[] = {
- {TLMM_HDRV_SDC3_CLK, GPIO_CFG_2MA},
- {TLMM_HDRV_SDC3_CMD, GPIO_CFG_2MA},
- {TLMM_HDRV_SDC3_DATA, GPIO_CFG_2MA}
-};
-
-static struct msm_mmc_pad_pull sdc3_pad_pull_on_cfg[] = {
- {TLMM_PULL_SDC3_CLK, GPIO_CFG_NO_PULL},
- {TLMM_PULL_SDC3_CMD, GPIO_CFG_PULL_UP},
- {TLMM_PULL_SDC3_DATA, GPIO_CFG_PULL_UP}
-};
-
-static struct msm_mmc_pad_pull sdc3_pad_pull_off_cfg[] = {
- {TLMM_PULL_SDC3_CLK, GPIO_CFG_NO_PULL},
- {TLMM_PULL_SDC3_CMD, GPIO_CFG_PULL_DOWN},
- {TLMM_PULL_SDC3_DATA, GPIO_CFG_PULL_DOWN}
-};
-
-static struct msm_mmc_pad_pull_data mmc_pad_pull_data[MAX_SDCC_CONTROLLER] = {
- [SDCC1] = {
- .on = sdc1_pad_pull_on_cfg,
- .off = sdc1_pad_pull_off_cfg,
- .size = ARRAY_SIZE(sdc1_pad_pull_on_cfg)
- },
- [SDCC3] = {
- .on = sdc3_pad_pull_on_cfg,
- .off = sdc3_pad_pull_off_cfg,
- .size = ARRAY_SIZE(sdc3_pad_pull_on_cfg)
+static struct slim_device apq8064_slim_tabla = {
+ .name = "tabla-slim",
+ .e_addr = {0, 1, 0x10, 0, 0x17, 2},
+ .dev = {
+ .platform_data = &apq8064_tabla_platform_data,
},
};
-static struct msm_mmc_pad_drv_data mmc_pad_drv_data[MAX_SDCC_CONTROLLER] = {
- [SDCC1] = {
- .on = sdc1_pad_drv_on_cfg,
- .off = sdc1_pad_drv_off_cfg,
- .size = ARRAY_SIZE(sdc1_pad_drv_on_cfg)
- },
- [SDCC3] = {
- .on = sdc3_pad_drv_on_cfg,
- .off = sdc3_pad_drv_off_cfg,
- .size = ARRAY_SIZE(sdc3_pad_drv_on_cfg)
- },
-};
-
-static struct msm_mmc_pad_data mmc_pad_data[MAX_SDCC_CONTROLLER] = {
- [SDCC1] = {
- .pull = &mmc_pad_pull_data[SDCC1],
- .drv = &mmc_pad_drv_data[SDCC1]
- },
- [SDCC3] = {
- .pull = &mmc_pad_pull_data[SDCC3],
- .drv = &mmc_pad_drv_data[SDCC3]
- },
-};
-
-static struct msm_mmc_pin_data mmc_slot_pin_data[MAX_SDCC_CONTROLLER] = {
- [SDCC1] = {
- .pad_data = &mmc_pad_data[SDCC1],
- },
- [SDCC3] = {
- .pad_data = &mmc_pad_data[SDCC3],
- },
-};
-
-#ifdef CONFIG_MMC_MSM_SDC1_SUPPORT
-static unsigned int sdc1_sup_clk_rates[] = {
- 400000, 24000000, 48000000, 96000000
-};
-
-static struct mmc_platform_data sdc1_data = {
- .ocr_mask = MMC_VDD_27_28 | MMC_VDD_28_29,
-#ifdef CONFIG_MMC_MSM_SDC1_8_BIT_SUPPORT
- .mmc_bus_width = MMC_CAP_8_BIT_DATA,
-#else
- .mmc_bus_width = MMC_CAP_4_BIT_DATA,
-#endif
- .sup_clk_table = sdc1_sup_clk_rates,
- .sup_clk_cnt = ARRAY_SIZE(sdc1_sup_clk_rates),
- .pin_data = &mmc_slot_pin_data[SDCC1],
- .vreg_data = &mmc_slot_vreg_data[SDCC1],
-};
-static struct mmc_platform_data *apq8064_sdc1_pdata = &sdc1_data;
-#else
-static struct mmc_platform_data *apq8064_sdc1_pdata;
-#endif
-
-#ifdef CONFIG_MMC_MSM_SDC3_SUPPORT
-static unsigned int sdc3_sup_clk_rates[] = {
- 400000, 24000000, 48000000, 96000000
-};
-
-static struct mmc_platform_data sdc3_data = {
- .ocr_mask = MMC_VDD_27_28 | MMC_VDD_28_29,
- .mmc_bus_width = MMC_CAP_4_BIT_DATA,
- .sup_clk_table = sdc3_sup_clk_rates,
- .sup_clk_cnt = ARRAY_SIZE(sdc3_sup_clk_rates),
- .pin_data = &mmc_slot_pin_data[SDCC3],
- .vreg_data = &mmc_slot_vreg_data[SDCC3],
-};
-static struct mmc_platform_data *apq8064_sdc3_pdata = &sdc3_data;
-#else
-static struct mmc_platform_data *apq8064_sdc3_pdata;
-#endif
-
-static void __init apq8064_init_mmc(void)
-{
- if ((machine_is_apq8064_rumi3()) || machine_is_apq8064_sim()) {
- if (apq8064_sdc1_pdata) {
- if (machine_is_apq8064_sim())
- apq8064_sdc1_pdata->disable_bam = true;
- apq8064_sdc1_pdata->disable_runtime_pm = true;
- apq8064_sdc1_pdata->disable_cmd23 = true;
- }
- if (apq8064_sdc3_pdata) {
- if (machine_is_apq8064_sim())
- apq8064_sdc3_pdata->disable_bam = true;
- apq8064_sdc3_pdata->disable_runtime_pm = true;
- apq8064_sdc3_pdata->disable_cmd23 = true;
- }
- }
- apq8064_add_sdcc(1, apq8064_sdc1_pdata);
- apq8064_add_sdcc(3, apq8064_sdc3_pdata);
-}
-
#if defined(CONFIG_CRYPTO_DEV_QCRYPTO) || \
defined(CONFIG_CRYPTO_DEV_QCRYPTO_MODULE) || \
defined(CONFIG_CRYPTO_DEV_QCEDEV) || \
@@ -652,6 +463,31 @@
defined(CONFIG_CRYPTO_DEV_QCEDEV_MODULE)
&qcedev_device,
#endif
+
+#ifdef CONFIG_HW_RANDOM_MSM
+ &apq8064_device_rng,
+#endif
+ &msm_pcm,
+ &msm_pcm_routing,
+ &msm_cpudai0,
+ &msm_cpudai1,
+ &msm_cpudai_hdmi_rx,
+ &msm_cpudai_bt_rx,
+ &msm_cpudai_bt_tx,
+ &msm_cpudai_fm_rx,
+ &msm_cpudai_fm_tx,
+ &msm_cpu_fe,
+ &msm_stub_codec,
+ &msm_voice,
+ &msm_voip,
+ &msm_lpa_pcm,
+ &msm_cpudai_afe_01_rx,
+ &msm_cpudai_afe_01_tx,
+ &msm_cpudai_afe_02_rx,
+ &msm_cpudai_afe_02_tx,
+ &msm_pcm_afe,
+ &msm_cpudai_auxpcm_rx,
+ &msm_cpudai_auxpcm_tx,
};
static struct platform_device *sim_devices[] __initdata = {
@@ -662,6 +498,10 @@
static struct platform_device *rumi3_devices[] __initdata = {
&apq8064_device_uart_gsbi1,
&msm_device_sps_apq8064,
+ &msm_cpudai_bt_rx,
+ &msm_cpudai_bt_tx,
+ &msm_cpudai_fm_rx,
+ &msm_cpudai_fm_tx,
};
static struct msm_spi_platform_data apq8064_qup_spi_gsbi5_pdata = {
@@ -806,7 +646,11 @@
};
static struct slim_boardinfo apq8064_slim_devices[] = {
- /* Add slimbus slaves as needed */
+ {
+ .bus_num = 1,
+ .slim_slave = &apq8064_slim_tabla,
+ },
+ /* add more slimbus slaves as needed */
};
static struct msm_i2c_platform_data apq8064_i2c_qup_gsbi4_pdata = {
@@ -814,6 +658,52 @@
.src_clk_rate = 24000000,
};
+
+static struct gpiomux_setting audio_auxpcm[] = {
+ /* Suspended state */
+ {
+ .func = GPIOMUX_FUNC_GPIO,
+ .drv = GPIOMUX_DRV_2MA,
+ .pull = GPIOMUX_PULL_NONE,
+ },
+ /* Active state */
+ {
+ .func = GPIOMUX_FUNC_1,
+ .drv = GPIOMUX_DRV_2MA,
+ .pull = GPIOMUX_PULL_NONE,
+ },
+};
+static struct msm_gpiomux_config apq8064_audio_auxpcm_configs[] __initdata = {
+ {
+ .gpio = 43,
+ .settings = {
+ [GPIOMUX_SUSPENDED] = &audio_auxpcm[0],
+ [GPIOMUX_ACTIVE] = &audio_auxpcm[1],
+ },
+ },
+ {
+ .gpio = 44,
+ .settings = {
+ [GPIOMUX_SUSPENDED] = &audio_auxpcm[0],
+ [GPIOMUX_ACTIVE] = &audio_auxpcm[1],
+ },
+ },
+ {
+ .gpio = 45,
+ .settings = {
+ [GPIOMUX_SUSPENDED] = &audio_auxpcm[0],
+ [GPIOMUX_ACTIVE] = &audio_auxpcm[1],
+ },
+ },
+ {
+ .gpio = 46,
+ .settings = {
+ [GPIOMUX_SUSPENDED] = &audio_auxpcm[0],
+ [GPIOMUX_ACTIVE] = &audio_auxpcm[1],
+ },
+ },
+};
+
static void __init apq8064_i2c_init(void)
{
apq8064_device_qup_i2c_gsbi4.dev.platform_data =
@@ -834,6 +724,8 @@
msm_gpiomux_install(apq8064_gsbi_configs,
ARRAY_SIZE(apq8064_gsbi_configs));
+ msm_gpiomux_install(apq8064_audio_auxpcm_configs,
+ ARRAY_SIZE(apq8064_audio_auxpcm_configs));
return 0;
}
diff --git a/arch/arm/mach-msm/board-apq8064.h b/arch/arm/mach-msm/board-8064.h
similarity index 98%
rename from arch/arm/mach-msm/board-apq8064.h
rename to arch/arm/mach-msm/board-8064.h
index 0928a58..d9da00a 100644
--- a/arch/arm/mach-msm/board-apq8064.h
+++ b/arch/arm/mach-msm/board-8064.h
@@ -41,4 +41,5 @@
int __init apq8064_add_sdcc(unsigned int controller,
struct mmc_platform_data *plat);
+void apq8064_init_mmc(void);
#endif
diff --git a/arch/arm/mach-msm/board-8930-camera.c b/arch/arm/mach-msm/board-8930-camera.c
new file mode 100644
index 0000000..9161fbf
--- /dev/null
+++ b/arch/arm/mach-msm/board-8930-camera.c
@@ -0,0 +1,470 @@
+/* Copyright (c) 2011, Code Aurora Forum. 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 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#include <linux/i2c.h>
+#include <linux/i2c/sx150x.h>
+#include <asm/mach-types.h>
+#include <mach/board.h>
+#include <mach/msm_bus_board.h>
+#include <mach/gpio.h>
+#include <mach/gpiomux.h>
+#include "devices.h"
+#include "board-8930.h"
+
+#if (defined(CONFIG_GPIO_SX150X) || defined(CONFIG_GPIO_SX150X_MODULE)) && \
+ defined(CONFIG_I2C)
+
+static struct i2c_board_info cam_expander_i2c_info[] = {
+ {
+ I2C_BOARD_INFO("sx1508q", 0x22),
+ .platform_data = &msm8930_sx150x_data[SX150X_CAM]
+ },
+};
+
+static struct msm_cam_expander_info cam_expander_info[] = {
+ {
+ cam_expander_i2c_info,
+ MSM_8930_GSBI4_QUP_I2C_BUS_ID,
+ },
+};
+#endif
+
+static struct gpiomux_setting cam_settings[] = {
+ {
+ .func = GPIOMUX_FUNC_GPIO, /*suspend*/
+ .drv = GPIOMUX_DRV_2MA,
+ .pull = GPIOMUX_PULL_DOWN,
+ },
+
+ {
+ .func = GPIOMUX_FUNC_1, /*active 1*/
+ .drv = GPIOMUX_DRV_2MA,
+ .pull = GPIOMUX_PULL_NONE,
+ },
+
+ {
+ .func = GPIOMUX_FUNC_GPIO, /*active 2*/
+ .drv = GPIOMUX_DRV_2MA,
+ .pull = GPIOMUX_PULL_NONE,
+ },
+
+ {
+ .func = GPIOMUX_FUNC_1, /*active 3*/
+ .drv = GPIOMUX_DRV_8MA,
+ .pull = GPIOMUX_PULL_NONE,
+ },
+
+ {
+ .func = GPIOMUX_FUNC_5, /*active 4*/
+ .drv = GPIOMUX_DRV_8MA,
+ .pull = GPIOMUX_PULL_UP,
+ },
+
+ {
+ .func = GPIOMUX_FUNC_6, /*active 5*/
+ .drv = GPIOMUX_DRV_8MA,
+ .pull = GPIOMUX_PULL_UP,
+ },
+
+ {
+ .func = GPIOMUX_FUNC_2, /*active 6*/
+ .drv = GPIOMUX_DRV_2MA,
+ .pull = GPIOMUX_PULL_UP,
+ },
+
+ {
+ .func = GPIOMUX_FUNC_3, /*active 7*/
+ .drv = GPIOMUX_DRV_8MA,
+ .pull = GPIOMUX_PULL_UP,
+ },
+
+ {
+ .func = GPIOMUX_FUNC_GPIO, /*i2c suspend*/
+ .drv = GPIOMUX_DRV_2MA,
+ .pull = GPIOMUX_PULL_KEEPER,
+ },
+
+};
+
+
+static struct msm_gpiomux_config msm8960_cam_common_configs[] = {
+ {
+ .gpio = 2,
+ .settings = {
+ [GPIOMUX_ACTIVE] = &cam_settings[2],
+ [GPIOMUX_SUSPENDED] = &cam_settings[0],
+ },
+ },
+ {
+ .gpio = 3,
+ .settings = {
+ [GPIOMUX_ACTIVE] = &cam_settings[1],
+ [GPIOMUX_SUSPENDED] = &cam_settings[0],
+ },
+ },
+ {
+ .gpio = 4,
+ .settings = {
+ [GPIOMUX_ACTIVE] = &cam_settings[1],
+ [GPIOMUX_SUSPENDED] = &cam_settings[0],
+ },
+ },
+ {
+ .gpio = 5,
+ .settings = {
+ [GPIOMUX_ACTIVE] = &cam_settings[1],
+ [GPIOMUX_SUSPENDED] = &cam_settings[0],
+ },
+ },
+ {
+ .gpio = 76,
+ .settings = {
+ [GPIOMUX_ACTIVE] = &cam_settings[2],
+ [GPIOMUX_SUSPENDED] = &cam_settings[0],
+ },
+ },
+ {
+ .gpio = 107,
+ .settings = {
+ [GPIOMUX_ACTIVE] = &cam_settings[2],
+ [GPIOMUX_SUSPENDED] = &cam_settings[0],
+ },
+ },
+};
+
+static struct msm_gpiomux_config msm8960_cam_2d_configs[] = {
+ {
+ .gpio = 18,
+ .settings = {
+ [GPIOMUX_ACTIVE] = &cam_settings[3],
+ [GPIOMUX_SUSPENDED] = &cam_settings[8],
+ },
+ },
+ {
+ .gpio = 19,
+ .settings = {
+ [GPIOMUX_ACTIVE] = &cam_settings[3],
+ [GPIOMUX_SUSPENDED] = &cam_settings[8],
+ },
+ },
+ {
+ .gpio = 20,
+ .settings = {
+ [GPIOMUX_ACTIVE] = &cam_settings[3],
+ [GPIOMUX_SUSPENDED] = &cam_settings[8],
+ },
+ },
+ {
+ .gpio = 21,
+ .settings = {
+ [GPIOMUX_ACTIVE] = &cam_settings[3],
+ [GPIOMUX_SUSPENDED] = &cam_settings[8],
+ },
+ },
+};
+
+#ifdef CONFIG_MSM_CAMERA
+
+static uint16_t msm_cam_gpio_2d_tbl[] = {
+ 5, /*CAMIF_MCLK*/
+ 20, /*CAMIF_I2C_DATA*/
+ 21, /*CAMIF_I2C_CLK*/
+};
+
+static struct msm_camera_gpio_conf gpio_conf = {
+ .cam_gpiomux_conf_tbl = msm8960_cam_2d_configs,
+ .cam_gpiomux_conf_tbl_size = ARRAY_SIZE(msm8960_cam_2d_configs),
+ .cam_gpio_tbl = msm_cam_gpio_2d_tbl,
+ .cam_gpio_tbl_size = ARRAY_SIZE(msm_cam_gpio_2d_tbl),
+};
+
+#define VFE_CAMIF_TIMER1_GPIO 2
+#define VFE_CAMIF_TIMER2_GPIO 3
+#define VFE_CAMIF_TIMER3_GPIO_INT 4
+static struct msm_camera_sensor_strobe_flash_data strobe_flash_xenon = {
+ .flash_trigger = VFE_CAMIF_TIMER2_GPIO,
+ .flash_charge = VFE_CAMIF_TIMER1_GPIO,
+ .flash_charge_done = VFE_CAMIF_TIMER3_GPIO_INT,
+ .flash_recharge_duration = 50000,
+ .irq = MSM_GPIO_TO_INT(VFE_CAMIF_TIMER3_GPIO_INT),
+};
+
+#ifdef CONFIG_MSM_CAMERA_FLASH
+static struct msm_camera_sensor_flash_src msm_flash_src = {
+ .flash_sr_type = MSM_CAMERA_FLASH_SRC_EXT,
+ ._fsrc.ext_driver_src.led_en = GPIO_CAM_GP_LED_EN1,
+ ._fsrc.ext_driver_src.led_flash_en = GPIO_CAM_GP_LED_EN2,
+#if defined(CONFIG_I2C) && (defined(CONFIG_GPIO_SX150X) || \
+ defined(CONFIG_GPIO_SX150X_MODULE))
+ ._fsrc.ext_driver_src.expander_info = cam_expander_info,
+#endif
+};
+#endif
+
+static struct msm_bus_vectors cam_init_vectors[] = {
+ {
+ .src = MSM_BUS_MASTER_VFE,
+ .dst = MSM_BUS_SLAVE_EBI_CH0,
+ .ab = 0,
+ .ib = 0,
+ },
+ {
+ .src = MSM_BUS_MASTER_VPE,
+ .dst = MSM_BUS_SLAVE_EBI_CH0,
+ .ab = 0,
+ .ib = 0,
+ },
+ {
+ .src = MSM_BUS_MASTER_JPEG_ENC,
+ .dst = MSM_BUS_SLAVE_EBI_CH0,
+ .ab = 0,
+ .ib = 0,
+ },
+};
+
+static struct msm_bus_vectors cam_preview_vectors[] = {
+ {
+ .src = MSM_BUS_MASTER_VFE,
+ .dst = MSM_BUS_SLAVE_EBI_CH0,
+ .ab = 27648000,
+ .ib = 110592000,
+ },
+ {
+ .src = MSM_BUS_MASTER_VPE,
+ .dst = MSM_BUS_SLAVE_EBI_CH0,
+ .ab = 0,
+ .ib = 0,
+ },
+ {
+ .src = MSM_BUS_MASTER_JPEG_ENC,
+ .dst = MSM_BUS_SLAVE_EBI_CH0,
+ .ab = 0,
+ .ib = 0,
+ },
+};
+
+static struct msm_bus_vectors cam_video_vectors[] = {
+ {
+ .src = MSM_BUS_MASTER_VFE,
+ .dst = MSM_BUS_SLAVE_EBI_CH0,
+ .ab = 140451840,
+ .ib = 561807360,
+ },
+ {
+ .src = MSM_BUS_MASTER_VPE,
+ .dst = MSM_BUS_SLAVE_EBI_CH0,
+ .ab = 206807040,
+ .ib = 488816640,
+ },
+ {
+ .src = MSM_BUS_MASTER_JPEG_ENC,
+ .dst = MSM_BUS_SLAVE_EBI_CH0,
+ .ab = 0,
+ .ib = 0,
+ },
+};
+
+static struct msm_bus_vectors cam_snapshot_vectors[] = {
+ {
+ .src = MSM_BUS_MASTER_VFE,
+ .dst = MSM_BUS_SLAVE_EBI_CH0,
+ .ab = 274423680,
+ .ib = 1097694720,
+ },
+ {
+ .src = MSM_BUS_MASTER_VPE,
+ .dst = MSM_BUS_SLAVE_EBI_CH0,
+ .ab = 0,
+ .ib = 0,
+ },
+ {
+ .src = MSM_BUS_MASTER_JPEG_ENC,
+ .dst = MSM_BUS_SLAVE_EBI_CH0,
+ .ab = 540000000,
+ .ib = 1350000000,
+ },
+};
+
+static struct msm_bus_vectors cam_zsl_vectors[] = {
+ {
+ .src = MSM_BUS_MASTER_VFE,
+ .dst = MSM_BUS_SLAVE_EBI_CH0,
+ .ab = 302071680,
+ .ib = 1208286720,
+ },
+ {
+ .src = MSM_BUS_MASTER_VPE,
+ .dst = MSM_BUS_SLAVE_EBI_CH0,
+ .ab = 0,
+ .ib = 0,
+ },
+ {
+ .src = MSM_BUS_MASTER_JPEG_ENC,
+ .dst = MSM_BUS_SLAVE_EBI_CH0,
+ .ab = 540000000,
+ .ib = 1350000000,
+ },
+};
+
+static struct msm_bus_paths cam_bus_client_config[] = {
+ {
+ ARRAY_SIZE(cam_init_vectors),
+ cam_init_vectors,
+ },
+ {
+ ARRAY_SIZE(cam_preview_vectors),
+ cam_preview_vectors,
+ },
+ {
+ ARRAY_SIZE(cam_video_vectors),
+ cam_video_vectors,
+ },
+ {
+ ARRAY_SIZE(cam_snapshot_vectors),
+ cam_snapshot_vectors,
+ },
+ {
+ ARRAY_SIZE(cam_zsl_vectors),
+ cam_zsl_vectors,
+ },
+};
+
+static struct msm_bus_scale_pdata cam_bus_client_pdata = {
+ cam_bus_client_config,
+ ARRAY_SIZE(cam_bus_client_config),
+ .name = "msm_camera",
+};
+
+static struct msm_camera_device_platform_data msm_camera_csi_device_data[] = {
+ {
+ .ioclk.mclk_clk_rate = 24000000,
+ .ioclk.vfe_clk_rate = 228570000,
+ .csid_core = 0,
+ .cam_bus_scale_table = &cam_bus_client_pdata,
+ },
+ {
+ .ioclk.mclk_clk_rate = 24000000,
+ .ioclk.vfe_clk_rate = 228570000,
+ .csid_core = 1,
+ .cam_bus_scale_table = &cam_bus_client_pdata,
+ },
+};
+
+#ifdef CONFIG_IMX074_ACT
+static struct i2c_board_info imx074_actuator_i2c_info = {
+ I2C_BOARD_INFO("imx074_act", 0x11),
+};
+
+static struct msm_actuator_info imx074_actuator_info = {
+ .board_info = &imx074_actuator_i2c_info,
+ .bus_id = MSM_8930_GSBI4_QUP_I2C_BUS_ID,
+ .vcm_pwd = 0,
+ .vcm_enable = 1,
+};
+#endif
+
+#ifdef CONFIG_IMX074
+static struct msm_camera_sensor_flash_data flash_imx074 = {
+ .flash_type = MSM_CAMERA_FLASH_LED,
+#ifdef CONFIG_MSM_CAMERA_FLASH
+ .flash_src = &msm_flash_src
+#endif
+};
+
+static struct msm_camera_sensor_platform_info sensor_board_info_imx074 = {
+ .mount_angle = 90,
+ .sensor_reset = 107,
+ .sensor_pwd = 85,
+ .vcm_pwd = 0,
+ .vcm_enable = 1,
+};
+
+static struct msm_camera_sensor_info msm_camera_sensor_imx074_data = {
+ .sensor_name = "imx074",
+ .pdata = &msm_camera_csi_device_data[0],
+ .flash_data = &flash_imx074,
+ .strobe_flash_data = &strobe_flash_xenon,
+ .sensor_platform_info = &sensor_board_info_imx074,
+ .gpio_conf = &gpio_conf,
+ .csi_if = 1,
+ .camera_type = BACK_CAMERA_2D,
+#ifdef CONFIG_IMX074_ACT
+ .actuator_info = &imx074_actuator_info
+#endif
+};
+
+static struct platform_device msm8960_camera_sensor_imx074 = {
+ .name = "msm_camera_imx074",
+ .dev = {
+ .platform_data = &msm_camera_sensor_imx074_data,
+ },
+};
+#endif
+#ifdef CONFIG_OV2720
+static struct msm_camera_sensor_flash_data flash_ov2720 = {
+ .flash_type = MSM_CAMERA_FLASH_NONE,
+};
+
+static struct msm_camera_sensor_platform_info sensor_board_info_ov2720 = {
+ .mount_angle = 0,
+ .sensor_reset = 76,
+ .sensor_pwd = 85,
+ .vcm_pwd = 0,
+ .vcm_enable = 1,
+};
+
+static struct msm_camera_sensor_info msm_camera_sensor_ov2720_data = {
+ .sensor_name = "ov2720",
+ .pdata = &msm_camera_csi_device_data[1],
+ .flash_data = &flash_ov2720,
+ .sensor_platform_info = &sensor_board_info_ov2720,
+ .gpio_conf = &gpio_conf,
+ .csi_if = 1,
+ .camera_type = FRONT_CAMERA_2D,
+};
+
+static struct platform_device msm8960_camera_sensor_ov2720 = {
+ .name = "msm_camera_ov2720",
+ .dev = {
+ .platform_data = &msm_camera_sensor_ov2720_data,
+ },
+};
+#endif
+
+void __init msm8930_init_cam(void)
+{
+ int i;
+ struct platform_device *cam_dev[] = {
+ &msm8960_camera_sensor_imx074,
+ &msm8960_camera_sensor_ov2720,
+ };
+
+ msm_gpiomux_install(msm8960_cam_common_configs,
+ ARRAY_SIZE(msm8960_cam_common_configs));
+
+ for (i = 0; i < ARRAY_SIZE(cam_dev); i++) {
+ struct msm_camera_sensor_info *s_info;
+ s_info = cam_dev[i]->dev.platform_data;
+ msm_get_cam_resources(s_info);
+ platform_device_register(cam_dev[i]);
+ }
+
+ platform_device_register(&msm8960_device_csiphy0);
+ platform_device_register(&msm8960_device_csiphy1);
+ platform_device_register(&msm8960_device_csid0);
+ platform_device_register(&msm8960_device_csid1);
+ platform_device_register(&msm8960_device_ispif);
+ platform_device_register(&msm8960_device_vfe);
+ platform_device_register(&msm8960_device_vpe);
+}
+#endif
diff --git a/arch/arm/mach-msm/board-8930-display.c b/arch/arm/mach-msm/board-8930-display.c
new file mode 100644
index 0000000..ca21fac
--- /dev/null
+++ b/arch/arm/mach-msm/board-8930-display.c
@@ -0,0 +1,793 @@
+/* Copyright (c) 2011, Code Aurora Forum. 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 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#include <linux/init.h>
+#include <linux/ioport.h>
+#include <linux/platform_device.h>
+#include <linux/bootmem.h>
+#include <asm/mach-types.h>
+#include <mach/msm_bus_board.h>
+#include <mach/board.h>
+#include <mach/gpio.h>
+#include <mach/gpiomux.h>
+#include <mach/socinfo.h>
+#include "devices.h"
+#include "board-8930.h"
+
+#ifdef CONFIG_FB_MSM_TRIPLE_BUFFER
+#define MSM_FB_PRIM_BUF_SIZE (1376 * 768 * 4 * 3) /* 4 bpp x 3 pages */
+#else
+#define MSM_FB_PRIM_BUF_SIZE (1376 * 768 * 4 * 2) /* 4 bpp x 2 pages */
+#endif
+
+#ifdef CONFIG_FB_MSM_HDMI_MSM_PANEL
+#define MSM_FB_EXT_BUF_SIZE (1920 * 1088 * 2 * 1) /* 2 bpp x 1 page */
+#elif defined(CONFIG_FB_MSM_TVOUT)
+#define MSM_FB_EXT_BUF_SIZE (720 * 576 * 2 * 2) /* 2 bpp x 2 pages */
+#else
+#define MSM_FB_EXT_BUF_SIZE 0
+#endif
+
+#ifdef CONFIG_FB_MSM_OVERLAY_WRITEBACK
+/* width x height x 3 bpp x 2 frame buffer */
+#define MSM_FB_WRITEBACK_SIZE (1376 * 768 * 3 * 2)
+#define MSM_FB_WRITEBACK_OFFSET \
+ (MSM_FB_PRIM_BUF_SIZE + MSM_FB_EXT_BUF_SIZE)
+#else
+#define MSM_FB_WRITEBACK_SIZE 0
+#define MSM_FB_WRITEBACK_OFFSET 0
+#endif
+
+#ifdef CONFIG_FB_MSM_HDMI_AS_PRIMARY
+/* 4 bpp x 2 page HDMI case */
+#define MSM_FB_SIZE roundup((1920 * 1088 * 4 * 2), 4096)
+#else
+/* Note: must be multiple of 4096 */
+#define MSM_FB_SIZE roundup(MSM_FB_PRIM_BUF_SIZE + MSM_FB_EXT_BUF_SIZE + \
+ MSM_FB_WRITEBACK_SIZE, 4096)
+#endif
+
+#define MDP_VSYNC_GPIO 0
+
+#define PANEL_NAME_MAX_LEN 30
+#define MIPI_CMD_NOVATEK_QHD_PANEL_NAME "mipi_cmd_novatek_qhd"
+#define MIPI_VIDEO_NOVATEK_QHD_PANEL_NAME "mipi_video_novatek_qhd"
+#define MIPI_VIDEO_TOSHIBA_WSVGA_PANEL_NAME "mipi_video_toshiba_wsvga"
+#define MIPI_VIDEO_CHIMEI_WXGA_PANEL_NAME "mipi_video_chimei_wxga"
+#define MIPI_VIDEO_SIMULATOR_VGA_PANEL_NAME "mipi_video_simulator_vga"
+#define MIPI_CMD_RENESAS_FWVGA_PANEL_NAME "mipi_cmd_renesas_fwvga"
+#define HDMI_PANEL_NAME "hdmi_msm"
+#define TVOUT_PANEL_NAME "tvout_msm"
+
+static int writeback_offset(void)
+{
+ return MSM_FB_WRITEBACK_OFFSET;
+}
+
+static struct resource msm_fb_resources[] = {
+ {
+ .flags = IORESOURCE_DMA,
+ }
+};
+
+static int msm_fb_detect_panel(const char *name)
+{
+ if (!strncmp(name, MIPI_VIDEO_TOSHIBA_WSVGA_PANEL_NAME,
+ strnlen(MIPI_VIDEO_TOSHIBA_WSVGA_PANEL_NAME,
+ PANEL_NAME_MAX_LEN)))
+ return 0;
+
+#ifndef CONFIG_FB_MSM_MIPI_PANEL_DETECT
+ if (!strncmp(name, MIPI_VIDEO_NOVATEK_QHD_PANEL_NAME,
+ strnlen(MIPI_VIDEO_NOVATEK_QHD_PANEL_NAME,
+ PANEL_NAME_MAX_LEN)))
+ return 0;
+
+ if (!strncmp(name, MIPI_CMD_NOVATEK_QHD_PANEL_NAME,
+ strnlen(MIPI_CMD_NOVATEK_QHD_PANEL_NAME,
+ PANEL_NAME_MAX_LEN)))
+ return 0;
+
+ if (!strncmp(name, MIPI_VIDEO_SIMULATOR_VGA_PANEL_NAME,
+ strnlen(MIPI_VIDEO_SIMULATOR_VGA_PANEL_NAME,
+ PANEL_NAME_MAX_LEN)))
+ return 0;
+
+ if (!strncmp(name, MIPI_CMD_RENESAS_FWVGA_PANEL_NAME,
+ strnlen(MIPI_CMD_RENESAS_FWVGA_PANEL_NAME,
+ PANEL_NAME_MAX_LEN)))
+ return 0;
+#endif
+
+ if (!strncmp(name, HDMI_PANEL_NAME,
+ strnlen(HDMI_PANEL_NAME,
+ PANEL_NAME_MAX_LEN)))
+ return 0;
+
+ if (!strncmp(name, TVOUT_PANEL_NAME,
+ strnlen(TVOUT_PANEL_NAME,
+ PANEL_NAME_MAX_LEN)))
+ return 0;
+
+ pr_warning("%s: not supported '%s'", __func__, name);
+ return -ENODEV;
+}
+
+static struct msm_fb_platform_data msm_fb_pdata = {
+ .detect_client = msm_fb_detect_panel,
+};
+
+static struct platform_device msm_fb_device = {
+ .name = "msm_fb",
+ .id = 0,
+ .num_resources = ARRAY_SIZE(msm_fb_resources),
+ .resource = msm_fb_resources,
+ .dev.platform_data = &msm_fb_pdata,
+};
+
+static bool dsi_power_on;
+
+static int mipi_dsi_cdp_panel_power(int on)
+{
+ static struct regulator *reg_l8, *reg_l23, *reg_l2;
+ static int gpio43;
+ int rc;
+
+ pr_info("%s: state : %d\n", __func__, on);
+
+ if (!dsi_power_on) {
+
+ reg_l8 = regulator_get(&msm_mipi_dsi1_device.dev,
+ "dsi_vdc");
+ if (IS_ERR(reg_l8)) {
+ pr_err("could not get 8921_l8, rc = %ld\n",
+ PTR_ERR(reg_l8));
+ return -ENODEV;
+ }
+ reg_l23 = regulator_get(&msm_mipi_dsi1_device.dev,
+ "dsi_vddio");
+ if (IS_ERR(reg_l23)) {
+ pr_err("could not get 8921_l23, rc = %ld\n",
+ PTR_ERR(reg_l23));
+ return -ENODEV;
+ }
+ reg_l2 = regulator_get(&msm_mipi_dsi1_device.dev,
+ "dsi_vdda");
+ if (IS_ERR(reg_l2)) {
+ pr_err("could not get 8921_l2, rc = %ld\n",
+ PTR_ERR(reg_l2));
+ return -ENODEV;
+ }
+ rc = regulator_set_voltage(reg_l8, 2800000, 3000000);
+ if (rc) {
+ pr_err("set_voltage l8 failed, rc=%d\n", rc);
+ return -EINVAL;
+ }
+ rc = regulator_set_voltage(reg_l23, 1800000, 1800000);
+ if (rc) {
+ pr_err("set_voltage l23 failed, rc=%d\n", rc);
+ return -EINVAL;
+ }
+ rc = regulator_set_voltage(reg_l2, 1200000, 1200000);
+ if (rc) {
+ pr_err("set_voltage l2 failed, rc=%d\n", rc);
+ return -EINVAL;
+ }
+ gpio43 = PM8921_GPIO_PM_TO_SYS(43);
+ rc = gpio_request(gpio43, "disp_rst_n");
+ if (rc) {
+ pr_err("request gpio 43 failed, rc=%d\n", rc);
+ return -ENODEV;
+ }
+ dsi_power_on = true;
+ }
+ if (on) {
+ rc = regulator_set_optimum_mode(reg_l8, 100000);
+ if (rc < 0) {
+ pr_err("set_optimum_mode l8 failed, rc=%d\n", rc);
+ return -EINVAL;
+ }
+ rc = regulator_set_optimum_mode(reg_l23, 100000);
+ if (rc < 0) {
+ pr_err("set_optimum_mode l23 failed, rc=%d\n", rc);
+ return -EINVAL;
+ }
+ rc = regulator_set_optimum_mode(reg_l2, 100000);
+ if (rc < 0) {
+ pr_err("set_optimum_mode l2 failed, rc=%d\n", rc);
+ return -EINVAL;
+ }
+ rc = regulator_enable(reg_l8);
+ if (rc) {
+ pr_err("enable l8 failed, rc=%d\n", rc);
+ return -ENODEV;
+ }
+ rc = regulator_enable(reg_l23);
+ if (rc) {
+ pr_err("enable l8 failed, rc=%d\n", rc);
+ return -ENODEV;
+ }
+ rc = regulator_enable(reg_l2);
+ if (rc) {
+ pr_err("enable l2 failed, rc=%d\n", rc);
+ return -ENODEV;
+ }
+ gpio_set_value_cansleep(gpio43, 1);
+ } else {
+ rc = regulator_disable(reg_l2);
+ if (rc) {
+ pr_err("disable reg_l2 failed, rc=%d\n", rc);
+ return -ENODEV;
+ }
+ rc = regulator_disable(reg_l8);
+ if (rc) {
+ pr_err("disable reg_l8 failed, rc=%d\n", rc);
+ return -ENODEV;
+ }
+ rc = regulator_disable(reg_l23);
+ if (rc) {
+ pr_err("disable reg_l23 failed, rc=%d\n", rc);
+ return -ENODEV;
+ }
+ rc = regulator_set_optimum_mode(reg_l8, 100);
+ if (rc < 0) {
+ pr_err("set_optimum_mode l8 failed, rc=%d\n", rc);
+ return -EINVAL;
+ }
+ rc = regulator_set_optimum_mode(reg_l23, 100);
+ if (rc < 0) {
+ pr_err("set_optimum_mode l23 failed, rc=%d\n", rc);
+ return -EINVAL;
+ }
+ rc = regulator_set_optimum_mode(reg_l2, 100);
+ if (rc < 0) {
+ pr_err("set_optimum_mode l2 failed, rc=%d\n", rc);
+ return -EINVAL;
+ }
+ gpio_set_value_cansleep(gpio43, 0);
+ }
+ return 0;
+}
+
+static int mipi_dsi_panel_power(int on)
+{
+ pr_info("%s: on=%d\n", __func__, on);
+
+ return mipi_dsi_cdp_panel_power(on);
+}
+
+static struct mipi_dsi_platform_data mipi_dsi_pdata = {
+ .vsync_gpio = MDP_VSYNC_GPIO,
+ .dsi_power_save = mipi_dsi_panel_power,
+};
+
+#ifdef CONFIG_MSM_BUS_SCALING
+
+static struct msm_bus_vectors mdp_init_vectors[] = {
+ {
+ .src = MSM_BUS_MASTER_MDP_PORT0,
+ .dst = MSM_BUS_SLAVE_EBI_CH0,
+ .ab = 0,
+ .ib = 0,
+ },
+};
+
+#ifdef CONFIG_FB_MSM_HDMI_AS_PRIMARY
+static struct msm_bus_vectors hdmi_as_primary_vectors[] = {
+ /* If HDMI is used as primary */
+ {
+ .src = MSM_BUS_MASTER_MDP_PORT0,
+ .dst = MSM_BUS_SLAVE_EBI_CH0,
+ .ab = 2000000000,
+ .ib = 2000000000,
+ },
+};
+static struct msm_bus_paths mdp_bus_scale_usecases[] = {
+ {
+ ARRAY_SIZE(mdp_init_vectors),
+ mdp_init_vectors,
+ },
+ {
+ ARRAY_SIZE(hdmi_as_primary_vectors),
+ hdmi_as_primary_vectors,
+ },
+ {
+ ARRAY_SIZE(hdmi_as_primary_vectors),
+ hdmi_as_primary_vectors,
+ },
+ {
+ ARRAY_SIZE(hdmi_as_primary_vectors),
+ hdmi_as_primary_vectors,
+ },
+ {
+ ARRAY_SIZE(hdmi_as_primary_vectors),
+ hdmi_as_primary_vectors,
+ },
+ {
+ ARRAY_SIZE(hdmi_as_primary_vectors),
+ hdmi_as_primary_vectors,
+ },
+};
+#else
+static struct msm_bus_vectors mdp_ui_vectors[] = {
+ {
+ .src = MSM_BUS_MASTER_MDP_PORT0,
+ .dst = MSM_BUS_SLAVE_EBI_CH0,
+ .ab = 216000000 * 2,
+ .ib = 270000000 * 2,
+ },
+};
+
+static struct msm_bus_vectors mdp_vga_vectors[] = {
+ /* VGA and less video */
+ {
+ .src = MSM_BUS_MASTER_MDP_PORT0,
+ .dst = MSM_BUS_SLAVE_EBI_CH0,
+ .ab = 216000000 * 2,
+ .ib = 270000000 * 2,
+ },
+};
+
+static struct msm_bus_vectors mdp_720p_vectors[] = {
+ /* 720p and less video */
+ {
+ .src = MSM_BUS_MASTER_MDP_PORT0,
+ .dst = MSM_BUS_SLAVE_EBI_CH0,
+ .ab = 230400000 * 2,
+ .ib = 288000000 * 2,
+ },
+};
+
+static struct msm_bus_vectors mdp_1080p_vectors[] = {
+ /* 1080p and less video */
+ {
+ .src = MSM_BUS_MASTER_MDP_PORT0,
+ .dst = MSM_BUS_SLAVE_EBI_CH0,
+ .ab = 334080000 * 2,
+ .ib = 417600000 * 2,
+ },
+};
+
+static struct msm_bus_paths mdp_bus_scale_usecases[] = {
+ {
+ ARRAY_SIZE(mdp_init_vectors),
+ mdp_init_vectors,
+ },
+ {
+ ARRAY_SIZE(mdp_ui_vectors),
+ mdp_ui_vectors,
+ },
+ {
+ ARRAY_SIZE(mdp_ui_vectors),
+ mdp_ui_vectors,
+ },
+ {
+ ARRAY_SIZE(mdp_vga_vectors),
+ mdp_vga_vectors,
+ },
+ {
+ ARRAY_SIZE(mdp_720p_vectors),
+ mdp_720p_vectors,
+ },
+ {
+ ARRAY_SIZE(mdp_1080p_vectors),
+ mdp_1080p_vectors,
+ },
+};
+#endif
+
+static struct msm_bus_scale_pdata mdp_bus_scale_pdata = {
+ mdp_bus_scale_usecases,
+ ARRAY_SIZE(mdp_bus_scale_usecases),
+ .name = "mdp",
+};
+
+#endif
+
+#ifdef CONFIG_FB_MSM_HDMI_AS_PRIMARY
+static int mdp_core_clk_rate_table[] = {
+ 200000000,
+ 200000000,
+ 200000000,
+ 200000000,
+};
+#else
+static int mdp_core_clk_rate_table[] = {
+ 85330000,
+ 85330000,
+ 160000000,
+ 200000000,
+};
+#endif
+
+static struct msm_panel_common_pdata mdp_pdata = {
+ .gpio = MDP_VSYNC_GPIO,
+#ifdef CONFIG_FB_MSM_HDMI_AS_PRIMARY
+ .mdp_core_clk_rate = 200000000,
+#else
+ .mdp_core_clk_rate = 85330000,
+#endif
+ .mdp_core_clk_table = mdp_core_clk_rate_table,
+ .num_mdp_clk = ARRAY_SIZE(mdp_core_clk_rate_table),
+#ifdef CONFIG_MSM_BUS_SCALING
+ .mdp_bus_scale_table = &mdp_bus_scale_pdata,
+#endif
+ .mdp_rev = MDP_REV_42,
+ .writeback_offset = writeback_offset,
+};
+
+#define LPM_CHANNEL0 0
+static int toshiba_gpio[] = {LPM_CHANNEL0};
+
+static struct mipi_dsi_panel_platform_data toshiba_pdata = {
+ .gpio = toshiba_gpio,
+};
+
+static struct platform_device mipi_dsi_toshiba_panel_device = {
+ .name = "mipi_toshiba",
+ .id = 0,
+ .dev = {
+ .platform_data = &toshiba_pdata,
+ }
+};
+
+#define FPGA_3D_GPIO_CONFIG_ADDR 0xB5
+
+static struct mipi_dsi_phy_ctrl dsi_novatek_cmd_mode_phy_db = {
+
+/* DSI_BIT_CLK at 500MHz, 2 lane, RGB888 */
+ {0x0F, 0x0a, 0x04, 0x00, 0x20}, /* regulator */
+ /* timing */
+ {0xab, 0x8a, 0x18, 0x00, 0x92, 0x97, 0x1b, 0x8c,
+ 0x0c, 0x03, 0x04, 0xa0},
+ {0x5f, 0x00, 0x00, 0x10}, /* phy ctrl */
+ {0xff, 0x00, 0x06, 0x00}, /* strength */
+ /* pll control */
+ {0x40, 0xf9, 0x30, 0xda, 0x00, 0x40, 0x03, 0x62,
+ 0x40, 0x07, 0x03,
+ 0x00, 0x1a, 0x00, 0x00, 0x02, 0x00, 0x20, 0x00, 0x01},
+};
+
+static struct mipi_dsi_panel_platform_data novatek_pdata = {
+ .fpga_3d_config_addr = FPGA_3D_GPIO_CONFIG_ADDR,
+ .fpga_ctrl_mode = FPGA_SPI_INTF,
+ .phy_ctrl_settings = &dsi_novatek_cmd_mode_phy_db,
+};
+
+static struct platform_device mipi_dsi_novatek_panel_device = {
+ .name = "mipi_novatek",
+ .id = 0,
+ .dev = {
+ .platform_data = &novatek_pdata,
+ }
+};
+
+#ifdef CONFIG_FB_MSM_HDMI_MSM_PANEL
+static struct resource hdmi_msm_resources[] = {
+ {
+ .name = "hdmi_msm_qfprom_addr",
+ .start = 0x00700000,
+ .end = 0x007060FF,
+ .flags = IORESOURCE_MEM,
+ },
+ {
+ .name = "hdmi_msm_hdmi_addr",
+ .start = 0x04A00000,
+ .end = 0x04A00FFF,
+ .flags = IORESOURCE_MEM,
+ },
+ {
+ .name = "hdmi_msm_irq",
+ .start = HDMI_IRQ,
+ .end = HDMI_IRQ,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+static int hdmi_enable_5v(int on);
+static int hdmi_core_power(int on, int show);
+static int hdmi_cec_power(int on);
+
+static struct msm_hdmi_platform_data hdmi_msm_data = {
+ .irq = HDMI_IRQ,
+ .enable_5v = hdmi_enable_5v,
+ .core_power = hdmi_core_power,
+ .cec_power = hdmi_cec_power,
+};
+
+static struct platform_device hdmi_msm_device = {
+ .name = "hdmi_msm",
+ .id = 0,
+ .num_resources = ARRAY_SIZE(hdmi_msm_resources),
+ .resource = hdmi_msm_resources,
+ .dev.platform_data = &hdmi_msm_data,
+};
+#endif /* CONFIG_FB_MSM_HDMI_MSM_PANEL */
+
+#ifdef CONFIG_FB_MSM_WRITEBACK_MSM_PANEL
+static struct platform_device wfd_panel_device = {
+ .name = "wfd_panel",
+ .id = 0,
+ .dev.platform_data = NULL,
+};
+
+static struct platform_device wfd_device = {
+ .name = "msm_wfd",
+ .id = -1,
+};
+#endif
+
+#ifdef CONFIG_MSM_BUS_SCALING
+static struct msm_bus_vectors dtv_bus_init_vectors[] = {
+ {
+ .src = MSM_BUS_MASTER_MDP_PORT0,
+ .dst = MSM_BUS_SLAVE_EBI_CH0,
+ .ab = 0,
+ .ib = 0,
+ },
+};
+
+#ifdef CONFIG_FB_MSM_HDMI_AS_PRIMARY
+static struct msm_bus_vectors dtv_bus_def_vectors[] = {
+ {
+ .src = MSM_BUS_MASTER_MDP_PORT0,
+ .dst = MSM_BUS_SLAVE_EBI_CH0,
+ .ab = 2000000000,
+ .ib = 2000000000,
+ },
+};
+#else
+static struct msm_bus_vectors dtv_bus_def_vectors[] = {
+ {
+ .src = MSM_BUS_MASTER_MDP_PORT0,
+ .dst = MSM_BUS_SLAVE_EBI_CH0,
+ .ab = 566092800 * 2,
+ .ib = 707616000 * 2,
+ },
+};
+#endif
+
+static struct msm_bus_paths dtv_bus_scale_usecases[] = {
+ {
+ ARRAY_SIZE(dtv_bus_init_vectors),
+ dtv_bus_init_vectors,
+ },
+ {
+ ARRAY_SIZE(dtv_bus_def_vectors),
+ dtv_bus_def_vectors,
+ },
+};
+static struct msm_bus_scale_pdata dtv_bus_scale_pdata = {
+ dtv_bus_scale_usecases,
+ ARRAY_SIZE(dtv_bus_scale_usecases),
+ .name = "dtv",
+};
+
+static struct lcdc_platform_data dtv_pdata = {
+ .bus_scale_table = &dtv_bus_scale_pdata,
+};
+#endif
+
+#ifdef CONFIG_FB_MSM_HDMI_MSM_PANEL
+static int hdmi_enable_5v(int on)
+{
+ /* TBD: PM8921 regulator instead of 8901 */
+ static struct regulator *reg_8921_hdmi_mvs; /* HDMI_5V */
+ static int prev_on;
+ int rc;
+
+ if (on == prev_on)
+ return 0;
+
+ if (!reg_8921_hdmi_mvs)
+ reg_8921_hdmi_mvs = regulator_get(&hdmi_msm_device.dev,
+ "hdmi_mvs");
+
+ if (on) {
+ rc = regulator_enable(reg_8921_hdmi_mvs);
+ if (rc) {
+ pr_err("'%s' regulator enable failed, rc=%d\n",
+ "8921_hdmi_mvs", rc);
+ return rc;
+ }
+ pr_debug("%s(on): success\n", __func__);
+ } else {
+ rc = regulator_disable(reg_8921_hdmi_mvs);
+ if (rc)
+ pr_warning("'%s' regulator disable failed, rc=%d\n",
+ "8921_hdmi_mvs", rc);
+ pr_debug("%s(off): success\n", __func__);
+ }
+
+ prev_on = on;
+
+ return 0;
+}
+
+static int hdmi_core_power(int on, int show)
+{
+ static struct regulator *reg_8921_l23, *reg_8921_s4;
+ static int prev_on;
+ int rc;
+
+ if (on == prev_on)
+ return 0;
+
+ /* TBD: PM8921 regulator instead of 8901 */
+ if (!reg_8921_l23) {
+ reg_8921_l23 = regulator_get(&hdmi_msm_device.dev, "hdmi_avdd");
+ if (IS_ERR(reg_8921_l23)) {
+ pr_err("could not get reg_8921_l23, rc = %ld\n",
+ PTR_ERR(reg_8921_l23));
+ return -ENODEV;
+ }
+ rc = regulator_set_voltage(reg_8921_l23, 1800000, 1800000);
+ if (rc) {
+ pr_err("set_voltage failed for 8921_l23, rc=%d\n", rc);
+ return -EINVAL;
+ }
+ }
+ if (!reg_8921_s4) {
+ reg_8921_s4 = regulator_get(&hdmi_msm_device.dev, "hdmi_vcc");
+ if (IS_ERR(reg_8921_s4)) {
+ pr_err("could not get reg_8921_s4, rc = %ld\n",
+ PTR_ERR(reg_8921_s4));
+ return -ENODEV;
+ }
+ rc = regulator_set_voltage(reg_8921_s4, 1800000, 1800000);
+ if (rc) {
+ pr_err("set_voltage failed for 8921_s4, rc=%d\n", rc);
+ return -EINVAL;
+ }
+ }
+
+ if (on) {
+ rc = regulator_set_optimum_mode(reg_8921_l23, 100000);
+ if (rc < 0) {
+ pr_err("set_optimum_mode l23 failed, rc=%d\n", rc);
+ return -EINVAL;
+ }
+ rc = regulator_enable(reg_8921_l23);
+ if (rc) {
+ pr_err("'%s' regulator enable failed, rc=%d\n",
+ "hdmi_avdd", rc);
+ return rc;
+ }
+ rc = regulator_enable(reg_8921_s4);
+ if (rc) {
+ pr_err("'%s' regulator enable failed, rc=%d\n",
+ "hdmi_vcc", rc);
+ return rc;
+ }
+ rc = gpio_request(100, "HDMI_DDC_CLK");
+ if (rc) {
+ pr_err("'%s'(%d) gpio_request failed, rc=%d\n",
+ "HDMI_DDC_CLK", 100, rc);
+ goto error1;
+ }
+ rc = gpio_request(101, "HDMI_DDC_DATA");
+ if (rc) {
+ pr_err("'%s'(%d) gpio_request failed, rc=%d\n",
+ "HDMI_DDC_DATA", 101, rc);
+ goto error2;
+ }
+ rc = gpio_request(102, "HDMI_HPD");
+ if (rc) {
+ pr_err("'%s'(%d) gpio_request failed, rc=%d\n",
+ "HDMI_HPD", 102, rc);
+ goto error3;
+ }
+ pr_debug("%s(on): success\n", __func__);
+ } else {
+ gpio_free(100);
+ gpio_free(101);
+ gpio_free(102);
+
+ rc = regulator_disable(reg_8921_l23);
+ if (rc) {
+ pr_err("disable reg_8921_l23 failed, rc=%d\n", rc);
+ return -ENODEV;
+ }
+ rc = regulator_disable(reg_8921_s4);
+ if (rc) {
+ pr_err("disable reg_8921_s4 failed, rc=%d\n", rc);
+ return -ENODEV;
+ }
+ rc = regulator_set_optimum_mode(reg_8921_l23, 100);
+ if (rc < 0) {
+ pr_err("set_optimum_mode l23 failed, rc=%d\n", rc);
+ return -EINVAL;
+ }
+ pr_debug("%s(off): success\n", __func__);
+ }
+
+ prev_on = on;
+
+ return 0;
+
+error3:
+ gpio_free(101);
+error2:
+ gpio_free(100);
+error1:
+ regulator_disable(reg_8921_l23);
+ regulator_disable(reg_8921_s4);
+ return rc;
+}
+
+static int hdmi_cec_power(int on)
+{
+ static int prev_on;
+ int rc;
+
+ if (on == prev_on)
+ return 0;
+
+ if (on) {
+ rc = gpio_request(99, "HDMI_CEC_VAR");
+ if (rc) {
+ pr_err("'%s'(%d) gpio_request failed, rc=%d\n",
+ "HDMI_CEC_VAR", 99, rc);
+ goto error;
+ }
+ pr_debug("%s(on): success\n", __func__);
+ } else {
+ gpio_free(99);
+ pr_debug("%s(off): success\n", __func__);
+ }
+
+ prev_on = on;
+
+ return 0;
+error:
+ return rc;
+}
+#endif /* CONFIG_FB_MSM_HDMI_MSM_PANEL */
+
+void __init msm8930_init_fb(void)
+{
+ platform_device_register(&msm_fb_device);
+
+#ifdef CONFIG_FB_MSM_WRITEBACK_MSM_PANEL
+ platform_device_register(&wfd_panel_device);
+ platform_device_register(&wfd_device);
+#endif
+
+ platform_device_register(&mipi_dsi_novatek_panel_device);
+
+#ifdef CONFIG_FB_MSM_HDMI_MSM_PANEL
+ if (!cpu_is_msm8627())
+ platform_device_register(&hdmi_msm_device);
+#endif
+
+ platform_device_register(&mipi_dsi_toshiba_panel_device);
+
+ msm_fb_register_device("mdp", &mdp_pdata);
+ msm_fb_register_device("mipi_dsi", &mipi_dsi_pdata);
+#ifdef CONFIG_MSM_BUS_SCALING
+ msm_fb_register_device("dtv", &dtv_pdata);
+#endif
+}
+
+void __init msm8930_allocate_fb_region(void)
+{
+ void *addr;
+ unsigned long size;
+
+ size = MSM_FB_SIZE;
+ addr = alloc_bootmem_align(size, 0x1000);
+ msm_fb_resources[0].start = __pa(addr);
+ msm_fb_resources[0].end = msm_fb_resources[0].start + size - 1;
+ pr_info("allocating %lu bytes at %p (%lx physical) for fb\n",
+ size, addr, __pa(addr));
+}
diff --git a/arch/arm/mach-msm/board-8930-gpiomux.c b/arch/arm/mach-msm/board-8930-gpiomux.c
new file mode 100644
index 0000000..e872d64
--- /dev/null
+++ b/arch/arm/mach-msm/board-8930-gpiomux.c
@@ -0,0 +1,662 @@
+/* Copyright (c) 2011, Code Aurora Forum. 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 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#include <asm/mach-types.h>
+#include <mach/gpio.h>
+#include <mach/gpiomux.h>
+#include <mach/socinfo.h>
+#include "devices.h"
+#include "board-8930.h"
+
+/* The SPI configurations apply to GSBI 1*/
+static struct gpiomux_setting spi_active = {
+ .func = GPIOMUX_FUNC_1,
+ .drv = GPIOMUX_DRV_12MA,
+ .pull = GPIOMUX_PULL_NONE,
+};
+
+static struct gpiomux_setting spi_suspended_config = {
+ .func = GPIOMUX_FUNC_GPIO,
+ .drv = GPIOMUX_DRV_2MA,
+ .pull = GPIOMUX_PULL_DOWN,
+};
+
+static struct gpiomux_setting spi_active_config2 = {
+ .func = GPIOMUX_FUNC_2,
+ .drv = GPIOMUX_DRV_8MA,
+ .pull = GPIOMUX_PULL_NONE,
+};
+
+static struct gpiomux_setting spi_suspended_config2 = {
+ .func = GPIOMUX_FUNC_GPIO,
+ .drv = GPIOMUX_DRV_2MA,
+ .pull = GPIOMUX_PULL_UP,
+};
+
+static struct gpiomux_setting gsbi3_suspended_cfg = {
+ .func = GPIOMUX_FUNC_1,
+ .drv = GPIOMUX_DRV_2MA,
+ .pull = GPIOMUX_PULL_KEEPER,
+};
+
+static struct gpiomux_setting gsbi3_active_cfg = {
+ .func = GPIOMUX_FUNC_1,
+ .drv = GPIOMUX_DRV_8MA,
+ .pull = GPIOMUX_PULL_NONE,
+};
+
+static struct gpiomux_setting gsbi5 = {
+ .func = GPIOMUX_FUNC_1,
+ .drv = GPIOMUX_DRV_8MA,
+ .pull = GPIOMUX_PULL_NONE,
+};
+
+static struct gpiomux_setting gsbi10 = {
+ .func = GPIOMUX_FUNC_2,
+ .drv = GPIOMUX_DRV_8MA,
+ .pull = GPIOMUX_PULL_NONE,
+};
+
+static struct gpiomux_setting gsbi12 = {
+ .func = GPIOMUX_FUNC_1,
+ .drv = GPIOMUX_DRV_8MA,
+ .pull = GPIOMUX_PULL_NONE,
+};
+
+static struct gpiomux_setting cdc_mclk = {
+ .func = GPIOMUX_FUNC_1,
+ .drv = GPIOMUX_DRV_8MA,
+ .pull = GPIOMUX_PULL_NONE,
+};
+
+static struct gpiomux_setting audio_auxpcm[] = {
+ /* Suspended state */
+ {
+ .func = GPIOMUX_FUNC_GPIO,
+ .drv = GPIOMUX_DRV_2MA,
+ .pull = GPIOMUX_PULL_NONE,
+ },
+ /* Active state */
+ {
+ .func = GPIOMUX_FUNC_1,
+ .drv = GPIOMUX_DRV_2MA,
+ .pull = GPIOMUX_PULL_NONE,
+ },
+};
+
+#if defined(CONFIG_KS8851) || defined(CONFIG_KS8851_MODULE)
+static struct gpiomux_setting gpio_eth_config = {
+ .pull = GPIOMUX_PULL_NONE,
+ .drv = GPIOMUX_DRV_8MA,
+ .func = GPIOMUX_FUNC_GPIO,
+};
+#endif
+
+static struct gpiomux_setting slimbus = {
+ .func = GPIOMUX_FUNC_1,
+ .drv = GPIOMUX_DRV_8MA,
+ .pull = GPIOMUX_PULL_KEEPER,
+};
+
+static struct gpiomux_setting wcnss_5wire_suspend_cfg = {
+ .func = GPIOMUX_FUNC_GPIO,
+ .drv = GPIOMUX_DRV_2MA,
+ .pull = GPIOMUX_PULL_UP,
+};
+
+static struct gpiomux_setting wcnss_5wire_active_cfg = {
+ .func = GPIOMUX_FUNC_1,
+ .drv = GPIOMUX_DRV_6MA,
+ .pull = GPIOMUX_PULL_DOWN,
+};
+
+static struct gpiomux_setting cyts_resout_sus_cfg = {
+ .func = GPIOMUX_FUNC_GPIO,
+ .drv = GPIOMUX_DRV_6MA,
+ .pull = GPIOMUX_PULL_UP,
+};
+
+static struct gpiomux_setting cyts_resout_act_cfg = {
+ .func = GPIOMUX_FUNC_GPIO,
+ .drv = GPIOMUX_DRV_6MA,
+ .pull = GPIOMUX_PULL_UP,
+};
+
+static struct gpiomux_setting cyts_sleep_sus_cfg = {
+ .func = GPIOMUX_FUNC_GPIO,
+ .drv = GPIOMUX_DRV_6MA,
+ .pull = GPIOMUX_PULL_DOWN,
+};
+
+static struct gpiomux_setting cyts_sleep_act_cfg = {
+ .func = GPIOMUX_FUNC_GPIO,
+ .drv = GPIOMUX_DRV_6MA,
+ .pull = GPIOMUX_PULL_DOWN,
+};
+
+static struct gpiomux_setting cyts_int_act_cfg = {
+ .func = GPIOMUX_FUNC_GPIO,
+ .drv = GPIOMUX_DRV_8MA,
+ .pull = GPIOMUX_PULL_UP,
+};
+
+static struct gpiomux_setting cyts_int_sus_cfg = {
+ .func = GPIOMUX_FUNC_GPIO,
+ .drv = GPIOMUX_DRV_2MA,
+ .pull = GPIOMUX_PULL_DOWN,
+};
+
+#ifdef CONFIG_USB_EHCI_MSM_HSIC
+static struct gpiomux_setting hsic_act_cfg = {
+ .func = GPIOMUX_FUNC_1,
+ .drv = GPIOMUX_DRV_12MA,
+ .pull = GPIOMUX_PULL_NONE,
+};
+
+static struct gpiomux_setting hsic_sus_cfg = {
+ .func = GPIOMUX_FUNC_GPIO,
+ .drv = GPIOMUX_DRV_2MA,
+ .pull = GPIOMUX_PULL_DOWN,
+ .dir = GPIOMUX_OUT_LOW,
+};
+
+static struct gpiomux_setting hsic_hub_act_cfg = {
+ .func = GPIOMUX_FUNC_GPIO,
+ .drv = GPIOMUX_DRV_2MA,
+ .pull = GPIOMUX_PULL_NONE,
+};
+#endif
+
+static struct gpiomux_setting hap_lvl_shft_suspended_config = {
+ .func = GPIOMUX_FUNC_GPIO,
+ .drv = GPIOMUX_DRV_2MA,
+ .pull = GPIOMUX_PULL_DOWN,
+};
+
+static struct gpiomux_setting hap_lvl_shft_active_config = {
+ .func = GPIOMUX_FUNC_GPIO,
+ .drv = GPIOMUX_DRV_8MA,
+ .pull = GPIOMUX_PULL_UP,
+};
+
+static struct gpiomux_setting ap2mdm_cfg = {
+ .func = GPIOMUX_FUNC_GPIO,
+ .drv = GPIOMUX_DRV_8MA,
+ .pull = GPIOMUX_PULL_DOWN,
+};
+
+static struct gpiomux_setting mdm2ap_status_cfg = {
+ .func = GPIOMUX_FUNC_GPIO,
+ .drv = GPIOMUX_DRV_8MA,
+ .pull = GPIOMUX_PULL_NONE,
+};
+
+static struct gpiomux_setting mdm2ap_errfatal_cfg = {
+ .func = GPIOMUX_FUNC_GPIO,
+ .drv = GPIOMUX_DRV_16MA,
+ .pull = GPIOMUX_PULL_DOWN,
+};
+
+static struct gpiomux_setting ap2mdm_kpdpwr_n_cfg = {
+ .func = GPIOMUX_FUNC_GPIO,
+ .drv = GPIOMUX_DRV_8MA,
+ .pull = GPIOMUX_PULL_NONE,
+};
+
+static struct gpiomux_setting mdp_vsync_suspend_cfg = {
+ .func = GPIOMUX_FUNC_GPIO,
+ .drv = GPIOMUX_DRV_2MA,
+ .pull = GPIOMUX_PULL_DOWN,
+};
+
+static struct gpiomux_setting mdp_vsync_active_cfg = {
+ .func = GPIOMUX_FUNC_1,
+ .drv = GPIOMUX_DRV_2MA,
+ .pull = GPIOMUX_PULL_DOWN,
+};
+
+#ifdef CONFIG_FB_MSM_HDMI_MSM_PANEL
+static struct gpiomux_setting hdmi_suspend_cfg = {
+ .func = GPIOMUX_FUNC_GPIO,
+ .drv = GPIOMUX_DRV_2MA,
+ .pull = GPIOMUX_PULL_DOWN,
+};
+
+static struct gpiomux_setting hdmi_active_1_cfg = {
+ .func = GPIOMUX_FUNC_1,
+ .drv = GPIOMUX_DRV_2MA,
+ .pull = GPIOMUX_PULL_UP,
+};
+
+static struct gpiomux_setting hdmi_active_2_cfg = {
+ .func = GPIOMUX_FUNC_1,
+ .drv = GPIOMUX_DRV_2MA,
+ .pull = GPIOMUX_PULL_DOWN,
+};
+#endif
+
+#if defined(CONFIG_KS8851) || defined(CONFIG_KS8851_MODULE)
+static struct msm_gpiomux_config msm8960_ethernet_configs[] = {
+ {
+ .gpio = 90,
+ .settings = {
+ [GPIOMUX_SUSPENDED] = &gpio_eth_config,
+ }
+ },
+ {
+ .gpio = 89,
+ .settings = {
+ [GPIOMUX_SUSPENDED] = &gpio_eth_config,
+ }
+ },
+};
+#endif
+
+static struct msm_gpiomux_config msm8960_gsbi_configs[] __initdata = {
+ {
+ .gpio = 6, /* GSBI1 QUP SPI_DATA_MOSI */
+ .settings = {
+ [GPIOMUX_SUSPENDED] = &spi_suspended_config,
+ [GPIOMUX_ACTIVE] = &spi_active,
+ },
+ },
+ {
+ .gpio = 7, /* GSBI1 QUP SPI_DATA_MISO */
+ .settings = {
+ [GPIOMUX_SUSPENDED] = &spi_suspended_config,
+ [GPIOMUX_ACTIVE] = &spi_active,
+ },
+ },
+ {
+ .gpio = 8, /* GSBI1 QUP SPI_CS_N */
+ .settings = {
+ [GPIOMUX_SUSPENDED] = &spi_suspended_config,
+ [GPIOMUX_ACTIVE] = &spi_active,
+ },
+ },
+ {
+ .gpio = 9, /* GSBI1 QUP SPI_CLK */
+ .settings = {
+ [GPIOMUX_SUSPENDED] = &spi_suspended_config,
+ [GPIOMUX_ACTIVE] = &spi_active,
+ },
+ },
+ {
+ .gpio = 14, /* GSBI1 SPI_CS_1 */
+ .settings = {
+ [GPIOMUX_SUSPENDED] = &spi_suspended_config2,
+ [GPIOMUX_ACTIVE] = &spi_active_config2,
+ },
+ },
+ {
+ .gpio = 16, /* GSBI3 I2C QUP SDA */
+ .settings = {
+ [GPIOMUX_SUSPENDED] = &gsbi3_suspended_cfg,
+ [GPIOMUX_ACTIVE] = &gsbi3_active_cfg,
+ },
+ },
+ {
+ .gpio = 17, /* GSBI3 I2C QUP SCL */
+ .settings = {
+ [GPIOMUX_SUSPENDED] = &gsbi3_suspended_cfg,
+ [GPIOMUX_ACTIVE] = &gsbi3_active_cfg,
+ },
+ },
+ {
+ .gpio = 22, /* GSBI5 UART2 */
+ .settings = {
+ [GPIOMUX_SUSPENDED] = &gsbi5,
+ },
+ },
+ {
+ .gpio = 23, /* GSBI5 UART2 */
+ .settings = {
+ [GPIOMUX_SUSPENDED] = &gsbi5,
+ },
+ },
+ {
+ .gpio = 24, /* GSBI5 UART2 */
+ .settings = {
+ [GPIOMUX_SUSPENDED] = &gsbi5,
+ },
+ },
+ {
+ .gpio = 25, /* GSBI5 UART2 */
+ .settings = {
+ [GPIOMUX_SUSPENDED] = &gsbi5,
+ },
+ },
+ {
+ .gpio = 44, /* GSBI12 I2C QUP SDA */
+ .settings = {
+ [GPIOMUX_SUSPENDED] = &gsbi12,
+ },
+ },
+ {
+ .gpio = 45, /* GSBI12 I2C QUP SCL */
+ .settings = {
+ [GPIOMUX_SUSPENDED] = &gsbi12,
+ },
+ },
+ {
+ .gpio = 73, /* GSBI10 I2C QUP SDA */
+ .settings = {
+ [GPIOMUX_SUSPENDED] = &gsbi10,
+ },
+ },
+ {
+ .gpio = 74, /* GSBI10 I2C QUP SCL */
+ .settings = {
+ [GPIOMUX_SUSPENDED] = &gsbi10,
+ },
+ },
+};
+
+static struct msm_gpiomux_config msm8960_slimbus_config[] __initdata = {
+ {
+ .gpio = 60, /* slimbus data */
+ .settings = {
+ [GPIOMUX_SUSPENDED] = &slimbus,
+ },
+ },
+ {
+ .gpio = 61, /* slimbus clk */
+ .settings = {
+ [GPIOMUX_SUSPENDED] = &slimbus,
+ },
+ },
+};
+
+static struct msm_gpiomux_config msm8960_audio_codec_configs[] __initdata = {
+ {
+ .gpio = 59,
+ .settings = {
+ [GPIOMUX_SUSPENDED] = &cdc_mclk,
+ },
+ },
+};
+
+static struct msm_gpiomux_config msm8960_audio_auxpcm_configs[] __initdata = {
+ {
+ .gpio = 63,
+ .settings = {
+ [GPIOMUX_SUSPENDED] = &audio_auxpcm[0],
+ [GPIOMUX_ACTIVE] = &audio_auxpcm[1],
+ },
+ },
+ {
+ .gpio = 64,
+ .settings = {
+ [GPIOMUX_SUSPENDED] = &audio_auxpcm[0],
+ [GPIOMUX_ACTIVE] = &audio_auxpcm[1],
+ },
+ },
+ {
+ .gpio = 65,
+ .settings = {
+ [GPIOMUX_SUSPENDED] = &audio_auxpcm[0],
+ [GPIOMUX_ACTIVE] = &audio_auxpcm[1],
+ },
+ },
+ {
+ .gpio = 66,
+ .settings = {
+ [GPIOMUX_SUSPENDED] = &audio_auxpcm[0],
+ [GPIOMUX_ACTIVE] = &audio_auxpcm[1],
+ },
+ },
+};
+
+static struct msm_gpiomux_config wcnss_5wire_interface[] = {
+ {
+ .gpio = 84,
+ .settings = {
+ [GPIOMUX_ACTIVE] = &wcnss_5wire_active_cfg,
+ [GPIOMUX_SUSPENDED] = &wcnss_5wire_suspend_cfg,
+ },
+ },
+ {
+ .gpio = 85,
+ .settings = {
+ [GPIOMUX_ACTIVE] = &wcnss_5wire_active_cfg,
+ [GPIOMUX_SUSPENDED] = &wcnss_5wire_suspend_cfg,
+ },
+ },
+ {
+ .gpio = 86,
+ .settings = {
+ [GPIOMUX_ACTIVE] = &wcnss_5wire_active_cfg,
+ [GPIOMUX_SUSPENDED] = &wcnss_5wire_suspend_cfg,
+ },
+ },
+ {
+ .gpio = 87,
+ .settings = {
+ [GPIOMUX_ACTIVE] = &wcnss_5wire_active_cfg,
+ [GPIOMUX_SUSPENDED] = &wcnss_5wire_suspend_cfg,
+ },
+ },
+ {
+ .gpio = 88,
+ .settings = {
+ [GPIOMUX_ACTIVE] = &wcnss_5wire_active_cfg,
+ [GPIOMUX_SUSPENDED] = &wcnss_5wire_suspend_cfg,
+ },
+ },
+};
+
+static struct msm_gpiomux_config msm8960_cyts_configs[] __initdata = {
+ { /* TS INTERRUPT */
+ .gpio = 11,
+ .settings = {
+ [GPIOMUX_ACTIVE] = &cyts_int_act_cfg,
+ [GPIOMUX_SUSPENDED] = &cyts_int_sus_cfg,
+ },
+ },
+ { /* TS SLEEP */
+ .gpio = 50,
+ .settings = {
+ [GPIOMUX_ACTIVE] = &cyts_sleep_act_cfg,
+ [GPIOMUX_SUSPENDED] = &cyts_sleep_sus_cfg,
+ },
+ },
+ { /* TS RESOUT */
+ .gpio = 52,
+ .settings = {
+ [GPIOMUX_ACTIVE] = &cyts_resout_act_cfg,
+ [GPIOMUX_SUSPENDED] = &cyts_resout_sus_cfg,
+ },
+ },
+};
+
+#ifdef CONFIG_USB_EHCI_MSM_HSIC
+static struct msm_gpiomux_config msm8960_hsic_configs[] = {
+ {
+ .gpio = 150, /*HSIC_STROBE */
+ .settings = {
+ [GPIOMUX_ACTIVE] = &hsic_act_cfg,
+ [GPIOMUX_SUSPENDED] = &hsic_sus_cfg,
+ },
+ },
+ {
+ .gpio = 151, /* HSIC_DATA */
+ .settings = {
+ [GPIOMUX_ACTIVE] = &hsic_act_cfg,
+ [GPIOMUX_SUSPENDED] = &hsic_sus_cfg,
+ },
+ },
+ {
+ .gpio = 91, /* HSIC_HUB_RESET */
+ .settings = {
+ [GPIOMUX_ACTIVE] = &hsic_hub_act_cfg,
+ [GPIOMUX_SUSPENDED] = &hsic_sus_cfg,
+ },
+ },
+};
+#endif
+
+static struct msm_gpiomux_config hap_lvl_shft_config[] __initdata = {
+ {
+ .gpio = 47,
+ .settings = {
+ [GPIOMUX_SUSPENDED] = &hap_lvl_shft_suspended_config,
+ [GPIOMUX_ACTIVE] = &hap_lvl_shft_active_config,
+ },
+ },
+};
+
+static struct msm_gpiomux_config mdm_configs[] __initdata = {
+ /* AP2MDM_STATUS */
+ {
+ .gpio = 94,
+ .settings = {
+ [GPIOMUX_SUSPENDED] = &ap2mdm_cfg,
+ }
+ },
+ /* MDM2AP_STATUS */
+ {
+ .gpio = 69,
+ .settings = {
+ [GPIOMUX_SUSPENDED] = &mdm2ap_status_cfg,
+ }
+ },
+ /* MDM2AP_ERRFATAL */
+ {
+ .gpio = 70,
+ .settings = {
+ [GPIOMUX_SUSPENDED] = &mdm2ap_errfatal_cfg,
+ }
+ },
+ /* AP2MDM_ERRFATAL */
+ {
+ .gpio = 95,
+ .settings = {
+ [GPIOMUX_SUSPENDED] = &ap2mdm_cfg,
+ }
+ },
+ /* AP2MDM_KPDPWR_N */
+ {
+ .gpio = 81,
+ .settings = {
+ [GPIOMUX_SUSPENDED] = &ap2mdm_kpdpwr_n_cfg,
+ }
+ },
+ /* AP2MDM_PMIC_RESET_N */
+ {
+ .gpio = 80,
+ .settings = {
+ [GPIOMUX_SUSPENDED] = &ap2mdm_kpdpwr_n_cfg,
+ }
+ }
+};
+
+static struct msm_gpiomux_config msm8960_mdp_vsync_configs[] __initdata = {
+ {
+ .gpio = 0,
+ .settings = {
+ [GPIOMUX_ACTIVE] = &mdp_vsync_active_cfg,
+ [GPIOMUX_SUSPENDED] = &mdp_vsync_suspend_cfg,
+ },
+ }
+};
+
+#ifdef CONFIG_FB_MSM_HDMI_MSM_PANEL
+static struct msm_gpiomux_config msm8960_hdmi_configs[] __initdata = {
+ {
+ .gpio = 99,
+ .settings = {
+ [GPIOMUX_ACTIVE] = &hdmi_active_1_cfg,
+ [GPIOMUX_SUSPENDED] = &hdmi_suspend_cfg,
+ },
+ },
+ {
+ .gpio = 100,
+ .settings = {
+ [GPIOMUX_ACTIVE] = &hdmi_active_1_cfg,
+ [GPIOMUX_SUSPENDED] = &hdmi_suspend_cfg,
+ },
+ },
+ {
+ .gpio = 101,
+ .settings = {
+ [GPIOMUX_ACTIVE] = &hdmi_active_1_cfg,
+ [GPIOMUX_SUSPENDED] = &hdmi_suspend_cfg,
+ },
+ },
+ {
+ .gpio = 102,
+ .settings = {
+ [GPIOMUX_ACTIVE] = &hdmi_active_2_cfg,
+ [GPIOMUX_SUSPENDED] = &hdmi_suspend_cfg,
+ },
+ },
+};
+#endif
+
+int __init msm8930_init_gpiomux(void)
+{
+ int rc = msm_gpiomux_init(NR_GPIO_IRQS);
+ if (rc) {
+ pr_err(KERN_ERR "msm_gpiomux_init failed %d\n", rc);
+ return rc;
+ }
+
+#if defined(CONFIG_KS8851) || defined(CONFIG_KS8851_MODULE)
+ msm_gpiomux_install(msm8960_ethernet_configs,
+ ARRAY_SIZE(msm8960_ethernet_configs));
+#endif
+
+ msm_gpiomux_install(msm8960_gsbi_configs,
+ ARRAY_SIZE(msm8960_gsbi_configs));
+
+ msm_gpiomux_install(msm8960_cyts_configs,
+ ARRAY_SIZE(msm8960_cyts_configs));
+
+ msm_gpiomux_install(msm8960_slimbus_config,
+ ARRAY_SIZE(msm8960_slimbus_config));
+
+ msm_gpiomux_install(msm8960_audio_codec_configs,
+ ARRAY_SIZE(msm8960_audio_codec_configs));
+
+ msm_gpiomux_install(msm8960_audio_auxpcm_configs,
+ ARRAY_SIZE(msm8960_audio_auxpcm_configs));
+
+ msm_gpiomux_install(wcnss_5wire_interface,
+ ARRAY_SIZE(wcnss_5wire_interface));
+
+ if (machine_is_msm8930_mtp() || machine_is_msm8930_fluid() ||
+ machine_is_msm8930_cdp())
+ msm_gpiomux_install(hap_lvl_shft_config,
+ ARRAY_SIZE(hap_lvl_shft_config));
+
+ if (PLATFORM_IS_CHARM25())
+ msm_gpiomux_install(mdm_configs,
+ ARRAY_SIZE(mdm_configs));
+
+#ifdef CONFIG_USB_EHCI_MSM_HSIC
+ if ((SOCINFO_VERSION_MAJOR(socinfo_get_version()) != 1) &&
+ !machine_is_msm8930_mtp() &&
+ !machine_is_msm8930_fluid())
+ msm_gpiomux_install(msm8960_hsic_configs,
+ ARRAY_SIZE(msm8960_hsic_configs));
+#endif
+
+#ifdef CONFIG_FB_MSM_HDMI_MSM_PANEL
+ msm_gpiomux_install(msm8960_hdmi_configs,
+ ARRAY_SIZE(msm8960_hdmi_configs));
+#endif
+
+ msm_gpiomux_install(msm8960_mdp_vsync_configs,
+ ARRAY_SIZE(msm8960_mdp_vsync_configs));
+ return 0;
+}
diff --git a/arch/arm/mach-msm/board-8930-pmic.c b/arch/arm/mach-msm/board-8930-pmic.c
new file mode 100644
index 0000000..cfb2347
--- /dev/null
+++ b/arch/arm/mach-msm/board-8930-pmic.c
@@ -0,0 +1,499 @@
+/* Copyright (c) 2011, Code Aurora Forum. 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 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#include <linux/interrupt.h>
+#include <linux/mfd/pm8xxx/pm8921.h>
+#include <linux/mfd/pm8xxx/pm8xxx-adc.h>
+#include <linux/leds.h>
+#include <linux/leds-pm8xxx.h>
+#include <linux/msm_ssbi.h>
+#include <asm/mach-types.h>
+#include <mach/msm_bus_board.h>
+#include <mach/restart.h>
+#include "devices.h"
+#include "board-8930.h"
+
+struct pm8xxx_gpio_init {
+ unsigned gpio;
+ struct pm_gpio config;
+};
+
+struct pm8xxx_mpp_init {
+ unsigned mpp;
+ struct pm8xxx_mpp_config_data config;
+};
+
+#define PM8XXX_GPIO_INIT(_gpio, _dir, _buf, _val, _pull, _vin, _out_strength, \
+ _func, _inv, _disable) \
+{ \
+ .gpio = PM8921_GPIO_PM_TO_SYS(_gpio), \
+ .config = { \
+ .direction = _dir, \
+ .output_buffer = _buf, \
+ .output_value = _val, \
+ .pull = _pull, \
+ .vin_sel = _vin, \
+ .out_strength = _out_strength, \
+ .function = _func, \
+ .inv_int_pol = _inv, \
+ .disable_pin = _disable, \
+ } \
+}
+
+#define PM8XXX_MPP_INIT(_mpp, _type, _level, _control) \
+{ \
+ .mpp = PM8921_MPP_PM_TO_SYS(_mpp), \
+ .config = { \
+ .type = PM8XXX_MPP_TYPE_##_type, \
+ .level = _level, \
+ .control = PM8XXX_MPP_##_control, \
+ } \
+}
+
+#define PM8XXX_GPIO_DISABLE(_gpio) \
+ PM8XXX_GPIO_INIT(_gpio, PM_GPIO_DIR_IN, 0, 0, 0, PM_GPIO_VIN_S4, \
+ 0, 0, 0, 1)
+
+#define PM8XXX_GPIO_OUTPUT(_gpio, _val) \
+ PM8XXX_GPIO_INIT(_gpio, PM_GPIO_DIR_OUT, PM_GPIO_OUT_BUF_CMOS, _val, \
+ PM_GPIO_PULL_NO, PM_GPIO_VIN_S4, \
+ PM_GPIO_STRENGTH_HIGH, \
+ PM_GPIO_FUNC_NORMAL, 0, 0)
+
+#define PM8XXX_GPIO_INPUT(_gpio, _pull) \
+ PM8XXX_GPIO_INIT(_gpio, PM_GPIO_DIR_IN, PM_GPIO_OUT_BUF_CMOS, 0, \
+ _pull, PM_GPIO_VIN_S4, \
+ PM_GPIO_STRENGTH_NO, \
+ PM_GPIO_FUNC_NORMAL, 0, 0)
+
+#define PM8XXX_GPIO_OUTPUT_FUNC(_gpio, _val, _func) \
+ PM8XXX_GPIO_INIT(_gpio, PM_GPIO_DIR_OUT, PM_GPIO_OUT_BUF_CMOS, _val, \
+ PM_GPIO_PULL_NO, PM_GPIO_VIN_S4, \
+ PM_GPIO_STRENGTH_HIGH, \
+ _func, 0, 0)
+
+#define PM8XXX_GPIO_OUTPUT_VIN(_gpio, _val, _vin) \
+ PM8XXX_GPIO_INIT(_gpio, PM_GPIO_DIR_OUT, PM_GPIO_OUT_BUF_CMOS, _val, \
+ PM_GPIO_PULL_NO, _vin, \
+ PM_GPIO_STRENGTH_HIGH, \
+ PM_GPIO_FUNC_NORMAL, 0, 0)
+
+/* Initial PM8921 GPIO configurations */
+static struct pm8xxx_gpio_init pm8921_gpios[] __initdata = {
+ PM8XXX_GPIO_DISABLE(6), /* Disable unused */
+ PM8XXX_GPIO_DISABLE(7), /* Disable NFC */
+ PM8XXX_GPIO_INPUT(16, PM_GPIO_PULL_UP_30), /* SD_CARD_WP */
+ /* External regulator shared by display and touchscreen on LiQUID */
+ PM8XXX_GPIO_OUTPUT(17, 0), /* DISP 3.3 V Boost */
+ PM8XXX_GPIO_OUTPUT_VIN(21, 1, PM_GPIO_VIN_VPH), /* Backlight Enable */
+ PM8XXX_GPIO_DISABLE(22), /* Disable NFC */
+ PM8XXX_GPIO_OUTPUT_FUNC(24, 0, PM_GPIO_FUNC_2), /* Bl: Off, PWM mode */
+ PM8XXX_GPIO_INPUT(26, PM_GPIO_PULL_UP_30), /* SD_CARD_DET_N */
+ PM8XXX_GPIO_OUTPUT(43, PM_GPIO_PULL_UP_30), /* DISP_RESET_N */
+ PM8XXX_GPIO_OUTPUT(42, 0), /* USB 5V reg enable */
+};
+
+/* Initial PM8921 MPP configurations */
+static struct pm8xxx_mpp_init pm8921_mpps[] __initdata = {
+ /* External 5V regulator enable; shared by HDMI and USB_OTG switches. */
+ PM8XXX_MPP_INIT(7, D_INPUT, PM8921_MPP_DIG_LEVEL_VPH, DIN_TO_INT),
+ PM8XXX_MPP_INIT(PM8XXX_AMUX_MPP_8, A_INPUT, PM8XXX_MPP_AIN_AMUX_CH8,
+ DOUT_CTRL_LOW),
+};
+
+void __init msm8930_pm8921_gpio_mpp_init(void)
+{
+ int i, rc;
+
+ for (i = 0; i < ARRAY_SIZE(pm8921_gpios); i++) {
+ rc = pm8xxx_gpio_config(pm8921_gpios[i].gpio,
+ &pm8921_gpios[i].config);
+ if (rc) {
+ pr_err("%s: pm8xxx_gpio_config: rc=%d\n", __func__, rc);
+ break;
+ }
+ }
+
+ for (i = 0; i < ARRAY_SIZE(pm8921_mpps); i++) {
+ rc = pm8xxx_mpp_config(pm8921_mpps[i].mpp,
+ &pm8921_mpps[i].config);
+ if (rc) {
+ pr_err("%s: pm8xxx_mpp_config: rc=%d\n", __func__, rc);
+ break;
+ }
+ }
+}
+
+static struct pm8xxx_adc_amux pm8xxx_adc_channels_data[] = {
+ {"vcoin", CHANNEL_VCOIN, CHAN_PATH_SCALING2, AMUX_RSV1,
+ ADC_DECIMATION_TYPE2, ADC_SCALE_DEFAULT},
+ {"vbat", CHANNEL_VBAT, CHAN_PATH_SCALING2, AMUX_RSV1,
+ ADC_DECIMATION_TYPE2, ADC_SCALE_DEFAULT},
+ {"dcin", CHANNEL_DCIN, CHAN_PATH_SCALING4, AMUX_RSV1,
+ ADC_DECIMATION_TYPE2, ADC_SCALE_DEFAULT},
+ {"ichg", CHANNEL_ICHG, CHAN_PATH_SCALING1, AMUX_RSV1,
+ ADC_DECIMATION_TYPE2, ADC_SCALE_DEFAULT},
+ {"vph_pwr", CHANNEL_VPH_PWR, CHAN_PATH_SCALING2, AMUX_RSV1,
+ ADC_DECIMATION_TYPE2, ADC_SCALE_DEFAULT},
+ {"ibat", CHANNEL_IBAT, CHAN_PATH_SCALING1, AMUX_RSV1,
+ ADC_DECIMATION_TYPE2, ADC_SCALE_DEFAULT},
+ {"batt_therm", CHANNEL_BATT_THERM, CHAN_PATH_SCALING1, AMUX_RSV2,
+ ADC_DECIMATION_TYPE2, ADC_SCALE_BATT_THERM},
+ {"batt_id", CHANNEL_BATT_ID, CHAN_PATH_SCALING1, AMUX_RSV1,
+ ADC_DECIMATION_TYPE2, ADC_SCALE_DEFAULT},
+ {"usbin", CHANNEL_USBIN, CHAN_PATH_SCALING3, AMUX_RSV1,
+ ADC_DECIMATION_TYPE2, ADC_SCALE_DEFAULT},
+ {"pmic_therm", CHANNEL_DIE_TEMP, CHAN_PATH_SCALING1, AMUX_RSV1,
+ ADC_DECIMATION_TYPE2, ADC_SCALE_PMIC_THERM},
+ {"625mv", CHANNEL_625MV, CHAN_PATH_SCALING1, AMUX_RSV1,
+ ADC_DECIMATION_TYPE2, ADC_SCALE_DEFAULT},
+ {"125v", CHANNEL_125V, CHAN_PATH_SCALING1, AMUX_RSV1,
+ ADC_DECIMATION_TYPE2, ADC_SCALE_DEFAULT},
+ {"chg_temp", CHANNEL_CHG_TEMP, CHAN_PATH_SCALING1, AMUX_RSV1,
+ ADC_DECIMATION_TYPE2, ADC_SCALE_DEFAULT},
+ {"pa_therm1", ADC_MPP_1_AMUX8, CHAN_PATH_SCALING1, AMUX_RSV1,
+ ADC_DECIMATION_TYPE2, ADC_SCALE_PA_THERM},
+ {"xo_therm", CHANNEL_MUXOFF, CHAN_PATH_SCALING1, AMUX_RSV0,
+ ADC_DECIMATION_TYPE2, ADC_SCALE_XOTHERM},
+ {"pa_therm0", ADC_MPP_1_AMUX3, CHAN_PATH_SCALING1, AMUX_RSV1,
+ ADC_DECIMATION_TYPE2, ADC_SCALE_PA_THERM},
+};
+
+static struct pm8xxx_adc_properties pm8xxx_adc_data = {
+ .adc_vdd_reference = 1800, /* milli-voltage for this adc */
+ .bitresolution = 15,
+ .bipolar = 0,
+};
+
+static struct pm8xxx_adc_platform_data pm8xxx_adc_pdata = {
+ .adc_channel = pm8xxx_adc_channels_data,
+ .adc_num_board_channel = ARRAY_SIZE(pm8xxx_adc_channels_data),
+ .adc_prop = &pm8xxx_adc_data,
+ .adc_mpp_base = PM8921_MPP_PM_TO_SYS(1),
+};
+
+
+static struct pm8xxx_irq_platform_data pm8xxx_irq_pdata __devinitdata = {
+ .irq_base = PM8921_IRQ_BASE,
+ .devirq = MSM_GPIO_TO_INT(104),
+ .irq_trigger_flag = IRQF_TRIGGER_LOW,
+};
+
+static struct pm8xxx_gpio_platform_data pm8xxx_gpio_pdata __devinitdata = {
+ .gpio_base = PM8921_GPIO_PM_TO_SYS(1),
+};
+
+static struct pm8xxx_mpp_platform_data pm8xxx_mpp_pdata __devinitdata = {
+ .mpp_base = PM8921_MPP_PM_TO_SYS(1),
+};
+
+static struct pm8xxx_rtc_platform_data pm8xxx_rtc_pdata __devinitdata = {
+ .rtc_write_enable = false,
+ .rtc_alarm_powerup = false,
+};
+
+static struct pm8xxx_pwrkey_platform_data pm8xxx_pwrkey_pdata = {
+ .pull_up = 1,
+ .kpd_trigger_delay_us = 970,
+ .wakeup = 1,
+};
+
+/* Rotate lock key is not available so use F1 */
+#define KEY_ROTATE_LOCK KEY_F1
+
+static const unsigned int keymap_liquid[] = {
+ KEY(0, 0, KEY_VOLUMEUP),
+ KEY(0, 1, KEY_VOLUMEDOWN),
+ KEY(1, 3, KEY_ROTATE_LOCK),
+ KEY(1, 4, KEY_HOME),
+};
+
+static const unsigned int keymap[] = {
+ KEY(0, 0, KEY_VOLUMEUP),
+ KEY(0, 1, KEY_VOLUMEDOWN),
+ KEY(0, 2, KEY_CAMERA_SNAPSHOT),
+ KEY(0, 3, KEY_CAMERA_FOCUS),
+};
+
+static struct matrix_keymap_data keymap_data = {
+ .keymap_size = ARRAY_SIZE(keymap),
+ .keymap = keymap,
+};
+
+static struct pm8xxx_keypad_platform_data keypad_data = {
+ .input_name = "keypad_8960",
+ .input_phys_device = "keypad_8960/input0",
+ .num_rows = 1,
+ .num_cols = 5,
+ .rows_gpio_start = PM8921_GPIO_PM_TO_SYS(9),
+ .cols_gpio_start = PM8921_GPIO_PM_TO_SYS(1),
+ .debounce_ms = 15,
+ .scan_delay_ms = 32,
+ .row_hold_ns = 91500,
+ .wakeup = 1,
+ .keymap_data = &keymap_data,
+};
+
+static const unsigned int keymap_sim[] = {
+ KEY(0, 0, KEY_7),
+ KEY(0, 1, KEY_DOWN),
+ KEY(0, 2, KEY_UP),
+ KEY(0, 3, KEY_RIGHT),
+ KEY(0, 4, KEY_ENTER),
+ KEY(0, 5, KEY_L),
+ KEY(0, 6, KEY_BACK),
+ KEY(0, 7, KEY_M),
+
+ KEY(1, 0, KEY_LEFT),
+ KEY(1, 1, KEY_SEND),
+ KEY(1, 2, KEY_1),
+ KEY(1, 3, KEY_4),
+ KEY(1, 4, KEY_CLEAR),
+ KEY(1, 5, KEY_MSDOS),
+ KEY(1, 6, KEY_SPACE),
+ KEY(1, 7, KEY_COMMA),
+
+ KEY(2, 0, KEY_6),
+ KEY(2, 1, KEY_5),
+ KEY(2, 2, KEY_8),
+ KEY(2, 3, KEY_3),
+ KEY(2, 4, KEY_NUMERIC_STAR),
+ KEY(2, 5, KEY_UP),
+ KEY(2, 6, KEY_DOWN),
+ KEY(2, 7, KEY_LEFTSHIFT),
+
+ KEY(3, 0, KEY_9),
+ KEY(3, 1, KEY_NUMERIC_POUND),
+ KEY(3, 2, KEY_0),
+ KEY(3, 3, KEY_2),
+ KEY(3, 4, KEY_SLEEP),
+ KEY(3, 5, KEY_F1),
+ KEY(3, 6, KEY_F2),
+ KEY(3, 7, KEY_F3),
+
+ KEY(4, 0, KEY_BACK),
+ KEY(4, 1, KEY_HOME),
+ KEY(4, 2, KEY_MENU),
+ KEY(4, 3, KEY_VOLUMEUP),
+ KEY(4, 4, KEY_VOLUMEDOWN),
+ KEY(4, 5, KEY_F4),
+ KEY(4, 6, KEY_F5),
+ KEY(4, 7, KEY_F6),
+
+ KEY(5, 0, KEY_R),
+ KEY(5, 1, KEY_T),
+ KEY(5, 2, KEY_Y),
+ KEY(5, 3, KEY_LEFTALT),
+ KEY(5, 4, KEY_KPENTER),
+ KEY(5, 5, KEY_Q),
+ KEY(5, 6, KEY_W),
+ KEY(5, 7, KEY_E),
+
+ KEY(6, 0, KEY_F),
+ KEY(6, 1, KEY_G),
+ KEY(6, 2, KEY_H),
+ KEY(6, 3, KEY_CAPSLOCK),
+ KEY(6, 4, KEY_PAGEUP),
+ KEY(6, 5, KEY_A),
+ KEY(6, 6, KEY_S),
+ KEY(6, 7, KEY_D),
+
+ KEY(7, 0, KEY_V),
+ KEY(7, 1, KEY_B),
+ KEY(7, 2, KEY_N),
+ KEY(7, 3, KEY_MENU),
+ KEY(7, 4, KEY_PAGEDOWN),
+ KEY(7, 5, KEY_Z),
+ KEY(7, 6, KEY_X),
+ KEY(7, 7, KEY_C),
+
+ KEY(8, 0, KEY_P),
+ KEY(8, 1, KEY_J),
+ KEY(8, 2, KEY_K),
+ KEY(8, 3, KEY_INSERT),
+ KEY(8, 4, KEY_LINEFEED),
+ KEY(8, 5, KEY_U),
+ KEY(8, 6, KEY_I),
+ KEY(8, 7, KEY_O),
+
+ KEY(9, 0, KEY_4),
+ KEY(9, 1, KEY_5),
+ KEY(9, 2, KEY_6),
+ KEY(9, 3, KEY_7),
+ KEY(9, 4, KEY_8),
+ KEY(9, 5, KEY_1),
+ KEY(9, 6, KEY_2),
+ KEY(9, 7, KEY_3),
+
+ KEY(10, 0, KEY_F7),
+ KEY(10, 1, KEY_F8),
+ KEY(10, 2, KEY_F9),
+ KEY(10, 3, KEY_F10),
+ KEY(10, 4, KEY_FN),
+ KEY(10, 5, KEY_9),
+ KEY(10, 6, KEY_0),
+ KEY(10, 7, KEY_DOT),
+
+ KEY(11, 0, KEY_LEFTCTRL),
+ KEY(11, 1, KEY_F11),
+ KEY(11, 2, KEY_ENTER),
+ KEY(11, 3, KEY_SEARCH),
+ KEY(11, 4, KEY_DELETE),
+ KEY(11, 5, KEY_RIGHT),
+ KEY(11, 6, KEY_LEFT),
+ KEY(11, 7, KEY_RIGHTSHIFT),
+ KEY(0, 0, KEY_VOLUMEUP),
+ KEY(0, 1, KEY_VOLUMEDOWN),
+ KEY(0, 2, KEY_CAMERA_SNAPSHOT),
+ KEY(0, 3, KEY_CAMERA_FOCUS),
+};
+
+static int pm8921_therm_mitigation[] = {
+ 1100,
+ 700,
+ 600,
+ 325,
+};
+
+static struct pm8921_charger_platform_data pm8921_chg_pdata __devinitdata = {
+ .safety_time = 180,
+ .update_time = 60000,
+ .max_voltage = 4200,
+ .min_voltage = 3200,
+ .resume_voltage_delta = 100,
+ .term_current = 100,
+ .cool_temp = 10,
+ .warm_temp = 40,
+ .temp_check_period = 1,
+ .max_bat_chg_current = 1100,
+ .cool_bat_chg_current = 350,
+ .warm_bat_chg_current = 350,
+ .cool_bat_voltage = 4100,
+ .warm_bat_voltage = 4100,
+ .thermal_mitigation = pm8921_therm_mitigation,
+ .thermal_levels = ARRAY_SIZE(pm8921_therm_mitigation),
+};
+
+static struct pm8xxx_misc_platform_data pm8xxx_misc_pdata = {
+ .priority = 0,
+};
+
+static struct pm8921_bms_platform_data pm8921_bms_pdata __devinitdata = {
+ .r_sense = 10,
+ .i_test = 2500,
+ .v_failure = 3000,
+ .calib_delay_ms = 600000,
+};
+
+#define PM8921_LC_LED_MAX_CURRENT 4 /* I = 4mA */
+#define PM8XXX_LED_PWM_PERIOD 1000
+#define PM8XXX_LED_PWM_DUTY_MS 20
+/**
+ * PM8XXX_PWM_CHANNEL_NONE shall be used when LED shall not be
+ * driven using PWM feature.
+ */
+#define PM8XXX_PWM_CHANNEL_NONE -1
+
+static struct led_info pm8921_led_info[] = {
+ [0] = {
+ .name = "led:battery_charging",
+ .default_trigger = "battery-charging",
+ },
+ [1] = {
+ .name = "led:battery_full",
+ .default_trigger = "battery-full",
+ },
+};
+
+static struct led_platform_data pm8921_led_core_pdata = {
+ .num_leds = ARRAY_SIZE(pm8921_led_info),
+ .leds = pm8921_led_info,
+};
+
+static int pm8921_led0_pwm_duty_pcts[56] = {
+ 1, 4, 8, 12, 16, 20, 24, 28, 32, 36,
+ 40, 44, 46, 52, 56, 60, 64, 68, 72, 76,
+ 80, 84, 88, 92, 96, 100, 100, 100, 98, 95,
+ 92, 88, 84, 82, 78, 74, 70, 66, 62, 58,
+ 58, 54, 50, 48, 42, 38, 34, 30, 26, 22,
+ 14, 10, 6, 4, 1
+};
+
+static struct pm8xxx_pwm_duty_cycles pm8921_led0_pwm_duty_cycles = {
+ .duty_pcts = (int *)&pm8921_led0_pwm_duty_pcts,
+ .num_duty_pcts = ARRAY_SIZE(pm8921_led0_pwm_duty_pcts),
+ .duty_ms = PM8XXX_LED_PWM_DUTY_MS,
+ .start_idx = 0,
+};
+
+static struct pm8xxx_led_config pm8921_led_configs[] = {
+ [0] = {
+ .id = PM8XXX_ID_LED_0,
+ .mode = PM8XXX_LED_MODE_PWM2,
+ .max_current = PM8921_LC_LED_MAX_CURRENT,
+ .pwm_channel = 5,
+ .pwm_period_us = PM8XXX_LED_PWM_PERIOD,
+ .pwm_duty_cycles = &pm8921_led0_pwm_duty_cycles,
+ },
+ [1] = {
+ .id = PM8XXX_ID_LED_1,
+ .mode = PM8XXX_LED_MODE_PWM1,
+ .max_current = PM8921_LC_LED_MAX_CURRENT,
+ .pwm_channel = 4,
+ .pwm_period_us = PM8XXX_LED_PWM_PERIOD,
+ },
+};
+
+static struct pm8xxx_led_platform_data pm8xxx_leds_pdata = {
+ .led_core = &pm8921_led_core_pdata,
+ .configs = pm8921_led_configs,
+ .num_configs = ARRAY_SIZE(pm8921_led_configs),
+};
+
+static struct pm8xxx_ccadc_platform_data pm8xxx_ccadc_pdata = {
+ .r_sense = 10,
+};
+
+static struct pm8921_platform_data pm8921_platform_data __devinitdata = {
+ .irq_pdata = &pm8xxx_irq_pdata,
+ .gpio_pdata = &pm8xxx_gpio_pdata,
+ .mpp_pdata = &pm8xxx_mpp_pdata,
+ .rtc_pdata = &pm8xxx_rtc_pdata,
+ .pwrkey_pdata = &pm8xxx_pwrkey_pdata,
+ .keypad_pdata = &keypad_data,
+ .misc_pdata = &pm8xxx_misc_pdata,
+ .regulator_pdatas = msm_pm8921_regulator_pdata,
+ .charger_pdata = &pm8921_chg_pdata,
+ .bms_pdata = &pm8921_bms_pdata,
+ .adc_pdata = &pm8xxx_adc_pdata,
+ .leds_pdata = &pm8xxx_leds_pdata,
+ .ccadc_pdata = &pm8xxx_ccadc_pdata,
+};
+
+static struct msm_ssbi_platform_data msm8960_ssbi_pm8921_pdata __devinitdata = {
+ .controller_type = MSM_SBI_CTRL_PMIC_ARBITER,
+ .slave = {
+ .name = "pm8921-core",
+ .platform_data = &pm8921_platform_data,
+ },
+};
+
+void __init msm8930_init_pmic(void)
+{
+ pmic_reset_irq = PM8921_IRQ_BASE + PM8921_RESOUT_IRQ;
+ msm8960_device_ssbi_pm8921.dev.platform_data =
+ &msm8960_ssbi_pm8921_pdata;
+ pm8921_platform_data.num_regulators = msm_pm8921_regulator_pdata_len;
+
+ /* Simulator supports a QWERTY keypad */
+}
diff --git a/arch/arm/mach-msm/board-8930-storage.c b/arch/arm/mach-msm/board-8930-storage.c
new file mode 100644
index 0000000..032d3d0
--- /dev/null
+++ b/arch/arm/mach-msm/board-8930-storage.c
@@ -0,0 +1,268 @@
+/* Copyright (c) 2011, Code Aurora Forum. 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 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#include <linux/init.h>
+#include <linux/ioport.h>
+#include <linux/platform_device.h>
+#include <linux/bootmem.h>
+#include <asm/mach-types.h>
+#include <asm/mach/mmc.h>
+#include <mach/msm_bus_board.h>
+#include <mach/board.h>
+#include <mach/gpio.h>
+#include <mach/gpiomux.h>
+#include "devices.h"
+#include "board-8930.h"
+
+/* MSM8960 has 5 SDCC controllers */
+enum sdcc_controllers {
+ SDCC1,
+ SDCC2,
+ SDCC3,
+ SDCC4,
+ SDCC5,
+ MAX_SDCC_CONTROLLER
+};
+
+/* All SDCC controllers require VDD/VCC voltage */
+static struct msm_mmc_reg_data mmc_vdd_reg_data[MAX_SDCC_CONTROLLER] = {
+ /* SDCC1 : eMMC card connected */
+ [SDCC1] = {
+ .name = "sdc_vdd",
+ .high_vol_level = 2950000,
+ .low_vol_level = 2950000,
+ .always_on = 1,
+ .lpm_sup = 1,
+ .lpm_uA = 9000,
+ .hpm_uA = 200000, /* 200mA */
+ },
+ /* SDCC3 : External card slot connected */
+ [SDCC3] = {
+ .name = "sdc_vdd",
+ .high_vol_level = 2950000,
+ .low_vol_level = 2950000,
+ .hpm_uA = 600000, /* 600mA */
+ }
+};
+
+/* Only slots having eMMC card will require VCCQ voltage */
+static struct msm_mmc_reg_data mmc_vccq_reg_data[1] = {
+ /* SDCC1 : eMMC card connected */
+ [SDCC1] = {
+ .name = "sdc_vccq",
+ .always_on = 1,
+ .high_vol_level = 1800000,
+ .low_vol_level = 1800000,
+ .hpm_uA = 200000, /* 200mA */
+ }
+};
+
+/* All SDCC controllers may require voting for VDD PAD voltage */
+static struct msm_mmc_reg_data mmc_vddp_reg_data[MAX_SDCC_CONTROLLER] = {
+ /* SDCC3 : External card slot connected */
+ [SDCC3] = {
+ .name = "sdc_vddp",
+ .high_vol_level = 2950000,
+ .low_vol_level = 1850000,
+ .always_on = 1,
+ .lpm_sup = 1,
+ /* Max. Active current required is 16 mA */
+ .hpm_uA = 16000,
+ /*
+ * Sleep current required is ~300 uA. But min. vote can be
+ * in terms of mA (min. 1 mA). So let's vote for 2 mA
+ * during sleep.
+ */
+ .lpm_uA = 2000,
+ }
+};
+
+static struct msm_mmc_slot_reg_data mmc_slot_vreg_data[MAX_SDCC_CONTROLLER] = {
+ /* SDCC1 : eMMC card connected */
+ [SDCC1] = {
+ .vdd_data = &mmc_vdd_reg_data[SDCC1],
+ .vccq_data = &mmc_vccq_reg_data[SDCC1],
+ },
+ /* SDCC3 : External card slot connected */
+ [SDCC3] = {
+ .vdd_data = &mmc_vdd_reg_data[SDCC3],
+ .vddp_data = &mmc_vddp_reg_data[SDCC3],
+ }
+};
+
+/* SDC1 pad data */
+static struct msm_mmc_pad_drv sdc1_pad_drv_on_cfg[] = {
+ {TLMM_HDRV_SDC1_CLK, GPIO_CFG_16MA},
+ {TLMM_HDRV_SDC1_CMD, GPIO_CFG_10MA},
+ {TLMM_HDRV_SDC1_DATA, GPIO_CFG_10MA}
+};
+
+static struct msm_mmc_pad_drv sdc1_pad_drv_off_cfg[] = {
+ {TLMM_HDRV_SDC1_CLK, GPIO_CFG_2MA},
+ {TLMM_HDRV_SDC1_CMD, GPIO_CFG_2MA},
+ {TLMM_HDRV_SDC1_DATA, GPIO_CFG_2MA}
+};
+
+static struct msm_mmc_pad_pull sdc1_pad_pull_on_cfg[] = {
+ {TLMM_PULL_SDC1_CLK, GPIO_CFG_NO_PULL},
+ {TLMM_PULL_SDC1_CMD, GPIO_CFG_PULL_UP},
+ {TLMM_PULL_SDC1_DATA, GPIO_CFG_PULL_UP}
+};
+
+static struct msm_mmc_pad_pull sdc1_pad_pull_off_cfg[] = {
+ {TLMM_PULL_SDC1_CLK, GPIO_CFG_NO_PULL},
+ {TLMM_PULL_SDC1_CMD, GPIO_CFG_PULL_DOWN},
+ {TLMM_PULL_SDC1_DATA, GPIO_CFG_PULL_DOWN}
+};
+
+/* SDC3 pad data */
+static struct msm_mmc_pad_drv sdc3_pad_drv_on_cfg[] = {
+ {TLMM_HDRV_SDC3_CLK, GPIO_CFG_8MA},
+ {TLMM_HDRV_SDC3_CMD, GPIO_CFG_8MA},
+ {TLMM_HDRV_SDC3_DATA, GPIO_CFG_8MA}
+};
+
+static struct msm_mmc_pad_drv sdc3_pad_drv_off_cfg[] = {
+ {TLMM_HDRV_SDC3_CLK, GPIO_CFG_2MA},
+ {TLMM_HDRV_SDC3_CMD, GPIO_CFG_2MA},
+ {TLMM_HDRV_SDC3_DATA, GPIO_CFG_2MA}
+};
+
+static struct msm_mmc_pad_pull sdc3_pad_pull_on_cfg[] = {
+ {TLMM_PULL_SDC3_CLK, GPIO_CFG_NO_PULL},
+ {TLMM_PULL_SDC3_CMD, GPIO_CFG_PULL_UP},
+ {TLMM_PULL_SDC3_DATA, GPIO_CFG_PULL_UP}
+};
+
+static struct msm_mmc_pad_pull sdc3_pad_pull_off_cfg[] = {
+ {TLMM_PULL_SDC3_CLK, GPIO_CFG_NO_PULL},
+ /*
+ * SDC3 CMD line should be PULLed UP otherwise fluid platform will
+ * see transitions (1 -> 0 and 0 -> 1) on card detection line,
+ * which would result in false card detection interrupts.
+ */
+ {TLMM_PULL_SDC3_CMD, GPIO_CFG_PULL_UP},
+ /*
+ * Keeping DATA lines status to PULL UP will make sure that
+ * there is no current leak during sleep if external pull up
+ * is connected to DATA lines.
+ */
+ {TLMM_PULL_SDC3_DATA, GPIO_CFG_PULL_UP}
+};
+
+static struct msm_mmc_pad_pull_data mmc_pad_pull_data[MAX_SDCC_CONTROLLER] = {
+ [SDCC1] = {
+ .on = sdc1_pad_pull_on_cfg,
+ .off = sdc1_pad_pull_off_cfg,
+ .size = ARRAY_SIZE(sdc1_pad_pull_on_cfg)
+ },
+ [SDCC3] = {
+ .on = sdc3_pad_pull_on_cfg,
+ .off = sdc3_pad_pull_off_cfg,
+ .size = ARRAY_SIZE(sdc3_pad_pull_on_cfg)
+ },
+};
+
+static struct msm_mmc_pad_drv_data mmc_pad_drv_data[MAX_SDCC_CONTROLLER] = {
+ [SDCC1] = {
+ .on = sdc1_pad_drv_on_cfg,
+ .off = sdc1_pad_drv_off_cfg,
+ .size = ARRAY_SIZE(sdc1_pad_drv_on_cfg)
+ },
+ [SDCC3] = {
+ .on = sdc3_pad_drv_on_cfg,
+ .off = sdc3_pad_drv_off_cfg,
+ .size = ARRAY_SIZE(sdc3_pad_drv_on_cfg)
+ },
+};
+
+static struct msm_mmc_pad_data mmc_pad_data[MAX_SDCC_CONTROLLER] = {
+ [SDCC1] = {
+ .pull = &mmc_pad_pull_data[SDCC1],
+ .drv = &mmc_pad_drv_data[SDCC1]
+ },
+ [SDCC3] = {
+ .pull = &mmc_pad_pull_data[SDCC3],
+ .drv = &mmc_pad_drv_data[SDCC3]
+ },
+};
+
+static struct msm_mmc_pin_data mmc_slot_pin_data[MAX_SDCC_CONTROLLER] = {
+ [SDCC1] = {
+ .pad_data = &mmc_pad_data[SDCC1],
+ },
+ [SDCC3] = {
+ .pad_data = &mmc_pad_data[SDCC3],
+ },
+};
+
+static unsigned int sdc1_sup_clk_rates[] = {
+ 400000, 24000000, 48000000
+};
+
+static unsigned int sdc3_sup_clk_rates[] = {
+ 400000, 24000000, 48000000, 96000000
+};
+
+#ifdef CONFIG_MMC_MSM_SDC1_SUPPORT
+static struct mmc_platform_data msm8960_sdc1_data = {
+ .ocr_mask = MMC_VDD_27_28 | MMC_VDD_28_29,
+#ifdef CONFIG_MMC_MSM_SDC1_8_BIT_SUPPORT
+ .mmc_bus_width = MMC_CAP_8_BIT_DATA,
+#else
+ .mmc_bus_width = MMC_CAP_4_BIT_DATA,
+#endif
+ .sup_clk_table = sdc1_sup_clk_rates,
+ .sup_clk_cnt = ARRAY_SIZE(sdc1_sup_clk_rates),
+ .pclk_src_dfab = 1,
+ .nonremovable = 1,
+ .vreg_data = &mmc_slot_vreg_data[SDCC1],
+ .pin_data = &mmc_slot_pin_data[SDCC1]
+};
+#endif
+
+#ifdef CONFIG_MMC_MSM_SDC3_SUPPORT
+static struct mmc_platform_data msm8960_sdc3_data = {
+ .ocr_mask = MMC_VDD_27_28 | MMC_VDD_28_29,
+ .mmc_bus_width = MMC_CAP_4_BIT_DATA,
+ .sup_clk_table = sdc3_sup_clk_rates,
+ .sup_clk_cnt = ARRAY_SIZE(sdc3_sup_clk_rates),
+ .pclk_src_dfab = 1,
+#ifdef CONFIG_MMC_MSM_SDC3_WP_SUPPORT
+ .wpswitch_gpio = PM8921_GPIO_PM_TO_SYS(16),
+#endif
+ .vreg_data = &mmc_slot_vreg_data[SDCC3],
+ .pin_data = &mmc_slot_pin_data[SDCC3],
+#ifdef CONFIG_MMC_MSM_CARD_HW_DETECTION
+ .status_gpio = PM8921_GPIO_PM_TO_SYS(26),
+ .status_irq = PM8921_GPIO_IRQ(PM8921_IRQ_BASE, 26),
+ .irq_flags = IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING,
+#endif
+ .xpc_cap = 1,
+ .uhs_caps = (MMC_CAP_UHS_SDR12 | MMC_CAP_UHS_SDR25 |
+ MMC_CAP_UHS_SDR50 | MMC_CAP_UHS_DDR50 |
+ MMC_CAP_MAX_CURRENT_600)
+};
+#endif
+
+void __init msm8930_init_mmc(void)
+{
+#ifdef CONFIG_MMC_MSM_SDC1_SUPPORT
+ /* SDC1 : eMMC card connected */
+ msm_add_sdcc(1, &msm8960_sdc1_data);
+#endif
+#ifdef CONFIG_MMC_MSM_SDC3_SUPPORT
+ /* SDC3: External card slot */
+ msm_add_sdcc(3, &msm8960_sdc3_data);
+#endif
+}
diff --git a/arch/arm/mach-msm/board-8930.c b/arch/arm/mach-msm/board-8930.c
new file mode 100644
index 0000000..cc020b5
--- /dev/null
+++ b/arch/arm/mach-msm/board-8930.c
@@ -0,0 +1,1985 @@
+/* Copyright (c) 2011, Code Aurora Forum. 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 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ */
+#include <linux/kernel.h>
+#include <linux/platform_device.h>
+#include <linux/io.h>
+#include <linux/irq.h>
+#include <linux/i2c.h>
+#include <linux/i2c/sx150x.h>
+#include <linux/i2c/isl9519.h>
+#include <linux/gpio.h>
+#include <linux/msm_ssbi.h>
+#include <linux/regulator/gpio-regulator.h>
+#include <linux/mfd/pm8xxx/pm8921.h>
+#include <linux/mfd/pm8xxx/pm8xxx-adc.h>
+#include <linux/regulator/consumer.h>
+#include <linux/spi/spi.h>
+#include <linux/slimbus/slimbus.h>
+#include <linux/bootmem.h>
+#include <linux/msm_kgsl.h>
+#ifdef CONFIG_ANDROID_PMEM
+#include <linux/android_pmem.h>
+#endif
+#include <linux/cyttsp.h>
+#include <linux/dma-mapping.h>
+#include <linux/platform_data/qcom_crypto_device.h>
+#include <linux/platform_data/qcom_wcnss_device.h>
+#include <linux/leds.h>
+#include <linux/leds-pm8xxx.h>
+#include <linux/i2c/atmel_mxt_ts.h>
+#include <linux/msm_tsens.h>
+#include <linux/ks8851.h>
+#include <linux/i2c/isa1200.h>
+
+#include <asm/mach-types.h>
+#include <asm/mach/arch.h>
+#include <asm/setup.h>
+#include <asm/hardware/gic.h>
+#include <asm/mach/mmc.h>
+
+#include <mach/board.h>
+#include <mach/msm_iomap.h>
+#include <mach/msm_spi.h>
+#ifdef CONFIG_USB_MSM_OTG_72K
+#include <mach/msm_hsusb.h>
+#else
+#include <linux/usb/msm_hsusb.h>
+#endif
+#include <linux/usb/android.h>
+#include <mach/usbdiag.h>
+#include <mach/socinfo.h>
+#include <mach/rpm.h>
+#include <mach/gpio.h>
+#include <mach/gpiomux.h>
+#include <mach/msm_bus_board.h>
+#include <mach/msm_memtypes.h>
+#include <mach/dma.h>
+#include <mach/msm_xo.h>
+#include <mach/restart.h>
+
+#ifdef CONFIG_WCD9310_CODEC
+#include <linux/slimbus/slimbus.h>
+#include <linux/mfd/wcd9310/core.h>
+#include <linux/mfd/wcd9310/pdata.h>
+#endif
+
+#include <linux/ion.h>
+#include <mach/ion.h>
+#include <mach/mdm2.h>
+
+#include "timer.h"
+#include "devices.h"
+#include "devices-msm8x60.h"
+#include "spm.h"
+#include "board-8930.h"
+#include "pm.h"
+#include "cpuidle.h"
+#include "rpm_resources.h"
+#include "mpm.h"
+#include "acpuclock.h"
+#include "rpm_log.h"
+#include "smd_private.h"
+#include "pm-boot.h"
+#include "msm_watchdog.h"
+
+static struct platform_device msm_fm_platform_init = {
+ .name = "iris_fm",
+ .id = -1,
+};
+
+#define KS8851_RST_GPIO 89
+#define KS8851_IRQ_GPIO 90
+#define HAP_SHIFT_LVL_OE_GPIO 47
+
+#if defined(CONFIG_GPIO_SX150X) || defined(CONFIG_GPIO_SX150X_MODULE)
+
+struct sx150x_platform_data msm8930_sx150x_data[] = {
+ [SX150X_CAM] = {
+ .gpio_base = GPIO_CAM_EXPANDER_BASE,
+ .oscio_is_gpo = false,
+ .io_pullup_ena = 0x0,
+ .io_pulldn_ena = 0xc0,
+ .io_open_drain_ena = 0x0,
+ .irq_summary = -1,
+ },
+};
+
+#endif
+
+#define MSM_PMEM_ADSP_SIZE 0x3800000
+#define MSM_PMEM_AUDIO_SIZE 0x28B000
+#ifdef CONFIG_FB_MSM_HDMI_AS_PRIMARY
+#define MSM_PMEM_SIZE 0x4000000 /* 64 Mbytes */
+#else
+#define MSM_PMEM_SIZE 0x1C00000 /* 28 Mbytes */
+#endif
+
+
+#ifdef CONFIG_MSM_MULTIMEDIA_USE_ION
+#define MSM_PMEM_KERNEL_EBI1_SIZE 0xB0C000
+#define MSM_ION_EBI_SIZE (MSM_PMEM_SIZE + 0x600000)
+#define MSM_ION_ADSP_SIZE MSM_PMEM_ADSP_SIZE
+#define MSM_ION_HEAP_NUM 4
+#else
+#define MSM_PMEM_KERNEL_EBI1_SIZE 0x110C000
+#define MSM_ION_HEAP_NUM 2
+#endif
+
+#ifdef CONFIG_KERNEL_PMEM_EBI_REGION
+static unsigned pmem_kernel_ebi1_size = MSM_PMEM_KERNEL_EBI1_SIZE;
+static int __init pmem_kernel_ebi1_size_setup(char *p)
+{
+ pmem_kernel_ebi1_size = memparse(p, NULL);
+ return 0;
+}
+early_param("pmem_kernel_ebi1_size", pmem_kernel_ebi1_size_setup);
+#endif
+
+#ifdef CONFIG_ANDROID_PMEM
+static unsigned pmem_size = MSM_PMEM_SIZE;
+static int __init pmem_size_setup(char *p)
+{
+ pmem_size = memparse(p, NULL);
+ return 0;
+}
+early_param("pmem_size", pmem_size_setup);
+
+static unsigned pmem_adsp_size = MSM_PMEM_ADSP_SIZE;
+
+static int __init pmem_adsp_size_setup(char *p)
+{
+ pmem_adsp_size = memparse(p, NULL);
+ return 0;
+}
+early_param("pmem_adsp_size", pmem_adsp_size_setup);
+
+static unsigned pmem_audio_size = MSM_PMEM_AUDIO_SIZE;
+
+static int __init pmem_audio_size_setup(char *p)
+{
+ pmem_audio_size = memparse(p, NULL);
+ return 0;
+}
+early_param("pmem_audio_size", pmem_audio_size_setup);
+#endif
+
+#ifdef CONFIG_ANDROID_PMEM
+#ifndef CONFIG_MSM_MULTIMEDIA_USE_ION
+static struct android_pmem_platform_data android_pmem_pdata = {
+ .name = "pmem",
+ .allocator_type = PMEM_ALLOCATORTYPE_ALLORNOTHING,
+ .cached = 1,
+ .memory_type = MEMTYPE_EBI1,
+};
+
+static struct platform_device android_pmem_device = {
+ .name = "android_pmem",
+ .id = 0,
+ .dev = {.platform_data = &android_pmem_pdata},
+};
+
+static struct android_pmem_platform_data android_pmem_adsp_pdata = {
+ .name = "pmem_adsp",
+ .allocator_type = PMEM_ALLOCATORTYPE_BITMAP,
+ .cached = 0,
+ .memory_type = MEMTYPE_EBI1,
+};
+static struct platform_device android_pmem_adsp_device = {
+ .name = "android_pmem",
+ .id = 2,
+ .dev = { .platform_data = &android_pmem_adsp_pdata },
+};
+#endif
+
+static struct android_pmem_platform_data android_pmem_audio_pdata = {
+ .name = "pmem_audio",
+ .allocator_type = PMEM_ALLOCATORTYPE_BITMAP,
+ .cached = 0,
+ .memory_type = MEMTYPE_EBI1,
+};
+
+static struct platform_device android_pmem_audio_device = {
+ .name = "android_pmem",
+ .id = 4,
+ .dev = { .platform_data = &android_pmem_audio_pdata },
+};
+#endif
+
+#define DSP_RAM_BASE_8960 0x8da00000
+#define DSP_RAM_SIZE_8960 0x1800000
+static int dspcrashd_pdata_8960 = 0xDEADDEAD;
+
+static struct resource resources_dspcrashd_8960[] = {
+ {
+ .name = "msm_dspcrashd",
+ .start = DSP_RAM_BASE_8960,
+ .end = DSP_RAM_BASE_8960 + DSP_RAM_SIZE_8960,
+ .flags = IORESOURCE_DMA,
+ },
+};
+
+static struct platform_device msm_device_dspcrashd_8960 = {
+ .name = "msm_dspcrashd",
+ .num_resources = ARRAY_SIZE(resources_dspcrashd_8960),
+ .resource = resources_dspcrashd_8960,
+ .dev = { .platform_data = &dspcrashd_pdata_8960 },
+};
+
+static struct memtype_reserve msm8930_reserve_table[] __initdata = {
+ [MEMTYPE_SMI] = {
+ },
+ [MEMTYPE_EBI0] = {
+ .flags = MEMTYPE_FLAGS_1M_ALIGN,
+ },
+ [MEMTYPE_EBI1] = {
+ .flags = MEMTYPE_FLAGS_1M_ALIGN,
+ },
+};
+
+static void __init size_pmem_devices(void)
+{
+#ifdef CONFIG_ANDROID_PMEM
+#ifndef CONFIG_MSM_MULTIMEDIA_USE_ION
+ android_pmem_adsp_pdata.size = pmem_adsp_size;
+ android_pmem_pdata.size = pmem_size;
+#endif
+ android_pmem_audio_pdata.size = MSM_PMEM_AUDIO_SIZE;
+#endif
+}
+
+static void __init reserve_memory_for(struct android_pmem_platform_data *p)
+{
+ msm8930_reserve_table[p->memory_type].size += p->size;
+}
+
+static void __init reserve_pmem_memory(void)
+{
+#ifdef CONFIG_ANDROID_PMEM
+#ifndef CONFIG_MSM_MULTIMEDIA_USE_ION
+ reserve_memory_for(&android_pmem_adsp_pdata);
+ reserve_memory_for(&android_pmem_pdata);
+#endif
+ reserve_memory_for(&android_pmem_audio_pdata);
+ msm8930_reserve_table[MEMTYPE_EBI1].size += pmem_kernel_ebi1_size;
+#endif
+}
+
+static int msm8930_paddr_to_memtype(unsigned int paddr)
+{
+ return MEMTYPE_EBI1;
+}
+
+#ifdef CONFIG_ION_MSM
+static struct ion_platform_data ion_pdata = {
+ .nr = MSM_ION_HEAP_NUM,
+ .heaps = {
+ {
+ .id = ION_HEAP_SYSTEM_ID,
+ .type = ION_HEAP_TYPE_SYSTEM,
+ .name = ION_KMALLOC_HEAP_NAME,
+ },
+ {
+ .id = ION_HEAP_SYSTEM_CONTIG_ID,
+ .type = ION_HEAP_TYPE_SYSTEM_CONTIG,
+ .name = ION_VMALLOC_HEAP_NAME,
+ },
+#ifdef CONFIG_MSM_MULTIMEDIA_USE_ION
+ {
+ .id = ION_HEAP_EBI_ID,
+ .type = ION_HEAP_TYPE_CARVEOUT,
+ .name = ION_EBI1_HEAP_NAME,
+ .size = MSM_ION_EBI_SIZE,
+ .memory_type = ION_EBI_TYPE,
+ },
+ {
+ .id = ION_HEAP_ADSP_ID,
+ .type = ION_HEAP_TYPE_CARVEOUT,
+ .name = ION_ADSP_HEAP_NAME,
+ .size = MSM_ION_ADSP_SIZE,
+ .memory_type = ION_EBI_TYPE,
+ },
+#endif
+ }
+};
+
+static struct platform_device ion_dev = {
+ .name = "ion-msm",
+ .id = 1,
+ .dev = { .platform_data = &ion_pdata },
+};
+#endif
+
+static void reserve_ion_memory(void)
+{
+#if defined(CONFIG_ION_MSM) && defined(CONFIG_MSM_MULTIMEDIA_USE_ION)
+ msm8930_reserve_table[MEMTYPE_EBI1].size += MSM_ION_EBI_SIZE;
+ msm8930_reserve_table[MEMTYPE_EBI1].size += MSM_ION_ADSP_SIZE;
+#endif
+}
+static void __init msm8930_calculate_reserve_sizes(void)
+{
+ size_pmem_devices();
+ reserve_pmem_memory();
+ reserve_ion_memory();
+}
+
+static struct reserve_info msm8930_reserve_info __initdata = {
+ .memtype_reserve_table = msm8930_reserve_table,
+ .calculate_reserve_sizes = msm8930_calculate_reserve_sizes,
+ .paddr_to_memtype = msm8930_paddr_to_memtype,
+};
+
+static int msm8930_memory_bank_size(void)
+{
+ return 1<<29;
+}
+
+static void __init locate_unstable_memory(void)
+{
+ struct membank *mb = &meminfo.bank[meminfo.nr_banks - 1];
+ unsigned long bank_size;
+ unsigned long low, high;
+
+ bank_size = msm8930_memory_bank_size();
+ low = meminfo.bank[0].start;
+ high = mb->start + mb->size;
+
+ /* Check if 32 bit overflow occured */
+ if (high < mb->start)
+ high = ~0UL;
+
+ low &= ~(bank_size - 1);
+
+ if (high - low <= bank_size)
+ return;
+ msm8930_reserve_info.low_unstable_address = low + bank_size;
+ /* To avoid overflow of u32 compute max_unstable_size
+ * by first subtracting low from mb->start)
+ * */
+ msm8930_reserve_info.max_unstable_size = (mb->start - low) +
+ mb->size - bank_size;
+
+ msm8930_reserve_info.bank_size = bank_size;
+ pr_info("low unstable address %lx max size %lx bank size %lx\n",
+ msm8930_reserve_info.low_unstable_address,
+ msm8930_reserve_info.max_unstable_size,
+ msm8930_reserve_info.bank_size);
+}
+
+static void __init place_movable_zone(void)
+{
+ movable_reserved_start = msm8930_reserve_info.low_unstable_address;
+ movable_reserved_size = msm8930_reserve_info.max_unstable_size;
+ pr_info("movable zone start %lx size %lx\n",
+ movable_reserved_start, movable_reserved_size);
+}
+
+static void __init msm8930_early_memory(void)
+{
+ reserve_info = &msm8930_reserve_info;
+ locate_unstable_memory();
+ place_movable_zone();
+}
+
+static void __init msm8930_reserve(void)
+{
+ msm_reserve();
+}
+
+static int msm8930_change_memory_power(u64 start, u64 size,
+ int change_type)
+{
+ return soc_change_memory_power(start, size, change_type);
+}
+
+static void __init msm8930_allocate_memory_regions(void)
+{
+ msm8930_allocate_fb_region();
+}
+
+#ifdef CONFIG_WCD9310_CODEC
+
+#define TABLA_INTERRUPT_BASE (NR_MSM_IRQS + NR_GPIO_IRQS + NR_PM8921_IRQS)
+
+/* Micbias setting is based on 8660 CDP/MTP/FLUID requirement
+ * 4 micbiases are used to power various analog and digital
+ * microphones operating at 1800 mV. Technically, all micbiases
+ * can source from single cfilter since all microphones operate
+ * at the same voltage level. The arrangement below is to make
+ * sure all cfilters are exercised. LDO_H regulator ouput level
+ * does not need to be as high as 2.85V. It is choosen for
+ * microphone sensitivity purpose.
+ */
+static struct tabla_pdata tabla_platform_data = {
+ .slimbus_slave_device = {
+ .name = "tabla-slave",
+ .e_addr = {0, 0, 0x10, 0, 0x17, 2},
+ },
+ .irq = MSM_GPIO_TO_INT(62),
+ .irq_base = TABLA_INTERRUPT_BASE,
+ .num_irqs = NR_TABLA_IRQS,
+ .reset_gpio = PM8921_GPIO_PM_TO_SYS(34),
+ .micbias = {
+ .ldoh_v = TABLA_LDOH_2P85_V,
+ .cfilt1_mv = 1800,
+ .cfilt2_mv = 1800,
+ .cfilt3_mv = 1800,
+ .bias1_cfilt_sel = TABLA_CFILT1_SEL,
+ .bias2_cfilt_sel = TABLA_CFILT2_SEL,
+ .bias3_cfilt_sel = TABLA_CFILT3_SEL,
+ .bias4_cfilt_sel = TABLA_CFILT3_SEL,
+ }
+};
+
+static struct slim_device msm_slim_tabla = {
+ .name = "tabla-slim",
+ .e_addr = {0, 1, 0x10, 0, 0x17, 2},
+ .dev = {
+ .platform_data = &tabla_platform_data,
+ },
+};
+
+static struct tabla_pdata tabla20_platform_data = {
+ .slimbus_slave_device = {
+ .name = "tabla-slave",
+ .e_addr = {0, 0, 0x60, 0, 0x17, 2},
+ },
+ .irq = MSM_GPIO_TO_INT(62),
+ .irq_base = TABLA_INTERRUPT_BASE,
+ .num_irqs = NR_TABLA_IRQS,
+ .reset_gpio = PM8921_GPIO_PM_TO_SYS(34),
+ .micbias = {
+ .ldoh_v = TABLA_LDOH_2P85_V,
+ .cfilt1_mv = 1800,
+ .cfilt2_mv = 1800,
+ .cfilt3_mv = 1800,
+ .bias1_cfilt_sel = TABLA_CFILT1_SEL,
+ .bias2_cfilt_sel = TABLA_CFILT2_SEL,
+ .bias3_cfilt_sel = TABLA_CFILT3_SEL,
+ .bias4_cfilt_sel = TABLA_CFILT3_SEL,
+ }
+};
+
+static struct slim_device msm_slim_tabla20 = {
+ .name = "tabla2x-slim",
+ .e_addr = {0, 1, 0x60, 0, 0x17, 2},
+ .dev = {
+ .platform_data = &tabla20_platform_data,
+ },
+};
+#endif
+
+static struct slim_boardinfo msm_slim_devices[] = {
+#ifdef CONFIG_WCD9310_CODEC
+ {
+ .bus_num = 1,
+ .slim_slave = &msm_slim_tabla,
+ },
+ {
+ .bus_num = 1,
+ .slim_slave = &msm_slim_tabla20,
+ },
+#endif
+ /* add more slimbus slaves as needed */
+};
+
+#define MSM_WCNSS_PHYS 0x03000000
+#define MSM_WCNSS_SIZE 0x280000
+
+static struct resource resources_wcnss_wlan[] = {
+ {
+ .start = RIVA_APPS_WLAN_RX_DATA_AVAIL_IRQ,
+ .end = RIVA_APPS_WLAN_RX_DATA_AVAIL_IRQ,
+ .name = "wcnss_wlanrx_irq",
+ .flags = IORESOURCE_IRQ,
+ },
+ {
+ .start = RIVA_APPS_WLAN_DATA_XFER_DONE_IRQ,
+ .end = RIVA_APPS_WLAN_DATA_XFER_DONE_IRQ,
+ .name = "wcnss_wlantx_irq",
+ .flags = IORESOURCE_IRQ,
+ },
+ {
+ .start = MSM_WCNSS_PHYS,
+ .end = MSM_WCNSS_PHYS + MSM_WCNSS_SIZE - 1,
+ .name = "wcnss_mmio",
+ .flags = IORESOURCE_MEM,
+ },
+ {
+ .start = 84,
+ .end = 88,
+ .name = "wcnss_gpios_5wire",
+ .flags = IORESOURCE_IO,
+ },
+};
+
+static struct qcom_wcnss_opts qcom_wcnss_pdata = {
+ .has_48mhz_xo = 1,
+};
+
+static struct platform_device msm_device_wcnss_wlan = {
+ .name = "wcnss_wlan",
+ .id = 0,
+ .num_resources = ARRAY_SIZE(resources_wcnss_wlan),
+ .resource = resources_wcnss_wlan,
+ .dev = {.platform_data = &qcom_wcnss_pdata},
+};
+
+#if defined(CONFIG_CRYPTO_DEV_QCRYPTO) || \
+ defined(CONFIG_CRYPTO_DEV_QCRYPTO_MODULE) || \
+ defined(CONFIG_CRYPTO_DEV_QCEDEV) || \
+ defined(CONFIG_CRYPTO_DEV_QCEDEV_MODULE)
+
+#define QCE_SIZE 0x10000
+#define QCE_0_BASE 0x18500000
+
+#define QCE_HW_KEY_SUPPORT 0
+#define QCE_SHA_HMAC_SUPPORT 1
+#define QCE_SHARE_CE_RESOURCE 1
+#define QCE_CE_SHARED 0
+
+static struct resource qcrypto_resources[] = {
+ [0] = {
+ .start = QCE_0_BASE,
+ .end = QCE_0_BASE + QCE_SIZE - 1,
+ .flags = IORESOURCE_MEM,
+ },
+ [1] = {
+ .name = "crypto_channels",
+ .start = DMOV_CE_IN_CHAN,
+ .end = DMOV_CE_OUT_CHAN,
+ .flags = IORESOURCE_DMA,
+ },
+ [2] = {
+ .name = "crypto_crci_in",
+ .start = DMOV_CE_IN_CRCI,
+ .end = DMOV_CE_IN_CRCI,
+ .flags = IORESOURCE_DMA,
+ },
+ [3] = {
+ .name = "crypto_crci_out",
+ .start = DMOV_CE_OUT_CRCI,
+ .end = DMOV_CE_OUT_CRCI,
+ .flags = IORESOURCE_DMA,
+ },
+};
+
+static struct resource qcedev_resources[] = {
+ [0] = {
+ .start = QCE_0_BASE,
+ .end = QCE_0_BASE + QCE_SIZE - 1,
+ .flags = IORESOURCE_MEM,
+ },
+ [1] = {
+ .name = "crypto_channels",
+ .start = DMOV_CE_IN_CHAN,
+ .end = DMOV_CE_OUT_CHAN,
+ .flags = IORESOURCE_DMA,
+ },
+ [2] = {
+ .name = "crypto_crci_in",
+ .start = DMOV_CE_IN_CRCI,
+ .end = DMOV_CE_IN_CRCI,
+ .flags = IORESOURCE_DMA,
+ },
+ [3] = {
+ .name = "crypto_crci_out",
+ .start = DMOV_CE_OUT_CRCI,
+ .end = DMOV_CE_OUT_CRCI,
+ .flags = IORESOURCE_DMA,
+ },
+};
+
+#endif
+
+#if defined(CONFIG_CRYPTO_DEV_QCRYPTO) || \
+ defined(CONFIG_CRYPTO_DEV_QCRYPTO_MODULE)
+
+static struct msm_ce_hw_support qcrypto_ce_hw_suppport = {
+ .ce_shared = QCE_CE_SHARED,
+ .shared_ce_resource = QCE_SHARE_CE_RESOURCE,
+ .hw_key_support = QCE_HW_KEY_SUPPORT,
+ .sha_hmac = QCE_SHA_HMAC_SUPPORT,
+};
+
+static struct platform_device qcrypto_device = {
+ .name = "qcrypto",
+ .id = 0,
+ .num_resources = ARRAY_SIZE(qcrypto_resources),
+ .resource = qcrypto_resources,
+ .dev = {
+ .coherent_dma_mask = DMA_BIT_MASK(32),
+ .platform_data = &qcrypto_ce_hw_suppport,
+ },
+};
+#endif
+
+#if defined(CONFIG_CRYPTO_DEV_QCEDEV) || \
+ defined(CONFIG_CRYPTO_DEV_QCEDEV_MODULE)
+
+static struct msm_ce_hw_support qcedev_ce_hw_suppport = {
+ .ce_shared = QCE_CE_SHARED,
+ .shared_ce_resource = QCE_SHARE_CE_RESOURCE,
+ .hw_key_support = QCE_HW_KEY_SUPPORT,
+ .sha_hmac = QCE_SHA_HMAC_SUPPORT,
+};
+
+static struct platform_device qcedev_device = {
+ .name = "qce",
+ .id = 0,
+ .num_resources = ARRAY_SIZE(qcedev_resources),
+ .resource = qcedev_resources,
+ .dev = {
+ .coherent_dma_mask = DMA_BIT_MASK(32),
+ .platform_data = &qcedev_ce_hw_suppport,
+ },
+};
+#endif
+
+#define MDM2AP_ERRFATAL 70
+#define AP2MDM_ERRFATAL 95
+#define MDM2AP_STATUS 69
+#define AP2MDM_STATUS 94
+#define AP2MDM_PMIC_RESET_N 80
+#define AP2MDM_KPDPWR_N 81
+
+static struct resource mdm_resources[] = {
+ {
+ .start = MDM2AP_ERRFATAL,
+ .end = MDM2AP_ERRFATAL,
+ .name = "MDM2AP_ERRFATAL",
+ .flags = IORESOURCE_IO,
+ },
+ {
+ .start = AP2MDM_ERRFATAL,
+ .end = AP2MDM_ERRFATAL,
+ .name = "AP2MDM_ERRFATAL",
+ .flags = IORESOURCE_IO,
+ },
+ {
+ .start = MDM2AP_STATUS,
+ .end = MDM2AP_STATUS,
+ .name = "MDM2AP_STATUS",
+ .flags = IORESOURCE_IO,
+ },
+ {
+ .start = AP2MDM_STATUS,
+ .end = AP2MDM_STATUS,
+ .name = "AP2MDM_STATUS",
+ .flags = IORESOURCE_IO,
+ },
+ {
+ .start = AP2MDM_PMIC_RESET_N,
+ .end = AP2MDM_PMIC_RESET_N,
+ .name = "AP2MDM_PMIC_RESET_N",
+ .flags = IORESOURCE_IO,
+ },
+ {
+ .start = AP2MDM_KPDPWR_N,
+ .end = AP2MDM_KPDPWR_N,
+ .name = "AP2MDM_KPDPWR_N",
+ .flags = IORESOURCE_IO,
+ },
+};
+
+static struct mdm_platform_data mdm_platform_data = {
+ .mdm_version = "2.5",
+};
+
+static struct platform_device mdm_device = {
+ .name = "mdm2_modem",
+ .id = -1,
+ .num_resources = ARRAY_SIZE(mdm_resources),
+ .resource = mdm_resources,
+ .dev = {
+ .platform_data = &mdm_platform_data,
+ },
+};
+
+static struct platform_device *mdm_devices[] __initdata = {
+ &mdm_device,
+};
+
+#define MSM_SHARED_RAM_PHYS 0x80000000
+
+static void __init msm8930_map_io(void)
+{
+ msm_shared_ram_phys = MSM_SHARED_RAM_PHYS;
+ msm_map_msm8930_io();
+
+ if (socinfo_init() < 0)
+ pr_err("socinfo_init() failed!\n");
+}
+
+static void __init msm8930_init_irq(void)
+{
+ unsigned int i;
+
+ msm_mpm_irq_extn_init();
+ gic_init(0, GIC_PPI_START, MSM_QGIC_DIST_BASE,
+ (void *)MSM_QGIC_CPU_BASE);
+
+ /* Edge trigger PPIs except AVS_SVICINT and AVS_SVICINTSWDONE */
+ writel_relaxed(0xFFFFD7FF, MSM_QGIC_DIST_BASE + GIC_DIST_CONFIG + 4);
+
+ writel_relaxed(0x0000FFFF, MSM_QGIC_DIST_BASE + GIC_DIST_ENABLE_SET);
+ mb();
+
+ /* FIXME: Not installing AVS_SVICINT and AVS_SVICINTSWDONE yet
+ * as they are configured as level, which does not play nice with
+ * handle_percpu_irq.
+ */
+ for (i = GIC_PPI_START; i < GIC_SPI_START; i++) {
+ if (i != AVS_SVICINT && i != AVS_SVICINTSWDONE)
+ irq_set_handler(i, handle_percpu_irq);
+ }
+}
+
+static void __init msm8930_init_buses(void)
+{
+#ifdef CONFIG_MSM_BUS_SCALING
+ msm_bus_rpm_set_mt_mask();
+ msm_bus_8960_apps_fabric_pdata.rpm_enabled = 1;
+ msm_bus_8960_sys_fabric_pdata.rpm_enabled = 1;
+ msm_bus_8960_mm_fabric_pdata.rpm_enabled = 1;
+ msm_bus_apps_fabric.dev.platform_data =
+ &msm_bus_8960_apps_fabric_pdata;
+ msm_bus_sys_fabric.dev.platform_data = &msm_bus_8960_sys_fabric_pdata;
+ msm_bus_mm_fabric.dev.platform_data = &msm_bus_8960_mm_fabric_pdata;
+ msm_bus_sys_fpb.dev.platform_data = &msm_bus_8960_sys_fpb_pdata;
+ msm_bus_cpss_fpb.dev.platform_data = &msm_bus_8960_cpss_fpb_pdata;
+#endif
+}
+
+static struct msm_spi_platform_data msm8960_qup_spi_gsbi1_pdata = {
+ .max_clock_speed = 15060000,
+};
+
+#ifdef CONFIG_USB_MSM_OTG_72K
+static struct msm_otg_platform_data msm_otg_pdata;
+#else
+#define USB_5V_EN 42
+static void msm_hsusb_vbus_power(bool on)
+{
+ int rc;
+ static bool vbus_is_on;
+ static struct regulator *mvs_otg_switch;
+
+ if (vbus_is_on == on)
+ return;
+
+ if (on) {
+ mvs_otg_switch = regulator_get(&msm8960_device_otg.dev,
+ "vbus_otg");
+ if (IS_ERR(mvs_otg_switch)) {
+ pr_err("Unable to get mvs_otg_switch\n");
+ return;
+ }
+
+ rc = gpio_request(PM8921_GPIO_PM_TO_SYS(USB_5V_EN),
+ "usb_5v_en");
+ if (rc < 0) {
+ pr_err("failed to request usb_5v_en gpio\n");
+ goto put_mvs_otg;
+ }
+
+ rc = gpio_direction_output(PM8921_GPIO_PM_TO_SYS(USB_5V_EN), 1);
+ if (rc) {
+ pr_err("%s: unable to set_direction for gpio [%d]\n",
+ __func__, PM8921_GPIO_PM_TO_SYS(USB_5V_EN));
+ goto free_usb_5v_en;
+ }
+
+ if (regulator_enable(mvs_otg_switch)) {
+ pr_err("unable to enable mvs_otg_switch\n");
+ goto err_ldo_gpio_set_dir;
+ }
+
+ vbus_is_on = true;
+ return;
+ }
+ regulator_disable(mvs_otg_switch);
+err_ldo_gpio_set_dir:
+ gpio_set_value(PM8921_GPIO_PM_TO_SYS(USB_5V_EN), 0);
+free_usb_5v_en:
+ gpio_free(PM8921_GPIO_PM_TO_SYS(USB_5V_EN));
+put_mvs_otg:
+ regulator_put(mvs_otg_switch);
+ vbus_is_on = false;
+}
+
+static struct msm_otg_platform_data msm_otg_pdata = {
+ .mode = USB_OTG,
+ .otg_control = OTG_PMIC_CONTROL,
+ .phy_type = SNPS_28NM_INTEGRATED_PHY,
+ .pclk_src_name = "dfab_usb_hs_clk",
+ .pmic_id_irq = PM8921_USB_ID_IN_IRQ(PM8921_IRQ_BASE),
+ .vbus_power = msm_hsusb_vbus_power,
+ .power_budget = 750,
+};
+#endif
+
+#ifdef CONFIG_USB_EHCI_MSM_HSIC
+#define HSIC_HUB_RESET_GPIO 91
+static struct msm_hsic_host_platform_data msm_hsic_pdata = {
+ .strobe = 150,
+ .data = 151,
+};
+#else
+static struct msm_hsic_host_platform_data msm_hsic_pdata;
+#endif
+
+#define PID_MAGIC_ID 0x71432909
+#define SERIAL_NUM_MAGIC_ID 0x61945374
+#define SERIAL_NUMBER_LENGTH 127
+#define DLOAD_USB_BASE_ADD 0x2A03F0C8
+
+struct magic_num_struct {
+ uint32_t pid;
+ uint32_t serial_num;
+};
+
+struct dload_struct {
+ uint32_t reserved1;
+ uint32_t reserved2;
+ uint32_t reserved3;
+ uint16_t reserved4;
+ uint16_t pid;
+ char serial_number[SERIAL_NUMBER_LENGTH];
+ uint16_t reserved5;
+ struct magic_num_struct magic_struct;
+};
+
+static int usb_diag_update_pid_and_serial_num(uint32_t pid, const char *snum)
+{
+ struct dload_struct __iomem *dload = 0;
+
+ dload = ioremap(DLOAD_USB_BASE_ADD, sizeof(*dload));
+ if (!dload) {
+ pr_err("%s: cannot remap I/O memory region: %08x\n",
+ __func__, DLOAD_USB_BASE_ADD);
+ return -ENXIO;
+ }
+
+ pr_debug("%s: dload:%p pid:%x serial_num:%s\n",
+ __func__, dload, pid, snum);
+ /* update pid */
+ dload->magic_struct.pid = PID_MAGIC_ID;
+ dload->pid = pid;
+
+ /* update serial number */
+ dload->magic_struct.serial_num = 0;
+ if (!snum) {
+ memset(dload->serial_number, 0, SERIAL_NUMBER_LENGTH);
+ goto out;
+ }
+
+ dload->magic_struct.serial_num = SERIAL_NUM_MAGIC_ID;
+ strlcpy(dload->serial_number, snum, SERIAL_NUMBER_LENGTH);
+out:
+ iounmap(dload);
+ return 0;
+}
+
+static struct android_usb_platform_data android_usb_pdata = {
+ .update_pid_and_serial_num = usb_diag_update_pid_and_serial_num,
+};
+
+static struct platform_device android_usb_device = {
+ .name = "android_usb",
+ .id = -1,
+ .dev = {
+ .platform_data = &android_usb_pdata,
+ },
+};
+
+static uint8_t spm_wfi_cmd_sequence[] __initdata = {
+ 0x03, 0x0f,
+};
+
+static uint8_t spm_power_collapse_without_rpm[] __initdata = {
+ 0x00, 0x24, 0x54, 0x10,
+ 0x09, 0x03, 0x01,
+ 0x10, 0x54, 0x30, 0x0C,
+ 0x24, 0x30, 0x0f,
+};
+
+static uint8_t spm_power_collapse_with_rpm[] __initdata = {
+ 0x00, 0x24, 0x54, 0x10,
+ 0x09, 0x07, 0x01, 0x0B,
+ 0x10, 0x54, 0x30, 0x0C,
+ 0x24, 0x30, 0x0f,
+};
+
+static struct msm_spm_seq_entry msm_spm_seq_list[] __initdata = {
+ [0] = {
+ .mode = MSM_SPM_MODE_CLOCK_GATING,
+ .notify_rpm = false,
+ .cmd = spm_wfi_cmd_sequence,
+ },
+ [1] = {
+ .mode = MSM_SPM_MODE_POWER_COLLAPSE,
+ .notify_rpm = false,
+ .cmd = spm_power_collapse_without_rpm,
+ },
+ [2] = {
+ .mode = MSM_SPM_MODE_POWER_COLLAPSE,
+ .notify_rpm = true,
+ .cmd = spm_power_collapse_with_rpm,
+ },
+};
+
+static struct msm_spm_platform_data msm_spm_data[] __initdata = {
+ [0] = {
+ .reg_base_addr = MSM_SAW0_BASE,
+ .reg_init_values[MSM_SPM_REG_SAW2_SECURE] = 0x00,
+ .reg_init_values[MSM_SPM_REG_SAW2_CFG] = 0x1F,
+ .reg_init_values[MSM_SPM_REG_SAW2_VCTL] = 0x9C,
+#if defined(CONFIG_MSM_AVS_HW)
+ .reg_init_values[MSM_SPM_REG_SAW2_AVS_CTL] = 0x00,
+ .reg_init_values[MSM_SPM_REG_SAW2_AVS_HYSTERESIS] = 0x00,
+#endif
+ .reg_init_values[MSM_SPM_REG_SAW2_SPM_CTL] = 0x01,
+ .reg_init_values[MSM_SPM_REG_SAW2_PMIC_DLY] = 0x02020202,
+ .reg_init_values[MSM_SPM_REG_SAW2_PMIC_DATA_0] = 0x0060009C,
+ .reg_init_values[MSM_SPM_REG_SAW2_PMIC_DATA_1] = 0x0000001C,
+ .vctl_timeout_us = 50,
+ .num_modes = ARRAY_SIZE(msm_spm_seq_list),
+ .modes = msm_spm_seq_list,
+ },
+ [1] = {
+ .reg_base_addr = MSM_SAW1_BASE,
+ .reg_init_values[MSM_SPM_REG_SAW2_SECURE] = 0x00,
+ .reg_init_values[MSM_SPM_REG_SAW2_CFG] = 0x1F,
+ .reg_init_values[MSM_SPM_REG_SAW2_VCTL] = 0x9C,
+#if defined(CONFIG_MSM_AVS_HW)
+ .reg_init_values[MSM_SPM_REG_SAW2_AVS_CTL] = 0x00,
+ .reg_init_values[MSM_SPM_REG_SAW2_AVS_HYSTERESIS] = 0x00,
+#endif
+ .reg_init_values[MSM_SPM_REG_SAW2_SPM_CTL] = 0x01,
+ .reg_init_values[MSM_SPM_REG_SAW2_PMIC_DLY] = 0x02020202,
+ .reg_init_values[MSM_SPM_REG_SAW2_PMIC_DATA_0] = 0x0060009C,
+ .reg_init_values[MSM_SPM_REG_SAW2_PMIC_DATA_1] = 0x0000001C,
+ .vctl_timeout_us = 50,
+ .num_modes = ARRAY_SIZE(msm_spm_seq_list),
+ .modes = msm_spm_seq_list,
+ },
+};
+
+static uint8_t l2_spm_wfi_cmd_sequence[] __initdata = {
+ 0x00, 0x20, 0x03, 0x20,
+ 0x00, 0x0f,
+};
+
+static uint8_t l2_spm_gdhs_cmd_sequence[] __initdata = {
+ 0x00, 0x20, 0x34, 0x64,
+ 0x48, 0x07, 0x48, 0x20,
+ 0x50, 0x64, 0x04, 0x34,
+ 0x50, 0x0f,
+};
+static uint8_t l2_spm_power_off_cmd_sequence[] __initdata = {
+ 0x00, 0x10, 0x34, 0x64,
+ 0x48, 0x07, 0x48, 0x10,
+ 0x50, 0x64, 0x04, 0x34,
+ 0x50, 0x0F,
+};
+
+static struct msm_spm_seq_entry msm_spm_l2_seq_list[] __initdata = {
+ [0] = {
+ .mode = MSM_SPM_L2_MODE_RETENTION,
+ .notify_rpm = false,
+ .cmd = l2_spm_wfi_cmd_sequence,
+ },
+ [1] = {
+ .mode = MSM_SPM_L2_MODE_GDHS,
+ .notify_rpm = true,
+ .cmd = l2_spm_gdhs_cmd_sequence,
+ },
+ [2] = {
+ .mode = MSM_SPM_L2_MODE_POWER_COLLAPSE,
+ .notify_rpm = true,
+ .cmd = l2_spm_power_off_cmd_sequence,
+ },
+};
+
+static struct msm_spm_platform_data msm_spm_l2_data[] __initdata = {
+ [0] = {
+ .reg_base_addr = MSM_SAW_L2_BASE,
+ .reg_init_values[MSM_SPM_REG_SAW2_SECURE] = 0x00,
+ .reg_init_values[MSM_SPM_REG_SAW2_SPM_CTL] = 0x00,
+ .reg_init_values[MSM_SPM_REG_SAW2_PMIC_DLY] = 0x02020202,
+ .reg_init_values[MSM_SPM_REG_SAW2_PMIC_DATA_0] = 0x00A000AE,
+ .reg_init_values[MSM_SPM_REG_SAW2_PMIC_DATA_1] = 0x00A00020,
+ .modes = msm_spm_l2_seq_list,
+ .num_modes = ARRAY_SIZE(msm_spm_l2_seq_list),
+ },
+};
+
+#define PM_HAP_EN_GPIO PM8921_GPIO_PM_TO_SYS(33)
+#define PM_HAP_LEN_GPIO PM8921_GPIO_PM_TO_SYS(20)
+
+static struct msm_xo_voter *xo_handle_d1;
+
+static int isa1200_power(int on)
+{
+ int rc = 0;
+
+ gpio_set_value(HAP_SHIFT_LVL_OE_GPIO, !!on);
+
+ rc = on ? msm_xo_mode_vote(xo_handle_d1, MSM_XO_MODE_ON) :
+ msm_xo_mode_vote(xo_handle_d1, MSM_XO_MODE_OFF);
+ if (rc < 0) {
+ pr_err("%s: failed to %svote for TCXO D1 buffer%d\n",
+ __func__, on ? "" : "de-", rc);
+ goto err_xo_vote;
+ }
+
+ return 0;
+
+err_xo_vote:
+ gpio_set_value(HAP_SHIFT_LVL_OE_GPIO, !on);
+ return rc;
+}
+
+static int isa1200_dev_setup(bool enable)
+{
+ int rc = 0;
+
+ struct pm_gpio hap_gpio_config = {
+ .direction = PM_GPIO_DIR_OUT,
+ .pull = PM_GPIO_PULL_NO,
+ .out_strength = PM_GPIO_STRENGTH_HIGH,
+ .function = PM_GPIO_FUNC_NORMAL,
+ .inv_int_pol = 0,
+ .vin_sel = 2,
+ .output_buffer = PM_GPIO_OUT_BUF_CMOS,
+ .output_value = 0,
+ };
+
+ if (enable == true) {
+ rc = pm8xxx_gpio_config(PM_HAP_EN_GPIO, &hap_gpio_config);
+ if (rc) {
+ pr_err("%s: pm8921 gpio %d config failed(%d)\n",
+ __func__, PM_HAP_EN_GPIO, rc);
+ return rc;
+ }
+
+ rc = pm8xxx_gpio_config(PM_HAP_LEN_GPIO, &hap_gpio_config);
+ if (rc) {
+ pr_err("%s: pm8921 gpio %d config failed(%d)\n",
+ __func__, PM_HAP_LEN_GPIO, rc);
+ return rc;
+ }
+
+ rc = gpio_request(HAP_SHIFT_LVL_OE_GPIO, "hap_shft_lvl_oe");
+ if (rc) {
+ pr_err("%s: unable to request gpio %d (%d)\n",
+ __func__, HAP_SHIFT_LVL_OE_GPIO, rc);
+ return rc;
+ }
+
+ rc = gpio_direction_output(HAP_SHIFT_LVL_OE_GPIO, 0);
+ if (rc) {
+ pr_err("%s: Unable to set direction\n", __func__);
+ goto free_gpio;
+ }
+
+ xo_handle_d1 = msm_xo_get(MSM_XO_TCXO_D1, "isa1200");
+ if (IS_ERR(xo_handle_d1)) {
+ rc = PTR_ERR(xo_handle_d1);
+ pr_err("%s: failed to get the handle for D1(%d)\n",
+ __func__, rc);
+ goto gpio_set_dir;
+ }
+ } else {
+ gpio_free(HAP_SHIFT_LVL_OE_GPIO);
+
+ msm_xo_put(xo_handle_d1);
+ }
+
+ return 0;
+
+gpio_set_dir:
+ gpio_set_value(HAP_SHIFT_LVL_OE_GPIO, 0);
+free_gpio:
+ gpio_free(HAP_SHIFT_LVL_OE_GPIO);
+ return rc;
+}
+
+static struct isa1200_regulator isa1200_reg_data[] = {
+ {
+ .name = "vcc_i2c",
+ .min_uV = ISA_I2C_VTG_MIN_UV,
+ .max_uV = ISA_I2C_VTG_MAX_UV,
+ .load_uA = ISA_I2C_CURR_UA,
+ },
+};
+
+static struct isa1200_platform_data isa1200_1_pdata = {
+ .name = "vibrator",
+ .dev_setup = isa1200_dev_setup,
+ .power_on = isa1200_power,
+ .hap_en_gpio = PM_HAP_EN_GPIO,
+ .hap_len_gpio = PM_HAP_LEN_GPIO,
+ .max_timeout = 15000,
+ .mode_ctrl = PWM_GEN_MODE,
+ .pwm_fd = {
+ .pwm_div = 256,
+ },
+ .is_erm = false,
+ .smart_en = true,
+ .ext_clk_en = true,
+ .chip_en = 1,
+ .regulator_info = isa1200_reg_data,
+ .num_regulators = ARRAY_SIZE(isa1200_reg_data),
+};
+
+static struct i2c_board_info msm_isa1200_board_info[] __initdata = {
+ {
+ I2C_BOARD_INFO("isa1200_1", 0x90>>1),
+ .platform_data = &isa1200_1_pdata,
+ },
+};
+
+#define CYTTSP_TS_GPIO_IRQ 11
+#define CYTTSP_TS_SLEEP_GPIO 50
+#define CYTTSP_TS_RESOUT_N_GPIO 52
+
+/*virtual key support */
+static ssize_t tma340_vkeys_show(struct kobject *kobj,
+ struct kobj_attribute *attr, char *buf)
+{
+ return snprintf(buf, 200,
+ __stringify(EV_KEY) ":" __stringify(KEY_BACK) ":73:1120:97:97"
+ ":" __stringify(EV_KEY) ":" __stringify(KEY_MENU) ":230:1120:97:97"
+ ":" __stringify(EV_KEY) ":" __stringify(KEY_HOME) ":389:1120:97:97"
+ ":" __stringify(EV_KEY) ":" __stringify(KEY_SEARCH) ":544:1120:97:97"
+ "\n");
+}
+
+static struct kobj_attribute tma340_vkeys_attr = {
+ .attr = {
+ .mode = S_IRUGO,
+ },
+ .show = &tma340_vkeys_show,
+};
+
+static struct attribute *tma340_properties_attrs[] = {
+ &tma340_vkeys_attr.attr,
+ NULL
+};
+
+static struct attribute_group tma340_properties_attr_group = {
+ .attrs = tma340_properties_attrs,
+};
+
+
+static int cyttsp_platform_init(struct i2c_client *client)
+{
+ int rc = 0;
+ static struct kobject *tma340_properties_kobj;
+
+ tma340_vkeys_attr.attr.name = "virtualkeys.cyttsp-i2c";
+ tma340_properties_kobj = kobject_create_and_add("board_properties",
+ NULL);
+ if (tma340_properties_kobj)
+ rc = sysfs_create_group(tma340_properties_kobj,
+ &tma340_properties_attr_group);
+ if (!tma340_properties_kobj || rc)
+ pr_err("%s: failed to create board_properties\n",
+ __func__);
+
+ return 0;
+}
+
+static struct cyttsp_regulator regulator_data[] = {
+ {
+ .name = "vdd",
+ .min_uV = CY_TMA300_VTG_MIN_UV,
+ .max_uV = CY_TMA300_VTG_MAX_UV,
+ .hpm_load_uA = CY_TMA300_CURR_24HZ_UA,
+ .lpm_load_uA = CY_TMA300_SLEEP_CURR_UA,
+ },
+ /* TODO: Remove after runtime PM is enabled in I2C driver */
+ {
+ .name = "vcc_i2c",
+ .min_uV = CY_I2C_VTG_MIN_UV,
+ .max_uV = CY_I2C_VTG_MAX_UV,
+ .hpm_load_uA = CY_I2C_CURR_UA,
+ .lpm_load_uA = CY_I2C_SLEEP_CURR_UA,
+ },
+};
+
+static struct cyttsp_platform_data cyttsp_pdata = {
+ .panel_maxx = 634,
+ .panel_maxy = 1166,
+ .disp_maxx = 616,
+ .disp_maxy = 1023,
+ .disp_minx = 0,
+ .disp_miny = 16,
+ .flags = 0x01,
+ .gen = CY_GEN3, /* or */
+ .use_st = CY_USE_ST,
+ .use_mt = CY_USE_MT,
+ .use_hndshk = CY_SEND_HNDSHK,
+ .use_trk_id = CY_USE_TRACKING_ID,
+ .use_sleep = CY_USE_DEEP_SLEEP_SEL | CY_USE_LOW_POWER_SEL,
+ .use_gestures = CY_USE_GESTURES,
+ .fw_fname = "cyttsp_8960_cdp.hex",
+ /* activate up to 4 groups
+ * and set active distance
+ */
+ .gest_set = CY_GEST_GRP1 | CY_GEST_GRP2 |
+ CY_GEST_GRP3 | CY_GEST_GRP4 |
+ CY_ACT_DIST,
+ /* change act_intrvl to customize the Active power state
+ * scanning/processing refresh interval for Operating mode
+ */
+ .act_intrvl = CY_ACT_INTRVL_DFLT,
+ /* change tch_tmout to customize the touch timeout for the
+ * Active power state for Operating mode
+ */
+ .tch_tmout = CY_TCH_TMOUT_DFLT,
+ /* change lp_intrvl to customize the Low Power power state
+ * scanning/processing refresh interval for Operating mode
+ */
+ .lp_intrvl = CY_LP_INTRVL_DFLT,
+ .sleep_gpio = CYTTSP_TS_SLEEP_GPIO,
+ .resout_gpio = CYTTSP_TS_RESOUT_N_GPIO,
+ .irq_gpio = CYTTSP_TS_GPIO_IRQ,
+ .regulator_info = regulator_data,
+ .num_regulators = ARRAY_SIZE(regulator_data),
+ .init = cyttsp_platform_init,
+ .correct_fw_ver = 9,
+};
+
+static struct i2c_board_info cyttsp_info[] __initdata = {
+ {
+ I2C_BOARD_INFO(CY_I2C_NAME, 0x24),
+ .platform_data = &cyttsp_pdata,
+#ifndef CY_USE_TIMER
+ .irq = MSM_GPIO_TO_INT(CYTTSP_TS_GPIO_IRQ),
+#endif /* CY_USE_TIMER */
+ },
+};
+
+/* configuration data */
+static const u8 mxt_config_data[] = {
+ /* T6 Object */
+ 0, 0, 0, 0, 0, 0,
+ /* T38 Object */
+ 11, 2, 0, 11, 11, 11, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0,
+ /* T7 Object */
+ 100, 16, 50,
+ /* T8 Object */
+ 8, 0, 0, 0, 0, 0, 8, 14, 50, 215,
+ /* T9 Object */
+ 131, 0, 0, 26, 42, 0, 32, 63, 3, 5,
+ 0, 2, 1, 113, 10, 10, 8, 10, 255, 2,
+ 85, 5, 0, 0, 20, 20, 75, 25, 202, 29,
+ 10, 10, 45, 46,
+ /* T15 Object */
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0,
+ /* T22 Object */
+ 5, 0, 0, 0, 0, 0, 0, 0, 30, 0,
+ 0, 0, 5, 8, 10, 13, 0,
+ /* T24 Object */
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ /* T25 Object */
+ 3, 0, 188, 52, 52, 33, 0, 0, 0, 0,
+ 0, 0, 0, 0,
+ /* T27 Object */
+ 0, 0, 0, 0, 0, 0, 0,
+ /* T28 Object */
+ 0, 0, 0, 8, 12, 60,
+ /* T40 Object */
+ 0, 0, 0, 0, 0,
+ /* T41 Object */
+ 0, 0, 0, 0, 0, 0,
+ /* T43 Object */
+ 0, 0, 0, 0, 0, 0,
+};
+
+#define MXT_TS_GPIO_IRQ 11
+#define MXT_TS_LDO_EN_GPIO 50
+#define MXT_TS_RESET_GPIO 52
+
+static struct mxt_platform_data mxt_platform_data = {
+ .config = mxt_config_data,
+ .config_length = ARRAY_SIZE(mxt_config_data),
+ .x_size = 1365,
+ .y_size = 767,
+ .irqflags = IRQF_TRIGGER_FALLING,
+ .i2c_pull_up = true,
+};
+
+static struct i2c_board_info mxt_device_info[] __initdata = {
+ {
+ I2C_BOARD_INFO("atmel_mxt_ts", 0x5b),
+ .platform_data = &mxt_platform_data,
+ .irq = MSM_GPIO_TO_INT(MXT_TS_GPIO_IRQ),
+ },
+};
+
+static void gsbi_qup_i2c_gpio_config(int adap_id, int config_type)
+{
+}
+
+static struct msm_i2c_platform_data msm8960_i2c_qup_gsbi4_pdata = {
+ .clk_freq = 100000,
+ .src_clk_rate = 24000000,
+ .msm_i2c_config_gpio = gsbi_qup_i2c_gpio_config,
+};
+
+static struct msm_i2c_platform_data msm8960_i2c_qup_gsbi3_pdata = {
+ .clk_freq = 100000,
+ .src_clk_rate = 24000000,
+ .msm_i2c_config_gpio = gsbi_qup_i2c_gpio_config,
+};
+
+static struct msm_i2c_platform_data msm8960_i2c_qup_gsbi10_pdata = {
+ .clk_freq = 100000,
+ .src_clk_rate = 24000000,
+ .msm_i2c_config_gpio = gsbi_qup_i2c_gpio_config,
+};
+
+static struct msm_i2c_platform_data msm8960_i2c_qup_gsbi12_pdata = {
+ .clk_freq = 100000,
+ .src_clk_rate = 24000000,
+ .msm_i2c_config_gpio = gsbi_qup_i2c_gpio_config,
+};
+
+static struct msm_rpm_platform_data msm_rpm_data = {
+ .reg_base_addrs = {
+ [MSM_RPM_PAGE_STATUS] = MSM_RPM_BASE,
+ [MSM_RPM_PAGE_CTRL] = MSM_RPM_BASE + 0x400,
+ [MSM_RPM_PAGE_REQ] = MSM_RPM_BASE + 0x600,
+ [MSM_RPM_PAGE_ACK] = MSM_RPM_BASE + 0xa00,
+ },
+
+ .irq_ack = RPM_APCC_CPU0_GP_HIGH_IRQ,
+ .irq_err = RPM_APCC_CPU0_GP_LOW_IRQ,
+ .irq_vmpm = RPM_APCC_CPU0_GP_MEDIUM_IRQ,
+ .msm_apps_ipc_rpm_reg = MSM_APCS_GCC_BASE + 0x008,
+ .msm_apps_ipc_rpm_val = 4,
+};
+
+static struct ks8851_pdata spi_eth_pdata = {
+ .irq_gpio = KS8851_IRQ_GPIO,
+ .rst_gpio = KS8851_RST_GPIO,
+};
+
+static struct spi_board_info spi_board_info[] __initdata = {
+ {
+ .modalias = "ks8851",
+ .irq = MSM_GPIO_TO_INT(KS8851_IRQ_GPIO),
+ .max_speed_hz = 19200000,
+ .bus_num = 0,
+ .chip_select = 0,
+ .mode = SPI_MODE_0,
+ .platform_data = &spi_eth_pdata
+ },
+ {
+ .modalias = "dsi_novatek_3d_panel_spi",
+ .max_speed_hz = 10800000,
+ .bus_num = 0,
+ .chip_select = 1,
+ .mode = SPI_MODE_0,
+ },
+};
+
+static struct platform_device msm_device_saw_core0 = {
+ .name = "saw-regulator",
+ .id = 0,
+ .dev = {
+ .platform_data = &msm_saw_regulator_pdata_s5,
+ },
+};
+
+static struct platform_device msm_device_saw_core1 = {
+ .name = "saw-regulator",
+ .id = 1,
+ .dev = {
+ .platform_data = &msm_saw_regulator_pdata_s6,
+ },
+};
+
+static struct tsens_platform_data msm_tsens_pdata = {
+ .slope = 910,
+ .tsens_factor = 1000,
+ .hw_type = MSM_8960,
+ .tsens_num_sensor = 5,
+};
+
+static struct platform_device msm_tsens_device = {
+ .name = "tsens8960-tm",
+ .id = -1,
+ .dev = {
+ .platform_data = &msm_tsens_pdata,
+ },
+};
+
+#ifdef CONFIG_MSM_FAKE_BATTERY
+static struct platform_device fish_battery_device = {
+ .name = "fish_battery",
+};
+#endif
+
+static struct platform_device msm8960_device_ext_5v_vreg __devinitdata = {
+ .name = GPIO_REGULATOR_DEV_NAME,
+ .id = PM8921_MPP_PM_TO_SYS(7),
+ .dev = {
+ .platform_data = &msm_gpio_regulator_pdata[GPIO_VREG_ID_EXT_5V],
+ },
+};
+
+static struct platform_device msm8960_device_ext_l2_vreg __devinitdata = {
+ .name = GPIO_REGULATOR_DEV_NAME,
+ .id = 91,
+ .dev = {
+ .platform_data = &msm_gpio_regulator_pdata[GPIO_VREG_ID_EXT_L2],
+ },
+};
+
+static struct platform_device msm8960_device_rpm_regulator __devinitdata = {
+ .name = "rpm-regulator",
+ .id = -1,
+ .dev = {
+ .platform_data = &msm_rpm_regulator_pdata,
+ },
+};
+
+static struct msm_rpm_log_platform_data msm_rpm_log_pdata = {
+ .phys_addr_base = 0x0010C000,
+ .reg_offsets = {
+ [MSM_RPM_LOG_PAGE_INDICES] = 0x00000080,
+ [MSM_RPM_LOG_PAGE_BUFFER] = 0x000000A0,
+ },
+ .phys_size = SZ_8K,
+ .log_len = 4096, /* log's buffer length in bytes */
+ .log_len_mask = (4096 >> 2) - 1, /* length mask in units of u32 */
+};
+
+static struct platform_device msm_rpm_log_device = {
+ .name = "msm_rpm_log",
+ .id = -1,
+ .dev = {
+ .platform_data = &msm_rpm_log_pdata,
+ },
+};
+
+static struct platform_device *common_devices[] __initdata = {
+ &msm8960_device_dmov,
+ &msm_device_smd,
+ &msm8960_device_uart_gsbi5,
+ &msm_device_uart_dm6,
+ &msm_device_saw_core0,
+ &msm_device_saw_core1,
+ &msm8960_device_ext_5v_vreg,
+ &msm8960_device_ext_l2_vreg,
+ &msm8960_device_ssbi_pm8921,
+ &msm8960_device_qup_spi_gsbi1,
+ &msm8960_device_qup_i2c_gsbi3,
+ &msm8960_device_qup_i2c_gsbi4,
+ &msm8960_device_qup_i2c_gsbi10,
+ &msm8960_device_qup_i2c_gsbi12,
+ &msm_slim_ctrl,
+ &msm_device_wcnss_wlan,
+#if defined(CONFIG_CRYPTO_DEV_QCRYPTO) || \
+ defined(CONFIG_CRYPTO_DEV_QCRYPTO_MODULE)
+ &qcrypto_device,
+#endif
+
+#if defined(CONFIG_CRYPTO_DEV_QCEDEV) || \
+ defined(CONFIG_CRYPTO_DEV_QCEDEV_MODULE)
+ &qcedev_device,
+#endif
+#ifdef CONFIG_MSM_ROTATOR
+ &msm_rotator_device,
+#endif
+ &msm_device_sps,
+#ifdef CONFIG_MSM_FAKE_BATTERY
+ &fish_battery_device,
+#endif
+#ifdef CONFIG_ANDROID_PMEM
+#ifndef CONFIG_MSM_MULTIMEDIA_USE_ION
+ &android_pmem_device,
+ &android_pmem_adsp_device,
+#endif
+ &android_pmem_audio_device,
+#endif
+ &msm_device_vidc,
+ &msm_device_bam_dmux,
+ &msm_fm_platform_init,
+
+#ifdef CONFIG_HW_RANDOM_MSM
+ &msm_device_rng,
+#endif
+ &msm_rpm_device,
+#ifdef CONFIG_ION_MSM
+ &ion_dev,
+#endif
+ &msm_rpm_log_device,
+ &msm_rpm_stat_device,
+ &msm_device_tz_log,
+
+#ifdef CONFIG_MSM_QDSS
+ &msm_etb_device,
+ &msm_tpiu_device,
+ &msm_funnel_device,
+ &msm_debug_device,
+ &msm_ptm_device,
+#endif
+ &msm_device_dspcrashd_8960,
+ &msm8960_device_watchdog,
+};
+
+static struct platform_device *cdp_devices[] __initdata = {
+ &msm8960_device_otg,
+ &msm8960_device_gadget_peripheral,
+ &msm_device_hsusb_host,
+ &android_usb_device,
+ &msm_pcm,
+ &msm_pcm_routing,
+ &msm_cpudai0,
+ &msm_cpudai1,
+ &msm_cpudai_hdmi_rx,
+ &msm_cpudai_bt_rx,
+ &msm_cpudai_bt_tx,
+ &msm_cpudai_fm_rx,
+ &msm_cpudai_fm_tx,
+ &msm_cpudai_auxpcm_rx,
+ &msm_cpudai_auxpcm_tx,
+ &msm_cpu_fe,
+ &msm_stub_codec,
+ &msm_kgsl_3d0,
+#ifdef CONFIG_MSM_KGSL_2D
+ &msm_kgsl_2d0,
+ &msm_kgsl_2d1,
+#endif
+#ifdef CONFIG_MSM_GEMINI
+ &msm8960_gemini_device,
+#endif
+ &msm_voice,
+ &msm_voip,
+ &msm_lpa_pcm,
+ &msm_cpudai_afe_01_rx,
+ &msm_cpudai_afe_01_tx,
+ &msm_cpudai_afe_02_rx,
+ &msm_cpudai_afe_02_tx,
+ &msm_pcm_afe,
+ &msm_pcm_hostless,
+ &msm_bus_apps_fabric,
+ &msm_bus_sys_fabric,
+ &msm_bus_mm_fabric,
+ &msm_bus_sys_fpb,
+ &msm_bus_cpss_fpb,
+ &msm_tsens_device,
+};
+
+static void __init msm8930_i2c_init(void)
+{
+ msm8960_device_qup_i2c_gsbi4.dev.platform_data =
+ &msm8960_i2c_qup_gsbi4_pdata;
+
+ msm8960_device_qup_i2c_gsbi3.dev.platform_data =
+ &msm8960_i2c_qup_gsbi3_pdata;
+
+ msm8960_device_qup_i2c_gsbi10.dev.platform_data =
+ &msm8960_i2c_qup_gsbi10_pdata;
+
+ msm8960_device_qup_i2c_gsbi12.dev.platform_data =
+ &msm8960_i2c_qup_gsbi12_pdata;
+}
+
+static void __init msm8930_gfx_init(void)
+{
+ uint32_t soc_platform_version = socinfo_get_version();
+ if (SOCINFO_VERSION_MAJOR(soc_platform_version) == 1) {
+ struct kgsl_device_platform_data *kgsl_3d0_pdata =
+ msm_kgsl_3d0.dev.platform_data;
+ kgsl_3d0_pdata->pwrlevel[0].gpu_freq = 320000000;
+ kgsl_3d0_pdata->pwrlevel[1].gpu_freq = 266667000;
+ }
+}
+
+static struct msm_cpuidle_state msm_cstates[] __initdata = {
+ {0, 0, "C0", "WFI",
+ MSM_PM_SLEEP_MODE_WAIT_FOR_INTERRUPT},
+
+ {0, 1, "C1", "STANDALONE_POWER_COLLAPSE",
+ MSM_PM_SLEEP_MODE_POWER_COLLAPSE_STANDALONE},
+
+ {0, 2, "C2", "POWER_COLLAPSE",
+ MSM_PM_SLEEP_MODE_POWER_COLLAPSE},
+
+ {1, 0, "C0", "WFI",
+ MSM_PM_SLEEP_MODE_WAIT_FOR_INTERRUPT},
+
+ {1, 1, "C1", "STANDALONE_POWER_COLLAPSE",
+ MSM_PM_SLEEP_MODE_POWER_COLLAPSE_STANDALONE},
+};
+
+static struct msm_pm_platform_data msm_pm_data[MSM_PM_SLEEP_MODE_NR * 2] = {
+ [MSM_PM_MODE(0, MSM_PM_SLEEP_MODE_POWER_COLLAPSE)] = {
+ .idle_supported = 1,
+ .suspend_supported = 1,
+ .idle_enabled = 0,
+ .suspend_enabled = 0,
+ },
+
+ [MSM_PM_MODE(0, MSM_PM_SLEEP_MODE_POWER_COLLAPSE_STANDALONE)] = {
+ .idle_supported = 1,
+ .suspend_supported = 1,
+ .idle_enabled = 0,
+ .suspend_enabled = 0,
+ },
+
+ [MSM_PM_MODE(0, MSM_PM_SLEEP_MODE_WAIT_FOR_INTERRUPT)] = {
+ .idle_supported = 1,
+ .suspend_supported = 1,
+ .idle_enabled = 1,
+ .suspend_enabled = 1,
+ },
+
+ [MSM_PM_MODE(1, MSM_PM_SLEEP_MODE_POWER_COLLAPSE)] = {
+ .idle_supported = 0,
+ .suspend_supported = 1,
+ .idle_enabled = 0,
+ .suspend_enabled = 0,
+ },
+
+ [MSM_PM_MODE(1, MSM_PM_SLEEP_MODE_POWER_COLLAPSE_STANDALONE)] = {
+ .idle_supported = 1,
+ .suspend_supported = 1,
+ .idle_enabled = 0,
+ .suspend_enabled = 0,
+ },
+
+ [MSM_PM_MODE(1, MSM_PM_SLEEP_MODE_WAIT_FOR_INTERRUPT)] = {
+ .idle_supported = 1,
+ .suspend_supported = 0,
+ .idle_enabled = 1,
+ .suspend_enabled = 0,
+ },
+};
+
+static struct msm_rpmrs_level msm_rpmrs_levels[] __initdata = {
+ {
+ MSM_PM_SLEEP_MODE_WAIT_FOR_INTERRUPT,
+ MSM_RPMRS_LIMITS(ON, ACTIVE, MAX, ACTIVE),
+ true,
+ 100, 8000, 100000, 1,
+ },
+
+ {
+ MSM_PM_SLEEP_MODE_POWER_COLLAPSE_STANDALONE,
+ MSM_RPMRS_LIMITS(ON, ACTIVE, MAX, ACTIVE),
+ true,
+ 2000, 6000, 60100000, 3000,
+ },
+
+ {
+ MSM_PM_SLEEP_MODE_POWER_COLLAPSE,
+ MSM_RPMRS_LIMITS(ON, GDHS, MAX, ACTIVE),
+ false,
+ 4200, 5000, 60350000, 3500,
+ },
+
+ {
+ MSM_PM_SLEEP_MODE_POWER_COLLAPSE,
+ MSM_RPMRS_LIMITS(ON, HSFS_OPEN, MAX, ACTIVE),
+ false,
+ 6300, 4500, 65350000, 4800,
+ },
+ {
+ MSM_PM_SLEEP_MODE_POWER_COLLAPSE,
+ MSM_RPMRS_LIMITS(ON, HSFS_OPEN, ACTIVE, RET_HIGH),
+ false,
+ 7000, 3500, 66600000, 5150,
+ },
+
+ {
+ MSM_PM_SLEEP_MODE_POWER_COLLAPSE,
+ MSM_RPMRS_LIMITS(OFF, GDHS, MAX, ACTIVE),
+ false,
+ 11700, 2500, 67850000, 5500,
+ },
+
+ {
+ MSM_PM_SLEEP_MODE_POWER_COLLAPSE,
+ MSM_RPMRS_LIMITS(OFF, HSFS_OPEN, MAX, ACTIVE),
+ false,
+ 13800, 2000, 71850000, 6800,
+ },
+
+ {
+ MSM_PM_SLEEP_MODE_POWER_COLLAPSE,
+ MSM_RPMRS_LIMITS(OFF, HSFS_OPEN, ACTIVE, RET_HIGH),
+ false,
+ 29700, 500, 75850000, 8800,
+ },
+
+ {
+ MSM_PM_SLEEP_MODE_POWER_COLLAPSE,
+ MSM_RPMRS_LIMITS(OFF, HSFS_OPEN, RET_HIGH, RET_LOW),
+ false,
+ 29700, 0, 76350000, 9800,
+ },
+};
+
+#ifdef CONFIG_I2C
+#define I2C_SURF 1
+#define I2C_FFA (1 << 1)
+#define I2C_RUMI (1 << 2)
+#define I2C_SIM (1 << 3)
+#define I2C_FLUID (1 << 4)
+#define I2C_LIQUID (1 << 5)
+
+struct i2c_registry {
+ u8 machs;
+ int bus;
+ struct i2c_board_info *info;
+ int len;
+};
+
+#ifdef CONFIG_MSM_CAMERA
+static struct i2c_board_info msm_camera_boardinfo[] __initdata = {
+#ifdef CONFIG_IMX074
+ {
+ I2C_BOARD_INFO("imx074", 0x1A),
+ },
+#endif
+#ifdef CONFIG_OV2720
+ {
+ I2C_BOARD_INFO("ov2720", 0x6C),
+ },
+#endif
+#ifdef CONFIG_MSM_CAMERA_FLASH_SC628A
+ {
+ I2C_BOARD_INFO("sc628a", 0x6E),
+ },
+#endif
+};
+#endif
+
+static void __init msm8930_init_hsic(void)
+{
+#ifdef CONFIG_USB_EHCI_MSM_HSIC
+ uint32_t version = socinfo_get_version();
+
+ pr_info("%s: version:%d mtp:%d\n", __func__,
+ SOCINFO_VERSION_MAJOR(version),
+ machine_is_msm8930_mtp());
+
+ if ((SOCINFO_VERSION_MAJOR(version) == 1) ||
+ machine_is_msm8930_mtp() ||
+ machine_is_msm8930_fluid())
+ return;
+
+ platform_device_register(&msm_device_hsic_host);
+#endif
+}
+
+#ifdef CONFIG_ISL9519_CHARGER
+static struct isl_platform_data isl_data __initdata = {
+ .valid_n_gpio = 0, /* Not required when notify-by-pmic */
+ .chg_detection_config = NULL, /* Not required when notify-by-pmic */
+ .max_system_voltage = 4200,
+ .min_system_voltage = 3200,
+ .chgcurrent = 1000, /* 1900, */
+ .term_current = 400, /* Need fine tuning */
+ .input_current = 2048,
+};
+
+static struct i2c_board_info isl_charger_i2c_info[] __initdata = {
+ {
+ I2C_BOARD_INFO("isl9519q", 0x9),
+ .irq = 0, /* Not required when notify-by-pmic */
+ .platform_data = &isl_data,
+ },
+};
+#endif /* CONFIG_ISL9519_CHARGER */
+
+static struct i2c_registry msm8960_i2c_devices[] __initdata = {
+#ifdef CONFIG_MSM_CAMERA
+ {
+ I2C_SURF | I2C_FFA | I2C_FLUID | I2C_LIQUID | I2C_RUMI,
+ MSM_8930_GSBI4_QUP_I2C_BUS_ID,
+ msm_camera_boardinfo,
+ ARRAY_SIZE(msm_camera_boardinfo),
+ },
+#endif
+#ifdef CONFIG_ISL9519_CHARGER
+ {
+ I2C_LIQUID,
+ MSM_8930_GSBI10_QUP_I2C_BUS_ID,
+ isl_charger_i2c_info,
+ ARRAY_SIZE(isl_charger_i2c_info),
+ },
+#endif /* CONFIG_ISL9519_CHARGER */
+ {
+ I2C_SURF | I2C_FFA | I2C_FLUID,
+ MSM_8930_GSBI3_QUP_I2C_BUS_ID,
+ cyttsp_info,
+ ARRAY_SIZE(cyttsp_info),
+ },
+ {
+ I2C_LIQUID,
+ MSM_8930_GSBI3_QUP_I2C_BUS_ID,
+ mxt_device_info,
+ ARRAY_SIZE(mxt_device_info),
+ },
+ {
+ I2C_LIQUID,
+ MSM_8930_GSBI10_QUP_I2C_BUS_ID,
+ msm_isa1200_board_info,
+ ARRAY_SIZE(msm_isa1200_board_info),
+ },
+};
+#endif /* CONFIG_I2C */
+
+static void __init register_i2c_devices(void)
+{
+#ifdef CONFIG_I2C
+ u8 mach_mask = 0;
+ int i;
+
+ /* Build the matching 'supported_machs' bitmask */
+ if (machine_is_msm8930_cdp() || machine_is_msm8627_cdp())
+ mach_mask = I2C_SURF;
+ else if (machine_is_msm8930_fluid())
+ mach_mask = I2C_FLUID;
+ else if (machine_is_msm8930_mtp() || machine_is_msm8627_mtp())
+ mach_mask = I2C_FFA;
+ else
+ pr_err("unmatched machine ID in register_i2c_devices\n");
+
+ /* Run the array and install devices as appropriate */
+ for (i = 0; i < ARRAY_SIZE(msm8960_i2c_devices); ++i) {
+ if (msm8960_i2c_devices[i].machs & mach_mask)
+ i2c_register_board_info(msm8960_i2c_devices[i].bus,
+ msm8960_i2c_devices[i].info,
+ msm8960_i2c_devices[i].len);
+ }
+#endif
+}
+
+static void __init msm8930_cdp_init(void)
+{
+ if (meminfo_init(SYS_MEMORY, SZ_256M) < 0)
+ pr_err("meminfo_init() failed!\n");
+
+ BUG_ON(msm_rpm_init(&msm_rpm_data));
+ BUG_ON(msm_rpmrs_levels_init(msm_rpmrs_levels,
+ ARRAY_SIZE(msm_rpmrs_levels)));
+
+ regulator_suppress_info_printing();
+ if (msm_xo_init())
+ pr_err("Failed to initialize XO votes\n");
+ platform_device_register(&msm8960_device_rpm_regulator);
+ msm_clock_init(&msm8960_clock_init_data);
+ msm8960_device_otg.dev.platform_data = &msm_otg_pdata;
+ msm_device_hsic_host.dev.platform_data = &msm_hsic_pdata;
+ msm8930_init_gpiomux();
+ msm8960_device_qup_spi_gsbi1.dev.platform_data =
+ &msm8960_qup_spi_gsbi1_pdata;
+ spi_register_board_info(spi_board_info, ARRAY_SIZE(spi_board_info));
+
+ msm8930_init_pmic();
+ msm8930_i2c_init();
+ msm8930_gfx_init();
+ msm_spm_init(msm_spm_data, ARRAY_SIZE(msm_spm_data));
+ msm_spm_l2_init(msm_spm_l2_data);
+ msm8930_init_buses();
+ platform_add_devices(msm_footswitch_devices,
+ msm_num_footswitch_devices);
+ platform_add_devices(common_devices, ARRAY_SIZE(common_devices));
+ msm8930_pm8921_gpio_mpp_init();
+ platform_add_devices(cdp_devices, ARRAY_SIZE(cdp_devices));
+ msm8930_init_hsic();
+ msm8930_init_cam();
+ msm8930_init_mmc();
+ acpuclk_init(&acpuclk_8960_soc_data);
+ register_i2c_devices();
+ msm8930_init_fb();
+ slim_register_board_info(msm_slim_devices,
+ ARRAY_SIZE(msm_slim_devices));
+ msm_pm_set_platform_data(msm_pm_data, ARRAY_SIZE(msm_pm_data));
+ msm_pm_set_rpm_wakeup_irq(RPM_APCC_CPU0_WAKE_UP_IRQ);
+ msm_cpuidle_set_states(msm_cstates, ARRAY_SIZE(msm_cstates),
+ msm_pm_data);
+ change_memory_power = &msm8930_change_memory_power;
+ BUG_ON(msm_pm_boot_init(MSM_PM_BOOT_CONFIG_TZ, NULL));
+
+ if (PLATFORM_IS_CHARM25())
+ platform_add_devices(mdm_devices, ARRAY_SIZE(mdm_devices));
+}
+
+MACHINE_START(MSM8930_CDP, "QCT MSM8930 CDP")
+ .map_io = msm8930_map_io,
+ .reserve = msm8930_reserve,
+ .init_irq = msm8930_init_irq,
+ .timer = &msm_timer,
+ .init_machine = msm8930_cdp_init,
+ .init_early = msm8930_allocate_memory_regions,
+ .init_very_early = msm8930_early_memory,
+MACHINE_END
+
+MACHINE_START(MSM8930_MTP, "QCT MSM8930 MTP")
+ .map_io = msm8930_map_io,
+ .reserve = msm8930_reserve,
+ .init_irq = msm8930_init_irq,
+ .timer = &msm_timer,
+ .init_machine = msm8930_cdp_init,
+ .init_early = msm8930_allocate_memory_regions,
+ .init_very_early = msm8930_early_memory,
+MACHINE_END
+
+MACHINE_START(MSM8930_FLUID, "QCT MSM8930 FLUID")
+ .map_io = msm8930_map_io,
+ .reserve = msm8930_reserve,
+ .init_irq = msm8930_init_irq,
+ .timer = &msm_timer,
+ .init_machine = msm8930_cdp_init,
+ .init_early = msm8930_allocate_memory_regions,
+ .init_very_early = msm8930_early_memory,
+MACHINE_END
+
+MACHINE_START(MSM8627_CDP, "QCT MSM8627 CDP")
+ .map_io = msm8930_map_io,
+ .reserve = msm8930_reserve,
+ .init_irq = msm8930_init_irq,
+ .timer = &msm_timer,
+ .init_machine = msm8930_cdp_init,
+ .init_early = msm8930_allocate_memory_regions,
+ .init_very_early = msm8930_early_memory,
+MACHINE_END
+
+MACHINE_START(MSM8627_MTP, "QCT MSM8627 MTP")
+ .map_io = msm8930_map_io,
+ .reserve = msm8930_reserve,
+ .init_irq = msm8930_init_irq,
+ .timer = &msm_timer,
+ .init_machine = msm8930_cdp_init,
+ .init_early = msm8930_allocate_memory_regions,
+ .init_very_early = msm8930_early_memory,
+MACHINE_END
diff --git a/arch/arm/mach-msm/board-8930.h b/arch/arm/mach-msm/board-8930.h
new file mode 100644
index 0000000..c413061
--- /dev/null
+++ b/arch/arm/mach-msm/board-8930.h
@@ -0,0 +1,86 @@
+/* Copyright (c) 2011, Code Aurora Forum. 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 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#ifndef __ARCH_ARM_MACH_MSM_BOARD_MSM8930_H
+#define __ARCH_ARM_MACH_MSM_BOARD_MSM8930_H
+
+#include <linux/regulator/gpio-regulator.h>
+#include <linux/mfd/pm8xxx/pm8921.h>
+#include <linux/i2c/sx150x.h>
+#include <mach/irqs.h>
+#include <mach/rpm-regulator.h>
+
+/* Macros assume PMIC GPIOs and MPPs start at 1 */
+#define PM8921_GPIO_BASE NR_GPIO_IRQS
+#define PM8921_GPIO_PM_TO_SYS(pm_gpio) (pm_gpio - 1 + PM8921_GPIO_BASE)
+#define PM8921_MPP_BASE (PM8921_GPIO_BASE + PM8921_NR_GPIOS)
+#define PM8921_MPP_PM_TO_SYS(pm_gpio) (pm_gpio - 1 + PM8921_MPP_BASE)
+#define PM8921_IRQ_BASE (NR_MSM_IRQS + NR_GPIO_IRQS)
+
+extern struct pm8921_regulator_platform_data
+ msm_pm8921_regulator_pdata[] __devinitdata;
+
+extern int msm_pm8921_regulator_pdata_len __devinitdata;
+
+#define GPIO_VREG_ID_EXT_5V 0
+#define GPIO_VREG_ID_EXT_L2 1
+#define GPIO_VREG_ID_EXT_3P3V 2
+
+extern struct gpio_regulator_platform_data
+ msm_gpio_regulator_pdata[] __devinitdata;
+
+extern struct regulator_init_data msm_saw_regulator_pdata_s5;
+extern struct regulator_init_data msm_saw_regulator_pdata_s6;
+
+extern struct rpm_regulator_platform_data msm_rpm_regulator_pdata __devinitdata;
+
+#if defined(CONFIG_GPIO_SX150X) || defined(CONFIG_GPIO_SX150X_MODULE)
+enum {
+ GPIO_EXPANDER_IRQ_BASE = (PM8921_IRQ_BASE + PM8921_NR_IRQS),
+ GPIO_EXPANDER_GPIO_BASE = (PM8921_MPP_BASE + PM8921_NR_MPPS),
+ /* CAM Expander */
+ GPIO_CAM_EXPANDER_BASE = GPIO_EXPANDER_GPIO_BASE,
+ GPIO_CAM_GP_STROBE_READY = GPIO_CAM_EXPANDER_BASE,
+ GPIO_CAM_GP_AFBUSY,
+ GPIO_CAM_GP_STROBE_CE,
+ GPIO_CAM_GP_CAM1MP_XCLR,
+ GPIO_CAM_GP_CAMIF_RESET_N,
+ GPIO_CAM_GP_XMT_FLASH_INT,
+ GPIO_CAM_GP_LED_EN1,
+ GPIO_CAM_GP_LED_EN2,
+
+};
+#endif
+
+enum {
+ SX150X_CAM,
+};
+
+#endif
+
+extern struct sx150x_platform_data msm8930_sx150x_data[];
+void msm8930_init_cam(void);
+void msm8930_init_fb(void);
+void msm8930_init_pmic(void);
+void msm8930_init_mmc(void);
+int msm8930_init_gpiomux(void);
+void msm8930_allocate_fb_region(void);
+void msm8930_pm8921_gpio_mpp_init(void);
+
+#define PLATFORM_IS_CHARM25() \
+ (machine_is_msm8930_cdp() && \
+ (socinfo_get_platform_subtype() == 1) \
+ )
+
+#define MSM_8930_GSBI4_QUP_I2C_BUS_ID 4
+#define MSM_8930_GSBI3_QUP_I2C_BUS_ID 3
+#define MSM_8930_GSBI10_QUP_I2C_BUS_ID 10
diff --git a/arch/arm/mach-msm/board-8960-camera.c b/arch/arm/mach-msm/board-8960-camera.c
new file mode 100644
index 0000000..e827b2b
--- /dev/null
+++ b/arch/arm/mach-msm/board-8960-camera.c
@@ -0,0 +1,503 @@
+/* Copyright (c) 2011, Code Aurora Forum. 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 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#include <linux/i2c.h>
+#include <linux/i2c/sx150x.h>
+#include <asm/mach-types.h>
+#include <mach/board.h>
+#include <mach/msm_bus_board.h>
+#include <mach/gpio.h>
+#include <mach/gpiomux.h>
+#include "devices.h"
+#include "board-8960.h"
+
+#if (defined(CONFIG_GPIO_SX150X) || defined(CONFIG_GPIO_SX150X_MODULE)) && \
+ defined(CONFIG_I2C)
+
+static struct i2c_board_info cam_expander_i2c_info[] = {
+ {
+ I2C_BOARD_INFO("sx1508q", 0x22),
+ .platform_data = &msm8960_sx150x_data[SX150X_CAM]
+ },
+};
+
+static struct msm_cam_expander_info cam_expander_info[] = {
+ {
+ cam_expander_i2c_info,
+ MSM_8960_GSBI4_QUP_I2C_BUS_ID,
+ },
+};
+#endif
+
+static struct gpiomux_setting cam_settings[] = {
+ {
+ .func = GPIOMUX_FUNC_GPIO, /*suspend*/
+ .drv = GPIOMUX_DRV_2MA,
+ .pull = GPIOMUX_PULL_DOWN,
+ },
+
+ {
+ .func = GPIOMUX_FUNC_1, /*active 1*/
+ .drv = GPIOMUX_DRV_2MA,
+ .pull = GPIOMUX_PULL_NONE,
+ },
+
+ {
+ .func = GPIOMUX_FUNC_GPIO, /*active 2*/
+ .drv = GPIOMUX_DRV_2MA,
+ .pull = GPIOMUX_PULL_NONE,
+ },
+
+ {
+ .func = GPIOMUX_FUNC_1, /*active 3*/
+ .drv = GPIOMUX_DRV_8MA,
+ .pull = GPIOMUX_PULL_NONE,
+ },
+
+ {
+ .func = GPIOMUX_FUNC_5, /*active 4*/
+ .drv = GPIOMUX_DRV_8MA,
+ .pull = GPIOMUX_PULL_UP,
+ },
+
+ {
+ .func = GPIOMUX_FUNC_6, /*active 5*/
+ .drv = GPIOMUX_DRV_8MA,
+ .pull = GPIOMUX_PULL_UP,
+ },
+
+ {
+ .func = GPIOMUX_FUNC_2, /*active 6*/
+ .drv = GPIOMUX_DRV_2MA,
+ .pull = GPIOMUX_PULL_UP,
+ },
+
+ {
+ .func = GPIOMUX_FUNC_3, /*active 7*/
+ .drv = GPIOMUX_DRV_8MA,
+ .pull = GPIOMUX_PULL_UP,
+ },
+
+ {
+ .func = GPIOMUX_FUNC_GPIO, /*i2c suspend*/
+ .drv = GPIOMUX_DRV_2MA,
+ .pull = GPIOMUX_PULL_KEEPER,
+ },
+
+};
+
+static struct msm_gpiomux_config msm8960_cdp_flash_configs[] = {
+ {
+ .gpio = 3,
+ .settings = {
+ [GPIOMUX_ACTIVE] = &cam_settings[1],
+ [GPIOMUX_SUSPENDED] = &cam_settings[0],
+ },
+ },
+};
+
+static struct msm_gpiomux_config msm8960_cam_common_configs[] = {
+ {
+ .gpio = 2,
+ .settings = {
+ [GPIOMUX_ACTIVE] = &cam_settings[2],
+ [GPIOMUX_SUSPENDED] = &cam_settings[0],
+ },
+ },
+ {
+ .gpio = 3,
+ .settings = {
+ [GPIOMUX_ACTIVE] = &cam_settings[2],
+ [GPIOMUX_SUSPENDED] = &cam_settings[0],
+ },
+ },
+ {
+ .gpio = 4,
+ .settings = {
+ [GPIOMUX_ACTIVE] = &cam_settings[1],
+ [GPIOMUX_SUSPENDED] = &cam_settings[0],
+ },
+ },
+ {
+ .gpio = 5,
+ .settings = {
+ [GPIOMUX_ACTIVE] = &cam_settings[1],
+ [GPIOMUX_SUSPENDED] = &cam_settings[0],
+ },
+ },
+ {
+ .gpio = 76,
+ .settings = {
+ [GPIOMUX_ACTIVE] = &cam_settings[2],
+ [GPIOMUX_SUSPENDED] = &cam_settings[0],
+ },
+ },
+ {
+ .gpio = 107,
+ .settings = {
+ [GPIOMUX_ACTIVE] = &cam_settings[2],
+ [GPIOMUX_SUSPENDED] = &cam_settings[0],
+ },
+ },
+};
+
+static struct msm_gpiomux_config msm8960_cam_2d_configs[] = {
+ {
+ .gpio = 18,
+ .settings = {
+ [GPIOMUX_ACTIVE] = &cam_settings[3],
+ [GPIOMUX_SUSPENDED] = &cam_settings[8],
+ },
+ },
+ {
+ .gpio = 19,
+ .settings = {
+ [GPIOMUX_ACTIVE] = &cam_settings[3],
+ [GPIOMUX_SUSPENDED] = &cam_settings[8],
+ },
+ },
+ {
+ .gpio = 20,
+ .settings = {
+ [GPIOMUX_ACTIVE] = &cam_settings[3],
+ [GPIOMUX_SUSPENDED] = &cam_settings[8],
+ },
+ },
+ {
+ .gpio = 21,
+ .settings = {
+ [GPIOMUX_ACTIVE] = &cam_settings[3],
+ [GPIOMUX_SUSPENDED] = &cam_settings[8],
+ },
+ },
+};
+
+#ifdef CONFIG_MSM_CAMERA
+
+static uint16_t msm_cam_gpio_2d_tbl[] = {
+ 5, /*CAMIF_MCLK*/
+ 20, /*CAMIF_I2C_DATA*/
+ 21, /*CAMIF_I2C_CLK*/
+};
+
+static struct msm_camera_gpio_conf gpio_conf = {
+ .cam_gpiomux_conf_tbl = msm8960_cam_2d_configs,
+ .cam_gpiomux_conf_tbl_size = ARRAY_SIZE(msm8960_cam_2d_configs),
+ .cam_gpio_tbl = msm_cam_gpio_2d_tbl,
+ .cam_gpio_tbl_size = ARRAY_SIZE(msm_cam_gpio_2d_tbl),
+};
+
+#define VFE_CAMIF_TIMER1_GPIO 2
+#define VFE_CAMIF_TIMER2_GPIO 3
+#define VFE_CAMIF_TIMER3_GPIO_INT 4
+static struct msm_camera_sensor_strobe_flash_data strobe_flash_xenon = {
+ .flash_trigger = VFE_CAMIF_TIMER2_GPIO,
+ .flash_charge = VFE_CAMIF_TIMER1_GPIO,
+ .flash_charge_done = VFE_CAMIF_TIMER3_GPIO_INT,
+ .flash_recharge_duration = 50000,
+ .irq = MSM_GPIO_TO_INT(VFE_CAMIF_TIMER3_GPIO_INT),
+};
+
+#ifdef CONFIG_MSM_CAMERA_FLASH
+static struct msm_camera_sensor_flash_src msm_flash_src = {
+ .flash_sr_type = MSM_CAMERA_FLASH_SRC_EXT,
+ ._fsrc.ext_driver_src.led_en = VFE_CAMIF_TIMER1_GPIO,
+ ._fsrc.ext_driver_src.led_flash_en = VFE_CAMIF_TIMER2_GPIO,
+};
+#endif
+
+static struct msm_bus_vectors cam_init_vectors[] = {
+ {
+ .src = MSM_BUS_MASTER_VFE,
+ .dst = MSM_BUS_SLAVE_EBI_CH0,
+ .ab = 0,
+ .ib = 0,
+ },
+ {
+ .src = MSM_BUS_MASTER_VPE,
+ .dst = MSM_BUS_SLAVE_EBI_CH0,
+ .ab = 0,
+ .ib = 0,
+ },
+ {
+ .src = MSM_BUS_MASTER_JPEG_ENC,
+ .dst = MSM_BUS_SLAVE_EBI_CH0,
+ .ab = 0,
+ .ib = 0,
+ },
+};
+
+static struct msm_bus_vectors cam_preview_vectors[] = {
+ {
+ .src = MSM_BUS_MASTER_VFE,
+ .dst = MSM_BUS_SLAVE_EBI_CH0,
+ .ab = 27648000,
+ .ib = 110592000,
+ },
+ {
+ .src = MSM_BUS_MASTER_VPE,
+ .dst = MSM_BUS_SLAVE_EBI_CH0,
+ .ab = 0,
+ .ib = 0,
+ },
+ {
+ .src = MSM_BUS_MASTER_JPEG_ENC,
+ .dst = MSM_BUS_SLAVE_EBI_CH0,
+ .ab = 0,
+ .ib = 0,
+ },
+};
+
+static struct msm_bus_vectors cam_video_vectors[] = {
+ {
+ .src = MSM_BUS_MASTER_VFE,
+ .dst = MSM_BUS_SLAVE_EBI_CH0,
+ .ab = 140451840,
+ .ib = 561807360,
+ },
+ {
+ .src = MSM_BUS_MASTER_VPE,
+ .dst = MSM_BUS_SLAVE_EBI_CH0,
+ .ab = 206807040,
+ .ib = 488816640,
+ },
+ {
+ .src = MSM_BUS_MASTER_JPEG_ENC,
+ .dst = MSM_BUS_SLAVE_EBI_CH0,
+ .ab = 0,
+ .ib = 0,
+ },
+};
+
+static struct msm_bus_vectors cam_snapshot_vectors[] = {
+ {
+ .src = MSM_BUS_MASTER_VFE,
+ .dst = MSM_BUS_SLAVE_EBI_CH0,
+ .ab = 274423680,
+ .ib = 1097694720,
+ },
+ {
+ .src = MSM_BUS_MASTER_VPE,
+ .dst = MSM_BUS_SLAVE_EBI_CH0,
+ .ab = 0,
+ .ib = 0,
+ },
+ {
+ .src = MSM_BUS_MASTER_JPEG_ENC,
+ .dst = MSM_BUS_SLAVE_EBI_CH0,
+ .ab = 540000000,
+ .ib = 1350000000,
+ },
+};
+
+static struct msm_bus_vectors cam_zsl_vectors[] = {
+ {
+ .src = MSM_BUS_MASTER_VFE,
+ .dst = MSM_BUS_SLAVE_EBI_CH0,
+ .ab = 302071680,
+ .ib = 1208286720,
+ },
+ {
+ .src = MSM_BUS_MASTER_VPE,
+ .dst = MSM_BUS_SLAVE_EBI_CH0,
+ .ab = 0,
+ .ib = 0,
+ },
+ {
+ .src = MSM_BUS_MASTER_JPEG_ENC,
+ .dst = MSM_BUS_SLAVE_EBI_CH0,
+ .ab = 540000000,
+ .ib = 1350000000,
+ },
+};
+
+static struct msm_bus_paths cam_bus_client_config[] = {
+ {
+ ARRAY_SIZE(cam_init_vectors),
+ cam_init_vectors,
+ },
+ {
+ ARRAY_SIZE(cam_preview_vectors),
+ cam_preview_vectors,
+ },
+ {
+ ARRAY_SIZE(cam_video_vectors),
+ cam_video_vectors,
+ },
+ {
+ ARRAY_SIZE(cam_snapshot_vectors),
+ cam_snapshot_vectors,
+ },
+ {
+ ARRAY_SIZE(cam_zsl_vectors),
+ cam_zsl_vectors,
+ },
+};
+
+static struct msm_bus_scale_pdata cam_bus_client_pdata = {
+ cam_bus_client_config,
+ ARRAY_SIZE(cam_bus_client_config),
+ .name = "msm_camera",
+};
+
+static struct msm_camera_device_platform_data msm_camera_csi_device_data[] = {
+ {
+ .ioclk.mclk_clk_rate = 24000000,
+ .ioclk.vfe_clk_rate = 228570000,
+ .csid_core = 0,
+ .cam_bus_scale_table = &cam_bus_client_pdata,
+ },
+ {
+ .ioclk.mclk_clk_rate = 24000000,
+ .ioclk.vfe_clk_rate = 228570000,
+ .csid_core = 1,
+ .cam_bus_scale_table = &cam_bus_client_pdata,
+ },
+};
+
+#ifdef CONFIG_IMX074_ACT
+static struct i2c_board_info imx074_actuator_i2c_info = {
+ I2C_BOARD_INFO("imx074_act", 0x11),
+};
+
+static struct msm_actuator_info imx074_actuator_info = {
+ .board_info = &imx074_actuator_i2c_info,
+ .bus_id = MSM_8960_GSBI4_QUP_I2C_BUS_ID,
+ .vcm_pwd = 0,
+ .vcm_enable = 1,
+};
+#endif
+
+#ifdef CONFIG_IMX074
+static struct msm_camera_sensor_flash_data flash_imx074 = {
+ .flash_type = MSM_CAMERA_FLASH_LED,
+#ifdef CONFIG_MSM_CAMERA_FLASH
+ .flash_src = &msm_flash_src
+#endif
+};
+
+static struct msm_camera_sensor_platform_info sensor_board_info_imx074 = {
+ .mount_angle = 90,
+ .sensor_reset = 107,
+ .sensor_pwd = 85,
+ .vcm_pwd = 0,
+ .vcm_enable = 1,
+};
+
+static struct msm_camera_sensor_info msm_camera_sensor_imx074_data = {
+ .sensor_name = "imx074",
+ .pdata = &msm_camera_csi_device_data[0],
+ .flash_data = &flash_imx074,
+ .strobe_flash_data = &strobe_flash_xenon,
+ .sensor_platform_info = &sensor_board_info_imx074,
+ .gpio_conf = &gpio_conf,
+ .csi_if = 1,
+ .camera_type = BACK_CAMERA_2D,
+#ifdef CONFIG_IMX074_ACT
+ .actuator_info = &imx074_actuator_info
+#endif
+};
+
+static struct platform_device msm8960_camera_sensor_imx074 = {
+ .name = "msm_camera_imx074",
+ .dev = {
+ .platform_data = &msm_camera_sensor_imx074_data,
+ },
+};
+#endif
+#ifdef CONFIG_OV2720
+static struct msm_camera_sensor_flash_data flash_ov2720 = {
+ .flash_type = MSM_CAMERA_FLASH_NONE,
+};
+
+static struct msm_camera_sensor_platform_info sensor_board_info_ov2720 = {
+ .mount_angle = 0,
+ .sensor_reset = 76,
+ .sensor_pwd = 85,
+ .vcm_pwd = 0,
+ .vcm_enable = 1,
+};
+
+static struct msm_camera_sensor_info msm_camera_sensor_ov2720_data = {
+ .sensor_name = "ov2720",
+ .pdata = &msm_camera_csi_device_data[1],
+ .flash_data = &flash_ov2720,
+ .sensor_platform_info = &sensor_board_info_ov2720,
+ .gpio_conf = &gpio_conf,
+ .csi_if = 1,
+ .camera_type = FRONT_CAMERA_2D,
+};
+
+static struct platform_device msm8960_camera_sensor_ov2720 = {
+ .name = "msm_camera_ov2720",
+ .dev = {
+ .platform_data = &msm_camera_sensor_ov2720_data,
+ },
+};
+#endif
+
+static struct msm8960_privacy_light_cfg privacy_light_info = {
+ .mpp = PM8921_MPP_PM_TO_SYS(12),
+};
+
+void __init msm8960_init_cam(void)
+{
+ int i;
+ struct platform_device *cam_dev[] = {
+ &msm8960_camera_sensor_imx074,
+ &msm8960_camera_sensor_ov2720,
+ };
+
+ msm_gpiomux_install(msm8960_cam_common_configs,
+ ARRAY_SIZE(msm8960_cam_common_configs));
+
+ if (machine_is_msm8960_cdp()) {
+ msm_gpiomux_install(msm8960_cdp_flash_configs,
+ ARRAY_SIZE(msm8960_cdp_flash_configs));
+ msm_flash_src._fsrc.ext_driver_src.led_en =
+ GPIO_CAM_GP_LED_EN1;
+ msm_flash_src._fsrc.ext_driver_src.led_flash_en =
+ GPIO_CAM_GP_LED_EN2;
+ #if defined(CONFIG_I2C) && (defined(CONFIG_GPIO_SX150X) || \
+ defined(CONFIG_GPIO_SX150X_MODULE))
+ msm_flash_src._fsrc.ext_driver_src.expander_info =
+ cam_expander_info;
+ #endif
+ }
+
+ if (machine_is_msm8960_liquid()) {
+ struct msm_camera_sensor_info *s_info;
+ s_info = msm8960_camera_sensor_imx074.dev.platform_data;
+ s_info->sensor_platform_info->mount_angle = 180;
+ s_info = msm8960_camera_sensor_ov2720.dev.platform_data;
+ s_info->sensor_platform_info->privacy_light = 1;
+ s_info->sensor_platform_info->privacy_light_info =
+ &privacy_light_info;
+ }
+
+ for (i = 0; i < ARRAY_SIZE(cam_dev); i++) {
+ struct msm_camera_sensor_info *s_info;
+ s_info = cam_dev[i]->dev.platform_data;
+ msm_get_cam_resources(s_info);
+ platform_device_register(cam_dev[i]);
+ }
+
+ platform_device_register(&msm8960_device_csiphy0);
+ platform_device_register(&msm8960_device_csiphy1);
+ platform_device_register(&msm8960_device_csid0);
+ platform_device_register(&msm8960_device_csid1);
+ platform_device_register(&msm8960_device_ispif);
+ platform_device_register(&msm8960_device_vfe);
+ platform_device_register(&msm8960_device_vpe);
+}
+#endif
diff --git a/arch/arm/mach-msm/board-8960-display.c b/arch/arm/mach-msm/board-8960-display.c
new file mode 100644
index 0000000..63c51ea
--- /dev/null
+++ b/arch/arm/mach-msm/board-8960-display.c
@@ -0,0 +1,961 @@
+/* Copyright (c) 2011, Code Aurora Forum. 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 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#include <linux/init.h>
+#include <linux/ioport.h>
+#include <linux/platform_device.h>
+#include <linux/bootmem.h>
+#include <asm/mach-types.h>
+#include <mach/msm_bus_board.h>
+#include <mach/board.h>
+#include <mach/gpio.h>
+#include <mach/gpiomux.h>
+#include "devices.h"
+#include "board-8960.h"
+
+#ifdef CONFIG_FB_MSM_TRIPLE_BUFFER
+#define MSM_FB_PRIM_BUF_SIZE (1376 * 768 * 4 * 3) /* 4 bpp x 3 pages */
+#else
+#define MSM_FB_PRIM_BUF_SIZE (1376 * 768 * 4 * 2) /* 4 bpp x 2 pages */
+#endif
+
+#ifdef CONFIG_FB_MSM_HDMI_MSM_PANEL
+#define MSM_FB_EXT_BUF_SIZE (1920 * 1088 * 2 * 1) /* 2 bpp x 1 page */
+#elif defined(CONFIG_FB_MSM_TVOUT)
+#define MSM_FB_EXT_BUF_SIZE (720 * 576 * 2 * 2) /* 2 bpp x 2 pages */
+#else
+#define MSM_FB_EXT_BUF_SIZE 0
+#endif
+
+#ifdef CONFIG_FB_MSM_OVERLAY0_WRITEBACK
+/* width x height x 3 bpp x 2 frame buffer */
+#define MSM_FB_WRITEBACK_SIZE (1376 * 768 * 3 * 2)
+#define MSM_FB_WRITEBACK_OFFSET \
+ (MSM_FB_PRIM_BUF_SIZE + MSM_FB_EXT_BUF_SIZE)
+#else
+#define MSM_FB_WRITEBACK_SIZE 0
+#define MSM_FB_WRITEBACK_OFFSET 0
+#endif
+
+#ifdef CONFIG_FB_MSM_HDMI_AS_PRIMARY
+/* 4 bpp x 2 page HDMI case */
+#define MSM_FB_SIZE roundup((1920 * 1088 * 4 * 2), 4096)
+#else
+/* Note: must be multiple of 4096 */
+#define MSM_FB_SIZE roundup(MSM_FB_PRIM_BUF_SIZE + MSM_FB_EXT_BUF_SIZE + \
+ MSM_FB_WRITEBACK_SIZE, 4096)
+#endif
+
+#define MDP_VSYNC_GPIO 0
+
+#define PANEL_NAME_MAX_LEN 30
+#define MIPI_CMD_NOVATEK_QHD_PANEL_NAME "mipi_cmd_novatek_qhd"
+#define MIPI_VIDEO_NOVATEK_QHD_PANEL_NAME "mipi_video_novatek_qhd"
+#define MIPI_VIDEO_TOSHIBA_WSVGA_PANEL_NAME "mipi_video_toshiba_wsvga"
+#define MIPI_VIDEO_CHIMEI_WXGA_PANEL_NAME "mipi_video_chimei_wxga"
+#define MIPI_VIDEO_SIMULATOR_VGA_PANEL_NAME "mipi_video_simulator_vga"
+#define MIPI_CMD_RENESAS_FWVGA_PANEL_NAME "mipi_cmd_renesas_fwvga"
+#define HDMI_PANEL_NAME "hdmi_msm"
+#define TVOUT_PANEL_NAME "tvout_msm"
+
+static int writeback_offset(void)
+{
+ return MSM_FB_WRITEBACK_OFFSET;
+}
+
+static struct resource msm_fb_resources[] = {
+ {
+ .flags = IORESOURCE_DMA,
+ }
+};
+
+static int msm_fb_detect_panel(const char *name)
+{
+ if (machine_is_msm8960_liquid()) {
+ if (!strncmp(name, MIPI_VIDEO_CHIMEI_WXGA_PANEL_NAME,
+ strnlen(MIPI_VIDEO_CHIMEI_WXGA_PANEL_NAME,
+ PANEL_NAME_MAX_LEN)))
+ return 0;
+ } else {
+ if (!strncmp(name, MIPI_VIDEO_TOSHIBA_WSVGA_PANEL_NAME,
+ strnlen(MIPI_VIDEO_TOSHIBA_WSVGA_PANEL_NAME,
+ PANEL_NAME_MAX_LEN)))
+ return 0;
+
+#ifndef CONFIG_FB_MSM_MIPI_PANEL_DETECT
+ if (!strncmp(name, MIPI_VIDEO_NOVATEK_QHD_PANEL_NAME,
+ strnlen(MIPI_VIDEO_NOVATEK_QHD_PANEL_NAME,
+ PANEL_NAME_MAX_LEN)))
+ return 0;
+
+ if (!strncmp(name, MIPI_CMD_NOVATEK_QHD_PANEL_NAME,
+ strnlen(MIPI_CMD_NOVATEK_QHD_PANEL_NAME,
+ PANEL_NAME_MAX_LEN)))
+ return 0;
+
+ if (!strncmp(name, MIPI_VIDEO_SIMULATOR_VGA_PANEL_NAME,
+ strnlen(MIPI_VIDEO_SIMULATOR_VGA_PANEL_NAME,
+ PANEL_NAME_MAX_LEN)))
+ return 0;
+
+ if (!strncmp(name, MIPI_CMD_RENESAS_FWVGA_PANEL_NAME,
+ strnlen(MIPI_CMD_RENESAS_FWVGA_PANEL_NAME,
+ PANEL_NAME_MAX_LEN)))
+ return 0;
+#endif
+ }
+
+ if (!strncmp(name, HDMI_PANEL_NAME,
+ strnlen(HDMI_PANEL_NAME,
+ PANEL_NAME_MAX_LEN)))
+ return 0;
+
+ if (!strncmp(name, TVOUT_PANEL_NAME,
+ strnlen(TVOUT_PANEL_NAME,
+ PANEL_NAME_MAX_LEN)))
+ return 0;
+
+ pr_warning("%s: not supported '%s'", __func__, name);
+ return -ENODEV;
+}
+
+static struct msm_fb_platform_data msm_fb_pdata = {
+ .detect_client = msm_fb_detect_panel,
+};
+
+static struct platform_device msm_fb_device = {
+ .name = "msm_fb",
+ .id = 0,
+ .num_resources = ARRAY_SIZE(msm_fb_resources),
+ .resource = msm_fb_resources,
+ .dev.platform_data = &msm_fb_pdata,
+};
+
+static bool dsi_power_on;
+
+/**
+ * LiQUID panel on/off
+ *
+ * @param on
+ *
+ * @return int
+ */
+static int mipi_dsi_liquid_panel_power(int on)
+{
+ static struct regulator *reg_l2, *reg_ext_3p3v;
+ static int gpio21, gpio24, gpio43;
+ int rc;
+
+ pr_info("%s: on=%d\n", __func__, on);
+
+ gpio21 = PM8921_GPIO_PM_TO_SYS(21); /* disp power enable_n */
+ gpio43 = PM8921_GPIO_PM_TO_SYS(43); /* Displays Enable (rst_n)*/
+ gpio24 = PM8921_GPIO_PM_TO_SYS(24); /* Backlight PWM */
+
+ if (!dsi_power_on) {
+
+ reg_l2 = regulator_get(&msm_mipi_dsi1_device.dev,
+ "dsi_vdda");
+ if (IS_ERR(reg_l2)) {
+ pr_err("could not get 8921_l2, rc = %ld\n",
+ PTR_ERR(reg_l2));
+ return -ENODEV;
+ }
+
+ rc = regulator_set_voltage(reg_l2, 1200000, 1200000);
+ if (rc) {
+ pr_err("set_voltage l2 failed, rc=%d\n", rc);
+ return -EINVAL;
+ }
+
+ reg_ext_3p3v = regulator_get(&msm_mipi_dsi1_device.dev,
+ "vdd_lvds_3p3v");
+ if (IS_ERR(reg_ext_3p3v)) {
+ pr_err("could not get reg_ext_3p3v, rc = %ld\n",
+ PTR_ERR(reg_ext_3p3v));
+ return -ENODEV;
+ }
+
+ rc = gpio_request(gpio21, "disp_pwr_en_n");
+ if (rc) {
+ pr_err("request gpio 21 failed, rc=%d\n", rc);
+ return -ENODEV;
+ }
+
+ rc = gpio_request(gpio43, "disp_rst_n");
+ if (rc) {
+ pr_err("request gpio 43 failed, rc=%d\n", rc);
+ return -ENODEV;
+ }
+
+ rc = gpio_request(gpio24, "disp_backlight_pwm");
+ if (rc) {
+ pr_err("request gpio 24 failed, rc=%d\n", rc);
+ return -ENODEV;
+ }
+
+ dsi_power_on = true;
+ }
+
+ if (on) {
+ rc = regulator_set_optimum_mode(reg_l2, 100000);
+ if (rc < 0) {
+ pr_err("set_optimum_mode l2 failed, rc=%d\n", rc);
+ return -EINVAL;
+ }
+ rc = regulator_enable(reg_l2);
+ if (rc) {
+ pr_err("enable l2 failed, rc=%d\n", rc);
+ return -ENODEV;
+ }
+
+ rc = regulator_enable(reg_ext_3p3v);
+ if (rc) {
+ pr_err("enable reg_ext_3p3v failed, rc=%d\n", rc);
+ return -ENODEV;
+ }
+
+ /* set reset pin before power enable */
+ gpio_set_value_cansleep(gpio43, 0); /* disp disable (resx=0) */
+
+ gpio_set_value_cansleep(gpio21, 0); /* disp power enable_n */
+ msleep(20);
+ gpio_set_value_cansleep(gpio43, 1); /* disp enable */
+ msleep(20);
+ gpio_set_value_cansleep(gpio43, 0); /* disp enable */
+ msleep(20);
+ gpio_set_value_cansleep(gpio43, 1); /* disp enable */
+ msleep(20);
+ } else {
+ gpio_set_value_cansleep(gpio43, 0);
+ gpio_set_value_cansleep(gpio21, 1);
+
+ rc = regulator_disable(reg_l2);
+ if (rc) {
+ pr_err("disable reg_l2 failed, rc=%d\n", rc);
+ return -ENODEV;
+ }
+ rc = regulator_disable(reg_ext_3p3v);
+ if (rc) {
+ pr_err("disable reg_ext_3p3v failed, rc=%d\n", rc);
+ return -ENODEV;
+ }
+ rc = regulator_set_optimum_mode(reg_l2, 100);
+ if (rc < 0) {
+ pr_err("set_optimum_mode l2 failed, rc=%d\n", rc);
+ return -EINVAL;
+ }
+ }
+
+ return 0;
+}
+
+static int mipi_dsi_cdp_panel_power(int on)
+{
+ static struct regulator *reg_l8, *reg_l23, *reg_l2;
+ static int gpio43;
+ int rc;
+
+ pr_info("%s: state : %d\n", __func__, on);
+
+ if (!dsi_power_on) {
+
+ reg_l8 = regulator_get(&msm_mipi_dsi1_device.dev,
+ "dsi_vdc");
+ if (IS_ERR(reg_l8)) {
+ pr_err("could not get 8921_l8, rc = %ld\n",
+ PTR_ERR(reg_l8));
+ return -ENODEV;
+ }
+ reg_l23 = regulator_get(&msm_mipi_dsi1_device.dev,
+ "dsi_vddio");
+ if (IS_ERR(reg_l23)) {
+ pr_err("could not get 8921_l23, rc = %ld\n",
+ PTR_ERR(reg_l23));
+ return -ENODEV;
+ }
+ reg_l2 = regulator_get(&msm_mipi_dsi1_device.dev,
+ "dsi_vdda");
+ if (IS_ERR(reg_l2)) {
+ pr_err("could not get 8921_l2, rc = %ld\n",
+ PTR_ERR(reg_l2));
+ return -ENODEV;
+ }
+ rc = regulator_set_voltage(reg_l8, 2800000, 3000000);
+ if (rc) {
+ pr_err("set_voltage l8 failed, rc=%d\n", rc);
+ return -EINVAL;
+ }
+ rc = regulator_set_voltage(reg_l23, 1800000, 1800000);
+ if (rc) {
+ pr_err("set_voltage l23 failed, rc=%d\n", rc);
+ return -EINVAL;
+ }
+ rc = regulator_set_voltage(reg_l2, 1200000, 1200000);
+ if (rc) {
+ pr_err("set_voltage l2 failed, rc=%d\n", rc);
+ return -EINVAL;
+ }
+ gpio43 = PM8921_GPIO_PM_TO_SYS(43);
+ rc = gpio_request(gpio43, "disp_rst_n");
+ if (rc) {
+ pr_err("request gpio 43 failed, rc=%d\n", rc);
+ return -ENODEV;
+ }
+ dsi_power_on = true;
+ }
+ if (on) {
+ rc = regulator_set_optimum_mode(reg_l8, 100000);
+ if (rc < 0) {
+ pr_err("set_optimum_mode l8 failed, rc=%d\n", rc);
+ return -EINVAL;
+ }
+ rc = regulator_set_optimum_mode(reg_l23, 100000);
+ if (rc < 0) {
+ pr_err("set_optimum_mode l23 failed, rc=%d\n", rc);
+ return -EINVAL;
+ }
+ rc = regulator_set_optimum_mode(reg_l2, 100000);
+ if (rc < 0) {
+ pr_err("set_optimum_mode l2 failed, rc=%d\n", rc);
+ return -EINVAL;
+ }
+ rc = regulator_enable(reg_l8);
+ if (rc) {
+ pr_err("enable l8 failed, rc=%d\n", rc);
+ return -ENODEV;
+ }
+ rc = regulator_enable(reg_l23);
+ if (rc) {
+ pr_err("enable l8 failed, rc=%d\n", rc);
+ return -ENODEV;
+ }
+ rc = regulator_enable(reg_l2);
+ if (rc) {
+ pr_err("enable l2 failed, rc=%d\n", rc);
+ return -ENODEV;
+ }
+ gpio_set_value_cansleep(gpio43, 1);
+ } else {
+ rc = regulator_disable(reg_l2);
+ if (rc) {
+ pr_err("disable reg_l2 failed, rc=%d\n", rc);
+ return -ENODEV;
+ }
+ rc = regulator_disable(reg_l8);
+ if (rc) {
+ pr_err("disable reg_l8 failed, rc=%d\n", rc);
+ return -ENODEV;
+ }
+ rc = regulator_disable(reg_l23);
+ if (rc) {
+ pr_err("disable reg_l23 failed, rc=%d\n", rc);
+ return -ENODEV;
+ }
+ rc = regulator_set_optimum_mode(reg_l8, 100);
+ if (rc < 0) {
+ pr_err("set_optimum_mode l8 failed, rc=%d\n", rc);
+ return -EINVAL;
+ }
+ rc = regulator_set_optimum_mode(reg_l23, 100);
+ if (rc < 0) {
+ pr_err("set_optimum_mode l23 failed, rc=%d\n", rc);
+ return -EINVAL;
+ }
+ rc = regulator_set_optimum_mode(reg_l2, 100);
+ if (rc < 0) {
+ pr_err("set_optimum_mode l2 failed, rc=%d\n", rc);
+ return -EINVAL;
+ }
+ gpio_set_value_cansleep(gpio43, 0);
+ }
+ return 0;
+}
+
+static int mipi_dsi_panel_power(int on)
+{
+ int ret;
+
+ pr_info("%s: on=%d\n", __func__, on);
+
+ if (machine_is_msm8960_liquid())
+ ret = mipi_dsi_liquid_panel_power(on);
+ else
+ ret = mipi_dsi_cdp_panel_power(on);
+
+ return ret;
+}
+
+static struct mipi_dsi_platform_data mipi_dsi_pdata = {
+ .vsync_gpio = MDP_VSYNC_GPIO,
+ .dsi_power_save = mipi_dsi_panel_power,
+};
+
+#ifdef CONFIG_MSM_BUS_SCALING
+
+static struct msm_bus_vectors mdp_init_vectors[] = {
+ {
+ .src = MSM_BUS_MASTER_MDP_PORT0,
+ .dst = MSM_BUS_SLAVE_EBI_CH0,
+ .ab = 0,
+ .ib = 0,
+ },
+};
+
+#ifdef CONFIG_FB_MSM_HDMI_AS_PRIMARY
+static struct msm_bus_vectors hdmi_as_primary_vectors[] = {
+ /* If HDMI is used as primary */
+ {
+ .src = MSM_BUS_MASTER_MDP_PORT0,
+ .dst = MSM_BUS_SLAVE_EBI_CH0,
+ .ab = 2000000000,
+ .ib = 2000000000,
+ },
+};
+static struct msm_bus_paths mdp_bus_scale_usecases[] = {
+ {
+ ARRAY_SIZE(mdp_init_vectors),
+ mdp_init_vectors,
+ },
+ {
+ ARRAY_SIZE(hdmi_as_primary_vectors),
+ hdmi_as_primary_vectors,
+ },
+ {
+ ARRAY_SIZE(hdmi_as_primary_vectors),
+ hdmi_as_primary_vectors,
+ },
+ {
+ ARRAY_SIZE(hdmi_as_primary_vectors),
+ hdmi_as_primary_vectors,
+ },
+ {
+ ARRAY_SIZE(hdmi_as_primary_vectors),
+ hdmi_as_primary_vectors,
+ },
+ {
+ ARRAY_SIZE(hdmi_as_primary_vectors),
+ hdmi_as_primary_vectors,
+ },
+};
+#else
+static struct msm_bus_vectors mdp_ui_vectors[] = {
+ {
+ .src = MSM_BUS_MASTER_MDP_PORT0,
+ .dst = MSM_BUS_SLAVE_EBI_CH0,
+ .ab = 216000000 * 2,
+ .ib = 270000000 * 2,
+ },
+};
+
+static struct msm_bus_vectors mdp_vga_vectors[] = {
+ /* VGA and less video */
+ {
+ .src = MSM_BUS_MASTER_MDP_PORT0,
+ .dst = MSM_BUS_SLAVE_EBI_CH0,
+ .ab = 216000000 * 2,
+ .ib = 270000000 * 2,
+ },
+};
+
+static struct msm_bus_vectors mdp_720p_vectors[] = {
+ /* 720p and less video */
+ {
+ .src = MSM_BUS_MASTER_MDP_PORT0,
+ .dst = MSM_BUS_SLAVE_EBI_CH0,
+ .ab = 230400000 * 2,
+ .ib = 288000000 * 2,
+ },
+};
+
+static struct msm_bus_vectors mdp_1080p_vectors[] = {
+ /* 1080p and less video */
+ {
+ .src = MSM_BUS_MASTER_MDP_PORT0,
+ .dst = MSM_BUS_SLAVE_EBI_CH0,
+ .ab = 334080000 * 2,
+ .ib = 417600000 * 2,
+ },
+};
+
+static struct msm_bus_paths mdp_bus_scale_usecases[] = {
+ {
+ ARRAY_SIZE(mdp_init_vectors),
+ mdp_init_vectors,
+ },
+ {
+ ARRAY_SIZE(mdp_ui_vectors),
+ mdp_ui_vectors,
+ },
+ {
+ ARRAY_SIZE(mdp_ui_vectors),
+ mdp_ui_vectors,
+ },
+ {
+ ARRAY_SIZE(mdp_vga_vectors),
+ mdp_vga_vectors,
+ },
+ {
+ ARRAY_SIZE(mdp_720p_vectors),
+ mdp_720p_vectors,
+ },
+ {
+ ARRAY_SIZE(mdp_1080p_vectors),
+ mdp_1080p_vectors,
+ },
+};
+#endif
+
+static struct msm_bus_scale_pdata mdp_bus_scale_pdata = {
+ mdp_bus_scale_usecases,
+ ARRAY_SIZE(mdp_bus_scale_usecases),
+ .name = "mdp",
+};
+
+#endif
+
+#ifdef CONFIG_FB_MSM_HDMI_AS_PRIMARY
+static int mdp_core_clk_rate_table[] = {
+ 200000000,
+ 200000000,
+ 200000000,
+ 200000000,
+};
+#else
+static int mdp_core_clk_rate_table[] = {
+ 85330000,
+ 85330000,
+ 160000000,
+ 200000000,
+};
+#endif
+
+static struct msm_panel_common_pdata mdp_pdata = {
+ .gpio = MDP_VSYNC_GPIO,
+#ifdef CONFIG_FB_MSM_HDMI_AS_PRIMARY
+ .mdp_core_clk_rate = 200000000,
+#else
+ .mdp_core_clk_rate = 85330000,
+#endif
+ .mdp_core_clk_table = mdp_core_clk_rate_table,
+ .num_mdp_clk = ARRAY_SIZE(mdp_core_clk_rate_table),
+#ifdef CONFIG_MSM_BUS_SCALING
+ .mdp_bus_scale_table = &mdp_bus_scale_pdata,
+#endif
+ .mdp_rev = MDP_REV_42,
+ .writeback_offset = writeback_offset,
+};
+
+static struct platform_device mipi_dsi_renesas_panel_device = {
+ .name = "mipi_renesas",
+ .id = 0,
+};
+
+static struct platform_device mipi_dsi_simulator_panel_device = {
+ .name = "mipi_simulator",
+ .id = 0,
+};
+
+#define LPM_CHANNEL0 0
+static int toshiba_gpio[] = {LPM_CHANNEL0};
+
+static struct mipi_dsi_panel_platform_data toshiba_pdata = {
+ .gpio = toshiba_gpio,
+};
+
+static struct platform_device mipi_dsi_toshiba_panel_device = {
+ .name = "mipi_toshiba",
+ .id = 0,
+ .dev = {
+ .platform_data = &toshiba_pdata,
+ }
+};
+
+#define FPGA_3D_GPIO_CONFIG_ADDR 0xB5
+static int dsi2lvds_gpio[2] = {
+ 0,/* Backlight PWM-ID=0 for PMIC-GPIO#24 */
+ 0x1F08 /* DSI2LVDS Bridge GPIO Output, mask=0x1f, out=0x08 */
+ };
+
+static struct msm_panel_common_pdata mipi_dsi2lvds_pdata = {
+ .gpio_num = dsi2lvds_gpio,
+};
+
+static struct mipi_dsi_phy_ctrl dsi_novatek_cmd_mode_phy_db = {
+
+/* DSI_BIT_CLK at 500MHz, 2 lane, RGB888 */
+ {0x0F, 0x0a, 0x04, 0x00, 0x20}, /* regulator */
+ /* timing */
+ {0xab, 0x8a, 0x18, 0x00, 0x92, 0x97, 0x1b, 0x8c,
+ 0x0c, 0x03, 0x04, 0xa0},
+ {0x5f, 0x00, 0x00, 0x10}, /* phy ctrl */
+ {0xff, 0x00, 0x06, 0x00}, /* strength */
+ /* pll control */
+ {0x40, 0xf9, 0x30, 0xda, 0x00, 0x40, 0x03, 0x62,
+ 0x40, 0x07, 0x03,
+ 0x00, 0x1a, 0x00, 0x00, 0x02, 0x00, 0x20, 0x00, 0x01},
+};
+
+static struct mipi_dsi_panel_platform_data novatek_pdata = {
+ .fpga_3d_config_addr = FPGA_3D_GPIO_CONFIG_ADDR,
+ .fpga_ctrl_mode = FPGA_SPI_INTF,
+ .phy_ctrl_settings = &dsi_novatek_cmd_mode_phy_db,
+};
+
+static struct platform_device mipi_dsi_novatek_panel_device = {
+ .name = "mipi_novatek",
+ .id = 0,
+ .dev = {
+ .platform_data = &novatek_pdata,
+ }
+};
+
+static struct platform_device mipi_dsi2lvds_bridge_device = {
+ .name = "mipi_tc358764",
+ .id = 0,
+ .dev.platform_data = &mipi_dsi2lvds_pdata,
+};
+
+#ifdef CONFIG_FB_MSM_HDMI_MSM_PANEL
+static struct resource hdmi_msm_resources[] = {
+ {
+ .name = "hdmi_msm_qfprom_addr",
+ .start = 0x00700000,
+ .end = 0x007060FF,
+ .flags = IORESOURCE_MEM,
+ },
+ {
+ .name = "hdmi_msm_hdmi_addr",
+ .start = 0x04A00000,
+ .end = 0x04A00FFF,
+ .flags = IORESOURCE_MEM,
+ },
+ {
+ .name = "hdmi_msm_irq",
+ .start = HDMI_IRQ,
+ .end = HDMI_IRQ,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+static int hdmi_enable_5v(int on);
+static int hdmi_core_power(int on, int show);
+static int hdmi_cec_power(int on);
+
+static struct msm_hdmi_platform_data hdmi_msm_data = {
+ .irq = HDMI_IRQ,
+ .enable_5v = hdmi_enable_5v,
+ .core_power = hdmi_core_power,
+ .cec_power = hdmi_cec_power,
+};
+
+static struct platform_device hdmi_msm_device = {
+ .name = "hdmi_msm",
+ .id = 0,
+ .num_resources = ARRAY_SIZE(hdmi_msm_resources),
+ .resource = hdmi_msm_resources,
+ .dev.platform_data = &hdmi_msm_data,
+};
+#endif /* CONFIG_FB_MSM_HDMI_MSM_PANEL */
+
+#ifdef CONFIG_FB_MSM_WRITEBACK_MSM_PANEL
+static struct platform_device wfd_panel_device = {
+ .name = "wfd_panel",
+ .id = 0,
+ .dev.platform_data = NULL,
+};
+
+static struct platform_device wfd_device = {
+ .name = "msm_wfd",
+ .id = -1,
+};
+#endif
+
+#ifdef CONFIG_MSM_BUS_SCALING
+static struct msm_bus_vectors dtv_bus_init_vectors[] = {
+ {
+ .src = MSM_BUS_MASTER_MDP_PORT0,
+ .dst = MSM_BUS_SLAVE_EBI_CH0,
+ .ab = 0,
+ .ib = 0,
+ },
+};
+
+#ifdef CONFIG_FB_MSM_HDMI_AS_PRIMARY
+static struct msm_bus_vectors dtv_bus_def_vectors[] = {
+ {
+ .src = MSM_BUS_MASTER_MDP_PORT0,
+ .dst = MSM_BUS_SLAVE_EBI_CH0,
+ .ab = 2000000000,
+ .ib = 2000000000,
+ },
+};
+#else
+static struct msm_bus_vectors dtv_bus_def_vectors[] = {
+ {
+ .src = MSM_BUS_MASTER_MDP_PORT0,
+ .dst = MSM_BUS_SLAVE_EBI_CH0,
+ .ab = 566092800 * 2,
+ .ib = 707616000 * 2,
+ },
+};
+#endif
+
+static struct msm_bus_paths dtv_bus_scale_usecases[] = {
+ {
+ ARRAY_SIZE(dtv_bus_init_vectors),
+ dtv_bus_init_vectors,
+ },
+ {
+ ARRAY_SIZE(dtv_bus_def_vectors),
+ dtv_bus_def_vectors,
+ },
+};
+static struct msm_bus_scale_pdata dtv_bus_scale_pdata = {
+ dtv_bus_scale_usecases,
+ ARRAY_SIZE(dtv_bus_scale_usecases),
+ .name = "dtv",
+};
+
+static struct lcdc_platform_data dtv_pdata = {
+ .bus_scale_table = &dtv_bus_scale_pdata,
+};
+#endif
+
+#ifdef CONFIG_FB_MSM_HDMI_MSM_PANEL
+static int hdmi_enable_5v(int on)
+{
+ /* TBD: PM8921 regulator instead of 8901 */
+ static struct regulator *reg_8921_hdmi_mvs; /* HDMI_5V */
+ static int prev_on;
+ int rc;
+
+ if (on == prev_on)
+ return 0;
+
+ if (!reg_8921_hdmi_mvs)
+ reg_8921_hdmi_mvs = regulator_get(&hdmi_msm_device.dev,
+ "hdmi_mvs");
+
+ if (on) {
+ rc = regulator_enable(reg_8921_hdmi_mvs);
+ if (rc) {
+ pr_err("'%s' regulator enable failed, rc=%d\n",
+ "8921_hdmi_mvs", rc);
+ return rc;
+ }
+ pr_debug("%s(on): success\n", __func__);
+ } else {
+ rc = regulator_disable(reg_8921_hdmi_mvs);
+ if (rc)
+ pr_warning("'%s' regulator disable failed, rc=%d\n",
+ "8921_hdmi_mvs", rc);
+ pr_debug("%s(off): success\n", __func__);
+ }
+
+ prev_on = on;
+
+ return 0;
+}
+
+static int hdmi_core_power(int on, int show)
+{
+ static struct regulator *reg_8921_l23, *reg_8921_s4;
+ static int prev_on;
+ int rc;
+
+ if (on == prev_on)
+ return 0;
+
+ /* TBD: PM8921 regulator instead of 8901 */
+ if (!reg_8921_l23) {
+ reg_8921_l23 = regulator_get(&hdmi_msm_device.dev, "hdmi_avdd");
+ if (IS_ERR(reg_8921_l23)) {
+ pr_err("could not get reg_8921_l23, rc = %ld\n",
+ PTR_ERR(reg_8921_l23));
+ return -ENODEV;
+ }
+ rc = regulator_set_voltage(reg_8921_l23, 1800000, 1800000);
+ if (rc) {
+ pr_err("set_voltage failed for 8921_l23, rc=%d\n", rc);
+ return -EINVAL;
+ }
+ }
+ if (!reg_8921_s4) {
+ reg_8921_s4 = regulator_get(&hdmi_msm_device.dev, "hdmi_vcc");
+ if (IS_ERR(reg_8921_s4)) {
+ pr_err("could not get reg_8921_s4, rc = %ld\n",
+ PTR_ERR(reg_8921_s4));
+ return -ENODEV;
+ }
+ rc = regulator_set_voltage(reg_8921_s4, 1800000, 1800000);
+ if (rc) {
+ pr_err("set_voltage failed for 8921_s4, rc=%d\n", rc);
+ return -EINVAL;
+ }
+ }
+
+ if (on) {
+ rc = regulator_set_optimum_mode(reg_8921_l23, 100000);
+ if (rc < 0) {
+ pr_err("set_optimum_mode l23 failed, rc=%d\n", rc);
+ return -EINVAL;
+ }
+ rc = regulator_enable(reg_8921_l23);
+ if (rc) {
+ pr_err("'%s' regulator enable failed, rc=%d\n",
+ "hdmi_avdd", rc);
+ return rc;
+ }
+ rc = regulator_enable(reg_8921_s4);
+ if (rc) {
+ pr_err("'%s' regulator enable failed, rc=%d\n",
+ "hdmi_vcc", rc);
+ return rc;
+ }
+ rc = gpio_request(100, "HDMI_DDC_CLK");
+ if (rc) {
+ pr_err("'%s'(%d) gpio_request failed, rc=%d\n",
+ "HDMI_DDC_CLK", 100, rc);
+ goto error1;
+ }
+ rc = gpio_request(101, "HDMI_DDC_DATA");
+ if (rc) {
+ pr_err("'%s'(%d) gpio_request failed, rc=%d\n",
+ "HDMI_DDC_DATA", 101, rc);
+ goto error2;
+ }
+ rc = gpio_request(102, "HDMI_HPD");
+ if (rc) {
+ pr_err("'%s'(%d) gpio_request failed, rc=%d\n",
+ "HDMI_HPD", 102, rc);
+ goto error3;
+ }
+ pr_debug("%s(on): success\n", __func__);
+ } else {
+ gpio_free(100);
+ gpio_free(101);
+ gpio_free(102);
+
+ rc = regulator_disable(reg_8921_l23);
+ if (rc) {
+ pr_err("disable reg_8921_l23 failed, rc=%d\n", rc);
+ return -ENODEV;
+ }
+ rc = regulator_disable(reg_8921_s4);
+ if (rc) {
+ pr_err("disable reg_8921_s4 failed, rc=%d\n", rc);
+ return -ENODEV;
+ }
+ rc = regulator_set_optimum_mode(reg_8921_l23, 100);
+ if (rc < 0) {
+ pr_err("set_optimum_mode l23 failed, rc=%d\n", rc);
+ return -EINVAL;
+ }
+ pr_debug("%s(off): success\n", __func__);
+ }
+
+ prev_on = on;
+
+ return 0;
+
+error3:
+ gpio_free(101);
+error2:
+ gpio_free(100);
+error1:
+ regulator_disable(reg_8921_l23);
+ regulator_disable(reg_8921_s4);
+ return rc;
+}
+
+static int hdmi_cec_power(int on)
+{
+ static int prev_on;
+ int rc;
+
+ if (on == prev_on)
+ return 0;
+
+ if (on) {
+ rc = gpio_request(99, "HDMI_CEC_VAR");
+ if (rc) {
+ pr_err("'%s'(%d) gpio_request failed, rc=%d\n",
+ "HDMI_CEC_VAR", 99, rc);
+ goto error;
+ }
+ pr_debug("%s(on): success\n", __func__);
+ } else {
+ gpio_free(99);
+ pr_debug("%s(off): success\n", __func__);
+ }
+
+ prev_on = on;
+
+ return 0;
+error:
+ return rc;
+}
+#endif /* CONFIG_FB_MSM_HDMI_MSM_PANEL */
+
+void __init msm8960_init_fb(void)
+{
+ platform_device_register(&msm_fb_device);
+
+#ifdef CONFIG_FB_MSM_WRITEBACK_MSM_PANEL
+ platform_device_register(&wfd_panel_device);
+ platform_device_register(&wfd_device);
+#endif
+
+ if (machine_is_msm8960_sim())
+ platform_device_register(&mipi_dsi_simulator_panel_device);
+
+ if (machine_is_msm8960_rumi3())
+ platform_device_register(&mipi_dsi_renesas_panel_device);
+
+ if (!machine_is_msm8960_sim() && !machine_is_msm8960_rumi3()) {
+ platform_device_register(&mipi_dsi_novatek_panel_device);
+
+#ifdef CONFIG_FB_MSM_HDMI_MSM_PANEL
+ platform_device_register(&hdmi_msm_device);
+#endif
+ }
+
+ if (machine_is_msm8960_liquid())
+ platform_device_register(&mipi_dsi2lvds_bridge_device);
+ else
+ platform_device_register(&mipi_dsi_toshiba_panel_device);
+
+ if (machine_is_msm8x60_rumi3()) {
+ msm_fb_register_device("mdp", NULL);
+ mipi_dsi_pdata.target_type = 1;
+ } else
+ msm_fb_register_device("mdp", &mdp_pdata);
+ msm_fb_register_device("mipi_dsi", &mipi_dsi_pdata);
+#ifdef CONFIG_MSM_BUS_SCALING
+ msm_fb_register_device("dtv", &dtv_pdata);
+#endif
+}
+
+void __init msm8960_allocate_fb_region(void)
+{
+ void *addr;
+ unsigned long size;
+
+ size = MSM_FB_SIZE;
+ addr = alloc_bootmem_align(size, 0x1000);
+ msm_fb_resources[0].start = __pa(addr);
+ msm_fb_resources[0].end = msm_fb_resources[0].start + size - 1;
+ pr_info("allocating %lu bytes at %p (%lx physical) for fb\n",
+ size, addr, __pa(addr));
+}
diff --git a/arch/arm/mach-msm/board-8960-gpiomux.c b/arch/arm/mach-msm/board-8960-gpiomux.c
new file mode 100644
index 0000000..9be65bb
--- /dev/null
+++ b/arch/arm/mach-msm/board-8960-gpiomux.c
@@ -0,0 +1,662 @@
+/* Copyright (c) 2011, Code Aurora Forum. 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 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#include <asm/mach-types.h>
+#include <mach/gpio.h>
+#include <mach/gpiomux.h>
+#include <mach/socinfo.h>
+#include "devices.h"
+#include "board-8960.h"
+
+/* The SPI configurations apply to GSBI 1*/
+static struct gpiomux_setting spi_active = {
+ .func = GPIOMUX_FUNC_1,
+ .drv = GPIOMUX_DRV_12MA,
+ .pull = GPIOMUX_PULL_NONE,
+};
+
+static struct gpiomux_setting spi_suspended_config = {
+ .func = GPIOMUX_FUNC_GPIO,
+ .drv = GPIOMUX_DRV_2MA,
+ .pull = GPIOMUX_PULL_DOWN,
+};
+
+static struct gpiomux_setting spi_active_config2 = {
+ .func = GPIOMUX_FUNC_2,
+ .drv = GPIOMUX_DRV_8MA,
+ .pull = GPIOMUX_PULL_NONE,
+};
+
+static struct gpiomux_setting spi_suspended_config2 = {
+ .func = GPIOMUX_FUNC_GPIO,
+ .drv = GPIOMUX_DRV_2MA,
+ .pull = GPIOMUX_PULL_UP,
+};
+
+static struct gpiomux_setting gsbi3_suspended_cfg = {
+ .func = GPIOMUX_FUNC_1,
+ .drv = GPIOMUX_DRV_2MA,
+ .pull = GPIOMUX_PULL_KEEPER,
+};
+
+static struct gpiomux_setting gsbi3_active_cfg = {
+ .func = GPIOMUX_FUNC_1,
+ .drv = GPIOMUX_DRV_8MA,
+ .pull = GPIOMUX_PULL_NONE,
+};
+
+static struct gpiomux_setting gsbi5 = {
+ .func = GPIOMUX_FUNC_1,
+ .drv = GPIOMUX_DRV_8MA,
+ .pull = GPIOMUX_PULL_NONE,
+};
+
+static struct gpiomux_setting gsbi10 = {
+ .func = GPIOMUX_FUNC_2,
+ .drv = GPIOMUX_DRV_8MA,
+ .pull = GPIOMUX_PULL_NONE,
+};
+
+static struct gpiomux_setting gsbi12 = {
+ .func = GPIOMUX_FUNC_1,
+ .drv = GPIOMUX_DRV_8MA,
+ .pull = GPIOMUX_PULL_NONE,
+};
+
+static struct gpiomux_setting cdc_mclk = {
+ .func = GPIOMUX_FUNC_1,
+ .drv = GPIOMUX_DRV_8MA,
+ .pull = GPIOMUX_PULL_NONE,
+};
+
+static struct gpiomux_setting audio_auxpcm[] = {
+ /* Suspended state */
+ {
+ .func = GPIOMUX_FUNC_GPIO,
+ .drv = GPIOMUX_DRV_2MA,
+ .pull = GPIOMUX_PULL_NONE,
+ },
+ /* Active state */
+ {
+ .func = GPIOMUX_FUNC_1,
+ .drv = GPIOMUX_DRV_2MA,
+ .pull = GPIOMUX_PULL_NONE,
+ },
+};
+
+#if defined(CONFIG_KS8851) || defined(CONFIG_KS8851_MODULE)
+static struct gpiomux_setting gpio_eth_config = {
+ .pull = GPIOMUX_PULL_NONE,
+ .drv = GPIOMUX_DRV_8MA,
+ .func = GPIOMUX_FUNC_GPIO,
+};
+#endif
+
+static struct gpiomux_setting slimbus = {
+ .func = GPIOMUX_FUNC_1,
+ .drv = GPIOMUX_DRV_8MA,
+ .pull = GPIOMUX_PULL_KEEPER,
+};
+
+static struct gpiomux_setting wcnss_5wire_suspend_cfg = {
+ .func = GPIOMUX_FUNC_GPIO,
+ .drv = GPIOMUX_DRV_2MA,
+ .pull = GPIOMUX_PULL_UP,
+};
+
+static struct gpiomux_setting wcnss_5wire_active_cfg = {
+ .func = GPIOMUX_FUNC_1,
+ .drv = GPIOMUX_DRV_6MA,
+ .pull = GPIOMUX_PULL_DOWN,
+};
+
+static struct gpiomux_setting cyts_resout_sus_cfg = {
+ .func = GPIOMUX_FUNC_GPIO,
+ .drv = GPIOMUX_DRV_6MA,
+ .pull = GPIOMUX_PULL_UP,
+};
+
+static struct gpiomux_setting cyts_resout_act_cfg = {
+ .func = GPIOMUX_FUNC_GPIO,
+ .drv = GPIOMUX_DRV_6MA,
+ .pull = GPIOMUX_PULL_UP,
+};
+
+static struct gpiomux_setting cyts_sleep_sus_cfg = {
+ .func = GPIOMUX_FUNC_GPIO,
+ .drv = GPIOMUX_DRV_6MA,
+ .pull = GPIOMUX_PULL_DOWN,
+};
+
+static struct gpiomux_setting cyts_sleep_act_cfg = {
+ .func = GPIOMUX_FUNC_GPIO,
+ .drv = GPIOMUX_DRV_6MA,
+ .pull = GPIOMUX_PULL_DOWN,
+};
+
+static struct gpiomux_setting cyts_int_act_cfg = {
+ .func = GPIOMUX_FUNC_GPIO,
+ .drv = GPIOMUX_DRV_8MA,
+ .pull = GPIOMUX_PULL_UP,
+};
+
+static struct gpiomux_setting cyts_int_sus_cfg = {
+ .func = GPIOMUX_FUNC_GPIO,
+ .drv = GPIOMUX_DRV_2MA,
+ .pull = GPIOMUX_PULL_DOWN,
+};
+
+#ifdef CONFIG_USB_EHCI_MSM_HSIC
+static struct gpiomux_setting hsic_act_cfg = {
+ .func = GPIOMUX_FUNC_1,
+ .drv = GPIOMUX_DRV_12MA,
+ .pull = GPIOMUX_PULL_NONE,
+};
+
+static struct gpiomux_setting hsic_sus_cfg = {
+ .func = GPIOMUX_FUNC_GPIO,
+ .drv = GPIOMUX_DRV_2MA,
+ .pull = GPIOMUX_PULL_DOWN,
+ .dir = GPIOMUX_OUT_LOW,
+};
+
+static struct gpiomux_setting hsic_hub_act_cfg = {
+ .func = GPIOMUX_FUNC_GPIO,
+ .drv = GPIOMUX_DRV_2MA,
+ .pull = GPIOMUX_PULL_NONE,
+};
+#endif
+
+static struct gpiomux_setting hap_lvl_shft_suspended_config = {
+ .func = GPIOMUX_FUNC_GPIO,
+ .drv = GPIOMUX_DRV_2MA,
+ .pull = GPIOMUX_PULL_DOWN,
+};
+
+static struct gpiomux_setting hap_lvl_shft_active_config = {
+ .func = GPIOMUX_FUNC_GPIO,
+ .drv = GPIOMUX_DRV_8MA,
+ .pull = GPIOMUX_PULL_UP,
+};
+
+static struct gpiomux_setting ap2mdm_cfg = {
+ .func = GPIOMUX_FUNC_GPIO,
+ .drv = GPIOMUX_DRV_8MA,
+ .pull = GPIOMUX_PULL_DOWN,
+};
+
+static struct gpiomux_setting mdm2ap_status_cfg = {
+ .func = GPIOMUX_FUNC_GPIO,
+ .drv = GPIOMUX_DRV_8MA,
+ .pull = GPIOMUX_PULL_NONE,
+};
+
+static struct gpiomux_setting mdm2ap_errfatal_cfg = {
+ .func = GPIOMUX_FUNC_GPIO,
+ .drv = GPIOMUX_DRV_16MA,
+ .pull = GPIOMUX_PULL_DOWN,
+};
+
+static struct gpiomux_setting ap2mdm_kpdpwr_n_cfg = {
+ .func = GPIOMUX_FUNC_GPIO,
+ .drv = GPIOMUX_DRV_8MA,
+ .pull = GPIOMUX_PULL_NONE,
+};
+
+static struct gpiomux_setting mdp_vsync_suspend_cfg = {
+ .func = GPIOMUX_FUNC_GPIO,
+ .drv = GPIOMUX_DRV_2MA,
+ .pull = GPIOMUX_PULL_DOWN,
+};
+
+static struct gpiomux_setting mdp_vsync_active_cfg = {
+ .func = GPIOMUX_FUNC_1,
+ .drv = GPIOMUX_DRV_2MA,
+ .pull = GPIOMUX_PULL_DOWN,
+};
+
+#ifdef CONFIG_FB_MSM_HDMI_MSM_PANEL
+static struct gpiomux_setting hdmi_suspend_cfg = {
+ .func = GPIOMUX_FUNC_GPIO,
+ .drv = GPIOMUX_DRV_2MA,
+ .pull = GPIOMUX_PULL_DOWN,
+};
+
+static struct gpiomux_setting hdmi_active_1_cfg = {
+ .func = GPIOMUX_FUNC_1,
+ .drv = GPIOMUX_DRV_2MA,
+ .pull = GPIOMUX_PULL_UP,
+};
+
+static struct gpiomux_setting hdmi_active_2_cfg = {
+ .func = GPIOMUX_FUNC_1,
+ .drv = GPIOMUX_DRV_2MA,
+ .pull = GPIOMUX_PULL_DOWN,
+};
+#endif
+
+#if defined(CONFIG_KS8851) || defined(CONFIG_KS8851_MODULE)
+static struct msm_gpiomux_config msm8960_ethernet_configs[] = {
+ {
+ .gpio = 90,
+ .settings = {
+ [GPIOMUX_SUSPENDED] = &gpio_eth_config,
+ }
+ },
+ {
+ .gpio = 89,
+ .settings = {
+ [GPIOMUX_SUSPENDED] = &gpio_eth_config,
+ }
+ },
+};
+#endif
+
+static struct msm_gpiomux_config msm8960_gsbi_configs[] __initdata = {
+ {
+ .gpio = 6, /* GSBI1 QUP SPI_DATA_MOSI */
+ .settings = {
+ [GPIOMUX_SUSPENDED] = &spi_suspended_config,
+ [GPIOMUX_ACTIVE] = &spi_active,
+ },
+ },
+ {
+ .gpio = 7, /* GSBI1 QUP SPI_DATA_MISO */
+ .settings = {
+ [GPIOMUX_SUSPENDED] = &spi_suspended_config,
+ [GPIOMUX_ACTIVE] = &spi_active,
+ },
+ },
+ {
+ .gpio = 8, /* GSBI1 QUP SPI_CS_N */
+ .settings = {
+ [GPIOMUX_SUSPENDED] = &spi_suspended_config,
+ [GPIOMUX_ACTIVE] = &spi_active,
+ },
+ },
+ {
+ .gpio = 9, /* GSBI1 QUP SPI_CLK */
+ .settings = {
+ [GPIOMUX_SUSPENDED] = &spi_suspended_config,
+ [GPIOMUX_ACTIVE] = &spi_active,
+ },
+ },
+ {
+ .gpio = 14, /* GSBI1 SPI_CS_1 */
+ .settings = {
+ [GPIOMUX_SUSPENDED] = &spi_suspended_config2,
+ [GPIOMUX_ACTIVE] = &spi_active_config2,
+ },
+ },
+ {
+ .gpio = 16, /* GSBI3 I2C QUP SDA */
+ .settings = {
+ [GPIOMUX_SUSPENDED] = &gsbi3_suspended_cfg,
+ [GPIOMUX_ACTIVE] = &gsbi3_active_cfg,
+ },
+ },
+ {
+ .gpio = 17, /* GSBI3 I2C QUP SCL */
+ .settings = {
+ [GPIOMUX_SUSPENDED] = &gsbi3_suspended_cfg,
+ [GPIOMUX_ACTIVE] = &gsbi3_active_cfg,
+ },
+ },
+ {
+ .gpio = 22, /* GSBI5 UART2 */
+ .settings = {
+ [GPIOMUX_SUSPENDED] = &gsbi5,
+ },
+ },
+ {
+ .gpio = 23, /* GSBI5 UART2 */
+ .settings = {
+ [GPIOMUX_SUSPENDED] = &gsbi5,
+ },
+ },
+ {
+ .gpio = 24, /* GSBI5 UART2 */
+ .settings = {
+ [GPIOMUX_SUSPENDED] = &gsbi5,
+ },
+ },
+ {
+ .gpio = 25, /* GSBI5 UART2 */
+ .settings = {
+ [GPIOMUX_SUSPENDED] = &gsbi5,
+ },
+ },
+ {
+ .gpio = 44, /* GSBI12 I2C QUP SDA */
+ .settings = {
+ [GPIOMUX_SUSPENDED] = &gsbi12,
+ },
+ },
+ {
+ .gpio = 45, /* GSBI12 I2C QUP SCL */
+ .settings = {
+ [GPIOMUX_SUSPENDED] = &gsbi12,
+ },
+ },
+ {
+ .gpio = 73, /* GSBI10 I2C QUP SDA */
+ .settings = {
+ [GPIOMUX_SUSPENDED] = &gsbi10,
+ },
+ },
+ {
+ .gpio = 74, /* GSBI10 I2C QUP SCL */
+ .settings = {
+ [GPIOMUX_SUSPENDED] = &gsbi10,
+ },
+ },
+};
+
+static struct msm_gpiomux_config msm8960_slimbus_config[] __initdata = {
+ {
+ .gpio = 60, /* slimbus data */
+ .settings = {
+ [GPIOMUX_SUSPENDED] = &slimbus,
+ },
+ },
+ {
+ .gpio = 61, /* slimbus clk */
+ .settings = {
+ [GPIOMUX_SUSPENDED] = &slimbus,
+ },
+ },
+};
+
+static struct msm_gpiomux_config msm8960_audio_codec_configs[] __initdata = {
+ {
+ .gpio = 59,
+ .settings = {
+ [GPIOMUX_SUSPENDED] = &cdc_mclk,
+ },
+ },
+};
+
+static struct msm_gpiomux_config msm8960_audio_auxpcm_configs[] __initdata = {
+ {
+ .gpio = 63,
+ .settings = {
+ [GPIOMUX_SUSPENDED] = &audio_auxpcm[0],
+ [GPIOMUX_ACTIVE] = &audio_auxpcm[1],
+ },
+ },
+ {
+ .gpio = 64,
+ .settings = {
+ [GPIOMUX_SUSPENDED] = &audio_auxpcm[0],
+ [GPIOMUX_ACTIVE] = &audio_auxpcm[1],
+ },
+ },
+ {
+ .gpio = 65,
+ .settings = {
+ [GPIOMUX_SUSPENDED] = &audio_auxpcm[0],
+ [GPIOMUX_ACTIVE] = &audio_auxpcm[1],
+ },
+ },
+ {
+ .gpio = 66,
+ .settings = {
+ [GPIOMUX_SUSPENDED] = &audio_auxpcm[0],
+ [GPIOMUX_ACTIVE] = &audio_auxpcm[1],
+ },
+ },
+};
+
+static struct msm_gpiomux_config wcnss_5wire_interface[] = {
+ {
+ .gpio = 84,
+ .settings = {
+ [GPIOMUX_ACTIVE] = &wcnss_5wire_active_cfg,
+ [GPIOMUX_SUSPENDED] = &wcnss_5wire_suspend_cfg,
+ },
+ },
+ {
+ .gpio = 85,
+ .settings = {
+ [GPIOMUX_ACTIVE] = &wcnss_5wire_active_cfg,
+ [GPIOMUX_SUSPENDED] = &wcnss_5wire_suspend_cfg,
+ },
+ },
+ {
+ .gpio = 86,
+ .settings = {
+ [GPIOMUX_ACTIVE] = &wcnss_5wire_active_cfg,
+ [GPIOMUX_SUSPENDED] = &wcnss_5wire_suspend_cfg,
+ },
+ },
+ {
+ .gpio = 87,
+ .settings = {
+ [GPIOMUX_ACTIVE] = &wcnss_5wire_active_cfg,
+ [GPIOMUX_SUSPENDED] = &wcnss_5wire_suspend_cfg,
+ },
+ },
+ {
+ .gpio = 88,
+ .settings = {
+ [GPIOMUX_ACTIVE] = &wcnss_5wire_active_cfg,
+ [GPIOMUX_SUSPENDED] = &wcnss_5wire_suspend_cfg,
+ },
+ },
+};
+
+static struct msm_gpiomux_config msm8960_cyts_configs[] __initdata = {
+ { /* TS INTERRUPT */
+ .gpio = 11,
+ .settings = {
+ [GPIOMUX_ACTIVE] = &cyts_int_act_cfg,
+ [GPIOMUX_SUSPENDED] = &cyts_int_sus_cfg,
+ },
+ },
+ { /* TS SLEEP */
+ .gpio = 50,
+ .settings = {
+ [GPIOMUX_ACTIVE] = &cyts_sleep_act_cfg,
+ [GPIOMUX_SUSPENDED] = &cyts_sleep_sus_cfg,
+ },
+ },
+ { /* TS RESOUT */
+ .gpio = 52,
+ .settings = {
+ [GPIOMUX_ACTIVE] = &cyts_resout_act_cfg,
+ [GPIOMUX_SUSPENDED] = &cyts_resout_sus_cfg,
+ },
+ },
+};
+
+#ifdef CONFIG_USB_EHCI_MSM_HSIC
+static struct msm_gpiomux_config msm8960_hsic_configs[] = {
+ {
+ .gpio = 150, /*HSIC_STROBE */
+ .settings = {
+ [GPIOMUX_ACTIVE] = &hsic_act_cfg,
+ [GPIOMUX_SUSPENDED] = &hsic_sus_cfg,
+ },
+ },
+ {
+ .gpio = 151, /* HSIC_DATA */
+ .settings = {
+ [GPIOMUX_ACTIVE] = &hsic_act_cfg,
+ [GPIOMUX_SUSPENDED] = &hsic_sus_cfg,
+ },
+ },
+ {
+ .gpio = 91, /* HSIC_HUB_RESET */
+ .settings = {
+ [GPIOMUX_ACTIVE] = &hsic_hub_act_cfg,
+ [GPIOMUX_SUSPENDED] = &hsic_sus_cfg,
+ },
+ },
+};
+#endif
+
+static struct msm_gpiomux_config hap_lvl_shft_config[] __initdata = {
+ {
+ .gpio = 47,
+ .settings = {
+ [GPIOMUX_SUSPENDED] = &hap_lvl_shft_suspended_config,
+ [GPIOMUX_ACTIVE] = &hap_lvl_shft_active_config,
+ },
+ },
+};
+
+static struct msm_gpiomux_config mdm_configs[] __initdata = {
+ /* AP2MDM_STATUS */
+ {
+ .gpio = 94,
+ .settings = {
+ [GPIOMUX_SUSPENDED] = &ap2mdm_cfg,
+ }
+ },
+ /* MDM2AP_STATUS */
+ {
+ .gpio = 69,
+ .settings = {
+ [GPIOMUX_SUSPENDED] = &mdm2ap_status_cfg,
+ }
+ },
+ /* MDM2AP_ERRFATAL */
+ {
+ .gpio = 70,
+ .settings = {
+ [GPIOMUX_SUSPENDED] = &mdm2ap_errfatal_cfg,
+ }
+ },
+ /* AP2MDM_ERRFATAL */
+ {
+ .gpio = 95,
+ .settings = {
+ [GPIOMUX_SUSPENDED] = &ap2mdm_cfg,
+ }
+ },
+ /* AP2MDM_KPDPWR_N */
+ {
+ .gpio = 81,
+ .settings = {
+ [GPIOMUX_SUSPENDED] = &ap2mdm_kpdpwr_n_cfg,
+ }
+ },
+ /* AP2MDM_PMIC_RESET_N */
+ {
+ .gpio = 80,
+ .settings = {
+ [GPIOMUX_SUSPENDED] = &ap2mdm_kpdpwr_n_cfg,
+ }
+ }
+};
+
+static struct msm_gpiomux_config msm8960_mdp_vsync_configs[] __initdata = {
+ {
+ .gpio = 0,
+ .settings = {
+ [GPIOMUX_ACTIVE] = &mdp_vsync_active_cfg,
+ [GPIOMUX_SUSPENDED] = &mdp_vsync_suspend_cfg,
+ },
+ }
+};
+
+#ifdef CONFIG_FB_MSM_HDMI_MSM_PANEL
+static struct msm_gpiomux_config msm8960_hdmi_configs[] __initdata = {
+ {
+ .gpio = 99,
+ .settings = {
+ [GPIOMUX_ACTIVE] = &hdmi_active_1_cfg,
+ [GPIOMUX_SUSPENDED] = &hdmi_suspend_cfg,
+ },
+ },
+ {
+ .gpio = 100,
+ .settings = {
+ [GPIOMUX_ACTIVE] = &hdmi_active_1_cfg,
+ [GPIOMUX_SUSPENDED] = &hdmi_suspend_cfg,
+ },
+ },
+ {
+ .gpio = 101,
+ .settings = {
+ [GPIOMUX_ACTIVE] = &hdmi_active_1_cfg,
+ [GPIOMUX_SUSPENDED] = &hdmi_suspend_cfg,
+ },
+ },
+ {
+ .gpio = 102,
+ .settings = {
+ [GPIOMUX_ACTIVE] = &hdmi_active_2_cfg,
+ [GPIOMUX_SUSPENDED] = &hdmi_suspend_cfg,
+ },
+ },
+};
+#endif
+
+int __init msm8960_init_gpiomux(void)
+{
+ int rc = msm_gpiomux_init(NR_GPIO_IRQS);
+ if (rc) {
+ pr_err(KERN_ERR "msm_gpiomux_init failed %d\n", rc);
+ return rc;
+ }
+
+#if defined(CONFIG_KS8851) || defined(CONFIG_KS8851_MODULE)
+ msm_gpiomux_install(msm8960_ethernet_configs,
+ ARRAY_SIZE(msm8960_ethernet_configs));
+#endif
+
+ msm_gpiomux_install(msm8960_gsbi_configs,
+ ARRAY_SIZE(msm8960_gsbi_configs));
+
+ msm_gpiomux_install(msm8960_cyts_configs,
+ ARRAY_SIZE(msm8960_cyts_configs));
+
+ msm_gpiomux_install(msm8960_slimbus_config,
+ ARRAY_SIZE(msm8960_slimbus_config));
+
+ msm_gpiomux_install(msm8960_audio_codec_configs,
+ ARRAY_SIZE(msm8960_audio_codec_configs));
+
+ msm_gpiomux_install(msm8960_audio_auxpcm_configs,
+ ARRAY_SIZE(msm8960_audio_auxpcm_configs));
+
+ msm_gpiomux_install(wcnss_5wire_interface,
+ ARRAY_SIZE(wcnss_5wire_interface));
+
+ if (machine_is_msm8960_mtp() || machine_is_msm8960_fluid() ||
+ machine_is_msm8960_liquid() || machine_is_msm8960_cdp())
+ msm_gpiomux_install(hap_lvl_shft_config,
+ ARRAY_SIZE(hap_lvl_shft_config));
+
+ if (PLATFORM_IS_CHARM25())
+ msm_gpiomux_install(mdm_configs,
+ ARRAY_SIZE(mdm_configs));
+
+#ifdef CONFIG_USB_EHCI_MSM_HSIC
+ if ((SOCINFO_VERSION_MAJOR(socinfo_get_version()) != 1) &&
+ (PLATFORM_IS_CHARM25() || machine_is_msm8960_liquid()))
+ msm_gpiomux_install(msm8960_hsic_configs,
+ ARRAY_SIZE(msm8960_hsic_configs));
+#endif
+
+#ifdef CONFIG_FB_MSM_HDMI_MSM_PANEL
+ msm_gpiomux_install(msm8960_hdmi_configs,
+ ARRAY_SIZE(msm8960_hdmi_configs));
+#endif
+
+ msm_gpiomux_install(msm8960_mdp_vsync_configs,
+ ARRAY_SIZE(msm8960_mdp_vsync_configs));
+
+ return 0;
+}
diff --git a/arch/arm/mach-msm/board-8960-pmic.c b/arch/arm/mach-msm/board-8960-pmic.c
new file mode 100644
index 0000000..44f7be6
--- /dev/null
+++ b/arch/arm/mach-msm/board-8960-pmic.c
@@ -0,0 +1,542 @@
+/* Copyright (c) 2011, Code Aurora Forum. 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 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#include <linux/interrupt.h>
+#include <linux/mfd/pm8xxx/pm8921.h>
+#include <linux/mfd/pm8xxx/pm8xxx-adc.h>
+#include <linux/leds.h>
+#include <linux/leds-pm8xxx.h>
+#include <linux/msm_ssbi.h>
+#include <asm/mach-types.h>
+#include <mach/msm_bus_board.h>
+#include <mach/restart.h>
+#include "devices.h"
+#include "board-8960.h"
+
+struct pm8xxx_gpio_init {
+ unsigned gpio;
+ struct pm_gpio config;
+};
+
+struct pm8xxx_mpp_init {
+ unsigned mpp;
+ struct pm8xxx_mpp_config_data config;
+};
+
+#define PM8XXX_GPIO_INIT(_gpio, _dir, _buf, _val, _pull, _vin, _out_strength, \
+ _func, _inv, _disable) \
+{ \
+ .gpio = PM8921_GPIO_PM_TO_SYS(_gpio), \
+ .config = { \
+ .direction = _dir, \
+ .output_buffer = _buf, \
+ .output_value = _val, \
+ .pull = _pull, \
+ .vin_sel = _vin, \
+ .out_strength = _out_strength, \
+ .function = _func, \
+ .inv_int_pol = _inv, \
+ .disable_pin = _disable, \
+ } \
+}
+
+#define PM8XXX_MPP_INIT(_mpp, _type, _level, _control) \
+{ \
+ .mpp = PM8921_MPP_PM_TO_SYS(_mpp), \
+ .config = { \
+ .type = PM8XXX_MPP_TYPE_##_type, \
+ .level = _level, \
+ .control = PM8XXX_MPP_##_control, \
+ } \
+}
+
+#define PM8XXX_GPIO_DISABLE(_gpio) \
+ PM8XXX_GPIO_INIT(_gpio, PM_GPIO_DIR_IN, 0, 0, 0, PM_GPIO_VIN_S4, \
+ 0, 0, 0, 1)
+
+#define PM8XXX_GPIO_OUTPUT(_gpio, _val) \
+ PM8XXX_GPIO_INIT(_gpio, PM_GPIO_DIR_OUT, PM_GPIO_OUT_BUF_CMOS, _val, \
+ PM_GPIO_PULL_NO, PM_GPIO_VIN_S4, \
+ PM_GPIO_STRENGTH_HIGH, \
+ PM_GPIO_FUNC_NORMAL, 0, 0)
+
+#define PM8XXX_GPIO_INPUT(_gpio, _pull) \
+ PM8XXX_GPIO_INIT(_gpio, PM_GPIO_DIR_IN, PM_GPIO_OUT_BUF_CMOS, 0, \
+ _pull, PM_GPIO_VIN_S4, \
+ PM_GPIO_STRENGTH_NO, \
+ PM_GPIO_FUNC_NORMAL, 0, 0)
+
+#define PM8XXX_GPIO_OUTPUT_FUNC(_gpio, _val, _func) \
+ PM8XXX_GPIO_INIT(_gpio, PM_GPIO_DIR_OUT, PM_GPIO_OUT_BUF_CMOS, _val, \
+ PM_GPIO_PULL_NO, PM_GPIO_VIN_S4, \
+ PM_GPIO_STRENGTH_HIGH, \
+ _func, 0, 0)
+
+#define PM8XXX_GPIO_OUTPUT_VIN(_gpio, _val, _vin) \
+ PM8XXX_GPIO_INIT(_gpio, PM_GPIO_DIR_OUT, PM_GPIO_OUT_BUF_CMOS, _val, \
+ PM_GPIO_PULL_NO, _vin, \
+ PM_GPIO_STRENGTH_HIGH, \
+ PM_GPIO_FUNC_NORMAL, 0, 0)
+
+/* Initial PM8921 GPIO configurations */
+static struct pm8xxx_gpio_init pm8921_gpios[] __initdata = {
+ PM8XXX_GPIO_DISABLE(6), /* Disable unused */
+ PM8XXX_GPIO_DISABLE(7), /* Disable NFC */
+ PM8XXX_GPIO_INPUT(16, PM_GPIO_PULL_UP_30), /* SD_CARD_WP */
+ /* External regulator shared by display and touchscreen on LiQUID */
+ PM8XXX_GPIO_OUTPUT(17, 0), /* DISP 3.3 V Boost */
+ PM8XXX_GPIO_OUTPUT_VIN(21, 1, PM_GPIO_VIN_VPH), /* Backlight Enable */
+ PM8XXX_GPIO_DISABLE(22), /* Disable NFC */
+ PM8XXX_GPIO_OUTPUT_FUNC(24, 0, PM_GPIO_FUNC_2), /* Bl: Off, PWM mode */
+ PM8XXX_GPIO_INPUT(26, PM_GPIO_PULL_UP_30), /* SD_CARD_DET_N */
+ PM8XXX_GPIO_OUTPUT(43, PM_GPIO_PULL_UP_30), /* DISP_RESET_N */
+ PM8XXX_GPIO_OUTPUT(42, 0), /* USB 5V reg enable */
+};
+
+/* Initial PM8921 MPP configurations */
+static struct pm8xxx_mpp_init pm8921_mpps[] __initdata = {
+ /* External 5V regulator enable; shared by HDMI and USB_OTG switches. */
+ PM8XXX_MPP_INIT(7, D_INPUT, PM8921_MPP_DIG_LEVEL_VPH, DIN_TO_INT),
+ PM8XXX_MPP_INIT(PM8XXX_AMUX_MPP_8, A_INPUT, PM8XXX_MPP_AIN_AMUX_CH8,
+ DOUT_CTRL_LOW),
+};
+
+void __init msm8960_pm8921_gpio_mpp_init(void)
+{
+ int i, rc;
+
+ for (i = 0; i < ARRAY_SIZE(pm8921_gpios); i++) {
+ rc = pm8xxx_gpio_config(pm8921_gpios[i].gpio,
+ &pm8921_gpios[i].config);
+ if (rc) {
+ pr_err("%s: pm8xxx_gpio_config: rc=%d\n", __func__, rc);
+ break;
+ }
+ }
+
+ for (i = 0; i < ARRAY_SIZE(pm8921_mpps); i++) {
+ rc = pm8xxx_mpp_config(pm8921_mpps[i].mpp,
+ &pm8921_mpps[i].config);
+ if (rc) {
+ pr_err("%s: pm8xxx_mpp_config: rc=%d\n", __func__, rc);
+ break;
+ }
+ }
+}
+
+static struct pm8xxx_adc_amux pm8xxx_adc_channels_data[] = {
+ {"vcoin", CHANNEL_VCOIN, CHAN_PATH_SCALING2, AMUX_RSV1,
+ ADC_DECIMATION_TYPE2, ADC_SCALE_DEFAULT},
+ {"vbat", CHANNEL_VBAT, CHAN_PATH_SCALING2, AMUX_RSV1,
+ ADC_DECIMATION_TYPE2, ADC_SCALE_DEFAULT},
+ {"dcin", CHANNEL_DCIN, CHAN_PATH_SCALING4, AMUX_RSV1,
+ ADC_DECIMATION_TYPE2, ADC_SCALE_DEFAULT},
+ {"ichg", CHANNEL_ICHG, CHAN_PATH_SCALING1, AMUX_RSV1,
+ ADC_DECIMATION_TYPE2, ADC_SCALE_DEFAULT},
+ {"vph_pwr", CHANNEL_VPH_PWR, CHAN_PATH_SCALING2, AMUX_RSV1,
+ ADC_DECIMATION_TYPE2, ADC_SCALE_DEFAULT},
+ {"ibat", CHANNEL_IBAT, CHAN_PATH_SCALING1, AMUX_RSV1,
+ ADC_DECIMATION_TYPE2, ADC_SCALE_DEFAULT},
+ {"batt_therm", CHANNEL_BATT_THERM, CHAN_PATH_SCALING1, AMUX_RSV2,
+ ADC_DECIMATION_TYPE2, ADC_SCALE_BATT_THERM},
+ {"batt_id", CHANNEL_BATT_ID, CHAN_PATH_SCALING1, AMUX_RSV1,
+ ADC_DECIMATION_TYPE2, ADC_SCALE_DEFAULT},
+ {"usbin", CHANNEL_USBIN, CHAN_PATH_SCALING3, AMUX_RSV1,
+ ADC_DECIMATION_TYPE2, ADC_SCALE_DEFAULT},
+ {"pmic_therm", CHANNEL_DIE_TEMP, CHAN_PATH_SCALING1, AMUX_RSV1,
+ ADC_DECIMATION_TYPE2, ADC_SCALE_PMIC_THERM},
+ {"625mv", CHANNEL_625MV, CHAN_PATH_SCALING1, AMUX_RSV1,
+ ADC_DECIMATION_TYPE2, ADC_SCALE_DEFAULT},
+ {"125v", CHANNEL_125V, CHAN_PATH_SCALING1, AMUX_RSV1,
+ ADC_DECIMATION_TYPE2, ADC_SCALE_DEFAULT},
+ {"chg_temp", CHANNEL_CHG_TEMP, CHAN_PATH_SCALING1, AMUX_RSV1,
+ ADC_DECIMATION_TYPE2, ADC_SCALE_DEFAULT},
+ {"pa_therm1", ADC_MPP_1_AMUX8, CHAN_PATH_SCALING1, AMUX_RSV1,
+ ADC_DECIMATION_TYPE2, ADC_SCALE_PA_THERM},
+ {"xo_therm", CHANNEL_MUXOFF, CHAN_PATH_SCALING1, AMUX_RSV0,
+ ADC_DECIMATION_TYPE2, ADC_SCALE_XOTHERM},
+ {"pa_therm0", ADC_MPP_1_AMUX3, CHAN_PATH_SCALING1, AMUX_RSV1,
+ ADC_DECIMATION_TYPE2, ADC_SCALE_PA_THERM},
+};
+
+static struct pm8xxx_adc_properties pm8xxx_adc_data = {
+ .adc_vdd_reference = 1800, /* milli-voltage for this adc */
+ .bitresolution = 15,
+ .bipolar = 0,
+};
+
+static struct pm8xxx_adc_platform_data pm8xxx_adc_pdata = {
+ .adc_channel = pm8xxx_adc_channels_data,
+ .adc_num_board_channel = ARRAY_SIZE(pm8xxx_adc_channels_data),
+ .adc_prop = &pm8xxx_adc_data,
+ .adc_mpp_base = PM8921_MPP_PM_TO_SYS(1),
+};
+
+static struct pm8xxx_irq_platform_data pm8xxx_irq_pdata __devinitdata = {
+ .irq_base = PM8921_IRQ_BASE,
+ .devirq = MSM_GPIO_TO_INT(104),
+ .irq_trigger_flag = IRQF_TRIGGER_LOW,
+};
+
+static struct pm8xxx_gpio_platform_data pm8xxx_gpio_pdata __devinitdata = {
+ .gpio_base = PM8921_GPIO_PM_TO_SYS(1),
+};
+
+static struct pm8xxx_mpp_platform_data pm8xxx_mpp_pdata __devinitdata = {
+ .mpp_base = PM8921_MPP_PM_TO_SYS(1),
+};
+
+static struct pm8xxx_rtc_platform_data pm8xxx_rtc_pdata __devinitdata = {
+ .rtc_write_enable = false,
+ .rtc_alarm_powerup = false,
+};
+
+static struct pm8xxx_pwrkey_platform_data pm8xxx_pwrkey_pdata = {
+ .pull_up = 1,
+ .kpd_trigger_delay_us = 15625,
+ .wakeup = 1,
+};
+
+/* Rotate lock key is not available so use F1 */
+#define KEY_ROTATE_LOCK KEY_F1
+
+static const unsigned int keymap_liquid[] = {
+ KEY(0, 0, KEY_VOLUMEUP),
+ KEY(0, 1, KEY_VOLUMEDOWN),
+ KEY(1, 3, KEY_ROTATE_LOCK),
+ KEY(1, 4, KEY_HOME),
+};
+
+static struct matrix_keymap_data keymap_data_liquid = {
+ .keymap_size = ARRAY_SIZE(keymap_liquid),
+ .keymap = keymap_liquid,
+};
+
+static struct pm8xxx_keypad_platform_data keypad_data_liquid = {
+ .input_name = "keypad_8960_liquid",
+ .input_phys_device = "keypad_8960/input0",
+ .num_rows = 2,
+ .num_cols = 5,
+ .rows_gpio_start = PM8921_GPIO_PM_TO_SYS(9),
+ .cols_gpio_start = PM8921_GPIO_PM_TO_SYS(1),
+ .debounce_ms = 15,
+ .scan_delay_ms = 32,
+ .row_hold_ns = 91500,
+ .wakeup = 1,
+ .keymap_data = &keymap_data_liquid,
+};
+
+
+static const unsigned int keymap[] = {
+ KEY(0, 0, KEY_VOLUMEUP),
+ KEY(0, 1, KEY_VOLUMEDOWN),
+ KEY(0, 2, KEY_CAMERA_SNAPSHOT),
+ KEY(0, 3, KEY_CAMERA_FOCUS),
+};
+
+static struct matrix_keymap_data keymap_data = {
+ .keymap_size = ARRAY_SIZE(keymap),
+ .keymap = keymap,
+};
+
+static struct pm8xxx_keypad_platform_data keypad_data = {
+ .input_name = "keypad_8960",
+ .input_phys_device = "keypad_8960/input0",
+ .num_rows = 1,
+ .num_cols = 5,
+ .rows_gpio_start = PM8921_GPIO_PM_TO_SYS(9),
+ .cols_gpio_start = PM8921_GPIO_PM_TO_SYS(1),
+ .debounce_ms = 15,
+ .scan_delay_ms = 32,
+ .row_hold_ns = 91500,
+ .wakeup = 1,
+ .keymap_data = &keymap_data,
+};
+
+static const unsigned int keymap_sim[] = {
+ KEY(0, 0, KEY_7),
+ KEY(0, 1, KEY_DOWN),
+ KEY(0, 2, KEY_UP),
+ KEY(0, 3, KEY_RIGHT),
+ KEY(0, 4, KEY_ENTER),
+ KEY(0, 5, KEY_L),
+ KEY(0, 6, KEY_BACK),
+ KEY(0, 7, KEY_M),
+
+ KEY(1, 0, KEY_LEFT),
+ KEY(1, 1, KEY_SEND),
+ KEY(1, 2, KEY_1),
+ KEY(1, 3, KEY_4),
+ KEY(1, 4, KEY_CLEAR),
+ KEY(1, 5, KEY_MSDOS),
+ KEY(1, 6, KEY_SPACE),
+ KEY(1, 7, KEY_COMMA),
+
+ KEY(2, 0, KEY_6),
+ KEY(2, 1, KEY_5),
+ KEY(2, 2, KEY_8),
+ KEY(2, 3, KEY_3),
+ KEY(2, 4, KEY_NUMERIC_STAR),
+ KEY(2, 5, KEY_UP),
+ KEY(2, 6, KEY_DOWN),
+ KEY(2, 7, KEY_LEFTSHIFT),
+
+ KEY(3, 0, KEY_9),
+ KEY(3, 1, KEY_NUMERIC_POUND),
+ KEY(3, 2, KEY_0),
+ KEY(3, 3, KEY_2),
+ KEY(3, 4, KEY_SLEEP),
+ KEY(3, 5, KEY_F1),
+ KEY(3, 6, KEY_F2),
+ KEY(3, 7, KEY_F3),
+
+ KEY(4, 0, KEY_BACK),
+ KEY(4, 1, KEY_HOME),
+ KEY(4, 2, KEY_MENU),
+ KEY(4, 3, KEY_VOLUMEUP),
+ KEY(4, 4, KEY_VOLUMEDOWN),
+ KEY(4, 5, KEY_F4),
+ KEY(4, 6, KEY_F5),
+ KEY(4, 7, KEY_F6),
+
+ KEY(5, 0, KEY_R),
+ KEY(5, 1, KEY_T),
+ KEY(5, 2, KEY_Y),
+ KEY(5, 3, KEY_LEFTALT),
+ KEY(5, 4, KEY_KPENTER),
+ KEY(5, 5, KEY_Q),
+ KEY(5, 6, KEY_W),
+ KEY(5, 7, KEY_E),
+
+ KEY(6, 0, KEY_F),
+ KEY(6, 1, KEY_G),
+ KEY(6, 2, KEY_H),
+ KEY(6, 3, KEY_CAPSLOCK),
+ KEY(6, 4, KEY_PAGEUP),
+ KEY(6, 5, KEY_A),
+ KEY(6, 6, KEY_S),
+ KEY(6, 7, KEY_D),
+
+ KEY(7, 0, KEY_V),
+ KEY(7, 1, KEY_B),
+ KEY(7, 2, KEY_N),
+ KEY(7, 3, KEY_MENU),
+ KEY(7, 4, KEY_PAGEDOWN),
+ KEY(7, 5, KEY_Z),
+ KEY(7, 6, KEY_X),
+ KEY(7, 7, KEY_C),
+
+ KEY(8, 0, KEY_P),
+ KEY(8, 1, KEY_J),
+ KEY(8, 2, KEY_K),
+ KEY(8, 3, KEY_INSERT),
+ KEY(8, 4, KEY_LINEFEED),
+ KEY(8, 5, KEY_U),
+ KEY(8, 6, KEY_I),
+ KEY(8, 7, KEY_O),
+
+ KEY(9, 0, KEY_4),
+ KEY(9, 1, KEY_5),
+ KEY(9, 2, KEY_6),
+ KEY(9, 3, KEY_7),
+ KEY(9, 4, KEY_8),
+ KEY(9, 5, KEY_1),
+ KEY(9, 6, KEY_2),
+ KEY(9, 7, KEY_3),
+
+ KEY(10, 0, KEY_F7),
+ KEY(10, 1, KEY_F8),
+ KEY(10, 2, KEY_F9),
+ KEY(10, 3, KEY_F10),
+ KEY(10, 4, KEY_FN),
+ KEY(10, 5, KEY_9),
+ KEY(10, 6, KEY_0),
+ KEY(10, 7, KEY_DOT),
+
+ KEY(11, 0, KEY_LEFTCTRL),
+ KEY(11, 1, KEY_F11),
+ KEY(11, 2, KEY_ENTER),
+ KEY(11, 3, KEY_SEARCH),
+ KEY(11, 4, KEY_DELETE),
+ KEY(11, 5, KEY_RIGHT),
+ KEY(11, 6, KEY_LEFT),
+ KEY(11, 7, KEY_RIGHTSHIFT),
+ KEY(0, 0, KEY_VOLUMEUP),
+ KEY(0, 1, KEY_VOLUMEDOWN),
+ KEY(0, 2, KEY_CAMERA_SNAPSHOT),
+ KEY(0, 3, KEY_CAMERA_FOCUS),
+};
+
+static struct matrix_keymap_data keymap_data_sim = {
+ .keymap_size = ARRAY_SIZE(keymap_sim),
+ .keymap = keymap_sim,
+};
+
+static struct pm8xxx_keypad_platform_data keypad_data_sim = {
+ .input_name = "keypad_8960",
+ .input_phys_device = "keypad_8960/input0",
+ .num_rows = 12,
+ .num_cols = 8,
+ .rows_gpio_start = PM8921_GPIO_PM_TO_SYS(9),
+ .cols_gpio_start = PM8921_GPIO_PM_TO_SYS(1),
+ .debounce_ms = 15,
+ .scan_delay_ms = 32,
+ .row_hold_ns = 91500,
+ .wakeup = 1,
+ .keymap_data = &keymap_data_sim,
+};
+
+static int pm8921_therm_mitigation[] = {
+ 1100,
+ 700,
+ 600,
+ 325,
+};
+
+static struct pm8921_charger_platform_data pm8921_chg_pdata __devinitdata = {
+ .safety_time = 180,
+ .update_time = 60000,
+ .max_voltage = 4200,
+ .min_voltage = 3200,
+ .resume_voltage_delta = 100,
+ .term_current = 100,
+ .cool_temp = 10,
+ .warm_temp = 40,
+ .temp_check_period = 1,
+ .max_bat_chg_current = 1100,
+ .cool_bat_chg_current = 350,
+ .warm_bat_chg_current = 350,
+ .cool_bat_voltage = 4100,
+ .warm_bat_voltage = 4100,
+ .thermal_mitigation = pm8921_therm_mitigation,
+ .thermal_levels = ARRAY_SIZE(pm8921_therm_mitigation),
+};
+
+static struct pm8xxx_misc_platform_data pm8xxx_misc_pdata = {
+ .priority = 0,
+};
+
+static struct pm8921_bms_platform_data pm8921_bms_pdata __devinitdata = {
+ .r_sense = 10,
+ .i_test = 2500,
+ .v_failure = 3000,
+ .calib_delay_ms = 600000,
+};
+
+#define PM8921_LC_LED_MAX_CURRENT 4 /* I = 4mA */
+#define PM8XXX_LED_PWM_PERIOD 1000
+#define PM8XXX_LED_PWM_DUTY_MS 20
+/**
+ * PM8XXX_PWM_CHANNEL_NONE shall be used when LED shall not be
+ * driven using PWM feature.
+ */
+#define PM8XXX_PWM_CHANNEL_NONE -1
+
+static struct led_info pm8921_led_info[] = {
+ [0] = {
+ .name = "led:battery_charging",
+ .default_trigger = "battery-charging",
+ },
+ [1] = {
+ .name = "led:battery_full",
+ .default_trigger = "battery-full",
+ },
+};
+
+static struct led_platform_data pm8921_led_core_pdata = {
+ .num_leds = ARRAY_SIZE(pm8921_led_info),
+ .leds = pm8921_led_info,
+};
+
+static int pm8921_led0_pwm_duty_pcts[56] = {
+ 1, 4, 8, 12, 16, 20, 24, 28, 32, 36,
+ 40, 44, 46, 52, 56, 60, 64, 68, 72, 76,
+ 80, 84, 88, 92, 96, 100, 100, 100, 98, 95,
+ 92, 88, 84, 82, 78, 74, 70, 66, 62, 58,
+ 58, 54, 50, 48, 42, 38, 34, 30, 26, 22,
+ 14, 10, 6, 4, 1
+};
+
+static struct pm8xxx_pwm_duty_cycles pm8921_led0_pwm_duty_cycles = {
+ .duty_pcts = (int *)&pm8921_led0_pwm_duty_pcts,
+ .num_duty_pcts = ARRAY_SIZE(pm8921_led0_pwm_duty_pcts),
+ .duty_ms = PM8XXX_LED_PWM_DUTY_MS,
+ .start_idx = 0,
+};
+
+static struct pm8xxx_led_config pm8921_led_configs[] = {
+ [0] = {
+ .id = PM8XXX_ID_LED_0,
+ .mode = PM8XXX_LED_MODE_PWM2,
+ .max_current = PM8921_LC_LED_MAX_CURRENT,
+ .pwm_channel = 5,
+ .pwm_period_us = PM8XXX_LED_PWM_PERIOD,
+ .pwm_duty_cycles = &pm8921_led0_pwm_duty_cycles,
+ },
+ [1] = {
+ .id = PM8XXX_ID_LED_1,
+ .mode = PM8XXX_LED_MODE_PWM1,
+ .max_current = PM8921_LC_LED_MAX_CURRENT,
+ .pwm_channel = 4,
+ .pwm_period_us = PM8XXX_LED_PWM_PERIOD,
+ },
+};
+
+static struct pm8xxx_led_platform_data pm8xxx_leds_pdata = {
+ .led_core = &pm8921_led_core_pdata,
+ .configs = pm8921_led_configs,
+ .num_configs = ARRAY_SIZE(pm8921_led_configs),
+};
+
+static struct pm8xxx_ccadc_platform_data pm8xxx_ccadc_pdata = {
+ .r_sense = 10,
+};
+
+static struct pm8921_platform_data pm8921_platform_data __devinitdata = {
+ .irq_pdata = &pm8xxx_irq_pdata,
+ .gpio_pdata = &pm8xxx_gpio_pdata,
+ .mpp_pdata = &pm8xxx_mpp_pdata,
+ .rtc_pdata = &pm8xxx_rtc_pdata,
+ .pwrkey_pdata = &pm8xxx_pwrkey_pdata,
+ .keypad_pdata = &keypad_data,
+ .misc_pdata = &pm8xxx_misc_pdata,
+ .regulator_pdatas = msm_pm8921_regulator_pdata,
+ .charger_pdata = &pm8921_chg_pdata,
+ .bms_pdata = &pm8921_bms_pdata,
+ .adc_pdata = &pm8xxx_adc_pdata,
+ .leds_pdata = &pm8xxx_leds_pdata,
+ .ccadc_pdata = &pm8xxx_ccadc_pdata,
+};
+
+static struct msm_ssbi_platform_data msm8960_ssbi_pm8921_pdata __devinitdata = {
+ .controller_type = MSM_SBI_CTRL_PMIC_ARBITER,
+ .slave = {
+ .name = "pm8921-core",
+ .platform_data = &pm8921_platform_data,
+ },
+};
+
+void __init msm8960_init_pmic(void)
+{
+ pmic_reset_irq = PM8921_IRQ_BASE + PM8921_RESOUT_IRQ;
+ msm8960_device_ssbi_pm8921.dev.platform_data =
+ &msm8960_ssbi_pm8921_pdata;
+ pm8921_platform_data.num_regulators = msm_pm8921_regulator_pdata_len;
+
+ /* Simulator supports a QWERTY keypad */
+ if (machine_is_msm8960_sim())
+ pm8921_platform_data.keypad_pdata = &keypad_data_sim;
+
+ if (machine_is_msm8960_liquid())
+ pm8921_platform_data.keypad_pdata = &keypad_data_liquid;
+}
diff --git a/arch/arm/mach-msm/board-msm8960-regulator.c b/arch/arm/mach-msm/board-8960-regulator.c
similarity index 98%
rename from arch/arm/mach-msm/board-msm8960-regulator.c
rename to arch/arm/mach-msm/board-8960-regulator.c
index 559312c..7bc3ca5 100644
--- a/arch/arm/mach-msm/board-msm8960-regulator.c
+++ b/arch/arm/mach-msm/board-8960-regulator.c
@@ -15,7 +15,7 @@
#include <linux/regulator/gpio-regulator.h>
#include <mach/rpm-regulator.h>
-#include "board-msm8960.h"
+#include "board-8960.h"
#define VREG_CONSUMERS(_id) \
static struct regulator_consumer_supply vreg_consumers_##_id[]
@@ -119,15 +119,15 @@
};
VREG_CONSUMERS(L26) = {
REGULATOR_SUPPLY("8921_l26", NULL),
- REGULATOR_SUPPLY("q6_lpass", NULL),
+ REGULATOR_SUPPLY("core_vdd", "pil_qdsp6v4.0"),
};
VREG_CONSUMERS(L27) = {
REGULATOR_SUPPLY("8921_l27", NULL),
- REGULATOR_SUPPLY("q6_modem_sw", NULL),
+ REGULATOR_SUPPLY("core_vdd", "pil_qdsp6v4.2"),
};
VREG_CONSUMERS(L28) = {
REGULATOR_SUPPLY("8921_l28", NULL),
- REGULATOR_SUPPLY("q6_modem_fw", NULL),
+ REGULATOR_SUPPLY("core_vdd", "pil_qdsp6v4.1"),
};
VREG_CONSUMERS(L29) = {
REGULATOR_SUPPLY("8921_l29", NULL),
@@ -449,9 +449,9 @@
/* SAW regulator constraints */
struct regulator_init_data msm_saw_regulator_pdata_s5 =
/* ID vreg_name min_uV max_uV */
- SAW_VREG_INIT(S5, "8921_s5", 950000, 1150000);
+ SAW_VREG_INIT(S5, "8921_s5", 950000, 1300000);
struct regulator_init_data msm_saw_regulator_pdata_s6 =
- SAW_VREG_INIT(S6, "8921_s6", 950000, 1150000);
+ SAW_VREG_INIT(S6, "8921_s6", 950000, 1300000);
/* PM8921 regulator constraints */
struct pm8921_regulator_platform_data
diff --git a/arch/arm/mach-msm/board-8960-storage.c b/arch/arm/mach-msm/board-8960-storage.c
new file mode 100644
index 0000000..dfcafd4
--- /dev/null
+++ b/arch/arm/mach-msm/board-8960-storage.c
@@ -0,0 +1,268 @@
+/* Copyright (c) 2011, Code Aurora Forum. 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 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#include <linux/init.h>
+#include <linux/ioport.h>
+#include <linux/platform_device.h>
+#include <linux/bootmem.h>
+#include <asm/mach-types.h>
+#include <asm/mach/mmc.h>
+#include <mach/msm_bus_board.h>
+#include <mach/board.h>
+#include <mach/gpio.h>
+#include <mach/gpiomux.h>
+#include "devices.h"
+#include "board-8960.h"
+
+/* MSM8960 has 5 SDCC controllers */
+enum sdcc_controllers {
+ SDCC1,
+ SDCC2,
+ SDCC3,
+ SDCC4,
+ SDCC5,
+ MAX_SDCC_CONTROLLER
+};
+
+/* All SDCC controllers require VDD/VCC voltage */
+static struct msm_mmc_reg_data mmc_vdd_reg_data[MAX_SDCC_CONTROLLER] = {
+ /* SDCC1 : eMMC card connected */
+ [SDCC1] = {
+ .name = "sdc_vdd",
+ .high_vol_level = 2950000,
+ .low_vol_level = 2950000,
+ .always_on = 1,
+ .lpm_sup = 1,
+ .lpm_uA = 9000,
+ .hpm_uA = 200000, /* 200mA */
+ },
+ /* SDCC3 : External card slot connected */
+ [SDCC3] = {
+ .name = "sdc_vdd",
+ .high_vol_level = 2950000,
+ .low_vol_level = 2950000,
+ .hpm_uA = 600000, /* 600mA */
+ }
+};
+
+/* Only slots having eMMC card will require VCCQ voltage */
+static struct msm_mmc_reg_data mmc_vccq_reg_data[1] = {
+ /* SDCC1 : eMMC card connected */
+ [SDCC1] = {
+ .name = "sdc_vccq",
+ .always_on = 1,
+ .high_vol_level = 1800000,
+ .low_vol_level = 1800000,
+ .hpm_uA = 200000, /* 200mA */
+ }
+};
+
+/* All SDCC controllers may require voting for VDD PAD voltage */
+static struct msm_mmc_reg_data mmc_vddp_reg_data[MAX_SDCC_CONTROLLER] = {
+ /* SDCC3 : External card slot connected */
+ [SDCC3] = {
+ .name = "sdc_vddp",
+ .high_vol_level = 2950000,
+ .low_vol_level = 1850000,
+ .always_on = 1,
+ .lpm_sup = 1,
+ /* Max. Active current required is 16 mA */
+ .hpm_uA = 16000,
+ /*
+ * Sleep current required is ~300 uA. But min. vote can be
+ * in terms of mA (min. 1 mA). So let's vote for 2 mA
+ * during sleep.
+ */
+ .lpm_uA = 2000,
+ }
+};
+
+static struct msm_mmc_slot_reg_data mmc_slot_vreg_data[MAX_SDCC_CONTROLLER] = {
+ /* SDCC1 : eMMC card connected */
+ [SDCC1] = {
+ .vdd_data = &mmc_vdd_reg_data[SDCC1],
+ .vccq_data = &mmc_vccq_reg_data[SDCC1],
+ },
+ /* SDCC3 : External card slot connected */
+ [SDCC3] = {
+ .vdd_data = &mmc_vdd_reg_data[SDCC3],
+ .vddp_data = &mmc_vddp_reg_data[SDCC3],
+ }
+};
+
+/* SDC1 pad data */
+static struct msm_mmc_pad_drv sdc1_pad_drv_on_cfg[] = {
+ {TLMM_HDRV_SDC1_CLK, GPIO_CFG_16MA},
+ {TLMM_HDRV_SDC1_CMD, GPIO_CFG_10MA},
+ {TLMM_HDRV_SDC1_DATA, GPIO_CFG_10MA}
+};
+
+static struct msm_mmc_pad_drv sdc1_pad_drv_off_cfg[] = {
+ {TLMM_HDRV_SDC1_CLK, GPIO_CFG_2MA},
+ {TLMM_HDRV_SDC1_CMD, GPIO_CFG_2MA},
+ {TLMM_HDRV_SDC1_DATA, GPIO_CFG_2MA}
+};
+
+static struct msm_mmc_pad_pull sdc1_pad_pull_on_cfg[] = {
+ {TLMM_PULL_SDC1_CLK, GPIO_CFG_NO_PULL},
+ {TLMM_PULL_SDC1_CMD, GPIO_CFG_PULL_UP},
+ {TLMM_PULL_SDC1_DATA, GPIO_CFG_PULL_UP}
+};
+
+static struct msm_mmc_pad_pull sdc1_pad_pull_off_cfg[] = {
+ {TLMM_PULL_SDC1_CLK, GPIO_CFG_NO_PULL},
+ {TLMM_PULL_SDC1_CMD, GPIO_CFG_PULL_DOWN},
+ {TLMM_PULL_SDC1_DATA, GPIO_CFG_PULL_DOWN}
+};
+
+/* SDC3 pad data */
+static struct msm_mmc_pad_drv sdc3_pad_drv_on_cfg[] = {
+ {TLMM_HDRV_SDC3_CLK, GPIO_CFG_8MA},
+ {TLMM_HDRV_SDC3_CMD, GPIO_CFG_8MA},
+ {TLMM_HDRV_SDC3_DATA, GPIO_CFG_8MA}
+};
+
+static struct msm_mmc_pad_drv sdc3_pad_drv_off_cfg[] = {
+ {TLMM_HDRV_SDC3_CLK, GPIO_CFG_2MA},
+ {TLMM_HDRV_SDC3_CMD, GPIO_CFG_2MA},
+ {TLMM_HDRV_SDC3_DATA, GPIO_CFG_2MA}
+};
+
+static struct msm_mmc_pad_pull sdc3_pad_pull_on_cfg[] = {
+ {TLMM_PULL_SDC3_CLK, GPIO_CFG_NO_PULL},
+ {TLMM_PULL_SDC3_CMD, GPIO_CFG_PULL_UP},
+ {TLMM_PULL_SDC3_DATA, GPIO_CFG_PULL_UP}
+};
+
+static struct msm_mmc_pad_pull sdc3_pad_pull_off_cfg[] = {
+ {TLMM_PULL_SDC3_CLK, GPIO_CFG_NO_PULL},
+ /*
+ * SDC3 CMD line should be PULLed UP otherwise fluid platform will
+ * see transitions (1 -> 0 and 0 -> 1) on card detection line,
+ * which would result in false card detection interrupts.
+ */
+ {TLMM_PULL_SDC3_CMD, GPIO_CFG_PULL_UP},
+ /*
+ * Keeping DATA lines status to PULL UP will make sure that
+ * there is no current leak during sleep if external pull up
+ * is connected to DATA lines.
+ */
+ {TLMM_PULL_SDC3_DATA, GPIO_CFG_PULL_UP}
+};
+
+static struct msm_mmc_pad_pull_data mmc_pad_pull_data[MAX_SDCC_CONTROLLER] = {
+ [SDCC1] = {
+ .on = sdc1_pad_pull_on_cfg,
+ .off = sdc1_pad_pull_off_cfg,
+ .size = ARRAY_SIZE(sdc1_pad_pull_on_cfg)
+ },
+ [SDCC3] = {
+ .on = sdc3_pad_pull_on_cfg,
+ .off = sdc3_pad_pull_off_cfg,
+ .size = ARRAY_SIZE(sdc3_pad_pull_on_cfg)
+ },
+};
+
+static struct msm_mmc_pad_drv_data mmc_pad_drv_data[MAX_SDCC_CONTROLLER] = {
+ [SDCC1] = {
+ .on = sdc1_pad_drv_on_cfg,
+ .off = sdc1_pad_drv_off_cfg,
+ .size = ARRAY_SIZE(sdc1_pad_drv_on_cfg)
+ },
+ [SDCC3] = {
+ .on = sdc3_pad_drv_on_cfg,
+ .off = sdc3_pad_drv_off_cfg,
+ .size = ARRAY_SIZE(sdc3_pad_drv_on_cfg)
+ },
+};
+
+static struct msm_mmc_pad_data mmc_pad_data[MAX_SDCC_CONTROLLER] = {
+ [SDCC1] = {
+ .pull = &mmc_pad_pull_data[SDCC1],
+ .drv = &mmc_pad_drv_data[SDCC1]
+ },
+ [SDCC3] = {
+ .pull = &mmc_pad_pull_data[SDCC3],
+ .drv = &mmc_pad_drv_data[SDCC3]
+ },
+};
+
+static struct msm_mmc_pin_data mmc_slot_pin_data[MAX_SDCC_CONTROLLER] = {
+ [SDCC1] = {
+ .pad_data = &mmc_pad_data[SDCC1],
+ },
+ [SDCC3] = {
+ .pad_data = &mmc_pad_data[SDCC3],
+ },
+};
+
+static unsigned int sdc1_sup_clk_rates[] = {
+ 400000, 24000000, 48000000
+};
+
+static unsigned int sdc3_sup_clk_rates[] = {
+ 400000, 24000000, 48000000, 96000000
+};
+
+#ifdef CONFIG_MMC_MSM_SDC1_SUPPORT
+static struct mmc_platform_data msm8960_sdc1_data = {
+ .ocr_mask = MMC_VDD_27_28 | MMC_VDD_28_29,
+#ifdef CONFIG_MMC_MSM_SDC1_8_BIT_SUPPORT
+ .mmc_bus_width = MMC_CAP_8_BIT_DATA,
+#else
+ .mmc_bus_width = MMC_CAP_4_BIT_DATA,
+#endif
+ .sup_clk_table = sdc1_sup_clk_rates,
+ .sup_clk_cnt = ARRAY_SIZE(sdc1_sup_clk_rates),
+ .pclk_src_dfab = 1,
+ .nonremovable = 1,
+ .vreg_data = &mmc_slot_vreg_data[SDCC1],
+ .pin_data = &mmc_slot_pin_data[SDCC1]
+};
+#endif
+
+#ifdef CONFIG_MMC_MSM_SDC3_SUPPORT
+static struct mmc_platform_data msm8960_sdc3_data = {
+ .ocr_mask = MMC_VDD_27_28 | MMC_VDD_28_29,
+ .mmc_bus_width = MMC_CAP_4_BIT_DATA,
+ .sup_clk_table = sdc3_sup_clk_rates,
+ .sup_clk_cnt = ARRAY_SIZE(sdc3_sup_clk_rates),
+ .pclk_src_dfab = 1,
+#ifdef CONFIG_MMC_MSM_SDC3_WP_SUPPORT
+ .wpswitch_gpio = PM8921_GPIO_PM_TO_SYS(16),
+#endif
+ .vreg_data = &mmc_slot_vreg_data[SDCC3],
+ .pin_data = &mmc_slot_pin_data[SDCC3],
+#ifdef CONFIG_MMC_MSM_CARD_HW_DETECTION
+ .status_gpio = PM8921_GPIO_PM_TO_SYS(26),
+ .status_irq = PM8921_GPIO_IRQ(PM8921_IRQ_BASE, 26),
+ .irq_flags = IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING,
+#endif
+ .xpc_cap = 1,
+ .uhs_caps = (MMC_CAP_UHS_SDR12 | MMC_CAP_UHS_SDR25 |
+ MMC_CAP_UHS_SDR50 | MMC_CAP_UHS_DDR50 |
+ MMC_CAP_MAX_CURRENT_600)
+};
+#endif
+
+void __init msm8960_init_mmc(void)
+{
+#ifdef CONFIG_MMC_MSM_SDC1_SUPPORT
+ /* SDC1 : eMMC card connected */
+ msm_add_sdcc(1, &msm8960_sdc1_data);
+#endif
+#ifdef CONFIG_MMC_MSM_SDC3_SUPPORT
+ /* SDC3: External card slot */
+ msm_add_sdcc(3, &msm8960_sdc3_data);
+#endif
+}
diff --git a/arch/arm/mach-msm/board-8960.c b/arch/arm/mach-msm/board-8960.c
new file mode 100644
index 0000000..2b9b0be
--- /dev/null
+++ b/arch/arm/mach-msm/board-8960.c
@@ -0,0 +1,2246 @@
+/* Copyright (c) 2011, Code Aurora Forum. 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 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ */
+#include <linux/kernel.h>
+#include <linux/platform_device.h>
+#include <linux/io.h>
+#include <linux/irq.h>
+#include <linux/i2c.h>
+#include <linux/i2c/sx150x.h>
+#include <linux/i2c/isl9519.h>
+#include <linux/gpio.h>
+#include <linux/msm_ssbi.h>
+#include <linux/regulator/gpio-regulator.h>
+#include <linux/mfd/pm8xxx/pm8921.h>
+#include <linux/mfd/pm8xxx/pm8xxx-adc.h>
+#include <linux/regulator/consumer.h>
+#include <linux/spi/spi.h>
+#include <linux/slimbus/slimbus.h>
+#include <linux/bootmem.h>
+#include <linux/msm_kgsl.h>
+#ifdef CONFIG_ANDROID_PMEM
+#include <linux/android_pmem.h>
+#endif
+#include <linux/cyttsp.h>
+#include <linux/dma-mapping.h>
+#include <linux/platform_data/qcom_crypto_device.h>
+#include <linux/platform_data/qcom_wcnss_device.h>
+#include <linux/leds.h>
+#include <linux/leds-pm8xxx.h>
+#include <linux/i2c/atmel_mxt_ts.h>
+#include <linux/msm_tsens.h>
+#include <linux/ks8851.h>
+#include <linux/i2c/isa1200.h>
+#include <linux/memory.h>
+
+#include <asm/mach-types.h>
+#include <asm/mach/arch.h>
+#include <asm/setup.h>
+#include <asm/hardware/gic.h>
+#include <asm/mach/mmc.h>
+
+#include <mach/board.h>
+#include <mach/msm_iomap.h>
+#include <mach/msm_spi.h>
+#ifdef CONFIG_USB_MSM_OTG_72K
+#include <mach/msm_hsusb.h>
+#else
+#include <linux/usb/msm_hsusb.h>
+#endif
+#include <linux/usb/android.h>
+#include <mach/usbdiag.h>
+#include <mach/socinfo.h>
+#include <mach/rpm.h>
+#include <mach/gpio.h>
+#include <mach/gpiomux.h>
+#include <mach/msm_bus_board.h>
+#include <mach/msm_memtypes.h>
+#include <mach/dma.h>
+#include <mach/msm_dsps.h>
+#include <mach/msm_xo.h>
+#include <mach/restart.h>
+
+#ifdef CONFIG_WCD9310_CODEC
+#include <linux/slimbus/slimbus.h>
+#include <linux/mfd/wcd9310/core.h>
+#include <linux/mfd/wcd9310/pdata.h>
+#endif
+
+#include <linux/ion.h>
+#include <mach/ion.h>
+#include <mach/mdm2.h>
+
+#include "timer.h"
+#include "devices.h"
+#include "devices-msm8x60.h"
+#include "spm.h"
+#include "board-8960.h"
+#include "pm.h"
+#include "cpuidle.h"
+#include "rpm_resources.h"
+#include "mpm.h"
+#include "acpuclock.h"
+#include "rpm_log.h"
+#include "smd_private.h"
+#include "pm-boot.h"
+#include "msm_watchdog.h"
+
+static struct platform_device msm_fm_platform_init = {
+ .name = "iris_fm",
+ .id = -1,
+};
+
+#define KS8851_RST_GPIO 89
+#define KS8851_IRQ_GPIO 90
+#define HAP_SHIFT_LVL_OE_GPIO 47
+
+#if defined(CONFIG_GPIO_SX150X) || defined(CONFIG_GPIO_SX150X_MODULE)
+
+struct sx150x_platform_data msm8960_sx150x_data[] = {
+ [SX150X_CAM] = {
+ .gpio_base = GPIO_CAM_EXPANDER_BASE,
+ .oscio_is_gpo = false,
+ .io_pullup_ena = 0x0,
+ .io_pulldn_ena = 0xc0,
+ .io_open_drain_ena = 0x0,
+ .irq_summary = -1,
+ },
+};
+
+#endif
+
+#define MSM_PMEM_ADSP_SIZE 0x3800000
+#define MSM_PMEM_AUDIO_SIZE 0x28B000
+#ifdef CONFIG_FB_MSM_HDMI_AS_PRIMARY
+#define MSM_PMEM_SIZE 0x4000000 /* 64 Mbytes */
+#else
+#define MSM_PMEM_SIZE 0x1C00000 /* 28 Mbytes */
+#endif
+
+
+#ifdef CONFIG_MSM_MULTIMEDIA_USE_ION
+#define MSM_PMEM_KERNEL_EBI1_SIZE 0xB0C000
+#define MSM_ION_EBI_SIZE (MSM_PMEM_SIZE + 0x600000)
+#define MSM_ION_ADSP_SIZE MSM_PMEM_ADSP_SIZE
+#define MSM_ION_HEAP_NUM 5
+#else
+#define MSM_PMEM_KERNEL_EBI1_SIZE 0x110C000
+#define MSM_ION_HEAP_NUM 2
+#endif
+
+#ifdef CONFIG_KERNEL_PMEM_EBI_REGION
+static unsigned pmem_kernel_ebi1_size = MSM_PMEM_KERNEL_EBI1_SIZE;
+static int __init pmem_kernel_ebi1_size_setup(char *p)
+{
+ pmem_kernel_ebi1_size = memparse(p, NULL);
+ return 0;
+}
+early_param("pmem_kernel_ebi1_size", pmem_kernel_ebi1_size_setup);
+#endif
+
+#ifdef CONFIG_ANDROID_PMEM
+static unsigned pmem_size = MSM_PMEM_SIZE;
+static int __init pmem_size_setup(char *p)
+{
+ pmem_size = memparse(p, NULL);
+ return 0;
+}
+early_param("pmem_size", pmem_size_setup);
+
+static unsigned pmem_adsp_size = MSM_PMEM_ADSP_SIZE;
+
+static int __init pmem_adsp_size_setup(char *p)
+{
+ pmem_adsp_size = memparse(p, NULL);
+ return 0;
+}
+early_param("pmem_adsp_size", pmem_adsp_size_setup);
+
+static unsigned pmem_audio_size = MSM_PMEM_AUDIO_SIZE;
+
+static int __init pmem_audio_size_setup(char *p)
+{
+ pmem_audio_size = memparse(p, NULL);
+ return 0;
+}
+early_param("pmem_audio_size", pmem_audio_size_setup);
+#endif
+
+#ifdef CONFIG_ANDROID_PMEM
+#ifndef CONFIG_MSM_MULTIMEDIA_USE_ION
+static struct android_pmem_platform_data android_pmem_pdata = {
+ .name = "pmem",
+ .allocator_type = PMEM_ALLOCATORTYPE_ALLORNOTHING,
+ .cached = 1,
+ .memory_type = MEMTYPE_EBI1,
+};
+
+static struct platform_device android_pmem_device = {
+ .name = "android_pmem",
+ .id = 0,
+ .dev = {.platform_data = &android_pmem_pdata},
+};
+
+static struct android_pmem_platform_data android_pmem_adsp_pdata = {
+ .name = "pmem_adsp",
+ .allocator_type = PMEM_ALLOCATORTYPE_BITMAP,
+ .cached = 0,
+ .memory_type = MEMTYPE_EBI1,
+};
+static struct platform_device android_pmem_adsp_device = {
+ .name = "android_pmem",
+ .id = 2,
+ .dev = { .platform_data = &android_pmem_adsp_pdata },
+};
+#endif
+
+static struct android_pmem_platform_data android_pmem_audio_pdata = {
+ .name = "pmem_audio",
+ .allocator_type = PMEM_ALLOCATORTYPE_BITMAP,
+ .cached = 0,
+ .memory_type = MEMTYPE_EBI1,
+};
+
+static struct platform_device android_pmem_audio_device = {
+ .name = "android_pmem",
+ .id = 4,
+ .dev = { .platform_data = &android_pmem_audio_pdata },
+};
+#endif
+
+#define DSP_RAM_BASE_8960 0x8da00000
+#define DSP_RAM_SIZE_8960 0x1800000
+static int dspcrashd_pdata_8960 = 0xDEADDEAD;
+
+static struct resource resources_dspcrashd_8960[] = {
+ {
+ .name = "msm_dspcrashd",
+ .start = DSP_RAM_BASE_8960,
+ .end = DSP_RAM_BASE_8960 + DSP_RAM_SIZE_8960,
+ .flags = IORESOURCE_DMA,
+ },
+};
+
+static struct platform_device msm_device_dspcrashd_8960 = {
+ .name = "msm_dspcrashd",
+ .num_resources = ARRAY_SIZE(resources_dspcrashd_8960),
+ .resource = resources_dspcrashd_8960,
+ .dev = { .platform_data = &dspcrashd_pdata_8960 },
+};
+
+static struct memtype_reserve msm8960_reserve_table[] __initdata = {
+ [MEMTYPE_SMI] = {
+ },
+ [MEMTYPE_EBI0] = {
+ .flags = MEMTYPE_FLAGS_1M_ALIGN,
+ },
+ [MEMTYPE_EBI1] = {
+ .flags = MEMTYPE_FLAGS_1M_ALIGN,
+ },
+};
+
+static void __init size_pmem_devices(void)
+{
+#ifdef CONFIG_ANDROID_PMEM
+#ifndef CONFIG_MSM_MULTIMEDIA_USE_ION
+ android_pmem_adsp_pdata.size = pmem_adsp_size;
+ android_pmem_pdata.size = pmem_size;
+#endif
+ android_pmem_audio_pdata.size = MSM_PMEM_AUDIO_SIZE;
+#endif
+}
+
+static void __init reserve_memory_for(struct android_pmem_platform_data *p)
+{
+ msm8960_reserve_table[p->memory_type].size += p->size;
+}
+
+static void __init reserve_pmem_memory(void)
+{
+#ifdef CONFIG_ANDROID_PMEM
+#ifndef CONFIG_MSM_MULTIMEDIA_USE_ION
+ reserve_memory_for(&android_pmem_adsp_pdata);
+ reserve_memory_for(&android_pmem_pdata);
+#endif
+ reserve_memory_for(&android_pmem_audio_pdata);
+ msm8960_reserve_table[MEMTYPE_EBI1].size += pmem_kernel_ebi1_size;
+#endif
+}
+
+static int msm8960_paddr_to_memtype(unsigned int paddr)
+{
+ return MEMTYPE_EBI1;
+}
+
+#ifdef CONFIG_ION_MSM
+static struct ion_platform_data ion_pdata = {
+ .nr = MSM_ION_HEAP_NUM,
+ .heaps = {
+ {
+ .id = ION_HEAP_SYSTEM_ID,
+ .type = ION_HEAP_TYPE_SYSTEM,
+ .name = ION_KMALLOC_HEAP_NAME,
+ },
+ {
+ .id = ION_HEAP_SYSTEM_CONTIG_ID,
+ .type = ION_HEAP_TYPE_SYSTEM_CONTIG,
+ .name = ION_VMALLOC_HEAP_NAME,
+ },
+#ifdef CONFIG_MSM_MULTIMEDIA_USE_ION
+ {
+ .id = ION_HEAP_EBI_ID,
+ .type = ION_HEAP_TYPE_CARVEOUT,
+ .name = ION_EBI1_HEAP_NAME,
+ .size = MSM_ION_EBI_SIZE,
+ .memory_type = ION_EBI_TYPE,
+ },
+ {
+ .id = ION_HEAP_ADSP_ID,
+ .type = ION_HEAP_TYPE_CARVEOUT,
+ .name = ION_ADSP_HEAP_NAME,
+ .size = MSM_ION_ADSP_SIZE,
+ .memory_type = ION_EBI_TYPE,
+ },
+ {
+ .id = ION_HEAP_IOMMU_ID,
+ .type = ION_HEAP_TYPE_IOMMU,
+ .name = ION_IOMMU_HEAP_NAME,
+ },
+#endif
+ }
+};
+
+static struct platform_device ion_dev = {
+ .name = "ion-msm",
+ .id = 1,
+ .dev = { .platform_data = &ion_pdata },
+};
+#endif
+
+static void reserve_ion_memory(void)
+{
+#if defined(CONFIG_ION_MSM) && defined(CONFIG_MSM_MULTIMEDIA_USE_ION)
+ msm8960_reserve_table[MEMTYPE_EBI1].size += MSM_ION_EBI_SIZE;
+ msm8960_reserve_table[MEMTYPE_EBI1].size += MSM_ION_ADSP_SIZE;
+#endif
+}
+static void __init msm8960_calculate_reserve_sizes(void)
+{
+ size_pmem_devices();
+ reserve_pmem_memory();
+ reserve_ion_memory();
+}
+
+static struct reserve_info msm8960_reserve_info __initdata = {
+ .memtype_reserve_table = msm8960_reserve_table,
+ .calculate_reserve_sizes = msm8960_calculate_reserve_sizes,
+ .paddr_to_memtype = msm8960_paddr_to_memtype,
+};
+
+static int msm8960_memory_bank_size(void)
+{
+ return 1<<29;
+}
+
+static void __init locate_unstable_memory(void)
+{
+ struct membank *mb = &meminfo.bank[meminfo.nr_banks - 1];
+ unsigned long bank_size;
+ unsigned long low, high;
+
+ bank_size = msm8960_memory_bank_size();
+ low = meminfo.bank[0].start;
+ high = mb->start + mb->size;
+
+ /* Check if 32 bit overflow occured */
+ if (high < mb->start)
+ high = ~0UL;
+
+ low &= ~(bank_size - 1);
+
+ if (high - low <= bank_size)
+ return;
+ msm8960_reserve_info.low_unstable_address = high -
+ MIN_MEMORY_BLOCK_SIZE;
+ msm8960_reserve_info.max_unstable_size = MIN_MEMORY_BLOCK_SIZE;
+
+ msm8960_reserve_info.bank_size = bank_size;
+ pr_info("low unstable address %lx max size %lx bank size %lx\n",
+ msm8960_reserve_info.low_unstable_address,
+ msm8960_reserve_info.max_unstable_size,
+ msm8960_reserve_info.bank_size);
+}
+
+static void __init place_movable_zone(void)
+{
+ movable_reserved_start = msm8960_reserve_info.low_unstable_address;
+ movable_reserved_size = msm8960_reserve_info.max_unstable_size;
+ pr_info("movable zone start %lx size %lx\n",
+ movable_reserved_start, movable_reserved_size);
+}
+
+static void __init msm8960_early_memory(void)
+{
+ reserve_info = &msm8960_reserve_info;
+ locate_unstable_memory();
+ place_movable_zone();
+}
+
+static void __init msm8960_reserve(void)
+{
+ msm_reserve();
+}
+
+static int msm8960_change_memory_power(u64 start, u64 size,
+ int change_type)
+{
+ return soc_change_memory_power(start, size, change_type);
+}
+
+static void __init msm8960_allocate_memory_regions(void)
+{
+ msm8960_allocate_fb_region();
+}
+
+#ifdef CONFIG_WCD9310_CODEC
+
+#define TABLA_INTERRUPT_BASE (NR_MSM_IRQS + NR_GPIO_IRQS + NR_PM8921_IRQS)
+
+/* Micbias setting is based on 8660 CDP/MTP/FLUID requirement
+ * 4 micbiases are used to power various analog and digital
+ * microphones operating at 1800 mV. Technically, all micbiases
+ * can source from single cfilter since all microphones operate
+ * at the same voltage level. The arrangement below is to make
+ * sure all cfilters are exercised. LDO_H regulator ouput level
+ * does not need to be as high as 2.85V. It is choosen for
+ * microphone sensitivity purpose.
+ */
+static struct tabla_pdata tabla_platform_data = {
+ .slimbus_slave_device = {
+ .name = "tabla-slave",
+ .e_addr = {0, 0, 0x10, 0, 0x17, 2},
+ },
+ .irq = MSM_GPIO_TO_INT(62),
+ .irq_base = TABLA_INTERRUPT_BASE,
+ .num_irqs = NR_TABLA_IRQS,
+ .reset_gpio = PM8921_GPIO_PM_TO_SYS(34),
+ .micbias = {
+ .ldoh_v = TABLA_LDOH_2P85_V,
+ .cfilt1_mv = 1800,
+ .cfilt2_mv = 1800,
+ .cfilt3_mv = 1800,
+ .bias1_cfilt_sel = TABLA_CFILT1_SEL,
+ .bias2_cfilt_sel = TABLA_CFILT2_SEL,
+ .bias3_cfilt_sel = TABLA_CFILT3_SEL,
+ .bias4_cfilt_sel = TABLA_CFILT3_SEL,
+ }
+};
+
+static struct slim_device msm_slim_tabla = {
+ .name = "tabla-slim",
+ .e_addr = {0, 1, 0x10, 0, 0x17, 2},
+ .dev = {
+ .platform_data = &tabla_platform_data,
+ },
+};
+
+static struct tabla_pdata tabla20_platform_data = {
+ .slimbus_slave_device = {
+ .name = "tabla-slave",
+ .e_addr = {0, 0, 0x60, 0, 0x17, 2},
+ },
+ .irq = MSM_GPIO_TO_INT(62),
+ .irq_base = TABLA_INTERRUPT_BASE,
+ .num_irqs = NR_TABLA_IRQS,
+ .reset_gpio = PM8921_GPIO_PM_TO_SYS(34),
+ .micbias = {
+ .ldoh_v = TABLA_LDOH_2P85_V,
+ .cfilt1_mv = 1800,
+ .cfilt2_mv = 1800,
+ .cfilt3_mv = 1800,
+ .bias1_cfilt_sel = TABLA_CFILT1_SEL,
+ .bias2_cfilt_sel = TABLA_CFILT2_SEL,
+ .bias3_cfilt_sel = TABLA_CFILT3_SEL,
+ .bias4_cfilt_sel = TABLA_CFILT3_SEL,
+ }
+};
+
+static struct slim_device msm_slim_tabla20 = {
+ .name = "tabla2x-slim",
+ .e_addr = {0, 1, 0x60, 0, 0x17, 2},
+ .dev = {
+ .platform_data = &tabla20_platform_data,
+ },
+};
+#endif
+
+static struct slim_boardinfo msm_slim_devices[] = {
+#ifdef CONFIG_WCD9310_CODEC
+ {
+ .bus_num = 1,
+ .slim_slave = &msm_slim_tabla,
+ },
+ {
+ .bus_num = 1,
+ .slim_slave = &msm_slim_tabla20,
+ },
+#endif
+ /* add more slimbus slaves as needed */
+};
+
+#define MSM_WCNSS_PHYS 0x03000000
+#define MSM_WCNSS_SIZE 0x280000
+
+static struct resource resources_wcnss_wlan[] = {
+ {
+ .start = RIVA_APPS_WLAN_RX_DATA_AVAIL_IRQ,
+ .end = RIVA_APPS_WLAN_RX_DATA_AVAIL_IRQ,
+ .name = "wcnss_wlanrx_irq",
+ .flags = IORESOURCE_IRQ,
+ },
+ {
+ .start = RIVA_APPS_WLAN_DATA_XFER_DONE_IRQ,
+ .end = RIVA_APPS_WLAN_DATA_XFER_DONE_IRQ,
+ .name = "wcnss_wlantx_irq",
+ .flags = IORESOURCE_IRQ,
+ },
+ {
+ .start = MSM_WCNSS_PHYS,
+ .end = MSM_WCNSS_PHYS + MSM_WCNSS_SIZE - 1,
+ .name = "wcnss_mmio",
+ .flags = IORESOURCE_MEM,
+ },
+ {
+ .start = 84,
+ .end = 88,
+ .name = "wcnss_gpios_5wire",
+ .flags = IORESOURCE_IO,
+ },
+};
+
+static struct qcom_wcnss_opts qcom_wcnss_pdata = {
+ .has_48mhz_xo = 1,
+};
+
+static struct platform_device msm_device_wcnss_wlan = {
+ .name = "wcnss_wlan",
+ .id = 0,
+ .num_resources = ARRAY_SIZE(resources_wcnss_wlan),
+ .resource = resources_wcnss_wlan,
+ .dev = {.platform_data = &qcom_wcnss_pdata},
+};
+
+#if defined(CONFIG_CRYPTO_DEV_QCRYPTO) || \
+ defined(CONFIG_CRYPTO_DEV_QCRYPTO_MODULE) || \
+ defined(CONFIG_CRYPTO_DEV_QCEDEV) || \
+ defined(CONFIG_CRYPTO_DEV_QCEDEV_MODULE)
+
+#define QCE_SIZE 0x10000
+#define QCE_0_BASE 0x18500000
+
+#define QCE_HW_KEY_SUPPORT 0
+#define QCE_SHA_HMAC_SUPPORT 1
+#define QCE_SHARE_CE_RESOURCE 1
+#define QCE_CE_SHARED 0
+
+static struct resource qcrypto_resources[] = {
+ [0] = {
+ .start = QCE_0_BASE,
+ .end = QCE_0_BASE + QCE_SIZE - 1,
+ .flags = IORESOURCE_MEM,
+ },
+ [1] = {
+ .name = "crypto_channels",
+ .start = DMOV_CE_IN_CHAN,
+ .end = DMOV_CE_OUT_CHAN,
+ .flags = IORESOURCE_DMA,
+ },
+ [2] = {
+ .name = "crypto_crci_in",
+ .start = DMOV_CE_IN_CRCI,
+ .end = DMOV_CE_IN_CRCI,
+ .flags = IORESOURCE_DMA,
+ },
+ [3] = {
+ .name = "crypto_crci_out",
+ .start = DMOV_CE_OUT_CRCI,
+ .end = DMOV_CE_OUT_CRCI,
+ .flags = IORESOURCE_DMA,
+ },
+};
+
+static struct resource qcedev_resources[] = {
+ [0] = {
+ .start = QCE_0_BASE,
+ .end = QCE_0_BASE + QCE_SIZE - 1,
+ .flags = IORESOURCE_MEM,
+ },
+ [1] = {
+ .name = "crypto_channels",
+ .start = DMOV_CE_IN_CHAN,
+ .end = DMOV_CE_OUT_CHAN,
+ .flags = IORESOURCE_DMA,
+ },
+ [2] = {
+ .name = "crypto_crci_in",
+ .start = DMOV_CE_IN_CRCI,
+ .end = DMOV_CE_IN_CRCI,
+ .flags = IORESOURCE_DMA,
+ },
+ [3] = {
+ .name = "crypto_crci_out",
+ .start = DMOV_CE_OUT_CRCI,
+ .end = DMOV_CE_OUT_CRCI,
+ .flags = IORESOURCE_DMA,
+ },
+};
+
+#endif
+
+#if defined(CONFIG_CRYPTO_DEV_QCRYPTO) || \
+ defined(CONFIG_CRYPTO_DEV_QCRYPTO_MODULE)
+
+static struct msm_ce_hw_support qcrypto_ce_hw_suppport = {
+ .ce_shared = QCE_CE_SHARED,
+ .shared_ce_resource = QCE_SHARE_CE_RESOURCE,
+ .hw_key_support = QCE_HW_KEY_SUPPORT,
+ .sha_hmac = QCE_SHA_HMAC_SUPPORT,
+};
+
+static struct platform_device qcrypto_device = {
+ .name = "qcrypto",
+ .id = 0,
+ .num_resources = ARRAY_SIZE(qcrypto_resources),
+ .resource = qcrypto_resources,
+ .dev = {
+ .coherent_dma_mask = DMA_BIT_MASK(32),
+ .platform_data = &qcrypto_ce_hw_suppport,
+ },
+};
+#endif
+
+#if defined(CONFIG_CRYPTO_DEV_QCEDEV) || \
+ defined(CONFIG_CRYPTO_DEV_QCEDEV_MODULE)
+
+static struct msm_ce_hw_support qcedev_ce_hw_suppport = {
+ .ce_shared = QCE_CE_SHARED,
+ .shared_ce_resource = QCE_SHARE_CE_RESOURCE,
+ .hw_key_support = QCE_HW_KEY_SUPPORT,
+ .sha_hmac = QCE_SHA_HMAC_SUPPORT,
+};
+
+static struct platform_device qcedev_device = {
+ .name = "qce",
+ .id = 0,
+ .num_resources = ARRAY_SIZE(qcedev_resources),
+ .resource = qcedev_resources,
+ .dev = {
+ .coherent_dma_mask = DMA_BIT_MASK(32),
+ .platform_data = &qcedev_ce_hw_suppport,
+ },
+};
+#endif
+
+#define MDM2AP_ERRFATAL 70
+#define AP2MDM_ERRFATAL 95
+#define MDM2AP_STATUS 69
+#define AP2MDM_STATUS 94
+#define AP2MDM_PMIC_RESET_N 80
+#define AP2MDM_KPDPWR_N 81
+
+static struct resource mdm_resources[] = {
+ {
+ .start = MDM2AP_ERRFATAL,
+ .end = MDM2AP_ERRFATAL,
+ .name = "MDM2AP_ERRFATAL",
+ .flags = IORESOURCE_IO,
+ },
+ {
+ .start = AP2MDM_ERRFATAL,
+ .end = AP2MDM_ERRFATAL,
+ .name = "AP2MDM_ERRFATAL",
+ .flags = IORESOURCE_IO,
+ },
+ {
+ .start = MDM2AP_STATUS,
+ .end = MDM2AP_STATUS,
+ .name = "MDM2AP_STATUS",
+ .flags = IORESOURCE_IO,
+ },
+ {
+ .start = AP2MDM_STATUS,
+ .end = AP2MDM_STATUS,
+ .name = "AP2MDM_STATUS",
+ .flags = IORESOURCE_IO,
+ },
+ {
+ .start = AP2MDM_PMIC_RESET_N,
+ .end = AP2MDM_PMIC_RESET_N,
+ .name = "AP2MDM_PMIC_RESET_N",
+ .flags = IORESOURCE_IO,
+ },
+ {
+ .start = AP2MDM_KPDPWR_N,
+ .end = AP2MDM_KPDPWR_N,
+ .name = "AP2MDM_KPDPWR_N",
+ .flags = IORESOURCE_IO,
+ },
+};
+
+static struct mdm_platform_data mdm_platform_data = {
+ .mdm_version = "2.5",
+};
+
+static struct platform_device mdm_device = {
+ .name = "mdm2_modem",
+ .id = -1,
+ .num_resources = ARRAY_SIZE(mdm_resources),
+ .resource = mdm_resources,
+ .dev = {
+ .platform_data = &mdm_platform_data,
+ },
+};
+
+static struct platform_device *mdm_devices[] __initdata = {
+ &mdm_device,
+};
+
+#define MSM_SHARED_RAM_PHYS 0x80000000
+
+static void __init msm8960_map_io(void)
+{
+ msm_shared_ram_phys = MSM_SHARED_RAM_PHYS;
+ msm_map_msm8960_io();
+
+ if (socinfo_init() < 0)
+ pr_err("socinfo_init() failed!\n");
+}
+
+static void __init msm8960_init_irq(void)
+{
+ unsigned int i;
+
+ msm_mpm_irq_extn_init();
+ gic_init(0, GIC_PPI_START, MSM_QGIC_DIST_BASE,
+ (void *)MSM_QGIC_CPU_BASE);
+
+ /* Edge trigger PPIs except AVS_SVICINT and AVS_SVICINTSWDONE */
+ writel_relaxed(0xFFFFD7FF, MSM_QGIC_DIST_BASE + GIC_DIST_CONFIG + 4);
+
+ writel_relaxed(0x0000FFFF, MSM_QGIC_DIST_BASE + GIC_DIST_ENABLE_SET);
+ mb();
+
+ /* FIXME: Not installing AVS_SVICINT and AVS_SVICINTSWDONE yet
+ * as they are configured as level, which does not play nice with
+ * handle_percpu_irq.
+ */
+ for (i = GIC_PPI_START; i < GIC_SPI_START; i++) {
+ if (i != AVS_SVICINT && i != AVS_SVICINTSWDONE)
+ irq_set_handler(i, handle_percpu_irq);
+ }
+}
+
+static void __init msm8960_init_buses(void)
+{
+#ifdef CONFIG_MSM_BUS_SCALING
+ msm_bus_rpm_set_mt_mask();
+ msm_bus_8960_apps_fabric_pdata.rpm_enabled = 1;
+ msm_bus_8960_sys_fabric_pdata.rpm_enabled = 1;
+ msm_bus_8960_mm_fabric_pdata.rpm_enabled = 1;
+ msm_bus_apps_fabric.dev.platform_data =
+ &msm_bus_8960_apps_fabric_pdata;
+ msm_bus_sys_fabric.dev.platform_data = &msm_bus_8960_sys_fabric_pdata;
+ msm_bus_mm_fabric.dev.platform_data = &msm_bus_8960_mm_fabric_pdata;
+ msm_bus_sys_fpb.dev.platform_data = &msm_bus_8960_sys_fpb_pdata;
+ msm_bus_cpss_fpb.dev.platform_data = &msm_bus_8960_cpss_fpb_pdata;
+#endif
+}
+
+static struct msm_spi_platform_data msm8960_qup_spi_gsbi1_pdata = {
+ .max_clock_speed = 15060000,
+};
+
+#ifdef CONFIG_USB_MSM_OTG_72K
+static struct msm_otg_platform_data msm_otg_pdata;
+#else
+#define USB_5V_EN 42
+static void msm_hsusb_vbus_power(bool on)
+{
+ int rc;
+ static bool vbus_is_on;
+ static struct regulator *mvs_otg_switch;
+
+ if (vbus_is_on == on)
+ return;
+
+ if (on) {
+ mvs_otg_switch = regulator_get(&msm8960_device_otg.dev,
+ "vbus_otg");
+ if (IS_ERR(mvs_otg_switch)) {
+ pr_err("Unable to get mvs_otg_switch\n");
+ return;
+ }
+
+ rc = gpio_request(PM8921_GPIO_PM_TO_SYS(USB_5V_EN),
+ "usb_5v_en");
+ if (rc < 0) {
+ pr_err("failed to request usb_5v_en gpio\n");
+ goto put_mvs_otg;
+ }
+
+ rc = gpio_direction_output(PM8921_GPIO_PM_TO_SYS(USB_5V_EN), 1);
+ if (rc) {
+ pr_err("%s: unable to set_direction for gpio [%d]\n",
+ __func__, PM8921_GPIO_PM_TO_SYS(USB_5V_EN));
+ goto free_usb_5v_en;
+ }
+
+ if (regulator_enable(mvs_otg_switch)) {
+ pr_err("unable to enable mvs_otg_switch\n");
+ goto err_ldo_gpio_set_dir;
+ }
+
+ vbus_is_on = true;
+ return;
+ }
+ regulator_disable(mvs_otg_switch);
+err_ldo_gpio_set_dir:
+ gpio_set_value(PM8921_GPIO_PM_TO_SYS(USB_5V_EN), 0);
+free_usb_5v_en:
+ gpio_free(PM8921_GPIO_PM_TO_SYS(USB_5V_EN));
+put_mvs_otg:
+ regulator_put(mvs_otg_switch);
+ vbus_is_on = false;
+}
+
+static int wr_phy_init_seq[] = {
+ 0x44, 0x80, /* set VBUS valid threshold
+ and disconnect valid threshold */
+ 0x38, 0x81, /* update DC voltage level */
+ 0x14, 0x82, /* set preemphasis and rise/fall time */
+ 0x13, 0x83, /* set source impedance adjusment */
+ -1};
+
+static int liquid_v1_phy_init_seq[] = {
+ 0x44, 0x80,/* set VBUS valid threshold
+ and disconnect valid threshold */
+ 0x3C, 0x81,/* update DC voltage level */
+ 0x18, 0x82,/* set preemphasis and rise/fall time */
+ 0x23, 0x83,/* set source impedance sdjusment */
+ -1};
+
+static struct msm_otg_platform_data msm_otg_pdata = {
+ .mode = USB_OTG,
+ .otg_control = OTG_PMIC_CONTROL,
+ .phy_type = SNPS_28NM_INTEGRATED_PHY,
+ .pclk_src_name = "dfab_usb_hs_clk",
+ .pmic_id_irq = PM8921_USB_ID_IN_IRQ(PM8921_IRQ_BASE),
+ .vbus_power = msm_hsusb_vbus_power,
+ .power_budget = 750,
+};
+#endif
+
+#ifdef CONFIG_USB_EHCI_MSM_HSIC
+#define HSIC_HUB_RESET_GPIO 91
+static struct msm_hsic_host_platform_data msm_hsic_pdata = {
+ .strobe = 150,
+ .data = 151,
+};
+#else
+static struct msm_hsic_host_platform_data msm_hsic_pdata;
+#endif
+
+#define PID_MAGIC_ID 0x71432909
+#define SERIAL_NUM_MAGIC_ID 0x61945374
+#define SERIAL_NUMBER_LENGTH 127
+#define DLOAD_USB_BASE_ADD 0x2A03F0C8
+
+struct magic_num_struct {
+ uint32_t pid;
+ uint32_t serial_num;
+};
+
+struct dload_struct {
+ uint32_t reserved1;
+ uint32_t reserved2;
+ uint32_t reserved3;
+ uint16_t reserved4;
+ uint16_t pid;
+ char serial_number[SERIAL_NUMBER_LENGTH];
+ uint16_t reserved5;
+ struct magic_num_struct magic_struct;
+};
+
+static int usb_diag_update_pid_and_serial_num(uint32_t pid, const char *snum)
+{
+ struct dload_struct __iomem *dload = 0;
+
+ dload = ioremap(DLOAD_USB_BASE_ADD, sizeof(*dload));
+ if (!dload) {
+ pr_err("%s: cannot remap I/O memory region: %08x\n",
+ __func__, DLOAD_USB_BASE_ADD);
+ return -ENXIO;
+ }
+
+ pr_debug("%s: dload:%p pid:%x serial_num:%s\n",
+ __func__, dload, pid, snum);
+ /* update pid */
+ dload->magic_struct.pid = PID_MAGIC_ID;
+ dload->pid = pid;
+
+ /* update serial number */
+ dload->magic_struct.serial_num = 0;
+ if (!snum) {
+ memset(dload->serial_number, 0, SERIAL_NUMBER_LENGTH);
+ goto out;
+ }
+
+ dload->magic_struct.serial_num = SERIAL_NUM_MAGIC_ID;
+ strlcpy(dload->serial_number, snum, SERIAL_NUMBER_LENGTH);
+out:
+ iounmap(dload);
+ return 0;
+}
+
+static struct android_usb_platform_data android_usb_pdata = {
+ .update_pid_and_serial_num = usb_diag_update_pid_and_serial_num,
+};
+
+static struct platform_device android_usb_device = {
+ .name = "android_usb",
+ .id = -1,
+ .dev = {
+ .platform_data = &android_usb_pdata,
+ },
+};
+
+static uint8_t spm_wfi_cmd_sequence[] __initdata = {
+ 0x03, 0x0f,
+};
+
+static uint8_t spm_power_collapse_without_rpm[] __initdata = {
+ 0x00, 0x24, 0x54, 0x10,
+ 0x09, 0x03, 0x01,
+ 0x10, 0x54, 0x30, 0x0C,
+ 0x24, 0x30, 0x0f,
+};
+
+static uint8_t spm_power_collapse_with_rpm[] __initdata = {
+ 0x00, 0x24, 0x54, 0x10,
+ 0x09, 0x07, 0x01, 0x0B,
+ 0x10, 0x54, 0x30, 0x0C,
+ 0x24, 0x30, 0x0f,
+};
+
+static struct msm_spm_seq_entry msm_spm_seq_list[] __initdata = {
+ [0] = {
+ .mode = MSM_SPM_MODE_CLOCK_GATING,
+ .notify_rpm = false,
+ .cmd = spm_wfi_cmd_sequence,
+ },
+ [1] = {
+ .mode = MSM_SPM_MODE_POWER_COLLAPSE,
+ .notify_rpm = false,
+ .cmd = spm_power_collapse_without_rpm,
+ },
+ [2] = {
+ .mode = MSM_SPM_MODE_POWER_COLLAPSE,
+ .notify_rpm = true,
+ .cmd = spm_power_collapse_with_rpm,
+ },
+};
+
+static struct msm_spm_platform_data msm_spm_data[] __initdata = {
+ [0] = {
+ .reg_base_addr = MSM_SAW0_BASE,
+ .reg_init_values[MSM_SPM_REG_SAW2_SECURE] = 0x00,
+ .reg_init_values[MSM_SPM_REG_SAW2_CFG] = 0x1F,
+ .reg_init_values[MSM_SPM_REG_SAW2_VCTL] = 0x9C,
+#if defined(CONFIG_MSM_AVS_HW)
+ .reg_init_values[MSM_SPM_REG_SAW2_AVS_CTL] = 0x00,
+ .reg_init_values[MSM_SPM_REG_SAW2_AVS_HYSTERESIS] = 0x00,
+#endif
+ .reg_init_values[MSM_SPM_REG_SAW2_SPM_CTL] = 0x01,
+ .reg_init_values[MSM_SPM_REG_SAW2_PMIC_DLY] = 0x02020202,
+ .reg_init_values[MSM_SPM_REG_SAW2_PMIC_DATA_0] = 0x0060009C,
+ .reg_init_values[MSM_SPM_REG_SAW2_PMIC_DATA_1] = 0x0000001C,
+ .vctl_timeout_us = 50,
+ .num_modes = ARRAY_SIZE(msm_spm_seq_list),
+ .modes = msm_spm_seq_list,
+ },
+ [1] = {
+ .reg_base_addr = MSM_SAW1_BASE,
+ .reg_init_values[MSM_SPM_REG_SAW2_SECURE] = 0x00,
+ .reg_init_values[MSM_SPM_REG_SAW2_CFG] = 0x1F,
+ .reg_init_values[MSM_SPM_REG_SAW2_VCTL] = 0x9C,
+#if defined(CONFIG_MSM_AVS_HW)
+ .reg_init_values[MSM_SPM_REG_SAW2_AVS_CTL] = 0x00,
+ .reg_init_values[MSM_SPM_REG_SAW2_AVS_HYSTERESIS] = 0x00,
+#endif
+ .reg_init_values[MSM_SPM_REG_SAW2_SPM_CTL] = 0x01,
+ .reg_init_values[MSM_SPM_REG_SAW2_PMIC_DLY] = 0x02020202,
+ .reg_init_values[MSM_SPM_REG_SAW2_PMIC_DATA_0] = 0x0060009C,
+ .reg_init_values[MSM_SPM_REG_SAW2_PMIC_DATA_1] = 0x0000001C,
+ .vctl_timeout_us = 50,
+ .num_modes = ARRAY_SIZE(msm_spm_seq_list),
+ .modes = msm_spm_seq_list,
+ },
+};
+
+static uint8_t l2_spm_wfi_cmd_sequence[] __initdata = {
+ 0x00, 0x20, 0x03, 0x20,
+ 0x00, 0x0f,
+};
+
+static uint8_t l2_spm_gdhs_cmd_sequence[] __initdata = {
+ 0x00, 0x20, 0x34, 0x64,
+ 0x48, 0x07, 0x48, 0x20,
+ 0x50, 0x64, 0x04, 0x34,
+ 0x50, 0x0f,
+};
+static uint8_t l2_spm_power_off_cmd_sequence[] __initdata = {
+ 0x00, 0x10, 0x34, 0x64,
+ 0x48, 0x07, 0x48, 0x10,
+ 0x50, 0x64, 0x04, 0x34,
+ 0x50, 0x0F,
+};
+
+static struct msm_spm_seq_entry msm_spm_l2_seq_list[] __initdata = {
+ [0] = {
+ .mode = MSM_SPM_L2_MODE_RETENTION,
+ .notify_rpm = false,
+ .cmd = l2_spm_wfi_cmd_sequence,
+ },
+ [1] = {
+ .mode = MSM_SPM_L2_MODE_GDHS,
+ .notify_rpm = true,
+ .cmd = l2_spm_gdhs_cmd_sequence,
+ },
+ [2] = {
+ .mode = MSM_SPM_L2_MODE_POWER_COLLAPSE,
+ .notify_rpm = true,
+ .cmd = l2_spm_power_off_cmd_sequence,
+ },
+};
+
+static struct msm_spm_platform_data msm_spm_l2_data[] __initdata = {
+ [0] = {
+ .reg_base_addr = MSM_SAW_L2_BASE,
+ .reg_init_values[MSM_SPM_REG_SAW2_SECURE] = 0x00,
+ .reg_init_values[MSM_SPM_REG_SAW2_SPM_CTL] = 0x00,
+ .reg_init_values[MSM_SPM_REG_SAW2_PMIC_DLY] = 0x02020202,
+ .reg_init_values[MSM_SPM_REG_SAW2_PMIC_DATA_0] = 0x00A000AE,
+ .reg_init_values[MSM_SPM_REG_SAW2_PMIC_DATA_1] = 0x00A00020,
+ .modes = msm_spm_l2_seq_list,
+ .num_modes = ARRAY_SIZE(msm_spm_l2_seq_list),
+ },
+};
+
+#define PM_HAP_EN_GPIO PM8921_GPIO_PM_TO_SYS(33)
+#define PM_HAP_LEN_GPIO PM8921_GPIO_PM_TO_SYS(20)
+
+static struct msm_xo_voter *xo_handle_d1;
+
+static int isa1200_power(int on)
+{
+ int rc = 0;
+
+ gpio_set_value(HAP_SHIFT_LVL_OE_GPIO, !!on);
+
+ rc = on ? msm_xo_mode_vote(xo_handle_d1, MSM_XO_MODE_ON) :
+ msm_xo_mode_vote(xo_handle_d1, MSM_XO_MODE_OFF);
+ if (rc < 0) {
+ pr_err("%s: failed to %svote for TCXO D1 buffer%d\n",
+ __func__, on ? "" : "de-", rc);
+ goto err_xo_vote;
+ }
+
+ return 0;
+
+err_xo_vote:
+ gpio_set_value(HAP_SHIFT_LVL_OE_GPIO, !on);
+ return rc;
+}
+
+static int isa1200_dev_setup(bool enable)
+{
+ int rc = 0;
+
+ struct pm_gpio hap_gpio_config = {
+ .direction = PM_GPIO_DIR_OUT,
+ .pull = PM_GPIO_PULL_NO,
+ .out_strength = PM_GPIO_STRENGTH_HIGH,
+ .function = PM_GPIO_FUNC_NORMAL,
+ .inv_int_pol = 0,
+ .vin_sel = 2,
+ .output_buffer = PM_GPIO_OUT_BUF_CMOS,
+ .output_value = 0,
+ };
+
+ if (enable == true) {
+ rc = pm8xxx_gpio_config(PM_HAP_EN_GPIO, &hap_gpio_config);
+ if (rc) {
+ pr_err("%s: pm8921 gpio %d config failed(%d)\n",
+ __func__, PM_HAP_EN_GPIO, rc);
+ return rc;
+ }
+
+ rc = pm8xxx_gpio_config(PM_HAP_LEN_GPIO, &hap_gpio_config);
+ if (rc) {
+ pr_err("%s: pm8921 gpio %d config failed(%d)\n",
+ __func__, PM_HAP_LEN_GPIO, rc);
+ return rc;
+ }
+
+ rc = gpio_request(HAP_SHIFT_LVL_OE_GPIO, "hap_shft_lvl_oe");
+ if (rc) {
+ pr_err("%s: unable to request gpio %d (%d)\n",
+ __func__, HAP_SHIFT_LVL_OE_GPIO, rc);
+ return rc;
+ }
+
+ rc = gpio_direction_output(HAP_SHIFT_LVL_OE_GPIO, 0);
+ if (rc) {
+ pr_err("%s: Unable to set direction\n", __func__);
+ goto free_gpio;
+ }
+
+ xo_handle_d1 = msm_xo_get(MSM_XO_TCXO_D1, "isa1200");
+ if (IS_ERR(xo_handle_d1)) {
+ rc = PTR_ERR(xo_handle_d1);
+ pr_err("%s: failed to get the handle for D1(%d)\n",
+ __func__, rc);
+ goto gpio_set_dir;
+ }
+ } else {
+ gpio_free(HAP_SHIFT_LVL_OE_GPIO);
+
+ msm_xo_put(xo_handle_d1);
+ }
+
+ return 0;
+
+gpio_set_dir:
+ gpio_set_value(HAP_SHIFT_LVL_OE_GPIO, 0);
+free_gpio:
+ gpio_free(HAP_SHIFT_LVL_OE_GPIO);
+ return rc;
+}
+
+static struct isa1200_regulator isa1200_reg_data[] = {
+ {
+ .name = "vcc_i2c",
+ .min_uV = ISA_I2C_VTG_MIN_UV,
+ .max_uV = ISA_I2C_VTG_MAX_UV,
+ .load_uA = ISA_I2C_CURR_UA,
+ },
+};
+
+static struct isa1200_platform_data isa1200_1_pdata = {
+ .name = "vibrator",
+ .dev_setup = isa1200_dev_setup,
+ .power_on = isa1200_power,
+ .hap_en_gpio = PM_HAP_EN_GPIO,
+ .hap_len_gpio = PM_HAP_LEN_GPIO,
+ .max_timeout = 15000,
+ .mode_ctrl = PWM_GEN_MODE,
+ .pwm_fd = {
+ .pwm_div = 256,
+ },
+ .is_erm = false,
+ .smart_en = true,
+ .ext_clk_en = true,
+ .chip_en = 1,
+ .regulator_info = isa1200_reg_data,
+ .num_regulators = ARRAY_SIZE(isa1200_reg_data),
+};
+
+static struct i2c_board_info msm_isa1200_board_info[] __initdata = {
+ {
+ I2C_BOARD_INFO("isa1200_1", 0x90>>1),
+ .platform_data = &isa1200_1_pdata,
+ },
+};
+
+#define CYTTSP_TS_GPIO_IRQ 11
+#define CYTTSP_TS_SLEEP_GPIO 50
+#define CYTTSP_TS_RESOUT_N_GPIO 52
+
+/*virtual key support */
+static ssize_t tma340_vkeys_show(struct kobject *kobj,
+ struct kobj_attribute *attr, char *buf)
+{
+ return snprintf(buf, 200,
+ __stringify(EV_KEY) ":" __stringify(KEY_BACK) ":73:1120:97:97"
+ ":" __stringify(EV_KEY) ":" __stringify(KEY_MENU) ":230:1120:97:97"
+ ":" __stringify(EV_KEY) ":" __stringify(KEY_HOME) ":389:1120:97:97"
+ ":" __stringify(EV_KEY) ":" __stringify(KEY_SEARCH) ":544:1120:97:97"
+ "\n");
+}
+
+static struct kobj_attribute tma340_vkeys_attr = {
+ .attr = {
+ .mode = S_IRUGO,
+ },
+ .show = &tma340_vkeys_show,
+};
+
+static struct attribute *tma340_properties_attrs[] = {
+ &tma340_vkeys_attr.attr,
+ NULL
+};
+
+static struct attribute_group tma340_properties_attr_group = {
+ .attrs = tma340_properties_attrs,
+};
+
+
+static int cyttsp_platform_init(struct i2c_client *client)
+{
+ int rc = 0;
+ static struct kobject *tma340_properties_kobj;
+
+ tma340_vkeys_attr.attr.name = "virtualkeys.cyttsp-i2c";
+ tma340_properties_kobj = kobject_create_and_add("board_properties",
+ NULL);
+ if (tma340_properties_kobj)
+ rc = sysfs_create_group(tma340_properties_kobj,
+ &tma340_properties_attr_group);
+ if (!tma340_properties_kobj || rc)
+ pr_err("%s: failed to create board_properties\n",
+ __func__);
+
+ return 0;
+}
+
+static struct cyttsp_regulator regulator_data[] = {
+ {
+ .name = "vdd",
+ .min_uV = CY_TMA300_VTG_MIN_UV,
+ .max_uV = CY_TMA300_VTG_MAX_UV,
+ .hpm_load_uA = CY_TMA300_CURR_24HZ_UA,
+ .lpm_load_uA = CY_TMA300_SLEEP_CURR_UA,
+ },
+ /* TODO: Remove after runtime PM is enabled in I2C driver */
+ {
+ .name = "vcc_i2c",
+ .min_uV = CY_I2C_VTG_MIN_UV,
+ .max_uV = CY_I2C_VTG_MAX_UV,
+ .hpm_load_uA = CY_I2C_CURR_UA,
+ .lpm_load_uA = CY_I2C_SLEEP_CURR_UA,
+ },
+};
+
+static struct cyttsp_platform_data cyttsp_pdata = {
+ .panel_maxx = 634,
+ .panel_maxy = 1166,
+ .disp_maxx = 616,
+ .disp_maxy = 1023,
+ .disp_minx = 0,
+ .disp_miny = 16,
+ .flags = 0x01,
+ .gen = CY_GEN3, /* or */
+ .use_st = CY_USE_ST,
+ .use_mt = CY_USE_MT,
+ .use_hndshk = CY_SEND_HNDSHK,
+ .use_trk_id = CY_USE_TRACKING_ID,
+ .use_sleep = CY_USE_DEEP_SLEEP_SEL | CY_USE_LOW_POWER_SEL,
+ .use_gestures = CY_USE_GESTURES,
+ .fw_fname = "cyttsp_8960_cdp.hex",
+ /* activate up to 4 groups
+ * and set active distance
+ */
+ .gest_set = CY_GEST_GRP1 | CY_GEST_GRP2 |
+ CY_GEST_GRP3 | CY_GEST_GRP4 |
+ CY_ACT_DIST,
+ /* change act_intrvl to customize the Active power state
+ * scanning/processing refresh interval for Operating mode
+ */
+ .act_intrvl = CY_ACT_INTRVL_DFLT,
+ /* change tch_tmout to customize the touch timeout for the
+ * Active power state for Operating mode
+ */
+ .tch_tmout = CY_TCH_TMOUT_DFLT,
+ /* change lp_intrvl to customize the Low Power power state
+ * scanning/processing refresh interval for Operating mode
+ */
+ .lp_intrvl = CY_LP_INTRVL_DFLT,
+ .sleep_gpio = CYTTSP_TS_SLEEP_GPIO,
+ .resout_gpio = CYTTSP_TS_RESOUT_N_GPIO,
+ .irq_gpio = CYTTSP_TS_GPIO_IRQ,
+ .regulator_info = regulator_data,
+ .num_regulators = ARRAY_SIZE(regulator_data),
+ .init = cyttsp_platform_init,
+ .correct_fw_ver = 9,
+};
+
+static struct i2c_board_info cyttsp_info[] __initdata = {
+ {
+ I2C_BOARD_INFO(CY_I2C_NAME, 0x24),
+ .platform_data = &cyttsp_pdata,
+#ifndef CY_USE_TIMER
+ .irq = MSM_GPIO_TO_INT(CYTTSP_TS_GPIO_IRQ),
+#endif /* CY_USE_TIMER */
+ },
+};
+
+/* configuration data */
+static const u8 mxt_config_data[] = {
+ /* T6 Object */
+ 0, 0, 0, 0, 0, 0,
+ /* T38 Object */
+ 11, 2, 0, 11, 11, 11, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0,
+ /* T7 Object */
+ 100, 16, 50,
+ /* T8 Object */
+ 8, 0, 0, 0, 0, 0, 8, 14, 50, 215,
+ /* T9 Object */
+ 131, 0, 0, 26, 42, 0, 32, 63, 3, 5,
+ 0, 2, 1, 113, 10, 10, 8, 10, 255, 2,
+ 85, 5, 0, 0, 20, 20, 75, 25, 202, 29,
+ 10, 10, 45, 46,
+ /* T15 Object */
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0,
+ /* T22 Object */
+ 5, 0, 0, 0, 0, 0, 0, 0, 30, 0,
+ 0, 0, 5, 8, 10, 13, 0,
+ /* T24 Object */
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ /* T25 Object */
+ 3, 0, 188, 52, 52, 33, 0, 0, 0, 0,
+ 0, 0, 0, 0,
+ /* T27 Object */
+ 0, 0, 0, 0, 0, 0, 0,
+ /* T28 Object */
+ 0, 0, 0, 8, 12, 60,
+ /* T40 Object */
+ 0, 0, 0, 0, 0,
+ /* T41 Object */
+ 0, 0, 0, 0, 0, 0,
+ /* T43 Object */
+ 0, 0, 0, 0, 0, 0,
+};
+
+#define MXT_TS_GPIO_IRQ 11
+#define MXT_TS_LDO_EN_GPIO 50
+#define MXT_TS_RESET_GPIO 52
+
+static void mxt_init_hw_liquid(void)
+{
+ int rc;
+
+ rc = gpio_request(MXT_TS_GPIO_IRQ, "mxt_ts_irq_gpio");
+ if (rc) {
+ pr_err("%s: unable to request mxt_ts_irq gpio [%d]\n",
+ __func__, MXT_TS_GPIO_IRQ);
+ return;
+ }
+
+ rc = gpio_direction_input(MXT_TS_GPIO_IRQ);
+ if (rc) {
+ pr_err("%s: unable to set_direction for mxt_ts_irq gpio [%d]\n",
+ __func__, MXT_TS_GPIO_IRQ);
+ goto err_irq_gpio_req;
+ }
+
+ rc = gpio_request(MXT_TS_LDO_EN_GPIO, "mxt_ldo_en_gpio");
+ if (rc) {
+ pr_err("%s: unable to request mxt_ldo_en gpio [%d]\n",
+ __func__, MXT_TS_LDO_EN_GPIO);
+ goto err_irq_gpio_req;
+ }
+
+ rc = gpio_direction_output(MXT_TS_LDO_EN_GPIO, 1);
+ if (rc) {
+ pr_err("%s: unable to set_direction for mxt_ldo_en gpio [%d]\n",
+ __func__, MXT_TS_LDO_EN_GPIO);
+ goto err_ldo_gpio_req;
+ }
+
+ rc = gpio_request(MXT_TS_RESET_GPIO, "mxt_reset_gpio");
+ if (rc) {
+ pr_err("%s: unable to request mxt_reset gpio [%d]\n",
+ __func__, MXT_TS_RESET_GPIO);
+ goto err_ldo_gpio_set_dir;
+ }
+
+ rc = gpio_direction_output(MXT_TS_RESET_GPIO, 1);
+ if (rc) {
+ pr_err("%s: unable to set_direction for mxt_reset gpio [%d]\n",
+ __func__, MXT_TS_RESET_GPIO);
+ goto err_reset_gpio_req;
+ }
+
+ return;
+
+err_reset_gpio_req:
+ gpio_free(MXT_TS_RESET_GPIO);
+err_ldo_gpio_set_dir:
+ gpio_set_value(MXT_TS_LDO_EN_GPIO, 0);
+err_ldo_gpio_req:
+ gpio_free(MXT_TS_LDO_EN_GPIO);
+err_irq_gpio_req:
+ gpio_free(MXT_TS_GPIO_IRQ);
+}
+
+static struct mxt_platform_data mxt_platform_data = {
+ .config = mxt_config_data,
+ .config_length = ARRAY_SIZE(mxt_config_data),
+ .x_size = 1365,
+ .y_size = 767,
+ .irqflags = IRQF_TRIGGER_FALLING,
+ .i2c_pull_up = true,
+};
+
+static struct i2c_board_info mxt_device_info[] __initdata = {
+ {
+ I2C_BOARD_INFO("atmel_mxt_ts", 0x5b),
+ .platform_data = &mxt_platform_data,
+ .irq = MSM_GPIO_TO_INT(MXT_TS_GPIO_IRQ),
+ },
+};
+
+static void gsbi_qup_i2c_gpio_config(int adap_id, int config_type)
+{
+}
+
+static struct msm_i2c_platform_data msm8960_i2c_qup_gsbi4_pdata = {
+ .clk_freq = 100000,
+ .src_clk_rate = 24000000,
+ .msm_i2c_config_gpio = gsbi_qup_i2c_gpio_config,
+};
+
+static struct msm_i2c_platform_data msm8960_i2c_qup_gsbi3_pdata = {
+ .clk_freq = 100000,
+ .src_clk_rate = 24000000,
+ .msm_i2c_config_gpio = gsbi_qup_i2c_gpio_config,
+};
+
+static struct msm_i2c_platform_data msm8960_i2c_qup_gsbi10_pdata = {
+ .clk_freq = 100000,
+ .src_clk_rate = 24000000,
+ .msm_i2c_config_gpio = gsbi_qup_i2c_gpio_config,
+};
+
+static struct msm_i2c_platform_data msm8960_i2c_qup_gsbi12_pdata = {
+ .clk_freq = 100000,
+ .src_clk_rate = 24000000,
+ .msm_i2c_config_gpio = gsbi_qup_i2c_gpio_config,
+};
+
+static struct msm_rpm_platform_data msm_rpm_data = {
+ .reg_base_addrs = {
+ [MSM_RPM_PAGE_STATUS] = MSM_RPM_BASE,
+ [MSM_RPM_PAGE_CTRL] = MSM_RPM_BASE + 0x400,
+ [MSM_RPM_PAGE_REQ] = MSM_RPM_BASE + 0x600,
+ [MSM_RPM_PAGE_ACK] = MSM_RPM_BASE + 0xa00,
+ },
+
+ .irq_ack = RPM_APCC_CPU0_GP_HIGH_IRQ,
+ .irq_err = RPM_APCC_CPU0_GP_LOW_IRQ,
+ .irq_vmpm = RPM_APCC_CPU0_GP_MEDIUM_IRQ,
+ .msm_apps_ipc_rpm_reg = MSM_APCS_GCC_BASE + 0x008,
+ .msm_apps_ipc_rpm_val = 4,
+};
+
+static struct ks8851_pdata spi_eth_pdata = {
+ .irq_gpio = KS8851_IRQ_GPIO,
+ .rst_gpio = KS8851_RST_GPIO,
+};
+
+static struct spi_board_info spi_board_info[] __initdata = {
+ {
+ .modalias = "ks8851",
+ .irq = MSM_GPIO_TO_INT(KS8851_IRQ_GPIO),
+ .max_speed_hz = 19200000,
+ .bus_num = 0,
+ .chip_select = 0,
+ .mode = SPI_MODE_0,
+ .platform_data = &spi_eth_pdata
+ },
+ {
+ .modalias = "dsi_novatek_3d_panel_spi",
+ .max_speed_hz = 10800000,
+ .bus_num = 0,
+ .chip_select = 1,
+ .mode = SPI_MODE_0,
+ },
+};
+
+static struct platform_device msm_device_saw_core0 = {
+ .name = "saw-regulator",
+ .id = 0,
+ .dev = {
+ .platform_data = &msm_saw_regulator_pdata_s5,
+ },
+};
+
+static struct platform_device msm_device_saw_core1 = {
+ .name = "saw-regulator",
+ .id = 1,
+ .dev = {
+ .platform_data = &msm_saw_regulator_pdata_s6,
+ },
+};
+
+static struct tsens_platform_data msm_tsens_pdata = {
+ .slope = 910,
+ .tsens_factor = 1000,
+ .hw_type = MSM_8960,
+ .tsens_num_sensor = 5,
+};
+
+static struct platform_device msm_tsens_device = {
+ .name = "tsens8960-tm",
+ .id = -1,
+ .dev = {
+ .platform_data = &msm_tsens_pdata,
+ },
+};
+
+#ifdef CONFIG_MSM_FAKE_BATTERY
+static struct platform_device fish_battery_device = {
+ .name = "fish_battery",
+};
+#endif
+
+static struct platform_device msm8960_device_ext_5v_vreg __devinitdata = {
+ .name = GPIO_REGULATOR_DEV_NAME,
+ .id = PM8921_MPP_PM_TO_SYS(7),
+ .dev = {
+ .platform_data = &msm_gpio_regulator_pdata[GPIO_VREG_ID_EXT_5V],
+ },
+};
+
+static struct platform_device msm8960_device_ext_l2_vreg __devinitdata = {
+ .name = GPIO_REGULATOR_DEV_NAME,
+ .id = 91,
+ .dev = {
+ .platform_data = &msm_gpio_regulator_pdata[GPIO_VREG_ID_EXT_L2],
+ },
+};
+
+static struct platform_device msm8960_device_ext_3p3v_vreg __devinitdata = {
+ .name = GPIO_REGULATOR_DEV_NAME,
+ .id = PM8921_GPIO_PM_TO_SYS(17),
+ .dev = {
+ .platform_data =
+ &msm_gpio_regulator_pdata[GPIO_VREG_ID_EXT_3P3V],
+ },
+};
+
+static struct platform_device msm8960_device_rpm_regulator __devinitdata = {
+ .name = "rpm-regulator",
+ .id = -1,
+ .dev = {
+ .platform_data = &msm_rpm_regulator_pdata,
+ },
+};
+
+static struct msm_rpm_log_platform_data msm_rpm_log_pdata = {
+ .phys_addr_base = 0x0010C000,
+ .reg_offsets = {
+ [MSM_RPM_LOG_PAGE_INDICES] = 0x00000080,
+ [MSM_RPM_LOG_PAGE_BUFFER] = 0x000000A0,
+ },
+ .phys_size = SZ_8K,
+ .log_len = 4096, /* log's buffer length in bytes */
+ .log_len_mask = (4096 >> 2) - 1, /* length mask in units of u32 */
+};
+
+static struct platform_device msm_rpm_log_device = {
+ .name = "msm_rpm_log",
+ .id = -1,
+ .dev = {
+ .platform_data = &msm_rpm_log_pdata,
+ },
+};
+
+static struct platform_device *common_devices[] __initdata = {
+ &msm8960_device_dmov,
+ &msm_device_smd,
+ &msm8960_device_uart_gsbi5,
+ &msm_device_uart_dm6,
+ &msm_device_saw_core0,
+ &msm_device_saw_core1,
+ &msm8960_device_ext_5v_vreg,
+ &msm8960_device_ext_l2_vreg,
+ &msm8960_device_ssbi_pm8921,
+ &msm8960_device_qup_spi_gsbi1,
+ &msm8960_device_qup_i2c_gsbi3,
+ &msm8960_device_qup_i2c_gsbi4,
+ &msm8960_device_qup_i2c_gsbi10,
+#ifndef CONFIG_MSM_DSPS
+ &msm8960_device_qup_i2c_gsbi12,
+#endif
+ &msm_slim_ctrl,
+ &msm_device_wcnss_wlan,
+#if defined(CONFIG_CRYPTO_DEV_QCRYPTO) || \
+ defined(CONFIG_CRYPTO_DEV_QCRYPTO_MODULE)
+ &qcrypto_device,
+#endif
+
+#if defined(CONFIG_CRYPTO_DEV_QCEDEV) || \
+ defined(CONFIG_CRYPTO_DEV_QCEDEV_MODULE)
+ &qcedev_device,
+#endif
+#ifdef CONFIG_MSM_ROTATOR
+ &msm_rotator_device,
+#endif
+ &msm_device_sps,
+#ifdef CONFIG_MSM_FAKE_BATTERY
+ &fish_battery_device,
+#endif
+#ifdef CONFIG_ANDROID_PMEM
+#ifndef CONFIG_MSM_MULTIMEDIA_USE_ION
+ &android_pmem_device,
+ &android_pmem_adsp_device,
+#endif
+ &android_pmem_audio_device,
+#endif
+ &msm_device_vidc,
+ &msm_device_bam_dmux,
+ &msm_fm_platform_init,
+
+#ifdef CONFIG_HW_RANDOM_MSM
+ &msm_device_rng,
+#endif
+ &msm_rpm_device,
+#ifdef CONFIG_ION_MSM
+ &ion_dev,
+#endif
+ &msm_rpm_log_device,
+ &msm_rpm_stat_device,
+ &msm_device_tz_log,
+
+#ifdef CONFIG_MSM_QDSS
+ &msm_etb_device,
+ &msm_tpiu_device,
+ &msm_funnel_device,
+ &msm_debug_device,
+ &msm_ptm_device,
+#endif
+ &msm_device_dspcrashd_8960,
+ &msm8960_device_watchdog,
+};
+
+static struct platform_device *sim_devices[] __initdata = {
+ &msm8960_device_otg,
+ &msm8960_device_gadget_peripheral,
+ &msm_device_hsusb_host,
+ &msm_device_hsic_host,
+ &android_usb_device,
+ &msm_device_vidc,
+ &msm_bus_apps_fabric,
+ &msm_bus_sys_fabric,
+ &msm_bus_mm_fabric,
+ &msm_bus_sys_fpb,
+ &msm_bus_cpss_fpb,
+ &msm_pcm,
+ &msm_pcm_routing,
+ &msm_cpudai0,
+ &msm_cpudai1,
+ &msm_cpudai_hdmi_rx,
+ &msm_cpudai_bt_rx,
+ &msm_cpudai_bt_tx,
+ &msm_cpudai_fm_rx,
+ &msm_cpudai_fm_tx,
+ &msm_cpudai_auxpcm_rx,
+ &msm_cpudai_auxpcm_tx,
+ &msm_cpu_fe,
+ &msm_stub_codec,
+ &msm_voice,
+ &msm_voip,
+ &msm_lpa_pcm,
+
+#if defined(CONFIG_CRYPTO_DEV_QCRYPTO) || \
+ defined(CONFIG_CRYPTO_DEV_QCRYPTO_MODULE)
+ &qcrypto_device,
+#endif
+
+#if defined(CONFIG_CRYPTO_DEV_QCEDEV) || \
+ defined(CONFIG_CRYPTO_DEV_QCEDEV_MODULE)
+ &qcedev_device,
+#endif
+};
+
+static struct platform_device *rumi3_devices[] __initdata = {
+ &msm_kgsl_3d0,
+ &msm_kgsl_2d0,
+ &msm_kgsl_2d1,
+#ifdef CONFIG_MSM_GEMINI
+ &msm8960_gemini_device,
+#endif
+};
+
+static struct platform_device *cdp_devices[] __initdata = {
+ &msm_8960_q6_lpass,
+ &msm_8960_q6_mss_fw,
+ &msm_8960_q6_mss_sw,
+ &msm8960_device_otg,
+ &msm8960_device_gadget_peripheral,
+ &msm_device_hsusb_host,
+ &android_usb_device,
+ &msm_pcm,
+ &msm_pcm_routing,
+ &msm_cpudai0,
+ &msm_cpudai1,
+ &msm_cpudai_hdmi_rx,
+ &msm_cpudai_bt_rx,
+ &msm_cpudai_bt_tx,
+ &msm_cpudai_fm_rx,
+ &msm_cpudai_fm_tx,
+ &msm_cpudai_auxpcm_rx,
+ &msm_cpudai_auxpcm_tx,
+ &msm_cpu_fe,
+ &msm_stub_codec,
+ &msm_kgsl_3d0,
+#ifdef CONFIG_MSM_KGSL_2D
+ &msm_kgsl_2d0,
+ &msm_kgsl_2d1,
+#endif
+#ifdef CONFIG_MSM_GEMINI
+ &msm8960_gemini_device,
+#endif
+ &msm_voice,
+ &msm_voip,
+ &msm_lpa_pcm,
+ &msm_cpudai_afe_01_rx,
+ &msm_cpudai_afe_01_tx,
+ &msm_cpudai_afe_02_rx,
+ &msm_cpudai_afe_02_tx,
+ &msm_pcm_afe,
+ &msm_pcm_hostless,
+ &msm_bus_apps_fabric,
+ &msm_bus_sys_fabric,
+ &msm_bus_mm_fabric,
+ &msm_bus_sys_fpb,
+ &msm_bus_cpss_fpb,
+ &msm_tsens_device,
+};
+
+static void __init msm8960_i2c_init(void)
+{
+ msm8960_device_qup_i2c_gsbi4.dev.platform_data =
+ &msm8960_i2c_qup_gsbi4_pdata;
+
+ msm8960_device_qup_i2c_gsbi3.dev.platform_data =
+ &msm8960_i2c_qup_gsbi3_pdata;
+
+ msm8960_device_qup_i2c_gsbi10.dev.platform_data =
+ &msm8960_i2c_qup_gsbi10_pdata;
+
+ msm8960_device_qup_i2c_gsbi12.dev.platform_data =
+ &msm8960_i2c_qup_gsbi12_pdata;
+}
+
+static void __init msm8960_gfx_init(void)
+{
+ uint32_t soc_platform_version = socinfo_get_version();
+ if (SOCINFO_VERSION_MAJOR(soc_platform_version) == 1) {
+ struct kgsl_device_platform_data *kgsl_3d0_pdata =
+ msm_kgsl_3d0.dev.platform_data;
+ kgsl_3d0_pdata->pwrlevel[0].gpu_freq = 320000000;
+ kgsl_3d0_pdata->pwrlevel[1].gpu_freq = 266667000;
+ }
+}
+
+static struct msm_cpuidle_state msm_cstates[] __initdata = {
+ {0, 0, "C0", "WFI",
+ MSM_PM_SLEEP_MODE_WAIT_FOR_INTERRUPT},
+
+ {0, 1, "C1", "STANDALONE_POWER_COLLAPSE",
+ MSM_PM_SLEEP_MODE_POWER_COLLAPSE_STANDALONE},
+
+ {0, 2, "C2", "POWER_COLLAPSE",
+ MSM_PM_SLEEP_MODE_POWER_COLLAPSE},
+
+ {1, 0, "C0", "WFI",
+ MSM_PM_SLEEP_MODE_WAIT_FOR_INTERRUPT},
+
+ {1, 1, "C1", "STANDALONE_POWER_COLLAPSE",
+ MSM_PM_SLEEP_MODE_POWER_COLLAPSE_STANDALONE},
+};
+
+static struct msm_pm_platform_data msm_pm_data[MSM_PM_SLEEP_MODE_NR * 2] = {
+ [MSM_PM_MODE(0, MSM_PM_SLEEP_MODE_POWER_COLLAPSE)] = {
+ .idle_supported = 1,
+ .suspend_supported = 1,
+ .idle_enabled = 0,
+ .suspend_enabled = 0,
+ },
+
+ [MSM_PM_MODE(0, MSM_PM_SLEEP_MODE_POWER_COLLAPSE_STANDALONE)] = {
+ .idle_supported = 1,
+ .suspend_supported = 1,
+ .idle_enabled = 0,
+ .suspend_enabled = 0,
+ },
+
+ [MSM_PM_MODE(0, MSM_PM_SLEEP_MODE_WAIT_FOR_INTERRUPT)] = {
+ .idle_supported = 1,
+ .suspend_supported = 1,
+ .idle_enabled = 1,
+ .suspend_enabled = 1,
+ },
+
+ [MSM_PM_MODE(1, MSM_PM_SLEEP_MODE_POWER_COLLAPSE)] = {
+ .idle_supported = 0,
+ .suspend_supported = 1,
+ .idle_enabled = 0,
+ .suspend_enabled = 0,
+ },
+
+ [MSM_PM_MODE(1, MSM_PM_SLEEP_MODE_POWER_COLLAPSE_STANDALONE)] = {
+ .idle_supported = 1,
+ .suspend_supported = 1,
+ .idle_enabled = 0,
+ .suspend_enabled = 0,
+ },
+
+ [MSM_PM_MODE(1, MSM_PM_SLEEP_MODE_WAIT_FOR_INTERRUPT)] = {
+ .idle_supported = 1,
+ .suspend_supported = 0,
+ .idle_enabled = 1,
+ .suspend_enabled = 0,
+ },
+};
+
+static struct msm_rpmrs_level msm_rpmrs_levels[] __initdata = {
+ {
+ MSM_PM_SLEEP_MODE_WAIT_FOR_INTERRUPT,
+ MSM_RPMRS_LIMITS(ON, ACTIVE, MAX, ACTIVE),
+ true,
+ 100, 8000, 100000, 1,
+ },
+
+ {
+ MSM_PM_SLEEP_MODE_POWER_COLLAPSE_STANDALONE,
+ MSM_RPMRS_LIMITS(ON, ACTIVE, MAX, ACTIVE),
+ true,
+ 2000, 6000, 60100000, 3000,
+ },
+
+ {
+ MSM_PM_SLEEP_MODE_POWER_COLLAPSE,
+ MSM_RPMRS_LIMITS(ON, GDHS, MAX, ACTIVE),
+ false,
+ 4200, 5000, 60350000, 3500,
+ },
+
+ {
+ MSM_PM_SLEEP_MODE_POWER_COLLAPSE,
+ MSM_RPMRS_LIMITS(ON, HSFS_OPEN, MAX, ACTIVE),
+ false,
+ 6300, 4500, 65350000, 4800,
+ },
+ {
+ MSM_PM_SLEEP_MODE_POWER_COLLAPSE,
+ MSM_RPMRS_LIMITS(ON, HSFS_OPEN, ACTIVE, RET_HIGH),
+ false,
+ 7000, 3500, 66600000, 5150,
+ },
+
+ {
+ MSM_PM_SLEEP_MODE_POWER_COLLAPSE,
+ MSM_RPMRS_LIMITS(OFF, GDHS, MAX, ACTIVE),
+ false,
+ 11700, 2500, 67850000, 5500,
+ },
+
+ {
+ MSM_PM_SLEEP_MODE_POWER_COLLAPSE,
+ MSM_RPMRS_LIMITS(OFF, HSFS_OPEN, MAX, ACTIVE),
+ false,
+ 13800, 2000, 71850000, 6800,
+ },
+
+ {
+ MSM_PM_SLEEP_MODE_POWER_COLLAPSE,
+ MSM_RPMRS_LIMITS(OFF, HSFS_OPEN, ACTIVE, RET_HIGH),
+ false,
+ 29700, 500, 75850000, 8800,
+ },
+
+ {
+ MSM_PM_SLEEP_MODE_POWER_COLLAPSE,
+ MSM_RPMRS_LIMITS(OFF, HSFS_OPEN, RET_HIGH, RET_LOW),
+ false,
+ 29700, 0, 76350000, 9800,
+ },
+};
+
+#ifdef CONFIG_I2C
+#define I2C_SURF 1
+#define I2C_FFA (1 << 1)
+#define I2C_RUMI (1 << 2)
+#define I2C_SIM (1 << 3)
+#define I2C_FLUID (1 << 4)
+#define I2C_LIQUID (1 << 5)
+
+struct i2c_registry {
+ u8 machs;
+ int bus;
+ struct i2c_board_info *info;
+ int len;
+};
+
+#ifdef CONFIG_MSM_CAMERA
+static struct i2c_board_info msm_camera_boardinfo[] __initdata = {
+#ifdef CONFIG_IMX074
+ {
+ I2C_BOARD_INFO("imx074", 0x1A),
+ },
+#endif
+#ifdef CONFIG_OV2720
+ {
+ I2C_BOARD_INFO("ov2720", 0x6C),
+ },
+#endif
+#ifdef CONFIG_MSM_CAMERA_FLASH_SC628A
+ {
+ I2C_BOARD_INFO("sc628a", 0x6E),
+ },
+#endif
+};
+#endif
+
+/* Sensors DSPS platform data */
+#ifdef CONFIG_MSM_DSPS
+#define DSPS_PIL_GENERIC_NAME "dsps"
+#endif /* CONFIG_MSM_DSPS */
+
+static void __init msm8960_init_dsps(void)
+{
+#ifdef CONFIG_MSM_DSPS
+ struct msm_dsps_platform_data *pdata =
+ msm_dsps_device.dev.platform_data;
+ pdata->pil_name = DSPS_PIL_GENERIC_NAME;
+ pdata->gpios = NULL;
+ pdata->gpios_num = 0;
+
+ platform_device_register(&msm_dsps_device);
+#endif /* CONFIG_MSM_DSPS */
+}
+
+static void __init msm8960_init_hsic(void)
+{
+#ifdef CONFIG_USB_EHCI_MSM_HSIC
+ uint32_t version = socinfo_get_version();
+
+ if (SOCINFO_VERSION_MAJOR(version) == 1)
+ return;
+
+ if (PLATFORM_IS_CHARM25() || machine_is_msm8960_liquid())
+ platform_device_register(&msm_device_hsic_host);
+#endif
+}
+
+#ifdef CONFIG_ISL9519_CHARGER
+static struct isl_platform_data isl_data __initdata = {
+ .valid_n_gpio = 0, /* Not required when notify-by-pmic */
+ .chg_detection_config = NULL, /* Not required when notify-by-pmic */
+ .max_system_voltage = 4200,
+ .min_system_voltage = 3200,
+ .chgcurrent = 1000, /* 1900, */
+ .term_current = 400, /* Need fine tuning */
+ .input_current = 2048,
+};
+
+static struct i2c_board_info isl_charger_i2c_info[] __initdata = {
+ {
+ I2C_BOARD_INFO("isl9519q", 0x9),
+ .irq = 0, /* Not required when notify-by-pmic */
+ .platform_data = &isl_data,
+ },
+};
+#endif /* CONFIG_ISL9519_CHARGER */
+
+static struct i2c_registry msm8960_i2c_devices[] __initdata = {
+#ifdef CONFIG_MSM_CAMERA
+ {
+ I2C_SURF | I2C_FFA | I2C_FLUID | I2C_LIQUID | I2C_RUMI,
+ MSM_8960_GSBI4_QUP_I2C_BUS_ID,
+ msm_camera_boardinfo,
+ ARRAY_SIZE(msm_camera_boardinfo),
+ },
+#endif
+#ifdef CONFIG_ISL9519_CHARGER
+ {
+ I2C_LIQUID,
+ MSM_8960_GSBI10_QUP_I2C_BUS_ID,
+ isl_charger_i2c_info,
+ ARRAY_SIZE(isl_charger_i2c_info),
+ },
+#endif /* CONFIG_ISL9519_CHARGER */
+ {
+ I2C_SURF | I2C_FFA | I2C_FLUID,
+ MSM_8960_GSBI3_QUP_I2C_BUS_ID,
+ cyttsp_info,
+ ARRAY_SIZE(cyttsp_info),
+ },
+ {
+ I2C_LIQUID,
+ MSM_8960_GSBI3_QUP_I2C_BUS_ID,
+ mxt_device_info,
+ ARRAY_SIZE(mxt_device_info),
+ },
+ {
+ I2C_LIQUID,
+ MSM_8960_GSBI10_QUP_I2C_BUS_ID,
+ msm_isa1200_board_info,
+ ARRAY_SIZE(msm_isa1200_board_info),
+ },
+};
+#endif /* CONFIG_I2C */
+
+static void __init register_i2c_devices(void)
+{
+#ifdef CONFIG_I2C
+ u8 mach_mask = 0;
+ int i;
+
+ /* Build the matching 'supported_machs' bitmask */
+ if (machine_is_msm8960_cdp())
+ mach_mask = I2C_SURF;
+ else if (machine_is_msm8960_rumi3())
+ mach_mask = I2C_RUMI;
+ else if (machine_is_msm8960_sim())
+ mach_mask = I2C_SIM;
+ else if (machine_is_msm8960_fluid())
+ mach_mask = I2C_FLUID;
+ else if (machine_is_msm8960_liquid())
+ mach_mask = I2C_LIQUID;
+ else if (machine_is_msm8960_mtp())
+ mach_mask = I2C_FFA;
+ else
+ pr_err("unmatched machine ID in register_i2c_devices\n");
+
+ /* Run the array and install devices as appropriate */
+ for (i = 0; i < ARRAY_SIZE(msm8960_i2c_devices); ++i) {
+ if (msm8960_i2c_devices[i].machs & mach_mask)
+ i2c_register_board_info(msm8960_i2c_devices[i].bus,
+ msm8960_i2c_devices[i].info,
+ msm8960_i2c_devices[i].len);
+ }
+#endif
+}
+
+static void __init msm8960_sim_init(void)
+{
+ struct msm_watchdog_pdata *wdog_pdata = (struct msm_watchdog_pdata *)
+ &msm8960_device_watchdog.dev.platform_data;
+
+ wdog_pdata->bark_time = 15000;
+ BUG_ON(msm_rpm_init(&msm_rpm_data));
+ BUG_ON(msm_rpmrs_levels_init(msm_rpmrs_levels,
+ ARRAY_SIZE(msm_rpmrs_levels)));
+ regulator_suppress_info_printing();
+ platform_device_register(&msm8960_device_rpm_regulator);
+ msm_clock_init(&msm8960_clock_init_data);
+ msm8960_init_pmic();
+
+ msm8960_device_otg.dev.platform_data = &msm_otg_pdata;
+ msm8960_init_gpiomux();
+ msm8960_i2c_init();
+ msm_spm_init(msm_spm_data, ARRAY_SIZE(msm_spm_data));
+ msm_spm_l2_init(msm_spm_l2_data);
+ msm8960_init_buses();
+ platform_add_devices(common_devices, ARRAY_SIZE(common_devices));
+ msm8960_pm8921_gpio_mpp_init();
+ platform_add_devices(sim_devices, ARRAY_SIZE(sim_devices));
+ acpuclk_init(&acpuclk_8960_soc_data);
+
+ msm8960_device_qup_spi_gsbi1.dev.platform_data =
+ &msm8960_qup_spi_gsbi1_pdata;
+ spi_register_board_info(spi_board_info, ARRAY_SIZE(spi_board_info));
+
+ msm8960_init_mmc();
+ msm8960_init_fb();
+ slim_register_board_info(msm_slim_devices,
+ ARRAY_SIZE(msm_slim_devices));
+ msm_pm_set_platform_data(msm_pm_data, ARRAY_SIZE(msm_pm_data));
+ msm_pm_set_rpm_wakeup_irq(RPM_APCC_CPU0_WAKE_UP_IRQ);
+ msm_cpuidle_set_states(msm_cstates, ARRAY_SIZE(msm_cstates),
+ msm_pm_data);
+ BUG_ON(msm_pm_boot_init(MSM_PM_BOOT_CONFIG_TZ, NULL));
+}
+
+static void __init msm8960_rumi3_init(void)
+{
+ BUG_ON(msm_rpm_init(&msm_rpm_data));
+ BUG_ON(msm_rpmrs_levels_init(msm_rpmrs_levels,
+ ARRAY_SIZE(msm_rpmrs_levels)));
+ regulator_suppress_info_printing();
+ platform_device_register(&msm8960_device_rpm_regulator);
+ msm_clock_init(&msm8960_dummy_clock_init_data);
+ msm8960_init_gpiomux();
+ msm8960_init_pmic();
+ msm8960_device_qup_spi_gsbi1.dev.platform_data =
+ &msm8960_qup_spi_gsbi1_pdata;
+ spi_register_board_info(spi_board_info, ARRAY_SIZE(spi_board_info));
+ msm8960_i2c_init();
+ msm_spm_init(msm_spm_data, ARRAY_SIZE(msm_spm_data));
+ msm_spm_l2_init(msm_spm_l2_data);
+ platform_add_devices(common_devices, ARRAY_SIZE(common_devices));
+ msm8960_pm8921_gpio_mpp_init();
+ platform_add_devices(rumi3_devices, ARRAY_SIZE(rumi3_devices));
+ msm8960_init_mmc();
+ register_i2c_devices();
+ msm8960_init_fb();
+ slim_register_board_info(msm_slim_devices,
+ ARRAY_SIZE(msm_slim_devices));
+ msm_pm_set_platform_data(msm_pm_data, ARRAY_SIZE(msm_pm_data));
+ msm_pm_set_rpm_wakeup_irq(RPM_APCC_CPU0_WAKE_UP_IRQ);
+ msm_cpuidle_set_states(msm_cstates, ARRAY_SIZE(msm_cstates),
+ msm_pm_data);
+ BUG_ON(msm_pm_boot_init(MSM_PM_BOOT_CONFIG_TZ, NULL));
+}
+
+static void __init msm8960_cdp_init(void)
+{
+ if (meminfo_init(SYS_MEMORY, SZ_256M) < 0)
+ pr_err("meminfo_init() failed!\n");
+
+ BUG_ON(msm_rpm_init(&msm_rpm_data));
+ BUG_ON(msm_rpmrs_levels_init(msm_rpmrs_levels,
+ ARRAY_SIZE(msm_rpmrs_levels)));
+
+ regulator_suppress_info_printing();
+ if (msm_xo_init())
+ pr_err("Failed to initialize XO votes\n");
+ platform_device_register(&msm8960_device_rpm_regulator);
+ msm_clock_init(&msm8960_clock_init_data);
+ if (machine_is_msm8960_liquid())
+ msm_otg_pdata.mhl_enable = true;
+ msm8960_device_otg.dev.platform_data = &msm_otg_pdata;
+ if (machine_is_msm8960_mtp() || machine_is_msm8960_fluid() ||
+ machine_is_msm8960_cdp()) {
+ msm_otg_pdata.phy_init_seq = wr_phy_init_seq;
+ } else if (machine_is_msm8960_liquid()) {
+ msm_otg_pdata.phy_init_seq =
+ liquid_v1_phy_init_seq;
+ }
+#ifdef CONFIG_USB_EHCI_MSM_HSIC
+ if (machine_is_msm8960_liquid()) {
+ if (SOCINFO_VERSION_MAJOR(socinfo_get_version()) >= 2)
+ msm_hsic_pdata.hub_reset = HSIC_HUB_RESET_GPIO;
+ }
+#endif
+ msm_device_hsic_host.dev.platform_data = &msm_hsic_pdata;
+ msm8960_init_gpiomux();
+ msm8960_device_qup_spi_gsbi1.dev.platform_data =
+ &msm8960_qup_spi_gsbi1_pdata;
+ spi_register_board_info(spi_board_info, ARRAY_SIZE(spi_board_info));
+
+ msm8960_init_pmic();
+ msm8960_i2c_init();
+ msm8960_gfx_init();
+ msm_spm_init(msm_spm_data, ARRAY_SIZE(msm_spm_data));
+ msm_spm_l2_init(msm_spm_l2_data);
+ msm8960_init_buses();
+ platform_add_devices(msm_footswitch_devices,
+ msm_num_footswitch_devices);
+ if (machine_is_msm8960_liquid())
+ platform_device_register(&msm8960_device_ext_3p3v_vreg);
+ platform_add_devices(common_devices, ARRAY_SIZE(common_devices));
+ msm8960_pm8921_gpio_mpp_init();
+ platform_add_devices(cdp_devices, ARRAY_SIZE(cdp_devices));
+ msm8960_init_hsic();
+ msm8960_init_cam();
+ msm8960_init_mmc();
+ acpuclk_init(&acpuclk_8960_soc_data);
+ if (machine_is_msm8960_liquid())
+ mxt_init_hw_liquid();
+ register_i2c_devices();
+ msm8960_init_fb();
+ slim_register_board_info(msm_slim_devices,
+ ARRAY_SIZE(msm_slim_devices));
+ msm8960_init_dsps();
+ msm_pm_set_platform_data(msm_pm_data, ARRAY_SIZE(msm_pm_data));
+ msm_pm_set_rpm_wakeup_irq(RPM_APCC_CPU0_WAKE_UP_IRQ);
+ msm_cpuidle_set_states(msm_cstates, ARRAY_SIZE(msm_cstates),
+ msm_pm_data);
+ change_memory_power = &msm8960_change_memory_power;
+ BUG_ON(msm_pm_boot_init(MSM_PM_BOOT_CONFIG_TZ, NULL));
+
+ if (PLATFORM_IS_CHARM25())
+ platform_add_devices(mdm_devices, ARRAY_SIZE(mdm_devices));
+}
+
+MACHINE_START(MSM8960_SIM, "QCT MSM8960 SIMULATOR")
+ .map_io = msm8960_map_io,
+ .reserve = msm8960_reserve,
+ .init_irq = msm8960_init_irq,
+ .timer = &msm_timer,
+ .init_machine = msm8960_sim_init,
+ .init_early = msm8960_allocate_memory_regions,
+ .init_very_early = msm8960_early_memory,
+MACHINE_END
+
+MACHINE_START(MSM8960_RUMI3, "QCT MSM8960 RUMI3")
+ .map_io = msm8960_map_io,
+ .reserve = msm8960_reserve,
+ .init_irq = msm8960_init_irq,
+ .timer = &msm_timer,
+ .init_machine = msm8960_rumi3_init,
+ .init_early = msm8960_allocate_memory_regions,
+ .init_very_early = msm8960_early_memory,
+MACHINE_END
+
+MACHINE_START(MSM8960_CDP, "QCT MSM8960 CDP")
+ .map_io = msm8960_map_io,
+ .reserve = msm8960_reserve,
+ .init_irq = msm8960_init_irq,
+ .timer = &msm_timer,
+ .init_machine = msm8960_cdp_init,
+ .init_early = msm8960_allocate_memory_regions,
+ .init_very_early = msm8960_early_memory,
+MACHINE_END
+
+MACHINE_START(MSM8960_MTP, "QCT MSM8960 MTP")
+ .map_io = msm8960_map_io,
+ .reserve = msm8960_reserve,
+ .init_irq = msm8960_init_irq,
+ .timer = &msm_timer,
+ .init_machine = msm8960_cdp_init,
+ .init_early = msm8960_allocate_memory_regions,
+ .init_very_early = msm8960_early_memory,
+MACHINE_END
+
+MACHINE_START(MSM8960_FLUID, "QCT MSM8960 FLUID")
+ .map_io = msm8960_map_io,
+ .reserve = msm8960_reserve,
+ .init_irq = msm8960_init_irq,
+ .timer = &msm_timer,
+ .init_machine = msm8960_cdp_init,
+ .init_early = msm8960_allocate_memory_regions,
+ .init_very_early = msm8960_early_memory,
+MACHINE_END
+
+MACHINE_START(MSM8960_LIQUID, "QCT MSM8960 LIQUID")
+ .map_io = msm8960_map_io,
+ .reserve = msm8960_reserve,
+ .init_irq = msm8960_init_irq,
+ .timer = &msm_timer,
+ .init_machine = msm8960_cdp_init,
+ .init_early = msm8960_allocate_memory_regions,
+ .init_very_early = msm8960_early_memory,
+MACHINE_END
diff --git a/arch/arm/mach-msm/board-8960.h b/arch/arm/mach-msm/board-8960.h
new file mode 100644
index 0000000..56fa3ca
--- /dev/null
+++ b/arch/arm/mach-msm/board-8960.h
@@ -0,0 +1,86 @@
+/* Copyright (c) 2011, Code Aurora Forum. 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 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#ifndef __ARCH_ARM_MACH_MSM_BOARD_MSM8960_H
+#define __ARCH_ARM_MACH_MSM_BOARD_MSM8960_H
+
+#include <linux/regulator/gpio-regulator.h>
+#include <linux/mfd/pm8xxx/pm8921.h>
+#include <linux/i2c/sx150x.h>
+#include <mach/irqs.h>
+#include <mach/rpm-regulator.h>
+
+/* Macros assume PMIC GPIOs and MPPs start at 1 */
+#define PM8921_GPIO_BASE NR_GPIO_IRQS
+#define PM8921_GPIO_PM_TO_SYS(pm_gpio) (pm_gpio - 1 + PM8921_GPIO_BASE)
+#define PM8921_MPP_BASE (PM8921_GPIO_BASE + PM8921_NR_GPIOS)
+#define PM8921_MPP_PM_TO_SYS(pm_gpio) (pm_gpio - 1 + PM8921_MPP_BASE)
+#define PM8921_IRQ_BASE (NR_MSM_IRQS + NR_GPIO_IRQS)
+
+extern struct pm8921_regulator_platform_data
+ msm_pm8921_regulator_pdata[] __devinitdata;
+
+extern int msm_pm8921_regulator_pdata_len __devinitdata;
+
+#define GPIO_VREG_ID_EXT_5V 0
+#define GPIO_VREG_ID_EXT_L2 1
+#define GPIO_VREG_ID_EXT_3P3V 2
+
+extern struct gpio_regulator_platform_data
+ msm_gpio_regulator_pdata[] __devinitdata;
+
+extern struct regulator_init_data msm_saw_regulator_pdata_s5;
+extern struct regulator_init_data msm_saw_regulator_pdata_s6;
+
+extern struct rpm_regulator_platform_data msm_rpm_regulator_pdata __devinitdata;
+
+#if defined(CONFIG_GPIO_SX150X) || defined(CONFIG_GPIO_SX150X_MODULE)
+enum {
+ GPIO_EXPANDER_IRQ_BASE = (PM8921_IRQ_BASE + PM8921_NR_IRQS),
+ GPIO_EXPANDER_GPIO_BASE = (PM8921_MPP_BASE + PM8921_NR_MPPS),
+ /* CAM Expander */
+ GPIO_CAM_EXPANDER_BASE = GPIO_EXPANDER_GPIO_BASE,
+ GPIO_CAM_GP_STROBE_READY = GPIO_CAM_EXPANDER_BASE,
+ GPIO_CAM_GP_AFBUSY,
+ GPIO_CAM_GP_STROBE_CE,
+ GPIO_CAM_GP_CAM1MP_XCLR,
+ GPIO_CAM_GP_CAMIF_RESET_N,
+ GPIO_CAM_GP_XMT_FLASH_INT,
+ GPIO_CAM_GP_LED_EN1,
+ GPIO_CAM_GP_LED_EN2,
+
+};
+#endif
+
+enum {
+ SX150X_CAM,
+};
+
+#endif
+
+extern struct sx150x_platform_data msm8960_sx150x_data[];
+void msm8960_init_cam(void);
+void msm8960_init_fb(void);
+void msm8960_init_pmic(void);
+void msm8960_init_mmc(void);
+int msm8960_init_gpiomux(void);
+void msm8960_allocate_fb_region(void);
+void msm8960_pm8921_gpio_mpp_init(void);
+
+#define PLATFORM_IS_CHARM25() \
+ (machine_is_msm8960_cdp() && \
+ (socinfo_get_platform_subtype() == 1) \
+ )
+
+#define MSM_8960_GSBI4_QUP_I2C_BUS_ID 4
+#define MSM_8960_GSBI3_QUP_I2C_BUS_ID 3
+#define MSM_8960_GSBI10_QUP_I2C_BUS_ID 10
diff --git a/arch/arm/mach-msm/board-9615.c b/arch/arm/mach-msm/board-9615.c
index 44b78d1..0a2e102 100644
--- a/arch/arm/mach-msm/board-9615.c
+++ b/arch/arm/mach-msm/board-9615.c
@@ -89,7 +89,7 @@
static struct pm8xxx_pwrkey_platform_data pm8xxx_pwrkey_pdata = {
.pull_up = 1,
- .kpd_trigger_delay_us = 970,
+ .kpd_trigger_delay_us = 15625,
.wakeup = 1,
};
@@ -674,6 +674,14 @@
vbus_is_on = false;
}
+static int shelby_phy_init_seq[] = {
+ 0x44, 0x80,/* set VBUS valid threshold and
+ disconnect valid threshold */
+ 0x38, 0x81, /* update DC voltage level */
+ 0x14, 0x82,/* set preemphasis and rise/fall time */
+ 0x13, 0x83,/* set source impedance adjustment */
+ -1};
+
static struct msm_otg_platform_data msm_otg_pdata = {
.mode = USB_OTG,
.otg_control = OTG_PHY_CONTROL,
@@ -766,6 +774,7 @@
pm8018_platform_data.num_regulators = msm_pm8018_regulator_pdata_len;
msm_device_otg.dev.platform_data = &msm_otg_pdata;
+ msm_otg_pdata.phy_init_seq = shelby_phy_init_seq;
platform_add_devices(common_devices, ARRAY_SIZE(common_devices));
acpuclk_init(&acpuclk_9615_soc_data);
diff --git a/arch/arm/mach-msm/board-copper.c b/arch/arm/mach-msm/board-copper.c
index a2ddeb4..13d63d3 100644
--- a/arch/arm/mach-msm/board-copper.c
+++ b/arch/arm/mach-msm/board-copper.c
@@ -83,6 +83,9 @@
CLK_DUMMY("usb_phy_clk", NULL, NULL, OFF),
CLK_DUMMY("usb_hs_clk", NULL, NULL, OFF),
CLK_DUMMY("usb_hs_pclk", NULL, NULL, OFF),
+ CLK_DUMMY("dfab_clk", DFAB_CLK, NULL, 0),
+ CLK_DUMMY("dma_bam_pclk", DMA_BAM_P_CLK, NULL, 0),
+ CLK_DUMMY("mem_clk", NULL, NULL, 0),
};
struct clock_init_data msm_dummy_clock_init_data __initdata = {
@@ -91,7 +94,7 @@
};
static struct of_dev_auxdata msm_copper_auxdata_lookup[] __initdata = {
- OF_DEV_AUXDATA("qcom,msm-lsuart-v14", 0xF9684000, \
+ OF_DEV_AUXDATA("qcom,msm-lsuart-v14", 0xF991F000, \
"msm_serial_hsl.0", NULL),
{}
};
diff --git a/arch/arm/mach-msm/board-dt.c b/arch/arm/mach-msm/board-dt.c
index 1a085de..ebe884de 100644
--- a/arch/arm/mach-msm/board-dt.c
+++ b/arch/arm/mach-msm/board-dt.c
@@ -16,10 +16,48 @@
#include <linux/of_address.h>
#include <linux/of_platform.h>
#include <linux/of_fdt.h>
+#include <linux/of_irq.h>
+#include <asm/arch_timer.h>
#include <asm/mach/arch.h>
+#include <asm/mach/time.h>
#include <mach/socinfo.h>
#include <mach/board.h>
-#include "timer.h"
+
+static void __init msm_dt_timer_init(void)
+{
+ struct device_node *node;
+ struct resource res;
+ struct of_irq oirq;
+
+ node = of_find_compatible_node(NULL, NULL, "qcom,msm-qtimer");
+ if (!node) {
+ pr_err("no matching timer node found\n");
+ return;
+ }
+
+ if (of_irq_map_one(node, 0, &oirq)) {
+ pr_err("interrupt not specified in timer node\n");
+ } else {
+ res.start = res.end = oirq.specifier[0];
+ res.flags = IORESOURCE_IRQ;
+ arch_timer_register(&res, 1);
+ }
+ of_node_put(node);
+}
+
+static struct sys_timer msm_dt_timer = {
+ .init = msm_dt_timer_init
+};
+
+int __cpuinit local_timer_setup(struct clock_event_device *evt)
+{
+ return 0;
+}
+
+int local_timer_ack(void)
+{
+ return 1;
+}
static void __init msm_dt_init_irq(void)
{
@@ -56,6 +94,6 @@
.map_io = msm_dt_map_io,
.init_irq = msm_dt_init_irq,
.init_machine = msm_dt_init,
- .timer = &msm_timer,
+ .timer = &msm_dt_timer,
.dt_compat = msm_dt_match,
MACHINE_END
diff --git a/arch/arm/mach-msm/board-msm7627-regulator.c b/arch/arm/mach-msm/board-msm7627-regulator.c
index 0b3baff..7437911 100644
--- a/arch/arm/mach-msm/board-msm7627-regulator.c
+++ b/arch/arm/mach-msm/board-msm7627-regulator.c
@@ -207,7 +207,7 @@
PCOM_VREG_LDO(ldo10, 7, NULL, 2600000, 2600000, 0, -1, 0, 0, 0, 0),
PCOM_VREG_LDO(ldo11, 21, NULL, 1800000, 1800000, 0, -1, 0, 0, 0, 0),
PCOM_VREG_LDO(ldo12, 11, NULL, 1800000, 1800000, 0, -1, 0, 0, 0, 0),
- PCOM_VREG_LDO(ldo13, 15, NULL, 2850000, 2850000, 0, -1, 0, 0, 0, 0),
+ PCOM_VREG_LDO(ldo13, 15, NULL, 1800000, 2850000, 0, -1, 0, 0, 0, 0),
PCOM_VREG_LDO(ldo14, 24, NULL, 2700000, 2700000, 0, -1, 0, 0, 0, 0),
PCOM_VREG_LDO(ldo15, 23, NULL, 2600000, 2600000, 0, -1, 0, 0, 0, 0),
PCOM_VREG_LDO(ldo16, 22, NULL, 2850000, 3000000, 0, -1, 0, 0, 0, 0),
diff --git a/arch/arm/mach-msm/board-msm7x27a.c b/arch/arm/mach-msm/board-msm7x27a.c
index 05b4896..5de5ea3 100644
--- a/arch/arm/mach-msm/board-msm7x27a.c
+++ b/arch/arm/mach-msm/board-msm7x27a.c
@@ -1072,7 +1072,7 @@
#define MSM_PMEM_MDP_SIZE 0x1900000
#define MSM7x25A_MSM_PMEM_MDP_SIZE 0x1000000
-#define MSM_PMEM_ADSP_SIZE 0x2000000
+#define MSM_PMEM_ADSP_SIZE 0x1000000
#define MSM7x25A_MSM_PMEM_ADSP_SIZE 0xB91000
@@ -3023,7 +3023,6 @@
gpio_tlmm_config(GPIO_CFG(ATMEL_TS_GPIO_IRQ, 0,
GPIO_CFG_INPUT, GPIO_CFG_NO_PULL,
GPIO_CFG_2MA), GPIO_CFG_DISABLE);
- regulator_bulk_disable(ARRAY_SIZE(regs_atmel), regs_atmel);
regulator_bulk_free(ARRAY_SIZE(regs_atmel), regs_atmel);
return 0;
}
diff --git a/arch/arm/mach-msm/board-msm7x30-regulator.c b/arch/arm/mach-msm/board-msm7x30-regulator.c
index 5329bbe..edfcc6b 100644
--- a/arch/arm/mach-msm/board-msm7x30-regulator.c
+++ b/arch/arm/mach-msm/board-msm7x30-regulator.c
@@ -289,7 +289,7 @@
PCOM_VREG_LDO(ldo10, 7, NULL, 2600000, 2600000, 0, -1, 0, 0, 0, 0),
PCOM_VREG_LDO(ldo11, 21, NULL, 2600000, 2600000, 0, -1, 0, 0, 0, 0),
PCOM_VREG_LDO(ldo12, 34, NULL, 1800000, 1800000, 0, -1, 0, 0, 0, 0),
- PCOM_VREG_LDO(ldo13, 15, NULL, 2900000, 2900000, 0, -1, 0, 0, 0, 0),
+ PCOM_VREG_LDO(ldo13, 15, NULL, 2900000, 3050000, 0, -1, 0, 0, 0, 0),
PCOM_VREG_LDO(ldo14, 24, NULL, 2850000, 2850000, 0, -1, 0, 0, 0, 0),
PCOM_VREG_LDO(ldo15, 23, NULL, 3050000, 3100000, 0, -1, 0, 0, 0, 0),
PCOM_VREG_LDO(ldo16, 35, NULL, 2600000, 2600000, 0, -1, 0, 0, 0, 0),
@@ -298,7 +298,7 @@
PCOM_VREG_LDO(ldo19, 45, NULL, 2500000, 2500000, 0, -1, 0, 0, 0, 0),
PCOM_VREG_LDO(ldo20, 38, NULL, 1500000, 1800000, 0, -1, 0, 0, 0, 0),
PCOM_VREG_LDO(ldo21, 39, NULL, 1100000, 1100000, 0, -1, 0, 0, 0, 0),
- PCOM_VREG_LDO(ldo22, 40, NULL, 1300000, 1300000, 0, -1, 0, 0, 0, 0),
+ PCOM_VREG_LDO(ldo22, 40, NULL, 1200000, 1300000, 0, -1, 0, 0, 0, 0),
PCOM_VREG_LDO(ldo23, 22, NULL, 1350000, 1350000, 0, -1, 0, 0, 0, 0),
PCOM_VREG_LDO(ldo24, 41, NULL, 1200000, 1200000, 0, -1, 0, 0, 0, 0),
PCOM_VREG_LDO(ldo25, 42, NULL, 1200000, 1200000, 0, -1, 0, 0, 0, 0),
diff --git a/arch/arm/mach-msm/board-msm7x30.c b/arch/arm/mach-msm/board-msm7x30.c
index d73f612..9ba92ed 100644
--- a/arch/arm/mach-msm/board-msm7x30.c
+++ b/arch/arm/mach-msm/board-msm7x30.c
@@ -4565,20 +4565,20 @@
{ .supply = "smps3", .min_uV = 1800000, .max_uV = 1800000 },
{ .supply = "smps2", .min_uV = 1300000, .max_uV = 1300000 },
{ .supply = "ldo24", .min_uV = 1200000, .max_uV = 1200000 },
- { .supply = "ldo13", .min_uV = 2900000, .max_uV = 2900000 },
+ { .supply = "ldo13", .min_uV = 2900000, .max_uV = 3050000 },
};
static struct regulator_bulk_data regs_bt_bahama_v1[] = {
{ .supply = "smps3", .min_uV = 1800000, .max_uV = 1800000 },
{ .supply = "ldo7", .min_uV = 1800000, .max_uV = 1800000 },
{ .supply = "smps2", .min_uV = 1300000, .max_uV = 1300000 },
- { .supply = "ldo13", .min_uV = 2900000, .max_uV = 2900000 },
+ { .supply = "ldo13", .min_uV = 2900000, .max_uV = 3050000 },
};
static struct regulator_bulk_data regs_bt_bahama_v2[] = {
{ .supply = "smps3", .min_uV = 1800000, .max_uV = 1800000 },
{ .supply = "ldo7", .min_uV = 1800000, .max_uV = 1800000 },
- { .supply = "ldo13", .min_uV = 2900000, .max_uV = 2900000 },
+ { .supply = "ldo13", .min_uV = 2900000, .max_uV = 3050000 },
};
static struct regulator_bulk_data *regs_bt;
diff --git a/arch/arm/mach-msm/board-msm8960.c b/arch/arm/mach-msm/board-msm8960.c
deleted file mode 100644
index 61423a6..0000000
--- a/arch/arm/mach-msm/board-msm8960.c
+++ /dev/null
@@ -1,5079 +0,0 @@
-/* Copyright (c) 2011, Code Aurora Forum. 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 and
- * only version 2 as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- */
-#include <linux/kernel.h>
-#include <linux/platform_device.h>
-#include <linux/io.h>
-#include <linux/irq.h>
-#include <linux/i2c.h>
-#include <linux/i2c/sx150x.h>
-#include <linux/i2c/isl9519.h>
-#include <linux/gpio.h>
-#include <linux/msm_ssbi.h>
-#include <linux/regulator/gpio-regulator.h>
-#include <linux/mfd/pm8xxx/pm8921.h>
-#include <linux/mfd/pm8xxx/pm8xxx-adc.h>
-#include <linux/regulator/consumer.h>
-#include <linux/spi/spi.h>
-#include <linux/slimbus/slimbus.h>
-#include <linux/bootmem.h>
-#include <linux/msm_kgsl.h>
-#ifdef CONFIG_ANDROID_PMEM
-#include <linux/android_pmem.h>
-#endif
-#include <linux/cyttsp.h>
-#include <linux/dma-mapping.h>
-#include <linux/platform_data/qcom_crypto_device.h>
-#include <linux/platform_data/qcom_wcnss_device.h>
-#include <linux/leds.h>
-#include <linux/leds-pm8xxx.h>
-#include <linux/i2c/atmel_mxt_ts.h>
-#include <linux/msm_tsens.h>
-#include <linux/ks8851.h>
-#include <linux/i2c/isa1200.h>
-
-#include <asm/mach-types.h>
-#include <asm/mach/arch.h>
-#include <asm/setup.h>
-#include <asm/hardware/gic.h>
-#include <asm/mach/mmc.h>
-
-#include <mach/board.h>
-#include <mach/msm_iomap.h>
-#include <mach/msm_spi.h>
-#ifdef CONFIG_USB_MSM_OTG_72K
-#include <mach/msm_hsusb.h>
-#else
-#include <linux/usb/msm_hsusb.h>
-#endif
-#include <linux/usb/android.h>
-#include <mach/usbdiag.h>
-#include <mach/socinfo.h>
-#include <mach/rpm.h>
-#include <mach/gpio.h>
-#include <mach/gpiomux.h>
-#include <mach/msm_bus_board.h>
-#include <mach/msm_memtypes.h>
-#include <mach/dma.h>
-#include <mach/msm_dsps.h>
-#include <mach/msm_xo.h>
-#include <mach/restart.h>
-
-#ifdef CONFIG_WCD9310_CODEC
-#include <linux/slimbus/slimbus.h>
-#include <linux/mfd/wcd9310/core.h>
-#include <linux/mfd/wcd9310/pdata.h>
-#endif
-
-#include <linux/ion.h>
-#include <mach/ion.h>
-#include <mach/mdm2.h>
-
-#include "timer.h"
-#include "devices.h"
-#include "devices-msm8x60.h"
-#include "spm.h"
-#include "board-msm8960.h"
-#include "pm.h"
-#include "cpuidle.h"
-#include "rpm_resources.h"
-#include "mpm.h"
-#include "acpuclock.h"
-#include "rpm_log.h"
-#include "smd_private.h"
-#include "pm-boot.h"
-#include "msm_watchdog.h"
-
-#define PLATFORM_IS_CHARM25() \
- (machine_is_msm8960_cdp() && \
- (socinfo_get_platform_subtype() == 1) \
- )
-
-static struct platform_device msm_fm_platform_init = {
- .name = "iris_fm",
- .id = -1,
-};
-
-struct pm8xxx_gpio_init {
- unsigned gpio;
- struct pm_gpio config;
-};
-
-struct pm8xxx_mpp_init {
- unsigned mpp;
- struct pm8xxx_mpp_config_data config;
-};
-
-#define PM8XXX_GPIO_INIT(_gpio, _dir, _buf, _val, _pull, _vin, _out_strength, \
- _func, _inv, _disable) \
-{ \
- .gpio = PM8921_GPIO_PM_TO_SYS(_gpio), \
- .config = { \
- .direction = _dir, \
- .output_buffer = _buf, \
- .output_value = _val, \
- .pull = _pull, \
- .vin_sel = _vin, \
- .out_strength = _out_strength, \
- .function = _func, \
- .inv_int_pol = _inv, \
- .disable_pin = _disable, \
- } \
-}
-
-#define PM8XXX_MPP_INIT(_mpp, _type, _level, _control) \
-{ \
- .mpp = PM8921_MPP_PM_TO_SYS(_mpp), \
- .config = { \
- .type = PM8XXX_MPP_TYPE_##_type, \
- .level = _level, \
- .control = PM8XXX_MPP_##_control, \
- } \
-}
-
-#define PM8XXX_GPIO_DISABLE(_gpio) \
- PM8XXX_GPIO_INIT(_gpio, PM_GPIO_DIR_IN, 0, 0, 0, PM_GPIO_VIN_S4, \
- 0, 0, 0, 1)
-
-#define PM8XXX_GPIO_OUTPUT(_gpio, _val) \
- PM8XXX_GPIO_INIT(_gpio, PM_GPIO_DIR_OUT, PM_GPIO_OUT_BUF_CMOS, _val, \
- PM_GPIO_PULL_NO, PM_GPIO_VIN_S4, \
- PM_GPIO_STRENGTH_HIGH, \
- PM_GPIO_FUNC_NORMAL, 0, 0)
-
-#define PM8XXX_GPIO_INPUT(_gpio, _pull) \
- PM8XXX_GPIO_INIT(_gpio, PM_GPIO_DIR_IN, PM_GPIO_OUT_BUF_CMOS, 0, \
- _pull, PM_GPIO_VIN_S4, \
- PM_GPIO_STRENGTH_NO, \
- PM_GPIO_FUNC_NORMAL, 0, 0)
-
-#define PM8XXX_GPIO_OUTPUT_FUNC(_gpio, _val, _func) \
- PM8XXX_GPIO_INIT(_gpio, PM_GPIO_DIR_OUT, PM_GPIO_OUT_BUF_CMOS, _val, \
- PM_GPIO_PULL_NO, PM_GPIO_VIN_S4, \
- PM_GPIO_STRENGTH_HIGH, \
- _func, 0, 0)
-
-#define PM8XXX_GPIO_OUTPUT_VIN(_gpio, _val, _vin) \
- PM8XXX_GPIO_INIT(_gpio, PM_GPIO_DIR_OUT, PM_GPIO_OUT_BUF_CMOS, _val, \
- PM_GPIO_PULL_NO, _vin, \
- PM_GPIO_STRENGTH_HIGH, \
- PM_GPIO_FUNC_NORMAL, 0, 0)
-
-/* Initial PM8921 GPIO configurations */
-static struct pm8xxx_gpio_init pm8921_gpios[] __initdata = {
- PM8XXX_GPIO_DISABLE(6), /* Disable unused */
- PM8XXX_GPIO_DISABLE(7), /* Disable NFC */
- PM8XXX_GPIO_INPUT(16, PM_GPIO_PULL_UP_30), /* SD_CARD_WP */
- /* External regulator shared by display and touchscreen on LiQUID */
- PM8XXX_GPIO_OUTPUT(17, 0), /* DISP 3.3 V Boost */
- PM8XXX_GPIO_OUTPUT_VIN(21, 1, PM_GPIO_VIN_VPH), /* Backlight Enable */
- PM8XXX_GPIO_DISABLE(22), /* Disable NFC */
- PM8XXX_GPIO_OUTPUT_FUNC(24, 0, PM_GPIO_FUNC_2), /* Bl: Off, PWM mode */
- PM8XXX_GPIO_INPUT(26, PM_GPIO_PULL_UP_30), /* SD_CARD_DET_N */
- PM8XXX_GPIO_OUTPUT(43, PM_GPIO_PULL_UP_30), /* DISP_RESET_N */
- PM8XXX_GPIO_OUTPUT(42, 0), /* USB 5V reg enable */
-};
-
-/* Initial PM8921 MPP configurations */
-static struct pm8xxx_mpp_init pm8921_mpps[] __initdata = {
- /* External 5V regulator enable; shared by HDMI and USB_OTG switches. */
- PM8XXX_MPP_INIT(7, D_INPUT, PM8921_MPP_DIG_LEVEL_VPH, DIN_TO_INT),
- PM8XXX_MPP_INIT(PM8XXX_AMUX_MPP_8, A_INPUT, PM8XXX_MPP_AIN_AMUX_CH8,
- DOUT_CTRL_LOW),
-};
-
-static void __init pm8921_gpio_mpp_init(void)
-{
- int i, rc;
-
- for (i = 0; i < ARRAY_SIZE(pm8921_gpios); i++) {
- rc = pm8xxx_gpio_config(pm8921_gpios[i].gpio,
- &pm8921_gpios[i].config);
- if (rc) {
- pr_err("%s: pm8xxx_gpio_config: rc=%d\n", __func__, rc);
- break;
- }
- }
-
- for (i = 0; i < ARRAY_SIZE(pm8921_mpps); i++) {
- rc = pm8xxx_mpp_config(pm8921_mpps[i].mpp,
- &pm8921_mpps[i].config);
- if (rc) {
- pr_err("%s: pm8xxx_mpp_config: rc=%d\n", __func__, rc);
- break;
- }
- }
-}
-
-#define KS8851_RST_GPIO 89
-#define KS8851_IRQ_GPIO 90
-
-#if defined(CONFIG_GPIO_SX150X) || defined(CONFIG_GPIO_SX150X_MODULE)
-enum {
- GPIO_EXPANDER_IRQ_BASE = (PM8921_IRQ_BASE + PM8921_NR_IRQS),
- GPIO_EXPANDER_GPIO_BASE = (PM8921_MPP_BASE + PM8921_NR_MPPS),
- /* CAM Expander */
- GPIO_CAM_EXPANDER_BASE = GPIO_EXPANDER_GPIO_BASE,
- GPIO_CAM_GP_STROBE_READY = GPIO_CAM_EXPANDER_BASE,
- GPIO_CAM_GP_AFBUSY,
- GPIO_CAM_GP_STROBE_CE,
- GPIO_CAM_GP_CAM1MP_XCLR,
- GPIO_CAM_GP_CAMIF_RESET_N,
- GPIO_CAM_GP_XMT_FLASH_INT,
- GPIO_CAM_GP_LED_EN1,
- GPIO_CAM_GP_LED_EN2,
-
-};
-#endif
-
-/* The SPI configurations apply to GSBI 1*/
-static struct gpiomux_setting spi_active = {
- .func = GPIOMUX_FUNC_1,
- .drv = GPIOMUX_DRV_12MA,
- .pull = GPIOMUX_PULL_NONE,
-};
-
-static struct gpiomux_setting spi_suspended_config = {
- .func = GPIOMUX_FUNC_GPIO,
- .drv = GPIOMUX_DRV_2MA,
- .pull = GPIOMUX_PULL_DOWN,
-};
-
-static struct gpiomux_setting spi_active_config2 = {
- .func = GPIOMUX_FUNC_2,
- .drv = GPIOMUX_DRV_8MA,
- .pull = GPIOMUX_PULL_NONE,
-};
-
-static struct gpiomux_setting spi_suspended_config2 = {
- .func = GPIOMUX_FUNC_GPIO,
- .drv = GPIOMUX_DRV_2MA,
- .pull = GPIOMUX_PULL_UP,
-};
-
-static struct gpiomux_setting gsbi3_suspended_cfg = {
- .func = GPIOMUX_FUNC_1,
- .drv = GPIOMUX_DRV_2MA,
- .pull = GPIOMUX_PULL_KEEPER,
-};
-
-static struct gpiomux_setting gsbi3_active_cfg = {
- .func = GPIOMUX_FUNC_1,
- .drv = GPIOMUX_DRV_8MA,
- .pull = GPIOMUX_PULL_NONE,
-};
-
-static struct gpiomux_setting gsbi5 = {
- .func = GPIOMUX_FUNC_1,
- .drv = GPIOMUX_DRV_8MA,
- .pull = GPIOMUX_PULL_NONE,
-};
-
-static struct gpiomux_setting gsbi10 = {
- .func = GPIOMUX_FUNC_2,
- .drv = GPIOMUX_DRV_8MA,
- .pull = GPIOMUX_PULL_NONE,
-};
-
-static struct gpiomux_setting gsbi12 = {
- .func = GPIOMUX_FUNC_1,
- .drv = GPIOMUX_DRV_8MA,
- .pull = GPIOMUX_PULL_NONE,
-};
-
-static struct gpiomux_setting cdc_mclk = {
- .func = GPIOMUX_FUNC_1,
- .drv = GPIOMUX_DRV_8MA,
- .pull = GPIOMUX_PULL_NONE,
-};
-
-static struct gpiomux_setting audio_auxpcm[] = {
- /* Suspended state */
- {
- .func = GPIOMUX_FUNC_GPIO,
- .drv = GPIOMUX_DRV_2MA,
- .pull = GPIOMUX_PULL_NONE,
- },
- /* Active state */
- {
- .func = GPIOMUX_FUNC_1,
- .drv = GPIOMUX_DRV_2MA,
- .pull = GPIOMUX_PULL_NONE,
- },
-};
-
-#if defined(CONFIG_KS8851) || defined(CONFIG_KS8851_MODULE)
-static struct gpiomux_setting gpio_eth_config = {
- .pull = GPIOMUX_PULL_NONE,
- .drv = GPIOMUX_DRV_8MA,
- .func = GPIOMUX_FUNC_GPIO,
-};
-#endif
-
-static struct gpiomux_setting slimbus = {
- .func = GPIOMUX_FUNC_1,
- .drv = GPIOMUX_DRV_8MA,
- .pull = GPIOMUX_PULL_KEEPER,
-};
-
-struct msm_gpiomux_config msm8960_gpiomux_configs[NR_GPIO_IRQS] = {
-#if defined(CONFIG_KS8851) || defined(CONFIG_KS8851_MODULE)
- {
- .gpio = KS8851_IRQ_GPIO,
- .settings = {
- [GPIOMUX_SUSPENDED] = &gpio_eth_config,
- }
- },
- {
- .gpio = KS8851_RST_GPIO,
- .settings = {
- [GPIOMUX_SUSPENDED] = &gpio_eth_config,
- }
- },
-#endif
-};
-
-static struct msm_gpiomux_config msm8960_gsbi_configs[] __initdata = {
- {
- .gpio = 6, /* GSBI1 QUP SPI_DATA_MOSI */
- .settings = {
- [GPIOMUX_SUSPENDED] = &spi_suspended_config,
- [GPIOMUX_ACTIVE] = &spi_active,
- },
- },
- {
- .gpio = 7, /* GSBI1 QUP SPI_DATA_MISO */
- .settings = {
- [GPIOMUX_SUSPENDED] = &spi_suspended_config,
- [GPIOMUX_ACTIVE] = &spi_active,
- },
- },
- {
- .gpio = 8, /* GSBI1 QUP SPI_CS_N */
- .settings = {
- [GPIOMUX_SUSPENDED] = &spi_suspended_config,
- [GPIOMUX_ACTIVE] = &spi_active,
- },
- },
- {
- .gpio = 9, /* GSBI1 QUP SPI_CLK */
- .settings = {
- [GPIOMUX_SUSPENDED] = &spi_suspended_config,
- [GPIOMUX_ACTIVE] = &spi_active,
- },
- },
- {
- .gpio = 14, /* GSBI1 SPI_CS_1 */
- .settings = {
- [GPIOMUX_SUSPENDED] = &spi_suspended_config2,
- [GPIOMUX_ACTIVE] = &spi_active_config2,
- },
- },
- {
- .gpio = 16, /* GSBI3 I2C QUP SDA */
- .settings = {
- [GPIOMUX_SUSPENDED] = &gsbi3_suspended_cfg,
- [GPIOMUX_ACTIVE] = &gsbi3_active_cfg,
- },
- },
- {
- .gpio = 17, /* GSBI3 I2C QUP SCL */
- .settings = {
- [GPIOMUX_SUSPENDED] = &gsbi3_suspended_cfg,
- [GPIOMUX_ACTIVE] = &gsbi3_active_cfg,
- },
- },
- {
- .gpio = 22, /* GSBI5 UART2 */
- .settings = {
- [GPIOMUX_SUSPENDED] = &gsbi5,
- },
- },
- {
- .gpio = 23, /* GSBI5 UART2 */
- .settings = {
- [GPIOMUX_SUSPENDED] = &gsbi5,
- },
- },
- {
- .gpio = 24, /* GSBI5 UART2 */
- .settings = {
- [GPIOMUX_SUSPENDED] = &gsbi5,
- },
- },
- {
- .gpio = 25, /* GSBI5 UART2 */
- .settings = {
- [GPIOMUX_SUSPENDED] = &gsbi5,
- },
- },
- {
- .gpio = 44, /* GSBI12 I2C QUP SDA */
- .settings = {
- [GPIOMUX_SUSPENDED] = &gsbi12,
- },
- },
- {
- .gpio = 45, /* GSBI12 I2C QUP SCL */
- .settings = {
- [GPIOMUX_SUSPENDED] = &gsbi12,
- },
- },
- {
- .gpio = 73, /* GSBI10 I2C QUP SDA */
- .settings = {
- [GPIOMUX_SUSPENDED] = &gsbi10,
- },
- },
- {
- .gpio = 74, /* GSBI10 I2C QUP SCL */
- .settings = {
- [GPIOMUX_SUSPENDED] = &gsbi10,
- },
- },
-};
-
-static struct msm_gpiomux_config msm8960_slimbus_config[] __initdata = {
- {
- .gpio = 60, /* slimbus data */
- .settings = {
- [GPIOMUX_SUSPENDED] = &slimbus,
- },
- },
- {
- .gpio = 61, /* slimbus clk */
- .settings = {
- [GPIOMUX_SUSPENDED] = &slimbus,
- },
- },
-};
-
-static struct msm_gpiomux_config msm8960_audio_codec_configs[] __initdata = {
- {
- .gpio = 59,
- .settings = {
- [GPIOMUX_SUSPENDED] = &cdc_mclk,
- },
- },
-};
-
-static struct msm_gpiomux_config msm8960_audio_auxpcm_configs[] __initdata = {
- {
- .gpio = 63,
- .settings = {
- [GPIOMUX_SUSPENDED] = &audio_auxpcm[0],
- [GPIOMUX_ACTIVE] = &audio_auxpcm[1],
- },
- },
- {
- .gpio = 64,
- .settings = {
- [GPIOMUX_SUSPENDED] = &audio_auxpcm[0],
- [GPIOMUX_ACTIVE] = &audio_auxpcm[1],
- },
- },
- {
- .gpio = 65,
- .settings = {
- [GPIOMUX_SUSPENDED] = &audio_auxpcm[0],
- [GPIOMUX_ACTIVE] = &audio_auxpcm[1],
- },
- },
- {
- .gpio = 66,
- .settings = {
- [GPIOMUX_SUSPENDED] = &audio_auxpcm[0],
- [GPIOMUX_ACTIVE] = &audio_auxpcm[1],
- },
- },
-};
-
-static struct gpiomux_setting wcnss_5wire_suspend_cfg = {
- .func = GPIOMUX_FUNC_GPIO,
- .drv = GPIOMUX_DRV_2MA,
- .pull = GPIOMUX_PULL_UP,
-};
-
-static struct gpiomux_setting wcnss_5wire_active_cfg = {
- .func = GPIOMUX_FUNC_1,
- .drv = GPIOMUX_DRV_6MA,
- .pull = GPIOMUX_PULL_DOWN,
-};
-
-static struct msm_gpiomux_config wcnss_5wire_interface[] = {
- {
- .gpio = 84,
- .settings = {
- [GPIOMUX_ACTIVE] = &wcnss_5wire_active_cfg,
- [GPIOMUX_SUSPENDED] = &wcnss_5wire_suspend_cfg,
- },
- },
- {
- .gpio = 85,
- .settings = {
- [GPIOMUX_ACTIVE] = &wcnss_5wire_active_cfg,
- [GPIOMUX_SUSPENDED] = &wcnss_5wire_suspend_cfg,
- },
- },
- {
- .gpio = 86,
- .settings = {
- [GPIOMUX_ACTIVE] = &wcnss_5wire_active_cfg,
- [GPIOMUX_SUSPENDED] = &wcnss_5wire_suspend_cfg,
- },
- },
- {
- .gpio = 87,
- .settings = {
- [GPIOMUX_ACTIVE] = &wcnss_5wire_active_cfg,
- [GPIOMUX_SUSPENDED] = &wcnss_5wire_suspend_cfg,
- },
- },
- {
- .gpio = 88,
- .settings = {
- [GPIOMUX_ACTIVE] = &wcnss_5wire_active_cfg,
- [GPIOMUX_SUSPENDED] = &wcnss_5wire_suspend_cfg,
- },
- },
-};
-static struct gpiomux_setting cam_settings[] = {
- {
- .func = GPIOMUX_FUNC_GPIO, /*suspend*/
- .drv = GPIOMUX_DRV_2MA,
- .pull = GPIOMUX_PULL_DOWN,
- },
-
- {
- .func = GPIOMUX_FUNC_1, /*active 1*/
- .drv = GPIOMUX_DRV_2MA,
- .pull = GPIOMUX_PULL_NONE,
- },
-
- {
- .func = GPIOMUX_FUNC_GPIO, /*active 2*/
- .drv = GPIOMUX_DRV_2MA,
- .pull = GPIOMUX_PULL_NONE,
- },
-
- {
- .func = GPIOMUX_FUNC_1, /*active 3*/
- .drv = GPIOMUX_DRV_8MA,
- .pull = GPIOMUX_PULL_NONE,
- },
-
- {
- .func = GPIOMUX_FUNC_5, /*active 4*/
- .drv = GPIOMUX_DRV_8MA,
- .pull = GPIOMUX_PULL_UP,
- },
-
- {
- .func = GPIOMUX_FUNC_6, /*active 5*/
- .drv = GPIOMUX_DRV_8MA,
- .pull = GPIOMUX_PULL_UP,
- },
-
- {
- .func = GPIOMUX_FUNC_2, /*active 6*/
- .drv = GPIOMUX_DRV_2MA,
- .pull = GPIOMUX_PULL_UP,
- },
-
- {
- .func = GPIOMUX_FUNC_3, /*active 7*/
- .drv = GPIOMUX_DRV_8MA,
- .pull = GPIOMUX_PULL_UP,
- },
-
- {
- .func = GPIOMUX_FUNC_GPIO, /*i2c suspend*/
- .drv = GPIOMUX_DRV_2MA,
- .pull = GPIOMUX_PULL_KEEPER,
- },
-
-};
-
-static struct msm_gpiomux_config msm8960_cam_common_configs[] = {
- {
- .gpio = 2,
- .settings = {
- [GPIOMUX_ACTIVE] = &cam_settings[2],
- [GPIOMUX_SUSPENDED] = &cam_settings[0],
- },
- },
- {
- .gpio = 3,
- .settings = {
- [GPIOMUX_ACTIVE] = &cam_settings[1],
- [GPIOMUX_SUSPENDED] = &cam_settings[0],
- },
- },
- {
- .gpio = 4,
- .settings = {
- [GPIOMUX_ACTIVE] = &cam_settings[1],
- [GPIOMUX_SUSPENDED] = &cam_settings[0],
- },
- },
- {
- .gpio = 5,
- .settings = {
- [GPIOMUX_ACTIVE] = &cam_settings[1],
- [GPIOMUX_SUSPENDED] = &cam_settings[0],
- },
- },
- {
- .gpio = 76,
- .settings = {
- [GPIOMUX_ACTIVE] = &cam_settings[2],
- [GPIOMUX_SUSPENDED] = &cam_settings[0],
- },
- },
- {
- .gpio = 107,
- .settings = {
- [GPIOMUX_ACTIVE] = &cam_settings[2],
- [GPIOMUX_SUSPENDED] = &cam_settings[0],
- },
- },
-};
-
-static struct msm_gpiomux_config msm8960_cam_2d_configs[] = {
- {
- .gpio = 18,
- .settings = {
- [GPIOMUX_ACTIVE] = &cam_settings[3],
- [GPIOMUX_SUSPENDED] = &cam_settings[8],
- },
- },
- {
- .gpio = 19,
- .settings = {
- [GPIOMUX_ACTIVE] = &cam_settings[3],
- [GPIOMUX_SUSPENDED] = &cam_settings[8],
- },
- },
- {
- .gpio = 20,
- .settings = {
- [GPIOMUX_ACTIVE] = &cam_settings[3],
- [GPIOMUX_SUSPENDED] = &cam_settings[8],
- },
- },
- {
- .gpio = 21,
- .settings = {
- [GPIOMUX_ACTIVE] = &cam_settings[3],
- [GPIOMUX_SUSPENDED] = &cam_settings[8],
- },
- },
-};
-
-static struct gpiomux_setting cyts_resout_sus_cfg = {
- .func = GPIOMUX_FUNC_GPIO,
- .drv = GPIOMUX_DRV_6MA,
- .pull = GPIOMUX_PULL_UP,
-};
-
-static struct gpiomux_setting cyts_resout_act_cfg = {
- .func = GPIOMUX_FUNC_GPIO,
- .drv = GPIOMUX_DRV_6MA,
- .pull = GPIOMUX_PULL_UP,
-};
-
-static struct gpiomux_setting cyts_sleep_sus_cfg = {
- .func = GPIOMUX_FUNC_GPIO,
- .drv = GPIOMUX_DRV_6MA,
- .pull = GPIOMUX_PULL_DOWN,
-};
-
-static struct gpiomux_setting cyts_sleep_act_cfg = {
- .func = GPIOMUX_FUNC_GPIO,
- .drv = GPIOMUX_DRV_6MA,
- .pull = GPIOMUX_PULL_DOWN,
-};
-
-static struct gpiomux_setting cyts_int_act_cfg = {
- .func = GPIOMUX_FUNC_GPIO,
- .drv = GPIOMUX_DRV_8MA,
- .pull = GPIOMUX_PULL_UP,
-};
-
-static struct gpiomux_setting cyts_int_sus_cfg = {
- .func = GPIOMUX_FUNC_GPIO,
- .drv = GPIOMUX_DRV_2MA,
- .pull = GPIOMUX_PULL_DOWN,
-};
-
-static struct msm_gpiomux_config msm8960_cyts_configs[] __initdata = {
- { /* TS INTERRUPT */
- .gpio = 11,
- .settings = {
- [GPIOMUX_ACTIVE] = &cyts_int_act_cfg,
- [GPIOMUX_SUSPENDED] = &cyts_int_sus_cfg,
- },
- },
- { /* TS SLEEP */
- .gpio = 50,
- .settings = {
- [GPIOMUX_ACTIVE] = &cyts_sleep_act_cfg,
- [GPIOMUX_SUSPENDED] = &cyts_sleep_sus_cfg,
- },
- },
- { /* TS RESOUT */
- .gpio = 52,
- .settings = {
- [GPIOMUX_ACTIVE] = &cyts_resout_act_cfg,
- [GPIOMUX_SUSPENDED] = &cyts_resout_sus_cfg,
- },
- },
-};
-
-#ifdef CONFIG_USB_EHCI_MSM_HSIC
-static struct gpiomux_setting hsic_act_cfg = {
- .func = GPIOMUX_FUNC_1,
- .drv = GPIOMUX_DRV_12MA,
- .pull = GPIOMUX_PULL_NONE,
-};
-
-static struct gpiomux_setting hsic_sus_cfg = {
- .func = GPIOMUX_FUNC_GPIO,
- .drv = GPIOMUX_DRV_2MA,
- .pull = GPIOMUX_PULL_DOWN,
- .dir = GPIOMUX_OUT_LOW,
-};
-
-static struct gpiomux_setting hsic_hub_act_cfg = {
- .func = GPIOMUX_FUNC_GPIO,
- .drv = GPIOMUX_DRV_2MA,
- .pull = GPIOMUX_PULL_NONE,
-};
-
-static struct msm_gpiomux_config msm8960_hsic_configs[] = {
- {
- .gpio = 150, /*HSIC_STROBE */
- .settings = {
- [GPIOMUX_ACTIVE] = &hsic_act_cfg,
- [GPIOMUX_SUSPENDED] = &hsic_sus_cfg,
- },
- },
- {
- .gpio = 151, /* HSIC_DATA */
- .settings = {
- [GPIOMUX_ACTIVE] = &hsic_act_cfg,
- [GPIOMUX_SUSPENDED] = &hsic_sus_cfg,
- },
- },
- {
- .gpio = 91, /* HSIC_HUB_RESET */
- .settings = {
- [GPIOMUX_ACTIVE] = &hsic_hub_act_cfg,
- [GPIOMUX_SUSPENDED] = &hsic_sus_cfg,
- },
- },
-};
-#endif
-
-#define HAP_SHIFT_LVL_OE_GPIO 47
-
-static struct gpiomux_setting hap_lvl_shft_suspended_config = {
- .func = GPIOMUX_FUNC_GPIO,
- .drv = GPIOMUX_DRV_2MA,
- .pull = GPIOMUX_PULL_DOWN,
-};
-
-static struct gpiomux_setting hap_lvl_shft_active_config = {
- .func = GPIOMUX_FUNC_GPIO,
- .drv = GPIOMUX_DRV_8MA,
- .pull = GPIOMUX_PULL_UP,
-};
-
-static struct msm_gpiomux_config hap_lvl_shft_config[] __initdata = {
- {
- .gpio = HAP_SHIFT_LVL_OE_GPIO,
- .settings = {
- [GPIOMUX_SUSPENDED] = &hap_lvl_shft_suspended_config,
- [GPIOMUX_ACTIVE] = &hap_lvl_shft_active_config,
- },
- },
-};
-
-#if defined(CONFIG_GPIO_SX150X) || defined(CONFIG_GPIO_SX150X_MODULE)
-enum {
- SX150X_CAM,
-};
-
-static struct sx150x_platform_data sx150x_data[] = {
- [SX150X_CAM] = {
- .gpio_base = GPIO_CAM_EXPANDER_BASE,
- .oscio_is_gpo = false,
- .io_pullup_ena = 0x0,
- .io_pulldn_ena = 0xc0,
- .io_open_drain_ena = 0x0,
- .irq_summary = -1,
- },
-};
-
-#endif
-
-#ifdef CONFIG_I2C
-
-#define MSM_8960_GSBI4_QUP_I2C_BUS_ID 4
-#define MSM_8960_GSBI3_QUP_I2C_BUS_ID 3
-#define MSM_8960_GSBI10_QUP_I2C_BUS_ID 10
-
-#if defined(CONFIG_GPIO_SX150X) || defined(CONFIG_GPIO_SX150X_MODULE)
-
-static struct i2c_board_info cam_expander_i2c_info[] = {
- {
- I2C_BOARD_INFO("sx1508q", 0x22),
- .platform_data = &sx150x_data[SX150X_CAM]
- },
-};
-
-static struct msm_cam_expander_info cam_expander_info[] = {
- {
- cam_expander_i2c_info,
- MSM_8960_GSBI4_QUP_I2C_BUS_ID,
- },
-};
-#endif
-#endif
-
-#define MSM_PMEM_ADSP_SIZE 0x3800000
-#define MSM_PMEM_AUDIO_SIZE 0x28B000
-#ifdef CONFIG_FB_MSM_HDMI_AS_PRIMARY
-#define MSM_PMEM_SIZE 0x4000000 /* 64 Mbytes */
-#else
-#define MSM_PMEM_SIZE 0x1C00000 /* 28 Mbytes */
-#endif
-
-
-#ifdef CONFIG_MSM_MULTIMEDIA_USE_ION
-#define MSM_PMEM_KERNEL_EBI1_SIZE 0xB0C000
-#define MSM_ION_EBI_SIZE (MSM_PMEM_SIZE + 0x600000)
-#define MSM_ION_ADSP_SIZE MSM_PMEM_ADSP_SIZE
-#define MSM_ION_HEAP_NUM 4
-#else
-#define MSM_PMEM_KERNEL_EBI1_SIZE 0x110C000
-#define MSM_ION_HEAP_NUM 2
-#endif
-
-#ifdef CONFIG_KERNEL_PMEM_EBI_REGION
-static unsigned pmem_kernel_ebi1_size = MSM_PMEM_KERNEL_EBI1_SIZE;
-static int __init pmem_kernel_ebi1_size_setup(char *p)
-{
- pmem_kernel_ebi1_size = memparse(p, NULL);
- return 0;
-}
-early_param("pmem_kernel_ebi1_size", pmem_kernel_ebi1_size_setup);
-#endif
-
-#ifdef CONFIG_ANDROID_PMEM
-static unsigned pmem_size = MSM_PMEM_SIZE;
-static int __init pmem_size_setup(char *p)
-{
- pmem_size = memparse(p, NULL);
- return 0;
-}
-early_param("pmem_size", pmem_size_setup);
-
-static unsigned pmem_adsp_size = MSM_PMEM_ADSP_SIZE;
-
-static int __init pmem_adsp_size_setup(char *p)
-{
- pmem_adsp_size = memparse(p, NULL);
- return 0;
-}
-early_param("pmem_adsp_size", pmem_adsp_size_setup);
-
-static unsigned pmem_audio_size = MSM_PMEM_AUDIO_SIZE;
-
-static int __init pmem_audio_size_setup(char *p)
-{
- pmem_audio_size = memparse(p, NULL);
- return 0;
-}
-early_param("pmem_audio_size", pmem_audio_size_setup);
-#endif
-
-#ifdef CONFIG_ANDROID_PMEM
-#ifndef CONFIG_MSM_MULTIMEDIA_USE_ION
-static struct android_pmem_platform_data android_pmem_pdata = {
- .name = "pmem",
- .allocator_type = PMEM_ALLOCATORTYPE_ALLORNOTHING,
- .cached = 1,
- .memory_type = MEMTYPE_EBI1,
-};
-
-static struct platform_device android_pmem_device = {
- .name = "android_pmem",
- .id = 0,
- .dev = {.platform_data = &android_pmem_pdata},
-};
-
-static struct android_pmem_platform_data android_pmem_adsp_pdata = {
- .name = "pmem_adsp",
- .allocator_type = PMEM_ALLOCATORTYPE_BITMAP,
- .cached = 0,
- .memory_type = MEMTYPE_EBI1,
-};
-static struct platform_device android_pmem_adsp_device = {
- .name = "android_pmem",
- .id = 2,
- .dev = { .platform_data = &android_pmem_adsp_pdata },
-};
-#endif
-
-static struct android_pmem_platform_data android_pmem_audio_pdata = {
- .name = "pmem_audio",
- .allocator_type = PMEM_ALLOCATORTYPE_BITMAP,
- .cached = 0,
- .memory_type = MEMTYPE_EBI1,
-};
-
-static struct platform_device android_pmem_audio_device = {
- .name = "android_pmem",
- .id = 4,
- .dev = { .platform_data = &android_pmem_audio_pdata },
-};
-#endif
-
-#define DSP_RAM_BASE_8960 0x8da00000
-#define DSP_RAM_SIZE_8960 0x1800000
-static int dspcrashd_pdata_8960 = 0xDEADDEAD;
-
-static struct resource resources_dspcrashd_8960[] = {
- {
- .name = "msm_dspcrashd",
- .start = DSP_RAM_BASE_8960,
- .end = DSP_RAM_BASE_8960 + DSP_RAM_SIZE_8960,
- .flags = IORESOURCE_DMA,
- },
-};
-
-struct platform_device msm_device_dspcrashd_8960 = {
- .name = "msm_dspcrashd",
- .num_resources = ARRAY_SIZE(resources_dspcrashd_8960),
- .resource = resources_dspcrashd_8960,
- .dev = { .platform_data = &dspcrashd_pdata_8960 },
-};
-
-static struct memtype_reserve msm8960_reserve_table[] __initdata = {
- [MEMTYPE_SMI] = {
- },
- [MEMTYPE_EBI0] = {
- .flags = MEMTYPE_FLAGS_1M_ALIGN,
- },
- [MEMTYPE_EBI1] = {
- .flags = MEMTYPE_FLAGS_1M_ALIGN,
- },
-};
-
-static void __init size_pmem_devices(void)
-{
-#ifdef CONFIG_ANDROID_PMEM
-#ifndef CONFIG_MSM_MULTIMEDIA_USE_ION
- android_pmem_adsp_pdata.size = pmem_adsp_size;
- android_pmem_pdata.size = pmem_size;
-#endif
- android_pmem_audio_pdata.size = MSM_PMEM_AUDIO_SIZE;
-#endif
-}
-
-static void __init reserve_memory_for(struct android_pmem_platform_data *p)
-{
- msm8960_reserve_table[p->memory_type].size += p->size;
-}
-
-static void __init reserve_pmem_memory(void)
-{
-#ifdef CONFIG_ANDROID_PMEM
-#ifndef CONFIG_MSM_MULTIMEDIA_USE_ION
- reserve_memory_for(&android_pmem_adsp_pdata);
- reserve_memory_for(&android_pmem_pdata);
-#endif
- reserve_memory_for(&android_pmem_audio_pdata);
- msm8960_reserve_table[MEMTYPE_EBI1].size += pmem_kernel_ebi1_size;
-#endif
-}
-
-static int msm8960_paddr_to_memtype(unsigned int paddr)
-{
- return MEMTYPE_EBI1;
-}
-
-#ifdef CONFIG_ION_MSM
-struct ion_platform_data ion_pdata = {
- .nr = MSM_ION_HEAP_NUM,
- .heaps = {
- {
- .id = ION_HEAP_SYSTEM_ID,
- .type = ION_HEAP_TYPE_SYSTEM,
- .name = ION_KMALLOC_HEAP_NAME,
- },
- {
- .id = ION_HEAP_SYSTEM_CONTIG_ID,
- .type = ION_HEAP_TYPE_SYSTEM_CONTIG,
- .name = ION_VMALLOC_HEAP_NAME,
- },
-#ifdef CONFIG_MSM_MULTIMEDIA_USE_ION
- {
- .id = ION_HEAP_EBI_ID,
- .type = ION_HEAP_TYPE_CARVEOUT,
- .name = ION_EBI1_HEAP_NAME,
- .size = MSM_ION_EBI_SIZE,
- .memory_type = ION_EBI_TYPE,
- },
- {
- .id = ION_HEAP_ADSP_ID,
- .type = ION_HEAP_TYPE_CARVEOUT,
- .name = ION_ADSP_HEAP_NAME,
- .size = MSM_ION_ADSP_SIZE,
- .memory_type = ION_EBI_TYPE,
- },
-#endif
- }
-};
-
-struct platform_device ion_dev = {
- .name = "ion-msm",
- .id = 1,
- .dev = { .platform_data = &ion_pdata },
-};
-#endif
-
-static void reserve_ion_memory(void)
-{
-#if defined(CONFIG_ION_MSM) && defined(CONFIG_MSM_MULTIMEDIA_USE_ION)
- msm8960_reserve_table[MEMTYPE_EBI1].size += MSM_ION_EBI_SIZE;
- msm8960_reserve_table[MEMTYPE_EBI1].size += MSM_ION_ADSP_SIZE;
-#endif
-}
-static void __init msm8960_calculate_reserve_sizes(void)
-{
- size_pmem_devices();
- reserve_pmem_memory();
- reserve_ion_memory();
-}
-
-static struct reserve_info msm8960_reserve_info __initdata = {
- .memtype_reserve_table = msm8960_reserve_table,
- .calculate_reserve_sizes = msm8960_calculate_reserve_sizes,
- .paddr_to_memtype = msm8960_paddr_to_memtype,
-};
-
-static int msm8960_memory_bank_size(void)
-{
- return 1<<29;
-}
-
-static void __init locate_unstable_memory(void)
-{
- struct membank *mb = &meminfo.bank[meminfo.nr_banks - 1];
- unsigned long bank_size;
- unsigned long low, high;
-
- bank_size = msm8960_memory_bank_size();
- low = meminfo.bank[0].start;
- high = mb->start + mb->size;
-
- /* Check if 32 bit overflow occured */
- if (high < mb->start)
- high = ~0UL;
-
- low &= ~(bank_size - 1);
-
- if (high - low <= bank_size)
- return;
- msm8960_reserve_info.low_unstable_address = low + bank_size;
- /* To avoid overflow of u32 compute max_unstable_size
- * by first subtracting low from mb->start)
- * */
- msm8960_reserve_info.max_unstable_size = (mb->start - low) +
- mb->size - bank_size;
-
- msm8960_reserve_info.bank_size = bank_size;
- pr_info("low unstable address %lx max size %lx bank size %lx\n",
- msm8960_reserve_info.low_unstable_address,
- msm8960_reserve_info.max_unstable_size,
- msm8960_reserve_info.bank_size);
-}
-
-static void __init place_movable_zone(void)
-{
- movable_reserved_start = msm8960_reserve_info.low_unstable_address;
- movable_reserved_size = msm8960_reserve_info.max_unstable_size;
- pr_info("movable zone start %lx size %lx\n",
- movable_reserved_start, movable_reserved_size);
-}
-
-static void __init msm8960_early_memory(void)
-{
- reserve_info = &msm8960_reserve_info;
- locate_unstable_memory();
- place_movable_zone();
-}
-
-static void __init msm8960_reserve(void)
-{
- msm_reserve();
-}
-
-static int msm8960_change_memory_power(u64 start, u64 size,
- int change_type)
-{
- return soc_change_memory_power(start, size, change_type);
-}
-
-#ifdef CONFIG_MSM_CAMERA
-
-static uint16_t msm_cam_gpio_2d_tbl[] = {
- 5, /*CAMIF_MCLK*/
- 20, /*CAMIF_I2C_DATA*/
- 21, /*CAMIF_I2C_CLK*/
-};
-
-static struct msm_camera_gpio_conf gpio_conf = {
- .cam_gpiomux_conf_tbl = msm8960_cam_2d_configs,
- .cam_gpiomux_conf_tbl_size = ARRAY_SIZE(msm8960_cam_2d_configs),
- .cam_gpio_tbl = msm_cam_gpio_2d_tbl,
- .cam_gpio_tbl_size = ARRAY_SIZE(msm_cam_gpio_2d_tbl),
-};
-
-#define VFE_CAMIF_TIMER1_GPIO 2
-#define VFE_CAMIF_TIMER2_GPIO 3
-#define VFE_CAMIF_TIMER3_GPIO_INT 4
-struct msm_camera_sensor_strobe_flash_data strobe_flash_xenon = {
- .flash_trigger = VFE_CAMIF_TIMER2_GPIO,
- .flash_charge = VFE_CAMIF_TIMER1_GPIO,
- .flash_charge_done = VFE_CAMIF_TIMER3_GPIO_INT,
- .flash_recharge_duration = 50000,
- .irq = MSM_GPIO_TO_INT(VFE_CAMIF_TIMER3_GPIO_INT),
-};
-
-#ifdef CONFIG_MSM_CAMERA_FLASH
-static struct msm_camera_sensor_flash_src msm_flash_src = {
- .flash_sr_type = MSM_CAMERA_FLASH_SRC_EXT,
- ._fsrc.ext_driver_src.led_en = GPIO_CAM_GP_LED_EN1,
- ._fsrc.ext_driver_src.led_flash_en = GPIO_CAM_GP_LED_EN2,
-#if defined(CONFIG_I2C) && (defined(CONFIG_GPIO_SX150X) || \
- defined(CONFIG_GPIO_SX150X_MODULE))
- ._fsrc.ext_driver_src.expander_info = cam_expander_info,
-#endif
-};
-#endif
-
-static struct msm_bus_vectors cam_init_vectors[] = {
- {
- .src = MSM_BUS_MASTER_VFE,
- .dst = MSM_BUS_SLAVE_EBI_CH0,
- .ab = 0,
- .ib = 0,
- },
- {
- .src = MSM_BUS_MASTER_VPE,
- .dst = MSM_BUS_SLAVE_EBI_CH0,
- .ab = 0,
- .ib = 0,
- },
- {
- .src = MSM_BUS_MASTER_JPEG_ENC,
- .dst = MSM_BUS_SLAVE_EBI_CH0,
- .ab = 0,
- .ib = 0,
- },
-};
-
-static struct msm_bus_vectors cam_preview_vectors[] = {
- {
- .src = MSM_BUS_MASTER_VFE,
- .dst = MSM_BUS_SLAVE_EBI_CH0,
- .ab = 27648000,
- .ib = 110592000,
- },
- {
- .src = MSM_BUS_MASTER_VPE,
- .dst = MSM_BUS_SLAVE_EBI_CH0,
- .ab = 0,
- .ib = 0,
- },
- {
- .src = MSM_BUS_MASTER_JPEG_ENC,
- .dst = MSM_BUS_SLAVE_EBI_CH0,
- .ab = 0,
- .ib = 0,
- },
-};
-
-static struct msm_bus_vectors cam_video_vectors[] = {
- {
- .src = MSM_BUS_MASTER_VFE,
- .dst = MSM_BUS_SLAVE_EBI_CH0,
- .ab = 140451840,
- .ib = 561807360,
- },
- {
- .src = MSM_BUS_MASTER_VPE,
- .dst = MSM_BUS_SLAVE_EBI_CH0,
- .ab = 206807040,
- .ib = 488816640,
- },
- {
- .src = MSM_BUS_MASTER_JPEG_ENC,
- .dst = MSM_BUS_SLAVE_EBI_CH0,
- .ab = 0,
- .ib = 0,
- },
-};
-
-static struct msm_bus_vectors cam_snapshot_vectors[] = {
- {
- .src = MSM_BUS_MASTER_VFE,
- .dst = MSM_BUS_SLAVE_EBI_CH0,
- .ab = 274423680,
- .ib = 1097694720,
- },
- {
- .src = MSM_BUS_MASTER_VPE,
- .dst = MSM_BUS_SLAVE_EBI_CH0,
- .ab = 0,
- .ib = 0,
- },
- {
- .src = MSM_BUS_MASTER_JPEG_ENC,
- .dst = MSM_BUS_SLAVE_EBI_CH0,
- .ab = 540000000,
- .ib = 1350000000,
- },
-};
-
-static struct msm_bus_vectors cam_zsl_vectors[] = {
- {
- .src = MSM_BUS_MASTER_VFE,
- .dst = MSM_BUS_SLAVE_EBI_CH0,
- .ab = 302071680,
- .ib = 1208286720,
- },
- {
- .src = MSM_BUS_MASTER_VPE,
- .dst = MSM_BUS_SLAVE_EBI_CH0,
- .ab = 0,
- .ib = 0,
- },
- {
- .src = MSM_BUS_MASTER_JPEG_ENC,
- .dst = MSM_BUS_SLAVE_EBI_CH0,
- .ab = 540000000,
- .ib = 1350000000,
- },
-};
-
-static struct msm_bus_paths cam_bus_client_config[] = {
- {
- ARRAY_SIZE(cam_init_vectors),
- cam_init_vectors,
- },
- {
- ARRAY_SIZE(cam_preview_vectors),
- cam_preview_vectors,
- },
- {
- ARRAY_SIZE(cam_video_vectors),
- cam_video_vectors,
- },
- {
- ARRAY_SIZE(cam_snapshot_vectors),
- cam_snapshot_vectors,
- },
- {
- ARRAY_SIZE(cam_zsl_vectors),
- cam_zsl_vectors,
- },
-};
-
-static struct msm_bus_scale_pdata cam_bus_client_pdata = {
- cam_bus_client_config,
- ARRAY_SIZE(cam_bus_client_config),
- .name = "msm_camera",
-};
-
-struct msm_camera_device_platform_data msm_camera_csi_device_data[] = {
- {
- .ioclk.mclk_clk_rate = 24000000,
- .ioclk.vfe_clk_rate = 228570000,
- .csid_core = 0,
- .cam_bus_scale_table = &cam_bus_client_pdata,
- },
- {
- .ioclk.mclk_clk_rate = 24000000,
- .ioclk.vfe_clk_rate = 228570000,
- .csid_core = 1,
- .cam_bus_scale_table = &cam_bus_client_pdata,
- },
-};
-
-#ifdef CONFIG_IMX074_ACT
-static struct i2c_board_info imx074_actuator_i2c_info = {
- I2C_BOARD_INFO("imx074_act", 0x11),
-};
-
-static struct msm_actuator_info imx074_actuator_info = {
- .board_info = &imx074_actuator_i2c_info,
- .bus_id = MSM_8960_GSBI4_QUP_I2C_BUS_ID,
- .vcm_pwd = 0,
- .vcm_enable = 1,
-};
-#endif
-
-#ifdef CONFIG_IMX074
-static struct msm_camera_sensor_flash_data flash_imx074 = {
- .flash_type = MSM_CAMERA_FLASH_LED,
-#ifdef CONFIG_MSM_CAMERA_FLASH
- .flash_src = &msm_flash_src
-#endif
-};
-
-static struct msm_camera_sensor_platform_info sensor_board_info_imx074 = {
- .mount_angle = 90,
- .sensor_reset = 107,
- .sensor_pwd = 85,
- .vcm_pwd = 0,
- .vcm_enable = 1,
-};
-
-static struct msm_camera_sensor_info msm_camera_sensor_imx074_data = {
- .sensor_name = "imx074",
- .pdata = &msm_camera_csi_device_data[0],
- .flash_data = &flash_imx074,
- .strobe_flash_data = &strobe_flash_xenon,
- .sensor_platform_info = &sensor_board_info_imx074,
- .gpio_conf = &gpio_conf,
- .csi_if = 1,
- .camera_type = BACK_CAMERA_2D,
-#ifdef CONFIG_IMX074_ACT
- .actuator_info = &imx074_actuator_info
-#endif
-};
-
-struct platform_device msm8960_camera_sensor_imx074 = {
- .name = "msm_camera_imx074",
- .dev = {
- .platform_data = &msm_camera_sensor_imx074_data,
- },
-};
-#endif
-#ifdef CONFIG_OV2720
-static struct msm_camera_sensor_flash_data flash_ov2720 = {
- .flash_type = MSM_CAMERA_FLASH_NONE,
-};
-
-static struct msm_camera_sensor_platform_info sensor_board_info_ov2720 = {
- .mount_angle = 0,
- .sensor_reset = 76,
- .sensor_pwd = 85,
- .vcm_pwd = 0,
- .vcm_enable = 1,
-};
-
-static struct msm_camera_sensor_info msm_camera_sensor_ov2720_data = {
- .sensor_name = "ov2720",
- .pdata = &msm_camera_csi_device_data[1],
- .flash_data = &flash_ov2720,
- .sensor_platform_info = &sensor_board_info_ov2720,
- .gpio_conf = &gpio_conf,
- .csi_if = 1,
- .camera_type = FRONT_CAMERA_2D,
-};
-
-struct platform_device msm8960_camera_sensor_ov2720 = {
- .name = "msm_camera_ov2720",
- .dev = {
- .platform_data = &msm_camera_sensor_ov2720_data,
- },
-};
-#endif
-
-static struct msm8960_privacy_light_cfg privacy_light_info = {
- .mpp = PM8921_MPP_PM_TO_SYS(12),
-};
-
-static void __init msm8960_init_cam(void)
-{
- int i;
- struct platform_device *cam_dev[] = {
- &msm8960_camera_sensor_imx074,
- &msm8960_camera_sensor_ov2720,
- };
-
- if (machine_is_msm8960_liquid()) {
- struct msm_camera_sensor_info *s_info;
- s_info = msm8960_camera_sensor_imx074.dev.platform_data;
- s_info->sensor_platform_info->mount_angle = 180;
- s_info = msm8960_camera_sensor_ov2720.dev.platform_data;
- s_info->sensor_platform_info->privacy_light = 1;
- s_info->sensor_platform_info->privacy_light_info =
- &privacy_light_info;
- }
-
- for (i = 0; i < ARRAY_SIZE(cam_dev); i++) {
- struct msm_camera_sensor_info *s_info;
- s_info = cam_dev[i]->dev.platform_data;
- msm_get_cam_resources(s_info);
- platform_device_register(cam_dev[i]);
- }
-
- platform_device_register(&msm8960_device_csiphy0);
- platform_device_register(&msm8960_device_csiphy1);
- platform_device_register(&msm8960_device_csid0);
- platform_device_register(&msm8960_device_csid1);
- platform_device_register(&msm8960_device_ispif);
- platform_device_register(&msm8960_device_vfe);
- platform_device_register(&msm8960_device_vpe);
-}
-#endif
-
-#ifdef CONFIG_FB_MSM_TRIPLE_BUFFER
-#define MSM_FB_PRIM_BUF_SIZE (1376 * 768 * 4 * 3) /* 4 bpp x 3 pages */
-#else
-#define MSM_FB_PRIM_BUF_SIZE (1376 * 768 * 4 * 2) /* 4 bpp x 2 pages */
-#endif
-
-
-#ifdef CONFIG_FB_MSM_HDMI_MSM_PANEL
-#define MSM_FB_EXT_BUF_SIZE (1920 * 1088 * 2 * 1) /* 2 bpp x 1 page */
-#elif defined(CONFIG_FB_MSM_TVOUT)
-#define MSM_FB_EXT_BUF_SIZE (720 * 576 * 2 * 2) /* 2 bpp x 2 pages */
-#else
-#define MSM_FB_EXT_BUF_SIZE 0
-#endif
-
-#ifdef CONFIG_FB_MSM_OVERLAY_WRITEBACK
-/* width x height x 3 bpp x 2 frame buffer */
-#define MSM_FB_WRITEBACK_SIZE (1376 * 768 * 3 * 2)
-#define MSM_FB_WRITEBACK_OFFSET \
- (MSM_FB_PRIM_BUF_SIZE + MSM_FB_EXT_BUF_SIZE)
-#else
-#define MSM_FB_WRITEBACK_SIZE 0
-#define MSM_FB_WRITEBACK_OFFSET 0
-#endif
-
-#ifdef CONFIG_FB_MSM_HDMI_AS_PRIMARY
-/* 4 bpp x 2 page HDMI case */
-#define MSM_FB_SIZE roundup((1920 * 1088 * 4 * 2), 4096)
-#else
-/* Note: must be multiple of 4096 */
-#define MSM_FB_SIZE roundup(MSM_FB_PRIM_BUF_SIZE + MSM_FB_EXT_BUF_SIZE + \
- MSM_FB_WRITEBACK_SIZE, 4096)
-#endif
-
-static int writeback_offset(void)
-{
- return MSM_FB_WRITEBACK_OFFSET;
-}
-
-
-#define MDP_VSYNC_GPIO 0
-
-#define PANEL_NAME_MAX_LEN 30
-#define MIPI_CMD_NOVATEK_QHD_PANEL_NAME "mipi_cmd_novatek_qhd"
-#define MIPI_VIDEO_NOVATEK_QHD_PANEL_NAME "mipi_video_novatek_qhd"
-#define MIPI_VIDEO_TOSHIBA_WSVGA_PANEL_NAME "mipi_video_toshiba_wsvga"
-#define MIPI_VIDEO_CHIMEI_WXGA_PANEL_NAME "mipi_video_chimei_wxga"
-#define MIPI_VIDEO_SIMULATOR_VGA_PANEL_NAME "mipi_video_simulator_vga"
-#define MIPI_CMD_RENESAS_FWVGA_PANEL_NAME "mipi_cmd_renesas_fwvga"
-#define HDMI_PANEL_NAME "hdmi_msm"
-#define TVOUT_PANEL_NAME "tvout_msm"
-
-static struct resource msm_fb_resources[] = {
- {
- .flags = IORESOURCE_DMA,
- }
-};
-
-static int msm_fb_detect_panel(const char *name)
-{
- if (machine_is_msm8960_liquid()) {
- if (!strncmp(name, MIPI_VIDEO_CHIMEI_WXGA_PANEL_NAME,
- strnlen(MIPI_VIDEO_CHIMEI_WXGA_PANEL_NAME,
- PANEL_NAME_MAX_LEN)))
- return 0;
- } else {
- if (!strncmp(name, MIPI_VIDEO_TOSHIBA_WSVGA_PANEL_NAME,
- strnlen(MIPI_VIDEO_TOSHIBA_WSVGA_PANEL_NAME,
- PANEL_NAME_MAX_LEN)))
- return 0;
-
-#ifndef CONFIG_FB_MSM_MIPI_PANEL_DETECT
- if (!strncmp(name, MIPI_VIDEO_NOVATEK_QHD_PANEL_NAME,
- strnlen(MIPI_VIDEO_NOVATEK_QHD_PANEL_NAME,
- PANEL_NAME_MAX_LEN)))
- return 0;
-
- if (!strncmp(name, MIPI_CMD_NOVATEK_QHD_PANEL_NAME,
- strnlen(MIPI_CMD_NOVATEK_QHD_PANEL_NAME,
- PANEL_NAME_MAX_LEN)))
- return 0;
-
- if (!strncmp(name, MIPI_VIDEO_SIMULATOR_VGA_PANEL_NAME,
- strnlen(MIPI_VIDEO_SIMULATOR_VGA_PANEL_NAME,
- PANEL_NAME_MAX_LEN)))
- return 0;
-
- if (!strncmp(name, MIPI_CMD_RENESAS_FWVGA_PANEL_NAME,
- strnlen(MIPI_CMD_RENESAS_FWVGA_PANEL_NAME,
- PANEL_NAME_MAX_LEN)))
- return 0;
-#endif
- }
-
- if (!strncmp(name, HDMI_PANEL_NAME,
- strnlen(HDMI_PANEL_NAME,
- PANEL_NAME_MAX_LEN)))
- return 0;
-
- if (!strncmp(name, TVOUT_PANEL_NAME,
- strnlen(TVOUT_PANEL_NAME,
- PANEL_NAME_MAX_LEN)))
- return 0;
-
- pr_warning("%s: not supported '%s'", __func__, name);
- return -ENODEV;
-}
-
-static struct msm_fb_platform_data msm_fb_pdata = {
- .detect_client = msm_fb_detect_panel,
-};
-
-static struct platform_device msm_fb_device = {
- .name = "msm_fb",
- .id = 0,
- .num_resources = ARRAY_SIZE(msm_fb_resources),
- .resource = msm_fb_resources,
- .dev.platform_data = &msm_fb_pdata,
-};
-
-static bool dsi_power_on;
-
-/**
- * LiQUID panel on/off
- *
- * @param on
- *
- * @return int
- */
-static int mipi_dsi_liquid_panel_power(int on)
-{
- static struct regulator *reg_l2, *reg_ext_3p3v;
- static int gpio21, gpio24, gpio43;
- int rc;
-
- pr_info("%s: on=%d\n", __func__, on);
-
- gpio21 = PM8921_GPIO_PM_TO_SYS(21); /* disp power enable_n */
- gpio43 = PM8921_GPIO_PM_TO_SYS(43); /* Displays Enable (rst_n)*/
- gpio24 = PM8921_GPIO_PM_TO_SYS(24); /* Backlight PWM */
-
- if (!dsi_power_on) {
-
- reg_l2 = regulator_get(&msm_mipi_dsi1_device.dev,
- "dsi_vdda");
- if (IS_ERR(reg_l2)) {
- pr_err("could not get 8921_l2, rc = %ld\n",
- PTR_ERR(reg_l2));
- return -ENODEV;
- }
-
- rc = regulator_set_voltage(reg_l2, 1200000, 1200000);
- if (rc) {
- pr_err("set_voltage l2 failed, rc=%d\n", rc);
- return -EINVAL;
- }
-
- reg_ext_3p3v = regulator_get(&msm_mipi_dsi1_device.dev,
- "vdd_lvds_3p3v");
- if (IS_ERR(reg_ext_3p3v)) {
- pr_err("could not get reg_ext_3p3v, rc = %ld\n",
- PTR_ERR(reg_ext_3p3v));
- return -ENODEV;
- }
-
- rc = gpio_request(gpio21, "disp_pwr_en_n");
- if (rc) {
- pr_err("request gpio 21 failed, rc=%d\n", rc);
- return -ENODEV;
- }
-
- rc = gpio_request(gpio43, "disp_rst_n");
- if (rc) {
- pr_err("request gpio 43 failed, rc=%d\n", rc);
- return -ENODEV;
- }
-
- rc = gpio_request(gpio24, "disp_backlight_pwm");
- if (rc) {
- pr_err("request gpio 24 failed, rc=%d\n", rc);
- return -ENODEV;
- }
-
- dsi_power_on = true;
- }
-
- if (on) {
- rc = regulator_set_optimum_mode(reg_l2, 100000);
- if (rc < 0) {
- pr_err("set_optimum_mode l2 failed, rc=%d\n", rc);
- return -EINVAL;
- }
- rc = regulator_enable(reg_l2);
- if (rc) {
- pr_err("enable l2 failed, rc=%d\n", rc);
- return -ENODEV;
- }
-
- rc = regulator_enable(reg_ext_3p3v);
- if (rc) {
- pr_err("enable reg_ext_3p3v failed, rc=%d\n", rc);
- return -ENODEV;
- }
-
- /* set reset pin before power enable */
- gpio_set_value_cansleep(gpio43, 0); /* disp disable (resx=0) */
-
- gpio_set_value_cansleep(gpio21, 0); /* disp power enable_n */
- msleep(20);
- gpio_set_value_cansleep(gpio43, 1); /* disp enable */
- msleep(20);
- gpio_set_value_cansleep(gpio43, 0); /* disp enable */
- msleep(20);
- gpio_set_value_cansleep(gpio43, 1); /* disp enable */
- msleep(20);
- } else {
- gpio_set_value_cansleep(gpio43, 0);
- gpio_set_value_cansleep(gpio21, 1);
-
- rc = regulator_disable(reg_l2);
- if (rc) {
- pr_err("disable reg_l2 failed, rc=%d\n", rc);
- return -ENODEV;
- }
- rc = regulator_disable(reg_ext_3p3v);
- if (rc) {
- pr_err("disable reg_ext_3p3v failed, rc=%d\n", rc);
- return -ENODEV;
- }
- rc = regulator_set_optimum_mode(reg_l2, 100);
- if (rc < 0) {
- pr_err("set_optimum_mode l2 failed, rc=%d\n", rc);
- return -EINVAL;
- }
- }
-
- return 0;
-}
-
-static int mipi_dsi_cdp_panel_power(int on)
-{
- static struct regulator *reg_l8, *reg_l23, *reg_l2;
- static int gpio43;
- int rc;
-
- pr_info("%s: state : %d\n", __func__, on);
-
- if (!dsi_power_on) {
-
- reg_l8 = regulator_get(&msm_mipi_dsi1_device.dev,
- "dsi_vdc");
- if (IS_ERR(reg_l8)) {
- pr_err("could not get 8921_l8, rc = %ld\n",
- PTR_ERR(reg_l8));
- return -ENODEV;
- }
- reg_l23 = regulator_get(&msm_mipi_dsi1_device.dev,
- "dsi_vddio");
- if (IS_ERR(reg_l23)) {
- pr_err("could not get 8921_l23, rc = %ld\n",
- PTR_ERR(reg_l23));
- return -ENODEV;
- }
- reg_l2 = regulator_get(&msm_mipi_dsi1_device.dev,
- "dsi_vdda");
- if (IS_ERR(reg_l2)) {
- pr_err("could not get 8921_l2, rc = %ld\n",
- PTR_ERR(reg_l2));
- return -ENODEV;
- }
- rc = regulator_set_voltage(reg_l8, 2800000, 3000000);
- if (rc) {
- pr_err("set_voltage l8 failed, rc=%d\n", rc);
- return -EINVAL;
- }
- rc = regulator_set_voltage(reg_l23, 1800000, 1800000);
- if (rc) {
- pr_err("set_voltage l23 failed, rc=%d\n", rc);
- return -EINVAL;
- }
- rc = regulator_set_voltage(reg_l2, 1200000, 1200000);
- if (rc) {
- pr_err("set_voltage l2 failed, rc=%d\n", rc);
- return -EINVAL;
- }
- gpio43 = PM8921_GPIO_PM_TO_SYS(43);
- rc = gpio_request(gpio43, "disp_rst_n");
- if (rc) {
- pr_err("request gpio 43 failed, rc=%d\n", rc);
- return -ENODEV;
- }
- dsi_power_on = true;
- }
- if (on) {
- rc = regulator_set_optimum_mode(reg_l8, 100000);
- if (rc < 0) {
- pr_err("set_optimum_mode l8 failed, rc=%d\n", rc);
- return -EINVAL;
- }
- rc = regulator_set_optimum_mode(reg_l23, 100000);
- if (rc < 0) {
- pr_err("set_optimum_mode l23 failed, rc=%d\n", rc);
- return -EINVAL;
- }
- rc = regulator_set_optimum_mode(reg_l2, 100000);
- if (rc < 0) {
- pr_err("set_optimum_mode l2 failed, rc=%d\n", rc);
- return -EINVAL;
- }
- rc = regulator_enable(reg_l8);
- if (rc) {
- pr_err("enable l8 failed, rc=%d\n", rc);
- return -ENODEV;
- }
- rc = regulator_enable(reg_l23);
- if (rc) {
- pr_err("enable l8 failed, rc=%d\n", rc);
- return -ENODEV;
- }
- rc = regulator_enable(reg_l2);
- if (rc) {
- pr_err("enable l2 failed, rc=%d\n", rc);
- return -ENODEV;
- }
- gpio_set_value_cansleep(gpio43, 1);
- } else {
- rc = regulator_disable(reg_l2);
- if (rc) {
- pr_err("disable reg_l2 failed, rc=%d\n", rc);
- return -ENODEV;
- }
- rc = regulator_disable(reg_l8);
- if (rc) {
- pr_err("disable reg_l8 failed, rc=%d\n", rc);
- return -ENODEV;
- }
- rc = regulator_disable(reg_l23);
- if (rc) {
- pr_err("disable reg_l23 failed, rc=%d\n", rc);
- return -ENODEV;
- }
- rc = regulator_set_optimum_mode(reg_l8, 100);
- if (rc < 0) {
- pr_err("set_optimum_mode l8 failed, rc=%d\n", rc);
- return -EINVAL;
- }
- rc = regulator_set_optimum_mode(reg_l23, 100);
- if (rc < 0) {
- pr_err("set_optimum_mode l23 failed, rc=%d\n", rc);
- return -EINVAL;
- }
- rc = regulator_set_optimum_mode(reg_l2, 100);
- if (rc < 0) {
- pr_err("set_optimum_mode l2 failed, rc=%d\n", rc);
- return -EINVAL;
- }
- gpio_set_value_cansleep(gpio43, 0);
- }
- return 0;
-}
-
-static int mipi_dsi_panel_power(int on)
-{
- int ret;
-
- pr_info("%s: on=%d\n", __func__, on);
-
- if (machine_is_msm8960_liquid())
- ret = mipi_dsi_liquid_panel_power(on);
- else
- ret = mipi_dsi_cdp_panel_power(on);
-
- return ret;
-}
-
-static struct mipi_dsi_platform_data mipi_dsi_pdata = {
- .vsync_gpio = MDP_VSYNC_GPIO,
- .dsi_power_save = mipi_dsi_panel_power,
-};
-
-#ifdef CONFIG_MSM_BUS_SCALING
-
-static struct msm_bus_vectors mdp_init_vectors[] = {
- {
- .src = MSM_BUS_MASTER_MDP_PORT0,
- .dst = MSM_BUS_SLAVE_EBI_CH0,
- .ab = 0,
- .ib = 0,
- },
-};
-
-#ifdef CONFIG_FB_MSM_HDMI_AS_PRIMARY
-static struct msm_bus_vectors hdmi_as_primary_vectors[] = {
- /* If HDMI is used as primary */
- {
- .src = MSM_BUS_MASTER_MDP_PORT0,
- .dst = MSM_BUS_SLAVE_EBI_CH0,
- .ab = 2000000000,
- .ib = 2000000000,
- },
-};
-static struct msm_bus_paths mdp_bus_scale_usecases[] = {
- {
- ARRAY_SIZE(mdp_init_vectors),
- mdp_init_vectors,
- },
- {
- ARRAY_SIZE(hdmi_as_primary_vectors),
- hdmi_as_primary_vectors,
- },
- {
- ARRAY_SIZE(hdmi_as_primary_vectors),
- hdmi_as_primary_vectors,
- },
- {
- ARRAY_SIZE(hdmi_as_primary_vectors),
- hdmi_as_primary_vectors,
- },
- {
- ARRAY_SIZE(hdmi_as_primary_vectors),
- hdmi_as_primary_vectors,
- },
- {
- ARRAY_SIZE(hdmi_as_primary_vectors),
- hdmi_as_primary_vectors,
- },
-};
-#else
-static struct msm_bus_vectors mdp_ui_vectors[] = {
- {
- .src = MSM_BUS_MASTER_MDP_PORT0,
- .dst = MSM_BUS_SLAVE_EBI_CH0,
- .ab = 216000000 * 2,
- .ib = 270000000 * 2,
- },
-};
-
-static struct msm_bus_vectors mdp_vga_vectors[] = {
- /* VGA and less video */
- {
- .src = MSM_BUS_MASTER_MDP_PORT0,
- .dst = MSM_BUS_SLAVE_EBI_CH0,
- .ab = 216000000 * 2,
- .ib = 270000000 * 2,
- },
-};
-
-static struct msm_bus_vectors mdp_720p_vectors[] = {
- /* 720p and less video */
- {
- .src = MSM_BUS_MASTER_MDP_PORT0,
- .dst = MSM_BUS_SLAVE_EBI_CH0,
- .ab = 230400000 * 2,
- .ib = 288000000 * 2,
- },
-};
-
-static struct msm_bus_vectors mdp_1080p_vectors[] = {
- /* 1080p and less video */
- {
- .src = MSM_BUS_MASTER_MDP_PORT0,
- .dst = MSM_BUS_SLAVE_EBI_CH0,
- .ab = 334080000 * 2,
- .ib = 417600000 * 2,
- },
-};
-
-static struct msm_bus_paths mdp_bus_scale_usecases[] = {
- {
- ARRAY_SIZE(mdp_init_vectors),
- mdp_init_vectors,
- },
- {
- ARRAY_SIZE(mdp_ui_vectors),
- mdp_ui_vectors,
- },
- {
- ARRAY_SIZE(mdp_ui_vectors),
- mdp_ui_vectors,
- },
- {
- ARRAY_SIZE(mdp_vga_vectors),
- mdp_vga_vectors,
- },
- {
- ARRAY_SIZE(mdp_720p_vectors),
- mdp_720p_vectors,
- },
- {
- ARRAY_SIZE(mdp_1080p_vectors),
- mdp_1080p_vectors,
- },
-};
-#endif
-
-static struct msm_bus_scale_pdata mdp_bus_scale_pdata = {
- mdp_bus_scale_usecases,
- ARRAY_SIZE(mdp_bus_scale_usecases),
- .name = "mdp",
-};
-
-#endif
-
-#ifdef CONFIG_FB_MSM_HDMI_AS_PRIMARY
-int mdp_core_clk_rate_table[] = {
- 200000000,
- 200000000,
- 200000000,
- 200000000,
-};
-#else
-int mdp_core_clk_rate_table[] = {
- 85330000,
- 85330000,
- 160000000,
- 200000000,
-};
-#endif
-
-static struct msm_panel_common_pdata mdp_pdata = {
- .gpio = MDP_VSYNC_GPIO,
-#ifdef CONFIG_FB_MSM_HDMI_AS_PRIMARY
- .mdp_core_clk_rate = 200000000,
-#else
- .mdp_core_clk_rate = 85330000,
-#endif
- .mdp_core_clk_table = mdp_core_clk_rate_table,
- .num_mdp_clk = ARRAY_SIZE(mdp_core_clk_rate_table),
-#ifdef CONFIG_MSM_BUS_SCALING
- .mdp_bus_scale_table = &mdp_bus_scale_pdata,
-#endif
- .mdp_rev = MDP_REV_42,
- .writeback_offset = writeback_offset,
-};
-
-static struct platform_device mipi_dsi_renesas_panel_device = {
- .name = "mipi_renesas",
- .id = 0,
-};
-
-static struct platform_device mipi_dsi_simulator_panel_device = {
- .name = "mipi_simulator",
- .id = 0,
-};
-
-#define LPM_CHANNEL0 0
-static int toshiba_gpio[] = {LPM_CHANNEL0};
-
-static struct mipi_dsi_panel_platform_data toshiba_pdata = {
- .gpio = toshiba_gpio,
-};
-
-static struct platform_device mipi_dsi_toshiba_panel_device = {
- .name = "mipi_toshiba",
- .id = 0,
- .dev = {
- .platform_data = &toshiba_pdata,
- }
-};
-
-#define FPGA_3D_GPIO_CONFIG_ADDR 0xB5
-static int dsi2lvds_gpio[2] = {
- 0,/* Backlight PWM-ID=0 for PMIC-GPIO#24 */
- 0x1F08 /* DSI2LVDS Bridge GPIO Output, mask=0x1f, out=0x08 */
- };
-
-static struct msm_panel_common_pdata mipi_dsi2lvds_pdata = {
- .gpio_num = dsi2lvds_gpio,
-};
-
-static struct mipi_dsi_phy_ctrl dsi_novatek_cmd_mode_phy_db = {
-
-/* DSI_BIT_CLK at 500MHz, 2 lane, RGB888 */
- {0x0F, 0x0a, 0x04, 0x00, 0x20}, /* regulator */
- /* timing */
- {0xab, 0x8a, 0x18, 0x00, 0x92, 0x97, 0x1b, 0x8c,
- 0x0c, 0x03, 0x04, 0xa0},
- {0x5f, 0x00, 0x00, 0x10}, /* phy ctrl */
- {0xff, 0x00, 0x06, 0x00}, /* strength */
- /* pll control */
- {0x40, 0xf9, 0x30, 0xda, 0x00, 0x40, 0x03, 0x62,
- 0x40, 0x07, 0x03,
- 0x00, 0x1a, 0x00, 0x00, 0x02, 0x00, 0x20, 0x00, 0x01},
-};
-
-static struct mipi_dsi_panel_platform_data novatek_pdata = {
- .fpga_3d_config_addr = FPGA_3D_GPIO_CONFIG_ADDR,
- .fpga_ctrl_mode = FPGA_SPI_INTF,
- .phy_ctrl_settings = &dsi_novatek_cmd_mode_phy_db,
-};
-
-static struct platform_device mipi_dsi_novatek_panel_device = {
- .name = "mipi_novatek",
- .id = 0,
- .dev = {
- .platform_data = &novatek_pdata,
- }
-};
-
-static struct platform_device mipi_dsi2lvds_bridge_device = {
- .name = "mipi_tc358764",
- .id = 0,
- .dev.platform_data = &mipi_dsi2lvds_pdata,
-};
-
-#ifdef CONFIG_FB_MSM_HDMI_MSM_PANEL
-static struct resource hdmi_msm_resources[] = {
- {
- .name = "hdmi_msm_qfprom_addr",
- .start = 0x00700000,
- .end = 0x007060FF,
- .flags = IORESOURCE_MEM,
- },
- {
- .name = "hdmi_msm_hdmi_addr",
- .start = 0x04A00000,
- .end = 0x04A00FFF,
- .flags = IORESOURCE_MEM,
- },
- {
- .name = "hdmi_msm_irq",
- .start = HDMI_IRQ,
- .end = HDMI_IRQ,
- .flags = IORESOURCE_IRQ,
- },
-};
-
-static int hdmi_enable_5v(int on);
-static int hdmi_core_power(int on, int show);
-static int hdmi_cec_power(int on);
-
-static struct msm_hdmi_platform_data hdmi_msm_data = {
- .irq = HDMI_IRQ,
- .enable_5v = hdmi_enable_5v,
- .core_power = hdmi_core_power,
- .cec_power = hdmi_cec_power,
-};
-
-static struct platform_device hdmi_msm_device = {
- .name = "hdmi_msm",
- .id = 0,
- .num_resources = ARRAY_SIZE(hdmi_msm_resources),
- .resource = hdmi_msm_resources,
- .dev.platform_data = &hdmi_msm_data,
-};
-#endif /* CONFIG_FB_MSM_HDMI_MSM_PANEL */
-
-#ifdef CONFIG_FB_MSM_WRITEBACK_MSM_PANEL
-static struct platform_device wfd_panel_device = {
- .name = "wfd_panel",
- .id = 0,
- .dev.platform_data = NULL,
-};
-#endif
-
-#ifdef CONFIG_MSM_BUS_SCALING
-static struct msm_bus_vectors dtv_bus_init_vectors[] = {
- {
- .src = MSM_BUS_MASTER_MDP_PORT0,
- .dst = MSM_BUS_SLAVE_EBI_CH0,
- .ab = 0,
- .ib = 0,
- },
-};
-
-#ifdef CONFIG_FB_MSM_HDMI_AS_PRIMARY
-static struct msm_bus_vectors dtv_bus_def_vectors[] = {
- {
- .src = MSM_BUS_MASTER_MDP_PORT0,
- .dst = MSM_BUS_SLAVE_EBI_CH0,
- .ab = 2000000000,
- .ib = 2000000000,
- },
-};
-#else
-static struct msm_bus_vectors dtv_bus_def_vectors[] = {
- {
- .src = MSM_BUS_MASTER_MDP_PORT0,
- .dst = MSM_BUS_SLAVE_EBI_CH0,
- .ab = 566092800 * 2,
- .ib = 707616000 * 2,
- },
-};
-#endif
-
-static struct msm_bus_paths dtv_bus_scale_usecases[] = {
- {
- ARRAY_SIZE(dtv_bus_init_vectors),
- dtv_bus_init_vectors,
- },
- {
- ARRAY_SIZE(dtv_bus_def_vectors),
- dtv_bus_def_vectors,
- },
-};
-static struct msm_bus_scale_pdata dtv_bus_scale_pdata = {
- dtv_bus_scale_usecases,
- ARRAY_SIZE(dtv_bus_scale_usecases),
- .name = "dtv",
-};
-
-static struct lcdc_platform_data dtv_pdata = {
- .bus_scale_table = &dtv_bus_scale_pdata,
-};
-#endif
-
-static void __init msm_fb_add_devices(void)
-{
- struct platform_device *ptr = NULL;
-
- if (machine_is_msm8960_liquid())
- ptr = &mipi_dsi2lvds_bridge_device;
- else
- ptr = &mipi_dsi_toshiba_panel_device;
- platform_add_devices(&ptr, 1);
-
- if (machine_is_msm8x60_rumi3()) {
- msm_fb_register_device("mdp", NULL);
- mipi_dsi_pdata.target_type = 1;
- } else
- msm_fb_register_device("mdp", &mdp_pdata);
- msm_fb_register_device("mipi_dsi", &mipi_dsi_pdata);
-#ifdef CONFIG_MSM_BUS_SCALING
- msm_fb_register_device("dtv", &dtv_pdata);
-#endif
-}
-
-static struct gpiomux_setting mdp_vsync_suspend_cfg = {
- .func = GPIOMUX_FUNC_GPIO,
- .drv = GPIOMUX_DRV_2MA,
- .pull = GPIOMUX_PULL_DOWN,
-};
-
-static struct gpiomux_setting mdp_vsync_active_cfg = {
- .func = GPIOMUX_FUNC_1,
- .drv = GPIOMUX_DRV_2MA,
- .pull = GPIOMUX_PULL_DOWN,
-};
-
-static struct msm_gpiomux_config msm8960_mdp_vsync_configs[] __initdata = {
- {
- .gpio = MDP_VSYNC_GPIO,
- .settings = {
- [GPIOMUX_ACTIVE] = &mdp_vsync_active_cfg,
- [GPIOMUX_SUSPENDED] = &mdp_vsync_suspend_cfg,
- },
- }
-};
-
-#ifdef CONFIG_FB_MSM_HDMI_MSM_PANEL
-static struct gpiomux_setting hdmi_suspend_cfg = {
- .func = GPIOMUX_FUNC_GPIO,
- .drv = GPIOMUX_DRV_2MA,
- .pull = GPIOMUX_PULL_DOWN,
-};
-
-static struct gpiomux_setting hdmi_active_1_cfg = {
- .func = GPIOMUX_FUNC_1,
- .drv = GPIOMUX_DRV_2MA,
- .pull = GPIOMUX_PULL_UP,
-};
-
-static struct gpiomux_setting hdmi_active_2_cfg = {
- .func = GPIOMUX_FUNC_1,
- .drv = GPIOMUX_DRV_2MA,
- .pull = GPIOMUX_PULL_DOWN,
-};
-
-static struct msm_gpiomux_config msm8960_hdmi_configs[] __initdata = {
- {
- .gpio = 99,
- .settings = {
- [GPIOMUX_ACTIVE] = &hdmi_active_1_cfg,
- [GPIOMUX_SUSPENDED] = &hdmi_suspend_cfg,
- },
- },
- {
- .gpio = 100,
- .settings = {
- [GPIOMUX_ACTIVE] = &hdmi_active_1_cfg,
- [GPIOMUX_SUSPENDED] = &hdmi_suspend_cfg,
- },
- },
- {
- .gpio = 101,
- .settings = {
- [GPIOMUX_ACTIVE] = &hdmi_active_1_cfg,
- [GPIOMUX_SUSPENDED] = &hdmi_suspend_cfg,
- },
- },
- {
- .gpio = 102,
- .settings = {
- [GPIOMUX_ACTIVE] = &hdmi_active_2_cfg,
- [GPIOMUX_SUSPENDED] = &hdmi_suspend_cfg,
- },
- },
-};
-
-static int hdmi_enable_5v(int on)
-{
- /* TBD: PM8921 regulator instead of 8901 */
- static struct regulator *reg_8921_hdmi_mvs; /* HDMI_5V */
- static int prev_on;
- int rc;
-
- if (on == prev_on)
- return 0;
-
- if (!reg_8921_hdmi_mvs)
- reg_8921_hdmi_mvs = regulator_get(&hdmi_msm_device.dev,
- "hdmi_mvs");
-
- if (on) {
- rc = regulator_enable(reg_8921_hdmi_mvs);
- if (rc) {
- pr_err("'%s' regulator enable failed, rc=%d\n",
- "8921_hdmi_mvs", rc);
- return rc;
- }
- pr_debug("%s(on): success\n", __func__);
- } else {
- rc = regulator_disable(reg_8921_hdmi_mvs);
- if (rc)
- pr_warning("'%s' regulator disable failed, rc=%d\n",
- "8921_hdmi_mvs", rc);
- pr_debug("%s(off): success\n", __func__);
- }
-
- prev_on = on;
-
- return 0;
-}
-
-static int hdmi_core_power(int on, int show)
-{
- static struct regulator *reg_8921_l23, *reg_8921_s4;
- static int prev_on;
- int rc;
-
- if (on == prev_on)
- return 0;
-
- /* TBD: PM8921 regulator instead of 8901 */
- if (!reg_8921_l23) {
- reg_8921_l23 = regulator_get(&hdmi_msm_device.dev, "hdmi_avdd");
- if (IS_ERR(reg_8921_l23)) {
- pr_err("could not get reg_8921_l23, rc = %ld\n",
- PTR_ERR(reg_8921_l23));
- return -ENODEV;
- }
- rc = regulator_set_voltage(reg_8921_l23, 1800000, 1800000);
- if (rc) {
- pr_err("set_voltage failed for 8921_l23, rc=%d\n", rc);
- return -EINVAL;
- }
- }
- if (!reg_8921_s4) {
- reg_8921_s4 = regulator_get(&hdmi_msm_device.dev, "hdmi_vcc");
- if (IS_ERR(reg_8921_s4)) {
- pr_err("could not get reg_8921_s4, rc = %ld\n",
- PTR_ERR(reg_8921_s4));
- return -ENODEV;
- }
- rc = regulator_set_voltage(reg_8921_s4, 1800000, 1800000);
- if (rc) {
- pr_err("set_voltage failed for 8921_s4, rc=%d\n", rc);
- return -EINVAL;
- }
- }
-
- if (on) {
- rc = regulator_set_optimum_mode(reg_8921_l23, 100000);
- if (rc < 0) {
- pr_err("set_optimum_mode l23 failed, rc=%d\n", rc);
- return -EINVAL;
- }
- rc = regulator_enable(reg_8921_l23);
- if (rc) {
- pr_err("'%s' regulator enable failed, rc=%d\n",
- "hdmi_avdd", rc);
- return rc;
- }
- rc = regulator_enable(reg_8921_s4);
- if (rc) {
- pr_err("'%s' regulator enable failed, rc=%d\n",
- "hdmi_vcc", rc);
- return rc;
- }
- rc = gpio_request(100, "HDMI_DDC_CLK");
- if (rc) {
- pr_err("'%s'(%d) gpio_request failed, rc=%d\n",
- "HDMI_DDC_CLK", 100, rc);
- goto error1;
- }
- rc = gpio_request(101, "HDMI_DDC_DATA");
- if (rc) {
- pr_err("'%s'(%d) gpio_request failed, rc=%d\n",
- "HDMI_DDC_DATA", 101, rc);
- goto error2;
- }
- rc = gpio_request(102, "HDMI_HPD");
- if (rc) {
- pr_err("'%s'(%d) gpio_request failed, rc=%d\n",
- "HDMI_HPD", 102, rc);
- goto error3;
- }
- pr_debug("%s(on): success\n", __func__);
- } else {
- gpio_free(100);
- gpio_free(101);
- gpio_free(102);
-
- rc = regulator_disable(reg_8921_l23);
- if (rc) {
- pr_err("disable reg_8921_l23 failed, rc=%d\n", rc);
- return -ENODEV;
- }
- rc = regulator_disable(reg_8921_s4);
- if (rc) {
- pr_err("disable reg_8921_s4 failed, rc=%d\n", rc);
- return -ENODEV;
- }
- rc = regulator_set_optimum_mode(reg_8921_l23, 100);
- if (rc < 0) {
- pr_err("set_optimum_mode l23 failed, rc=%d\n", rc);
- return -EINVAL;
- }
- pr_debug("%s(off): success\n", __func__);
- }
-
- prev_on = on;
-
- return 0;
-
-error3:
- gpio_free(101);
-error2:
- gpio_free(100);
-error1:
- regulator_disable(reg_8921_l23);
- regulator_disable(reg_8921_s4);
- return rc;
-}
-
-static int hdmi_cec_power(int on)
-{
- static int prev_on;
- int rc;
-
- if (on == prev_on)
- return 0;
-
- if (on) {
- rc = gpio_request(99, "HDMI_CEC_VAR");
- if (rc) {
- pr_err("'%s'(%d) gpio_request failed, rc=%d\n",
- "HDMI_CEC_VAR", 99, rc);
- goto error;
- }
- pr_debug("%s(on): success\n", __func__);
- } else {
- gpio_free(99);
- pr_debug("%s(off): success\n", __func__);
- }
-
- prev_on = on;
-
- return 0;
-error:
- return rc;
-}
-#endif /* CONFIG_FB_MSM_HDMI_MSM_PANEL */
-
-static void __init msm8960_allocate_memory_regions(void)
-{
- void *addr;
- unsigned long size;
-
- size = MSM_FB_SIZE;
- addr = alloc_bootmem_align(size, 0x1000);
- msm_fb_resources[0].start = __pa(addr);
- msm_fb_resources[0].end = msm_fb_resources[0].start + size - 1;
- pr_info("allocating %lu bytes at %p (%lx physical) for fb\n",
- size, addr, __pa(addr));
-
-}
-#ifdef CONFIG_WCD9310_CODEC
-
-#define TABLA_INTERRUPT_BASE (NR_MSM_IRQS + NR_GPIO_IRQS + NR_PM8921_IRQS)
-
-/* Micbias setting is based on 8660 CDP/MTP/FLUID requirement
- * 4 micbiases are used to power various analog and digital
- * microphones operating at 1800 mV. Technically, all micbiases
- * can source from single cfilter since all microphones operate
- * at the same voltage level. The arrangement below is to make
- * sure all cfilters are exercised. LDO_H regulator ouput level
- * does not need to be as high as 2.85V. It is choosen for
- * microphone sensitivity purpose.
- */
-static struct tabla_pdata tabla_platform_data = {
- .slimbus_slave_device = {
- .name = "tabla-slave",
- .e_addr = {0, 0, 0x10, 0, 0x17, 2},
- },
- .irq = MSM_GPIO_TO_INT(62),
- .irq_base = TABLA_INTERRUPT_BASE,
- .num_irqs = NR_TABLA_IRQS,
- .reset_gpio = PM8921_GPIO_PM_TO_SYS(34),
- .micbias = {
- .ldoh_v = TABLA_LDOH_2P85_V,
- .cfilt1_mv = 1800,
- .cfilt2_mv = 1800,
- .cfilt3_mv = 1800,
- .bias1_cfilt_sel = TABLA_CFILT1_SEL,
- .bias2_cfilt_sel = TABLA_CFILT2_SEL,
- .bias3_cfilt_sel = TABLA_CFILT3_SEL,
- .bias4_cfilt_sel = TABLA_CFILT3_SEL,
- }
-};
-
-static struct slim_device msm_slim_tabla = {
- .name = "tabla-slim",
- .e_addr = {0, 1, 0x10, 0, 0x17, 2},
- .dev = {
- .platform_data = &tabla_platform_data,
- },
-};
-
-static struct tabla_pdata tabla20_platform_data = {
- .slimbus_slave_device = {
- .name = "tabla-slave",
- .e_addr = {0, 0, 0x60, 0, 0x17, 2},
- },
- .irq = MSM_GPIO_TO_INT(62),
- .irq_base = TABLA_INTERRUPT_BASE,
- .num_irqs = NR_TABLA_IRQS,
- .reset_gpio = PM8921_GPIO_PM_TO_SYS(34),
- .micbias = {
- .ldoh_v = TABLA_LDOH_2P85_V,
- .cfilt1_mv = 1800,
- .cfilt2_mv = 1800,
- .cfilt3_mv = 1800,
- .bias1_cfilt_sel = TABLA_CFILT1_SEL,
- .bias2_cfilt_sel = TABLA_CFILT2_SEL,
- .bias3_cfilt_sel = TABLA_CFILT3_SEL,
- .bias4_cfilt_sel = TABLA_CFILT3_SEL,
- }
-};
-
-static struct slim_device msm_slim_tabla20 = {
- .name = "tabla2x-slim",
- .e_addr = {0, 1, 0x60, 0, 0x17, 2},
- .dev = {
- .platform_data = &tabla20_platform_data,
- },
-};
-#endif
-
-static struct slim_boardinfo msm_slim_devices[] = {
-#ifdef CONFIG_WCD9310_CODEC
- {
- .bus_num = 1,
- .slim_slave = &msm_slim_tabla,
- },
- {
- .bus_num = 1,
- .slim_slave = &msm_slim_tabla20,
- },
-#endif
- /* add more slimbus slaves as needed */
-};
-
-#define MSM_WCNSS_PHYS 0x03000000
-#define MSM_WCNSS_SIZE 0x280000
-
-static struct resource resources_wcnss_wlan[] = {
- {
- .start = RIVA_APPS_WLAN_RX_DATA_AVAIL_IRQ,
- .end = RIVA_APPS_WLAN_RX_DATA_AVAIL_IRQ,
- .name = "wcnss_wlanrx_irq",
- .flags = IORESOURCE_IRQ,
- },
- {
- .start = RIVA_APPS_WLAN_DATA_XFER_DONE_IRQ,
- .end = RIVA_APPS_WLAN_DATA_XFER_DONE_IRQ,
- .name = "wcnss_wlantx_irq",
- .flags = IORESOURCE_IRQ,
- },
- {
- .start = MSM_WCNSS_PHYS,
- .end = MSM_WCNSS_PHYS + MSM_WCNSS_SIZE - 1,
- .name = "wcnss_mmio",
- .flags = IORESOURCE_MEM,
- },
- {
- .start = 84,
- .end = 88,
- .name = "wcnss_gpios_5wire",
- .flags = IORESOURCE_IO,
- },
-};
-
-static struct qcom_wcnss_opts qcom_wcnss_pdata = {
- .has_48mhz_xo = 1,
-};
-
-static struct platform_device msm_device_wcnss_wlan = {
- .name = "wcnss_wlan",
- .id = 0,
- .num_resources = ARRAY_SIZE(resources_wcnss_wlan),
- .resource = resources_wcnss_wlan,
- .dev = {.platform_data = &qcom_wcnss_pdata},
-};
-
-#if defined(CONFIG_CRYPTO_DEV_QCRYPTO) || \
- defined(CONFIG_CRYPTO_DEV_QCRYPTO_MODULE) || \
- defined(CONFIG_CRYPTO_DEV_QCEDEV) || \
- defined(CONFIG_CRYPTO_DEV_QCEDEV_MODULE)
-
-#define QCE_SIZE 0x10000
-#define QCE_0_BASE 0x18500000
-
-#define QCE_HW_KEY_SUPPORT 0
-#define QCE_SHA_HMAC_SUPPORT 1
-#define QCE_SHARE_CE_RESOURCE 1
-#define QCE_CE_SHARED 0
-
-static struct resource qcrypto_resources[] = {
- [0] = {
- .start = QCE_0_BASE,
- .end = QCE_0_BASE + QCE_SIZE - 1,
- .flags = IORESOURCE_MEM,
- },
- [1] = {
- .name = "crypto_channels",
- .start = DMOV_CE_IN_CHAN,
- .end = DMOV_CE_OUT_CHAN,
- .flags = IORESOURCE_DMA,
- },
- [2] = {
- .name = "crypto_crci_in",
- .start = DMOV_CE_IN_CRCI,
- .end = DMOV_CE_IN_CRCI,
- .flags = IORESOURCE_DMA,
- },
- [3] = {
- .name = "crypto_crci_out",
- .start = DMOV_CE_OUT_CRCI,
- .end = DMOV_CE_OUT_CRCI,
- .flags = IORESOURCE_DMA,
- },
-};
-
-static struct resource qcedev_resources[] = {
- [0] = {
- .start = QCE_0_BASE,
- .end = QCE_0_BASE + QCE_SIZE - 1,
- .flags = IORESOURCE_MEM,
- },
- [1] = {
- .name = "crypto_channels",
- .start = DMOV_CE_IN_CHAN,
- .end = DMOV_CE_OUT_CHAN,
- .flags = IORESOURCE_DMA,
- },
- [2] = {
- .name = "crypto_crci_in",
- .start = DMOV_CE_IN_CRCI,
- .end = DMOV_CE_IN_CRCI,
- .flags = IORESOURCE_DMA,
- },
- [3] = {
- .name = "crypto_crci_out",
- .start = DMOV_CE_OUT_CRCI,
- .end = DMOV_CE_OUT_CRCI,
- .flags = IORESOURCE_DMA,
- },
-};
-
-#endif
-
-#if defined(CONFIG_CRYPTO_DEV_QCRYPTO) || \
- defined(CONFIG_CRYPTO_DEV_QCRYPTO_MODULE)
-
-static struct msm_ce_hw_support qcrypto_ce_hw_suppport = {
- .ce_shared = QCE_CE_SHARED,
- .shared_ce_resource = QCE_SHARE_CE_RESOURCE,
- .hw_key_support = QCE_HW_KEY_SUPPORT,
- .sha_hmac = QCE_SHA_HMAC_SUPPORT,
-};
-
-static struct platform_device qcrypto_device = {
- .name = "qcrypto",
- .id = 0,
- .num_resources = ARRAY_SIZE(qcrypto_resources),
- .resource = qcrypto_resources,
- .dev = {
- .coherent_dma_mask = DMA_BIT_MASK(32),
- .platform_data = &qcrypto_ce_hw_suppport,
- },
-};
-#endif
-
-#if defined(CONFIG_CRYPTO_DEV_QCEDEV) || \
- defined(CONFIG_CRYPTO_DEV_QCEDEV_MODULE)
-
-static struct msm_ce_hw_support qcedev_ce_hw_suppport = {
- .ce_shared = QCE_CE_SHARED,
- .shared_ce_resource = QCE_SHARE_CE_RESOURCE,
- .hw_key_support = QCE_HW_KEY_SUPPORT,
- .sha_hmac = QCE_SHA_HMAC_SUPPORT,
-};
-
-static struct platform_device qcedev_device = {
- .name = "qce",
- .id = 0,
- .num_resources = ARRAY_SIZE(qcedev_resources),
- .resource = qcedev_resources,
- .dev = {
- .coherent_dma_mask = DMA_BIT_MASK(32),
- .platform_data = &qcedev_ce_hw_suppport,
- },
-};
-#endif
-
-#define MDM2AP_ERRFATAL 70
-#define AP2MDM_ERRFATAL 95
-#define MDM2AP_STATUS 69
-#define AP2MDM_STATUS 94
-#define AP2MDM_PMIC_RESET_N 80
-#define AP2MDM_KPDPWR_N 81
-
-static struct gpiomux_setting ap2mdm_cfg = {
- .func = GPIOMUX_FUNC_GPIO,
- .drv = GPIOMUX_DRV_8MA,
- .pull = GPIOMUX_PULL_DOWN,
-};
-
-static struct gpiomux_setting mdm2ap_status_cfg = {
- .func = GPIOMUX_FUNC_GPIO,
- .drv = GPIOMUX_DRV_8MA,
- .pull = GPIOMUX_PULL_NONE,
-};
-
-static struct gpiomux_setting mdm2ap_errfatal_cfg = {
- .func = GPIOMUX_FUNC_GPIO,
- .drv = GPIOMUX_DRV_16MA,
- .pull = GPIOMUX_PULL_DOWN,
-};
-
-static struct gpiomux_setting ap2mdm_kpdpwr_n_cfg = {
- .func = GPIOMUX_FUNC_GPIO,
- .drv = GPIOMUX_DRV_8MA,
- .pull = GPIOMUX_PULL_NONE,
-};
-
-static struct msm_gpiomux_config mdm_configs[] __initdata = {
- /* AP2MDM_STATUS */
- {
- .gpio = AP2MDM_STATUS,
- .settings = {
- [GPIOMUX_SUSPENDED] = &ap2mdm_cfg,
- }
- },
- /* MDM2AP_STATUS */
- {
- .gpio = MDM2AP_STATUS,
- .settings = {
- [GPIOMUX_SUSPENDED] = &mdm2ap_status_cfg,
- }
- },
- /* MDM2AP_ERRFATAL */
- {
- .gpio = MDM2AP_ERRFATAL,
- .settings = {
- [GPIOMUX_SUSPENDED] = &mdm2ap_errfatal_cfg,
- }
- },
- /* AP2MDM_ERRFATAL */
- {
- .gpio = AP2MDM_ERRFATAL,
- .settings = {
- [GPIOMUX_SUSPENDED] = &ap2mdm_cfg,
- }
- },
- /* AP2MDM_KPDPWR_N */
- {
- .gpio = AP2MDM_KPDPWR_N,
- .settings = {
- [GPIOMUX_SUSPENDED] = &ap2mdm_kpdpwr_n_cfg,
- }
- },
- /* AP2MDM_PMIC_RESET_N */
- {
- .gpio = AP2MDM_PMIC_RESET_N,
- .settings = {
- [GPIOMUX_SUSPENDED] = &ap2mdm_kpdpwr_n_cfg,
- }
- }
-};
-
-static struct resource mdm_resources[] = {
- {
- .start = MDM2AP_ERRFATAL,
- .end = MDM2AP_ERRFATAL,
- .name = "MDM2AP_ERRFATAL",
- .flags = IORESOURCE_IO,
- },
- {
- .start = AP2MDM_ERRFATAL,
- .end = AP2MDM_ERRFATAL,
- .name = "AP2MDM_ERRFATAL",
- .flags = IORESOURCE_IO,
- },
- {
- .start = MDM2AP_STATUS,
- .end = MDM2AP_STATUS,
- .name = "MDM2AP_STATUS",
- .flags = IORESOURCE_IO,
- },
- {
- .start = AP2MDM_STATUS,
- .end = AP2MDM_STATUS,
- .name = "AP2MDM_STATUS",
- .flags = IORESOURCE_IO,
- },
- {
- .start = AP2MDM_PMIC_RESET_N,
- .end = AP2MDM_PMIC_RESET_N,
- .name = "AP2MDM_PMIC_RESET_N",
- .flags = IORESOURCE_IO,
- },
- {
- .start = AP2MDM_KPDPWR_N,
- .end = AP2MDM_KPDPWR_N,
- .name = "AP2MDM_KPDPWR_N",
- .flags = IORESOURCE_IO,
- },
-};
-
-static struct mdm_platform_data mdm_platform_data = {
- .mdm_version = "2.5",
-};
-
-struct platform_device mdm_device = {
- .name = "mdm2_modem",
- .id = -1,
- .num_resources = ARRAY_SIZE(mdm_resources),
- .resource = mdm_resources,
- .dev = {
- .platform_data = &mdm_platform_data,
- },
-};
-
-static struct platform_device *mdm_devices[] __initdata = {
- &mdm_device,
-};
-
-static int __init gpiomux_init(void)
-{
- int rc;
-
- rc = msm_gpiomux_init(NR_GPIO_IRQS);
- if (rc) {
- pr_err(KERN_ERR "msm_gpiomux_init failed %d\n", rc);
- return rc;
- }
-
- msm_gpiomux_install(msm8960_cam_common_configs,
- ARRAY_SIZE(msm8960_cam_common_configs));
-
- msm_gpiomux_install(msm8960_gpiomux_configs,
- ARRAY_SIZE(msm8960_gpiomux_configs));
-
- msm_gpiomux_install(msm8960_gsbi_configs,
- ARRAY_SIZE(msm8960_gsbi_configs));
-
- msm_gpiomux_install(msm8960_cyts_configs,
- ARRAY_SIZE(msm8960_cyts_configs));
-
- msm_gpiomux_install(msm8960_slimbus_config,
- ARRAY_SIZE(msm8960_slimbus_config));
-
- msm_gpiomux_install(msm8960_audio_codec_configs,
- ARRAY_SIZE(msm8960_audio_codec_configs));
-
- msm_gpiomux_install(msm8960_audio_auxpcm_configs,
- ARRAY_SIZE(msm8960_audio_auxpcm_configs));
-
-#ifdef CONFIG_FB_MSM_HDMI_MSM_PANEL
- msm_gpiomux_install(msm8960_hdmi_configs,
- ARRAY_SIZE(msm8960_hdmi_configs));
-#endif
-
- msm_gpiomux_install(msm8960_mdp_vsync_configs,
- ARRAY_SIZE(msm8960_mdp_vsync_configs));
-
- msm_gpiomux_install(wcnss_5wire_interface,
- ARRAY_SIZE(wcnss_5wire_interface));
-
- if (machine_is_msm8960_mtp() || machine_is_msm8960_fluid() ||
- machine_is_msm8960_liquid() || machine_is_msm8960_cdp())
- msm_gpiomux_install(hap_lvl_shft_config,
- ARRAY_SIZE(hap_lvl_shft_config));
-
- if (PLATFORM_IS_CHARM25())
- msm_gpiomux_install(mdm_configs,
- ARRAY_SIZE(mdm_configs));
-
- return 0;
-}
-
-#define MSM_SHARED_RAM_PHYS 0x80000000
-
-static struct pm8xxx_adc_amux pm8xxx_adc_channels_data[] = {
- {"vcoin", CHANNEL_VCOIN, CHAN_PATH_SCALING2, AMUX_RSV1,
- ADC_DECIMATION_TYPE2, ADC_SCALE_DEFAULT},
- {"vbat", CHANNEL_VBAT, CHAN_PATH_SCALING2, AMUX_RSV1,
- ADC_DECIMATION_TYPE2, ADC_SCALE_DEFAULT},
- {"dcin", CHANNEL_DCIN, CHAN_PATH_SCALING4, AMUX_RSV1,
- ADC_DECIMATION_TYPE2, ADC_SCALE_DEFAULT},
- {"ichg", CHANNEL_ICHG, CHAN_PATH_SCALING1, AMUX_RSV1,
- ADC_DECIMATION_TYPE2, ADC_SCALE_DEFAULT},
- {"vph_pwr", CHANNEL_VPH_PWR, CHAN_PATH_SCALING2, AMUX_RSV1,
- ADC_DECIMATION_TYPE2, ADC_SCALE_DEFAULT},
- {"ibat", CHANNEL_IBAT, CHAN_PATH_SCALING1, AMUX_RSV1,
- ADC_DECIMATION_TYPE2, ADC_SCALE_DEFAULT},
- {"batt_therm", CHANNEL_BATT_THERM, CHAN_PATH_SCALING1, AMUX_RSV2,
- ADC_DECIMATION_TYPE2, ADC_SCALE_BATT_THERM},
- {"batt_id", CHANNEL_BATT_ID, CHAN_PATH_SCALING1, AMUX_RSV1,
- ADC_DECIMATION_TYPE2, ADC_SCALE_DEFAULT},
- {"usbin", CHANNEL_USBIN, CHAN_PATH_SCALING3, AMUX_RSV1,
- ADC_DECIMATION_TYPE2, ADC_SCALE_DEFAULT},
- {"pmic_therm", CHANNEL_DIE_TEMP, CHAN_PATH_SCALING1, AMUX_RSV1,
- ADC_DECIMATION_TYPE2, ADC_SCALE_PMIC_THERM},
- {"625mv", CHANNEL_625MV, CHAN_PATH_SCALING1, AMUX_RSV1,
- ADC_DECIMATION_TYPE2, ADC_SCALE_DEFAULT},
- {"125v", CHANNEL_125V, CHAN_PATH_SCALING1, AMUX_RSV1,
- ADC_DECIMATION_TYPE2, ADC_SCALE_DEFAULT},
- {"chg_temp", CHANNEL_CHG_TEMP, CHAN_PATH_SCALING1, AMUX_RSV1,
- ADC_DECIMATION_TYPE2, ADC_SCALE_DEFAULT},
- {"pa_therm1", ADC_MPP_1_AMUX8, CHAN_PATH_SCALING1, AMUX_RSV1,
- ADC_DECIMATION_TYPE2, ADC_SCALE_PA_THERM},
- {"xo_therm", CHANNEL_MUXOFF, CHAN_PATH_SCALING1, AMUX_RSV0,
- ADC_DECIMATION_TYPE2, ADC_SCALE_XOTHERM},
- {"pa_therm0", ADC_MPP_1_AMUX3, CHAN_PATH_SCALING1, AMUX_RSV1,
- ADC_DECIMATION_TYPE2, ADC_SCALE_PA_THERM},
-};
-
-static struct pm8xxx_adc_properties pm8xxx_adc_data = {
- .adc_vdd_reference = 1800, /* milli-voltage for this adc */
- .bitresolution = 15,
- .bipolar = 0,
-};
-
-static struct pm8xxx_adc_platform_data pm8xxx_adc_pdata = {
- .adc_channel = pm8xxx_adc_channels_data,
- .adc_num_board_channel = ARRAY_SIZE(pm8xxx_adc_channels_data),
- .adc_prop = &pm8xxx_adc_data,
- .adc_mpp_base = PM8921_MPP_PM_TO_SYS(1),
-};
-
-static void __init msm8960_map_io(void)
-{
- msm_shared_ram_phys = MSM_SHARED_RAM_PHYS;
- msm_map_msm8960_io();
-
- if (socinfo_init() < 0)
- pr_err("socinfo_init() failed!\n");
-}
-
-#ifdef CONFIG_ARCH_MSM8930
-static void __init msm8930_map_io(void)
-{
- msm_shared_ram_phys = MSM_SHARED_RAM_PHYS;
- msm_map_msm8930_io();
-
- if (socinfo_init() < 0)
- pr_err("socinfo_init() failed!\n");
-}
-#endif
-
-static void __init msm8960_init_irq(void)
-{
- unsigned int i;
-
- msm_mpm_irq_extn_init();
- gic_init(0, GIC_PPI_START, MSM_QGIC_DIST_BASE,
- (void *)MSM_QGIC_CPU_BASE);
-
- /* Edge trigger PPIs except AVS_SVICINT and AVS_SVICINTSWDONE */
- writel_relaxed(0xFFFFD7FF, MSM_QGIC_DIST_BASE + GIC_DIST_CONFIG + 4);
-
- writel_relaxed(0x0000FFFF, MSM_QGIC_DIST_BASE + GIC_DIST_ENABLE_SET);
- mb();
-
- /* FIXME: Not installing AVS_SVICINT and AVS_SVICINTSWDONE yet
- * as they are configured as level, which does not play nice with
- * handle_percpu_irq.
- */
- for (i = GIC_PPI_START; i < GIC_SPI_START; i++) {
- if (i != AVS_SVICINT && i != AVS_SVICINTSWDONE)
- irq_set_handler(i, handle_percpu_irq);
- }
-}
-
-/* MSM8960 has 5 SDCC controllers */
-enum sdcc_controllers {
- SDCC1,
- SDCC2,
- SDCC3,
- SDCC4,
- SDCC5,
- MAX_SDCC_CONTROLLER
-};
-
-/* All SDCC controllers require VDD/VCC voltage */
-static struct msm_mmc_reg_data mmc_vdd_reg_data[MAX_SDCC_CONTROLLER] = {
- /* SDCC1 : eMMC card connected */
- [SDCC1] = {
- .name = "sdc_vdd",
- .high_vol_level = 2950000,
- .low_vol_level = 2950000,
- .always_on = 1,
- .lpm_sup = 1,
- .lpm_uA = 9000,
- .hpm_uA = 200000, /* 200mA */
- },
- /* SDCC3 : External card slot connected */
- [SDCC3] = {
- .name = "sdc_vdd",
- .high_vol_level = 2950000,
- .low_vol_level = 2950000,
- .hpm_uA = 600000, /* 600mA */
- }
-};
-
-/* Only slots having eMMC card will require VCCQ voltage */
-static struct msm_mmc_reg_data mmc_vccq_reg_data[1] = {
- /* SDCC1 : eMMC card connected */
- [SDCC1] = {
- .name = "sdc_vccq",
- .always_on = 1,
- .high_vol_level = 1800000,
- .low_vol_level = 1800000,
- .hpm_uA = 200000, /* 200mA */
- }
-};
-
-/* All SDCC controllers may require voting for VDD PAD voltage */
-static struct msm_mmc_reg_data mmc_vddp_reg_data[MAX_SDCC_CONTROLLER] = {
- /* SDCC3 : External card slot connected */
- [SDCC3] = {
- .name = "sdc_vddp",
- .high_vol_level = 2950000,
- .low_vol_level = 1850000,
- .always_on = 1,
- .lpm_sup = 1,
- /* Max. Active current required is 16 mA */
- .hpm_uA = 16000,
- /*
- * Sleep current required is ~300 uA. But min. vote can be
- * in terms of mA (min. 1 mA). So let's vote for 2 mA
- * during sleep.
- */
- .lpm_uA = 2000,
- }
-};
-
-static struct msm_mmc_slot_reg_data mmc_slot_vreg_data[MAX_SDCC_CONTROLLER] = {
- /* SDCC1 : eMMC card connected */
- [SDCC1] = {
- .vdd_data = &mmc_vdd_reg_data[SDCC1],
- .vccq_data = &mmc_vccq_reg_data[SDCC1],
- },
- /* SDCC3 : External card slot connected */
- [SDCC3] = {
- .vdd_data = &mmc_vdd_reg_data[SDCC3],
- .vddp_data = &mmc_vddp_reg_data[SDCC3],
- }
-};
-
-/* SDC1 pad data */
-static struct msm_mmc_pad_drv sdc1_pad_drv_on_cfg[] = {
- {TLMM_HDRV_SDC1_CLK, GPIO_CFG_16MA},
- {TLMM_HDRV_SDC1_CMD, GPIO_CFG_10MA},
- {TLMM_HDRV_SDC1_DATA, GPIO_CFG_10MA}
-};
-
-static struct msm_mmc_pad_drv sdc1_pad_drv_off_cfg[] = {
- {TLMM_HDRV_SDC1_CLK, GPIO_CFG_2MA},
- {TLMM_HDRV_SDC1_CMD, GPIO_CFG_2MA},
- {TLMM_HDRV_SDC1_DATA, GPIO_CFG_2MA}
-};
-
-static struct msm_mmc_pad_pull sdc1_pad_pull_on_cfg[] = {
- {TLMM_PULL_SDC1_CLK, GPIO_CFG_NO_PULL},
- {TLMM_PULL_SDC1_CMD, GPIO_CFG_PULL_UP},
- {TLMM_PULL_SDC1_DATA, GPIO_CFG_PULL_UP}
-};
-
-static struct msm_mmc_pad_pull sdc1_pad_pull_off_cfg[] = {
- {TLMM_PULL_SDC1_CLK, GPIO_CFG_NO_PULL},
- {TLMM_PULL_SDC1_CMD, GPIO_CFG_PULL_DOWN},
- {TLMM_PULL_SDC1_DATA, GPIO_CFG_PULL_DOWN}
-};
-
-/* SDC3 pad data */
-static struct msm_mmc_pad_drv sdc3_pad_drv_on_cfg[] = {
- {TLMM_HDRV_SDC3_CLK, GPIO_CFG_8MA},
- {TLMM_HDRV_SDC3_CMD, GPIO_CFG_8MA},
- {TLMM_HDRV_SDC3_DATA, GPIO_CFG_8MA}
-};
-
-static struct msm_mmc_pad_drv sdc3_pad_drv_off_cfg[] = {
- {TLMM_HDRV_SDC3_CLK, GPIO_CFG_2MA},
- {TLMM_HDRV_SDC3_CMD, GPIO_CFG_2MA},
- {TLMM_HDRV_SDC3_DATA, GPIO_CFG_2MA}
-};
-
-static struct msm_mmc_pad_pull sdc3_pad_pull_on_cfg[] = {
- {TLMM_PULL_SDC3_CLK, GPIO_CFG_NO_PULL},
- {TLMM_PULL_SDC3_CMD, GPIO_CFG_PULL_UP},
- {TLMM_PULL_SDC3_DATA, GPIO_CFG_PULL_UP}
-};
-
-static struct msm_mmc_pad_pull sdc3_pad_pull_off_cfg[] = {
- {TLMM_PULL_SDC3_CLK, GPIO_CFG_NO_PULL},
- /*
- * SDC3 CMD line should be PULLed UP otherwise fluid platform will
- * see transitions (1 -> 0 and 0 -> 1) on card detection line,
- * which would result in false card detection interrupts.
- */
- {TLMM_PULL_SDC3_CMD, GPIO_CFG_PULL_UP},
- /*
- * Keeping DATA lines status to PULL UP will make sure that
- * there is no current leak during sleep if external pull up
- * is connected to DATA lines.
- */
- {TLMM_PULL_SDC3_DATA, GPIO_CFG_PULL_UP}
-};
-
-struct msm_mmc_pad_pull_data mmc_pad_pull_data[MAX_SDCC_CONTROLLER] = {
- [SDCC1] = {
- .on = sdc1_pad_pull_on_cfg,
- .off = sdc1_pad_pull_off_cfg,
- .size = ARRAY_SIZE(sdc1_pad_pull_on_cfg)
- },
- [SDCC3] = {
- .on = sdc3_pad_pull_on_cfg,
- .off = sdc3_pad_pull_off_cfg,
- .size = ARRAY_SIZE(sdc3_pad_pull_on_cfg)
- },
-};
-
-struct msm_mmc_pad_drv_data mmc_pad_drv_data[MAX_SDCC_CONTROLLER] = {
- [SDCC1] = {
- .on = sdc1_pad_drv_on_cfg,
- .off = sdc1_pad_drv_off_cfg,
- .size = ARRAY_SIZE(sdc1_pad_drv_on_cfg)
- },
- [SDCC3] = {
- .on = sdc3_pad_drv_on_cfg,
- .off = sdc3_pad_drv_off_cfg,
- .size = ARRAY_SIZE(sdc3_pad_drv_on_cfg)
- },
-};
-
-struct msm_mmc_pad_data mmc_pad_data[MAX_SDCC_CONTROLLER] = {
- [SDCC1] = {
- .pull = &mmc_pad_pull_data[SDCC1],
- .drv = &mmc_pad_drv_data[SDCC1]
- },
- [SDCC3] = {
- .pull = &mmc_pad_pull_data[SDCC3],
- .drv = &mmc_pad_drv_data[SDCC3]
- },
-};
-
-struct msm_mmc_pin_data mmc_slot_pin_data[MAX_SDCC_CONTROLLER] = {
- [SDCC1] = {
- .pad_data = &mmc_pad_data[SDCC1],
- },
- [SDCC3] = {
- .pad_data = &mmc_pad_data[SDCC3],
- },
-};
-
-static unsigned int sdc1_sup_clk_rates[] = {
- 400000, 24000000, 48000000
-};
-
-static unsigned int sdc3_sup_clk_rates[] = {
- 400000, 24000000, 48000000, 96000000
-};
-
-#ifdef CONFIG_MMC_MSM_SDC1_SUPPORT
-static struct mmc_platform_data msm8960_sdc1_data = {
- .ocr_mask = MMC_VDD_27_28 | MMC_VDD_28_29,
-#ifdef CONFIG_MMC_MSM_SDC1_8_BIT_SUPPORT
- .mmc_bus_width = MMC_CAP_8_BIT_DATA,
-#else
- .mmc_bus_width = MMC_CAP_4_BIT_DATA,
-#endif
- .sup_clk_table = sdc1_sup_clk_rates,
- .sup_clk_cnt = ARRAY_SIZE(sdc1_sup_clk_rates),
- .pclk_src_dfab = 1,
- .nonremovable = 1,
- .vreg_data = &mmc_slot_vreg_data[SDCC1],
- .pin_data = &mmc_slot_pin_data[SDCC1]
-};
-#endif
-
-#ifdef CONFIG_MMC_MSM_SDC3_SUPPORT
-static struct mmc_platform_data msm8960_sdc3_data = {
- .ocr_mask = MMC_VDD_27_28 | MMC_VDD_28_29,
- .mmc_bus_width = MMC_CAP_4_BIT_DATA,
- .sup_clk_table = sdc3_sup_clk_rates,
- .sup_clk_cnt = ARRAY_SIZE(sdc3_sup_clk_rates),
- .pclk_src_dfab = 1,
-#ifdef CONFIG_MMC_MSM_SDC3_WP_SUPPORT
- .wpswitch_gpio = PM8921_GPIO_PM_TO_SYS(16),
-#endif
- .vreg_data = &mmc_slot_vreg_data[SDCC3],
- .pin_data = &mmc_slot_pin_data[SDCC3],
-#ifdef CONFIG_MMC_MSM_CARD_HW_DETECTION
- .status_gpio = PM8921_GPIO_PM_TO_SYS(26),
- .status_irq = PM8921_GPIO_IRQ(PM8921_IRQ_BASE, 26),
- .irq_flags = IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING,
-#endif
- .xpc_cap = 1,
- .uhs_caps = (MMC_CAP_UHS_SDR12 | MMC_CAP_UHS_SDR25 |
- MMC_CAP_UHS_SDR50 | MMC_CAP_UHS_DDR50 |
- MMC_CAP_MAX_CURRENT_600)
-};
-#endif
-
-static void __init msm8960_init_mmc(void)
-{
-#ifdef CONFIG_MMC_MSM_SDC1_SUPPORT
- /* SDC1 : eMMC card connected */
- msm_add_sdcc(1, &msm8960_sdc1_data);
-#endif
-#ifdef CONFIG_MMC_MSM_SDC3_SUPPORT
- /* SDC3: External card slot */
- msm_add_sdcc(3, &msm8960_sdc3_data);
-#endif
-}
-
-static void __init msm8960_init_buses(void)
-{
-#ifdef CONFIG_MSM_BUS_SCALING
- msm_bus_rpm_set_mt_mask();
- msm_bus_8960_apps_fabric_pdata.rpm_enabled = 1;
- msm_bus_8960_sys_fabric_pdata.rpm_enabled = 1;
- msm_bus_8960_mm_fabric_pdata.rpm_enabled = 1;
- msm_bus_apps_fabric.dev.platform_data =
- &msm_bus_8960_apps_fabric_pdata;
- msm_bus_sys_fabric.dev.platform_data = &msm_bus_8960_sys_fabric_pdata;
- msm_bus_mm_fabric.dev.platform_data = &msm_bus_8960_mm_fabric_pdata;
- msm_bus_sys_fpb.dev.platform_data = &msm_bus_8960_sys_fpb_pdata;
- msm_bus_cpss_fpb.dev.platform_data = &msm_bus_8960_cpss_fpb_pdata;
-#endif
-}
-
-static struct msm_spi_platform_data msm8960_qup_spi_gsbi1_pdata = {
- .max_clock_speed = 15060000,
-};
-
-#ifdef CONFIG_USB_MSM_OTG_72K
-static struct msm_otg_platform_data msm_otg_pdata;
-#else
-#define USB_5V_EN 42
-static void msm_hsusb_vbus_power(bool on)
-{
- int rc;
- static bool vbus_is_on;
- static struct regulator *mvs_otg_switch;
-
- if (vbus_is_on == on)
- return;
-
- if (on) {
- mvs_otg_switch = regulator_get(&msm8960_device_otg.dev,
- "vbus_otg");
- if (IS_ERR(mvs_otg_switch)) {
- pr_err("Unable to get mvs_otg_switch\n");
- return;
- }
-
- rc = gpio_request(PM8921_GPIO_PM_TO_SYS(USB_5V_EN),
- "usb_5v_en");
- if (rc < 0) {
- pr_err("failed to request usb_5v_en gpio\n");
- goto put_mvs_otg;
- }
-
- rc = gpio_direction_output(PM8921_GPIO_PM_TO_SYS(USB_5V_EN), 1);
- if (rc) {
- pr_err("%s: unable to set_direction for gpio [%d]\n",
- __func__, PM8921_GPIO_PM_TO_SYS(USB_5V_EN));
- goto free_usb_5v_en;
- }
-
- if (regulator_enable(mvs_otg_switch)) {
- pr_err("unable to enable mvs_otg_switch\n");
- goto err_ldo_gpio_set_dir;
- }
-
- vbus_is_on = true;
- return;
- }
- regulator_disable(mvs_otg_switch);
-err_ldo_gpio_set_dir:
- gpio_set_value(PM8921_GPIO_PM_TO_SYS(USB_5V_EN), 0);
-free_usb_5v_en:
- gpio_free(PM8921_GPIO_PM_TO_SYS(USB_5V_EN));
-put_mvs_otg:
- regulator_put(mvs_otg_switch);
- vbus_is_on = false;
-}
-
-static struct msm_otg_platform_data msm_otg_pdata = {
- .mode = USB_OTG,
- .otg_control = OTG_PMIC_CONTROL,
- .phy_type = SNPS_28NM_INTEGRATED_PHY,
- .pclk_src_name = "dfab_usb_hs_clk",
- .pmic_id_irq = PM8921_USB_ID_IN_IRQ(PM8921_IRQ_BASE),
- .vbus_power = msm_hsusb_vbus_power,
- .power_budget = 750,
-};
-#endif
-
-#ifdef CONFIG_USB_EHCI_MSM_HSIC
-#define HSIC_HUB_RESET_GPIO 91
-static struct msm_hsic_host_platform_data msm_hsic_pdata = {
- .strobe = 150,
- .data = 151,
-};
-#else
-static struct msm_hsic_host_platform_data msm_hsic_pdata;
-#endif
-
-#define PID_MAGIC_ID 0x71432909
-#define SERIAL_NUM_MAGIC_ID 0x61945374
-#define SERIAL_NUMBER_LENGTH 127
-#define DLOAD_USB_BASE_ADD 0x2A03F0C8
-
-struct magic_num_struct {
- uint32_t pid;
- uint32_t serial_num;
-};
-
-struct dload_struct {
- uint32_t reserved1;
- uint32_t reserved2;
- uint32_t reserved3;
- uint16_t reserved4;
- uint16_t pid;
- char serial_number[SERIAL_NUMBER_LENGTH];
- uint16_t reserved5;
- struct magic_num_struct magic_struct;
-};
-
-static int usb_diag_update_pid_and_serial_num(uint32_t pid, const char *snum)
-{
- struct dload_struct __iomem *dload = 0;
-
- dload = ioremap(DLOAD_USB_BASE_ADD, sizeof(*dload));
- if (!dload) {
- pr_err("%s: cannot remap I/O memory region: %08x\n",
- __func__, DLOAD_USB_BASE_ADD);
- return -ENXIO;
- }
-
- pr_debug("%s: dload:%p pid:%x serial_num:%s\n",
- __func__, dload, pid, snum);
- /* update pid */
- dload->magic_struct.pid = PID_MAGIC_ID;
- dload->pid = pid;
-
- /* update serial number */
- dload->magic_struct.serial_num = 0;
- if (!snum) {
- memset(dload->serial_number, 0, SERIAL_NUMBER_LENGTH);
- goto out;
- }
-
- dload->magic_struct.serial_num = SERIAL_NUM_MAGIC_ID;
- strlcpy(dload->serial_number, snum, SERIAL_NUMBER_LENGTH);
-out:
- iounmap(dload);
- return 0;
-}
-
-static struct android_usb_platform_data android_usb_pdata = {
- .update_pid_and_serial_num = usb_diag_update_pid_and_serial_num,
-};
-
-static struct platform_device android_usb_device = {
- .name = "android_usb",
- .id = -1,
- .dev = {
- .platform_data = &android_usb_pdata,
- },
-};
-
-static uint8_t spm_wfi_cmd_sequence[] __initdata = {
- 0x03, 0x0f,
-};
-
-static uint8_t spm_power_collapse_without_rpm[] __initdata = {
- 0x00, 0x24, 0x54, 0x10,
- 0x09, 0x03, 0x01,
- 0x10, 0x54, 0x30, 0x0C,
- 0x24, 0x30, 0x0f,
-};
-
-static uint8_t spm_power_collapse_with_rpm[] __initdata = {
- 0x00, 0x24, 0x54, 0x10,
- 0x09, 0x07, 0x01, 0x0B,
- 0x10, 0x54, 0x30, 0x0C,
- 0x24, 0x30, 0x0f,
-};
-
-static struct msm_spm_seq_entry msm_spm_seq_list[] __initdata = {
- [0] = {
- .mode = MSM_SPM_MODE_CLOCK_GATING,
- .notify_rpm = false,
- .cmd = spm_wfi_cmd_sequence,
- },
- [1] = {
- .mode = MSM_SPM_MODE_POWER_COLLAPSE,
- .notify_rpm = false,
- .cmd = spm_power_collapse_without_rpm,
- },
- [2] = {
- .mode = MSM_SPM_MODE_POWER_COLLAPSE,
- .notify_rpm = true,
- .cmd = spm_power_collapse_with_rpm,
- },
-};
-
-static struct msm_spm_platform_data msm_spm_data[] __initdata = {
- [0] = {
- .reg_base_addr = MSM_SAW0_BASE,
- .reg_init_values[MSM_SPM_REG_SAW2_SECURE] = 0x00,
- .reg_init_values[MSM_SPM_REG_SAW2_CFG] = 0x1F,
- .reg_init_values[MSM_SPM_REG_SAW2_VCTL] = 0x9C,
-#if defined(CONFIG_MSM_AVS_HW)
- .reg_init_values[MSM_SPM_REG_SAW2_AVS_CTL] = 0x00,
- .reg_init_values[MSM_SPM_REG_SAW2_AVS_HYSTERESIS] = 0x00,
-#endif
- .reg_init_values[MSM_SPM_REG_SAW2_SPM_CTL] = 0x01,
- .reg_init_values[MSM_SPM_REG_SAW2_PMIC_DLY] = 0x02020202,
- .reg_init_values[MSM_SPM_REG_SAW2_PMIC_DATA_0] = 0x0060009C,
- .reg_init_values[MSM_SPM_REG_SAW2_PMIC_DATA_1] = 0x0000001C,
- .vctl_timeout_us = 50,
- .num_modes = ARRAY_SIZE(msm_spm_seq_list),
- .modes = msm_spm_seq_list,
- },
- [1] = {
- .reg_base_addr = MSM_SAW1_BASE,
- .reg_init_values[MSM_SPM_REG_SAW2_SECURE] = 0x00,
- .reg_init_values[MSM_SPM_REG_SAW2_CFG] = 0x1F,
- .reg_init_values[MSM_SPM_REG_SAW2_VCTL] = 0x9C,
-#if defined(CONFIG_MSM_AVS_HW)
- .reg_init_values[MSM_SPM_REG_SAW2_AVS_CTL] = 0x00,
- .reg_init_values[MSM_SPM_REG_SAW2_AVS_HYSTERESIS] = 0x00,
-#endif
- .reg_init_values[MSM_SPM_REG_SAW2_SPM_CTL] = 0x01,
- .reg_init_values[MSM_SPM_REG_SAW2_PMIC_DLY] = 0x02020202,
- .reg_init_values[MSM_SPM_REG_SAW2_PMIC_DATA_0] = 0x0060009C,
- .reg_init_values[MSM_SPM_REG_SAW2_PMIC_DATA_1] = 0x0000001C,
- .vctl_timeout_us = 50,
- .num_modes = ARRAY_SIZE(msm_spm_seq_list),
- .modes = msm_spm_seq_list,
- },
-};
-
-static uint8_t l2_spm_wfi_cmd_sequence[] __initdata = {
- 0x00, 0x20, 0x03, 0x20,
- 0x00, 0x0f,
-};
-
-static uint8_t l2_spm_gdhs_cmd_sequence[] __initdata = {
- 0x00, 0x20, 0x34, 0x64,
- 0x48, 0x07, 0x48, 0x20,
- 0x50, 0x64, 0x04, 0x34,
- 0x50, 0x0f,
-};
-static uint8_t l2_spm_power_off_cmd_sequence[] __initdata = {
- 0x00, 0x10, 0x34, 0x64,
- 0x48, 0x07, 0x48, 0x10,
- 0x50, 0x64, 0x04, 0x34,
- 0x50, 0x0F,
-};
-
-static struct msm_spm_seq_entry msm_spm_l2_seq_list[] __initdata = {
- [0] = {
- .mode = MSM_SPM_L2_MODE_RETENTION,
- .notify_rpm = false,
- .cmd = l2_spm_wfi_cmd_sequence,
- },
- [1] = {
- .mode = MSM_SPM_L2_MODE_GDHS,
- .notify_rpm = true,
- .cmd = l2_spm_gdhs_cmd_sequence,
- },
- [2] = {
- .mode = MSM_SPM_L2_MODE_POWER_COLLAPSE,
- .notify_rpm = true,
- .cmd = l2_spm_power_off_cmd_sequence,
- },
-};
-
-
-static struct msm_spm_platform_data msm_spm_l2_data[] __initdata = {
- [0] = {
- .reg_base_addr = MSM_SAW_L2_BASE,
- .reg_init_values[MSM_SPM_REG_SAW2_SECURE] = 0x00,
- .reg_init_values[MSM_SPM_REG_SAW2_SPM_CTL] = 0x00,
- .reg_init_values[MSM_SPM_REG_SAW2_PMIC_DLY] = 0x02020202,
- .reg_init_values[MSM_SPM_REG_SAW2_PMIC_DATA_0] = 0x00A000AE,
- .reg_init_values[MSM_SPM_REG_SAW2_PMIC_DATA_1] = 0x00A00020,
- .modes = msm_spm_l2_seq_list,
- .num_modes = ARRAY_SIZE(msm_spm_l2_seq_list),
- },
-};
-
-#define PM_HAP_EN_GPIO PM8921_GPIO_PM_TO_SYS(33)
-#define PM_HAP_LEN_GPIO PM8921_GPIO_PM_TO_SYS(20)
-
-static struct msm_xo_voter *xo_handle_d1;
-
-static int isa1200_power(int on)
-{
- int rc = 0;
-
- gpio_set_value(HAP_SHIFT_LVL_OE_GPIO, !!on);
-
- rc = on ? msm_xo_mode_vote(xo_handle_d1, MSM_XO_MODE_ON) :
- msm_xo_mode_vote(xo_handle_d1, MSM_XO_MODE_OFF);
- if (rc < 0) {
- pr_err("%s: failed to %svote for TCXO D1 buffer%d\n",
- __func__, on ? "" : "de-", rc);
- goto err_xo_vote;
- }
-
- return 0;
-
-err_xo_vote:
- gpio_set_value(HAP_SHIFT_LVL_OE_GPIO, !on);
- return rc;
-}
-
-static int isa1200_dev_setup(bool enable)
-{
- int rc = 0;
-
- struct pm_gpio hap_gpio_config = {
- .direction = PM_GPIO_DIR_OUT,
- .pull = PM_GPIO_PULL_NO,
- .out_strength = PM_GPIO_STRENGTH_HIGH,
- .function = PM_GPIO_FUNC_NORMAL,
- .inv_int_pol = 0,
- .vin_sel = 2,
- .output_buffer = PM_GPIO_OUT_BUF_CMOS,
- .output_value = 0,
- };
-
- if (enable == true) {
- rc = pm8xxx_gpio_config(PM_HAP_EN_GPIO, &hap_gpio_config);
- if (rc) {
- pr_err("%s: pm8921 gpio %d config failed(%d)\n",
- __func__, PM_HAP_EN_GPIO, rc);
- return rc;
- }
-
- rc = pm8xxx_gpio_config(PM_HAP_LEN_GPIO, &hap_gpio_config);
- if (rc) {
- pr_err("%s: pm8921 gpio %d config failed(%d)\n",
- __func__, PM_HAP_LEN_GPIO, rc);
- return rc;
- }
-
- rc = gpio_request(HAP_SHIFT_LVL_OE_GPIO, "hap_shft_lvl_oe");
- if (rc) {
- pr_err("%s: unable to request gpio %d (%d)\n",
- __func__, HAP_SHIFT_LVL_OE_GPIO, rc);
- return rc;
- }
-
- rc = gpio_direction_output(HAP_SHIFT_LVL_OE_GPIO, 0);
- if (rc) {
- pr_err("%s: Unable to set direction\n", __func__);
- goto free_gpio;
- }
-
- xo_handle_d1 = msm_xo_get(MSM_XO_TCXO_D1, "isa1200");
- if (IS_ERR(xo_handle_d1)) {
- rc = PTR_ERR(xo_handle_d1);
- pr_err("%s: failed to get the handle for D1(%d)\n",
- __func__, rc);
- goto gpio_set_dir;
- }
- } else {
- gpio_free(HAP_SHIFT_LVL_OE_GPIO);
-
- msm_xo_put(xo_handle_d1);
- }
-
- return 0;
-
-gpio_set_dir:
- gpio_set_value(HAP_SHIFT_LVL_OE_GPIO, 0);
-free_gpio:
- gpio_free(HAP_SHIFT_LVL_OE_GPIO);
- return rc;
-}
-
-static struct isa1200_regulator isa1200_reg_data[] = {
- {
- .name = "vcc_i2c",
- .min_uV = ISA_I2C_VTG_MIN_UV,
- .max_uV = ISA_I2C_VTG_MAX_UV,
- .load_uA = ISA_I2C_CURR_UA,
- },
-};
-
-static struct isa1200_platform_data isa1200_1_pdata = {
- .name = "vibrator",
- .dev_setup = isa1200_dev_setup,
- .power_on = isa1200_power,
- .hap_en_gpio = PM_HAP_EN_GPIO,
- .hap_len_gpio = PM_HAP_LEN_GPIO,
- .max_timeout = 15000,
- .mode_ctrl = PWM_GEN_MODE,
- .pwm_fd = {
- .pwm_div = 256,
- },
- .is_erm = false,
- .smart_en = true,
- .ext_clk_en = true,
- .chip_en = 1,
- .regulator_info = isa1200_reg_data,
- .num_regulators = ARRAY_SIZE(isa1200_reg_data),
-};
-
-static struct i2c_board_info msm_isa1200_board_info[] __initdata = {
- {
- I2C_BOARD_INFO("isa1200_1", 0x90>>1),
- .platform_data = &isa1200_1_pdata,
- },
-};
-
-#define CYTTSP_TS_GPIO_IRQ 11
-#define CYTTSP_TS_SLEEP_GPIO 50
-#define CYTTSP_TS_RESOUT_N_GPIO 52
-
-/*virtual key support */
-static ssize_t tma340_vkeys_show(struct kobject *kobj,
- struct kobj_attribute *attr, char *buf)
-{
- return snprintf(buf, 200,
- __stringify(EV_KEY) ":" __stringify(KEY_BACK) ":73:1120:97:97"
- ":" __stringify(EV_KEY) ":" __stringify(KEY_MENU) ":230:1120:97:97"
- ":" __stringify(EV_KEY) ":" __stringify(KEY_HOME) ":389:1120:97:97"
- ":" __stringify(EV_KEY) ":" __stringify(KEY_SEARCH) ":544:1120:97:97"
- "\n");
-}
-
-static struct kobj_attribute tma340_vkeys_attr = {
- .attr = {
- .mode = S_IRUGO,
- },
- .show = &tma340_vkeys_show,
-};
-
-static struct attribute *tma340_properties_attrs[] = {
- &tma340_vkeys_attr.attr,
- NULL
-};
-
-static struct attribute_group tma340_properties_attr_group = {
- .attrs = tma340_properties_attrs,
-};
-
-
-static int cyttsp_platform_init(struct i2c_client *client)
-{
- int rc = 0;
- static struct kobject *tma340_properties_kobj;
-
- tma340_vkeys_attr.attr.name = "virtualkeys.cyttsp-i2c";
- tma340_properties_kobj = kobject_create_and_add("board_properties",
- NULL);
- if (tma340_properties_kobj)
- rc = sysfs_create_group(tma340_properties_kobj,
- &tma340_properties_attr_group);
- if (!tma340_properties_kobj || rc)
- pr_err("%s: failed to create board_properties\n",
- __func__);
-
- return 0;
-}
-
-static struct cyttsp_regulator regulator_data[] = {
- {
- .name = "vdd",
- .min_uV = CY_TMA300_VTG_MIN_UV,
- .max_uV = CY_TMA300_VTG_MAX_UV,
- .hpm_load_uA = CY_TMA300_CURR_24HZ_UA,
- .lpm_load_uA = CY_TMA300_SLEEP_CURR_UA,
- },
- /* TODO: Remove after runtime PM is enabled in I2C driver */
- {
- .name = "vcc_i2c",
- .min_uV = CY_I2C_VTG_MIN_UV,
- .max_uV = CY_I2C_VTG_MAX_UV,
- .hpm_load_uA = CY_I2C_CURR_UA,
- .lpm_load_uA = CY_I2C_SLEEP_CURR_UA,
- },
-};
-
-static struct cyttsp_platform_data cyttsp_pdata = {
- .panel_maxx = 634,
- .panel_maxy = 1166,
- .disp_maxx = 616,
- .disp_maxy = 1023,
- .disp_minx = 0,
- .disp_miny = 16,
- .flags = 0x01,
- .gen = CY_GEN3, /* or */
- .use_st = CY_USE_ST,
- .use_mt = CY_USE_MT,
- .use_hndshk = CY_SEND_HNDSHK,
- .use_trk_id = CY_USE_TRACKING_ID,
- .use_sleep = CY_USE_DEEP_SLEEP_SEL | CY_USE_LOW_POWER_SEL,
- .use_gestures = CY_USE_GESTURES,
- .fw_fname = "cyttsp_8960_cdp.hex",
- /* activate up to 4 groups
- * and set active distance
- */
- .gest_set = CY_GEST_GRP1 | CY_GEST_GRP2 |
- CY_GEST_GRP3 | CY_GEST_GRP4 |
- CY_ACT_DIST,
- /* change act_intrvl to customize the Active power state
- * scanning/processing refresh interval for Operating mode
- */
- .act_intrvl = CY_ACT_INTRVL_DFLT,
- /* change tch_tmout to customize the touch timeout for the
- * Active power state for Operating mode
- */
- .tch_tmout = CY_TCH_TMOUT_DFLT,
- /* change lp_intrvl to customize the Low Power power state
- * scanning/processing refresh interval for Operating mode
- */
- .lp_intrvl = CY_LP_INTRVL_DFLT,
- .sleep_gpio = CYTTSP_TS_SLEEP_GPIO,
- .resout_gpio = CYTTSP_TS_RESOUT_N_GPIO,
- .irq_gpio = CYTTSP_TS_GPIO_IRQ,
- .regulator_info = regulator_data,
- .num_regulators = ARRAY_SIZE(regulator_data),
- .init = cyttsp_platform_init,
- .correct_fw_ver = 9,
-};
-
-static struct i2c_board_info cyttsp_info[] __initdata = {
- {
- I2C_BOARD_INFO(CY_I2C_NAME, 0x24),
- .platform_data = &cyttsp_pdata,
-#ifndef CY_USE_TIMER
- .irq = MSM_GPIO_TO_INT(CYTTSP_TS_GPIO_IRQ),
-#endif /* CY_USE_TIMER */
- },
-};
-
-/* configuration data */
-static const u8 mxt_config_data[] = {
- /* T6 Object */
- 0, 0, 0, 0, 0, 0,
- /* T38 Object */
- 11, 2, 0, 11, 11, 11, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0,
- /* T7 Object */
- 100, 16, 50,
- /* T8 Object */
- 8, 0, 0, 0, 0, 0, 8, 14, 50, 215,
- /* T9 Object */
- 131, 0, 0, 26, 42, 0, 32, 63, 3, 5,
- 0, 2, 1, 113, 10, 10, 8, 10, 255, 2,
- 85, 5, 0, 0, 20, 20, 75, 25, 202, 29,
- 10, 10, 45, 46,
- /* T15 Object */
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0,
- /* T22 Object */
- 5, 0, 0, 0, 0, 0, 0, 0, 30, 0,
- 0, 0, 5, 8, 10, 13, 0,
- /* T24 Object */
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0,
- /* T25 Object */
- 3, 0, 188, 52, 52, 33, 0, 0, 0, 0,
- 0, 0, 0, 0,
- /* T27 Object */
- 0, 0, 0, 0, 0, 0, 0,
- /* T28 Object */
- 0, 0, 0, 8, 12, 60,
- /* T40 Object */
- 0, 0, 0, 0, 0,
- /* T41 Object */
- 0, 0, 0, 0, 0, 0,
- /* T43 Object */
- 0, 0, 0, 0, 0, 0,
-};
-
-#define MXT_TS_GPIO_IRQ 11
-#define MXT_TS_LDO_EN_GPIO 50
-#define MXT_TS_RESET_GPIO 52
-
-static void mxt_init_hw_liquid(void)
-{
- int rc;
-
- rc = gpio_request(MXT_TS_GPIO_IRQ, "mxt_ts_irq_gpio");
- if (rc) {
- pr_err("%s: unable to request mxt_ts_irq gpio [%d]\n",
- __func__, MXT_TS_GPIO_IRQ);
- return;
- }
-
- rc = gpio_direction_input(MXT_TS_GPIO_IRQ);
- if (rc) {
- pr_err("%s: unable to set_direction for mxt_ts_irq gpio [%d]\n",
- __func__, MXT_TS_GPIO_IRQ);
- goto err_irq_gpio_req;
- }
-
- rc = gpio_request(MXT_TS_LDO_EN_GPIO, "mxt_ldo_en_gpio");
- if (rc) {
- pr_err("%s: unable to request mxt_ldo_en gpio [%d]\n",
- __func__, MXT_TS_LDO_EN_GPIO);
- goto err_irq_gpio_req;
- }
-
- rc = gpio_direction_output(MXT_TS_LDO_EN_GPIO, 1);
- if (rc) {
- pr_err("%s: unable to set_direction for mxt_ldo_en gpio [%d]\n",
- __func__, MXT_TS_LDO_EN_GPIO);
- goto err_ldo_gpio_req;
- }
-
- rc = gpio_request(MXT_TS_RESET_GPIO, "mxt_reset_gpio");
- if (rc) {
- pr_err("%s: unable to request mxt_reset gpio [%d]\n",
- __func__, MXT_TS_RESET_GPIO);
- goto err_ldo_gpio_set_dir;
- }
-
- rc = gpio_direction_output(MXT_TS_RESET_GPIO, 1);
- if (rc) {
- pr_err("%s: unable to set_direction for mxt_reset gpio [%d]\n",
- __func__, MXT_TS_RESET_GPIO);
- goto err_reset_gpio_req;
- }
-
- return;
-
-err_reset_gpio_req:
- gpio_free(MXT_TS_RESET_GPIO);
-err_ldo_gpio_set_dir:
- gpio_set_value(MXT_TS_LDO_EN_GPIO, 0);
-err_ldo_gpio_req:
- gpio_free(MXT_TS_LDO_EN_GPIO);
-err_irq_gpio_req:
- gpio_free(MXT_TS_GPIO_IRQ);
-}
-
-static struct mxt_platform_data mxt_platform_data = {
- .config = mxt_config_data,
- .config_length = ARRAY_SIZE(mxt_config_data),
- .x_size = 1365,
- .y_size = 767,
- .irqflags = IRQF_TRIGGER_FALLING,
- .i2c_pull_up = true,
-};
-
-static struct i2c_board_info mxt_device_info[] __initdata = {
- {
- I2C_BOARD_INFO("atmel_mxt_ts", 0x5b),
- .platform_data = &mxt_platform_data,
- .irq = MSM_GPIO_TO_INT(MXT_TS_GPIO_IRQ),
- },
-};
-
-static void gsbi_qup_i2c_gpio_config(int adap_id, int config_type)
-{
-}
-
-static struct msm_i2c_platform_data msm8960_i2c_qup_gsbi4_pdata = {
- .clk_freq = 100000,
- .src_clk_rate = 24000000,
- .msm_i2c_config_gpio = gsbi_qup_i2c_gpio_config,
-};
-
-static struct msm_i2c_platform_data msm8960_i2c_qup_gsbi3_pdata = {
- .clk_freq = 100000,
- .src_clk_rate = 24000000,
- .msm_i2c_config_gpio = gsbi_qup_i2c_gpio_config,
-};
-
-static struct msm_i2c_platform_data msm8960_i2c_qup_gsbi10_pdata = {
- .clk_freq = 100000,
- .src_clk_rate = 24000000,
- .msm_i2c_config_gpio = gsbi_qup_i2c_gpio_config,
-};
-
-static struct msm_i2c_platform_data msm8960_i2c_qup_gsbi12_pdata = {
- .clk_freq = 100000,
- .src_clk_rate = 24000000,
- .msm_i2c_config_gpio = gsbi_qup_i2c_gpio_config,
-};
-
-static struct msm_rpm_platform_data msm_rpm_data = {
- .reg_base_addrs = {
- [MSM_RPM_PAGE_STATUS] = MSM_RPM_BASE,
- [MSM_RPM_PAGE_CTRL] = MSM_RPM_BASE + 0x400,
- [MSM_RPM_PAGE_REQ] = MSM_RPM_BASE + 0x600,
- [MSM_RPM_PAGE_ACK] = MSM_RPM_BASE + 0xa00,
- },
-
- .irq_ack = RPM_APCC_CPU0_GP_HIGH_IRQ,
- .irq_err = RPM_APCC_CPU0_GP_LOW_IRQ,
- .irq_vmpm = RPM_APCC_CPU0_GP_MEDIUM_IRQ,
- .msm_apps_ipc_rpm_reg = MSM_APCS_GCC_BASE + 0x008,
- .msm_apps_ipc_rpm_val = 4,
-};
-
-static struct ks8851_pdata spi_eth_pdata = {
- .irq_gpio = KS8851_IRQ_GPIO,
- .rst_gpio = KS8851_RST_GPIO,
-};
-
-static struct spi_board_info spi_board_info[] __initdata = {
- {
- .modalias = "ks8851",
- .irq = MSM_GPIO_TO_INT(KS8851_IRQ_GPIO),
- .max_speed_hz = 19200000,
- .bus_num = 0,
- .chip_select = 0,
- .mode = SPI_MODE_0,
- .platform_data = &spi_eth_pdata
- },
- {
- .modalias = "dsi_novatek_3d_panel_spi",
- .max_speed_hz = 10800000,
- .bus_num = 0,
- .chip_select = 1,
- .mode = SPI_MODE_0,
- },
-};
-
-static struct platform_device msm_device_saw_core0 = {
- .name = "saw-regulator",
- .id = 0,
- .dev = {
- .platform_data = &msm_saw_regulator_pdata_s5,
- },
-};
-
-static struct platform_device msm_device_saw_core1 = {
- .name = "saw-regulator",
- .id = 1,
- .dev = {
- .platform_data = &msm_saw_regulator_pdata_s6,
- },
-};
-
-#ifdef CONFIG_FB_MSM_WRITEBACK_MSM_PANEL
-static struct platform_device wfd_device = {
- .name = "msm_wfd",
- .id = -1,
-};
-#endif
-
-static struct tsens_platform_data msm_tsens_pdata = {
- .slope = 910,
- .tsens_factor = 1000,
- .hw_type = MSM_8960,
- .tsens_num_sensor = 5,
-};
-
-static struct platform_device msm_tsens_device = {
- .name = "tsens8960-tm",
- .id = -1,
- .dev = {
- .platform_data = &msm_tsens_pdata,
- },
-};
-
-#ifdef CONFIG_MSM_FAKE_BATTERY
-static struct platform_device fish_battery_device = {
- .name = "fish_battery",
-};
-#endif
-
-static struct platform_device msm8960_device_ext_5v_vreg __devinitdata = {
- .name = GPIO_REGULATOR_DEV_NAME,
- .id = PM8921_MPP_PM_TO_SYS(7),
- .dev = {
- .platform_data = &msm_gpio_regulator_pdata[GPIO_VREG_ID_EXT_5V],
- },
-};
-
-static struct platform_device msm8960_device_ext_l2_vreg __devinitdata = {
- .name = GPIO_REGULATOR_DEV_NAME,
- .id = 91,
- .dev = {
- .platform_data = &msm_gpio_regulator_pdata[GPIO_VREG_ID_EXT_L2],
- },
-};
-
-static struct platform_device msm8960_device_ext_3p3v_vreg __devinitdata = {
- .name = GPIO_REGULATOR_DEV_NAME,
- .id = PM8921_GPIO_PM_TO_SYS(17),
- .dev = {
- .platform_data =
- &msm_gpio_regulator_pdata[GPIO_VREG_ID_EXT_3P3V],
- },
-};
-
-static struct platform_device msm8960_device_rpm_regulator __devinitdata = {
- .name = "rpm-regulator",
- .id = -1,
- .dev = {
- .platform_data = &msm_rpm_regulator_pdata,
- },
-};
-
-static struct msm_rpm_log_platform_data msm_rpm_log_pdata = {
- .phys_addr_base = 0x0010C000,
- .reg_offsets = {
- [MSM_RPM_LOG_PAGE_INDICES] = 0x00000080,
- [MSM_RPM_LOG_PAGE_BUFFER] = 0x000000A0,
- },
- .phys_size = SZ_8K,
- .log_len = 4096, /* log's buffer length in bytes */
- .log_len_mask = (4096 >> 2) - 1, /* length mask in units of u32 */
-};
-
-static struct platform_device msm_rpm_log_device = {
- .name = "msm_rpm_log",
- .id = -1,
- .dev = {
- .platform_data = &msm_rpm_log_pdata,
- },
-};
-
-static struct platform_device *common_devices[] __initdata = {
- &msm8960_device_dmov,
- &msm_device_smd,
- &msm8960_device_uart_gsbi5,
- &msm_device_uart_dm6,
- &msm_device_saw_core0,
- &msm_device_saw_core1,
- &msm8960_device_ext_5v_vreg,
- &msm8960_device_ext_l2_vreg,
- &msm8960_device_ssbi_pm8921,
- &msm8960_device_qup_spi_gsbi1,
- &msm8960_device_qup_i2c_gsbi3,
- &msm8960_device_qup_i2c_gsbi4,
- &msm8960_device_qup_i2c_gsbi10,
-#ifndef CONFIG_MSM_DSPS
- &msm8960_device_qup_i2c_gsbi12,
-#endif
- &msm_slim_ctrl,
- &msm_device_wcnss_wlan,
-#if defined(CONFIG_CRYPTO_DEV_QCRYPTO) || \
- defined(CONFIG_CRYPTO_DEV_QCRYPTO_MODULE)
- &qcrypto_device,
-#endif
-
-#if defined(CONFIG_CRYPTO_DEV_QCEDEV) || \
- defined(CONFIG_CRYPTO_DEV_QCEDEV_MODULE)
- &qcedev_device,
-#endif
-#ifdef CONFIG_MSM_ROTATOR
- &msm_rotator_device,
-#endif
- &msm_device_sps,
-#ifdef CONFIG_MSM_FAKE_BATTERY
- &fish_battery_device,
-#endif
-#ifdef CONFIG_ANDROID_PMEM
-#ifndef CONFIG_MSM_MULTIMEDIA_USE_ION
- &android_pmem_device,
- &android_pmem_adsp_device,
-#endif
- &android_pmem_audio_device,
-#endif
- &msm_fb_device,
- &msm_device_vidc,
- &msm_device_bam_dmux,
- &msm_fm_platform_init,
-
-#ifdef CONFIG_HW_RANDOM_MSM
- &msm_device_rng,
-#endif
- &msm_rpm_device,
-#ifdef CONFIG_ION_MSM
- &ion_dev,
-#endif
- &msm_rpm_log_device,
- &msm_rpm_stat_device,
- &msm_device_tz_log,
-
-#ifdef CONFIG_MSM_QDSS
- &msm_etb_device,
- &msm_tpiu_device,
- &msm_funnel_device,
- &msm_debug_device,
- &msm_ptm_device,
-#endif
- &msm_device_dspcrashd_8960,
- &msm8960_device_watchdog,
-#ifdef CONFIG_FB_MSM_WRITEBACK_MSM_PANEL
- &wfd_panel_device,
- &wfd_device,
-#endif
-};
-
-static struct platform_device *sim_devices[] __initdata = {
- &msm8960_device_otg,
- &msm8960_device_gadget_peripheral,
- &msm_device_hsusb_host,
- &msm_device_hsic_host,
- &android_usb_device,
- &msm_device_vidc,
- &mipi_dsi_simulator_panel_device,
- &msm_bus_apps_fabric,
- &msm_bus_sys_fabric,
- &msm_bus_mm_fabric,
- &msm_bus_sys_fpb,
- &msm_bus_cpss_fpb,
- &msm_pcm,
- &msm_pcm_routing,
- &msm_cpudai0,
- &msm_cpudai1,
- &msm_cpudai_hdmi_rx,
- &msm_cpudai_bt_rx,
- &msm_cpudai_bt_tx,
- &msm_cpudai_fm_rx,
- &msm_cpudai_fm_tx,
- &msm_cpudai_auxpcm_rx,
- &msm_cpudai_auxpcm_tx,
- &msm_cpu_fe,
- &msm_stub_codec,
- &msm_voice,
- &msm_voip,
- &msm_lpa_pcm,
-
-#if defined(CONFIG_CRYPTO_DEV_QCRYPTO) || \
- defined(CONFIG_CRYPTO_DEV_QCRYPTO_MODULE)
- &qcrypto_device,
-#endif
-
-#if defined(CONFIG_CRYPTO_DEV_QCEDEV) || \
- defined(CONFIG_CRYPTO_DEV_QCEDEV_MODULE)
- &qcedev_device,
-#endif
-};
-
-static struct platform_device *rumi3_devices[] __initdata = {
- &msm_kgsl_3d0,
- &msm_kgsl_2d0,
- &msm_kgsl_2d1,
- &mipi_dsi_renesas_panel_device,
-#ifdef CONFIG_MSM_GEMINI
- &msm8960_gemini_device,
-#endif
-};
-
-static struct platform_device *cdp_devices[] __initdata = {
- &msm8960_device_otg,
- &msm8960_device_gadget_peripheral,
- &msm_device_hsusb_host,
- &android_usb_device,
- &msm_pcm,
- &msm_pcm_routing,
- &msm_cpudai0,
- &msm_cpudai1,
- &msm_cpudai_hdmi_rx,
- &msm_cpudai_bt_rx,
- &msm_cpudai_bt_tx,
- &msm_cpudai_fm_rx,
- &msm_cpudai_fm_tx,
- &msm_cpudai_auxpcm_rx,
- &msm_cpudai_auxpcm_tx,
- &msm_cpu_fe,
- &msm_stub_codec,
- &msm_kgsl_3d0,
-#ifdef CONFIG_MSM_KGSL_2D
- &msm_kgsl_2d0,
- &msm_kgsl_2d1,
-#endif
- &mipi_dsi_novatek_panel_device,
-#ifdef CONFIG_MSM_GEMINI
- &msm8960_gemini_device,
-#endif
- &msm_voice,
- &msm_voip,
- &msm_lpa_pcm,
- &msm_cpudai_afe_01_rx,
- &msm_cpudai_afe_01_tx,
- &msm_cpudai_afe_02_rx,
- &msm_cpudai_afe_02_tx,
- &msm_pcm_afe,
-#ifdef CONFIG_FB_MSM_HDMI_MSM_PANEL
- &hdmi_msm_device,
-#endif
- &msm_pcm_hostless,
- &msm_bus_apps_fabric,
- &msm_bus_sys_fabric,
- &msm_bus_mm_fabric,
- &msm_bus_sys_fpb,
- &msm_bus_cpss_fpb,
- &msm_tsens_device,
-};
-
-static void __init msm8960_i2c_init(void)
-{
- msm8960_device_qup_i2c_gsbi4.dev.platform_data =
- &msm8960_i2c_qup_gsbi4_pdata;
-
- msm8960_device_qup_i2c_gsbi3.dev.platform_data =
- &msm8960_i2c_qup_gsbi3_pdata;
-
- msm8960_device_qup_i2c_gsbi10.dev.platform_data =
- &msm8960_i2c_qup_gsbi10_pdata;
-
- msm8960_device_qup_i2c_gsbi12.dev.platform_data =
- &msm8960_i2c_qup_gsbi12_pdata;
-}
-
-static void __init msm8960_gfx_init(void)
-{
- uint32_t soc_platform_version = socinfo_get_version();
- if (SOCINFO_VERSION_MAJOR(soc_platform_version) == 1) {
- struct kgsl_device_platform_data *kgsl_3d0_pdata =
- msm_kgsl_3d0.dev.platform_data;
- kgsl_3d0_pdata->pwrlevel[0].gpu_freq = 320000000;
- kgsl_3d0_pdata->pwrlevel[1].gpu_freq = 266667000;
- }
-}
-
-static struct pm8xxx_irq_platform_data pm8xxx_irq_pdata __devinitdata = {
- .irq_base = PM8921_IRQ_BASE,
- .devirq = MSM_GPIO_TO_INT(104),
- .irq_trigger_flag = IRQF_TRIGGER_LOW,
-};
-
-static struct pm8xxx_gpio_platform_data pm8xxx_gpio_pdata __devinitdata = {
- .gpio_base = PM8921_GPIO_PM_TO_SYS(1),
-};
-
-static struct pm8xxx_mpp_platform_data pm8xxx_mpp_pdata __devinitdata = {
- .mpp_base = PM8921_MPP_PM_TO_SYS(1),
-};
-
-static struct pm8xxx_rtc_platform_data pm8xxx_rtc_pdata __devinitdata = {
- .rtc_write_enable = false,
- .rtc_alarm_powerup = false,
-};
-
-static struct pm8xxx_pwrkey_platform_data pm8xxx_pwrkey_pdata = {
- .pull_up = 1,
- .kpd_trigger_delay_us = 970,
- .wakeup = 1,
-};
-
-/* Rotate lock key is not available so use F1 */
-#define KEY_ROTATE_LOCK KEY_F1
-
-static const unsigned int keymap_liquid[] = {
- KEY(0, 0, KEY_VOLUMEUP),
- KEY(0, 1, KEY_VOLUMEDOWN),
- KEY(1, 3, KEY_ROTATE_LOCK),
- KEY(1, 4, KEY_HOME),
-};
-
-static struct matrix_keymap_data keymap_data_liquid = {
- .keymap_size = ARRAY_SIZE(keymap_liquid),
- .keymap = keymap_liquid,
-};
-
-static struct pm8xxx_keypad_platform_data keypad_data_liquid = {
- .input_name = "keypad_8960_liquid",
- .input_phys_device = "keypad_8960/input0",
- .num_rows = 2,
- .num_cols = 5,
- .rows_gpio_start = PM8921_GPIO_PM_TO_SYS(9),
- .cols_gpio_start = PM8921_GPIO_PM_TO_SYS(1),
- .debounce_ms = 15,
- .scan_delay_ms = 32,
- .row_hold_ns = 91500,
- .wakeup = 1,
- .keymap_data = &keymap_data_liquid,
-};
-
-
-static const unsigned int keymap[] = {
- KEY(0, 0, KEY_VOLUMEUP),
- KEY(0, 1, KEY_VOLUMEDOWN),
- KEY(0, 2, KEY_CAMERA_SNAPSHOT),
- KEY(0, 3, KEY_CAMERA_FOCUS),
-};
-
-static struct matrix_keymap_data keymap_data = {
- .keymap_size = ARRAY_SIZE(keymap),
- .keymap = keymap,
-};
-
-static struct pm8xxx_keypad_platform_data keypad_data = {
- .input_name = "keypad_8960",
- .input_phys_device = "keypad_8960/input0",
- .num_rows = 1,
- .num_cols = 5,
- .rows_gpio_start = PM8921_GPIO_PM_TO_SYS(9),
- .cols_gpio_start = PM8921_GPIO_PM_TO_SYS(1),
- .debounce_ms = 15,
- .scan_delay_ms = 32,
- .row_hold_ns = 91500,
- .wakeup = 1,
- .keymap_data = &keymap_data,
-};
-
-static const unsigned int keymap_sim[] = {
- KEY(0, 0, KEY_7),
- KEY(0, 1, KEY_DOWN),
- KEY(0, 2, KEY_UP),
- KEY(0, 3, KEY_RIGHT),
- KEY(0, 4, KEY_ENTER),
- KEY(0, 5, KEY_L),
- KEY(0, 6, KEY_BACK),
- KEY(0, 7, KEY_M),
-
- KEY(1, 0, KEY_LEFT),
- KEY(1, 1, KEY_SEND),
- KEY(1, 2, KEY_1),
- KEY(1, 3, KEY_4),
- KEY(1, 4, KEY_CLEAR),
- KEY(1, 5, KEY_MSDOS),
- KEY(1, 6, KEY_SPACE),
- KEY(1, 7, KEY_COMMA),
-
- KEY(2, 0, KEY_6),
- KEY(2, 1, KEY_5),
- KEY(2, 2, KEY_8),
- KEY(2, 3, KEY_3),
- KEY(2, 4, KEY_NUMERIC_STAR),
- KEY(2, 5, KEY_UP),
- KEY(2, 6, KEY_DOWN),
- KEY(2, 7, KEY_LEFTSHIFT),
-
- KEY(3, 0, KEY_9),
- KEY(3, 1, KEY_NUMERIC_POUND),
- KEY(3, 2, KEY_0),
- KEY(3, 3, KEY_2),
- KEY(3, 4, KEY_SLEEP),
- KEY(3, 5, KEY_F1),
- KEY(3, 6, KEY_F2),
- KEY(3, 7, KEY_F3),
-
- KEY(4, 0, KEY_BACK),
- KEY(4, 1, KEY_HOME),
- KEY(4, 2, KEY_MENU),
- KEY(4, 3, KEY_VOLUMEUP),
- KEY(4, 4, KEY_VOLUMEDOWN),
- KEY(4, 5, KEY_F4),
- KEY(4, 6, KEY_F5),
- KEY(4, 7, KEY_F6),
-
- KEY(5, 0, KEY_R),
- KEY(5, 1, KEY_T),
- KEY(5, 2, KEY_Y),
- KEY(5, 3, KEY_LEFTALT),
- KEY(5, 4, KEY_KPENTER),
- KEY(5, 5, KEY_Q),
- KEY(5, 6, KEY_W),
- KEY(5, 7, KEY_E),
-
- KEY(6, 0, KEY_F),
- KEY(6, 1, KEY_G),
- KEY(6, 2, KEY_H),
- KEY(6, 3, KEY_CAPSLOCK),
- KEY(6, 4, KEY_PAGEUP),
- KEY(6, 5, KEY_A),
- KEY(6, 6, KEY_S),
- KEY(6, 7, KEY_D),
-
- KEY(7, 0, KEY_V),
- KEY(7, 1, KEY_B),
- KEY(7, 2, KEY_N),
- KEY(7, 3, KEY_MENU),
- KEY(7, 4, KEY_PAGEDOWN),
- KEY(7, 5, KEY_Z),
- KEY(7, 6, KEY_X),
- KEY(7, 7, KEY_C),
-
- KEY(8, 0, KEY_P),
- KEY(8, 1, KEY_J),
- KEY(8, 2, KEY_K),
- KEY(8, 3, KEY_INSERT),
- KEY(8, 4, KEY_LINEFEED),
- KEY(8, 5, KEY_U),
- KEY(8, 6, KEY_I),
- KEY(8, 7, KEY_O),
-
- KEY(9, 0, KEY_4),
- KEY(9, 1, KEY_5),
- KEY(9, 2, KEY_6),
- KEY(9, 3, KEY_7),
- KEY(9, 4, KEY_8),
- KEY(9, 5, KEY_1),
- KEY(9, 6, KEY_2),
- KEY(9, 7, KEY_3),
-
- KEY(10, 0, KEY_F7),
- KEY(10, 1, KEY_F8),
- KEY(10, 2, KEY_F9),
- KEY(10, 3, KEY_F10),
- KEY(10, 4, KEY_FN),
- KEY(10, 5, KEY_9),
- KEY(10, 6, KEY_0),
- KEY(10, 7, KEY_DOT),
-
- KEY(11, 0, KEY_LEFTCTRL),
- KEY(11, 1, KEY_F11),
- KEY(11, 2, KEY_ENTER),
- KEY(11, 3, KEY_SEARCH),
- KEY(11, 4, KEY_DELETE),
- KEY(11, 5, KEY_RIGHT),
- KEY(11, 6, KEY_LEFT),
- KEY(11, 7, KEY_RIGHTSHIFT),
- KEY(0, 0, KEY_VOLUMEUP),
- KEY(0, 1, KEY_VOLUMEDOWN),
- KEY(0, 2, KEY_CAMERA_SNAPSHOT),
- KEY(0, 3, KEY_CAMERA_FOCUS),
-};
-
-static struct matrix_keymap_data keymap_data_sim = {
- .keymap_size = ARRAY_SIZE(keymap_sim),
- .keymap = keymap_sim,
-};
-
-static struct pm8xxx_keypad_platform_data keypad_data_sim = {
- .input_name = "keypad_8960",
- .input_phys_device = "keypad_8960/input0",
- .num_rows = 12,
- .num_cols = 8,
- .rows_gpio_start = PM8921_GPIO_PM_TO_SYS(9),
- .cols_gpio_start = PM8921_GPIO_PM_TO_SYS(1),
- .debounce_ms = 15,
- .scan_delay_ms = 32,
- .row_hold_ns = 91500,
- .wakeup = 1,
- .keymap_data = &keymap_data_sim,
-};
-
-static int pm8921_therm_mitigation[] = {
- 1100,
- 700,
- 600,
- 325,
-};
-
-static struct pm8921_charger_platform_data pm8921_chg_pdata __devinitdata = {
- .safety_time = 180,
- .update_time = 60000,
- .max_voltage = 4200,
- .min_voltage = 3200,
- .resume_voltage_delta = 100,
- .term_current = 100,
- .cool_temp = 10,
- .warm_temp = 40,
- .temp_check_period = 1,
- .max_bat_chg_current = 1100,
- .cool_bat_chg_current = 350,
- .warm_bat_chg_current = 350,
- .cool_bat_voltage = 4100,
- .warm_bat_voltage = 4100,
- .thermal_mitigation = pm8921_therm_mitigation,
- .thermal_levels = ARRAY_SIZE(pm8921_therm_mitigation),
-};
-
-static struct pm8xxx_misc_platform_data pm8xxx_misc_pdata = {
- .priority = 0,
-};
-
-static struct pm8921_bms_platform_data pm8921_bms_pdata __devinitdata = {
- .r_sense = 10,
- .i_test = 2500,
- .v_failure = 3000,
- .calib_delay_ms = 600000,
-};
-
-#define PM8921_LC_LED_MAX_CURRENT 4 /* I = 4mA */
-#define PM8XXX_LED_PWM_PERIOD 1000
-#define PM8XXX_LED_PWM_DUTY_MS 20
-/**
- * PM8XXX_PWM_CHANNEL_NONE shall be used when LED shall not be
- * driven using PWM feature.
- */
-#define PM8XXX_PWM_CHANNEL_NONE -1
-
-static struct led_info pm8921_led_info[] = {
- [0] = {
- .name = "led:battery_charging",
- .default_trigger = "battery-charging",
- },
- [1] = {
- .name = "led:battery_full",
- .default_trigger = "battery-full",
- },
-};
-
-static struct led_platform_data pm8921_led_core_pdata = {
- .num_leds = ARRAY_SIZE(pm8921_led_info),
- .leds = pm8921_led_info,
-};
-
-static int pm8921_led0_pwm_duty_pcts[56] = {
- 1, 4, 8, 12, 16, 20, 24, 28, 32, 36,
- 40, 44, 46, 52, 56, 60, 64, 68, 72, 76,
- 80, 84, 88, 92, 96, 100, 100, 100, 98, 95,
- 92, 88, 84, 82, 78, 74, 70, 66, 62, 58,
- 58, 54, 50, 48, 42, 38, 34, 30, 26, 22,
- 14, 10, 6, 4, 1
-};
-
-static struct pm8xxx_pwm_duty_cycles pm8921_led0_pwm_duty_cycles = {
- .duty_pcts = (int *)&pm8921_led0_pwm_duty_pcts,
- .num_duty_pcts = ARRAY_SIZE(pm8921_led0_pwm_duty_pcts),
- .duty_ms = PM8XXX_LED_PWM_DUTY_MS,
- .start_idx = 0,
-};
-
-static struct pm8xxx_led_config pm8921_led_configs[] = {
- [0] = {
- .id = PM8XXX_ID_LED_0,
- .mode = PM8XXX_LED_MODE_PWM2,
- .max_current = PM8921_LC_LED_MAX_CURRENT,
- .pwm_channel = 5,
- .pwm_period_us = PM8XXX_LED_PWM_PERIOD,
- .pwm_duty_cycles = &pm8921_led0_pwm_duty_cycles,
- },
- [1] = {
- .id = PM8XXX_ID_LED_1,
- .mode = PM8XXX_LED_MODE_PWM1,
- .max_current = PM8921_LC_LED_MAX_CURRENT,
- .pwm_channel = 4,
- .pwm_period_us = PM8XXX_LED_PWM_PERIOD,
- },
-};
-
-static struct pm8xxx_led_platform_data pm8xxx_leds_pdata = {
- .led_core = &pm8921_led_core_pdata,
- .configs = pm8921_led_configs,
- .num_configs = ARRAY_SIZE(pm8921_led_configs),
-};
-
-static struct pm8xxx_ccadc_platform_data pm8xxx_ccadc_pdata = {
- .r_sense = 10,
-};
-
-static struct pm8921_platform_data pm8921_platform_data __devinitdata = {
- .irq_pdata = &pm8xxx_irq_pdata,
- .gpio_pdata = &pm8xxx_gpio_pdata,
- .mpp_pdata = &pm8xxx_mpp_pdata,
- .rtc_pdata = &pm8xxx_rtc_pdata,
- .pwrkey_pdata = &pm8xxx_pwrkey_pdata,
- .keypad_pdata = &keypad_data,
- .misc_pdata = &pm8xxx_misc_pdata,
- .regulator_pdatas = msm_pm8921_regulator_pdata,
- .charger_pdata = &pm8921_chg_pdata,
- .bms_pdata = &pm8921_bms_pdata,
- .adc_pdata = &pm8xxx_adc_pdata,
- .leds_pdata = &pm8xxx_leds_pdata,
- .ccadc_pdata = &pm8xxx_ccadc_pdata,
-};
-
-static struct msm_ssbi_platform_data msm8960_ssbi_pm8921_pdata __devinitdata = {
- .controller_type = MSM_SBI_CTRL_PMIC_ARBITER,
- .slave = {
- .name = "pm8921-core",
- .platform_data = &pm8921_platform_data,
- },
-};
-
-static struct msm_cpuidle_state msm_cstates[] __initdata = {
- {0, 0, "C0", "WFI",
- MSM_PM_SLEEP_MODE_WAIT_FOR_INTERRUPT},
-
- {0, 1, "C1", "STANDALONE_POWER_COLLAPSE",
- MSM_PM_SLEEP_MODE_POWER_COLLAPSE_STANDALONE},
-
- {0, 2, "C2", "POWER_COLLAPSE",
- MSM_PM_SLEEP_MODE_POWER_COLLAPSE},
-
- {1, 0, "C0", "WFI",
- MSM_PM_SLEEP_MODE_WAIT_FOR_INTERRUPT},
-
- {1, 1, "C1", "STANDALONE_POWER_COLLAPSE",
- MSM_PM_SLEEP_MODE_POWER_COLLAPSE_STANDALONE},
-};
-
-static struct msm_pm_platform_data msm_pm_data[MSM_PM_SLEEP_MODE_NR * 2] = {
- [MSM_PM_MODE(0, MSM_PM_SLEEP_MODE_POWER_COLLAPSE)] = {
- .idle_supported = 1,
- .suspend_supported = 1,
- .idle_enabled = 0,
- .suspend_enabled = 0,
- },
-
- [MSM_PM_MODE(0, MSM_PM_SLEEP_MODE_POWER_COLLAPSE_STANDALONE)] = {
- .idle_supported = 1,
- .suspend_supported = 1,
- .idle_enabled = 0,
- .suspend_enabled = 0,
- },
-
- [MSM_PM_MODE(0, MSM_PM_SLEEP_MODE_WAIT_FOR_INTERRUPT)] = {
- .idle_supported = 1,
- .suspend_supported = 1,
- .idle_enabled = 1,
- .suspend_enabled = 1,
- },
-
- [MSM_PM_MODE(1, MSM_PM_SLEEP_MODE_POWER_COLLAPSE)] = {
- .idle_supported = 0,
- .suspend_supported = 1,
- .idle_enabled = 0,
- .suspend_enabled = 0,
- },
-
- [MSM_PM_MODE(1, MSM_PM_SLEEP_MODE_POWER_COLLAPSE_STANDALONE)] = {
- .idle_supported = 1,
- .suspend_supported = 1,
- .idle_enabled = 0,
- .suspend_enabled = 0,
- },
-
- [MSM_PM_MODE(1, MSM_PM_SLEEP_MODE_WAIT_FOR_INTERRUPT)] = {
- .idle_supported = 1,
- .suspend_supported = 0,
- .idle_enabled = 1,
- .suspend_enabled = 0,
- },
-};
-
-static struct msm_rpmrs_level msm_rpmrs_levels[] __initdata = {
- {
- MSM_PM_SLEEP_MODE_WAIT_FOR_INTERRUPT,
- MSM_RPMRS_LIMITS(ON, ACTIVE, MAX, ACTIVE),
- true,
- 100, 8000, 100000, 1,
- },
-
- {
- MSM_PM_SLEEP_MODE_POWER_COLLAPSE_STANDALONE,
- MSM_RPMRS_LIMITS(ON, ACTIVE, MAX, ACTIVE),
- true,
- 2000, 6000, 60100000, 3000,
- },
-
- {
- MSM_PM_SLEEP_MODE_POWER_COLLAPSE,
- MSM_RPMRS_LIMITS(ON, GDHS, MAX, ACTIVE),
- false,
- 4200, 5000, 60350000, 3500,
- },
-
- {
- MSM_PM_SLEEP_MODE_POWER_COLLAPSE,
- MSM_RPMRS_LIMITS(ON, HSFS_OPEN, MAX, ACTIVE),
- false,
- 6300, 4500, 65350000, 4800,
- },
- {
- MSM_PM_SLEEP_MODE_POWER_COLLAPSE,
- MSM_RPMRS_LIMITS(ON, HSFS_OPEN, ACTIVE, RET_HIGH),
- false,
- 7000, 3500, 66600000, 5150,
- },
-
- {
- MSM_PM_SLEEP_MODE_POWER_COLLAPSE,
- MSM_RPMRS_LIMITS(OFF, GDHS, MAX, ACTIVE),
- false,
- 11700, 2500, 67850000, 5500,
- },
-
- {
- MSM_PM_SLEEP_MODE_POWER_COLLAPSE,
- MSM_RPMRS_LIMITS(OFF, HSFS_OPEN, MAX, ACTIVE),
- false,
- 13800, 2000, 71850000, 6800,
- },
-
- {
- MSM_PM_SLEEP_MODE_POWER_COLLAPSE,
- MSM_RPMRS_LIMITS(OFF, HSFS_OPEN, ACTIVE, RET_HIGH),
- false,
- 29700, 500, 75850000, 8800,
- },
-
- {
- MSM_PM_SLEEP_MODE_POWER_COLLAPSE,
- MSM_RPMRS_LIMITS(OFF, HSFS_OPEN, RET_HIGH, RET_LOW),
- false,
- 29700, 0, 76350000, 9800,
- },
-};
-
-#ifdef CONFIG_I2C
-#define I2C_SURF 1
-#define I2C_FFA (1 << 1)
-#define I2C_RUMI (1 << 2)
-#define I2C_SIM (1 << 3)
-#define I2C_FLUID (1 << 4)
-#define I2C_LIQUID (1 << 5)
-
-struct i2c_registry {
- u8 machs;
- int bus;
- struct i2c_board_info *info;
- int len;
-};
-
-#ifdef CONFIG_MSM_CAMERA
-static struct i2c_board_info msm_camera_boardinfo[] __initdata = {
-#ifdef CONFIG_IMX074
- {
- I2C_BOARD_INFO("imx074", 0x1A),
- },
-#endif
-#ifdef CONFIG_OV2720
- {
- I2C_BOARD_INFO("ov2720", 0x6C),
- },
-#endif
-#ifdef CONFIG_MSM_CAMERA_FLASH_SC628A
- {
- I2C_BOARD_INFO("sc628a", 0x6E),
- },
-#endif
-};
-#endif
-
-/* Sensors DSPS platform data */
-#ifdef CONFIG_MSM_DSPS
-#define DSPS_PIL_GENERIC_NAME "dsps"
-#endif /* CONFIG_MSM_DSPS */
-
-static void __init msm8960_init_dsps(void)
-{
-#ifdef CONFIG_MSM_DSPS
- struct msm_dsps_platform_data *pdata =
- msm_dsps_device.dev.platform_data;
- pdata->pil_name = DSPS_PIL_GENERIC_NAME;
- pdata->gpios = NULL;
- pdata->gpios_num = 0;
-
- platform_device_register(&msm_dsps_device);
-#endif /* CONFIG_MSM_DSPS */
-}
-
-static void __init msm8960_init_hsic(void)
-{
-#ifdef CONFIG_USB_EHCI_MSM_HSIC
- uint32_t version = socinfo_get_version();
-
- pr_info("%s: version:%d mtp:%d\n", __func__,
- SOCINFO_VERSION_MAJOR(version),
- machine_is_msm8960_mtp());
-
- if ((SOCINFO_VERSION_MAJOR(version) == 1) ||
- machine_is_msm8960_mtp() ||
- machine_is_msm8960_fluid())
- return;
-
- msm_gpiomux_install(msm8960_hsic_configs,
- ARRAY_SIZE(msm8960_hsic_configs));
-
- platform_device_register(&msm_device_hsic_host);
-#endif
-}
-
-
-#ifdef CONFIG_ISL9519_CHARGER
-static struct isl_platform_data isl_data __initdata = {
- .valid_n_gpio = 0, /* Not required when notify-by-pmic */
- .chg_detection_config = NULL, /* Not required when notify-by-pmic */
- .max_system_voltage = 4200,
- .min_system_voltage = 3200,
- .chgcurrent = 1000, /* 1900, */
- .term_current = 400, /* Need fine tuning */
- .input_current = 2048,
-};
-
-static struct i2c_board_info isl_charger_i2c_info[] __initdata = {
- {
- I2C_BOARD_INFO("isl9519q", 0x9),
- .irq = 0, /* Not required when notify-by-pmic */
- .platform_data = &isl_data,
- },
-};
-#endif /* CONFIG_ISL9519_CHARGER */
-
-static struct i2c_registry msm8960_i2c_devices[] __initdata = {
-#ifdef CONFIG_MSM_CAMERA
- {
- I2C_SURF | I2C_FFA | I2C_FLUID | I2C_LIQUID | I2C_RUMI,
- MSM_8960_GSBI4_QUP_I2C_BUS_ID,
- msm_camera_boardinfo,
- ARRAY_SIZE(msm_camera_boardinfo),
- },
-#endif
-#ifdef CONFIG_ISL9519_CHARGER
- {
- I2C_LIQUID,
- MSM_8960_GSBI10_QUP_I2C_BUS_ID,
- isl_charger_i2c_info,
- ARRAY_SIZE(isl_charger_i2c_info),
- },
-#endif /* CONFIG_ISL9519_CHARGER */
- {
- I2C_SURF | I2C_FFA | I2C_FLUID,
- MSM_8960_GSBI3_QUP_I2C_BUS_ID,
- cyttsp_info,
- ARRAY_SIZE(cyttsp_info),
- },
- {
- I2C_LIQUID,
- MSM_8960_GSBI3_QUP_I2C_BUS_ID,
- mxt_device_info,
- ARRAY_SIZE(mxt_device_info),
- },
- {
- I2C_LIQUID,
- MSM_8960_GSBI10_QUP_I2C_BUS_ID,
- msm_isa1200_board_info,
- ARRAY_SIZE(msm_isa1200_board_info),
- },
-};
-#endif /* CONFIG_I2C */
-
-static void __init register_i2c_devices(void)
-{
-#ifdef CONFIG_I2C
- u8 mach_mask = 0;
- int i;
-
- /* Build the matching 'supported_machs' bitmask */
- if (machine_is_msm8960_cdp())
- mach_mask = I2C_SURF;
- else if (machine_is_msm8960_rumi3())
- mach_mask = I2C_RUMI;
- else if (machine_is_msm8960_sim())
- mach_mask = I2C_SIM;
- else if (machine_is_msm8960_fluid())
- mach_mask = I2C_FLUID;
- else if (machine_is_msm8960_liquid())
- mach_mask = I2C_LIQUID;
- else if (machine_is_msm8960_mtp())
- mach_mask = I2C_FFA;
- else
- pr_err("unmatched machine ID in register_i2c_devices\n");
-
- /* Run the array and install devices as appropriate */
- for (i = 0; i < ARRAY_SIZE(msm8960_i2c_devices); ++i) {
- if (msm8960_i2c_devices[i].machs & mach_mask)
- i2c_register_board_info(msm8960_i2c_devices[i].bus,
- msm8960_i2c_devices[i].info,
- msm8960_i2c_devices[i].len);
- }
-#endif
-}
-
-static void __init msm8960_sim_init(void)
-{
- struct msm_watchdog_pdata *wdog_pdata = (struct msm_watchdog_pdata *)
- &msm8960_device_watchdog.dev.platform_data;
-
- wdog_pdata->bark_time = 15000;
- BUG_ON(msm_rpm_init(&msm_rpm_data));
- BUG_ON(msm_rpmrs_levels_init(msm_rpmrs_levels,
- ARRAY_SIZE(msm_rpmrs_levels)));
- regulator_suppress_info_printing();
- platform_device_register(&msm8960_device_rpm_regulator);
- msm_clock_init(&msm8960_clock_init_data);
- msm8960_device_ssbi_pm8921.dev.platform_data =
- &msm8960_ssbi_pm8921_pdata;
- pm8921_platform_data.num_regulators = msm_pm8921_regulator_pdata_len;
-
- /* Simulator supports a QWERTY keypad */
- pm8921_platform_data.keypad_pdata = &keypad_data_sim;
-
- msm8960_device_otg.dev.platform_data = &msm_otg_pdata;
- gpiomux_init();
- msm8960_i2c_init();
- msm_spm_init(msm_spm_data, ARRAY_SIZE(msm_spm_data));
- msm_spm_l2_init(msm_spm_l2_data);
- msm8960_init_buses();
- platform_add_devices(common_devices, ARRAY_SIZE(common_devices));
- pm8921_gpio_mpp_init();
- platform_add_devices(sim_devices, ARRAY_SIZE(sim_devices));
- acpuclk_init(&acpuclk_8960_soc_data);
-
- msm8960_device_qup_spi_gsbi1.dev.platform_data =
- &msm8960_qup_spi_gsbi1_pdata;
- spi_register_board_info(spi_board_info, ARRAY_SIZE(spi_board_info));
-
- msm8960_init_mmc();
- msm_fb_add_devices();
- slim_register_board_info(msm_slim_devices,
- ARRAY_SIZE(msm_slim_devices));
- msm_pm_set_platform_data(msm_pm_data, ARRAY_SIZE(msm_pm_data));
- msm_pm_set_rpm_wakeup_irq(RPM_APCC_CPU0_WAKE_UP_IRQ);
- msm_cpuidle_set_states(msm_cstates, ARRAY_SIZE(msm_cstates),
- msm_pm_data);
- BUG_ON(msm_pm_boot_init(MSM_PM_BOOT_CONFIG_TZ, NULL));
-}
-
-static void __init msm8960_rumi3_init(void)
-{
- BUG_ON(msm_rpm_init(&msm_rpm_data));
- BUG_ON(msm_rpmrs_levels_init(msm_rpmrs_levels,
- ARRAY_SIZE(msm_rpmrs_levels)));
- regulator_suppress_info_printing();
- platform_device_register(&msm8960_device_rpm_regulator);
- msm_clock_init(&msm8960_dummy_clock_init_data);
- gpiomux_init();
- msm8960_device_ssbi_pm8921.dev.platform_data =
- &msm8960_ssbi_pm8921_pdata;
- pm8921_platform_data.num_regulators = msm_pm8921_regulator_pdata_len;
- msm8960_device_qup_spi_gsbi1.dev.platform_data =
- &msm8960_qup_spi_gsbi1_pdata;
- spi_register_board_info(spi_board_info, ARRAY_SIZE(spi_board_info));
- msm8960_i2c_init();
- msm_spm_init(msm_spm_data, ARRAY_SIZE(msm_spm_data));
- msm_spm_l2_init(msm_spm_l2_data);
- platform_add_devices(common_devices, ARRAY_SIZE(common_devices));
- pm8921_gpio_mpp_init();
- platform_add_devices(rumi3_devices, ARRAY_SIZE(rumi3_devices));
- msm8960_init_mmc();
- register_i2c_devices();
- msm_fb_add_devices();
- slim_register_board_info(msm_slim_devices,
- ARRAY_SIZE(msm_slim_devices));
- msm_pm_set_platform_data(msm_pm_data, ARRAY_SIZE(msm_pm_data));
- msm_pm_set_rpm_wakeup_irq(RPM_APCC_CPU0_WAKE_UP_IRQ);
- msm_cpuidle_set_states(msm_cstates, ARRAY_SIZE(msm_cstates),
- msm_pm_data);
- BUG_ON(msm_pm_boot_init(MSM_PM_BOOT_CONFIG_TZ, NULL));
-}
-
-static void __init msm8960_cdp_init(void)
-{
- if (meminfo_init(SYS_MEMORY, SZ_256M) < 0)
- pr_err("meminfo_init() failed!\n");
-
- BUG_ON(msm_rpm_init(&msm_rpm_data));
- BUG_ON(msm_rpmrs_levels_init(msm_rpmrs_levels,
- ARRAY_SIZE(msm_rpmrs_levels)));
-
- pmic_reset_irq = PM8921_IRQ_BASE + PM8921_RESOUT_IRQ;
- regulator_suppress_info_printing();
- if (msm_xo_init())
- pr_err("Failed to initialize XO votes\n");
- platform_device_register(&msm8960_device_rpm_regulator);
- msm_clock_init(&msm8960_clock_init_data);
- if (machine_is_msm8960_liquid())
- msm_otg_pdata.mhl_enable = true;
- msm8960_device_otg.dev.platform_data = &msm_otg_pdata;
-#ifdef CONFIG_USB_EHCI_MSM_HSIC
- if (machine_is_msm8960_liquid()) {
- if (SOCINFO_VERSION_MAJOR(socinfo_get_version()) >= 2)
- msm_hsic_pdata.hub_reset = HSIC_HUB_RESET_GPIO;
- }
-#endif
- msm_device_hsic_host.dev.platform_data = &msm_hsic_pdata;
- gpiomux_init();
- if (machine_is_msm8960_liquid())
- pm8921_platform_data.keypad_pdata = &keypad_data_liquid;
- msm8960_device_qup_spi_gsbi1.dev.platform_data =
- &msm8960_qup_spi_gsbi1_pdata;
- spi_register_board_info(spi_board_info, ARRAY_SIZE(spi_board_info));
- msm8960_device_ssbi_pm8921.dev.platform_data =
- &msm8960_ssbi_pm8921_pdata;
- pm8921_platform_data.num_regulators = msm_pm8921_regulator_pdata_len;
- msm8960_i2c_init();
- msm8960_gfx_init();
- msm_spm_init(msm_spm_data, ARRAY_SIZE(msm_spm_data));
- msm_spm_l2_init(msm_spm_l2_data);
- msm8960_init_buses();
- platform_add_devices(msm_footswitch_devices,
- msm_num_footswitch_devices);
- if (machine_is_msm8960_liquid())
- platform_device_register(&msm8960_device_ext_3p3v_vreg);
- platform_add_devices(common_devices, ARRAY_SIZE(common_devices));
- pm8921_gpio_mpp_init();
- platform_add_devices(cdp_devices, ARRAY_SIZE(cdp_devices));
- msm8960_init_hsic();
- msm8960_init_cam();
- msm8960_init_mmc();
- acpuclk_init(&acpuclk_8960_soc_data);
- if (machine_is_msm8960_liquid())
- mxt_init_hw_liquid();
- register_i2c_devices();
- msm_fb_add_devices();
- slim_register_board_info(msm_slim_devices,
- ARRAY_SIZE(msm_slim_devices));
- msm8960_init_dsps();
- msm_pm_set_platform_data(msm_pm_data, ARRAY_SIZE(msm_pm_data));
- msm_pm_set_rpm_wakeup_irq(RPM_APCC_CPU0_WAKE_UP_IRQ);
- msm_cpuidle_set_states(msm_cstates, ARRAY_SIZE(msm_cstates),
- msm_pm_data);
- change_memory_power = &msm8960_change_memory_power;
- BUG_ON(msm_pm_boot_init(MSM_PM_BOOT_CONFIG_TZ, NULL));
-
- if (PLATFORM_IS_CHARM25())
- platform_add_devices(mdm_devices, ARRAY_SIZE(mdm_devices));
-}
-
-MACHINE_START(MSM8960_SIM, "QCT MSM8960 SIMULATOR")
- .map_io = msm8960_map_io,
- .reserve = msm8960_reserve,
- .init_irq = msm8960_init_irq,
- .timer = &msm_timer,
- .init_machine = msm8960_sim_init,
- .init_early = msm8960_allocate_memory_regions,
- .init_very_early = msm8960_early_memory,
-MACHINE_END
-
-MACHINE_START(MSM8960_RUMI3, "QCT MSM8960 RUMI3")
- .map_io = msm8960_map_io,
- .reserve = msm8960_reserve,
- .init_irq = msm8960_init_irq,
- .timer = &msm_timer,
- .init_machine = msm8960_rumi3_init,
- .init_early = msm8960_allocate_memory_regions,
- .init_very_early = msm8960_early_memory,
-MACHINE_END
-
-MACHINE_START(MSM8960_CDP, "QCT MSM8960 CDP")
- .map_io = msm8960_map_io,
- .reserve = msm8960_reserve,
- .init_irq = msm8960_init_irq,
- .timer = &msm_timer,
- .init_machine = msm8960_cdp_init,
- .init_early = msm8960_allocate_memory_regions,
- .init_very_early = msm8960_early_memory,
-MACHINE_END
-
-MACHINE_START(MSM8960_MTP, "QCT MSM8960 MTP")
- .map_io = msm8960_map_io,
- .reserve = msm8960_reserve,
- .init_irq = msm8960_init_irq,
- .timer = &msm_timer,
- .init_machine = msm8960_cdp_init,
- .init_early = msm8960_allocate_memory_regions,
- .init_very_early = msm8960_early_memory,
-MACHINE_END
-
-MACHINE_START(MSM8960_FLUID, "QCT MSM8960 FLUID")
- .map_io = msm8960_map_io,
- .reserve = msm8960_reserve,
- .init_irq = msm8960_init_irq,
- .timer = &msm_timer,
- .init_machine = msm8960_cdp_init,
- .init_early = msm8960_allocate_memory_regions,
- .init_very_early = msm8960_early_memory,
-MACHINE_END
-
-MACHINE_START(MSM8960_LIQUID, "QCT MSM8960 LIQUID")
- .map_io = msm8960_map_io,
- .reserve = msm8960_reserve,
- .init_irq = msm8960_init_irq,
- .timer = &msm_timer,
- .init_machine = msm8960_cdp_init,
- .init_early = msm8960_allocate_memory_regions,
- .init_very_early = msm8960_early_memory,
-MACHINE_END
-
-#ifdef CONFIG_ARCH_MSM8930
-MACHINE_START(MSM8930_CDP, "QCT MSM8930 CDP")
- .map_io = msm8930_map_io,
- .reserve = msm8960_reserve,
- .init_irq = msm8960_init_irq,
- .timer = &msm_timer,
- .init_machine = msm8960_cdp_init,
- .init_early = msm8960_allocate_memory_regions,
- .init_very_early = msm8960_early_memory,
-MACHINE_END
-
-MACHINE_START(MSM8930_MTP, "QCT MSM8930 MTP")
- .map_io = msm8930_map_io,
- .reserve = msm8960_reserve,
- .init_irq = msm8960_init_irq,
- .timer = &msm_timer,
- .init_machine = msm8960_cdp_init,
- .init_early = msm8960_allocate_memory_regions,
- .init_very_early = msm8960_early_memory,
-MACHINE_END
-
-MACHINE_START(MSM8930_FLUID, "QCT MSM8930 FLUID")
- .map_io = msm8930_map_io,
- .reserve = msm8960_reserve,
- .init_irq = msm8960_init_irq,
- .timer = &msm_timer,
- .init_machine = msm8960_cdp_init,
- .init_early = msm8960_allocate_memory_regions,
- .init_very_early = msm8960_early_memory,
-MACHINE_END
-#endif
diff --git a/arch/arm/mach-msm/board-msm8960.h b/arch/arm/mach-msm/board-msm8960.h
deleted file mode 100644
index 1cfcfdd..0000000
--- a/arch/arm/mach-msm/board-msm8960.h
+++ /dev/null
@@ -1,44 +0,0 @@
-/* Copyright (c) 2011, Code Aurora Forum. 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 and
- * only version 2 as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- */
-
-#ifndef __ARCH_ARM_MACH_MSM_BOARD_MSM8960_H
-#define __ARCH_ARM_MACH_MSM_BOARD_MSM8960_H
-
-#include <mach/irqs.h>
-#include <mach/rpm-regulator.h>
-#include <linux/mfd/pm8xxx/pm8921.h>
-
-/* Macros assume PMIC GPIOs and MPPs start at 1 */
-#define PM8921_GPIO_BASE NR_GPIO_IRQS
-#define PM8921_GPIO_PM_TO_SYS(pm_gpio) (pm_gpio - 1 + PM8921_GPIO_BASE)
-#define PM8921_MPP_BASE (PM8921_GPIO_BASE + PM8921_NR_GPIOS)
-#define PM8921_MPP_PM_TO_SYS(pm_gpio) (pm_gpio - 1 + PM8921_MPP_BASE)
-#define PM8921_IRQ_BASE (NR_MSM_IRQS + NR_GPIO_IRQS)
-
-extern struct pm8921_regulator_platform_data
- msm_pm8921_regulator_pdata[] __devinitdata;
-
-extern int msm_pm8921_regulator_pdata_len __devinitdata;
-
-#define GPIO_VREG_ID_EXT_5V 0
-#define GPIO_VREG_ID_EXT_L2 1
-#define GPIO_VREG_ID_EXT_3P3V 2
-
-extern struct gpio_regulator_platform_data
- msm_gpio_regulator_pdata[] __devinitdata;
-
-extern struct regulator_init_data msm_saw_regulator_pdata_s5;
-extern struct regulator_init_data msm_saw_regulator_pdata_s6;
-
-extern struct rpm_regulator_platform_data msm_rpm_regulator_pdata __devinitdata;
-
-#endif
diff --git a/arch/arm/mach-msm/board-msm8x60.c b/arch/arm/mach-msm/board-msm8x60.c
index c22d54c..3038ff0 100644
--- a/arch/arm/mach-msm/board-msm8x60.c
+++ b/arch/arm/mach-msm/board-msm8x60.c
@@ -144,6 +144,10 @@
#define DSPS_PIL_GENERIC_NAME "dsps"
#define DSPS_PIL_FLUID_NAME "dsps_fluid"
+#ifdef CONFIG_ION_MSM
+static struct platform_device ion_dev;
+#endif
+
enum {
GPIO_EXPANDER_IRQ_BASE = PM8901_IRQ_BASE + NR_PMIC8901_IRQS,
GPIO_EXPANDER_GPIO_BASE = PM8901_GPIO_BASE + PM8901_MPPS,
@@ -1523,7 +1527,7 @@
#endif
-
+
#ifdef CONFIG_MSM_VPE
static struct resource msm_vpe_resources[] = {
{
@@ -2618,7 +2622,7 @@
#define MSM_FB_EXT_BUFT_SIZE 0
#endif
-#ifdef CONFIG_FB_MSM_OVERLAY_WRITEBACK
+#ifdef CONFIG_FB_MSM_OVERLAY0_WRITEBACK
/* width x height x 3 bpp x 2 frame buffer */
#define MSM_FB_WRITEBACK_SIZE (1024 * 600 * 3 * 2)
#define MSM_FB_WRITEBACK_OFFSET \
@@ -2657,7 +2661,7 @@
#define MSM_SMI_SIZE 0x4000000
#define KERNEL_SMI_BASE (MSM_SMI_BASE)
-#define KERNEL_SMI_SIZE 0x300000
+#define KERNEL_SMI_SIZE 0x600000
#define USER_SMI_BASE (KERNEL_SMI_BASE + KERNEL_SMI_SIZE)
#define USER_SMI_SIZE (MSM_SMI_SIZE - KERNEL_SMI_SIZE)
@@ -5158,7 +5162,7 @@
};
#ifdef CONFIG_ION_MSM
-struct ion_platform_data ion_pdata = {
+static struct ion_platform_data ion_pdata = {
.nr = MSM_ION_HEAP_NUM,
.heaps = {
{
@@ -5197,7 +5201,7 @@
}
};
-struct platform_device ion_dev = {
+static struct platform_device ion_dev = {
.name = "ion-msm",
.id = 1,
.dev = { .platform_data = &ion_pdata },
@@ -5781,7 +5785,7 @@
static struct pm8xxx_pwrkey_platform_data pm8058_pwrkey_pdata = {
.pull_up = 1,
- .kpd_trigger_delay_us = 970,
+ .kpd_trigger_delay_us = 15625,
.wakeup = 1,
};
diff --git a/arch/arm/mach-msm/board-qrd7627a.c b/arch/arm/mach-msm/board-qrd7627a.c
index d192faf..91bb455 100644
--- a/arch/arm/mach-msm/board-qrd7627a.c
+++ b/arch/arm/mach-msm/board-qrd7627a.c
@@ -77,6 +77,7 @@
/* FM Platform power and shutdown routines */
#define FPGA_MSM_CNTRL_REG2 0x90008010
+#if defined(CONFIG_BT) && defined(CONFIG_MARIMBA_CORE)
static void config_pcm_i2s_mode(int mode)
{
void __iomem *cfg_ptr;
@@ -401,6 +402,7 @@
.is_fm_soc_i2s_master = true,
.config_i2s_gpio = msm_bahama_setup_pcm_i2s,
};
+#endif
static struct platform_device msm_wlan_ar6000_pm_device = {
.name = "wlan_ar6000_pm_dev",
diff --git a/arch/arm/mach-msm/clock-7x30.c b/arch/arm/mach-msm/clock-7x30.c
index a478b6f..100689b 100644
--- a/arch/arm/mach-msm/clock-7x30.c
+++ b/arch/arm/mach-msm/clock-7x30.c
@@ -2316,7 +2316,7 @@
static DEFINE_CLK_PCOM(p_grp_2d_clk, GRP_2D_CLK, CLKFLAG_SKIP_AUTO_OFF);
static DEFINE_CLK_PCOM(p_grp_2d_p_clk, GRP_2D_P_CLK, CLKFLAG_SKIP_AUTO_OFF);
static DEFINE_CLK_PCOM(p_hdmi_clk, HDMI_CLK, CLKFLAG_SKIP_AUTO_OFF);
-static DEFINE_CLK_PCOM(p_jpeg_clk, JPEG_CLK, 0);
+static DEFINE_CLK_PCOM(p_jpeg_clk, JPEG_CLK, CLKFLAG_MIN);
static DEFINE_CLK_PCOM(p_jpeg_p_clk, JPEG_P_CLK, 0);
static DEFINE_CLK_PCOM(p_lpa_codec_clk, LPA_CODEC_CLK, CLKFLAG_SKIP_AUTO_OFF);
static DEFINE_CLK_PCOM(p_lpa_core_clk, LPA_CORE_CLK, CLKFLAG_SKIP_AUTO_OFF);
@@ -2386,7 +2386,7 @@
static DEFINE_CLK_PCOM(p_csi0_clk, CSI0_CLK, CLKFLAG_SKIP_AUTO_OFF);
static DEFINE_CLK_PCOM(p_csi0_vfe_clk, CSI0_VFE_CLK, CLKFLAG_SKIP_AUTO_OFF);
static DEFINE_CLK_PCOM(p_csi0_p_clk, CSI0_P_CLK, CLKFLAG_SKIP_AUTO_OFF);
-static DEFINE_CLK_PCOM(p_mdp_clk, MDP_CLK, 0);
+static DEFINE_CLK_PCOM(p_mdp_clk, MDP_CLK, CLKFLAG_MIN);
static DEFINE_CLK_PCOM(p_mfc_clk, MFC_CLK, CLKFLAG_SKIP_AUTO_OFF);
static DEFINE_CLK_PCOM(p_mfc_div2_clk, MFC_DIV2_CLK, CLKFLAG_SKIP_AUTO_OFF);
static DEFINE_CLK_PCOM(p_mfc_p_clk, MFC_P_CLK, CLKFLAG_SKIP_AUTO_OFF);
diff --git a/arch/arm/mach-msm/clock-8960.c b/arch/arm/mach-msm/clock-8960.c
index a4c8b2a2..3214be5 100644
--- a/arch/arm/mach-msm/clock-8960.c
+++ b/arch/arm/mach-msm/clock-8960.c
@@ -4480,22 +4480,8 @@
}, \
}
-#define F_AIF_BIT(d, s) \
- { \
- .freq_hz = d, \
- .ns_val = (BVAL(14, 14, s) | BVAL(13, 10, (d-1))) \
- }
-static struct clk_freq_tbl clk_tbl_aif_bit[] = {
- F_AIF_BIT(0, 1), /* Use external clock. */
- F_AIF_BIT(1, 0), F_AIF_BIT(2, 0), F_AIF_BIT(3, 0), F_AIF_BIT(4, 0),
- F_AIF_BIT(5, 0), F_AIF_BIT(6, 0), F_AIF_BIT(7, 0), F_AIF_BIT(8, 0),
- F_AIF_BIT(9, 0), F_AIF_BIT(10, 0), F_AIF_BIT(11, 0), F_AIF_BIT(12, 0),
- F_AIF_BIT(13, 0), F_AIF_BIT(14, 0), F_AIF_BIT(15, 0), F_AIF_BIT(16, 0),
- F_END
-};
-
#define CLK_AIF_BIT(i, ns, h_r) \
- struct rcg_clk i##_clk = { \
+ struct cdiv_clk i##_clk = { \
.b = { \
.ctl_reg = ns, \
.en_mask = BIT(15), \
@@ -4503,35 +4489,18 @@
.halt_check = DELAY, \
}, \
.ns_reg = ns, \
- .ns_mask = BM(14, 10), \
- .set_rate = set_rate_nop, \
- .freq_tbl = clk_tbl_aif_bit, \
- .current_freq = &rcg_dummy_freq, \
+ .ext_mask = BIT(14), \
+ .div_offset = 10, \
+ .max_div = 16, \
.c = { \
.dbg_name = #i "_clk", \
- .ops = &clk_ops_rcg_8960, \
+ .ops = &clk_ops_cdiv, \
CLK_INIT(i##_clk.c), \
}, \
}
-#define F_AIF_BIT_D(d, s) \
- { \
- .freq_hz = d, \
- .ns_val = (BVAL(18, 18, s) | BVAL(17, 10, (d-1))) \
- }
-static struct clk_freq_tbl clk_tbl_aif_bit_div[] = {
- F_AIF_BIT_D(0, 1), /* Use external clock. */
- F_AIF_BIT_D(1, 0), F_AIF_BIT_D(2, 0), F_AIF_BIT_D(3, 0),
- F_AIF_BIT_D(4, 0), F_AIF_BIT_D(5, 0), F_AIF_BIT_D(6, 0),
- F_AIF_BIT_D(7, 0), F_AIF_BIT_D(8, 0), F_AIF_BIT_D(9, 0),
- F_AIF_BIT_D(10, 0), F_AIF_BIT_D(11, 0), F_AIF_BIT_D(12, 0),
- F_AIF_BIT_D(13, 0), F_AIF_BIT_D(14, 0), F_AIF_BIT_D(15, 0),
- F_AIF_BIT_D(16, 0),
- F_END
-};
-
#define CLK_AIF_BIT_DIV(i, ns, h_r) \
- struct rcg_clk i##_clk = { \
+ struct cdiv_clk i##_clk = { \
.b = { \
.ctl_reg = ns, \
.en_mask = BIT(19), \
@@ -4539,13 +4508,12 @@
.halt_check = ENABLE, \
}, \
.ns_reg = ns, \
- .ns_mask = BM(18, 10), \
- .set_rate = set_rate_nop, \
- .freq_tbl = clk_tbl_aif_bit_div, \
- .current_freq = &rcg_dummy_freq, \
+ .ext_mask = BIT(18), \
+ .div_offset = 10, \
+ .max_div = 256, \
.c = { \
.dbg_name = #i "_clk", \
- .ops = &clk_ops_rcg_8960, \
+ .ops = &clk_ops_cdiv, \
CLK_INIT(i##_clk.c), \
}, \
}
@@ -5144,7 +5112,7 @@
CLK_LOOKUP("core_clk", gsbi7_qup_clk.c, NULL),
CLK_LOOKUP("core_clk", pdm_clk.c, NULL),
CLK_LOOKUP("pmem_clk", pmem_clk.c, NULL),
- CLK_DUMMY("core_clk", PRNG_CLK, NULL, OFF),
+ CLK_DUMMY("core_clk", PRNG_CLK, "msm_rng.0", OFF),
CLK_LOOKUP("core_clk", sdc1_clk.c, "msm_sdcc.1"),
CLK_LOOKUP("core_clk", sdc2_clk.c, "msm_sdcc.2"),
CLK_LOOKUP("core_clk", sdc3_clk.c, "msm_sdcc.3"),
@@ -5224,7 +5192,7 @@
CLK_LOOKUP("dsi_esc_clk", dsi2_esc_clk.c, NULL),
CLK_DUMMY("rgb_tv_clk", RGB_TV_CLK, NULL, OFF),
CLK_DUMMY("npl_tv_clk", NPL_TV_CLK, NULL, OFF),
- CLK_LOOKUP("core_clk", gfx3d_clk.c, NULL),
+ CLK_LOOKUP("core_clk", gfx3d_clk.c, "kgsl-3d0.0"),
CLK_LOOKUP("core_clk", gfx3d_clk.c, "footswitch-8x60.2"),
CLK_LOOKUP("bus_clk", gfx3d_axi_clk.c, "footswitch-8x60.2"),
CLK_LOOKUP("iface_clk", vcap_p_clk.c, NULL),
@@ -5268,7 +5236,7 @@
CLK_LOOKUP("dsi_s_pclk", dsi1_s_p_clk.c, NULL),
CLK_LOOKUP("dsi_m_pclk", dsi2_m_p_clk.c, NULL),
CLK_LOOKUP("dsi_s_pclk", dsi2_s_p_clk.c, NULL),
- CLK_LOOKUP("iface_clk", gfx3d_p_clk.c, NULL),
+ CLK_LOOKUP("iface_clk", gfx3d_p_clk.c, "kgsl-3d0.0"),
CLK_LOOKUP("iface_clk", gfx3d_p_clk.c, "footswitch-8x60.2"),
CLK_LOOKUP("master_iface_clk", hdmi_m_p_clk.c, NULL),
CLK_LOOKUP("slave_iface_clk", hdmi_s_p_clk.c, NULL),
diff --git a/arch/arm/mach-msm/clock-8x60.c b/arch/arm/mach-msm/clock-8x60.c
index 17052ae..662e9a6 100644
--- a/arch/arm/mach-msm/clock-8x60.c
+++ b/arch/arm/mach-msm/clock-8x60.c
@@ -3106,22 +3106,8 @@
}, \
}
-#define F_AIF_BIT(d, s) \
- { \
- .freq_hz = d, \
- .ns_val = (BVAL(14, 14, s) | BVAL(13, 10, (d-1))) \
- }
-static struct clk_freq_tbl clk_tbl_aif_bit[] = {
- F_AIF_BIT(0, 1), /* Use external clock. */
- F_AIF_BIT(1, 0), F_AIF_BIT(2, 0), F_AIF_BIT(3, 0), F_AIF_BIT(4, 0),
- F_AIF_BIT(5, 0), F_AIF_BIT(6, 0), F_AIF_BIT(7, 0), F_AIF_BIT(8, 0),
- F_AIF_BIT(9, 0), F_AIF_BIT(10, 0), F_AIF_BIT(11, 0), F_AIF_BIT(12, 0),
- F_AIF_BIT(13, 0), F_AIF_BIT(14, 0), F_AIF_BIT(15, 0), F_AIF_BIT(16, 0),
- F_END
-};
-
#define CLK_AIF_BIT(i, ns, h_r) \
- struct rcg_clk i##_clk = { \
+ struct cdiv_clk i##_clk = { \
.b = { \
.ctl_reg = ns, \
.en_mask = BIT(15), \
@@ -3129,13 +3115,12 @@
.halt_check = DELAY, \
}, \
.ns_reg = ns, \
- .ns_mask = BM(14, 10), \
- .set_rate = set_rate_nop, \
- .freq_tbl = clk_tbl_aif_bit, \
- .current_freq = &rcg_dummy_freq, \
+ .ext_mask = BIT(14), \
+ .div_offset = 10, \
+ .max_div = 16, \
.c = { \
.dbg_name = #i "_clk", \
- .ops = &clk_ops_rcg_8x60, \
+ .ops = &clk_ops_cdiv, \
CLK_INIT(i##_clk.c), \
}, \
}
diff --git a/arch/arm/mach-msm/clock-9615.c b/arch/arm/mach-msm/clock-9615.c
index c8212a3..e47981e 100644
--- a/arch/arm/mach-msm/clock-9615.c
+++ b/arch/arm/mach-msm/clock-9615.c
@@ -1211,22 +1211,8 @@
}, \
}
-#define F_AIF_BIT(d, s) \
- { \
- .freq_hz = d, \
- .ns_val = (BVAL(14, 14, s) | BVAL(13, 10, (d-1))) \
- }
-static struct clk_freq_tbl clk_tbl_aif_bit[] = {
- F_AIF_BIT(0, 1), /* Use external clock. */
- F_AIF_BIT(1, 0), F_AIF_BIT(2, 0), F_AIF_BIT(3, 0), F_AIF_BIT(4, 0),
- F_AIF_BIT(5, 0), F_AIF_BIT(6, 0), F_AIF_BIT(7, 0), F_AIF_BIT(8, 0),
- F_AIF_BIT(9, 0), F_AIF_BIT(10, 0), F_AIF_BIT(11, 0), F_AIF_BIT(12, 0),
- F_AIF_BIT(13, 0), F_AIF_BIT(14, 0), F_AIF_BIT(15, 0), F_AIF_BIT(16, 0),
- F_END
-};
-
#define CLK_AIF_BIT(i, ns, h_r) \
- struct rcg_clk i##_clk = { \
+ struct cdiv_clk i##_clk = { \
.b = { \
.ctl_reg = ns, \
.en_mask = BIT(15), \
@@ -1234,35 +1220,18 @@
.halt_check = DELAY, \
}, \
.ns_reg = ns, \
- .ns_mask = BM(14, 10), \
- .set_rate = set_rate_nop, \
- .freq_tbl = clk_tbl_aif_bit, \
- .current_freq = &rcg_dummy_freq, \
+ .ext_mask = BIT(14), \
+ .div_offset = 10, \
+ .max_div = 16, \
.c = { \
.dbg_name = #i "_clk", \
- .ops = &clk_ops_rcg_9615, \
+ .ops = &clk_ops_cdiv, \
CLK_INIT(i##_clk.c), \
}, \
}
-#define F_AIF_BIT_D(d, s) \
- { \
- .freq_hz = d, \
- .ns_val = (BVAL(18, 18, s) | BVAL(17, 10, (d-1))) \
- }
-static struct clk_freq_tbl clk_tbl_aif_bit_div[] = {
- F_AIF_BIT_D(0, 1), /* Use external clock. */
- F_AIF_BIT_D(1, 0), F_AIF_BIT_D(2, 0), F_AIF_BIT_D(3, 0),
- F_AIF_BIT_D(4, 0), F_AIF_BIT_D(5, 0), F_AIF_BIT_D(6, 0),
- F_AIF_BIT_D(7, 0), F_AIF_BIT_D(8, 0), F_AIF_BIT_D(9, 0),
- F_AIF_BIT_D(10, 0), F_AIF_BIT_D(11, 0), F_AIF_BIT_D(12, 0),
- F_AIF_BIT_D(13, 0), F_AIF_BIT_D(14, 0), F_AIF_BIT_D(15, 0),
- F_AIF_BIT_D(16, 0),
- F_END
-};
-
#define CLK_AIF_BIT_DIV(i, ns, h_r) \
- struct rcg_clk i##_clk = { \
+ struct cdiv_clk i##_clk = { \
.b = { \
.ctl_reg = ns, \
.en_mask = BIT(19), \
@@ -1270,13 +1239,12 @@
.halt_check = ENABLE, \
}, \
.ns_reg = ns, \
- .ns_mask = BM(18, 10), \
- .set_rate = set_rate_nop, \
- .freq_tbl = clk_tbl_aif_bit_div, \
- .current_freq = &rcg_dummy_freq, \
+ .ext_mask = BIT(18), \
+ .div_offset = 10, \
+ .max_div = 256, \
.c = { \
.dbg_name = #i "_clk", \
- .ops = &clk_ops_rcg_9615, \
+ .ops = &clk_ops_cdiv, \
CLK_INIT(i##_clk.c), \
}, \
}
@@ -1679,14 +1647,10 @@
CLK_LOOKUP("core_clk", gp1_clk.c, NULL),
CLK_LOOKUP("core_clk", gp2_clk.c, NULL),
- CLK_LOOKUP("core_clk", gsbi1_uart_clk.c, NULL),
- CLK_LOOKUP("core_clk", gsbi2_uart_clk.c, NULL),
CLK_LOOKUP("core_clk", gsbi3_uart_clk.c, NULL),
CLK_LOOKUP("core_clk", gsbi4_uart_clk.c, "msm_serial_hsl.0"),
CLK_LOOKUP("core_clk", gsbi5_uart_clk.c, NULL),
- CLK_LOOKUP("core_clk", gsbi1_qup_clk.c, NULL),
- CLK_LOOKUP("core_clk", gsbi2_qup_clk.c, NULL),
CLK_LOOKUP("core_clk", gsbi3_qup_clk.c, "spi_qsd.0"),
CLK_LOOKUP("core_clk", gsbi4_qup_clk.c, NULL),
CLK_LOOKUP("core_clk", gsbi5_qup_clk.c, "qup_i2c.0"),
@@ -1700,8 +1664,6 @@
CLK_LOOKUP("core_clk", ce1_core_clk.c, NULL),
CLK_LOOKUP("dma_bam_pclk", dma_bam_p_clk.c, NULL),
- CLK_LOOKUP("iface_clk", gsbi1_p_clk.c, NULL),
- CLK_LOOKUP("iface_clk", gsbi2_p_clk.c, NULL),
CLK_LOOKUP("iface_clk", gsbi3_p_clk.c, "spi_qsd.0"),
CLK_LOOKUP("iface_clk", gsbi4_p_clk.c, "msm_serial_hsl.0"),
CLK_LOOKUP("iface_clk", gsbi5_p_clk.c, "qup_i2c.0"),
diff --git a/arch/arm/mach-msm/clock-pcom-lookup.c b/arch/arm/mach-msm/clock-pcom-lookup.c
index d1a257d..dd31bd7 100644
--- a/arch/arm/mach-msm/clock-pcom-lookup.c
+++ b/arch/arm/mach-msm/clock-pcom-lookup.c
@@ -87,7 +87,7 @@
static DEFINE_CLK_PCOM(icodec_tx_clk, ICODEC_TX_CLK, CLKFLAG_SKIP_AUTO_OFF);
static DEFINE_CLK_PCOM(imem_clk, IMEM_CLK, 0);
static DEFINE_CLK_PCOM(mdc_clk, MDC_CLK, CLKFLAG_SKIP_AUTO_OFF);
-static DEFINE_CLK_PCOM(mdp_clk, MDP_CLK, 0);
+static DEFINE_CLK_PCOM(mdp_clk, MDP_CLK, CLKFLAG_MIN);
static DEFINE_CLK_PCOM(mdp_lcdc_pad_pclk_clk, MDP_LCDC_PAD_PCLK_CLK,
CLKFLAG_SKIP_AUTO_OFF);
static DEFINE_CLK_PCOM(mdp_lcdc_pclk_clk, MDP_LCDC_PCLK_CLK,
diff --git a/arch/arm/mach-msm/devices-8064.c b/arch/arm/mach-msm/devices-8064.c
index afc2649..7420bc0 100644
--- a/arch/arm/mach-msm/devices-8064.c
+++ b/arch/arm/mach-msm/devices-8064.c
@@ -581,6 +581,23 @@
.id = -1,
};
+#ifdef CONFIG_HW_RANDOM_MSM
+/* PRNG device */
+#define MSM_PRNG_PHYS 0x1A500000
+static struct resource rng_resources = {
+ .flags = IORESOURCE_MEM,
+ .start = MSM_PRNG_PHYS,
+ .end = MSM_PRNG_PHYS + SZ_512 - 1,
+};
+
+struct platform_device apq8064_device_rng = {
+ .name = "msm_rng",
+ .id = 0,
+ .num_resources = 1,
+ .resource = &rng_resources,
+};
+#endif
+
static struct clk_lookup msm_clocks_8064_dummy[] = {
CLK_DUMMY("pll2", PLL2, NULL, 0),
CLK_DUMMY("pll8", PLL8, NULL, 0),
@@ -625,7 +642,7 @@
CLK_DUMMY("core_clk", GSBI7_QUP_CLK, NULL, OFF),
CLK_DUMMY("core_clk", PDM_CLK, NULL, OFF),
CLK_DUMMY("mem_clk", PMEM_CLK, NULL, OFF),
- CLK_DUMMY("core_clk", PRNG_CLK, NULL, OFF),
+ CLK_DUMMY("core_clk", PRNG_CLK, "msm_rng.0", OFF),
CLK_DUMMY("core_clk", SDC1_CLK, NULL, OFF),
CLK_DUMMY("core_clk", SDC2_CLK, NULL, OFF),
CLK_DUMMY("core_clk", SDC3_CLK, NULL, OFF),
@@ -688,7 +705,7 @@
CLK_DUMMY("dsi_esc_clk", DSI2_ESC_CLK, NULL, OFF),
CLK_DUMMY("core_clk", VCAP_CLK, NULL, OFF),
CLK_DUMMY("npl_clk", VCAP_NPL_CLK, NULL, OFF),
- CLK_DUMMY("core_clk", GFX3D_CLK, NULL, OFF),
+ CLK_DUMMY("core_clk", GFX3D_CLK, "kgsl-3d0.0", OFF),
CLK_DUMMY("ijpeg_clk", IJPEG_CLK, NULL, OFF),
CLK_DUMMY("mem_clk", IMEM_CLK, NULL, OFF),
CLK_DUMMY("core_clk", JPEGD_CLK, NULL, OFF),
@@ -727,7 +744,7 @@
CLK_DUMMY("mdp_p2clk", MDP_P2CLK, NULL, OFF),
CLK_DUMMY("dsi2_pixel_clk", DSI2_PIXEL_CLK, NULL, OFF),
CLK_DUMMY("lvds_ref_clk", LVDS_REF_CLK, NULL, OFF),
- CLK_DUMMY("iface_clk", GFX3D_P_CLK, NULL, OFF),
+ CLK_DUMMY("iface_clk", GFX3D_P_CLK, "kgsl-3d0.0", OFF),
CLK_DUMMY("master_iface_clk", HDMI_M_P_CLK, "hdmi_msm.1", OFF),
CLK_DUMMY("slave_iface_clk", HDMI_S_P_CLK, "hdmi_msm.1", OFF),
CLK_DUMMY("ijpeg_pclk", IJPEG_P_CLK, NULL, OFF),
diff --git a/arch/arm/mach-msm/devices-8960.c b/arch/arm/mach-msm/devices-8960.c
index 2add8f9..e814b4e 100644
--- a/arch/arm/mach-msm/devices-8960.c
+++ b/arch/arm/mach-msm/devices-8960.c
@@ -30,6 +30,7 @@
#include <mach/rpm.h>
#include <mach/msm_bus_board.h>
#include <mach/msm_memtypes.h>
+#include <mach/msm_xo.h>
#include <sound/msm-dai-q6.h>
#include <sound/apr_audio.h>
#include "clock.h"
@@ -38,6 +39,8 @@
#include "footswitch.h"
#include "msm_watchdog.h"
#include "rpm_stats.h"
+#include "pil-q6v4.h"
+#include "scm-pas.h"
#ifdef CONFIG_MSM_MPM
#include "mpm.h"
@@ -815,6 +818,113 @@
},
};
+#define MSM_LPASS_QDSP6SS_PHYS 0x28800000
+#define SFAB_LPASS_Q6_ACLK_CTL (MSM_CLK_CTL_BASE + 0x23A0)
+
+static struct resource msm_8960_q6_lpass_resources[] = {
+ {
+ .start = MSM_LPASS_QDSP6SS_PHYS,
+ .end = MSM_LPASS_QDSP6SS_PHYS + SZ_256 - 1,
+ .flags = IORESOURCE_MEM,
+ },
+};
+
+static struct pil_q6v4_pdata msm_8960_q6_lpass_data = {
+ .strap_tcm_base = 0x01460000,
+ .strap_ahb_upper = 0x00290000,
+ .strap_ahb_lower = 0x00000280,
+ .aclk_reg = SFAB_LPASS_Q6_ACLK_CTL,
+ .xo_id = MSM_XO_PXO,
+ .name = "q6",
+ .pas_id = PAS_Q6,
+ .bus_port = MSM_BUS_MASTER_LPASS_PROC,
+};
+
+struct platform_device msm_8960_q6_lpass = {
+ .name = "pil_qdsp6v4",
+ .id = 0,
+ .num_resources = ARRAY_SIZE(msm_8960_q6_lpass_resources),
+ .resource = msm_8960_q6_lpass_resources,
+ .dev.platform_data = &msm_8960_q6_lpass_data,
+};
+
+#define MSM_MSS_ENABLE_PHYS 0x08B00000
+#define MSM_FW_QDSP6SS_PHYS 0x08800000
+#define MSS_Q6FW_JTAG_CLK_CTL (MSM_CLK_CTL_BASE + 0x2C6C)
+#define SFAB_MSS_Q6_FW_ACLK_CTL (MSM_CLK_CTL_BASE + 0x2044)
+
+static struct resource msm_8960_q6_mss_fw_resources[] = {
+ {
+ .start = MSM_FW_QDSP6SS_PHYS,
+ .end = MSM_FW_QDSP6SS_PHYS + SZ_256 - 1,
+ .flags = IORESOURCE_MEM,
+ },
+ {
+ .start = MSM_MSS_ENABLE_PHYS,
+ .end = MSM_MSS_ENABLE_PHYS + 4 - 1,
+ .flags = IORESOURCE_MEM,
+ },
+};
+
+static struct pil_q6v4_pdata msm_8960_q6_mss_fw_data = {
+ .strap_tcm_base = 0x00400000,
+ .strap_ahb_upper = 0x00090000,
+ .strap_ahb_lower = 0x00000080,
+ .aclk_reg = SFAB_MSS_Q6_FW_ACLK_CTL,
+ .jtag_clk_reg = MSS_Q6FW_JTAG_CLK_CTL,
+ .xo_id = MSM_XO_TCXO_D0,
+ .name = "modem_fw",
+ .depends = "q6",
+ .pas_id = PAS_MODEM_FW,
+ .bus_port = MSM_BUS_MASTER_MSS_FW_PROC,
+};
+
+struct platform_device msm_8960_q6_mss_fw = {
+ .name = "pil_qdsp6v4",
+ .id = 1,
+ .num_resources = ARRAY_SIZE(msm_8960_q6_mss_fw_resources),
+ .resource = msm_8960_q6_mss_fw_resources,
+ .dev.platform_data = &msm_8960_q6_mss_fw_data,
+};
+
+#define MSM_SW_QDSP6SS_PHYS 0x08900000
+#define SFAB_MSS_Q6_SW_ACLK_CTL (MSM_CLK_CTL_BASE + 0x2040)
+#define MSS_Q6SW_JTAG_CLK_CTL (MSM_CLK_CTL_BASE + 0x2C68)
+
+static struct resource msm_8960_q6_mss_sw_resources[] = {
+ {
+ .start = MSM_SW_QDSP6SS_PHYS,
+ .end = MSM_SW_QDSP6SS_PHYS + SZ_256 - 1,
+ .flags = IORESOURCE_MEM,
+ },
+ {
+ .start = MSM_MSS_ENABLE_PHYS,
+ .end = MSM_MSS_ENABLE_PHYS + 4 - 1,
+ .flags = IORESOURCE_MEM,
+ },
+};
+
+static struct pil_q6v4_pdata msm_8960_q6_mss_sw_data = {
+ .strap_tcm_base = 0x00420000,
+ .strap_ahb_upper = 0x00090000,
+ .strap_ahb_lower = 0x00000080,
+ .aclk_reg = SFAB_MSS_Q6_SW_ACLK_CTL,
+ .jtag_clk_reg = MSS_Q6SW_JTAG_CLK_CTL,
+ .xo_id = MSM_XO_TCXO_D0,
+ .name = "modem",
+ .depends = "modem_fw",
+ .pas_id = PAS_MODEM_SW,
+ .bus_port = MSM_BUS_MASTER_MSS_SW_PROC,
+};
+
+struct platform_device msm_8960_q6_mss_sw = {
+ .name = "pil_qdsp6v4",
+ .id = 2,
+ .num_resources = ARRAY_SIZE(msm_8960_q6_mss_sw_resources),
+ .resource = msm_8960_q6_mss_sw_resources,
+ .dev.platform_data = &msm_8960_q6_mss_sw_data,
+};
+
struct platform_device msm_device_smd = {
.name = "msm_smd",
.id = -1,
@@ -1217,18 +1327,6 @@
.flags = IORESOURCE_IO,
},
{
- .name = "spi_cs",
- .start = 8,
- .end = 8,
- .flags = IORESOURCE_IO,
- },
- {
- .name = "spi_cs1",
- .start = 14,
- .end = 14,
- .flags = IORESOURCE_IO,
- },
- {
.name = "spi_miso",
.start = 7,
.end = 7,
@@ -1240,6 +1338,18 @@
.end = 6,
.flags = IORESOURCE_IO,
},
+ {
+ .name = "spi_cs",
+ .start = 8,
+ .end = 8,
+ .flags = IORESOURCE_IO,
+ },
+ {
+ .name = "spi_cs1",
+ .start = 14,
+ .end = 14,
+ .flags = IORESOURCE_IO,
+ },
};
struct platform_device msm8960_device_qup_spi_gsbi1 = {
diff --git a/arch/arm/mach-msm/devices-msm8x60.c b/arch/arm/mach-msm/devices-msm8x60.c
index d89c9d7..b9ff604 100644
--- a/arch/arm/mach-msm/devices-msm8x60.c
+++ b/arch/arm/mach-msm/devices-msm8x60.c
@@ -949,12 +949,6 @@
.flags = IORESOURCE_IO,
},
{
- .name = "spi_cs",
- .start = 35,
- .end = 35,
- .flags = IORESOURCE_IO,
- },
- {
.name = "spi_miso",
.start = 34,
.end = 34,
@@ -966,6 +960,12 @@
.end = 33,
.flags = IORESOURCE_IO,
},
+ {
+ .name = "spi_cs",
+ .start = 35,
+ .end = 35,
+ .flags = IORESOURCE_IO,
+ },
};
/* Use GSBI1 QUP for SPI-0 */
diff --git a/arch/arm/mach-msm/devices.h b/arch/arm/mach-msm/devices.h
index a95d0b6..147f01d 100644
--- a/arch/arm/mach-msm/devices.h
+++ b/arch/arm/mach-msm/devices.h
@@ -172,6 +172,10 @@
extern struct platform_device msm_cpudai_afe_02_tx;
extern struct platform_device msm_pcm_afe;
+extern struct platform_device msm_8960_q6_lpass;
+extern struct platform_device msm_8960_q6_mss_fw;
+extern struct platform_device msm_8960_q6_mss_sw;
+
extern struct platform_device *msm_footswitch_devices[];
extern unsigned msm_num_footswitch_devices;
@@ -199,10 +203,10 @@
extern struct platform_device led_pdev;
-extern struct platform_device ion_dev;
extern struct platform_device msm_rpm_device;
extern struct platform_device msm_rpm_stat_device;
extern struct platform_device msm_device_rng;
+extern struct platform_device apq8064_device_rng;
#if defined(CONFIG_CRYPTO_DEV_QCRYPTO) || \
defined(CONFIG_CRYPTO_DEV_QCRYPTO_MODULE)
diff --git a/arch/arm/mach-msm/footswitch-8x60.c b/arch/arm/mach-msm/footswitch-8x60.c
index 98447fa..a8e2449 100644
--- a/arch/arm/mach-msm/footswitch-8x60.c
+++ b/arch/arm/mach-msm/footswitch-8x60.c
@@ -256,6 +256,14 @@
udelay(RESET_DELAY_US);
/*
+ * Return clocks to their state before this function. For robustness
+ * if memory-retention across collapses is required, clocks should
+ * be disabled before asserting the clamps. Assuming clocks were off
+ * before entering footswitch_disable(), this will be true.
+ */
+ restore_clocks(fs);
+
+ /*
* Clamp the I/O ports of the core to ensure the values
* remain fixed while the core is collapsed.
*/
@@ -266,9 +274,6 @@
regval &= ~ENABLE_BIT;
writel_relaxed(regval, fs->gfs_ctl_reg);
- /* Return clocks to their state before this function. */
- restore_clocks(fs);
-
fs->is_enabled = false;
return rc;
diff --git a/arch/arm/mach-msm/include/mach/bam_dmux.h b/arch/arm/mach-msm/include/mach/bam_dmux.h
index a2b0126..fb70da4 100644
--- a/arch/arm/mach-msm/include/mach/bam_dmux.h
+++ b/arch/arm/mach-msm/include/mach/bam_dmux.h
@@ -59,6 +59,10 @@
int msm_bam_dmux_write(uint32_t id, struct sk_buff *skb);
void msm_bam_dmux_kickoff_ul_wakeup(void);
+
+int msm_bam_dmux_is_ch_full(uint32_t id);
+
+int msm_bam_dmux_is_ch_low(uint32_t id);
#else
int msm_bam_dmux_open(uint32_t id, void *priv,
void (*notify)(void *priv, int event_type,
@@ -80,5 +84,15 @@
void msm_bam_dmux_kickoff_ul_wakeup(void)
{
}
+
+int msm_bam_dmux_is_ch_full(uint32_t id)
+{
+ return -ENODEV;
+}
+
+int msm_bam_dmux_is_ch_low(uint32_t id)
+{
+ return -ENODEV;
+}
#endif
#endif /* _BAM_DMUX_H */
diff --git a/arch/arm/mach-msm/include/mach/camera.h b/arch/arm/mach-msm/include/mach/camera.h
index 1745f26..b41398e 100644
--- a/arch/arm/mach-msm/include/mach/camera.h
+++ b/arch/arm/mach-msm/include/mach/camera.h
@@ -635,7 +635,6 @@
void msm_camio_clk_rate_set(int rate);
int msm_camio_vfe_clk_rate_set(int rate);
void msm_camio_clk_rate_set_2(struct clk *clk, int rate);
-void msm_camio_clk_set_min_rate(struct clk *clk, int rate);
void msm_camio_clk_axi_rate_set(int rate);
void msm_disable_io_gpio_clk(struct platform_device *);
diff --git a/arch/arm/mach-msm/include/mach/irqs-copper.h b/arch/arm/mach-msm/include/mach/irqs-copper.h
index d019047..24da0a4 100644
--- a/arch/arm/mach-msm/include/mach/irqs-copper.h
+++ b/arch/arm/mach-msm/include/mach/irqs-copper.h
@@ -24,9 +24,6 @@
#define GIC_PPI_START 16
#define GIC_SPI_START 32
-#define INT_VGIC (GIC_PPI_START + 0)
-#define INT_DEBUG_TIMER_EXP (GIC_PPI_START + 1)
-#define INT_GP_TIMER_EXP (GIC_PPI_START + 2)
#define AVS_SVICINT (GIC_PPI_START + 6)
#define AVS_SVICINTSWDONE (GIC_PPI_START + 7)
#define INT_ARMQC_PERFMON (GIC_PPI_START + 10)
diff --git a/arch/arm/mach-msm/include/mach/memory.h b/arch/arm/mach-msm/include/mach/memory.h
index f208d88..9cd73db 100644
--- a/arch/arm/mach-msm/include/mach/memory.h
+++ b/arch/arm/mach-msm/include/mach/memory.h
@@ -21,7 +21,7 @@
#define PLAT_PHYS_OFFSET UL(CONFIG_PHYS_OFFSET)
#define MAX_PHYSMEM_BITS 32
-#define SECTION_SIZE_BITS 29
+#define SECTION_SIZE_BITS 28
/* Maximum number of Memory Regions */
#define MAX_NR_REGIONS 4
@@ -58,8 +58,6 @@
#endif
-#define HAS_ARCH_IO_REMAP_PFN_RANGE
-
#ifndef __ASSEMBLY__
void *alloc_bootmem_aligned(unsigned long size, unsigned long alignment);
void *allocate_contiguous_ebi(unsigned long, unsigned long, int);
diff --git a/arch/arm/mach-msm/include/mach/msm_iomap-copper.h b/arch/arm/mach-msm/include/mach/msm_iomap-copper.h
index 57758c3..a3c9da8 100644
--- a/arch/arm/mach-msm/include/mach/msm_iomap-copper.h
+++ b/arch/arm/mach-msm/include/mach/msm_iomap-copper.h
@@ -29,18 +29,12 @@
#define COPPER_QGIC_CPU_PHYS 0xF9002000
#define COPPER_QGIC_CPU_SIZE SZ_4K
-#define COPPER_TLMM_PHYS 0xFC4A0000
+#define COPPER_TLMM_PHYS 0xFD400000
#define COPPER_TLMM_SIZE SZ_16K
-#define COPPER_TMR_PHYS 0xF900A000
-#define COPPER_TMR_SIZE SZ_4K
-
-#define COPPER_TMR0_PHYS 0xF908A000
-#define COPPER_TMR0_SIZE SZ_4K
-
#ifdef CONFIG_DEBUG_MSMCOPPER_UART
-#define MSM_DEBUG_UART_BASE IOMEM(0xFA782000)
-#define MSM_DEBUG_UART_PHYS 0xF9682000
+#define MSM_DEBUG_UART_BASE IOMEM(0xFA71E000)
+#define MSM_DEBUG_UART_PHYS 0xF991E000
#endif
#endif
diff --git a/arch/arm/mach-msm/include/mach/msm_smsm.h b/arch/arm/mach-msm/include/mach/msm_smsm.h
index 0c2cd4b..6d45b7d 100644
--- a/arch/arm/mach-msm/include/mach/msm_smsm.h
+++ b/arch/arm/mach-msm/include/mach/msm_smsm.h
@@ -209,7 +209,13 @@
SMEM_SMEM_LOG_MPROC_WRAP,
SMEM_BOOT_INFO_FOR_APPS,
SMEM_SMSM_SIZE_INFO,
- SMEM_MEM_LAST = SMEM_SMSM_SIZE_INFO,
+ SMEM_SMD_LOOPBACK_REGISTER,
+ SMEM_SSR_REASON_MSS0,
+ SMEM_SSR_REASON_WCNSS0,
+ SMEM_SSR_REASON_LPASS0,
+ SMEM_SSR_REASON_DSPS0,
+ SMEM_SSR_REASON_VCODEC0,
+ SMEM_MEM_LAST = SMEM_SSR_REASON_VCODEC0,
SMEM_NUM_ITEMS,
};
diff --git a/arch/arm/mach-msm/include/mach/qdsp6v2/q6voice.h b/arch/arm/mach-msm/include/mach/qdsp6v2/q6voice.h
index 1f8ce68..674cfe8 100644
--- a/arch/arm/mach-msm/include/mach/qdsp6v2/q6voice.h
+++ b/arch/arm/mach-msm/include/mach/qdsp6v2/q6voice.h
@@ -521,6 +521,8 @@
#define VSS_NETWORK_ID_VOIP_WV 0x00011242
/* Media types */
+#define VSS_MEDIA_ID_13K_MODEM 0x00010FC1
+/* Qcelp vocoder modem format */
#define VSS_MEDIA_ID_EVRC_MODEM 0x00010FC2
/* 80-VF690-47 CDMA enhanced variable rate vocoder modem format. */
#define VSS_MEDIA_ID_4GV_NB_MODEM 0x00010FC3
@@ -531,6 +533,12 @@
/* 80-VF690-47 UMTS AMR-NB vocoder modem format. */
#define VSS_MEDIA_ID_AMR_WB_MODEM 0x00010FC7
/* 80-VF690-47 UMTS AMR-WB vocoder modem format. */
+#define VSS_MEDIA_ID_EFR_MODEM 0x00010FC8
+/*EFR modem format */
+#define VSS_MEDIA_ID_FR_MODEM 0x00010FC9
+/*FR modem format */
+#define VSS_MEDIA_ID_HR_MODEM 0x00010FCA
+/*HR modem format */
#define VSS_MEDIA_ID_PCM_NB 0x00010FCB
/* Linear PCM (16-bit, little-endian). */
#define VSS_MEDIA_ID_PCM_WB 0x00010FCC
diff --git a/arch/arm/mach-msm/include/mach/sdio_tty.h b/arch/arm/mach-msm/include/mach/sdio_tty.h
deleted file mode 100644
index 86746b3..0000000
--- a/arch/arm/mach-msm/include/mach/sdio_tty.h
+++ /dev/null
@@ -1,48 +0,0 @@
-/* Copyright (c) 2011, Code Aurora Forum. 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 and
- * only version 2 as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- */
-
-/*
- * SDIO TTY interface.
- */
-
-#ifndef __SDIO_TTY__
-#define __SDIO_TTY__
-
-/**
- * sdio_tty_init_tty - Initialize the SDIO TTY driver.
- *
- * @tty_name: tty name - identify the tty device.
- * @sdio_ch_name: channel name - identify the channel.
- * @return sdio_tty handle on success, NULL on error.
- *
- */
-void *sdio_tty_init_tty(char *tty_name, char* sdio_ch_name);
-
-/**
- * sdio_tty_uninit_tty - Uninitialize the SDIO TTY driver.
- *
- * @sdio_tty_handle: sdio_tty handle.
- * @return 0 on success, negative value on error.
- */
-int sdio_tty_uninit_tty(void *sdio_tty_handle);
-
-/**
- * sdio_tty_enable_debug_msg - Enable/Disable sdio_tty debug
- * messages.
- *
- * @enable: A flag to indicate if to enable or disable the debug
- * messages.
- * @return 0 on success, negative value on error.
- */
-void sdio_tty_enable_debug_msg(void *sdio_tty_handle, int enable);
-
-#endif /* __SDIO_TTY__ */
diff --git a/arch/arm/mach-msm/include/mach/socinfo.h b/arch/arm/mach-msm/include/mach/socinfo.h
index fba6efe2..a06b9ae 100644
--- a/arch/arm/mach-msm/include/mach/socinfo.h
+++ b/arch/arm/mach-msm/include/mach/socinfo.h
@@ -61,6 +61,7 @@
MSM_CPU_7X27AA,
MSM_CPU_9615,
MSM_CPU_COPPER,
+ MSM_CPU_8627,
};
enum msm_cpu socinfo_get_msm_cpu(void);
@@ -225,7 +226,18 @@
static inline int cpu_is_msm8930(void)
{
#ifdef CONFIG_ARCH_MSM8930
- return read_msm_cpu_type() == MSM_CPU_8930;
+ return (read_msm_cpu_type() == MSM_CPU_8930) ||
+ (read_msm_cpu_type() == MSM_CPU_8627);
+#else
+ return 0;
+#endif
+}
+
+static inline int cpu_is_msm8627(void)
+{
+/* 8930 and 8627 will share the same CONFIG_ARCH type unless otherwise needed */
+#ifdef CONFIG_ARCH_MSM8930
+ return read_msm_cpu_type() == MSM_CPU_8627;
#else
return 0;
#endif
diff --git a/arch/arm/mach-msm/io.c b/arch/arm/mach-msm/io.c
index f09c6d9..2d5b0a4 100644
--- a/arch/arm/mach-msm/io.c
+++ b/arch/arm/mach-msm/io.c
@@ -284,8 +284,6 @@
MSM_CHIP_DEVICE(QGIC_DIST, COPPER),
MSM_CHIP_DEVICE(QGIC_CPU, COPPER),
MSM_CHIP_DEVICE(TLMM, COPPER),
- MSM_CHIP_DEVICE(TMR, COPPER),
- MSM_CHIP_DEVICE(TMR0, COPPER),
#ifdef CONFIG_DEBUG_MSMCOPPER_UART
MSM_DEVICE(DEBUG_UART),
#endif
diff --git a/arch/arm/mach-msm/ipc_router.c b/arch/arm/mach-msm/ipc_router.c
index 3d34a30..8e9cc0f 100644
--- a/arch/arm/mach-msm/ipc_router.c
+++ b/arch/arm/mach-msm/ipc_router.c
@@ -1938,7 +1938,6 @@
}
mutex_unlock(&port_ptr->port_rx_q_lock);
- wake_lock_destroy(&port_ptr->port_rx_wake_lock);
if (port_ptr->type == SERVER_PORT) {
server = msm_ipc_router_lookup_server(
port_ptr->port_name.service,
@@ -1962,6 +1961,7 @@
mutex_unlock(&control_ports_lock);
}
+ wake_lock_destroy(&port_ptr->port_rx_wake_lock);
kfree(port_ptr);
return 0;
}
diff --git a/arch/arm/mach-msm/memory.c b/arch/arm/mach-msm/memory.c
index 00f315d..31fbd43 100644
--- a/arch/arm/mach-msm/memory.c
+++ b/arch/arm/mach-msm/memory.c
@@ -38,17 +38,6 @@
#include <mach/socinfo.h>
#include <../../mm/mm.h>
-int arch_io_remap_pfn_range(struct vm_area_struct *vma, unsigned long addr,
- unsigned long pfn, unsigned long size, pgprot_t prot)
-{
- unsigned long pfn_addr = pfn << PAGE_SHIFT;
- if ((pfn_addr >= 0x88000000) && (pfn_addr < 0xD0000000)) {
- prot = pgprot_device(prot);
- pr_debug("remapping device %lx\n", prot);
- }
- return remap_pfn_range(vma, addr, pfn, size, prot);
-}
-
void *strongly_ordered_page;
char strongly_ordered_mem[PAGE_SIZE*2-4];
diff --git a/arch/arm/mach-msm/modem-8960.c b/arch/arm/mach-msm/modem-8960.c
index f0aa13c..7345a89 100644
--- a/arch/arm/mach-msm/modem-8960.c
+++ b/arch/arm/mach-msm/modem-8960.c
@@ -149,9 +149,58 @@
smsm_reset_modem(SMSM_RESET);
}
-int modem_ramdump(int enable, const struct subsys_data *subsys)
+/* FIXME: Get address, size from PIL */
+static struct ramdump_segment modemsw_segments[] = {
+ {0x89000000, 0x8D400000 - 0x89000000},
+};
+
+static struct ramdump_segment modemfw_segments[] = {
+ {0x8D400000, 0x8DA00000 - 0x8D400000},
+};
+
+static struct ramdump_segment smem_segments[] = {
+ {0x80000000, 0x00200000},
+};
+
+static void *modemfw_ramdump_dev;
+static void *modemsw_ramdump_dev;
+static void *smem_ramdump_dev;
+
+static int modem_ramdump(int enable,
+ const struct subsys_data *crashed_subsys)
{
- return 0;
+ int ret = 0;
+
+ if (enable) {
+ ret = do_ramdump(modemsw_ramdump_dev, modemsw_segments,
+ ARRAY_SIZE(modemsw_segments));
+
+ if (ret < 0) {
+ pr_err("Unable to dump modem sw memory (rc = %d).\n",
+ ret);
+ goto out;
+ }
+
+ ret = do_ramdump(modemfw_ramdump_dev, modemfw_segments,
+ ARRAY_SIZE(modemfw_segments));
+
+ if (ret < 0) {
+ pr_err("Unable to dump modem fw memory (rc = %d).\n",
+ ret);
+ goto out;
+ }
+
+ ret = do_ramdump(smem_ramdump_dev, smem_segments,
+ ARRAY_SIZE(smem_segments));
+
+ if (ret < 0) {
+ pr_err("Unable to dump smem memory (rc = %d).\n", ret);
+ goto out;
+ }
+ }
+
+out:
+ return ret;
}
static irqreturn_t modem_wdog_bite_irq(int irq, void *dev_id)
@@ -263,6 +312,33 @@
goto out;
}
+ modemfw_ramdump_dev = create_ramdump_device("modem_fw");
+
+ if (!modemfw_ramdump_dev) {
+ pr_err("%s: Unable to create modem fw ramdump device. (%d)\n",
+ __func__, -ENOMEM);
+ ret = -ENOMEM;
+ goto out;
+ }
+
+ modemsw_ramdump_dev = create_ramdump_device("modem_sw");
+
+ if (!modemsw_ramdump_dev) {
+ pr_err("%s: Unable to create modem sw ramdump device. (%d)\n",
+ __func__, -ENOMEM);
+ ret = -ENOMEM;
+ goto out;
+ }
+
+ smem_ramdump_dev = create_ramdump_device("smem");
+
+ if (!smem_ramdump_dev) {
+ pr_err("%s: Unable to create smem ramdump device. (%d)\n",
+ __func__, -ENOMEM);
+ ret = -ENOMEM;
+ goto out;
+ }
+
ret = modem_debugfs_init();
pr_info("%s: modem fatal driver init'ed.\n", __func__);
diff --git a/arch/arm/mach-msm/msm_rq_stats.c b/arch/arm/mach-msm/msm_rq_stats.c
index 9daaaba..da7fb51 100644
--- a/arch/arm/mach-msm/msm_rq_stats.c
+++ b/arch/arm/mach-msm/msm_rq_stats.c
@@ -198,6 +198,8 @@
static int __init msm_rq_stats_init(void)
{
+ int ret;
+
rq_wq = create_singlethread_workqueue("rq_stats");
BUG_ON(!rq_wq);
INIT_WORK(&rq_info.def_timer_work, def_work_fn);
@@ -206,7 +208,9 @@
rq_info.def_timer_jiffies = DEFAULT_DEF_TIMER_JIFFIES;
rq_info.rq_poll_last_jiffy = 0;
rq_info.def_timer_last_jiffy = 0;
+ ret = init_rq_attribs();
+
rq_info.init = 1;
- return init_rq_attribs();
+ return ret;
}
late_initcall(msm_rq_stats_init);
diff --git a/arch/arm/mach-msm/msm_xo.c b/arch/arm/mach-msm/msm_xo.c
index 1e9c05f..29cb1a8 100644
--- a/arch/arm/mach-msm/msm_xo.c
+++ b/arch/arm/mach-msm/msm_xo.c
@@ -223,9 +223,10 @@
/*
* TODO: Remove early return for 8064 once RPM XO voting support
- * is available.
+ * is available. Remove early return for 8960 TCXO_D0 once all
+ * voters for it are in place.
*/
- if (cpu_is_apq8064())
+ if (cpu_is_apq8064() || (cpu_is_msm8960() && xo_id == MSM_XO_TCXO_D0))
return NULL;
if (xo_id >= NUM_MSM_XO_IDS) {
diff --git a/arch/arm/mach-msm/peripheral-reset-8960.c b/arch/arm/mach-msm/peripheral-reset-8960.c
index b964417..fa22e4e 100644
--- a/arch/arm/mach-msm/peripheral-reset-8960.c
+++ b/arch/arm/mach-msm/peripheral-reset-8960.c
@@ -28,49 +28,6 @@
#include "peripheral-loader.h"
#include "scm-pas.h"
-#define MSM_FW_QDSP6SS_PHYS 0x08800000
-#define MSM_SW_QDSP6SS_PHYS 0x08900000
-#define MSM_LPASS_QDSP6SS_PHYS 0x28800000
-#define MSM_MSS_ENABLE_PHYS 0x08B00000
-
-#define QDSP6SS_RST_EVB 0x0
-#define QDSP6SS_RESET 0x04
-#define QDSP6SS_CGC_OVERRIDE 0x18
-#define QDSP6SS_STRAP_TCM 0x1C
-#define QDSP6SS_STRAP_AHB 0x20
-#define QDSP6SS_GFMUX_CTL 0x30
-#define QDSP6SS_PWR_CTL 0x38
-
-#define MSS_S_HCLK_CTL (MSM_CLK_CTL_BASE + 0x2C70)
-#define MSS_SLP_CLK_CTL (MSM_CLK_CTL_BASE + 0x2C60)
-#define SFAB_MSS_M_ACLK_CTL (MSM_CLK_CTL_BASE + 0x2340)
-#define SFAB_MSS_S_HCLK_CTL (MSM_CLK_CTL_BASE + 0x2C00)
-#define SFAB_MSS_Q6_FW_ACLK_CTL (MSM_CLK_CTL_BASE + 0x2044)
-#define SFAB_MSS_Q6_SW_ACLK_CTL (MSM_CLK_CTL_BASE + 0x2040)
-#define SFAB_LPASS_Q6_ACLK_CTL (MSM_CLK_CTL_BASE + 0x23A0)
-#define MSS_Q6FW_JTAG_CLK_CTL (MSM_CLK_CTL_BASE + 0x2C6C)
-#define MSS_Q6SW_JTAG_CLK_CTL (MSM_CLK_CTL_BASE + 0x2C68)
-#define MSS_RESET (MSM_CLK_CTL_BASE + 0x2C64)
-
-#define Q6SS_SS_ARES BIT(0)
-#define Q6SS_CORE_ARES BIT(1)
-#define Q6SS_ISDB_ARES BIT(2)
-#define Q6SS_ETM_ARES BIT(3)
-#define Q6SS_STOP_CORE_ARES BIT(4)
-#define Q6SS_PRIV_ARES BIT(5)
-
-#define Q6SS_L2DATA_SLP_NRET_N BIT(0)
-#define Q6SS_SLP_RET_N BIT(1)
-#define Q6SS_L1TCM_SLP_NRET_N BIT(2)
-#define Q6SS_L2TAG_SLP_NRET_N BIT(3)
-#define Q6SS_ETB_SLEEP_NRET_N BIT(4)
-#define Q6SS_ARR_STBY_N BIT(5)
-#define Q6SS_CLAMP_IO BIT(6)
-
-#define Q6SS_CLK_ENA BIT(1)
-#define Q6SS_SRC_SWITCH_CLK_OVR BIT(8)
-#define Q6SS_AXIS_ACLK_EN BIT(9)
-
#define MSM_RIVA_PHYS 0x03204000
#define RIVA_PMU_A2XB_CFG (msm_riva_base + 0xB8)
#define RIVA_PMU_A2XB_CFG_EN BIT(0)
@@ -121,339 +78,14 @@
#define PPSS_PROC_CLK_CTL (MSM_CLK_CTL_BASE + 0x2588)
#define PPSS_HCLK_CTL (MSM_CLK_CTL_BASE + 0x2580)
-struct q6_data {
- const unsigned strap_tcm_base;
- const unsigned strap_ahb_upper;
- const unsigned strap_ahb_lower;
- const unsigned reg_base_phys;
- void __iomem *reg_base;
- void __iomem *aclk_reg;
- void __iomem *jtag_clk_reg;
- int start_addr;
- struct regulator *vreg;
- bool vreg_enabled;
- const char *name;
-};
-
-static struct q6_data q6_lpass = {
- .strap_tcm_base = (0x146 << 16),
- .strap_ahb_upper = (0x029 << 16),
- .strap_ahb_lower = (0x028 << 4),
- .reg_base_phys = MSM_LPASS_QDSP6SS_PHYS,
- .aclk_reg = SFAB_LPASS_Q6_ACLK_CTL,
- .name = "q6_lpass",
-};
-
-static struct q6_data q6_modem_fw = {
- .strap_tcm_base = (0x40 << 16),
- .strap_ahb_upper = (0x09 << 16),
- .strap_ahb_lower = (0x08 << 4),
- .reg_base_phys = MSM_FW_QDSP6SS_PHYS,
- .aclk_reg = SFAB_MSS_Q6_FW_ACLK_CTL,
- .jtag_clk_reg = MSS_Q6FW_JTAG_CLK_CTL,
- .name = "q6_modem_fw",
-};
-
-static struct q6_data q6_modem_sw = {
- .strap_tcm_base = (0x42 << 16),
- .strap_ahb_upper = (0x09 << 16),
- .strap_ahb_lower = (0x08 << 4),
- .reg_base_phys = MSM_SW_QDSP6SS_PHYS,
- .aclk_reg = SFAB_MSS_Q6_SW_ACLK_CTL,
- .jtag_clk_reg = MSS_Q6SW_JTAG_CLK_CTL,
- .name = "q6_modem_sw",
-};
-
-static void __iomem *mss_enable_reg;
static void __iomem *msm_riva_base;
static unsigned long riva_start;
-static int init_image_lpass_q6_trusted(struct pil_desc *pil,
- const u8 *metadata, size_t size)
-{
- return pas_init_image(PAS_Q6, metadata, size);
-}
-
-static int init_image_modem_fw_q6_trusted(struct pil_desc *pil,
- const u8 *metadata, size_t size)
-{
- return pas_init_image(PAS_MODEM_FW, metadata, size);
-}
-
-static int init_image_modem_sw_q6_trusted(struct pil_desc *pil,
- const u8 *metadata, size_t size)
-{
- return pas_init_image(PAS_MODEM_SW, metadata, size);
-}
-
-static int init_image_lpass_q6_untrusted(struct pil_desc *pil,
- const u8 *metadata, size_t size)
-{
- const struct elf32_hdr *ehdr = (struct elf32_hdr *)metadata;
- q6_lpass.start_addr = ehdr->e_entry;
- return 0;
-}
-
-static int init_image_modem_fw_q6_untrusted(struct pil_desc *pil,
- const u8 *metadata, size_t size)
-{
- const struct elf32_hdr *ehdr = (struct elf32_hdr *)metadata;
- q6_modem_fw.start_addr = ehdr->e_entry;
- return 0;
-}
-
-static int init_image_modem_sw_q6_untrusted(struct pil_desc *pil,
- const u8 *metadata, size_t size)
-{
- const struct elf32_hdr *ehdr = (struct elf32_hdr *)metadata;
- q6_modem_sw.start_addr = ehdr->e_entry;
- return 0;
-}
-
static int verify_blob(struct pil_desc *pil, u32 phy_addr, size_t size)
{
return 0;
}
-static int power_up_q6(struct q6_data *q6)
-{
- int err;
-
- err = regulator_set_voltage(q6->vreg, 1050000, 1050000);
- if (err) {
- pr_err("Failed to set %s regulator's voltage.\n", q6->name);
- return err;
- }
- err = regulator_set_optimum_mode(q6->vreg, 100000);
- if (err < 0) {
- pr_err("Failed to set %s regulator's mode.\n", q6->name);
- return err;
- }
- err = regulator_enable(q6->vreg);
- if (err) {
- pr_err("Failed to enable %s's regulator.\n", q6->name);
- return err;
- }
- q6->vreg_enabled = true;
- return 0;
-}
-
-static int reset_q6_trusted(int id, struct q6_data *q6)
-{
- int err = power_up_q6(q6);
- if (err)
- return err;
- return pas_auth_and_reset(id);
-}
-
-static int reset_lpass_q6_trusted(struct pil_desc *pil)
-{
- return reset_q6_trusted(PAS_Q6, &q6_lpass);
-}
-
-static int reset_modem_fw_q6_trusted(struct pil_desc *pil)
-{
- return reset_q6_trusted(PAS_MODEM_FW, &q6_modem_fw);
-}
-
-static int reset_modem_sw_q6_trusted(struct pil_desc *pil)
-{
- return reset_q6_trusted(PAS_MODEM_SW, &q6_modem_sw);
-}
-
-static int reset_q6_untrusted(struct q6_data *q6)
-{
- u32 reg, err = 0;
-
- err = power_up_q6(q6);
- if (err)
- return err;
- /* Enable Q6 ACLK */
- writel_relaxed(0x10, q6->aclk_reg);
-
- if (q6 == &q6_modem_fw || q6 == &q6_modem_sw) {
- /* Enable MSS clocks */
- writel_relaxed(0x10, SFAB_MSS_M_ACLK_CTL);
- writel_relaxed(0x10, SFAB_MSS_S_HCLK_CTL);
- writel_relaxed(0x10, MSS_S_HCLK_CTL);
- writel_relaxed(0x10, MSS_SLP_CLK_CTL);
- /* Wait for clocks to enable */
- mb();
- udelay(10);
-
- /* Enable JTAG clocks */
- /* TODO: Remove if/when Q6 software enables them? */
- writel_relaxed(0x10, q6->jtag_clk_reg);
-
- /* De-assert MSS reset */
- writel_relaxed(0x0, MSS_RESET);
- mb();
- udelay(10);
-
- /* Enable MSS */
- writel_relaxed(0x7, mss_enable_reg);
- }
-
- /*
- * Assert AXIS_ACLK_EN override to allow for correct updating of the
- * QDSP6_CORE_STATE status bit. This is mandatory only for the SW Q6
- * in 8960v1 and optional elsewhere.
- */
- reg = readl_relaxed(q6->reg_base + QDSP6SS_CGC_OVERRIDE);
- reg |= Q6SS_AXIS_ACLK_EN;
- writel_relaxed(reg, q6->reg_base + QDSP6SS_CGC_OVERRIDE);
-
- /* Deassert Q6SS_SS_ARES */
- reg = readl_relaxed(q6->reg_base + QDSP6SS_RESET);
- reg &= ~(Q6SS_SS_ARES);
- writel_relaxed(reg, q6->reg_base + QDSP6SS_RESET);
-
- /* Program boot address */
- writel_relaxed((q6->start_addr >> 8) & 0xFFFFFF,
- q6->reg_base + QDSP6SS_RST_EVB);
-
- /* Program TCM and AHB address ranges */
- writel_relaxed(q6->strap_tcm_base, q6->reg_base + QDSP6SS_STRAP_TCM);
- writel_relaxed(q6->strap_ahb_upper | q6->strap_ahb_lower,
- q6->reg_base + QDSP6SS_STRAP_AHB);
-
- /* Turn off Q6 core clock */
- writel_relaxed(Q6SS_SRC_SWITCH_CLK_OVR,
- q6->reg_base + QDSP6SS_GFMUX_CTL);
-
- /* Put memories to sleep */
- writel_relaxed(Q6SS_CLAMP_IO, q6->reg_base + QDSP6SS_PWR_CTL);
-
- /* Assert resets */
- reg = readl_relaxed(q6->reg_base + QDSP6SS_RESET);
- reg |= (Q6SS_CORE_ARES | Q6SS_ISDB_ARES | Q6SS_ETM_ARES
- | Q6SS_STOP_CORE_ARES);
- writel_relaxed(reg, q6->reg_base + QDSP6SS_RESET);
-
- /* Wait 8 AHB cycles for Q6 to be fully reset (AHB = 1.5Mhz) */
- mb();
- usleep_range(20, 30);
-
- /* Turn on Q6 memories */
- reg = Q6SS_L2DATA_SLP_NRET_N | Q6SS_SLP_RET_N | Q6SS_L1TCM_SLP_NRET_N
- | Q6SS_L2TAG_SLP_NRET_N | Q6SS_ETB_SLEEP_NRET_N | Q6SS_ARR_STBY_N
- | Q6SS_CLAMP_IO;
- writel_relaxed(reg, q6->reg_base + QDSP6SS_PWR_CTL);
-
- /* Turn on Q6 core clock */
- reg = Q6SS_CLK_ENA | Q6SS_SRC_SWITCH_CLK_OVR;
- writel_relaxed(reg, q6->reg_base + QDSP6SS_GFMUX_CTL);
-
- /* Remove Q6SS_CLAMP_IO */
- reg = readl_relaxed(q6->reg_base + QDSP6SS_PWR_CTL);
- reg &= ~Q6SS_CLAMP_IO;
- writel_relaxed(reg, q6->reg_base + QDSP6SS_PWR_CTL);
-
- /* Bring Q6 core out of reset and start execution. */
- writel_relaxed(0x0, q6->reg_base + QDSP6SS_RESET);
-
- /*
- * Re-enable auto-gating of AXIS_ACLK at lease one AXI clock cycle
- * after resets are de-asserted.
- */
- mb();
- usleep_range(1, 10);
- reg = readl_relaxed(q6->reg_base + QDSP6SS_CGC_OVERRIDE);
- reg &= ~Q6SS_AXIS_ACLK_EN;
- writel_relaxed(reg, q6->reg_base + QDSP6SS_CGC_OVERRIDE);
-
- return 0;
-}
-
-static int reset_lpass_q6_untrusted(struct pil_desc *pil)
-{
- return reset_q6_untrusted(&q6_lpass);
-}
-
-static int reset_modem_fw_q6_untrusted(struct pil_desc *pil)
-{
- return reset_q6_untrusted(&q6_modem_fw);
-}
-
-static int reset_modem_sw_q6_untrusted(struct pil_desc *pil)
-{
- return reset_q6_untrusted(&q6_modem_sw);
-}
-
-static int shutdown_q6_trusted(int id, struct q6_data *q6)
-{
- int ret;
-
- ret = pas_shutdown(id);
- if (ret)
- return ret;
-
- if (q6->vreg_enabled) {
- regulator_disable(q6->vreg);
- q6->vreg_enabled = false;
- }
-
- return ret;
-}
-
-static int shutdown_lpass_q6_trusted(struct pil_desc *pil)
-{
- return shutdown_q6_trusted(PAS_Q6, &q6_lpass);
-}
-
-static int shutdown_modem_fw_q6_trusted(struct pil_desc *pil)
-{
- return shutdown_q6_trusted(PAS_MODEM_FW, &q6_modem_fw);
-}
-
-static int shutdown_modem_sw_q6_trusted(struct pil_desc *pil)
-{
- return shutdown_q6_trusted(PAS_MODEM_SW, &q6_modem_sw);
-}
-
-static int shutdown_q6_untrusted(struct q6_data *q6)
-{
- u32 reg;
-
- /* Turn off Q6 core clock */
- writel_relaxed(Q6SS_SRC_SWITCH_CLK_OVR,
- q6->reg_base + QDSP6SS_GFMUX_CTL);
-
- /* Assert resets */
- reg = (Q6SS_SS_ARES | Q6SS_CORE_ARES | Q6SS_ISDB_ARES
- | Q6SS_ETM_ARES | Q6SS_STOP_CORE_ARES | Q6SS_PRIV_ARES);
- writel_relaxed(reg, q6->reg_base + QDSP6SS_RESET);
-
- /* Turn off Q6 memories */
- writel_relaxed(Q6SS_CLAMP_IO, q6->reg_base + QDSP6SS_PWR_CTL);
-
- /* Put Modem Subsystem back into reset when shutting down FWQ6 */
- if (q6 == &q6_modem_fw)
- writel_relaxed(0x1, MSS_RESET);
-
- if (q6->vreg_enabled) {
- regulator_disable(q6->vreg);
- q6->vreg_enabled = false;
- }
-
- return 0;
-}
-
-static int shutdown_lpass_q6_untrusted(struct pil_desc *pil)
-{
- return shutdown_q6_untrusted(&q6_lpass);
-}
-
-static int shutdown_modem_fw_q6_untrusted(struct pil_desc *pil)
-{
- return shutdown_q6_untrusted(&q6_modem_fw);
-}
-
-static int shutdown_modem_sw_q6_untrusted(struct pil_desc *pil)
-{
- return shutdown_q6_untrusted(&q6_modem_sw);
-}
-
static int init_image_riva_untrusted(struct pil_desc *pil, const u8 *metadata,
size_t size)
{
@@ -468,49 +100,55 @@
bool xo;
/* Enable A2XB bridge */
- reg = readl(RIVA_PMU_A2XB_CFG);
+ reg = readl_relaxed(RIVA_PMU_A2XB_CFG);
reg |= RIVA_PMU_A2XB_CFG_EN;
- writel(reg, RIVA_PMU_A2XB_CFG);
+ writel_relaxed(reg, RIVA_PMU_A2XB_CFG);
/* Determine which XO to use */
- reg = readl(RIVA_PMU_CFG);
+ reg = readl_relaxed(RIVA_PMU_CFG);
xo = (reg & RIVA_PMU_CFG_IRIS_XO_MODE) == RIVA_PMU_CFG_IRIS_XO_MODE_48;
/* Program PLL 13 to 960 MHz */
- reg = readl(RIVA_PLL_MODE);
+ reg = readl_relaxed(RIVA_PLL_MODE);
reg &= ~(PLL_MODE_BYPASSNL | PLL_MODE_OUTCTRL | PLL_MODE_RESET_N);
- writel(reg, RIVA_PLL_MODE);
+ writel_relaxed(reg, RIVA_PLL_MODE);
if (xo)
- writel(0x40000C00 | 40, RIVA_PLL_L_VAL);
+ writel_relaxed(0x40000C00 | 40, RIVA_PLL_L_VAL);
else
- writel(0x40000C00 | 50, RIVA_PLL_L_VAL);
- writel(0, RIVA_PLL_M_VAL);
- writel(1, RIVA_PLL_N_VAL);
+ writel_relaxed(0x40000C00 | 50, RIVA_PLL_L_VAL);
+ writel_relaxed(0, RIVA_PLL_M_VAL);
+ writel_relaxed(1, RIVA_PLL_N_VAL);
writel_relaxed(0x01495227, RIVA_PLL_CONFIG);
- reg = readl(RIVA_PLL_MODE);
+ reg = readl_relaxed(RIVA_PLL_MODE);
reg &= ~(PLL_MODE_REF_XO_SEL);
reg |= xo ? PLL_MODE_REF_XO_SEL_RF : PLL_MODE_REF_XO_SEL_CXO;
- writel(reg, RIVA_PLL_MODE);
+ writel_relaxed(reg, RIVA_PLL_MODE);
/* Enable PLL 13 */
reg |= PLL_MODE_BYPASSNL;
- writel(reg, RIVA_PLL_MODE);
+ writel_relaxed(reg, RIVA_PLL_MODE);
+ /*
+ * H/W requires a 5us delay between disabling the bypass and
+ * de-asserting the reset. Delay 10us just to be safe.
+ */
+ mb();
usleep_range(10, 20);
reg |= PLL_MODE_RESET_N;
- writel(reg, RIVA_PLL_MODE);
+ writel_relaxed(reg, RIVA_PLL_MODE);
reg |= PLL_MODE_OUTCTRL;
- writel(reg, RIVA_PLL_MODE);
+ writel_relaxed(reg, RIVA_PLL_MODE);
/* Wait for PLL to settle */
+ mb();
usleep_range(50, 100);
/* Configure cCPU for 240 MHz */
- reg = readl(RIVA_PMU_CLK_ROOT3);
- if (readl(RIVA_PMU_ROOT_CLK_SEL) & RIVA_PMU_ROOT_CLK_SEL_3) {
+ reg = readl_relaxed(RIVA_PMU_CLK_ROOT3);
+ if (readl_relaxed(RIVA_PMU_ROOT_CLK_SEL) & RIVA_PMU_ROOT_CLK_SEL_3) {
reg &= ~(RIVA_PMU_CLK_ROOT3_SRC0_SEL |
RIVA_PMU_CLK_ROOT3_SRC0_DIV);
reg |= RIVA_PMU_CLK_ROOT3_SRC0_SEL_RIVA |
@@ -521,34 +159,34 @@
reg |= RIVA_PMU_CLK_ROOT3_SRC1_SEL_RIVA |
RIVA_PMU_CLK_ROOT3_SRC1_DIV_2;
}
- writel(reg, RIVA_PMU_CLK_ROOT3);
+ writel_relaxed(reg, RIVA_PMU_CLK_ROOT3);
reg |= RIVA_PMU_CLK_ROOT3_ENA;
- writel(reg, RIVA_PMU_CLK_ROOT3);
- reg = readl(RIVA_PMU_ROOT_CLK_SEL);
+ writel_relaxed(reg, RIVA_PMU_CLK_ROOT3);
+ reg = readl_relaxed(RIVA_PMU_ROOT_CLK_SEL);
reg ^= RIVA_PMU_ROOT_CLK_SEL_3;
- writel(reg, RIVA_PMU_ROOT_CLK_SEL);
+ writel_relaxed(reg, RIVA_PMU_ROOT_CLK_SEL);
/* Use the high vector table */
- reg = readl(RIVA_PMU_CCPU_CTL);
+ reg = readl_relaxed(RIVA_PMU_CCPU_CTL);
reg |= RIVA_PMU_CCPU_CTL_HIGH_IVT | RIVA_PMU_CCPU_CTL_REMAP_EN;
- writel(reg, RIVA_PMU_CCPU_CTL);
+ writel_relaxed(reg, RIVA_PMU_CCPU_CTL);
/* Set base memory address */
writel_relaxed(riva_start >> 16, RIVA_PMU_CCPU_BOOT_REMAP_ADDR);
/* Clear warmboot bit indicating this is a cold boot */
- reg = readl(RIVA_PMU_CFG);
+ reg = readl_relaxed(RIVA_PMU_CFG);
reg &= ~(RIVA_PMU_CFG_WARM_BOOT);
- writel(reg, RIVA_PMU_CFG);
+ writel_relaxed(reg, RIVA_PMU_CFG);
/* Enable the cCPU clock */
- reg = readl(RIVA_PMU_OVRD_VAL);
+ reg = readl_relaxed(RIVA_PMU_OVRD_VAL);
reg |= RIVA_PMU_OVRD_VAL_CCPU_CLK;
- writel(reg, RIVA_PMU_OVRD_VAL);
+ writel_relaxed(reg, RIVA_PMU_OVRD_VAL);
/* Take cCPU out of reset */
reg |= RIVA_PMU_OVRD_VAL_CCPU_RESET;
- writel(reg, RIVA_PMU_OVRD_VAL);
+ writel_relaxed(reg, RIVA_PMU_OVRD_VAL);
return 0;
}
@@ -557,9 +195,9 @@
{
u32 reg;
/* Put riva into reset */
- reg = readl(RIVA_PMU_OVRD_VAL);
+ reg = readl_relaxed(RIVA_PMU_OVRD_VAL);
reg &= ~(RIVA_PMU_OVRD_VAL_CCPU_RESET | RIVA_PMU_OVRD_VAL_CCPU_CLK);
- writel(reg, RIVA_PMU_OVRD_VAL);
+ writel_relaxed(reg, RIVA_PMU_OVRD_VAL);
return 0;
}
@@ -635,27 +273,6 @@
return pas_shutdown(PAS_TZAPPS);
}
-static struct pil_reset_ops pil_modem_fw_q6_ops = {
- .init_image = init_image_modem_fw_q6_untrusted,
- .verify_blob = verify_blob,
- .auth_and_reset = reset_modem_fw_q6_untrusted,
- .shutdown = shutdown_modem_fw_q6_untrusted,
-};
-
-static struct pil_reset_ops pil_modem_sw_q6_ops = {
- .init_image = init_image_modem_sw_q6_untrusted,
- .verify_blob = verify_blob,
- .auth_and_reset = reset_modem_sw_q6_untrusted,
- .shutdown = shutdown_modem_sw_q6_untrusted,
-};
-
-static struct pil_reset_ops pil_lpass_q6_ops = {
- .init_image = init_image_lpass_q6_untrusted,
- .verify_blob = verify_blob,
- .auth_and_reset = reset_lpass_q6_untrusted,
- .shutdown = shutdown_lpass_q6_untrusted,
-};
-
static struct pil_reset_ops pil_riva_ops = {
.init_image = init_image_riva_untrusted,
.verify_blob = verify_blob,
@@ -677,38 +294,6 @@
.shutdown = shutdown_tzapps,
};
-static struct platform_device pil_lpass_q6 = {
- .name = "pil_lpass_q6",
-};
-
-static struct pil_desc pil_lpass_q6_desc = {
- .name = "q6",
- .dev = &pil_lpass_q6.dev,
- .ops = &pil_lpass_q6_ops,
-};
-
-static struct platform_device pil_modem_fw_q6 = {
- .name = "pil_modem_fw_q6",
-};
-
-static struct pil_desc pil_modem_fw_q6_desc = {
- .name = "modem_fw",
- .depends_on = "q6",
- .dev = &pil_modem_fw_q6.dev,
- .ops = &pil_modem_fw_q6_ops,
-};
-
-static struct platform_device pil_modem_sw_q6 = {
- .name = "pil_modem_sw_q6",
-};
-
-static struct pil_desc pil_modem_sw_q6_desc = {
- .name = "modem",
- .depends_on = "modem_fw",
- .dev = &pil_modem_sw_q6.dev,
- .ops = &pil_modem_sw_q6_ops,
-};
-
static struct platform_device pil_riva = {
.name = "pil_riva",
};
@@ -739,51 +324,8 @@
.ops = &pil_tzapps_ops,
};
-static int __init q6_reset_init(struct q6_data *q6)
-{
- int err;
-
- q6->reg_base = ioremap(q6->reg_base_phys, SZ_256);
- if (!q6->reg_base) {
- err = -ENOMEM;
- goto err_map;
- }
-
- q6->vreg = regulator_get(NULL, q6->name);
- if (IS_ERR(q6->vreg)) {
- err = PTR_ERR(q6->vreg);
- goto err_vreg;
- }
-
- return 0;
-
-err_vreg:
- iounmap(q6->reg_base);
-err_map:
- return err;
-}
-
static void __init use_secure_pil(void)
{
-
- if (pas_supported(PAS_Q6) > 0) {
- pil_lpass_q6_ops.init_image = init_image_lpass_q6_trusted;
- pil_lpass_q6_ops.auth_and_reset = reset_lpass_q6_trusted;
- pil_lpass_q6_ops.shutdown = shutdown_lpass_q6_trusted;
- }
-
- if (pas_supported(PAS_MODEM_FW) > 0) {
- pil_modem_fw_q6_ops.init_image = init_image_modem_fw_q6_trusted;
- pil_modem_fw_q6_ops.auth_and_reset = reset_modem_fw_q6_trusted;
- pil_modem_fw_q6_ops.shutdown = shutdown_modem_fw_q6_trusted;
- }
-
- if (pas_supported(PAS_MODEM_SW) > 0) {
- pil_modem_sw_q6_ops.init_image = init_image_modem_sw_q6_trusted;
- pil_modem_sw_q6_ops.auth_and_reset = reset_modem_sw_q6_trusted;
- pil_modem_sw_q6_ops.shutdown = shutdown_modem_sw_q6_trusted;
- }
-
if (pas_supported(PAS_DSPS) > 0) {
pil_dsps_ops.init_image = init_image_dsps_trusted;
pil_dsps_ops.auth_and_reset = reset_dsps_trusted;
@@ -797,11 +339,8 @@
}
}
-
static int __init msm_peripheral_reset_init(void)
{
- int err;
-
/*
* Don't initialize PIL on simulated targets, as some
* subsystems may not be emulated on them.
@@ -811,34 +350,6 @@
use_secure_pil();
- err = q6_reset_init(&q6_lpass);
- if (err)
- return err;
- BUG_ON(platform_device_register(&pil_lpass_q6));
- BUG_ON(msm_pil_register(&pil_lpass_q6_desc));
-
- mss_enable_reg = ioremap(MSM_MSS_ENABLE_PHYS, 4);
- if (!mss_enable_reg)
- return -ENOMEM;
-
- err = q6_reset_init(&q6_modem_fw);
- if (err) {
- iounmap(mss_enable_reg);
- return err;
- }
- BUG_ON(platform_device_register(&pil_modem_fw_q6));
- if (err) {
- iounmap(mss_enable_reg);
- return err;
- }
- BUG_ON(msm_pil_register(&pil_modem_fw_q6_desc));
-
- err = q6_reset_init(&q6_modem_sw);
- if (err)
- return err;
- BUG_ON(platform_device_register(&pil_modem_sw_q6));
- BUG_ON(msm_pil_register(&pil_modem_sw_q6_desc));
-
BUG_ON(platform_device_register(&pil_dsps));
BUG_ON(msm_pil_register(&pil_dsps_desc));
BUG_ON(platform_device_register(&pil_tzapps));
diff --git a/arch/arm/mach-msm/pil-q6v4.c b/arch/arm/mach-msm/pil-q6v4.c
new file mode 100644
index 0000000..24c479c
--- /dev/null
+++ b/arch/arm/mach-msm/pil-q6v4.c
@@ -0,0 +1,460 @@
+/* Copyright (c) 2011, Code Aurora Forum. 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 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/io.h>
+#include <linux/ioport.h>
+#include <linux/regulator/consumer.h>
+#include <linux/elf.h>
+#include <linux/delay.h>
+#include <linux/err.h>
+
+#include <mach/msm_bus.h>
+#include <mach/msm_iomap.h>
+#include <mach/msm_xo.h>
+
+#include "peripheral-loader.h"
+#include "pil-q6v4.h"
+#include "scm-pas.h"
+
+#define PROXY_VOTE_TIMEOUT 10000
+
+#define QDSP6SS_RST_EVB 0x0
+#define QDSP6SS_RESET 0x04
+#define QDSP6SS_CGC_OVERRIDE 0x18
+#define QDSP6SS_STRAP_TCM 0x1C
+#define QDSP6SS_STRAP_AHB 0x20
+#define QDSP6SS_GFMUX_CTL 0x30
+#define QDSP6SS_PWR_CTL 0x38
+
+#define MSS_S_HCLK_CTL (MSM_CLK_CTL_BASE + 0x2C70)
+#define MSS_SLP_CLK_CTL (MSM_CLK_CTL_BASE + 0x2C60)
+#define SFAB_MSS_M_ACLK_CTL (MSM_CLK_CTL_BASE + 0x2340)
+#define SFAB_MSS_S_HCLK_CTL (MSM_CLK_CTL_BASE + 0x2C00)
+#define MSS_RESET (MSM_CLK_CTL_BASE + 0x2C64)
+
+#define Q6SS_SS_ARES BIT(0)
+#define Q6SS_CORE_ARES BIT(1)
+#define Q6SS_ISDB_ARES BIT(2)
+#define Q6SS_ETM_ARES BIT(3)
+#define Q6SS_STOP_CORE_ARES BIT(4)
+#define Q6SS_PRIV_ARES BIT(5)
+
+#define Q6SS_L2DATA_SLP_NRET_N BIT(0)
+#define Q6SS_SLP_RET_N BIT(1)
+#define Q6SS_L1TCM_SLP_NRET_N BIT(2)
+#define Q6SS_L2TAG_SLP_NRET_N BIT(3)
+#define Q6SS_ETB_SLEEP_NRET_N BIT(4)
+#define Q6SS_ARR_STBY_N BIT(5)
+#define Q6SS_CLAMP_IO BIT(6)
+
+#define Q6SS_CLK_ENA BIT(1)
+#define Q6SS_SRC_SWITCH_CLK_OVR BIT(8)
+#define Q6SS_AXIS_ACLK_EN BIT(9)
+
+struct q6v4_data {
+ void __iomem *base;
+ void __iomem *modem_base;
+ unsigned long start_addr;
+ struct regulator *vreg;
+ bool vreg_enabled;
+ struct msm_xo_voter *xo;
+ struct timer_list xo_timer;
+};
+
+static int pil_q6v4_init_image(struct pil_desc *pil, const u8 *metadata,
+ size_t size)
+{
+ const struct elf32_hdr *ehdr = (struct elf32_hdr *)metadata;
+ struct q6v4_data *drv = dev_get_drvdata(pil->dev);
+ drv->start_addr = ehdr->e_entry;
+ return 0;
+}
+
+static int nop_verify_blob(struct pil_desc *pil, u32 phy_addr, size_t size)
+{
+ return 0;
+}
+
+static void pil_q6v4_make_xo_proxy_votes(struct device *dev)
+{
+ struct q6v4_data *drv = dev_get_drvdata(dev);
+
+ msm_xo_mode_vote(drv->xo, MSM_XO_MODE_ON);
+ mod_timer(&drv->xo_timer, jiffies+msecs_to_jiffies(PROXY_VOTE_TIMEOUT));
+}
+
+static void pil_q6v4_remove_xo_proxy_votes(unsigned long data)
+{
+ struct q6v4_data *drv = (struct q6v4_data *)data;
+
+ msm_xo_mode_vote(drv->xo, MSM_XO_MODE_OFF);
+}
+
+static void pil_q6v4_remove_xo_proxy_votes_now(struct device *dev)
+{
+ struct q6v4_data *drv = dev_get_drvdata(dev);
+
+ if (del_timer(&drv->xo_timer))
+ pil_q6v4_remove_xo_proxy_votes((unsigned long)drv);
+}
+
+static int pil_q6v4_power_up(struct device *dev)
+{
+ int err;
+ struct q6v4_data *drv = dev_get_drvdata(dev);
+
+ err = regulator_set_voltage(drv->vreg, 1050000, 1050000);
+ if (err) {
+ dev_err(dev, "Failed to set regulator's voltage.\n");
+ return err;
+ }
+ err = regulator_set_optimum_mode(drv->vreg, 100000);
+ if (err < 0) {
+ dev_err(dev, "Failed to set regulator's mode.\n");
+ return err;
+ }
+ err = regulator_enable(drv->vreg);
+ if (err) {
+ dev_err(dev, "Failed to enable regulator.\n");
+ return err;
+ }
+ drv->vreg_enabled = true;
+ return 0;
+}
+
+static DEFINE_MUTEX(pil_q6v4_modem_lock);
+static unsigned pil_q6v4_modem_count;
+
+/* Bring modem subsystem out of reset */
+static void pil_q6v4_init_modem(void __iomem *base, void __iomem *jtag_clk)
+{
+ mutex_lock(&pil_q6v4_modem_lock);
+ if (!pil_q6v4_modem_count) {
+ /* Enable MSS clocks */
+ writel_relaxed(0x10, SFAB_MSS_M_ACLK_CTL);
+ writel_relaxed(0x10, SFAB_MSS_S_HCLK_CTL);
+ writel_relaxed(0x10, MSS_S_HCLK_CTL);
+ writel_relaxed(0x10, MSS_SLP_CLK_CTL);
+ /* Wait for clocks to enable */
+ mb();
+ udelay(10);
+
+ /* De-assert MSS reset */
+ writel_relaxed(0x0, MSS_RESET);
+ mb();
+ udelay(10);
+ /* Enable MSS */
+ writel_relaxed(0x7, base);
+ }
+
+ /* Enable JTAG clocks */
+ /* TODO: Remove if/when Q6 software enables them? */
+ writel_relaxed(0x10, jtag_clk);
+
+ pil_q6v4_modem_count++;
+ mutex_unlock(&pil_q6v4_modem_lock);
+}
+
+/* Put modem subsystem back into reset */
+static void pil_q6v4_shutdown_modem(void)
+{
+ mutex_lock(&pil_q6v4_modem_lock);
+ if (pil_q6v4_modem_count)
+ pil_q6v4_modem_count--;
+ if (pil_q6v4_modem_count == 0)
+ writel_relaxed(0x1, MSS_RESET);
+ mutex_unlock(&pil_q6v4_modem_lock);
+}
+
+static int pil_q6v4_reset(struct pil_desc *pil)
+{
+ u32 reg, err = 0;
+ const struct q6v4_data *drv = dev_get_drvdata(pil->dev);
+ const struct pil_q6v4_pdata *pdata = pil->dev->platform_data;
+
+ pil_q6v4_make_xo_proxy_votes(pil->dev);
+
+ err = pil_q6v4_power_up(pil->dev);
+ if (err)
+ return err;
+ /* Enable Q6 ACLK */
+ writel_relaxed(0x10, pdata->aclk_reg);
+
+ if (drv->modem_base)
+ pil_q6v4_init_modem(drv->modem_base, pdata->jtag_clk_reg);
+
+ /* Unhalt bus port */
+ err = msm_bus_axi_portunhalt(pdata->bus_port);
+ if (err)
+ dev_err(pil->dev, "Failed to unhalt bus port\n");
+
+ /*
+ * Assert AXIS_ACLK_EN override to allow for correct updating of the
+ * QDSP6_CORE_STATE status bit. This is mandatory only for the SW Q6
+ * in 8960v1 and optional elsewhere.
+ */
+ reg = readl_relaxed(drv->base + QDSP6SS_CGC_OVERRIDE);
+ reg |= Q6SS_AXIS_ACLK_EN;
+ writel_relaxed(reg, drv->base + QDSP6SS_CGC_OVERRIDE);
+
+ /* Deassert Q6SS_SS_ARES */
+ reg = readl_relaxed(drv->base + QDSP6SS_RESET);
+ reg &= ~(Q6SS_SS_ARES);
+ writel_relaxed(reg, drv->base + QDSP6SS_RESET);
+
+ /* Program boot address */
+ writel_relaxed((drv->start_addr >> 8) & 0xFFFFFF,
+ drv->base + QDSP6SS_RST_EVB);
+
+ /* Program TCM and AHB address ranges */
+ writel_relaxed(pdata->strap_tcm_base, drv->base + QDSP6SS_STRAP_TCM);
+ writel_relaxed(pdata->strap_ahb_upper | pdata->strap_ahb_lower,
+ drv->base + QDSP6SS_STRAP_AHB);
+
+ /* Turn off Q6 core clock */
+ writel_relaxed(Q6SS_SRC_SWITCH_CLK_OVR,
+ drv->base + QDSP6SS_GFMUX_CTL);
+
+ /* Put memories to sleep */
+ writel_relaxed(Q6SS_CLAMP_IO, drv->base + QDSP6SS_PWR_CTL);
+
+ /* Assert resets */
+ reg = readl_relaxed(drv->base + QDSP6SS_RESET);
+ reg |= (Q6SS_CORE_ARES | Q6SS_ISDB_ARES | Q6SS_ETM_ARES
+ | Q6SS_STOP_CORE_ARES);
+ writel_relaxed(reg, drv->base + QDSP6SS_RESET);
+
+ /* Wait 8 AHB cycles for Q6 to be fully reset (AHB = 1.5Mhz) */
+ mb();
+ usleep_range(20, 30);
+
+ /* Turn on Q6 memories */
+ reg = Q6SS_L2DATA_SLP_NRET_N | Q6SS_SLP_RET_N | Q6SS_L1TCM_SLP_NRET_N
+ | Q6SS_L2TAG_SLP_NRET_N | Q6SS_ETB_SLEEP_NRET_N | Q6SS_ARR_STBY_N
+ | Q6SS_CLAMP_IO;
+ writel_relaxed(reg, drv->base + QDSP6SS_PWR_CTL);
+
+ /* Turn on Q6 core clock */
+ reg = Q6SS_CLK_ENA | Q6SS_SRC_SWITCH_CLK_OVR;
+ writel_relaxed(reg, drv->base + QDSP6SS_GFMUX_CTL);
+
+ /* Remove Q6SS_CLAMP_IO */
+ reg = readl_relaxed(drv->base + QDSP6SS_PWR_CTL);
+ reg &= ~Q6SS_CLAMP_IO;
+ writel_relaxed(reg, drv->base + QDSP6SS_PWR_CTL);
+
+ /* Bring Q6 core out of reset and start execution. */
+ writel_relaxed(0x0, drv->base + QDSP6SS_RESET);
+
+ /*
+ * Re-enable auto-gating of AXIS_ACLK at lease one AXI clock cycle
+ * after resets are de-asserted.
+ */
+ mb();
+ usleep_range(1, 10);
+ reg = readl_relaxed(drv->base + QDSP6SS_CGC_OVERRIDE);
+ reg &= ~Q6SS_AXIS_ACLK_EN;
+ writel_relaxed(reg, drv->base + QDSP6SS_CGC_OVERRIDE);
+
+ return 0;
+}
+
+static int pil_q6v4_shutdown(struct pil_desc *pil)
+{
+ u32 reg;
+ struct q6v4_data *drv = dev_get_drvdata(pil->dev);
+ const struct pil_q6v4_pdata *pdata = pil->dev->platform_data;
+
+ /* Make sure bus port is halted */
+ msm_bus_axi_porthalt(pdata->bus_port);
+
+ /* Turn off Q6 core clock */
+ writel_relaxed(Q6SS_SRC_SWITCH_CLK_OVR,
+ drv->base + QDSP6SS_GFMUX_CTL);
+
+ /* Assert resets */
+ reg = (Q6SS_SS_ARES | Q6SS_CORE_ARES | Q6SS_ISDB_ARES
+ | Q6SS_ETM_ARES | Q6SS_STOP_CORE_ARES | Q6SS_PRIV_ARES);
+ writel_relaxed(reg, drv->base + QDSP6SS_RESET);
+
+ /* Turn off Q6 memories */
+ writel_relaxed(Q6SS_CLAMP_IO, drv->base + QDSP6SS_PWR_CTL);
+
+ if (drv->modem_base)
+ pil_q6v4_shutdown_modem();
+
+ if (drv->vreg_enabled) {
+ regulator_disable(drv->vreg);
+ drv->vreg_enabled = false;
+ }
+
+ pil_q6v4_remove_xo_proxy_votes_now(pil->dev);
+
+ return 0;
+}
+
+static struct pil_reset_ops pil_q6v4_ops = {
+ .init_image = pil_q6v4_init_image,
+ .verify_blob = nop_verify_blob,
+ .auth_and_reset = pil_q6v4_reset,
+ .shutdown = pil_q6v4_shutdown,
+};
+
+static int pil_q6v4_init_image_trusted(struct pil_desc *pil,
+ const u8 *metadata, size_t size)
+{
+ const struct pil_q6v4_pdata *pdata = pil->dev->platform_data;
+ return pas_init_image(pdata->pas_id, metadata, size);
+}
+
+static int pil_q6v4_reset_trusted(struct pil_desc *pil)
+{
+ const struct pil_q6v4_pdata *pdata = pil->dev->platform_data;
+ int err;
+
+ pil_q6v4_make_xo_proxy_votes(pil->dev);
+
+ err = pil_q6v4_power_up(pil->dev);
+ if (err)
+ return err;
+
+ /* Unhalt bus port */
+ err = msm_bus_axi_portunhalt(pdata->bus_port);
+ if (err)
+ dev_err(pil->dev, "Failed to unhalt bus port\n");
+ return pas_auth_and_reset(pdata->pas_id);
+}
+
+static int pil_q6v4_shutdown_trusted(struct pil_desc *pil)
+{
+ int ret;
+ struct q6v4_data *drv = dev_get_drvdata(pil->dev);
+ struct pil_q6v4_pdata *pdata = pil->dev->platform_data;
+
+ /* Make sure bus port is halted */
+ msm_bus_axi_porthalt(pdata->bus_port);
+
+ ret = pas_shutdown(pdata->pas_id);
+ if (ret)
+ return ret;
+
+ if (drv->vreg_enabled) {
+ regulator_disable(drv->vreg);
+ drv->vreg_enabled = false;
+ }
+
+ pil_q6v4_remove_xo_proxy_votes_now(pil->dev);
+
+ return ret;
+}
+
+static struct pil_reset_ops pil_q6v4_ops_trusted = {
+ .init_image = pil_q6v4_init_image_trusted,
+ .verify_blob = nop_verify_blob,
+ .auth_and_reset = pil_q6v4_reset_trusted,
+ .shutdown = pil_q6v4_shutdown_trusted,
+};
+
+static int __devinit pil_q6v4_driver_probe(struct platform_device *pdev)
+{
+ const struct pil_q6v4_pdata *pdata = pdev->dev.platform_data;
+ struct q6v4_data *drv;
+ struct resource *res;
+ struct pil_desc *desc;
+
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ if (!res)
+ return -EINVAL;
+
+ drv = devm_kzalloc(&pdev->dev, sizeof(*drv), GFP_KERNEL);
+ if (!drv)
+ return -ENOMEM;
+ platform_set_drvdata(pdev, drv);
+
+ drv->base = devm_ioremap(&pdev->dev, res->start, resource_size(res));
+ if (!drv->base)
+ return -ENOMEM;
+
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
+ if (res) {
+ drv->modem_base = devm_ioremap(&pdev->dev, res->start,
+ resource_size(res));
+ if (!drv->modem_base)
+ return -ENOMEM;
+ }
+
+ desc = devm_kzalloc(&pdev->dev, sizeof(*desc), GFP_KERNEL);
+ if (!drv)
+ return -ENOMEM;
+
+ desc->name = pdata->name;
+ desc->depends_on = pdata->depends;
+ desc->dev = &pdev->dev;
+
+ if (pas_supported(pdata->pas_id) > 0) {
+ desc->ops = &pil_q6v4_ops_trusted;
+ dev_info(&pdev->dev, "using secure boot\n");
+ } else {
+ desc->ops = &pil_q6v4_ops;
+ dev_info(&pdev->dev, "using non-secure boot\n");
+ }
+
+ drv->vreg = regulator_get(&pdev->dev, "core_vdd");
+ if (IS_ERR(drv->vreg))
+ return PTR_ERR(drv->vreg);
+
+ setup_timer(&drv->xo_timer, pil_q6v4_remove_xo_proxy_votes,
+ (unsigned long)drv);
+ drv->xo = msm_xo_get(pdata->xo_id, pdata->name);
+ if (IS_ERR(drv->xo))
+ return PTR_ERR(drv->xo);
+
+ if (msm_pil_register(desc)) {
+ regulator_put(drv->vreg);
+ return -EINVAL;
+ }
+ return 0;
+}
+
+static int __devexit pil_q6v4_driver_exit(struct platform_device *pdev)
+{
+ struct q6v4_data *drv = platform_get_drvdata(pdev);
+ regulator_put(drv->vreg);
+ return 0;
+}
+
+static struct platform_driver pil_q6v4_driver = {
+ .probe = pil_q6v4_driver_probe,
+ .remove = __devexit_p(pil_q6v4_driver_exit),
+ .driver = {
+ .name = "pil_qdsp6v4",
+ .owner = THIS_MODULE,
+ },
+};
+
+static int __init pil_q6v4_init(void)
+{
+ return platform_driver_register(&pil_q6v4_driver);
+}
+module_init(pil_q6v4_init);
+
+static void __exit pil_q6v4_exit(void)
+{
+ platform_driver_unregister(&pil_q6v4_driver);
+}
+module_exit(pil_q6v4_exit);
+
+MODULE_DESCRIPTION("Support for booting QDSP6v4 (Hexagon) processors");
+MODULE_LICENSE("GPL v2");
diff --git a/arch/arm/mach-msm/pil-q6v4.h b/arch/arm/mach-msm/pil-q6v4.h
new file mode 100644
index 0000000..54bdf88
--- /dev/null
+++ b/arch/arm/mach-msm/pil-q6v4.h
@@ -0,0 +1,27 @@
+/* Copyright (c) 2011, Code Aurora Forum. 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 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+#ifndef __MSM_PIL_Q6V4_H
+#define __MSM_PIL_Q6V4_H
+
+struct pil_q6v4_pdata {
+ const unsigned long strap_tcm_base;
+ const unsigned long strap_ahb_upper;
+ const unsigned long strap_ahb_lower;
+ void __iomem *aclk_reg;
+ void __iomem *jtag_clk_reg;
+ const int xo_id;
+ const char *name;
+ const char *depends;
+ const unsigned pas_id;
+ int bus_port;
+};
+#endif
diff --git a/arch/arm/mach-msm/pm-boot.h b/arch/arm/mach-msm/pm-boot.h
index 7e1a439..2234192 100644
--- a/arch/arm/mach-msm/pm-boot.h
+++ b/arch/arm/mach-msm/pm-boot.h
@@ -18,7 +18,14 @@
MSM_PM_BOOT_CONFIG_RESET_VECTOR = 1,
};
+#ifdef CONFIG_PM
int __init msm_pm_boot_init(int boot_config, uint32_t* address);
+#else
+static inline int __init msm_pm_boot_init(int boot_config, uint32_t* address)
+{
+ return 0;
+}
+#endif
void msm_pm_boot_config_before_pc(unsigned int cpu, unsigned long entry);
void msm_pm_boot_config_after_pc(unsigned int cpu);
diff --git a/arch/arm/mach-msm/qdsp6v2/audio_mvs.c b/arch/arm/mach-msm/qdsp6v2/audio_mvs.c
index 0b4997c..6e7961c 100644
--- a/arch/arm/mach-msm/qdsp6v2/audio_mvs.c
+++ b/arch/arm/mach-msm/qdsp6v2/audio_mvs.c
@@ -205,6 +205,7 @@
break;
}
+ case MVS_MODE_G711:
case MVS_MODE_G711A: {
/* G711 frames are 10ms each, but the DSP works with
* 20ms frames and sends two 10ms frames per buffer.
@@ -212,11 +213,16 @@
* buffers.
*/
/* Remove the first DSP frame info header.
- * Header format:
+ * Header format: G711A
* Bits 0-1: Frame type
* Bits 2-3: Frame rate
+ *
+ * Header format: G711
+ * Bits 2-3: Frame rate
*/
- buf_node->frame.header.frame_type = (*voc_pkt) & 0x03;
+ if (audio->mvs_mode == MVS_MODE_G711A)
+ buf_node->frame.header.frame_type =
+ (*voc_pkt) & 0x03;
voc_pkt = voc_pkt + DSP_FRAME_HDR_LEN;
/* There are two frames in the buffer. Length of the
@@ -247,7 +253,8 @@
* Bits 0-1: Frame type
* Bits 2-3: Frame rate
*/
- buf_node->frame.header.frame_type =
+ if (audio->mvs_mode == MVS_MODE_G711A)
+ buf_node->frame.header.frame_type =
(*voc_pkt) & 0x03;
voc_pkt = voc_pkt + DSP_FRAME_HDR_LEN;
@@ -271,6 +278,7 @@
break;
}
+ case MVS_MODE_IS733:
case MVS_MODE_4GV_NB:
case MVS_MODE_4GV_WB: {
/* Remove the DSP frame info header.
@@ -284,6 +292,32 @@
memcpy(&buf_node->frame.voc_pkt[0],
voc_pkt,
buf_node->frame.len);
+
+ list_add_tail(&buf_node->list, &audio->out_queue);
+ break;
+ }
+
+ case MVS_MODE_EFR:
+ case MVS_MODE_FR:
+ case MVS_MODE_HR: {
+ /*
+ * Remove the DSP frame info header
+ * Header Format
+ * Bit 0: bfi unused for uplink
+ * Bit 1-2: sid applies to both uplink and downlink
+ * Bit 3: taf unused for uplink
+ * MVS_MODE_HR
+ * Bit 4: ufi unused for uplink
+ */
+ buf_node->frame.header.gsm_frame_type.sid =
+ ((*voc_pkt) & 0x06) >> 1;
+ voc_pkt = voc_pkt + DSP_FRAME_HDR_LEN;
+ buf_node->frame.len = pkt_len - DSP_FRAME_HDR_LEN;
+
+ memcpy(&buf_node->frame.voc_pkt[0],
+ voc_pkt,
+ buf_node->frame.len);
+
list_add_tail(&buf_node->list, &audio->out_queue);
break;
}
@@ -353,7 +387,6 @@
case MVS_MODE_IS127: {
/* Add the DSP frame info header. Header format:
* Bits 0-3: Frame rate
- * Bits 4-7: Frame type
*/
*voc_pkt = buf_node->frame.header.packet_rate & 0x0F;
voc_pkt = voc_pkt + DSP_FRAME_HDR_LEN;
@@ -423,6 +456,7 @@
break;
}
+ case MVS_MODE_G711:
case MVS_MODE_G711A: {
/* G711 frames are 10ms each but the DSP expects 20ms
* worth of data, so send two 10ms frames per buffer.
@@ -481,6 +515,7 @@
break;
}
+ case MVS_MODE_IS733:
case MVS_MODE_4GV_NB:
case MVS_MODE_4GV_WB: {
/* Add the DSP frame info header. Header format:
@@ -498,6 +533,48 @@
break;
}
+ case MVS_MODE_EFR:
+ case MVS_MODE_FR:
+ case MVS_MODE_HR: {
+ /*
+ * Remove the DSP frame info header
+ * Header Format
+ * Bit 0: bfi applies only for downlink
+ * Bit 1-2: sid applies for downlink and uplink
+ * Bit 3: taf applies only for downlink
+ * MVS_MODE_HR
+ * Bit 4: ufi applies only for downlink
+ */
+ *voc_pkt =
+ ((buf_node->frame.header.gsm_frame_type.bfi
+ & 0x01) |
+ ((buf_node->frame.header.gsm_frame_type.sid
+ & 0x03) << 1) |
+ ((buf_node->frame.header.gsm_frame_type.taf
+ & 0x01) << 3));
+
+ if (audio->mvs_mode == MVS_MODE_HR) {
+ *voc_pkt = (*voc_pkt |
+ ((buf_node->frame.header.gsm_frame_type.ufi
+ & 0x01) << 4) |
+ ((0 & 0x07) << 5));
+ } else {
+ *voc_pkt = (*voc_pkt |
+ ((0 & 0x0F) << 4));
+ }
+
+ voc_pkt = voc_pkt + DSP_FRAME_HDR_LEN;
+ *pkt_len = buf_node->frame.len + DSP_FRAME_HDR_LEN;
+
+ memcpy(voc_pkt,
+ &buf_node->frame.voc_pkt[0],
+ buf_node->frame.len);
+
+ list_add_tail(&buf_node->list, &audio->free_in_queue);
+
+ break;
+ }
+
default: {
*pkt_len = buf_node->frame.len;
@@ -523,6 +600,10 @@
uint32_t media_type;
switch (mvs_mode) {
+ case MVS_MODE_IS733:
+ media_type = VSS_MEDIA_ID_13K_MODEM;
+ break;
+
case MVS_MODE_IS127:
media_type = VSS_MEDIA_ID_EVRC_MODEM;
break;
@@ -539,6 +620,18 @@
media_type = VSS_MEDIA_ID_AMR_NB_MODEM;
break;
+ case MVS_MODE_EFR:
+ media_type = VSS_MEDIA_ID_EFR_MODEM;
+ break;
+
+ case MVS_MODE_FR:
+ media_type = VSS_MEDIA_ID_FR_MODEM;
+ break;
+
+ case MVS_MODE_HR:
+ media_type = VSS_MEDIA_ID_HR_MODEM;
+ break;
+
case MVS_MODE_LINEAR_PCM:
media_type = VSS_MEDIA_ID_PCM_NB;
break;
@@ -555,6 +648,7 @@
media_type = VSS_MEDIA_ID_G729;
break;
+ case MVS_MODE_G711:
case MVS_MODE_G711A:
if (rate_type == MVS_G711A_MODE_MULAW)
media_type = VSS_MEDIA_ID_G711_MULAW;
@@ -580,10 +674,15 @@
uint32_t network_type;
switch (mvs_mode) {
+ case MVS_MODE_IS733:
case MVS_MODE_IS127:
case MVS_MODE_4GV_NB:
case MVS_MODE_AMR:
+ case MVS_MODE_EFR:
+ case MVS_MODE_FR:
+ case MVS_MODE_HR:
case MVS_MODE_LINEAR_PCM:
+ case MVS_MODE_G711:
case MVS_MODE_PCM:
case MVS_MODE_G729A:
case MVS_MODE_G711A:
diff --git a/arch/arm/mach-msm/qdsp6v2/lpa_if_hdmi.c b/arch/arm/mach-msm/qdsp6v2/lpa_if_hdmi.c
index 64344ef..c19fd85 100644
--- a/arch/arm/mach-msm/qdsp6v2/lpa_if_hdmi.c
+++ b/arch/arm/mach-msm/qdsp6v2/lpa_if_hdmi.c
@@ -404,6 +404,9 @@
}
core_req_bus_bandwith(AUDIO_IF_BUS_ID, 0, 0);
+ if (hdmi_msm_audio_get_sample_rate() != HDMI_SAMPLE_RATE_48KHZ)
+ hdmi_msm_audio_sample_rate_reset(HDMI_SAMPLE_RATE_48KHZ);
+
return 0;
}
diff --git a/arch/arm/mach-msm/qdsp6v2/q6voice.c b/arch/arm/mach-msm/qdsp6v2/q6voice.c
index 058e281..34169c0 100644
--- a/arch/arm/mach-msm/qdsp6v2/q6voice.c
+++ b/arch/arm/mach-msm/qdsp6v2/q6voice.c
@@ -1117,6 +1117,7 @@
/* Set encoder properties. */
switch (common.mvs_info.media_type) {
+ case VSS_MEDIA_ID_13K_MODEM:
case VSS_MEDIA_ID_4GV_NB_MODEM:
case VSS_MEDIA_ID_4GV_WB_MODEM:
case VSS_MEDIA_ID_EVRC_MODEM: {
@@ -1253,6 +1254,9 @@
break;
}
+ case VSS_MEDIA_ID_EFR_MODEM:
+ case VSS_MEDIA_ID_FR_MODEM:
+ case VSS_MEDIA_ID_HR_MODEM:
case VSS_MEDIA_ID_G729:
case VSS_MEDIA_ID_G711_ALAW:
case VSS_MEDIA_ID_G711_MULAW: {
diff --git a/arch/arm/mach-msm/rpm-regulator.c b/arch/arm/mach-msm/rpm-regulator.c
index c10281b..e2ebbd4 100644
--- a/arch/arm/mach-msm/rpm-regulator.c
+++ b/arch/arm/mach-msm/rpm-regulator.c
@@ -490,6 +490,14 @@
*/
uV = (uV - range->min_uV + range->step_uV - 1) / range->step_uV;
uV = uV * range->step_uV + range->min_uV;
+
+ if (uV > max_uV) {
+ vreg_err(vreg,
+ "request v=[%d, %d] cannot be met by any set point; "
+ "next set point: %d\n",
+ min_uV, max_uV, uV);
+ return -EINVAL;
+ }
}
if (vreg->part->uV.mask) {
@@ -812,6 +820,14 @@
uV = (uV - range->min_uV + range->step_uV - 1) / range->step_uV;
uV = uV * range->step_uV + range->min_uV;
+ if (uV > max_uV) {
+ vreg_err(vreg,
+ "request v=[%d, %d] cannot be met by any set point; "
+ "next set point: %d\n",
+ min_uV, max_uV, uV);
+ return -EINVAL;
+ }
+
if (vreg->part->uV.mask) {
val[vreg->part->uV.word] = uV << vreg->part->uV.shift;
mask[vreg->part->uV.word] = vreg->part->uV.mask;
diff --git a/arch/arm/mach-msm/rpm_resources.c b/arch/arm/mach-msm/rpm_resources.c
index 9fe9eea6..3568070 100644
--- a/arch/arm/mach-msm/rpm_resources.c
+++ b/arch/arm/mach-msm/rpm_resources.c
@@ -928,10 +928,6 @@
{
int rc = 0;
- rc = msm_rpmrs_flush_L2(limits, notify_rpm);
- if (rc)
- return rc;
-
if (notify_rpm) {
rc = msm_rpmrs_flush_buffer(sclk_count, limits, from_idle);
if (rc)
@@ -941,6 +937,7 @@
msm_mpm_enter_sleep(from_idle);
}
+ rc = msm_rpmrs_flush_L2(limits, notify_rpm);
return rc;
}
diff --git a/arch/arm/mach-msm/sdio_al_test.c b/arch/arm/mach-msm/sdio_al_test.c
index 8b9abcf..a71aae3 100644
--- a/arch/arm/mach-msm/sdio_al_test.c
+++ b/arch/arm/mach-msm/sdio_al_test.c
@@ -298,6 +298,7 @@
uint32_t smem_counter;
struct platform_device *ciq_app_pdev;
+ struct platform_device *csvt_app_pdev;
wait_queue_head_t wait_q;
int test_completed;
@@ -6162,7 +6163,7 @@
int ret;
pr_debug(TEST_MODULE_NAME ":%s.\n", __func__);
- pr_info(TEST_MODULE_NAME ": init test cahnnel %s.\n", name);
+ pr_info(TEST_MODULE_NAME ": init test channel %s.\n", name);
ch_id = channel_name_to_id(name);
pr_debug(TEST_MODULE_NAME ":id = %d.\n", ch_id);
@@ -6324,6 +6325,35 @@
return sdio_test_channel_remove(pdev);
}
+static int sdio_test_channel_csvt_probe(struct platform_device *pdev)
+{
+ int ret = 0;
+
+ if (!pdev)
+ return -ENODEV;
+
+ test_ctx->csvt_app_pdev = platform_device_alloc("SDIO_CSVT_TEST_APP",
+ -1);
+ ret = platform_device_add(test_ctx->csvt_app_pdev);
+ if (ret) {
+ pr_err(MODULE_NAME ":platform_device_add failed, "
+ "ret=%d\n", ret);
+ return ret;
+ }
+
+ return sdio_test_channel_probe(pdev);
+}
+
+static int sdio_test_channel_csvt_remove(struct platform_device *pdev)
+{
+ if (!pdev)
+ return -ENODEV;
+
+ platform_device_unregister(test_ctx->csvt_app_pdev);
+
+ return sdio_test_channel_remove(pdev);
+}
+
static struct platform_driver sdio_rpc_drv = {
.probe = sdio_test_channel_probe,
.remove = sdio_test_channel_remove,
@@ -6388,8 +6418,8 @@
};
static struct platform_driver sdio_csvt_drv = {
- .probe = sdio_test_channel_probe,
- .remove = sdio_test_channel_remove,
+ .probe = sdio_test_channel_csvt_probe,
+ .remove = sdio_test_channel_csvt_remove,
.driver = {
.name = "SDIO_CSVT_TEST",
.owner = THIS_MODULE,
diff --git a/arch/arm/mach-msm/sdio_tty.c b/arch/arm/mach-msm/sdio_tty.c
index fca88d8..e249d06 100644
--- a/arch/arm/mach-msm/sdio_tty.c
+++ b/arch/arm/mach-msm/sdio_tty.c
@@ -17,6 +17,7 @@
#include <linux/platform_device.h>
#include <linux/tty.h>
#include <linux/tty_flip.h>
+#include <linux/module.h>
#include <mach/sdio_al.h>
#define INPUT_SPEED 4800
@@ -24,6 +25,19 @@
#define SDIO_TTY_MODULE_NAME "sdio_tty"
#define SDIO_TTY_MAX_PACKET_SIZE 4096
#define MAX_SDIO_TTY_DRV 1
+#define MAX_SDIO_TTY_DEVS 2
+#define MAX_SDIO_TTY_DEV_NAME_SIZE 25
+
+/* Configurations per channel device */
+/* CIQ */
+#define SDIO_TTY_CIQ_DEV "sdio_tty_ciq_0"
+#define SDIO_TTY_CIQ_TEST_DEV "sdio_tty_ciq_test_0"
+#define SDIO_TTY_CH_CIQ "SDIO_CIQ"
+
+/* CSVT */
+#define SDIO_TTY_CSVT_DEV "sdio_tty_csvt_0"
+#define SDIO_TTY_CSVT_TEST_DEV "sdio_tty_csvt_test_0"
+#define SDIO_TTY_CH_CSVT "SDIO_CSVT"
enum sdio_tty_state {
TTY_INITIAL = 0,
@@ -32,9 +46,27 @@
TTY_CLOSED = 3,
};
+enum sdio_tty_devices {
+ SDIO_CIQ,
+ SDIO_CIQ_TEST_APP,
+ SDIO_CSVT,
+ SDIO_CSVT_TEST_APP,
+};
+
+static const struct platform_device_id sdio_tty_id_table[] = {
+ { "SDIO_CIQ", SDIO_CIQ },
+ { "SDIO_CIQ_TEST_APP", SDIO_CIQ_TEST_APP },
+ { "SDIO_CSVT", SDIO_CSVT },
+ { "SDIO_CSVT_TEST_APP", SDIO_CSVT_TEST_APP },
+ { },
+};
+MODULE_DEVICE_TABLE(platform, sdio_tty_id_table);
+
struct sdio_tty {
struct sdio_channel *ch;
char *sdio_ch_name;
+ char tty_dev_name[MAX_SDIO_TTY_DEV_NAME_SIZE];
+ int device_id;
struct workqueue_struct *workq;
struct work_struct work_read;
wait_queue_head_t waitq;
@@ -44,11 +76,21 @@
char *read_buf;
enum sdio_tty_state sdio_tty_state;
int is_sdio_open;
+ int tty_open_count;
};
-static struct sdio_tty *sdio_tty;
+static struct sdio_tty *sdio_tty[MAX_SDIO_TTY_DEVS];
-#define DEBUG_MSG(sdio_tty, x...) if (sdio_tty->debug_msg_on) pr_info(x)
+#define DEBUG_MSG(sdio_tty_drv, x...) if (sdio_tty_drv->debug_msg_on) pr_info(x)
+
+/*
+ * Enable sdio_tty debug messages
+ * By default the sdio_tty debug messages are turned off
+ */
+static int ciq_debug_msg_on;
+module_param(ciq_debug_msg_on, int, 0);
+static int csvt_debug_msg_on;
+module_param(csvt_debug_msg_on, int, 0);
static void sdio_tty_read(struct work_struct *work)
{
@@ -62,30 +104,30 @@
sdio_tty_drv = container_of(work, struct sdio_tty, work_read);
if (!sdio_tty_drv) {
- pr_err(SDIO_TTY_MODULE_NAME ": %s: NULL sdio_tty",
- __func__);
+ pr_err(SDIO_TTY_MODULE_NAME ": %s: NULL sdio_tty", __func__);
return ;
}
if (sdio_tty_drv->sdio_tty_state != TTY_OPENED) {
pr_err(SDIO_TTY_MODULE_NAME ": %s: sdio_tty_state = %d",
- __func__, sdio_tty_drv->sdio_tty_state);
+ __func__, sdio_tty_drv->sdio_tty_state);
return;
}
if (!sdio_tty_drv->read_buf) {
- pr_err(SDIO_TTY_MODULE_NAME ": %s: NULL read_buf", __func__);
+ pr_err(SDIO_TTY_MODULE_NAME ": %s: NULL read_buf for dev %s",
+ __func__, sdio_tty_drv->tty_dev_name);
return;
}
- /* Read the data from teh SDIO channel as long as there is available
+ /* Read the data from the SDIO channel as long as there is available
data */
while (1) {
if (test_bit(TTY_THROTTLED, &sdio_tty_drv->tty_str->flags)) {
- DEBUG_MSG(sdio_tty_drv,
- SDIO_TTY_MODULE_NAME ": %s: TTY_THROTTLED bit"
- " is set, exit",
- __func__);
+ DEBUG_MSG(sdio_tty_drv, SDIO_TTY_MODULE_NAME
+ ": %s: TTY_THROTTLED bit is set for "
+ "dev %s, exit", __func__,
+ sdio_tty_drv->tty_dev_name);
return;
}
@@ -93,20 +135,22 @@
read_avail = sdio_read_avail(sdio_tty_drv->ch);
DEBUG_MSG(sdio_tty_drv, SDIO_TTY_MODULE_NAME
- ": %s: read_avail is %d", __func__,
- read_avail);
+ ": %s: read_avail is %d for dev %s", __func__,
+ read_avail, sdio_tty_drv->tty_dev_name);
if (read_avail == 0) {
- DEBUG_MSG(sdio_tty_drv,
- SDIO_TTY_MODULE_NAME ": %s: read_avail is 0",
- __func__);
+ DEBUG_MSG(sdio_tty_drv, SDIO_TTY_MODULE_NAME
+ ": %s: read_avail is 0 for dev %s",
+ __func__, sdio_tty_drv->tty_dev_name);
return;
}
if (read_avail > SDIO_TTY_MAX_PACKET_SIZE) {
pr_err(SDIO_TTY_MODULE_NAME ": %s: read_avail(%d) is "
- "bigger than SDIO_TTY_MAX_PACKET_SIZE(%d)",
- __func__, read_avail, SDIO_TTY_MAX_PACKET_SIZE);
+ "bigger than SDIO_TTY_MAX_PACKET_SIZE(%d) "
+ "for dev %s", __func__, read_avail,
+ SDIO_TTY_MAX_PACKET_SIZE,
+ sdio_tty_drv->tty_dev_name);
return;
}
@@ -114,8 +158,9 @@
sdio_tty_drv->read_buf,
read_avail);
if (ret < 0) {
- pr_err(SDIO_TTY_MODULE_NAME ": %s: sdio_read error(%d)",
- __func__, ret);
+ pr_err(SDIO_TTY_MODULE_NAME ": %s: sdio_read error(%d) "
+ "for dev %s", __func__, ret,
+ sdio_tty_drv->tty_dev_name);
return;
}
@@ -132,15 +177,17 @@
if (total_push != read_avail) {
pr_err(SDIO_TTY_MODULE_NAME ": %s: failed, total_push"
- "(%d) != read_avail(%d)\n",
- __func__, total_push, read_avail);
+ "(%d) != read_avail(%d) for dev %s\n",
+ __func__, total_push, read_avail,
+ sdio_tty_drv->tty_dev_name);
}
tty_flip_buffer_push(sdio_tty_drv->tty_str);
- DEBUG_MSG(sdio_tty_drv,
- SDIO_TTY_MODULE_NAME ": %s: End of read %d bytes",
- __func__, read_avail);
+ DEBUG_MSG(sdio_tty_drv, SDIO_TTY_MODULE_NAME
+ ": %s: End of read %d bytes for dev %s",
+ __func__, read_avail,
+ sdio_tty_drv->tty_dev_name);
}
}
@@ -159,27 +206,26 @@
struct sdio_tty *sdio_tty_drv = NULL;
if (!tty) {
- pr_err(SDIO_TTY_MODULE_NAME ": %s: NULL tty",
- __func__);
+ pr_err(SDIO_TTY_MODULE_NAME ": %s: NULL tty", __func__);
return -ENODEV;
}
sdio_tty_drv = tty->driver_data;
if (!sdio_tty_drv) {
pr_err(SDIO_TTY_MODULE_NAME ": %s: NULL sdio_tty_drv",
- __func__);
+ __func__);
return -ENODEV;
}
if (sdio_tty_drv->sdio_tty_state != TTY_OPENED) {
pr_err(SDIO_TTY_MODULE_NAME ": %s: sdio_tty_state = %d",
- __func__, sdio_tty_drv->sdio_tty_state);
+ __func__, sdio_tty_drv->sdio_tty_state);
return -EPERM;
}
write_avail = sdio_write_avail(sdio_tty_drv->ch);
- DEBUG_MSG(sdio_tty_drv,
- SDIO_TTY_MODULE_NAME ": %s: write_avail=%d",
- __func__, write_avail);
+ DEBUG_MSG(sdio_tty_drv, SDIO_TTY_MODULE_NAME ": %s: write_avail=%d "
+ "for dev %s", __func__, write_avail,
+ sdio_tty_drv->tty_dev_name);
return write_avail;
}
@@ -205,60 +251,60 @@
struct sdio_tty *sdio_tty_drv = NULL;
if (!tty) {
- pr_err(SDIO_TTY_MODULE_NAME ": %s: NULL tty",
- __func__);
+ pr_err(SDIO_TTY_MODULE_NAME ": %s: NULL tty", __func__);
return -ENODEV;
}
sdio_tty_drv = tty->driver_data;
if (!sdio_tty_drv) {
pr_err(SDIO_TTY_MODULE_NAME ": %s: NULL sdio_tty_drv",
- __func__);
+ __func__);
return -ENODEV;
}
if (sdio_tty_drv->sdio_tty_state != TTY_OPENED) {
pr_err(SDIO_TTY_MODULE_NAME ": %s: sdio_tty_state = %d",
- __func__, sdio_tty_drv->sdio_tty_state);
+ __func__, sdio_tty_drv->sdio_tty_state);
return -EPERM;
}
- DEBUG_MSG(sdio_tty_drv,
- SDIO_TTY_MODULE_NAME ": %s: WRITING CALLBACK CALLED WITH "
- "%d bytes\n",
- __func__, count);
+ DEBUG_MSG(sdio_tty_drv, SDIO_TTY_MODULE_NAME ": %s: Write Callback "
+ "called with %d bytes for dev %s\n", __func__, count,
+ sdio_tty_drv->tty_dev_name);
write_avail = sdio_write_avail(sdio_tty_drv->ch);
if (write_avail == 0) {
- DEBUG_MSG(sdio_tty_drv,
- SDIO_TTY_MODULE_NAME ": %s: write_avail is 0\n",
- __func__);
+ DEBUG_MSG(sdio_tty_drv, SDIO_TTY_MODULE_NAME ": %s: "
+ "write_avail is 0 for dev %s\n",
+ __func__, sdio_tty_drv->tty_dev_name);
return 0;
}
if (write_avail > SDIO_TTY_MAX_PACKET_SIZE) {
- DEBUG_MSG(sdio_tty_drv,
- SDIO_TTY_MODULE_NAME ": %s: write_avail(%d) is "
- "bigger than max packet size,(%d), setting to "
- "max_packet_size\n",
- __func__, write_avail, SDIO_TTY_MAX_PACKET_SIZE);
+ DEBUG_MSG(sdio_tty_drv, SDIO_TTY_MODULE_NAME ": %s: "
+ "write_avail(%d) is bigger than max packet "
+ "size(%d) for dev %s, setting to "
+ "max_packet_size\n", __func__, write_avail,
+ SDIO_TTY_MAX_PACKET_SIZE,
+ sdio_tty_drv->tty_dev_name);
write_avail = SDIO_TTY_MAX_PACKET_SIZE;
}
if (write_avail < count) {
- DEBUG_MSG(sdio_tty_drv,
- SDIO_TTY_MODULE_NAME ": %s: write_avail(%d) is "
- "smaller than "
- "required(%d), writing only %d bytes\n",
- __func__, write_avail, count, write_avail);
+ DEBUG_MSG(sdio_tty_drv, SDIO_TTY_MODULE_NAME ": %s: "
+ "write_avail(%d) is smaller than required(%d) "
+ "for dev %s, writing only %d bytes\n",
+ __func__, write_avail, count,
+ sdio_tty_drv->tty_dev_name, write_avail);
len = write_avail;
}
ret = sdio_write(sdio_tty_drv->ch, buf, len);
if (ret) {
- pr_err(SDIO_TTY_MODULE_NAME ": %s: sdio_write failed, ret=%d\n",
- __func__, ret);
+ pr_err(SDIO_TTY_MODULE_NAME ": %s: sdio_write failed for "
+ "dev %s, ret=%d\n", __func__,
+ sdio_tty_drv->tty_dev_name, ret);
return 0;
}
- DEBUG_MSG(sdio_tty_drv,
- SDIO_TTY_MODULE_NAME ": %s: End of function, len=%d bytes\n",
- __func__, len);
+ DEBUG_MSG(sdio_tty_drv, SDIO_TTY_MODULE_NAME ": %s: End of function, "
+ "dev=%s, len=%d bytes\n", __func__,
+ sdio_tty_drv->tty_dev_name, len);
return len;
}
@@ -269,18 +315,18 @@
if (!sdio_tty_drv) {
pr_err(SDIO_TTY_MODULE_NAME ": %s: NULL sdio_tty_drv",
- __func__);
+ __func__);
}
if (sdio_tty_drv->sdio_tty_state != TTY_OPENED) {
pr_err(SDIO_TTY_MODULE_NAME ": %s: sdio_tty_state = %d",
- __func__, sdio_tty_drv->sdio_tty_state);
+ __func__, sdio_tty_drv->sdio_tty_state);
return;
}
- DEBUG_MSG(sdio_tty_drv,
- SDIO_TTY_MODULE_NAME ": %s: event %d received\n", __func__,
- event);
+ DEBUG_MSG(sdio_tty_drv, SDIO_TTY_MODULE_NAME ": %s: event %d "
+ "received for dev %s\n", __func__, event,
+ sdio_tty_drv->tty_dev_name);
if (event == SDIO_EVENT_DATA_READ_AVAIL)
queue_work(sdio_tty_drv->workq, &sdio_tty_drv->work_read);
@@ -298,20 +344,37 @@
static int sdio_tty_open(struct tty_struct *tty, struct file *file)
{
int ret = 0;
+ int i = 0;
struct sdio_tty *sdio_tty_drv = NULL;
if (!tty) {
- pr_err(SDIO_TTY_MODULE_NAME ": %s: NULL tty",
- __func__);
+ pr_err(SDIO_TTY_MODULE_NAME ": %s: NULL tty", __func__);
return -ENODEV;
}
- sdio_tty_drv = sdio_tty;
+
+ for (i = 0; i < MAX_SDIO_TTY_DEVS; i++) {
+ if (sdio_tty[i] == NULL)
+ continue;
+ if (!strncmp(sdio_tty[i]->tty_dev_name, tty->name,
+ MAX_SDIO_TTY_DEV_NAME_SIZE)) {
+ sdio_tty_drv = sdio_tty[i];
+ break;
+ }
+ }
+
if (!sdio_tty_drv) {
pr_err(SDIO_TTY_MODULE_NAME ": %s: NULL sdio_tty_drv",
__func__);
return -ENODEV;
}
+ sdio_tty_drv->tty_open_count++;
+ if (sdio_tty_drv->sdio_tty_state == TTY_OPENED) {
+ pr_err(SDIO_TTY_MODULE_NAME ": %s: tty dev(%s) is already open",
+ __func__, sdio_tty_drv->tty_dev_name);
+ return -EBUSY;
+ }
+
tty->driver_data = sdio_tty_drv;
sdio_tty_drv->tty_str = tty;
@@ -321,36 +384,31 @@
sdio_tty_drv->read_buf = kzalloc(SDIO_TTY_MAX_PACKET_SIZE, GFP_KERNEL);
if (sdio_tty_drv->read_buf == NULL) {
- pr_err(SDIO_TTY_MODULE_NAME ": %s: failed to allocate read_buf",
- __func__);
+ pr_err(SDIO_TTY_MODULE_NAME ": %s: failed to allocate read_buf "
+ "for dev %s", __func__, sdio_tty_drv->tty_dev_name);
return -ENOMEM;
}
sdio_tty_drv->workq = create_singlethread_workqueue("sdio_tty_read");
if (!sdio_tty_drv->workq) {
- pr_err(SDIO_TTY_MODULE_NAME ": %s: failed to create workq",
- __func__);
+ pr_err(SDIO_TTY_MODULE_NAME ": %s: failed to create workq "
+ "for dev %s", __func__, sdio_tty_drv->tty_dev_name);
return -ENOMEM;
}
- if (sdio_tty_drv->sdio_tty_state == TTY_OPENED) {
- pr_err(SDIO_TTY_MODULE_NAME ": %s: tty is already open",
- __func__);
- return -EBUSY;
- }
-
if (!sdio_tty_drv->is_sdio_open) {
ret = sdio_open(sdio_tty_drv->sdio_ch_name, &sdio_tty_drv->ch,
sdio_tty_drv, sdio_tty_notify);
if (ret < 0) {
- pr_err(SDIO_TTY_MODULE_NAME ": %s: sdio_open err=%d\n",
- __func__, ret);
+ pr_err(SDIO_TTY_MODULE_NAME ": %s: sdio_open err=%d "
+ "for dev %s\n", __func__, ret,
+ sdio_tty_drv->tty_dev_name);
destroy_workqueue(sdio_tty_drv->workq);
return ret;
}
- pr_info(SDIO_TTY_MODULE_NAME ": %s: SDIO_TTY channel opened\n",
- __func__);
+ pr_info(SDIO_TTY_MODULE_NAME ": %s: SDIO_TTY channel(%s) opened "
+ "\n", __func__, sdio_tty_drv->sdio_ch_name);
sdio_tty_drv->is_sdio_open = 1;
} else {
@@ -363,8 +421,8 @@
sdio_tty_drv->sdio_tty_state = TTY_OPENED;
- pr_info(SDIO_TTY_MODULE_NAME ": %s: TTY device opened\n",
- __func__);
+ pr_info(SDIO_TTY_MODULE_NAME ": %s: TTY device(%s) opened\n",
+ __func__, sdio_tty_drv->tty_dev_name);
return ret;
}
@@ -385,8 +443,7 @@
struct sdio_tty *sdio_tty_drv = NULL;
if (!tty) {
- pr_err(SDIO_TTY_MODULE_NAME ": %s: NULL tty",
- __func__);
+ pr_err(SDIO_TTY_MODULE_NAME ": %s: NULL tty", __func__);
return;
}
sdio_tty_drv = tty->driver_data;
@@ -397,10 +454,11 @@
}
if (sdio_tty_drv->sdio_tty_state != TTY_OPENED) {
pr_err(SDIO_TTY_MODULE_NAME ": %s: trying to close a "
- "TTY device that was not opened\n",
- __func__);
+ "TTY device that was not opened\n", __func__);
return;
}
+ if (--sdio_tty_drv->tty_open_count != 0)
+ return;
flush_workqueue(sdio_tty_drv->workq);
destroy_workqueue(sdio_tty_drv->workq);
@@ -410,8 +468,8 @@
sdio_tty_drv->sdio_tty_state = TTY_CLOSED;
- pr_info(SDIO_TTY_MODULE_NAME ": %s: SDIO_TTY channel closed\n",
- __func__);
+ pr_info(SDIO_TTY_MODULE_NAME ": %s: SDIO_TTY device(%s) closed\n",
+ __func__, sdio_tty_drv->tty_dev_name);
}
static void sdio_tty_unthrottle(struct tty_struct *tty)
@@ -419,8 +477,7 @@
struct sdio_tty *sdio_tty_drv = NULL;
if (!tty) {
- pr_err(SDIO_TTY_MODULE_NAME ": %s: NULL tty",
- __func__);
+ pr_err(SDIO_TTY_MODULE_NAME ": %s: NULL tty", __func__);
return;
}
sdio_tty_drv = tty->driver_data;
@@ -448,33 +505,53 @@
.unthrottle = sdio_tty_unthrottle,
};
-void *sdio_tty_init_tty(char *tty_name, char *sdio_ch_name)
+int sdio_tty_init_tty(char *tty_name, char *sdio_ch_name,
+ enum sdio_tty_devices device_id, int debug_msg_on)
{
int ret = 0;
- struct device *tty_dev;
- struct sdio_tty *sdio_tty_drv;
-
- pr_info(SDIO_TTY_MODULE_NAME ": %s\n", __func__);
+ int i = 0;
+ struct device *tty_dev = NULL;
+ struct sdio_tty *sdio_tty_drv = NULL;
sdio_tty_drv = kzalloc(sizeof(struct sdio_tty), GFP_KERNEL);
if (sdio_tty_drv == NULL) {
- pr_err(SDIO_TTY_MODULE_NAME "%s: failed to allocate sdio_tty",
- __func__);
- return NULL;
+ pr_err(SDIO_TTY_MODULE_NAME ": %s: failed to allocate sdio_tty "
+ "for dev %s", __func__, tty_name);
+ return -ENOMEM;
}
- sdio_tty = sdio_tty_drv;
+ for (i = 0; i < MAX_SDIO_TTY_DEVS; i++) {
+ if (sdio_tty[i] == NULL) {
+ sdio_tty[i] = sdio_tty_drv;
+ break;
+ }
+ }
+
+ if (i == MAX_SDIO_TTY_DEVS) {
+ pr_err(SDIO_TTY_MODULE_NAME ": %s: tty dev(%s) creation failed,"
+ " max limit(%d) reached.", __func__, tty_name,
+ MAX_SDIO_TTY_DEVS);
+ kfree(sdio_tty_drv);
+ return -ENODEV;
+ }
+
+ snprintf(sdio_tty_drv->tty_dev_name, MAX_SDIO_TTY_DEV_NAME_SIZE,
+ "%s%d", tty_name, 0);
sdio_tty_drv->sdio_ch_name = sdio_ch_name;
+ sdio_tty_drv->device_id = device_id;
+ pr_info(SDIO_TTY_MODULE_NAME ": %s: dev=%s, id=%d, channel=%s\n",
+ __func__, sdio_tty_drv->tty_dev_name, sdio_tty_drv->device_id,
+ sdio_tty_drv->sdio_ch_name);
INIT_WORK(&sdio_tty_drv->work_read, sdio_tty_read);
sdio_tty_drv->tty_drv = alloc_tty_driver(MAX_SDIO_TTY_DRV);
if (!sdio_tty_drv->tty_drv) {
- pr_err(SDIO_TTY_MODULE_NAME ": %s - tty_drv is NULL",
- __func__);
+ pr_err(SDIO_TTY_MODULE_NAME ": %s - tty_drv is NULL for dev %s",
+ __func__, sdio_tty_drv->tty_dev_name);
kfree(sdio_tty_drv);
- return NULL;
+ return -ENODEV;
}
sdio_tty_drv->tty_drv->name = tty_name;
@@ -500,31 +577,38 @@
if (ret) {
put_tty_driver(sdio_tty_drv->tty_drv);
pr_err(SDIO_TTY_MODULE_NAME ": %s: tty_register_driver() "
- "failed\n", __func__);
+ "failed for dev %s\n", __func__,
+ sdio_tty_drv->tty_dev_name);
sdio_tty_drv->tty_drv = NULL;
kfree(sdio_tty_drv);
- return NULL;
+ return -ENODEV;
}
tty_dev = tty_register_device(sdio_tty_drv->tty_drv, 0, NULL);
if (IS_ERR(tty_dev)) {
pr_err(SDIO_TTY_MODULE_NAME ": %s: tty_register_device() "
- "failed\n", __func__);
+ "failed for dev %s\n", __func__,
+ sdio_tty_drv->tty_dev_name);
tty_unregister_driver(sdio_tty_drv->tty_drv);
put_tty_driver(sdio_tty_drv->tty_drv);
kfree(sdio_tty_drv);
- return NULL;
+ return -ENODEV;
}
sdio_tty_drv->sdio_tty_state = TTY_REGISTERED;
- return sdio_tty_drv;
+ if (debug_msg_on) {
+ pr_info(SDIO_TTY_MODULE_NAME ": %s: turn on debug msg for %s",
+ __func__, sdio_tty_drv->tty_dev_name);
+ sdio_tty_drv->debug_msg_on = debug_msg_on;
+ }
+ return 0;
}
-EXPORT_SYMBOL(sdio_tty_init_tty);
int sdio_tty_uninit_tty(void *sdio_tty_handle)
{
int ret = 0;
+ int i = 0;
struct sdio_tty *sdio_tty_drv = sdio_tty_handle;
if (!sdio_tty_drv) {
@@ -546,51 +630,151 @@
ret = tty_unregister_driver(sdio_tty_drv->tty_drv);
if (ret) {
pr_err(SDIO_TTY_MODULE_NAME ": %s: "
- "tty_unregister_driver() failed\n", __func__);
+ "tty_unregister_driver() failed for dev %s\n",
+ __func__, sdio_tty_drv->tty_dev_name);
}
put_tty_driver(sdio_tty_drv->tty_drv);
sdio_tty_drv->sdio_tty_state = TTY_INITIAL;
sdio_tty_drv->tty_drv = NULL;
}
- pr_info(SDIO_TTY_MODULE_NAME ": %s: Freeing sdio_tty structure",
- __func__);
+ for (i = 0; i < MAX_SDIO_TTY_DEVS; i++) {
+ if (sdio_tty[i] == NULL)
+ continue;
+ if (sdio_tty[i]->device_id == sdio_tty_drv->device_id) {
+ sdio_tty[i] = NULL;
+ break;
+ }
+ }
+
+ DEBUG_MSG(sdio_tty_drv, SDIO_TTY_MODULE_NAME ": %s: Freeing sdio_tty "
+ "structure, dev=%s", __func__,
+ sdio_tty_drv->tty_dev_name);
kfree(sdio_tty_drv);
return 0;
}
-EXPORT_SYMBOL(sdio_tty_uninit_tty);
-
-void sdio_tty_enable_debug_msg(void *sdio_tty_handle, int enable)
+static int sdio_tty_probe(struct platform_device *pdev)
{
- struct sdio_tty *sdio_tty_drv = sdio_tty_handle;
+ const struct platform_device_id *id = platform_get_device_id(pdev);
+ enum sdio_tty_devices device_id = id->driver_data;
+ char *device_name = NULL;
+ char *channel_name = NULL;
+ int debug_msg_on = 0;
+ int ret = 0;
+
+ pr_debug(SDIO_TTY_MODULE_NAME ": %s for %s", __func__, pdev->name);
+
+ switch (device_id) {
+ case SDIO_CIQ:
+ device_name = SDIO_TTY_CIQ_DEV;
+ channel_name = SDIO_TTY_CH_CIQ;
+ debug_msg_on = ciq_debug_msg_on;
+ break;
+ case SDIO_CIQ_TEST_APP:
+ device_name = SDIO_TTY_CIQ_TEST_DEV;
+ channel_name = SDIO_TTY_CH_CIQ;
+ debug_msg_on = ciq_debug_msg_on;
+ break;
+ case SDIO_CSVT:
+ device_name = SDIO_TTY_CSVT_DEV;
+ channel_name = SDIO_TTY_CH_CSVT;
+ debug_msg_on = csvt_debug_msg_on;
+ break;
+ case SDIO_CSVT_TEST_APP:
+ device_name = SDIO_TTY_CSVT_TEST_DEV;
+ channel_name = SDIO_TTY_CH_CSVT;
+ debug_msg_on = csvt_debug_msg_on;
+ break;
+ default:
+ pr_err(SDIO_TTY_MODULE_NAME ": %s Invalid device:%s, id:%d",
+ __func__, pdev->name, device_id);
+ ret = -ENODEV;
+ break;
+ }
+
+ if (device_name) {
+ ret = sdio_tty_init_tty(device_name, channel_name,
+ device_id, debug_msg_on);
+ if (ret) {
+ pr_err(SDIO_TTY_MODULE_NAME ": %s: sdio_tty_init_tty "
+ "failed for dev:%s", __func__, device_name);
+ }
+ }
+ return ret;
+}
+
+static int sdio_tty_remove(struct platform_device *pdev)
+{
+ const struct platform_device_id *id = platform_get_device_id(pdev);
+ enum sdio_tty_devices device_id = id->driver_data;
+ struct sdio_tty *sdio_tty_drv = NULL;
+ int i = 0;
+ int ret = 0;
+
+ pr_debug(SDIO_TTY_MODULE_NAME ": %s for %s", __func__, pdev->name);
+
+ for (i = 0; i < MAX_SDIO_TTY_DEVS; i++) {
+ if (sdio_tty[i] == NULL)
+ continue;
+ if (sdio_tty[i]->device_id == device_id) {
+ sdio_tty_drv = sdio_tty[i];
+ break;
+ }
+ }
if (!sdio_tty_drv) {
pr_err(SDIO_TTY_MODULE_NAME ": %s: NULL sdio_tty_drv",
__func__);
- return;
+ return -ENODEV;
}
- pr_info(SDIO_TTY_MODULE_NAME ": %s: setting debug_msg_on to %d",
- __func__, enable);
- sdio_tty_drv->debug_msg_on = enable;
+
+ ret = sdio_tty_uninit_tty(sdio_tty_drv);
+ if (ret) {
+ pr_err(SDIO_TTY_MODULE_NAME ": %s: sdio_tty_uninit_tty "
+ "failed for %s", __func__, pdev->name);
+ }
+ return ret;
}
-EXPORT_SYMBOL(sdio_tty_enable_debug_msg);
+static struct platform_driver sdio_tty_pdrv = {
+ .probe = sdio_tty_probe,
+ .remove = sdio_tty_remove,
+ .id_table = sdio_tty_id_table,
+ .driver = {
+ .name = "SDIO_TTY",
+ .owner = THIS_MODULE,
+ },
+};
+/*
+ * Module Init.
+ *
+ * Register SDIO TTY driver.
+ *
+ */
static int __init sdio_tty_init(void)
{
- return 0;
+ int ret = 0;
+
+ ret = platform_driver_register(&sdio_tty_pdrv);
+ if (ret) {
+ pr_err(SDIO_TTY_MODULE_NAME ": %s: platform_driver_register "
+ "failed", __func__);
+ }
+ return ret;
};
/*
* Module Exit.
*
- * Unregister SDIO driver.
+ * Unregister SDIO TTY driver.
*
*/
static void __exit sdio_tty_exit(void)
{
+ platform_driver_unregister(&sdio_tty_pdrv);
}
module_init(sdio_tty_init);
diff --git a/arch/arm/mach-msm/sdio_tty_ciq.c b/arch/arm/mach-msm/sdio_tty_ciq.c
deleted file mode 100644
index 64b772d..0000000
--- a/arch/arm/mach-msm/sdio_tty_ciq.c
+++ /dev/null
@@ -1,134 +0,0 @@
-/* Copyright (c) 2011, Code Aurora Forum. 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 and
- * only version 2 as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- */
-
-#include <linux/slab.h>
-#include <linux/platform_device.h>
-#include <linux/debugfs.h>
-#include <mach/sdio_al.h>
-#include <mach/sdio_tty.h>
-
-#define SDIO_TTY_DEV "sdio_tty_ciq_0"
-#define SDIO_CIQ "sdio_ciq"
-#define SDIO_TTY_DEV_TEST "sdio_tty_ciq_test_0"
-#define TTY_CIQ_MODULE_NAME "sdio_tty_ciq"
-
-struct sdio_tty_ciq {
- void *sdio_tty_handle;
-};
-
-static struct sdio_tty_ciq sdio_tty_ciq;
-
-/*
- * Enable sdio_tty debug messages
- * By default the sdio_tty debug messages are turned off
- */
-static int debug_msg_on;
-module_param(debug_msg_on, int, 0);
-
-static int sdio_tty_probe(struct platform_device *pdev)
-{
- sdio_tty_ciq.sdio_tty_handle = sdio_tty_init_tty(SDIO_TTY_DEV,
- "SDIO_CIQ");
- if (!sdio_tty_ciq.sdio_tty_handle) {
- pr_err(TTY_CIQ_MODULE_NAME ": %s: NULL sdio_tty_handle",
- __func__);
- return -ENODEV;
- }
-
- if (debug_msg_on)
- sdio_tty_enable_debug_msg(sdio_tty_ciq.sdio_tty_handle,
- debug_msg_on);
-
- return 0;
-}
-
-static int sdio_tty_test_probe(struct platform_device *pdev)
-{
- sdio_tty_ciq.sdio_tty_handle = sdio_tty_init_tty(SDIO_TTY_DEV_TEST,
- "SDIO_CIQ");
- if (!sdio_tty_ciq.sdio_tty_handle) {
- pr_err(TTY_CIQ_MODULE_NAME ": %s: NULL sdio_tty_handle",
- __func__);
- return -ENODEV;
- }
-
- if (debug_msg_on)
- sdio_tty_enable_debug_msg(sdio_tty_ciq.sdio_tty_handle,
- debug_msg_on);
-
- return 0;
-}
-
-static int sdio_tty_remove(struct platform_device *pdev)
-{
- int ret = 0;
-
- pr_info(TTY_CIQ_MODULE_NAME ": %s", __func__);
- ret = sdio_tty_uninit_tty(sdio_tty_ciq.sdio_tty_handle);
- if (ret) {
- pr_err(TTY_CIQ_MODULE_NAME ": %s: sdio_tty_uninit_tty failed",
- __func__);
- return ret;
- }
-
- return 0;
-}
-
-static struct platform_driver sdio_tty_pdrv = {
- .probe = sdio_tty_probe,
- .remove = sdio_tty_remove,
- .driver = {
- .name = "SDIO_CIQ",
- .owner = THIS_MODULE,
- },
-};
-
-static struct platform_driver sdio_tty_test_pdrv = {
- .probe = sdio_tty_test_probe,
- .remove = sdio_tty_remove,
- .driver = {
- .name = "SDIO_CIQ_TEST_APP",
- .owner = THIS_MODULE,
- },
-};
-
-static int __init sdio_tty_ciq_init(void)
-{
- int ret = 0;
-
- ret = platform_driver_register(&sdio_tty_pdrv);
- if (ret) {
- pr_err(TTY_CIQ_MODULE_NAME ": %s: platform_driver_register "
- "failed", __func__);
- return ret;
- }
- return platform_driver_register(&sdio_tty_test_pdrv);
-};
-
-/*
- * Module Exit.
- *
- * Unregister SDIO driver.
- *
- */
-static void __exit sdio_tty_ciq_exit(void)
-{
- platform_driver_unregister(&sdio_tty_pdrv);
- platform_driver_unregister(&sdio_tty_test_pdrv);
-}
-
-module_init(sdio_tty_ciq_init);
-module_exit(sdio_tty_ciq_exit);
-
-MODULE_DESCRIPTION("SDIO TTY CIQ");
-MODULE_LICENSE("GPL v2");
-MODULE_AUTHOR("Maya Erez <merez@codeaurora.org>");
diff --git a/arch/arm/mach-msm/smd.c b/arch/arm/mach-msm/smd.c
index e794801..691dad2 100644
--- a/arch/arm/mach-msm/smd.c
+++ b/arch/arm/mach-msm/smd.c
@@ -660,9 +660,11 @@
if (smsm_info.state) {
writel_relaxed(0, SMSM_STATE_ADDR(restart_pid));
- /* clear apps SMSM to restart SMSM init handshake */
- if (restart_pid == SMSM_MODEM)
- writel_relaxed(0, SMSM_STATE_ADDR(SMSM_APPS));
+ /* restart SMSM init handshake */
+ if (restart_pid == SMSM_MODEM) {
+ smsm_change_state(SMSM_APPS_STATE,
+ SMSM_INIT | SMSM_SMD_LOOPBACK, 0);
+ }
/* notify SMSM processors */
smsm_irq_handler(0, 0);
@@ -2541,8 +2543,10 @@
void *data);
static struct restart_notifier_block restart_notifiers[] = {
- {SMSM_MODEM, "modem", .nb.notifier_call = restart_notifier_cb},
- {SMSM_Q6, "lpass", .nb.notifier_call = restart_notifier_cb},
+ {SMD_MODEM, "modem", .nb.notifier_call = restart_notifier_cb},
+ {SMD_Q6, "lpass", .nb.notifier_call = restart_notifier_cb},
+ {SMD_WCNSS, "riva", .nb.notifier_call = restart_notifier_cb},
+ {SMD_DSPS, "dsps", .nb.notifier_call = restart_notifier_cb},
};
static int restart_notifier_cb(struct notifier_block *this,
diff --git a/arch/arm/mach-msm/socinfo.c b/arch/arm/mach-msm/socinfo.c
index c4bc76c..87b6d3f 100644
--- a/arch/arm/mach-msm/socinfo.c
+++ b/arch/arm/mach-msm/socinfo.c
@@ -217,6 +217,13 @@
/* 8930 IDs */
[116] = MSM_CPU_8930,
+ [117] = MSM_CPU_8930,
+ [118] = MSM_CPU_8930,
+ [119] = MSM_CPU_8930,
+
+ /* 8627 IDs */
+ [120] = MSM_CPU_8627,
+ [121] = MSM_CPU_8627,
/* 8660A ID */
[122] = MSM_CPU_8960,
diff --git a/arch/arm/mach-msm/timer.c b/arch/arm/mach-msm/timer.c
index 9647646..f076a10 100644
--- a/arch/arm/mach-msm/timer.c
+++ b/arch/arm/mach-msm/timer.c
@@ -1020,12 +1020,13 @@
gpt->freq = 32765;
gpt_hz = 32765;
sclk_hz = 32765;
- gpt->flags |= MSM_CLOCK_FLAGS_UNSTABLE_COUNT;
- dgt->flags |= MSM_CLOCK_FLAGS_UNSTABLE_COUNT;
+ if (!machine_is_apq8064_rumi3()) {
+ gpt->flags |= MSM_CLOCK_FLAGS_UNSTABLE_COUNT;
+ dgt->flags |= MSM_CLOCK_FLAGS_UNSTABLE_COUNT;
+ }
} else {
WARN_ON("Timer running on unknown hardware. Configure this! "
"Assuming default configuration.\n");
- global_timer_offset = MSM_TMR0_BASE - MSM_TMR_BASE;
dgt->freq = 6750000;
}
diff --git a/arch/arm/mach-msm/vreg.c b/arch/arm/mach-msm/vreg.c
index 8f782a9..cffa5c7 100644
--- a/arch/arm/mach-msm/vreg.c
+++ b/arch/arm/mach-msm/vreg.c
@@ -18,7 +18,12 @@
#include <linux/kernel.h>
#include <linux/device.h>
#include <linux/init.h>
+#include <linux/slab.h>
+#include <linux/list.h>
+#include <linux/mutex.h>
+#include <linux/atomic.h>
#include <linux/debugfs.h>
+#include <linux/regulator/consumer.h>
#include <linux/string.h>
#include <mach/vreg.h>
@@ -33,173 +38,187 @@
#endif
struct vreg {
- const char *name;
- unsigned id;
- int status;
- unsigned refcnt;
+ struct list_head list;
+ struct mutex lock;
+ const char *name;
+ u64 refcnt;
+ unsigned mv;
+ struct regulator *reg;
};
-#define VREG(_name, _id, _status, _refcnt) \
- { .name = _name, .id = _id, .status = _status, .refcnt = _refcnt }
+static LIST_HEAD(vreg_list);
+static DEFINE_MUTEX(vreg_lock);
-static struct vreg vregs[] = {
- VREG("msma", 0, 0, 0),
- VREG("msmp", 1, 0, 0),
- VREG("msme1", 2, 0, 0),
- VREG("msmc1", 3, 0, 0),
- VREG("msmc2", 4, 0, 0),
- VREG("gp3", 5, 0, 0),
- VREG("msme2", 6, 0, 0),
- VREG("gp4", 7, 0, 0),
- VREG("gp1", 8, 0, 0),
- VREG("tcxo", 9, 0, 0),
- VREG("pa", 10, 0, 0),
- VREG("rftx", 11, 0, 0),
- VREG("rfrx1", 12, 0, 0),
- VREG("rfrx2", 13, 0, 0),
- VREG("synt", 14, 0, 0),
- VREG("wlan", 15, 0, 0),
- VREG("usb", 16, 0, 0),
- VREG("boost", 17, 0, 0),
- VREG("mmc", 18, 0, 0),
- VREG("ruim", 19, 0, 0),
- VREG("msmc0", 20, 0, 0),
- VREG("gp2", 21, 0, 0),
- VREG("gp5", 22, 0, 0),
- VREG("gp6", 23, 0, 0),
- VREG("rf", 24, 0, 0),
- VREG("rf_vco", 26, 0, 0),
- VREG("mpll", 27, 0, 0),
- VREG("s2", 28, 0, 0),
- VREG("s3", 29, 0, 0),
- VREG("rfubm", 30, 0, 0),
- VREG("ncp", 31, 0, 0),
- VREG("gp7", 32, 0, 0),
- VREG("gp8", 33, 0, 0),
- VREG("gp9", 34, 0, 0),
- VREG("gp10", 35, 0, 0),
- VREG("gp11", 36, 0, 0),
- VREG("gp12", 37, 0, 0),
- VREG("gp13", 38, 0, 0),
- VREG("gp14", 39, 0, 0),
- VREG("gp15", 40, 0, 0),
- VREG("gp16", 41, 0, 0),
- VREG("gp17", 42, 0, 0),
- VREG("s4", 43, 0, 0),
- VREG("usb2", 44, 0, 0),
- VREG("wlan2", 45, 0, 0),
- VREG("xo_out", 46, 0, 0),
- VREG("lvsw0", 47, 0, 0),
- VREG("lvsw1", 48, 0, 0),
- VREG("mddi", 49, 0, 0),
- VREG("pllx", 50, 0, 0),
- VREG("wlan3", 51, 0, 0),
- VREG("emmc", 52, 0, 0),
- VREG("wlan_tcx0", 53, 0, 0),
- VREG("usim2", 54, 0, 0),
- VREG("usim", 55, 0, 0),
- VREG("bt", 56, 0, 0),
- VREG("wlan4", 57, 0, 0),
-};
+#ifdef CONFIG_DEBUG_FS
+static void vreg_add_debugfs(struct vreg *vreg);
+#else
+static inline void vreg_add_debugfs(struct vreg *vreg) { }
+#endif
+
+static struct vreg *vreg_create(const char *id)
+{
+ int rc;
+ struct vreg *vreg;
+
+ vreg = kzalloc(sizeof(*vreg), GFP_KERNEL);
+ if (!vreg) {
+ rc = -ENOMEM;
+ goto error;
+ }
+
+ INIT_LIST_HEAD(&vreg->list);
+ mutex_init(&vreg->lock);
+
+ vreg->reg = regulator_get(NULL, id);
+ if (IS_ERR(vreg->reg)) {
+ rc = PTR_ERR(vreg->reg);
+ goto free_vreg;
+ }
+
+ vreg->name = kstrdup(id, GFP_KERNEL);
+ if (!vreg->name) {
+ rc = -ENOMEM;
+ goto put_reg;
+ }
+
+ list_add_tail(&vreg->list, &vreg_list);
+ vreg_add_debugfs(vreg);
+
+ return vreg;
+
+put_reg:
+ regulator_put(vreg->reg);
+free_vreg:
+ kfree(vreg);
+error:
+ return ERR_PTR(rc);
+}
+
+static void vreg_destroy(struct vreg *vreg)
+{
+ if (!vreg)
+ return;
+
+ if (vreg->refcnt)
+ regulator_disable(vreg->reg);
+
+ kfree(vreg->name);
+ regulator_put(vreg->reg);
+ kfree(vreg);
+}
struct vreg *vreg_get(struct device *dev, const char *id)
{
- int n;
- for (n = 0; n < ARRAY_SIZE(vregs); n++) {
- if (!strcmp(vregs[n].name, id))
- return vregs + n;
+ struct vreg *vreg = NULL;
+
+ if (!id)
+ return ERR_PTR(-EINVAL);
+
+ mutex_lock(&vreg_lock);
+ list_for_each_entry(vreg, &vreg_list, list) {
+ if (!strncmp(vreg->name, id, 10))
+ goto ret;
}
- return ERR_PTR(-ENOENT);
+
+ vreg = vreg_create(id);
+
+ret:
+ mutex_unlock(&vreg_lock);
+ return vreg;
}
EXPORT_SYMBOL(vreg_get);
void vreg_put(struct vreg *vreg)
{
+ kfree(vreg->name);
+ regulator_put(vreg->reg);
}
int vreg_enable(struct vreg *vreg)
{
- unsigned id = vreg->id;
- int enable = VREG_SWITCH_ENABLE;
+ int rc = 0;
+ if (!vreg)
+ return -ENODEV;
- if (vreg->refcnt == 0)
- vreg->status = msm_proc_comm(PCOM_VREG_SWITCH, &id, &enable);
+ mutex_lock(&vreg->lock);
+ if (vreg->refcnt == 0) {
+ rc = regulator_enable(vreg->reg);
+ if (!rc)
+ vreg->refcnt++;
+ } else {
+ rc = 0;
+ if (vreg->refcnt < UINT_MAX)
+ vreg->refcnt++;
+ }
+ mutex_unlock(&vreg->lock);
- if ((vreg->refcnt < UINT_MAX) && (!vreg->status))
- vreg->refcnt++;
-
- return vreg->status;
+ return rc;
}
EXPORT_SYMBOL(vreg_enable);
int vreg_disable(struct vreg *vreg)
{
- unsigned id = vreg->id;
- int disable = VREG_SWITCH_DISABLE;
+ int rc = 0;
+ if (!vreg)
+ return -ENODEV;
- if (!vreg->refcnt)
- return 0;
-
- if (vreg->refcnt == 1)
- vreg->status = msm_proc_comm(PCOM_VREG_SWITCH, &id, &disable);
-
- if (!vreg->status)
+ mutex_lock(&vreg->lock);
+ if (vreg->refcnt == 0) {
+ pr_warn("%s: unbalanced disables for vreg %s\n",
+ __func__, vreg->name);
+ rc = -EINVAL;
+ } else if (vreg->refcnt == 1) {
+ rc = regulator_disable(vreg->reg);
+ if (!rc)
+ vreg->refcnt--;
+ } else {
+ rc = 0;
vreg->refcnt--;
+ }
+ mutex_unlock(&vreg->lock);
- return vreg->status;
+ return rc;
}
EXPORT_SYMBOL(vreg_disable);
int vreg_set_level(struct vreg *vreg, unsigned mv)
{
- unsigned id = vreg->id;
+ unsigned uv;
+ int rc;
- vreg->status = msm_proc_comm(PCOM_VREG_SET_LEVEL, &id, &mv);
- return vreg->status;
+ if (!vreg)
+ return -EINVAL;
+
+ if (mv > (UINT_MAX / 1000))
+ return -ERANGE;
+
+ uv = mv * 1000;
+
+ mutex_lock(&vreg->lock);
+ rc = regulator_set_voltage(vreg->reg, uv, uv);
+ if (!rc)
+ vreg->mv = mv;
+ mutex_unlock(&vreg->lock);
+
+ return rc;
}
EXPORT_SYMBOL(vreg_set_level);
#if defined(CONFIG_DEBUG_FS)
-static int vreg_debug_set(void *data, u64 val)
-{
- struct vreg *vreg = data;
- switch (val) {
- case 0:
- vreg_disable(vreg);
- break;
- case 1:
- vreg_enable(vreg);
- break;
- default:
- vreg_set_level(vreg, val);
- break;
- }
- return 0;
-}
-
-static int vreg_debug_get(void *data, u64 *val)
+static int vreg_debug_enabled_set(void *data, u64 val)
{
struct vreg *vreg = data;
- if (!vreg->status)
- *val = 0;
+ if (val == 0)
+ return vreg_disable(vreg);
+ else if (val == 1)
+ return vreg_enable(vreg);
else
- *val = 1;
-
- return 0;
+ return -EINVAL;
}
-static int vreg_debug_count_set(void *data, u64 val)
-{
- struct vreg *vreg = data;
- if (val > UINT_MAX)
- val = UINT_MAX;
- vreg->refcnt = val;
- return 0;
-}
-
-static int vreg_debug_count_get(void *data, u64 *val)
+static int vreg_debug_enabled_get(void *data, u64 *val)
{
struct vreg *vreg = data;
@@ -208,33 +227,97 @@
return 0;
}
-DEFINE_SIMPLE_ATTRIBUTE(vreg_fops, vreg_debug_get, vreg_debug_set, "%llu\n");
-DEFINE_SIMPLE_ATTRIBUTE(vreg_count_fops, vreg_debug_count_get,
- vreg_debug_count_set, "%llu\n");
-
-static int __init vreg_debug_init(void)
+static int vreg_debug_voltage_set(void *data, u64 val)
{
- struct dentry *dent;
- int n;
- char name[32];
- const char *refcnt_name = "_refcnt";
+ struct vreg *vreg = data;
+ return vreg_set_level(vreg, val);
+}
- dent = debugfs_create_dir("vreg", 0);
- if (IS_ERR(dent))
- return 0;
+static int vreg_debug_voltage_get(void *data, u64 *val)
+{
+ struct vreg *vreg = data;
+ *val = vreg->mv;
+ return 0;
+}
- for (n = 0; n < ARRAY_SIZE(vregs); n++) {
- (void) debugfs_create_file(vregs[n].name, 0644,
- dent, vregs + n, &vreg_fops);
+DEFINE_SIMPLE_ATTRIBUTE(vreg_debug_enabled, vreg_debug_enabled_get,
+ vreg_debug_enabled_set, "%llu");
+DEFINE_SIMPLE_ATTRIBUTE(vreg_debug_voltage, vreg_debug_voltage_get,
+ vreg_debug_voltage_set, "%llu");
- strlcpy(name, vregs[n].name, sizeof(name));
- strlcat(name, refcnt_name, sizeof(name));
- (void) debugfs_create_file(name, 0644,
- dent, vregs + n, &vreg_count_fops);
+static struct dentry *root;
+
+static void vreg_add_debugfs(struct vreg *vreg)
+{
+ struct dentry *dir;
+
+ if (!root)
+ return;
+
+ dir = debugfs_create_dir(vreg->name, root);
+
+ if (IS_ERR_OR_NULL(dir))
+ goto err;
+
+ if (IS_ERR_OR_NULL(debugfs_create_file("enabled", 0644, dir, vreg,
+ &vreg_debug_enabled)))
+ goto destroy;
+
+ if (IS_ERR_OR_NULL(debugfs_create_file("voltage", 0644, dir, vreg,
+ &vreg_debug_voltage)))
+ goto destroy;
+
+ return;
+
+destroy:
+ debugfs_remove_recursive(dir);
+err:
+ pr_warn("%s: could not create debugfs for vreg %s\n",
+ __func__, vreg->name);
+}
+
+static int __devinit vreg_debug_init(void)
+{
+ root = debugfs_create_dir("vreg", NULL);
+
+ if (IS_ERR_OR_NULL(root)) {
+ pr_debug("%s: error initializing debugfs: %ld - "
+ "disabling debugfs\n",
+ __func__, root ? PTR_ERR(root) : 0);
+ root = NULL;
}
return 0;
}
-
-device_initcall(vreg_debug_init);
+static void __devexit vreg_debug_exit(void)
+{
+ if (root)
+ debugfs_remove_recursive(root);
+ root = NULL;
+}
+#else
+static inline int __init vreg_debug_init(void) { return 0; }
+static inline void __exit vreg_debug_exit(void) { return 0; }
#endif
+
+static int __init vreg_init(void)
+{
+ return vreg_debug_init();
+}
+module_init(vreg_init);
+
+static void __exit vreg_exit(void)
+{
+ struct vreg *vreg, *next;
+ vreg_debug_exit();
+
+ mutex_lock(&vreg_lock);
+ list_for_each_entry_safe(vreg, next, &vreg_list, list)
+ vreg_destroy(vreg);
+ mutex_unlock(&vreg_lock);
+}
+module_exit(vreg_exit);
+
+MODULE_LICENSE("GPL v2");
+MODULE_DESCRIPTION("vreg.c regulator shim");
+MODULE_VERSION("1.0");
diff --git a/arch/arm/mach-shark/leds.c b/arch/arm/mach-shark/leds.c
index c9e32de..ccd4918 100644
--- a/arch/arm/mach-shark/leds.c
+++ b/arch/arm/mach-shark/leds.c
@@ -36,7 +36,7 @@
static short hw_led_state;
static short saved_state;
-static DEFINE_SPINLOCK(leds_lock);
+static DEFINE_RAW_SPINLOCK(leds_lock);
short sequoia_read(int addr) {
outw(addr,0x24);
@@ -52,7 +52,7 @@
{
unsigned long flags;
- spin_lock_irqsave(&leds_lock, flags);
+ raw_spin_lock_irqsave(&leds_lock, flags);
hw_led_state = sequoia_read(0x09);
@@ -144,7 +144,7 @@
if (led_state & LED_STATE_ENABLED)
sequoia_write(hw_led_state,0x09);
- spin_unlock_irqrestore(&leds_lock, flags);
+ raw_spin_unlock_irqrestore(&leds_lock, flags);
}
static int __init leds_init(void)
diff --git a/arch/arm/mm/cache-l2x0.c b/arch/arm/mm/cache-l2x0.c
index 7aacb84..bc5ffce 100644
--- a/arch/arm/mm/cache-l2x0.c
+++ b/arch/arm/mm/cache-l2x0.c
@@ -29,7 +29,8 @@
static void __iomem *l2x0_base;
static uint32_t aux_ctrl_save;
static uint32_t data_latency_ctrl;
-static DEFINE_SPINLOCK(l2x0_lock);
+static DEFINE_RAW_SPINLOCK(l2x0_lock);
+
static uint32_t l2x0_way_mask; /* Bitmask of active ways */
static uint32_t l2x0_size;
static u32 l2x0_cache_id;
@@ -126,7 +127,11 @@
void l2x0_cache_sync(void)
{
+ unsigned long flags;
+
+ raw_spin_lock_irqsave(&l2x0_lock, flags);
cache_sync();
+ raw_spin_unlock_irqrestore(&l2x0_lock, flags);
}
#ifdef CONFIG_PL310_ERRATA_727915
@@ -167,9 +172,9 @@
#endif
/* clean all ways */
- spin_lock_irqsave(&l2x0_lock, flags);
+ raw_spin_lock_irqsave(&l2x0_lock, flags);
__l2x0_flush_all();
- spin_unlock_irqrestore(&l2x0_lock, flags);
+ raw_spin_unlock_irqrestore(&l2x0_lock, flags);
}
static void l2x0_clean_all(void)
@@ -184,13 +189,13 @@
#endif
/* clean all ways */
- spin_lock_irqsave(&l2x0_lock, flags);
+ raw_spin_lock_irqsave(&l2x0_lock, flags);
debug_writel(0x03);
writel_relaxed(l2x0_way_mask, l2x0_base + L2X0_CLEAN_WAY);
cache_wait_way(l2x0_base + L2X0_CLEAN_WAY, l2x0_way_mask);
cache_sync();
debug_writel(0x00);
- spin_unlock_irqrestore(&l2x0_lock, flags);
+ raw_spin_unlock_irqrestore(&l2x0_lock, flags);
}
static void l2x0_inv_all(void)
@@ -198,13 +203,13 @@
unsigned long flags;
/* invalidate all ways */
- spin_lock_irqsave(&l2x0_lock, flags);
+ raw_spin_lock_irqsave(&l2x0_lock, flags);
/* Invalidating when L2 is enabled is a nono */
BUG_ON(readl(l2x0_base + L2X0_CTRL) & 1);
writel_relaxed(l2x0_way_mask, l2x0_base + L2X0_INV_WAY);
cache_wait_way(l2x0_base + L2X0_INV_WAY, l2x0_way_mask);
cache_sync();
- spin_unlock_irqrestore(&l2x0_lock, flags);
+ raw_spin_unlock_irqrestore(&l2x0_lock, flags);
}
static void l2x0_inv_range(unsigned long start, unsigned long end)
@@ -212,7 +217,7 @@
void __iomem *base = l2x0_base;
unsigned long flags;
- spin_lock_irqsave(&l2x0_lock, flags);
+ raw_spin_lock_irqsave(&l2x0_lock, flags);
if (start & (CACHE_LINE_SIZE - 1)) {
start &= ~(CACHE_LINE_SIZE - 1);
debug_writel(0x03);
@@ -237,13 +242,13 @@
}
if (blk_end < end) {
- spin_unlock_irqrestore(&l2x0_lock, flags);
- spin_lock_irqsave(&l2x0_lock, flags);
+ raw_spin_unlock_irqrestore(&l2x0_lock, flags);
+ raw_spin_lock_irqsave(&l2x0_lock, flags);
}
}
cache_wait(base + L2X0_INV_LINE_PA, 1);
cache_sync();
- spin_unlock_irqrestore(&l2x0_lock, flags);
+ raw_spin_unlock_irqrestore(&l2x0_lock, flags);
}
static void l2x0_inv_range_atomic(unsigned long start, unsigned long end)
@@ -277,7 +282,7 @@
return;
}
- spin_lock_irqsave(&l2x0_lock, flags);
+ raw_spin_lock_irqsave(&l2x0_lock, flags);
start &= ~(CACHE_LINE_SIZE - 1);
while (start < end) {
unsigned long blk_end = start + min(end - start, 4096UL);
@@ -288,13 +293,13 @@
}
if (blk_end < end) {
- spin_unlock_irqrestore(&l2x0_lock, flags);
- spin_lock_irqsave(&l2x0_lock, flags);
+ raw_spin_unlock_irqrestore(&l2x0_lock, flags);
+ raw_spin_lock_irqsave(&l2x0_lock, flags);
}
}
cache_wait(base + L2X0_CLEAN_LINE_PA, 1);
cache_sync();
- spin_unlock_irqrestore(&l2x0_lock, flags);
+ raw_spin_unlock_irqrestore(&l2x0_lock, flags);
}
static void l2x0_clean_range_atomic(unsigned long start, unsigned long end)
@@ -318,7 +323,7 @@
return;
}
- spin_lock_irqsave(&l2x0_lock, flags);
+ raw_spin_lock_irqsave(&l2x0_lock, flags);
start &= ~(CACHE_LINE_SIZE - 1);
while (start < end) {
unsigned long blk_end = start + min(end - start, 4096UL);
@@ -331,13 +336,13 @@
debug_writel(0x00);
if (blk_end < end) {
- spin_unlock_irqrestore(&l2x0_lock, flags);
- spin_lock_irqsave(&l2x0_lock, flags);
+ raw_spin_unlock_irqrestore(&l2x0_lock, flags);
+ raw_spin_lock_irqsave(&l2x0_lock, flags);
}
}
cache_wait(base + L2X0_CLEAN_INV_LINE_PA, 1);
cache_sync();
- spin_unlock_irqrestore(&l2x0_lock, flags);
+ raw_spin_unlock_irqrestore(&l2x0_lock, flags);
}
void l2x0_flush_range_atomic(unsigned long start, unsigned long end)
@@ -355,11 +360,11 @@
{
unsigned long flags;
- spin_lock_irqsave(&l2x0_lock, flags);
+ raw_spin_lock_irqsave(&l2x0_lock, flags);
__l2x0_flush_all();
writel_relaxed(0, l2x0_base + L2X0_CTRL);
dsb();
- spin_unlock_irqrestore(&l2x0_lock, flags);
+ raw_spin_unlock_irqrestore(&l2x0_lock, flags);
}
void __init l2x0_init(void __iomem *base, __u32 aux_val, __u32 aux_mask)
diff --git a/arch/arm/mm/context.c b/arch/arm/mm/context.c
index b0ee9ba..93aac06 100644
--- a/arch/arm/mm/context.c
+++ b/arch/arm/mm/context.c
@@ -16,7 +16,7 @@
#include <asm/mmu_context.h>
#include <asm/tlbflush.h>
-static DEFINE_SPINLOCK(cpu_asid_lock);
+static DEFINE_RAW_SPINLOCK(cpu_asid_lock);
unsigned int cpu_last_asid = ASID_FIRST_VERSION;
#ifdef CONFIG_SMP
DEFINE_PER_CPU(struct mm_struct *, current_mm);
@@ -31,7 +31,7 @@
void __init_new_context(struct task_struct *tsk, struct mm_struct *mm)
{
mm->context.id = 0;
- spin_lock_init(&mm->context.id_lock);
+ raw_spin_lock_init(&mm->context.id_lock);
}
static void flush_context(void)
@@ -58,7 +58,7 @@
* the broadcast. This function is also called via IPI so the
* mm->context.id_lock has to be IRQ-safe.
*/
- spin_lock_irqsave(&mm->context.id_lock, flags);
+ raw_spin_lock_irqsave(&mm->context.id_lock, flags);
if (likely((mm->context.id ^ cpu_last_asid) >> ASID_BITS)) {
/*
* Old version of ASID found. Set the new one and
@@ -67,7 +67,7 @@
mm->context.id = asid;
cpumask_clear(mm_cpumask(mm));
}
- spin_unlock_irqrestore(&mm->context.id_lock, flags);
+ raw_spin_unlock_irqrestore(&mm->context.id_lock, flags);
/*
* Set the mm_cpumask(mm) bit for the current CPU.
@@ -117,7 +117,7 @@
{
unsigned int asid;
- spin_lock(&cpu_asid_lock);
+ raw_spin_lock(&cpu_asid_lock);
#ifdef CONFIG_SMP
/*
* Check the ASID again, in case the change was broadcast from
@@ -125,7 +125,7 @@
*/
if (unlikely(((mm->context.id ^ cpu_last_asid) >> ASID_BITS) == 0)) {
cpumask_set_cpu(smp_processor_id(), mm_cpumask(mm));
- spin_unlock(&cpu_asid_lock);
+ raw_spin_unlock(&cpu_asid_lock);
return;
}
#endif
@@ -153,5 +153,5 @@
}
set_mm_context(mm, asid);
- spin_unlock(&cpu_asid_lock);
+ raw_spin_unlock(&cpu_asid_lock);
}
diff --git a/arch/arm/mm/copypage-v4mc.c b/arch/arm/mm/copypage-v4mc.c
index b806151..7d0a8c2 100644
--- a/arch/arm/mm/copypage-v4mc.c
+++ b/arch/arm/mm/copypage-v4mc.c
@@ -30,7 +30,7 @@
#define minicache_pgprot __pgprot(L_PTE_PRESENT | L_PTE_YOUNG | \
L_PTE_MT_MINICACHE)
-static DEFINE_SPINLOCK(minicache_lock);
+static DEFINE_RAW_SPINLOCK(minicache_lock);
/*
* ARMv4 mini-dcache optimised copy_user_highpage
@@ -76,14 +76,14 @@
if (!test_and_set_bit(PG_dcache_clean, &from->flags))
__flush_dcache_page(page_mapping(from), from);
- spin_lock(&minicache_lock);
+ raw_spin_lock(&minicache_lock);
set_pte_ext(TOP_PTE(0xffff8000), pfn_pte(page_to_pfn(from), minicache_pgprot), 0);
flush_tlb_kernel_page(0xffff8000);
mc_copy_user_page((void *)0xffff8000, kto);
- spin_unlock(&minicache_lock);
+ raw_spin_unlock(&minicache_lock);
kunmap_atomic(kto, KM_USER1);
}
diff --git a/arch/arm/mm/copypage-v6.c b/arch/arm/mm/copypage-v6.c
index bdba6c6..b2a8f9c 100644
--- a/arch/arm/mm/copypage-v6.c
+++ b/arch/arm/mm/copypage-v6.c
@@ -27,7 +27,7 @@
#define from_address (0xffff8000)
#define to_address (0xffffc000)
-static DEFINE_SPINLOCK(v6_lock);
+static DEFINE_RAW_SPINLOCK(v6_lock);
/*
* Copy the user page. No aliasing to deal with so we can just
@@ -89,7 +89,7 @@
* Now copy the page using the same cache colour as the
* pages ultimate destination.
*/
- spin_lock(&v6_lock);
+ raw_spin_lock(&v6_lock);
set_pte_ext(TOP_PTE(from_address) + offset, pfn_pte(page_to_pfn(from), PAGE_KERNEL), 0);
set_pte_ext(TOP_PTE(to_address) + offset, pfn_pte(page_to_pfn(to), PAGE_KERNEL), 0);
@@ -102,7 +102,7 @@
copy_page((void *)kto, (void *)kfrom);
- spin_unlock(&v6_lock);
+ raw_spin_unlock(&v6_lock);
}
/*
@@ -122,13 +122,13 @@
* Now clear the page using the same cache colour as
* the pages ultimate destination.
*/
- spin_lock(&v6_lock);
+ raw_spin_lock(&v6_lock);
set_pte_ext(TOP_PTE(to_address) + offset, pfn_pte(page_to_pfn(page), PAGE_KERNEL), 0);
flush_tlb_kernel_page(to);
clear_page((void *)to);
- spin_unlock(&v6_lock);
+ raw_spin_unlock(&v6_lock);
}
struct cpu_user_fns v6_user_fns __initdata = {
diff --git a/arch/arm/mm/copypage-xscale.c b/arch/arm/mm/copypage-xscale.c
index 649bbcd..610c24c 100644
--- a/arch/arm/mm/copypage-xscale.c
+++ b/arch/arm/mm/copypage-xscale.c
@@ -32,7 +32,7 @@
#define minicache_pgprot __pgprot(L_PTE_PRESENT | L_PTE_YOUNG | \
L_PTE_MT_MINICACHE)
-static DEFINE_SPINLOCK(minicache_lock);
+static DEFINE_RAW_SPINLOCK(minicache_lock);
/*
* XScale mini-dcache optimised copy_user_highpage
@@ -98,14 +98,14 @@
if (!test_and_set_bit(PG_dcache_clean, &from->flags))
__flush_dcache_page(page_mapping(from), from);
- spin_lock(&minicache_lock);
+ raw_spin_lock(&minicache_lock);
set_pte_ext(TOP_PTE(COPYPAGE_MINICACHE), pfn_pte(page_to_pfn(from), minicache_pgprot), 0);
flush_tlb_kernel_page(COPYPAGE_MINICACHE);
mc_copy_user_page((void *)COPYPAGE_MINICACHE, kto);
- spin_unlock(&minicache_lock);
+ raw_spin_unlock(&minicache_lock);
kunmap_atomic(kto, KM_USER1);
}
diff --git a/arch/arm/mm/init.c b/arch/arm/mm/init.c
index 5739a34..e5e3486 100644
--- a/arch/arm/mm/init.c
+++ b/arch/arm/mm/init.c
@@ -637,6 +637,9 @@
extern u32 dtcm_end;
extern u32 itcm_end;
#endif
+#ifdef CONFIG_FIX_MOVABLE_ZONE
+ struct zone *zone;
+#endif
max_mapnr = pfn_to_page(max_pfn + PHYS_PFN_OFFSET) - mem_map;
@@ -682,6 +685,14 @@
#endif
}
+#ifdef CONFIG_FIX_MOVABLE_ZONE
+ for_each_zone(zone) {
+ if (zone_idx(zone) == ZONE_MOVABLE)
+ total_unmovable_pages = totalram_pages -
+ zone->spanned_pages;
+ }
+#endif
+
/*
* Since our memory may not be contiguous, calculate the
* real number of pages we have in this system
@@ -784,6 +795,7 @@
void free_initmem(void)
{
+ unsigned long reclaimed_initmem;
#ifdef CONFIG_HAVE_TCM
extern char __tcm_start, __tcm_end;
@@ -792,10 +804,15 @@
"TCM link");
#endif
- if (!machine_is_integrator() && !machine_is_cintegrator())
- totalram_pages += free_area(__phys_to_pfn(__pa(__init_begin)),
+ if (!machine_is_integrator() && !machine_is_cintegrator()) {
+ reclaimed_initmem = free_area(__phys_to_pfn(__pa(__init_begin)),
__phys_to_pfn(__pa(__init_end)),
"init");
+ totalram_pages += reclaimed_initmem;
+#ifdef CONFIG_FIX_MOVABLE_ZONE
+ total_unmovable_pages += reclaimed_initmem;
+#endif
+ }
}
#ifdef CONFIG_MEMORY_HOTPLUG
@@ -831,10 +848,16 @@
void free_initrd_mem(unsigned long start, unsigned long end)
{
- if (!keep_initrd)
- totalram_pages += free_area(__phys_to_pfn(__pa(start)),
+ unsigned long reclaimed_initrd_mem;
+ if (!keep_initrd) {
+ reclaimed_initrd_mem = free_area(__phys_to_pfn(__pa(start)),
__phys_to_pfn(__pa(end)),
"initrd");
+ totalram_pages += reclaimed_initrd_mem;
+#ifdef CONFIG_FIX_MOVABLE_ZONE
+ total_unmovable_pages += reclaimed_initrd_mem;
+#endif
+ }
}
static int __init keepinitrd_setup(char *__unused)
diff --git a/arch/arm/mm/mmu.c b/arch/arm/mm/mmu.c
index 84a7e5c..0f79b76 100644
--- a/arch/arm/mm/mmu.c
+++ b/arch/arm/mm/mmu.c
@@ -1124,6 +1124,20 @@
}
#endif
+void mem_text_write_kernel_word(unsigned long *addr, unsigned long word)
+{
+ unsigned long flags;
+
+ mem_text_writeable_spinlock(&flags);
+ mem_text_address_writeable((unsigned long)addr);
+ *addr = word;
+ flush_icache_range((unsigned long)addr,
+ ((unsigned long)addr + sizeof(long)));
+ mem_text_address_restore();
+ mem_text_writeable_spinunlock(&flags);
+}
+EXPORT_SYMBOL(mem_text_write_kernel_word);
+
static void __init map_lowmem(void)
{
struct memblock_region *reg;
diff --git a/arch/arm/mm/proc-v7.S b/arch/arm/mm/proc-v7.S
index 46729ee..5943005 100644
--- a/arch/arm/mm/proc-v7.S
+++ b/arch/arm/mm/proc-v7.S
@@ -219,7 +219,11 @@
* NOS = PRRR[24+n] = 1 - not outer shareable
*/
.equ PRRR, 0xff0a81a8
+#if defined (CONFIG_ARCH_MSM_SCORPIONMP)
+.equ NMRR, 0x40e080e0
+#else
.equ NMRR, 0x40e040e0
+#endif
/* Suspend/resume support: derived from arch/arm/mach-s5pv210/sleep.S */
.globl cpu_v7_suspend_size
diff --git a/arch/arm/vfp/vfpmodule.c b/arch/arm/vfp/vfpmodule.c
index e7fc95c..d25fabf 100644
--- a/arch/arm/vfp/vfpmodule.c
+++ b/arch/arm/vfp/vfpmodule.c
@@ -629,7 +629,9 @@
if ((fmrx(MVFR1) & 0x000fff00) == 0x00011100)
elf_hwcap |= HWCAP_NEON;
#endif
- if ((fmrx(MVFR1) & 0xf0000000) == 0x10000000)
+
+ if ((fmrx(MVFR1) & 0xf0000000) == 0x10000000 ||
+ (read_cpuid_id() & 0xff00fc00) == 0x51000400)
elf_hwcap |= HWCAP_VFPv4;
}
}
diff --git a/drivers/base/genlock.c b/drivers/base/genlock.c
index 40b9575..41bbd3a 100644
--- a/drivers/base/genlock.c
+++ b/drivers/base/genlock.c
@@ -37,6 +37,7 @@
wait_queue_head_t queue; /* Holding pen for processes pending lock */
struct file *file; /* File structure for exported lock */
int state; /* Current state of the lock */
+ struct kref refcount;
};
struct genlock_handle {
@@ -47,6 +48,14 @@
taken */
};
+static void genlock_destroy(struct kref *kref)
+{
+ struct genlock *lock = container_of(kref, struct genlock,
+ refcount);
+
+ kfree(lock);
+}
+
/*
* Release the genlock object. Called when all the references to
* the genlock file descriptor are released
@@ -54,7 +63,6 @@
static int genlock_release(struct inode *inodep, struct file *file)
{
- kfree(file->private_data);
return 0;
}
@@ -96,6 +104,7 @@
/* Attach the new lock to the handle */
handle->lock = lock;
+ kref_init(&lock->refcount);
return lock;
}
@@ -131,6 +140,7 @@
struct genlock *genlock_attach_lock(struct genlock_handle *handle, int fd)
{
struct file *file;
+ struct genlock *lock;
if (handle->lock != NULL)
return ERR_PTR(-EINVAL);
@@ -139,9 +149,17 @@
if (file == NULL)
return ERR_PTR(-EBADF);
- handle->lock = file->private_data;
+ lock = file->private_data;
- return handle->lock;
+ fput(file);
+
+ if (lock == NULL)
+ return ERR_PTR(-EINVAL);
+
+ handle->lock = lock;
+ kref_get(&lock->refcount);
+
+ return lock;
}
EXPORT_SYMBOL(genlock_attach_lock);
@@ -418,7 +436,7 @@
}
spin_unlock_irqrestore(&handle->lock->lock, flags);
- fput(handle->lock->file);
+ kref_put(&handle->lock->refcount, genlock_destroy);
handle->lock = NULL;
handle->active = 0;
}
@@ -575,7 +593,8 @@
{
struct genlock_handle *handle = file->private_data;
- genlock_put_handle(handle);
+ genlock_release_lock(handle);
+ kfree(handle);
return 0;
}
diff --git a/drivers/bluetooth/hci_smd.c b/drivers/bluetooth/hci_smd.c
index 118bbb3..a321849 100644
--- a/drivers/bluetooth/hci_smd.c
+++ b/drivers/bluetooth/hci_smd.c
@@ -140,20 +140,20 @@
wake_lock(&hs.wake_lock_rx);
len = smd_read_avail(hsmd->data_channel);
- if (len <= 0) {
- BT_ERR("Nothing to read from SMD channel\n");
+ if (len > HCI_MAX_FRAME_SIZE) {
+ BT_ERR("Frame larger than the allowed size");
goto out_data;
}
while (len > 0) {
skb = bt_skb_alloc(len, GFP_ATOMIC);
if (!skb) {
- BT_ERR("Error in allocating socket buffer\n");
+ BT_ERR("Error in allocating socket buffer");
goto out_data;
}
buf = kmalloc(len, GFP_ATOMIC);
if (!buf) {
- BT_ERR("Error in allocating buffer\n");
+ BT_ERR("Error in allocating buffer");
rc = -ENOMEM;
goto out_data;
}
@@ -188,7 +188,7 @@
* Start the timer to monitor whether the Rx queue is
* empty for releasing the Rx wake lock
*/
- BT_DBG("Rx Timer is starting\n");
+ BT_DBG("Rx Timer is starting");
mod_timer(&hsmd->rx_q_timer,
jiffies + msecs_to_jiffies(RX_Q_MONITOR));
}
@@ -214,20 +214,17 @@
if (len > HCI_MAX_FRAME_SIZE) {
BT_ERR("Frame larger than the allowed size");
goto out_event;
- } else if (len <= 0) {
- BT_ERR("Nothing to read from SMD channel\n");
- goto out_event;
}
while (len > 0) {
skb = bt_skb_alloc(len, GFP_ATOMIC);
if (!skb) {
- BT_ERR("Error in allocating socket buffer\n");
+ BT_ERR("Error in allocating socket buffer");
goto out_event;
}
buf = kmalloc(len, GFP_ATOMIC);
if (!buf) {
- BT_ERR("Error in allocating buffer\n");
+ BT_ERR("Error in allocating buffer");
rc = -ENOMEM;
goto out_event;
}
@@ -261,7 +258,7 @@
* Start the timer to monitor whether the Rx queue is
* empty for releasing the Rx wake lock
*/
- BT_DBG("Rx Timer is starting\n");
+ BT_DBG("Rx Timer is starting");
mod_timer(&hsmd->rx_q_timer,
jiffies + msecs_to_jiffies(RX_Q_MONITOR));
}
@@ -308,7 +305,7 @@
}
break;
default:
- BT_ERR("Uknown packet type\n");
+ BT_ERR("Uknown packet type");
ret = -ENODEV;
break;
}
@@ -322,6 +319,8 @@
static void hci_smd_notify_event(void *data, unsigned int event)
{
struct hci_dev *hdev = hs.hdev;
+ struct hci_smd_data *hsmd = &hs;
+ int len = 0;
if (!hdev) {
BT_ERR("Frame for unknown HCI device (hdev=NULL)");
@@ -330,12 +329,19 @@
switch (event) {
case SMD_EVENT_DATA:
- tasklet_hi_schedule(&hs.hci_event_task);
+ len = smd_read_avail(hsmd->event_channel);
+ if (len > 0)
+ tasklet_hi_schedule(&hs.hci_event_task);
+ else if (len < 0)
+ BT_ERR("Failed to read event from smd %d", len);
+
break;
case SMD_EVENT_OPEN:
+ BT_INFO("opening HCI-SMD channel :%s", EVENT_CHANNEL);
hci_smd_open(hdev);
break;
case SMD_EVENT_CLOSE:
+ BT_INFO("Closing HCI-SMD channel :%s", EVENT_CHANNEL);
hci_smd_close(hdev);
break;
default:
@@ -346,6 +352,9 @@
static void hci_smd_notify_data(void *data, unsigned int event)
{
struct hci_dev *hdev = hs.hdev;
+ struct hci_smd_data *hsmd = &hs;
+ int len = 0;
+
if (!hdev) {
BT_ERR("HCI device (hdev=NULL)");
return;
@@ -353,12 +362,18 @@
switch (event) {
case SMD_EVENT_DATA:
- tasklet_hi_schedule(&hs.hci_data_task);
+ len = smd_read_avail(hsmd->data_channel);
+ if (len > 0)
+ tasklet_hi_schedule(&hs.hci_data_task);
+ else if (len < 0)
+ BT_ERR("Failed to read data from smd %d", len);
break;
case SMD_EVENT_OPEN:
+ BT_INFO("opening HCI-SMD channel :%s", DATA_CHANNEL);
hci_smd_open(hdev);
break;
case SMD_EVENT_CLOSE:
+ BT_INFO("Closing HCI-SMD channel :%s", DATA_CHANNEL);
hci_smd_close(hdev);
break;
default:
@@ -419,7 +434,7 @@
rc = smd_named_open_on_edge(DATA_CHANNEL, SMD_APPS_WCNSS,
&hsmd->data_channel, hdev, hci_smd_notify_data);
if (rc < 0) {
- BT_ERR("Failed to open the Data channel\n");
+ BT_ERR("Failed to open the Data channel");
hci_free_dev(hdev);
return -ENODEV;
}
diff --git a/drivers/gpu/ion/Makefile b/drivers/gpu/ion/Makefile
index c0a47d8..3911950 100644
--- a/drivers/gpu/ion/Makefile
+++ b/drivers/gpu/ion/Makefile
@@ -1,3 +1,3 @@
-obj-$(CONFIG_ION) += ion.o ion_heap.o ion_system_heap.o ion_carveout_heap.o
+obj-$(CONFIG_ION) += ion.o ion_heap.o ion_system_heap.o ion_carveout_heap.o ion_iommu_heap.o
obj-$(CONFIG_ION_TEGRA) += tegra/
obj-$(CONFIG_ION_MSM) += msm/
diff --git a/drivers/gpu/ion/ion.c b/drivers/gpu/ion/ion.c
index 48dc9c0..e659df5 100644
--- a/drivers/gpu/ion/ion.c
+++ b/drivers/gpu/ion/ion.c
@@ -30,6 +30,7 @@
#include <linux/uaccess.h>
#include <linux/debugfs.h>
+#include <mach/iommu_domains.h>
#include "ion_priv.h"
#define DEBUG
@@ -102,8 +103,27 @@
unsigned int kmap_cnt;
unsigned int dmap_cnt;
unsigned int usermap_cnt;
+ unsigned int iommu_map_cnt;
};
+static int ion_validate_buffer_flags(struct ion_buffer *buffer,
+ unsigned long flags)
+{
+ if (buffer->kmap_cnt || buffer->dmap_cnt || buffer->umap_cnt ||
+ buffer->iommu_map_cnt) {
+ if (buffer->flags != flags) {
+ pr_err("%s: buffer was already mapped with flags %lx,"
+ " cannot map with flags %lx\n", __func__,
+ buffer->flags, flags);
+ return 1;
+ }
+
+ } else {
+ buffer->flags = flags;
+ }
+ return 0;
+}
+
/* this function should only be called while dev->lock is held */
static void ion_buffer_add(struct ion_device *dev,
struct ion_buffer *buffer)
@@ -130,6 +150,61 @@
rb_insert_color(&buffer->node, &dev->buffers);
}
+void ion_iommu_add(struct ion_buffer *buffer,
+ struct ion_iommu_map *iommu)
+{
+ struct rb_node **p = &buffer->iommu_maps.rb_node;
+ struct rb_node *parent = NULL;
+ struct ion_iommu_map *entry;
+
+ while (*p) {
+ parent = *p;
+ entry = rb_entry(parent, struct ion_iommu_map, node);
+
+ if (iommu->key < entry->key) {
+ p = &(*p)->rb_left;
+ } else if (iommu->key > entry->key) {
+ p = &(*p)->rb_right;
+ } else {
+ pr_err("%s: buffer %p already has mapping for domain %d"
+ " and partition %d\n", __func__,
+ buffer,
+ iommu_map_domain(iommu),
+ iommu_map_partition(iommu));
+ BUG();
+ }
+ }
+
+ rb_link_node(&iommu->node, parent, p);
+ rb_insert_color(&iommu->node, &buffer->iommu_maps);
+
+}
+
+static struct ion_iommu_map *ion_iommu_lookup(struct ion_buffer *buffer,
+ unsigned int domain_no,
+ unsigned int partition_no)
+{
+ struct rb_node **p = &buffer->iommu_maps.rb_node;
+ struct rb_node *parent = NULL;
+ struct ion_iommu_map *entry;
+ uint64_t key = domain_no;
+ key = key << 32 | partition_no;
+
+ while (*p) {
+ parent = *p;
+ entry = rb_entry(parent, struct ion_iommu_map, node);
+
+ if (key < entry->key)
+ p = &(*p)->rb_left;
+ else if (key > entry->key)
+ p = &(*p)->rb_right;
+ else
+ return entry;
+ }
+
+ return NULL;
+}
+
/* this function should only be called while dev->lock is held */
static struct ion_buffer *ion_buffer_create(struct ion_heap *heap,
struct ion_device *dev,
@@ -433,17 +508,9 @@
return ERR_PTR(-ENODEV);
}
- if (buffer->kmap_cnt || buffer->dmap_cnt || buffer->umap_cnt) {
- if (buffer->flags != flags) {
- pr_err("%s: buffer was already mapped with flags %lx,"
- " cannot map with flags %lx\n", __func__,
- buffer->flags, flags);
+ if (ion_validate_buffer_flags(buffer, flags)) {
vaddr = ERR_PTR(-EEXIST);
goto out;
- }
-
- } else {
- buffer->flags = flags;
}
if (_ion_map(&buffer->kmap_cnt, &handle->kmap_cnt)) {
@@ -462,6 +529,179 @@
return vaddr;
}
+int __ion_iommu_map(struct ion_buffer *buffer,
+ int domain_num, int partition_num, unsigned long align,
+ unsigned long iova_length, unsigned long flags,
+ unsigned long *iova)
+{
+ struct ion_iommu_map *data;
+ int ret;
+
+ data = kmalloc(sizeof(*data), GFP_ATOMIC);
+
+ if (!data)
+ return -ENOMEM;
+
+ data->buffer = buffer;
+ iommu_map_domain(data) = domain_num;
+ iommu_map_partition(data) = partition_num;
+
+ ret = buffer->heap->ops->map_iommu(buffer, data,
+ domain_num,
+ partition_num,
+ align,
+ iova_length,
+ flags);
+
+ if (ret)
+ goto out;
+
+ kref_init(&data->ref);
+ *iova = data->iova_addr;
+
+ ion_iommu_add(buffer, data);
+
+ return 0;
+
+out:
+ msm_free_iova_address(data->iova_addr, domain_num, partition_num,
+ buffer->size);
+ kfree(data);
+ return ret;
+}
+
+int ion_map_iommu(struct ion_client *client, struct ion_handle *handle,
+ int domain_num, int partition_num, unsigned long align,
+ unsigned long iova_length, unsigned long *iova,
+ unsigned long *buffer_size,
+ unsigned long flags)
+{
+ struct ion_buffer *buffer;
+ struct ion_iommu_map *iommu_map;
+ int ret = 0;
+
+ mutex_lock(&client->lock);
+ if (!ion_handle_validate(client, handle)) {
+ pr_err("%s: invalid handle passed to map_kernel.\n",
+ __func__);
+ mutex_unlock(&client->lock);
+ return -EINVAL;
+ }
+
+ buffer = handle->buffer;
+ mutex_lock(&buffer->lock);
+
+ if (!handle->buffer->heap->ops->map_iommu) {
+ pr_err("%s: map_iommu is not implemented by this heap.\n",
+ __func__);
+ ret = -ENODEV;
+ goto out;
+ }
+
+ if (ion_validate_buffer_flags(buffer, flags)) {
+ ret = -EEXIST;
+ goto out;
+ }
+
+ /*
+ * If clients don't want a custom iova length, just use whatever
+ * the buffer size is
+ */
+ if (!iova_length)
+ iova_length = buffer->size;
+
+ if (buffer->size > iova_length) {
+ pr_debug("%s: iova length %lx is not at least buffer size"
+ " %x\n", __func__, iova_length, buffer->size);
+ ret = -EINVAL;
+ goto out;
+ }
+
+ if (buffer->size & ~PAGE_MASK) {
+ pr_debug("%s: buffer size %x is not aligned to %lx", __func__,
+ buffer->size, PAGE_SIZE);
+ ret = -EINVAL;
+ goto out;
+ }
+
+ if (iova_length & ~PAGE_MASK) {
+ pr_debug("%s: iova_length %lx is not aligned to %lx", __func__,
+ iova_length, PAGE_SIZE);
+ ret = -EINVAL;
+ goto out;
+ }
+
+ iommu_map = ion_iommu_lookup(buffer, domain_num, partition_num);
+ if (_ion_map(&buffer->iommu_map_cnt, &handle->iommu_map_cnt) ||
+ !iommu_map) {
+ ret = __ion_iommu_map(buffer, domain_num, partition_num, align,
+ iova_length, flags, iova);
+ if (ret < 0)
+ _ion_unmap(&buffer->iommu_map_cnt,
+ &handle->iommu_map_cnt);
+ } else {
+ if (iommu_map->mapped_size != iova_length) {
+ pr_err("%s: handle %p is already mapped with length"
+ " %x, trying to map with length %lx\n",
+ __func__, handle, iommu_map->mapped_size,
+ iova_length);
+ _ion_unmap(&buffer->iommu_map_cnt,
+ &handle->iommu_map_cnt);
+ ret = -EINVAL;
+ } else {
+ kref_get(&iommu_map->ref);
+ *iova = iommu_map->iova_addr;
+ }
+ }
+ *buffer_size = buffer->size;
+out:
+ mutex_unlock(&buffer->lock);
+ mutex_unlock(&client->lock);
+ return ret;
+}
+EXPORT_SYMBOL(ion_map_iommu);
+
+static void ion_iommu_release(struct kref *kref)
+{
+ struct ion_iommu_map *map = container_of(kref, struct ion_iommu_map,
+ ref);
+ struct ion_buffer *buffer = map->buffer;
+
+ rb_erase(&map->node, &buffer->iommu_maps);
+ buffer->heap->ops->unmap_iommu(map);
+ kfree(map);
+}
+
+void ion_unmap_iommu(struct ion_client *client, struct ion_handle *handle,
+ int domain_num, int partition_num)
+{
+ struct ion_iommu_map *iommu_map;
+ struct ion_buffer *buffer;
+
+ mutex_lock(&client->lock);
+ buffer = handle->buffer;
+
+ mutex_lock(&buffer->lock);
+
+ iommu_map = ion_iommu_lookup(buffer, domain_num, partition_num);
+
+ if (!iommu_map) {
+ WARN(1, "%s: (%d,%d) was never mapped for %p\n", __func__,
+ domain_num, partition_num, buffer);
+ goto out;
+ }
+
+ _ion_unmap(&buffer->iommu_map_cnt, &handle->iommu_map_cnt);
+ kref_put(&iommu_map->ref, ion_iommu_release);
+
+out:
+ mutex_unlock(&buffer->lock);
+
+ mutex_unlock(&client->lock);
+
+}
+EXPORT_SYMBOL(ion_unmap_iommu);
+
struct scatterlist *ion_map_dma(struct ion_client *client,
struct ion_handle *handle,
unsigned long flags)
@@ -487,17 +727,9 @@
return ERR_PTR(-ENODEV);
}
- if (buffer->kmap_cnt || buffer->dmap_cnt || buffer->umap_cnt) {
- if (buffer->flags != flags) {
- pr_err("%s: buffer was already mapped with flags %lx,"
- " cannot map with flags %lx\n", __func__,
- buffer->flags, flags);
- sglist = ERR_PTR(-EEXIST);
- goto out;
- }
-
- } else {
- buffer->flags = flags;
+ if (ion_validate_buffer_flags(buffer, flags)) {
+ sglist = ERR_PTR(-EEXIST);
+ goto out;
}
if (_ion_map(&buffer->dmap_cnt, &handle->dmap_cnt)) {
@@ -746,7 +978,6 @@
struct rb_node **p;
struct rb_node *parent = NULL;
struct ion_client *entry;
- char debug_name[64];
pid_t pid;
get_task_struct(current->group_leader);
@@ -816,8 +1047,8 @@
rb_insert_color(&client->node, &dev->kernel_clients);
}
- snprintf(debug_name, 64, "%u", client->pid);
- client->debug_root = debugfs_create_file(debug_name, 0664,
+
+ client->debug_root = debugfs_create_file(name, 0664,
dev->debug_root, client,
&debug_client_fops);
mutex_unlock(&dev->lock);
@@ -888,14 +1119,33 @@
}
EXPORT_SYMBOL(ion_handle_get_flags);
+int ion_handle_get_size(struct ion_client *client, struct ion_handle *handle,
+ unsigned long *size)
+{
+ struct ion_buffer *buffer;
+
+ mutex_lock(&client->lock);
+ if (!ion_handle_validate(client, handle)) {
+ pr_err("%s: invalid handle passed to %s.\n",
+ __func__, __func__);
+ mutex_unlock(&client->lock);
+ return -EINVAL;
+ }
+ buffer = handle->buffer;
+ mutex_lock(&buffer->lock);
+ *size = buffer->size;
+ mutex_unlock(&buffer->lock);
+ mutex_unlock(&client->lock);
+
+ return 0;
+}
+EXPORT_SYMBOL(ion_handle_get_size);
+
static int ion_share_release(struct inode *inode, struct file* file)
{
struct ion_buffer *buffer = file->private_data;
pr_debug("%s: %d\n", __func__, __LINE__);
- mutex_lock(&buffer->lock);
- buffer->umap_cnt--;
- mutex_unlock(&buffer->lock);
/* drop the reference to the buffer -- this prevents the
buffer from going away because the client holding it exited
while it was being passed */
@@ -918,6 +1168,9 @@
vma->vm_private_data = NULL;
return;
}
+ mutex_lock(&buffer->lock);
+ buffer->umap_cnt++;
+ mutex_unlock(&buffer->lock);
pr_debug("%s: %d client_cnt %d handle_cnt %d alloc_cnt %d\n",
__func__, __LINE__,
atomic_read(&client->ref.refcount),
@@ -936,6 +1189,14 @@
if (!handle)
return;
client = handle->client;
+ mutex_lock(&buffer->lock);
+ buffer->umap_cnt--;
+ mutex_unlock(&buffer->lock);
+
+ if (buffer->heap->ops->unmap_user)
+ buffer->heap->ops->unmap_user(buffer->heap, buffer);
+
+
pr_debug("%s: %d client_cnt %d handle_cnt %d alloc_cnt %d\n",
__func__, __LINE__,
atomic_read(&client->ref.refcount),
@@ -1001,23 +1262,16 @@
}
mutex_lock(&buffer->lock);
- if (buffer->kmap_cnt || buffer->dmap_cnt || buffer->umap_cnt) {
- if (buffer->flags != flags) {
- pr_err("%s: buffer was already mapped with flags %lx,"
- " cannot map with flags %lx\n", __func__,
- buffer->flags, flags);
- ret = -EEXIST;
- mutex_unlock(&buffer->lock);
- goto err1;
- }
- } else {
- buffer->flags = flags;
+ if (ion_validate_buffer_flags(buffer, flags)) {
+ ret = -EEXIST;
+ mutex_unlock(&buffer->lock);
+ goto err1;
}
+
/* now map it to userspace */
ret = buffer->heap->ops->map_user(buffer->heap, buffer, vma,
flags);
- buffer->umap_cnt++;
mutex_unlock(&buffer->lock);
if (ret) {
pr_err("%s: failure mapping buffer to userspace\n",
@@ -1242,9 +1496,11 @@
struct miscdevice *miscdev = file->private_data;
struct ion_device *dev = container_of(miscdev, struct ion_device, dev);
struct ion_client *client;
+ char debug_name[64];
pr_debug("%s: %d\n", __func__, __LINE__);
- client = ion_client_create(dev, -1, "user");
+ snprintf(debug_name, 64, "%u", task_pid_nr(current->group_leader));
+ client = ion_client_create(dev, -1, debug_name);
if (IS_ERR_OR_NULL(client))
return PTR_ERR(client);
file->private_data = client;
diff --git a/drivers/gpu/ion/ion_carveout_heap.c b/drivers/gpu/ion/ion_carveout_heap.c
index 71dea89..9cb338a 100644
--- a/drivers/gpu/ion/ion_carveout_heap.c
+++ b/drivers/gpu/ion/ion_carveout_heap.c
@@ -2,6 +2,7 @@
* drivers/gpu/ion/ion_carveout_heap.c
*
* Copyright (C) 2011 Google, Inc.
+ * Copyright (c) 2011, Code Aurora Forum. All rights reserved.
*
* This software is licensed under the terms of the GNU General Public
* License version 2, as published by the Free Software Foundation, and
@@ -23,8 +24,10 @@
#include <linux/scatterlist.h>
#include <linux/slab.h>
#include <linux/vmalloc.h>
+#include <linux/iommu.h>
#include "ion_priv.h"
+#include <mach/iommu_domains.h>
#include <asm/mach/map.h>
struct ion_carveout_heap {
@@ -33,6 +36,10 @@
ion_phys_addr_t base;
unsigned long allocated_bytes;
unsigned long total_size;
+ void (*request_region)(void *);
+ void (*release_region)(void *);
+ atomic_t map_count;
+ void *bus_id;
};
ion_phys_addr_t ion_carveout_allocate(struct ion_heap *heap,
@@ -128,6 +135,13 @@
struct ion_buffer *buffer,
unsigned long flags)
{
+ struct ion_carveout_heap *carveout_heap =
+ container_of(heap, struct ion_carveout_heap, heap);
+
+ if (atomic_inc_return(&carveout_heap->map_count) == 1)
+ if (carveout_heap->request_region)
+ carveout_heap->request_region(carveout_heap->bus_id);
+
if (ION_IS_CACHED(flags))
return ioremap_cached(buffer->priv_phys, buffer->size);
else
@@ -137,26 +151,52 @@
void ion_carveout_heap_unmap_kernel(struct ion_heap *heap,
struct ion_buffer *buffer)
{
+ struct ion_carveout_heap *carveout_heap =
+ container_of(heap, struct ion_carveout_heap, heap);
+
__arch_iounmap(buffer->vaddr);
buffer->vaddr = NULL;
+
+ if (atomic_dec_and_test(&carveout_heap->map_count))
+ if (carveout_heap->release_region)
+ carveout_heap->release_region(carveout_heap->bus_id);
+
return;
}
int ion_carveout_heap_map_user(struct ion_heap *heap, struct ion_buffer *buffer,
struct vm_area_struct *vma, unsigned long flags)
{
+ struct ion_carveout_heap *carveout_heap =
+ container_of(heap, struct ion_carveout_heap, heap);
+
+ if (atomic_inc_return(&carveout_heap->map_count) == 1)
+ if (carveout_heap->request_region)
+ carveout_heap->request_region(carveout_heap->bus_id);
+
if (ION_IS_CACHED(flags))
return remap_pfn_range(vma, vma->vm_start,
__phys_to_pfn(buffer->priv_phys) + vma->vm_pgoff,
- buffer->size,
+ vma->vm_end - vma->vm_start,
vma->vm_page_prot);
else
return remap_pfn_range(vma, vma->vm_start,
__phys_to_pfn(buffer->priv_phys) + vma->vm_pgoff,
- buffer->size,
+ vma->vm_end - vma->vm_start,
pgprot_noncached(vma->vm_page_prot));
}
+void ion_carveout_heap_unmap_user(struct ion_heap *heap,
+ struct ion_buffer *buffer)
+{
+ struct ion_carveout_heap *carveout_heap =
+ container_of(heap, struct ion_carveout_heap, heap);
+
+ if (atomic_dec_and_test(&carveout_heap->map_count))
+ if (carveout_heap->release_region)
+ carveout_heap->release_region(carveout_heap->bus_id);
+}
+
int ion_carveout_cache_ops(struct ion_heap *heap, struct ion_buffer *buffer,
void *vaddr, unsigned int offset, unsigned int length,
unsigned int cmd)
@@ -199,18 +239,123 @@
return carveout_heap->total_size;
}
+int ion_carveout_heap_map_iommu(struct ion_buffer *buffer,
+ struct ion_iommu_map *data,
+ unsigned int domain_num,
+ unsigned int partition_num,
+ unsigned long align,
+ unsigned long iova_length,
+ unsigned long flags)
+{
+ unsigned long temp_phys, temp_iova;
+ struct iommu_domain *domain;
+ int i, ret = 0;
+ unsigned long extra;
+
+ data->mapped_size = iova_length;
+
+ if (!msm_use_iommu()) {
+ data->iova_addr = buffer->priv_phys;
+ return 0;
+ }
+
+ extra = iova_length - buffer->size;
+
+ data->iova_addr = msm_allocate_iova_address(domain_num, partition_num,
+ data->mapped_size, align);
+
+ if (!data->iova_addr) {
+ ret = -ENOMEM;
+ goto out;
+ }
+
+ domain = msm_get_iommu_domain(domain_num);
+
+ if (!domain) {
+ ret = -ENOMEM;
+ goto out1;
+ }
+
+ temp_iova = data->iova_addr;
+ temp_phys = buffer->priv_phys;
+ for (i = buffer->size; i > 0; i -= SZ_4K, temp_iova += SZ_4K,
+ temp_phys += SZ_4K) {
+ ret = iommu_map(domain, temp_iova, temp_phys,
+ get_order(SZ_4K),
+ ION_IS_CACHED(flags) ? 1 : 0);
+
+ if (ret) {
+ pr_err("%s: could not map %lx to %lx in domain %p\n",
+ __func__, temp_iova, temp_phys, domain);
+ goto out2;
+ }
+ }
+
+ if (extra && (msm_iommu_map_extra(domain, temp_iova, extra, flags) < 0))
+ goto out2;
+
+ return 0;
+
+
+out2:
+ for ( ; i < buffer->size; i += SZ_4K, temp_iova -= SZ_4K)
+ iommu_unmap(domain, temp_iova, get_order(SZ_4K));
+
+out1:
+ msm_free_iova_address(data->iova_addr, domain_num, partition_num,
+ data->mapped_size);
+
+out:
+
+ return ret;
+}
+
+void ion_carveout_heap_unmap_iommu(struct ion_iommu_map *data)
+{
+ int i;
+ unsigned long temp_iova;
+ unsigned int domain_num;
+ unsigned int partition_num;
+ struct iommu_domain *domain;
+
+ if (!msm_use_iommu())
+ return;
+
+ domain_num = iommu_map_domain(data);
+ partition_num = iommu_map_partition(data);
+
+ domain = msm_get_iommu_domain(domain_num);
+
+ if (!domain) {
+ WARN(1, "Could not get domain %d. Corruption?\n", domain_num);
+ return;
+ }
+
+ temp_iova = data->iova_addr;
+ for (i = data->mapped_size; i > 0; i -= SZ_4K, temp_iova += SZ_4K)
+ iommu_unmap(domain, temp_iova, get_order(SZ_4K));
+
+ msm_free_iova_address(data->iova_addr, domain_num, partition_num,
+ data->mapped_size);
+
+ return;
+}
+
static struct ion_heap_ops carveout_heap_ops = {
.allocate = ion_carveout_heap_allocate,
.free = ion_carveout_heap_free,
.phys = ion_carveout_heap_phys,
.map_user = ion_carveout_heap_map_user,
.map_kernel = ion_carveout_heap_map_kernel,
+ .unmap_user = ion_carveout_heap_unmap_user,
.unmap_kernel = ion_carveout_heap_unmap_kernel,
.map_dma = ion_carveout_heap_map_dma,
.unmap_dma = ion_carveout_heap_unmap_dma,
.cache_op = ion_carveout_cache_ops,
.get_allocated = ion_carveout_get_allocated,
.get_total = ion_carveout_get_total,
+ .map_iommu = ion_carveout_heap_map_iommu,
+ .unmap_iommu = ion_carveout_heap_unmap_iommu,
};
struct ion_heap *ion_carveout_heap_create(struct ion_platform_heap *heap_data)
@@ -238,6 +383,12 @@
carveout_heap->heap.type = ION_HEAP_TYPE_CARVEOUT;
carveout_heap->allocated_bytes = 0;
carveout_heap->total_size = heap_data->size;
+ if (heap_data->setup_region)
+ carveout_heap->bus_id = heap_data->setup_region();
+ if (heap_data->request_region)
+ carveout_heap->request_region = heap_data->request_region;
+ if (heap_data->release_region)
+ carveout_heap->release_region = heap_data->release_region;
return &carveout_heap->heap;
}
diff --git a/drivers/gpu/ion/ion_heap.c b/drivers/gpu/ion/ion_heap.c
index 8ce3c19..900f445 100644
--- a/drivers/gpu/ion/ion_heap.c
+++ b/drivers/gpu/ion/ion_heap.c
@@ -32,6 +32,9 @@
case ION_HEAP_TYPE_CARVEOUT:
heap = ion_carveout_heap_create(heap_data);
break;
+ case ION_HEAP_TYPE_IOMMU:
+ heap = ion_iommu_heap_create(heap_data);
+ break;
default:
pr_err("%s: Invalid heap type %d\n", __func__,
heap_data->type);
diff --git a/drivers/gpu/ion/ion_iommu_heap.c b/drivers/gpu/ion/ion_iommu_heap.c
new file mode 100644
index 0000000..d37a811
--- /dev/null
+++ b/drivers/gpu/ion/ion_iommu_heap.c
@@ -0,0 +1,288 @@
+/*
+ * Copyright (c) 2011, Code Aurora Forum. 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 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+#include <linux/err.h>
+#include <linux/io.h>
+#include <linux/ion.h>
+#include <linux/mm.h>
+#include <linux/scatterlist.h>
+#include <linux/slab.h>
+#include <linux/vmalloc.h>
+#include <linux/iommu.h>
+#include <linux/pfn.h>
+#include "ion_priv.h"
+
+#include <asm/mach/map.h>
+#include <asm/page.h>
+#include <mach/iommu_domains.h>
+
+struct ion_iommu_heap {
+ struct ion_heap heap;
+};
+
+struct ion_iommu_priv_data {
+ struct page **pages;
+ int nrpages;
+ unsigned long size;
+};
+
+static int ion_iommu_heap_allocate(struct ion_heap *heap,
+ struct ion_buffer *buffer,
+ unsigned long size, unsigned long align,
+ unsigned long flags)
+{
+ int ret, i;
+ struct ion_iommu_priv_data *data = NULL;
+
+ if (msm_use_iommu()) {
+ data = kmalloc(sizeof(*data), GFP_KERNEL);
+ if (!data)
+ return -ENOMEM;
+
+ data->size = PFN_ALIGN(size);
+ data->nrpages = data->size >> PAGE_SHIFT;
+ data->pages = kzalloc(sizeof(struct page *)*data->nrpages,
+ GFP_KERNEL);
+ if (!data->pages) {
+ ret = -ENOMEM;
+ goto err1;
+ }
+
+ for (i = 0; i < data->nrpages; i++) {
+ data->pages[i] = alloc_page(GFP_KERNEL | __GFP_ZERO);
+ if (!data->pages[i])
+ goto err2;
+ }
+
+
+ buffer->priv_virt = data;
+ return 0;
+
+ } else {
+ return -ENOMEM;
+ }
+
+
+err2:
+ for (i = 0; i < data->nrpages; i++) {
+ if (data->pages[i])
+ __free_page(data->pages[i]);
+ }
+ kfree(data->pages);
+err1:
+ kfree(data);
+ return ret;
+}
+
+static void ion_iommu_heap_free(struct ion_buffer *buffer)
+{
+ struct ion_iommu_priv_data *data = buffer->priv_virt;
+ int i;
+
+ if (!data)
+ return;
+
+ for (i = 0; i < data->nrpages; i++)
+ __free_page(data->pages[i]);
+
+ kfree(data->pages);
+ kfree(data);
+}
+
+void *ion_iommu_heap_map_kernel(struct ion_heap *heap,
+ struct ion_buffer *buffer,
+ unsigned long flags)
+{
+ struct ion_iommu_priv_data *data = buffer->priv_virt;
+ pgprot_t page_prot = PAGE_KERNEL;
+
+ if (!data)
+ return NULL;
+
+ if (!ION_IS_CACHED(flags))
+ page_prot = pgprot_noncached(page_prot);
+
+ buffer->vaddr = vmap(data->pages, data->nrpages, VM_IOREMAP, page_prot);
+
+ return buffer->vaddr;
+}
+
+void ion_iommu_heap_unmap_kernel(struct ion_heap *heap,
+ struct ion_buffer *buffer)
+{
+ if (!buffer->vaddr)
+ return;
+
+ vunmap(buffer->vaddr);
+ buffer->vaddr = NULL;
+}
+
+int ion_iommu_heap_map_user(struct ion_heap *heap, struct ion_buffer *buffer,
+ struct vm_area_struct *vma, unsigned long flags)
+{
+ struct ion_iommu_priv_data *data = buffer->priv_virt;
+ int i;
+
+ if (!data)
+ return -EINVAL;
+
+ if (!ION_IS_CACHED(flags))
+ vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot);
+
+ for (i = 0; i < data->nrpages; i++)
+ if (vm_insert_page(vma, vma->vm_start + i * PAGE_SIZE,
+ data->pages[i]))
+ /*
+ * This will fail the mmap which will
+ * clean up the vma space properly.
+ */
+ return -EINVAL;
+
+ return 0;
+}
+
+int ion_iommu_heap_map_iommu(struct ion_buffer *buffer,
+ struct ion_iommu_map *data,
+ unsigned int domain_num,
+ unsigned int partition_num,
+ unsigned long align,
+ unsigned long iova_length,
+ unsigned long flags)
+{
+ unsigned long temp_iova;
+ struct iommu_domain *domain;
+ struct ion_iommu_priv_data *buffer_data = buffer->priv_virt;
+ int i, j, ret = 0;
+ unsigned long extra;
+
+ BUG_ON(!msm_use_iommu());
+
+ data->mapped_size = iova_length;
+ extra = iova_length - buffer->size;
+
+ data->iova_addr = msm_allocate_iova_address(domain_num, partition_num,
+ data->mapped_size, align);
+
+ if (!data->iova_addr) {
+ ret = -ENOMEM;
+ goto out;
+ }
+
+ domain = msm_get_iommu_domain(domain_num);
+
+ if (!domain) {
+ ret = -ENOMEM;
+ goto out1;
+ }
+
+ temp_iova = data->iova_addr;
+ for (i = buffer->size, j = 0; i > 0; j++, i -= SZ_4K,
+ temp_iova += SZ_4K) {
+ ret = iommu_map(domain, temp_iova,
+ page_to_phys(buffer_data->pages[j]),
+ get_order(SZ_4K),
+ ION_IS_CACHED(flags) ? 1 : 0);
+
+ if (ret) {
+ pr_err("%s: could not map %lx to %x in domain %p\n",
+ __func__, temp_iova,
+ page_to_phys(buffer_data->pages[j]),
+ domain);
+ goto out2;
+ }
+ }
+
+
+ if (extra &&
+ msm_iommu_map_extra
+ (domain, temp_iova, extra, flags) < 0)
+ goto out2;
+
+ return 0;
+
+
+out2:
+ for ( ; i < buffer->size; i += SZ_4K, temp_iova -= SZ_4K)
+ iommu_unmap(domain, temp_iova, get_order(SZ_4K));
+
+out1:
+ msm_free_iova_address(data->iova_addr, domain_num, partition_num,
+ buffer->size);
+
+out:
+
+ return ret;
+}
+
+void ion_iommu_heap_unmap_iommu(struct ion_iommu_map *data)
+{
+ int i;
+ unsigned long temp_iova;
+ unsigned int domain_num;
+ unsigned int partition_num;
+ struct iommu_domain *domain;
+
+ BUG_ON(!msm_use_iommu());
+
+ domain_num = iommu_map_domain(data);
+ partition_num = iommu_map_partition(data);
+
+ domain = msm_get_iommu_domain(domain_num);
+
+ if (!domain) {
+ WARN(1, "Could not get domain %d. Corruption?\n", domain_num);
+ return;
+ }
+
+ temp_iova = data->iova_addr;
+ for (i = data->mapped_size; i > 0; i -= SZ_4K, temp_iova += SZ_4K)
+ iommu_unmap(domain, temp_iova, get_order(SZ_4K));
+
+ msm_free_iova_address(data->iova_addr, domain_num, partition_num,
+ data->mapped_size);
+
+ return;
+}
+
+
+static struct ion_heap_ops iommu_heap_ops = {
+ .allocate = ion_iommu_heap_allocate,
+ .free = ion_iommu_heap_free,
+ .map_user = ion_iommu_heap_map_user,
+ .map_kernel = ion_iommu_heap_map_kernel,
+ .unmap_kernel = ion_iommu_heap_unmap_kernel,
+ .map_iommu = ion_iommu_heap_map_iommu,
+ .unmap_iommu = ion_iommu_heap_unmap_iommu,
+};
+
+struct ion_heap *ion_iommu_heap_create(struct ion_platform_heap *heap_data)
+{
+ struct ion_iommu_heap *iommu_heap;
+
+ iommu_heap = kzalloc(sizeof(struct ion_iommu_heap), GFP_KERNEL);
+ if (!iommu_heap)
+ return ERR_PTR(-ENOMEM);
+
+ iommu_heap->heap.ops = &iommu_heap_ops;
+ iommu_heap->heap.type = ION_HEAP_TYPE_IOMMU;
+
+ return &iommu_heap->heap;
+}
+
+void ion_iommu_heap_destroy(struct ion_heap *heap)
+{
+ struct ion_iommu_heap *iommu_heap =
+ container_of(heap, struct ion_iommu_heap, heap);
+
+ kfree(iommu_heap);
+ iommu_heap = NULL;
+}
diff --git a/drivers/gpu/ion/ion_priv.h b/drivers/gpu/ion/ion_priv.h
index 888b599..77b73e2 100644
--- a/drivers/gpu/ion/ion_priv.h
+++ b/drivers/gpu/ion/ion_priv.h
@@ -22,6 +22,7 @@
#include <linux/mutex.h>
#include <linux/rbtree.h>
#include <linux/ion.h>
+#include <linux/iommu.h>
struct ion_mapping;
@@ -35,6 +36,34 @@
void *vaddr;
};
+/**
+ * struct ion_iommu_map - represents a mapping of an ion buffer to an iommu
+ * @iova_addr - iommu virtual address
+ * @node - rb node to exist in the buffer's tree of iommu mappings
+ * @domain_info - contains the partition number and domain number
+ * domain_info[1] = domain number
+ * domain_info[0] = partition number
+ * @ref - for reference counting this mapping
+ * @mapped_size - size of the iova space mapped
+ * (may not be the same as the buffer size)
+ *
+ * Represents a mapping of one ion buffer to a particular iommu domain
+ * and address range. There may exist other mappings of this buffer in
+ * different domains or address ranges. All mappings will have the same
+ * cacheability and security.
+ */
+struct ion_iommu_map {
+ unsigned long iova_addr;
+ struct rb_node node;
+ union {
+ int domain_info[2];
+ uint64_t key;
+ };
+ struct ion_buffer *buffer;
+ struct kref ref;
+ int mapped_size;
+};
+
struct ion_buffer *ion_handle_buffer(struct ion_handle *handle);
/**
@@ -72,6 +101,8 @@
int dmap_cnt;
struct scatterlist *sglist;
int umap_cnt;
+ unsigned int iommu_map_cnt;
+ struct rb_root iommu_maps;
int marked;
};
@@ -86,6 +117,7 @@
* @map_kernel map memory to the kernel
* @unmap_kernel unmap memory to the kernel
* @map_user map memory to userspace
+ * @unmap_user unmap memory to userspace
*/
struct ion_heap_ops {
int (*allocate) (struct ion_heap *heap,
@@ -102,11 +134,21 @@
void (*unmap_kernel) (struct ion_heap *heap, struct ion_buffer *buffer);
int (*map_user) (struct ion_heap *mapper, struct ion_buffer *buffer,
struct vm_area_struct *vma, unsigned long flags);
+ void (*unmap_user) (struct ion_heap *mapper, struct ion_buffer *buffer);
int (*cache_op)(struct ion_heap *heap, struct ion_buffer *buffer,
void *vaddr, unsigned int offset,
unsigned int length, unsigned int cmd);
unsigned long (*get_allocated)(struct ion_heap *heap);
unsigned long (*get_total)(struct ion_heap *heap);
+ int (*map_iommu)(struct ion_buffer *buffer,
+ struct ion_iommu_map *map_data,
+ unsigned int domain_num,
+ unsigned int partition_num,
+ unsigned long align,
+ unsigned long iova_length,
+ unsigned long flags);
+ void (*unmap_iommu)(struct ion_iommu_map *data);
+
};
/**
@@ -134,6 +176,11 @@
const char *name;
};
+
+
+#define iommu_map_domain(__m) ((__m)->domain_info[1])
+#define iommu_map_partition(__m) ((__m)->domain_info[0])
+
/**
* ion_device_create - allocates and returns an ion device
* @custom_ioctl: arch specific ioctl function if applicable
@@ -175,6 +222,10 @@
struct ion_heap *ion_carveout_heap_create(struct ion_platform_heap *);
void ion_carveout_heap_destroy(struct ion_heap *);
+
+struct ion_heap *ion_iommu_heap_create(struct ion_platform_heap *);
+void ion_iommu_heap_destroy(struct ion_heap *);
+
/**
* kernel api to allocate/free from carveout -- used when carveout is
* used to back an architecture specific custom heap
@@ -183,6 +234,9 @@
unsigned long align);
void ion_carveout_free(struct ion_heap *heap, ion_phys_addr_t addr,
unsigned long size);
+
+
+struct ion_heap *msm_get_contiguous_heap(void);
/**
* The carveout heap returns physical addresses, since 0 may be a valid
* physical address, this is used to indicate allocation failed
diff --git a/drivers/gpu/ion/ion_system_heap.c b/drivers/gpu/ion/ion_system_heap.c
index b26d48c..5957658 100644
--- a/drivers/gpu/ion/ion_system_heap.c
+++ b/drivers/gpu/ion/ion_system_heap.c
@@ -2,6 +2,7 @@
* drivers/gpu/ion/ion_system_heap.c
*
* Copyright (C) 2011 Google, Inc.
+ * Copyright (c) 2011, Code Aurora Forum. All rights reserved.
*
* This software is licensed under the terms of the GNU General Public
* License version 2, as published by the Free Software Foundation, and
@@ -20,6 +21,8 @@
#include <linux/scatterlist.h>
#include <linux/slab.h>
#include <linux/vmalloc.h>
+#include <linux/iommu.h>
+#include <mach/iommu_domains.h>
#include "ion_priv.h"
#include <mach/memory.h>
@@ -98,6 +101,37 @@
{
}
+void ion_system_heap_unmap_iommu(struct ion_iommu_map *data)
+{
+ int i;
+ unsigned long temp_iova;
+ unsigned int domain_num;
+ unsigned int partition_num;
+ struct iommu_domain *domain;
+
+ if (!msm_use_iommu())
+ return;
+
+ domain_num = iommu_map_domain(data);
+ partition_num = iommu_map_partition(data);
+
+ domain = msm_get_iommu_domain(domain_num);
+
+ if (!domain) {
+ WARN(1, "Could not get domain %d. Corruption?\n", domain_num);
+ return;
+ }
+
+ temp_iova = data->iova_addr;
+ for (i = data->mapped_size; i > 0; i -= SZ_4K, temp_iova += SZ_4K)
+ iommu_unmap(domain, temp_iova, get_order(SZ_4K));
+
+ msm_free_iova_address(data->iova_addr, domain_num, partition_num,
+ data->mapped_size);
+
+ return;
+}
+
int ion_system_heap_map_user(struct ion_heap *heap, struct ion_buffer *buffer,
struct vm_area_struct *vma, unsigned long flags)
{
@@ -160,6 +194,77 @@
return atomic_read(&system_heap_allocated);
}
+int ion_system_heap_map_iommu(struct ion_buffer *buffer,
+ struct ion_iommu_map *data,
+ unsigned int domain_num,
+ unsigned int partition_num,
+ unsigned long align,
+ unsigned long iova_length,
+ unsigned long flags)
+{
+ int ret, i;
+ unsigned long temp_iova;
+ struct iommu_domain *domain;
+ void *temp_phys;
+ unsigned long extra;
+
+ if (!ION_IS_CACHED(flags))
+ return -EINVAL;
+
+ if (!msm_use_iommu())
+ return -EINVAL;
+
+ data->mapped_size = iova_length;
+ extra = iova_length - buffer->size;
+
+ data->iova_addr = msm_allocate_iova_address(domain_num, partition_num,
+ data->mapped_size, align);
+
+ if (!data->iova_addr) {
+ ret = -ENOMEM;
+ goto out;
+ }
+
+ domain = msm_get_iommu_domain(domain_num);
+
+ if (!domain) {
+ ret = -ENOMEM;
+ goto out1;
+ }
+
+ temp_iova = data->iova_addr;
+ temp_phys = buffer->vaddr;
+ for (i = buffer->size; i > 0; i -= SZ_4K, temp_iova += SZ_4K,
+ temp_phys += SZ_4K) {
+ ret = iommu_map(domain, temp_iova,
+ page_to_phys(vmalloc_to_page(temp_phys)),
+ get_order(SZ_4K), ION_IS_CACHED(flags) ? 1 : 0);
+
+ if (ret) {
+ pr_err("%s: could not map %lx to %x in domain %p\n",
+ __func__, temp_iova,
+ page_to_phys(vmalloc_to_page(temp_phys)),
+ domain);
+ goto out2;
+ }
+ }
+
+ if (extra && (msm_iommu_map_extra(domain, temp_iova, extra, flags) < 0))
+ goto out2;
+
+ return 0;
+
+out2:
+ for ( ; i < buffer->size; i += SZ_4K, temp_iova -= SZ_4K)
+ iommu_unmap(domain, temp_iova, get_order(SZ_4K));
+
+out1:
+ msm_free_iova_address(data->iova_addr, domain_num, partition_num,
+ data->mapped_size);
+out:
+ return ret;
+}
+
static struct ion_heap_ops vmalloc_ops = {
.allocate = ion_system_heap_allocate,
.free = ion_system_heap_free,
@@ -170,6 +275,8 @@
.map_user = ion_system_heap_map_user,
.cache_op = ion_system_heap_cache_ops,
.get_allocated = ion_system_heap_get_allocated,
+ .map_iommu = ion_system_heap_map_iommu,
+ .unmap_iommu = ion_system_heap_unmap_iommu,
};
struct ion_heap *ion_system_heap_create(struct ion_platform_heap *unused)
@@ -285,6 +392,74 @@
return atomic_read(&system_contig_heap_allocated);
}
+int ion_system_contig_heap_map_iommu(struct ion_buffer *buffer,
+ struct ion_iommu_map *data,
+ unsigned int domain_num,
+ unsigned int partition_num,
+ unsigned long align,
+ unsigned long iova_length,
+ unsigned long flags)
+{
+ int ret, i;
+ struct iommu_domain *domain;
+ unsigned long temp_phys, temp_iova;
+ unsigned long extra;
+
+ if (!ION_IS_CACHED(flags))
+ return -EINVAL;
+
+ if (!msm_use_iommu()) {
+ data->iova_addr = virt_to_phys(buffer->vaddr);
+ return 0;
+ }
+
+ data->mapped_size = iova_length;
+ extra = iova_length - buffer->size;
+
+ data->iova_addr = msm_allocate_iova_address(domain_num, partition_num,
+ data->mapped_size, align);
+
+ if (!data->iova_addr) {
+ ret = -ENOMEM;
+ goto out;
+ }
+
+ domain = msm_get_iommu_domain(domain_num);
+
+ if (!domain) {
+ ret = -ENOMEM;
+ goto out1;
+ }
+ temp_iova = data->iova_addr;
+ temp_phys = virt_to_phys(buffer->vaddr);
+ for (i = buffer->size; i > 0; i -= SZ_4K, temp_iova += SZ_4K,
+ temp_phys += SZ_4K) {
+ ret = iommu_map(domain, temp_iova,
+ temp_phys,
+ get_order(SZ_4K), ION_IS_CACHED(flags) ? 1 : 0);
+
+ if (ret) {
+ pr_err("%s: could not map %lx to %lx in domain %p\n",
+ __func__, temp_iova, temp_phys, domain);
+ goto out2;
+ }
+ }
+
+ if (extra && (msm_iommu_map_extra(domain, temp_iova, extra, flags) < 0))
+ goto out2;
+
+ return 0;
+out2:
+ for ( ; i < buffer->size; i += SZ_4K, temp_iova -= SZ_4K)
+ iommu_unmap(domain, temp_iova, get_order(SZ_4K));
+
+out1:
+ msm_free_iova_address(data->iova_addr, domain_num, partition_num,
+ data->mapped_size);
+out:
+ return ret;
+}
+
static struct ion_heap_ops kmalloc_ops = {
.allocate = ion_system_contig_heap_allocate,
.free = ion_system_contig_heap_free,
@@ -296,6 +471,8 @@
.map_user = ion_system_contig_heap_map_user,
.cache_op = ion_system_contig_heap_cache_ops,
.get_allocated = ion_system_contig_heap_get_allocated,
+ .map_iommu = ion_system_contig_heap_map_iommu,
+ .unmap_iommu = ion_system_heap_unmap_iommu,
};
struct ion_heap *ion_system_contig_heap_create(struct ion_platform_heap *unused)
diff --git a/drivers/gpu/ion/msm/msm_ion.c b/drivers/gpu/ion/msm/msm_ion.c
index 54dd056..0c96eaf 100644
--- a/drivers/gpu/ion/msm/msm_ion.c
+++ b/drivers/gpu/ion/msm/msm_ion.c
@@ -89,6 +89,7 @@
heaps[i] = 0;
continue;
}
+
ion_device_add_heap(idev, heaps[i]);
}
platform_set_drvdata(pdev, idev);
diff --git a/drivers/gpu/msm/Makefile b/drivers/gpu/msm/Makefile
index b4cd286..39a7b04 100644
--- a/drivers/gpu/msm/Makefile
+++ b/drivers/gpu/msm/Makefile
@@ -1,7 +1,8 @@
-ccflags-y := -Iinclude/drm
+ccflags-y := -Iinclude/drm -Idrivers/gpu/msm
msm_kgsl_core-y = \
kgsl.o \
+ kgsl_trace.o \
kgsl_sharedmem.o \
kgsl_pwrctrl.o \
kgsl_pwrscale.o \
@@ -20,11 +21,14 @@
adreno_drawctxt.o \
adreno_postmortem.o \
adreno_a2xx.o \
+ adreno_a2xx_trace.o \
adreno.o
msm_adreno-$(CONFIG_DEBUG_FS) += adreno_debugfs.o
-msm_z180-y += z180.o
+msm_z180-y += \
+ z180.o \
+ z180_trace.o
msm_kgsl_core-objs = $(msm_kgsl_core-y)
msm_adreno-objs = $(msm_adreno-y)
diff --git a/drivers/gpu/msm/adreno.c b/drivers/gpu/msm/adreno.c
index 23ecfb3..2681263 100644
--- a/drivers/gpu/msm/adreno.c
+++ b/drivers/gpu/msm/adreno.c
@@ -149,6 +149,9 @@
{ ADRENO_REV_A225, 2, 2, 0, 5,
"a225p5_pm4.fw", "a225_pfp.fw", &adreno_a2xx_gpudev,
1536, 768 },
+ { ADRENO_REV_A225, 2, 2, 0, 6,
+ "a225_pm4.fw", "a225_pfp.fw", &adreno_a2xx_gpudev,
+ 1536, 768 },
{ ADRENO_REV_A225, 2, 2, ANY_ID, ANY_ID,
"a225_pm4.fw", "a225_pfp.fw", &adreno_a2xx_gpudev,
1536, 768 },
@@ -270,10 +273,13 @@
int sizedwords = 0;
unsigned int mh_mmu_invalidate = 0x00000003; /*invalidate all and tc */
- /* If possible, then set the state via the command stream to avoid
- a CPU idle. Otherwise, use the default setstate which uses register
- writes */
- if (adreno_dev->drawctxt_active) {
+ /*
+ * If possible, then set the state via the command stream to avoid
+ * a CPU idle. Otherwise, use the default setstate which uses register
+ * writes For CFF dump we must idle and use the registers so that it is
+ * easier to filter out the mmu accesses from the dump
+ */
+ if (!kgsl_cff_dump_enable && adreno_dev->drawctxt_active) {
if (flags & KGSL_MMUFLAGS_PTUPDATE) {
/* wait for graphics pipe to be idle */
*cmds++ = cp_type3_packet(CP_WAIT_FOR_IDLE, 1);
@@ -358,6 +364,7 @@
{
unsigned int chipid = 0;
unsigned int coreid, majorid, minorid, patchid, revid;
+ uint32_t soc_platform_version = socinfo_get_version();
adreno_regread(device, REG_RBBM_PERIPHID1, &coreid);
adreno_regread(device, REG_RBBM_PERIPHID2, &majorid);
@@ -379,8 +386,12 @@
patchid = ((revid >> 16) & 0xFF);
/* 8x50 returns 0 for patch release, but it should be 1 */
+ /* 8960v3 returns 5 for patch release, but it should be 6 */
if (cpu_is_qsd8x50())
patchid = 1;
+ else if (cpu_is_msm8960() &&
+ SOCINFO_VERSION_MAJOR(soc_platform_version) == 3)
+ patchid = 6;
chipid |= (minorid << 8) | patchid;
@@ -926,29 +937,27 @@
return status;
}
-uint8_t *kgsl_sharedmem_convertaddr(struct kgsl_device *device,
- unsigned int pt_base, unsigned int gpuaddr, unsigned int *size)
+const struct kgsl_memdesc *adreno_find_region(struct kgsl_device *device,
+ unsigned int pt_base,
+ unsigned int gpuaddr,
+ unsigned int size)
{
- uint8_t *result = NULL;
+ struct kgsl_memdesc *result = NULL;
struct kgsl_mem_entry *entry;
struct kgsl_process_private *priv;
struct adreno_device *adreno_dev = ADRENO_DEVICE(device);
struct adreno_ringbuffer *ringbuffer = &adreno_dev->ringbuffer;
+ struct kgsl_context *context;
+ int next = 0;
- if (kgsl_gpuaddr_in_memdesc(&ringbuffer->buffer_desc, gpuaddr)) {
- return kgsl_gpuaddr_to_vaddr(&ringbuffer->buffer_desc,
- gpuaddr, size);
- }
+ if (kgsl_gpuaddr_in_memdesc(&ringbuffer->buffer_desc, gpuaddr, size))
+ return &ringbuffer->buffer_desc;
- if (kgsl_gpuaddr_in_memdesc(&ringbuffer->memptrs_desc, gpuaddr)) {
- return kgsl_gpuaddr_to_vaddr(&ringbuffer->memptrs_desc,
- gpuaddr, size);
- }
+ if (kgsl_gpuaddr_in_memdesc(&ringbuffer->memptrs_desc, gpuaddr, size))
+ return &ringbuffer->memptrs_desc;
- if (kgsl_gpuaddr_in_memdesc(&device->memstore, gpuaddr)) {
- return kgsl_gpuaddr_to_vaddr(&device->memstore,
- gpuaddr, size);
- }
+ if (kgsl_gpuaddr_in_memdesc(&device->memstore, gpuaddr, size))
+ return &device->memstore;
mutex_lock(&kgsl_driver.process_mutex);
list_for_each_entry(priv, &kgsl_driver.process_list, list) {
@@ -958,8 +967,7 @@
entry = kgsl_sharedmem_find_region(priv, gpuaddr,
sizeof(unsigned int));
if (entry) {
- result = kgsl_gpuaddr_to_vaddr(&entry->memdesc,
- gpuaddr, size);
+ result = &entry->memdesc;
spin_unlock(&priv->mem_lock);
mutex_unlock(&kgsl_driver.process_mutex);
return result;
@@ -970,14 +978,52 @@
BUG_ON(!mutex_is_locked(&device->mutex));
list_for_each_entry(entry, &device->memqueue, list) {
- if (kgsl_gpuaddr_in_memdesc(&entry->memdesc, gpuaddr)) {
- result = kgsl_gpuaddr_to_vaddr(&entry->memdesc,
- gpuaddr, size);
- break;
+ if (kgsl_gpuaddr_in_memdesc(&entry->memdesc, gpuaddr, size)) {
+ result = &entry->memdesc;
+ return result;
}
}
- return result;
+
+ while (1) {
+ struct adreno_context *adreno_context = NULL;
+ struct kgsl_memdesc *gpustate;
+ struct kgsl_memdesc *gmemshadow;
+ context = idr_get_next(&device->context_idr, &next);
+ if (context == NULL)
+ break;
+
+ adreno_context = (struct adreno_context *)context->devctxt;
+
+ if (!kgsl_mmu_pt_equal(adreno_context->pagetable, pt_base))
+ continue;
+
+ gpustate = &adreno_context->gpustate;
+ if (kgsl_gpuaddr_in_memdesc(gpustate, gpuaddr, size)) {
+ result = gpustate;
+ return result;
+ }
+ gmemshadow = &adreno_context->context_gmem_shadow.gmemshadow;
+ if (kgsl_gpuaddr_in_memdesc(gmemshadow, gpuaddr, size)) {
+ result = gmemshadow;
+ return result;
+ }
+
+ next = next + 1;
+ }
+
+ return NULL;
+
+}
+
+uint8_t *adreno_convertaddr(struct kgsl_device *device, unsigned int pt_base,
+ unsigned int gpuaddr, unsigned int size)
+{
+ const struct kgsl_memdesc *memdesc;
+
+ memdesc = adreno_find_region(device, pt_base, gpuaddr, size);
+
+ return memdesc ? kgsl_gpuaddr_to_vaddr(memdesc, gpuaddr) : NULL;
}
void adreno_regread(struct kgsl_device *device, unsigned int offsetwords,
@@ -1271,6 +1317,18 @@
adreno_dev->gpudev->irq_control(adreno_dev, state);
}
+static unsigned int adreno_gpuid(struct kgsl_device *device)
+{
+ struct adreno_device *adreno_dev = ADRENO_DEVICE(device);
+
+ /* Standard KGSL gpuid format:
+ * top word is 0x0002 for 2D or 0x0003 for 3D
+ * Bottom word is core specific identifer
+ */
+
+ return (0x0003 << 16) | ((int) adreno_dev->gpurev);
+}
+
static const struct kgsl_functable adreno_functable = {
/* Mandatory functions */
.regread = adreno_regread,
@@ -1289,6 +1347,7 @@
.cleanup_pt = adreno_cleanup_pt,
.power_stats = adreno_power_stats,
.irqctrl = adreno_irqctrl,
+ .gpuid = adreno_gpuid,
/* Optional functions */
.setstate = adreno_setstate,
.drawctxt_create = adreno_drawctxt_create,
diff --git a/drivers/gpu/msm/adreno.h b/drivers/gpu/msm/adreno.h
index 0776a24..99c6c52 100644
--- a/drivers/gpu/msm/adreno.h
+++ b/drivers/gpu/msm/adreno.h
@@ -43,6 +43,7 @@
*/
#define ADRENO_ISTORE_BYTES 12
#define ADRENO_ISTORE_WORDS 3
+#define ADRENO_ISTORE_START 0x5000
enum adreno_gpurev {
ADRENO_REV_UNKNOWN = 0,
@@ -93,8 +94,13 @@
void adreno_regwrite(struct kgsl_device *device, unsigned int offsetwords,
unsigned int value);
-uint8_t *kgsl_sharedmem_convertaddr(struct kgsl_device *device,
- unsigned int pt_base, unsigned int gpuaddr, unsigned int *size);
+const struct kgsl_memdesc *adreno_find_region(struct kgsl_device *device,
+ unsigned int pt_base,
+ unsigned int gpuaddr,
+ unsigned int size);
+
+uint8_t *adreno_convertaddr(struct kgsl_device *device,
+ unsigned int pt_base, unsigned int gpuaddr, unsigned int size);
static inline int adreno_is_a200(struct adreno_device *adreno_dev)
{
diff --git a/drivers/gpu/msm/adreno_a2xx.c b/drivers/gpu/msm/adreno_a2xx.c
index 7b27f61..d083586 100644
--- a/drivers/gpu/msm/adreno_a2xx.c
+++ b/drivers/gpu/msm/adreno_a2xx.c
@@ -15,6 +15,7 @@
#include "kgsl_sharedmem.h"
#include "kgsl_cffdump.h"
#include "adreno.h"
+#include "adreno_a2xx_trace.h"
/*
*
@@ -598,7 +599,7 @@
/* Repartition shaders */
*cmds++ = cp_type0_packet(REG_SQ_INST_STORE_MANAGMENT, 1);
- *cmds++ = 0x180;
+ *cmds++ = adreno_dev->pix_shader_start;
/* Invalidate Vertex & Pixel instruction code address and sizes */
*cmds++ = cp_type3_packet(CP_INVALIDATE_STATE, 1);
@@ -800,7 +801,7 @@
/* Repartition shaders */
*cmds++ = cp_type0_packet(REG_SQ_INST_STORE_MANAGMENT, 1);
- *cmds++ = 0x180;
+ *cmds++ = adreno_dev->pix_shader_start;
/* Invalidate Vertex & Pixel instruction code address and sizes */
*cmds++ = cp_type3_packet(CP_INVALIDATE_STATE, 1);
@@ -1511,6 +1512,9 @@
KGSL_DRV_WARN(device,
"Looped %d times to read REG_CP_INT_STATUS\n",
num_reads);
+
+ trace_kgsl_a2xx_irq_status(device, master_status, status);
+
if (!status) {
if (master_status & MASTER_INT_SIGNAL__CP_INT_STAT) {
/* This indicates that we could not read CP_INT_STAT.
diff --git a/drivers/gpu/msm/adreno_a2xx_trace.c b/drivers/gpu/msm/adreno_a2xx_trace.c
new file mode 100644
index 0000000..c91d1a0
--- /dev/null
+++ b/drivers/gpu/msm/adreno_a2xx_trace.c
@@ -0,0 +1,19 @@
+/* Copyright (c) 2011, Code Aurora Forum. 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 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#include "kgsl.h"
+#include "adreno.h"
+
+/* Instantiate tracepoints */
+#define CREATE_TRACE_POINTS
+#include "adreno_a2xx_trace.h"
diff --git a/drivers/gpu/msm/adreno_a2xx_trace.h b/drivers/gpu/msm/adreno_a2xx_trace.h
new file mode 100644
index 0000000..2528e15
--- /dev/null
+++ b/drivers/gpu/msm/adreno_a2xx_trace.h
@@ -0,0 +1,78 @@
+/* Copyright (c) 2011, Code Aurora Forum. 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 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#if !defined(_ADRENO_A2XX_TRACE_H) || defined(TRACE_HEADER_MULTI_READ)
+#define _ADRENO_A2XX_TRACE_H
+
+#undef TRACE_SYSTEM
+#define TRACE_SYSTEM kgsl
+#undef TRACE_INCLUDE_PATH
+#define TRACE_INCLUDE_PATH .
+#undef TRACE_INCLUDE_FILE
+#define TRACE_INCLUDE_FILE adreno_a2xx_trace
+
+#include <linux/tracepoint.h>
+
+struct kgsl_device;
+
+/*
+ * Tracepoint for a2xx irq. Includes status info
+ */
+TRACE_EVENT(kgsl_a2xx_irq_status,
+
+ TP_PROTO(struct kgsl_device *device, unsigned int master_status,
+ unsigned int status),
+
+ TP_ARGS(device, master_status, status),
+
+ TP_STRUCT__entry(
+ __string(device_name, device->name)
+ __field(unsigned int, master_status)
+ __field(unsigned int, status)
+ ),
+
+ TP_fast_assign(
+ __assign_str(device_name, device->name);
+ __entry->master_status = master_status;
+ __entry->status = status;
+ ),
+
+ TP_printk(
+ "d_name=%s master=%s status=%s",
+ __get_str(device_name),
+ __entry->master_status ? __print_flags(__entry->master_status,
+ "|",
+ { MASTER_INT_SIGNAL__MH_INT_STAT, "MH" },
+ { MASTER_INT_SIGNAL__SQ_INT_STAT, "SQ" },
+ { MASTER_INT_SIGNAL__CP_INT_STAT, "CP" },
+ { MASTER_INT_SIGNAL__RBBM_INT_STAT, "RBBM" }) : "None",
+ __entry->status ? __print_flags(__entry->status, "|",
+ { CP_INT_CNTL__SW_INT_MASK, "SW" },
+ { CP_INT_CNTL__T0_PACKET_IN_IB_MASK,
+ "T0_PACKET_IN_IB" },
+ { CP_INT_CNTL__OPCODE_ERROR_MASK, "OPCODE_ERROR" },
+ { CP_INT_CNTL__PROTECTED_MODE_ERROR_MASK,
+ "PROTECTED_MODE_ERROR" },
+ { CP_INT_CNTL__RESERVED_BIT_ERROR_MASK,
+ "RESERVED_BIT_ERROR" },
+ { CP_INT_CNTL__IB_ERROR_MASK, "IB_ERROR" },
+ { CP_INT_CNTL__IB2_INT_MASK, "IB2" },
+ { CP_INT_CNTL__IB1_INT_MASK, "IB1" },
+ { CP_INT_CNTL__RB_INT_MASK, "RB" }) : "None"
+ )
+);
+
+#endif /* _ADRENO_A2XX_TRACE_H */
+
+/* This part must be outside protection */
+#include <trace/define_trace.h>
diff --git a/drivers/gpu/msm/adreno_debugfs.c b/drivers/gpu/msm/adreno_debugfs.c
index 419ce9d..c1b9e4c 100644
--- a/drivers/gpu/msm/adreno_debugfs.c
+++ b/drivers/gpu/msm/adreno_debugfs.c
@@ -25,9 +25,6 @@
unsigned int kgsl_cff_dump_enable;
int kgsl_pm_regs_enabled;
-static uint32_t kgsl_ib_base;
-static uint32_t kgsl_ib_size;
-
static struct dentry *pm_d_debugfs;
static int pm_dump_set(void *data, u64 val)
@@ -115,98 +112,6 @@
return ss;
}
-static ssize_t kgsl_ib_dump_read(
- struct file *file,
- char __user *buff,
- size_t buff_count,
- loff_t *ppos)
-{
- int i, count = kgsl_ib_size, remaining, pos = 0, tot = 0, ss;
- struct kgsl_device *device = file->private_data;
- const int rowc = 32;
- unsigned int pt_base, ib_memsize;
- uint8_t *base_addr;
- char linebuf[80];
-
- if (!ppos || !device || !kgsl_ib_base)
- return 0;
-
- kgsl_regread(device, MH_MMU_PT_BASE, &pt_base);
- base_addr = kgsl_sharedmem_convertaddr(device, pt_base, kgsl_ib_base,
- &ib_memsize);
-
- if (!base_addr)
- return 0;
-
- pr_info("%s ppos=%ld, buff_count=%d, count=%d\n", __func__, (long)*ppos,
- buff_count, count);
- ss = snprintf(linebuf, sizeof(linebuf), "IB: base=%08x(%08x"
- "), size=%d, memsize=%d\n", kgsl_ib_base,
- (uint32_t)base_addr, kgsl_ib_size, ib_memsize);
- if (*ppos == 0) {
- if (copy_to_user(buff, linebuf, ss+1))
- return -EFAULT;
- tot += ss;
- buff += ss;
- *ppos += ss;
- }
- pos += ss;
- remaining = count;
- for (i = 0; i < count; i += rowc) {
- int linec = min(remaining, rowc);
-
- remaining -= rowc;
- ss = kgsl_hex_dump("IB: %05x: ", i, base_addr, rowc, linec,
- buff);
- if (ss < 0)
- return ss;
-
- if (pos >= *ppos) {
- if (tot+ss >= buff_count) {
- ss = copy_to_user(buff, "", 1);
- return tot;
- }
- tot += ss;
- buff += ss;
- *ppos += ss;
- }
- pos += ss;
- base_addr += linec;
- }
-
- return tot;
-}
-
-static ssize_t kgsl_ib_dump_write(
- struct file *file,
- const char __user *buff,
- size_t count,
- loff_t *ppos)
-{
- char local_buff[64];
-
- if (count >= sizeof(local_buff))
- return -EFAULT;
-
- if (copy_from_user(local_buff, buff, count))
- return -EFAULT;
-
- local_buff[count] = 0; /* end of string */
- sscanf(local_buff, "%x %d", &kgsl_ib_base, &kgsl_ib_size);
-
- pr_info("%s: base=%08X size=%d\n", __func__, kgsl_ib_base,
- kgsl_ib_size);
-
- return count;
-}
-
-static const struct file_operations kgsl_ib_dump_fops = {
- .open = kgsl_dbgfs_open,
- .release = kgsl_dbgfs_release,
- .read = kgsl_ib_dump_read,
- .write = kgsl_ib_dump_write,
-};
-
static int kgsl_regread_nolock(struct kgsl_device *device,
unsigned int offsetwords, unsigned int *value)
{
@@ -223,7 +128,6 @@
return 0;
}
-#define ADRENO_ISTORE_START 0x5000
static ssize_t kgsl_istore_read(
struct file *file,
char __user *buff,
@@ -429,8 +333,6 @@
if (!device->d_debugfs || IS_ERR(device->d_debugfs))
return;
- debugfs_create_file("ib_dump", 0600, device->d_debugfs, device,
- &kgsl_ib_dump_fops);
debugfs_create_file("istore", 0400, device->d_debugfs, device,
&kgsl_istore_fops);
debugfs_create_file("sx_debug", 0400, device->d_debugfs, device,
diff --git a/drivers/gpu/msm/adreno_postmortem.c b/drivers/gpu/msm/adreno_postmortem.c
index cc69360..c6b850e 100644
--- a/drivers/gpu/msm/adreno_postmortem.c
+++ b/drivers/gpu/msm/adreno_postmortem.c
@@ -247,9 +247,8 @@
static void dump_ib(struct kgsl_device *device, char* buffId, uint32_t pt_base,
uint32_t base_offset, uint32_t ib_base, uint32_t ib_size, bool dump)
{
- unsigned int memsize;
- uint8_t *base_addr = kgsl_sharedmem_convertaddr(device, pt_base,
- ib_base, &memsize);
+ uint8_t *base_addr = adreno_convertaddr(device, pt_base,
+ ib_base, ib_size*sizeof(uint32_t));
if (base_addr && dump)
print_hex_dump(KERN_ERR, buffId, DUMP_PREFIX_OFFSET,
@@ -277,14 +276,13 @@
int i, j;
uint32_t value;
uint32_t *ib1_addr;
- unsigned int memsize;
dump_ib(device, "IB1:", pt_base, base_offset, ib1_base,
ib1_size, dump);
/* fetch virtual address for given IB base */
- ib1_addr = (uint32_t *)kgsl_sharedmem_convertaddr(device, pt_base,
- ib1_base, &memsize);
+ ib1_addr = (uint32_t *)adreno_convertaddr(device, pt_base,
+ ib1_base, ib1_size*sizeof(uint32_t));
if (!ib1_addr)
return;
@@ -466,7 +464,7 @@
const uint32_t *rb_vaddr;
int num_item = 0;
int read_idx, write_idx;
- unsigned int ts_processed, rb_memsize;
+ unsigned int ts_processed;
static struct ib_list ib_list;
@@ -681,11 +679,16 @@
KGSL_LOG_DUMP(device, "RB: rd_addr:%8.8x rb_size:%d num_item:%d\n",
cp_rb_base, rb_count<<2, num_item);
- rb_vaddr = (const uint32_t *)kgsl_sharedmem_convertaddr(device,
- cur_pt_base, cp_rb_base, &rb_memsize);
+
+ if (adreno_dev->ringbuffer.buffer_desc.gpuaddr != cp_rb_base)
+ KGSL_LOG_POSTMORTEM_WRITE(device,
+ "rb address mismatch, should be 0x%08x\n",
+ adreno_dev->ringbuffer.buffer_desc.gpuaddr);
+
+ rb_vaddr = adreno_dev->ringbuffer.buffer_desc.hostptr;
if (!rb_vaddr) {
KGSL_LOG_POSTMORTEM_WRITE(device,
- "Can't fetch vaddr for CP_RB_BASE\n");
+ "rb has no kernel mapping!\n");
goto error_vfree;
}
diff --git a/drivers/gpu/msm/kgsl.c b/drivers/gpu/msm/kgsl.c
index 53b9e8a..7a42dcd 100644
--- a/drivers/gpu/msm/kgsl.c
+++ b/drivers/gpu/msm/kgsl.c
@@ -33,6 +33,7 @@
#include "kgsl_log.h"
#include "kgsl_sharedmem.h"
#include "kgsl_device.h"
+#include "kgsl_trace.h"
#undef MODULE_PARAM_PREFIX
#define MODULE_PARAM_PREFIX "kgsl."
@@ -773,9 +774,7 @@
BUG_ON(private == NULL);
list_for_each_entry(entry, &private->mem_list, list) {
- if (gpuaddr >= entry->memdesc.gpuaddr &&
- ((gpuaddr + size) <=
- (entry->memdesc.gpuaddr + entry->memdesc.size))) {
+ if (kgsl_gpuaddr_in_memdesc(&entry->memdesc, gpuaddr, size)) {
result = entry;
break;
}
@@ -785,20 +784,6 @@
}
EXPORT_SYMBOL(kgsl_sharedmem_find_region);
-uint8_t *kgsl_gpuaddr_to_vaddr(const struct kgsl_memdesc *memdesc,
- unsigned int gpuaddr, unsigned int *size)
-{
- BUG_ON(memdesc->hostptr == NULL);
-
- if (memdesc->gpuaddr == 0 || (gpuaddr < memdesc->gpuaddr ||
- gpuaddr >= memdesc->gpuaddr + memdesc->size))
- return NULL;
-
- *size = memdesc->size - (gpuaddr - memdesc->gpuaddr);
- return memdesc->hostptr + (gpuaddr - memdesc->gpuaddr);
-}
-EXPORT_SYMBOL(kgsl_gpuaddr_to_vaddr);
-
/*call all ioctl sub functions with driver locked*/
static long kgsl_ioctl_device_getproperty(struct kgsl_device_private *dev_priv,
unsigned int cmd, void *data)
@@ -847,10 +832,14 @@
dev_priv->device->active_cnt++;
+ trace_kgsl_waittimestamp_entry(dev_priv->device, param);
+
result = dev_priv->device->ftbl->waittimestamp(dev_priv->device,
param->timestamp,
param->timeout);
+ trace_kgsl_waittimestamp_exit(dev_priv->device, result);
+
/* Fire off any pending suspend operations that are in flight */
INIT_COMPLETION(dev_priv->device->suspend_gate);
@@ -975,6 +964,8 @@
¶m->timestamp,
param->flags);
+ trace_kgsl_issueibcmds(dev_priv->device, param, result);
+
if (result != 0)
goto free_ibdesc;
@@ -1008,6 +999,8 @@
dev_priv->device->ftbl->readtimestamp(dev_priv->device,
param->type);
+ trace_kgsl_readtimestamp(dev_priv->device, param);
+
return 0;
}
@@ -1671,11 +1664,6 @@
result = -EINVAL;
goto done;
}
- if (!entry->memdesc.hostptr)
- entry->memdesc.hostptr =
- kgsl_gpuaddr_to_vaddr(&entry->memdesc,
- param->gpuaddr, &entry->memdesc.size);
-
if (!entry->memdesc.hostptr) {
KGSL_CORE_ERR("invalid hostptr with gpuaddr %08x\n",
param->gpuaddr);
@@ -1897,7 +1885,7 @@
KGSL_IOCTL_FUNC(IOCTL_KGSL_CFF_USER_EVENT,
kgsl_ioctl_cff_user_event, 0),
KGSL_IOCTL_FUNC(IOCTL_KGSL_TIMESTAMP_EVENT,
- kgsl_ioctl_timestamp_event, 0),
+ kgsl_ioctl_timestamp_event, 1),
};
static long kgsl_ioctl(struct file *filep, unsigned int cmd, unsigned long arg)
@@ -2447,8 +2435,6 @@
if (result)
goto err;
- kgsl_mmu_set_mmutype(ksgl_mmu_type);
-
return 0;
err:
diff --git a/drivers/gpu/msm/kgsl.h b/drivers/gpu/msm/kgsl.h
index 3bb722d..1135adb 100644
--- a/drivers/gpu/msm/kgsl.h
+++ b/drivers/gpu/msm/kgsl.h
@@ -145,8 +145,6 @@
#endif
void kgsl_mem_entry_destroy(struct kref *kref);
-uint8_t *kgsl_gpuaddr_to_vaddr(const struct kgsl_memdesc *memdesc,
- unsigned int gpuaddr, unsigned int *size);
struct kgsl_mem_entry *kgsl_sharedmem_find_region(
struct kgsl_process_private *private, unsigned int gpuaddr,
size_t size);
@@ -175,14 +173,24 @@
#endif
static inline int kgsl_gpuaddr_in_memdesc(const struct kgsl_memdesc *memdesc,
- unsigned int gpuaddr)
+ unsigned int gpuaddr, unsigned int size)
{
- if (gpuaddr >= memdesc->gpuaddr && (gpuaddr + sizeof(unsigned int)) <=
- (memdesc->gpuaddr + memdesc->size)) {
+ if (gpuaddr >= memdesc->gpuaddr &&
+ ((gpuaddr + size) <= (memdesc->gpuaddr + memdesc->size))) {
return 1;
}
return 0;
}
+static inline uint8_t *kgsl_gpuaddr_to_vaddr(const struct kgsl_memdesc *memdesc,
+ unsigned int gpuaddr)
+{
+ if (memdesc->hostptr == NULL || memdesc->gpuaddr == 0 ||
+ (gpuaddr < memdesc->gpuaddr ||
+ gpuaddr >= memdesc->gpuaddr + memdesc->size))
+ return NULL;
+
+ return memdesc->hostptr + (gpuaddr - memdesc->gpuaddr);
+}
static inline int timestamp_cmp(unsigned int new, unsigned int old)
{
diff --git a/drivers/gpu/msm/kgsl_cffdump.c b/drivers/gpu/msm/kgsl_cffdump.c
index aa33152..e9455cb 100644
--- a/drivers/gpu/msm/kgsl_cffdump.c
+++ b/drivers/gpu/msm/kgsl_cffdump.c
@@ -231,8 +231,6 @@
spin_lock(&cffdump_lock);
if (opcode == CFF_OP_WRITE_MEM) {
- if (op1 < 0x40000000 || op1 >= 0x60000000)
- KGSL_CORE_ERR("addr out-of-range: op1=%08x", op1);
if ((cff_op_write_membuf.addr != op1 &&
cff_op_write_membuf.count)
|| (cff_op_write_membuf.count == MEMBUF_SIZE))
@@ -360,15 +358,7 @@
void kgsl_cffdump_open(enum kgsl_deviceid device_id)
{
- /*TODO: move this to where we can report correct gmemsize*/
- unsigned int va_base;
-
- if (cpu_is_msm8x60() || cpu_is_msm8960() || cpu_is_msm8930())
- va_base = 0x40000000;
- else
- va_base = 0x20000000;
-
- kgsl_cffdump_memory_base(device_id, va_base,
+ kgsl_cffdump_memory_base(device_id, KGSL_PAGETABLE_BASE,
CONFIG_MSM_KGSL_PAGE_TABLE_SIZE, SZ_256K);
}
@@ -401,8 +391,6 @@
bool clean_cache)
{
const void *src;
- uint host_size;
- uint physaddr;
if (!kgsl_cff_dump_enable)
return;
@@ -422,13 +410,9 @@
}
memdesc = &entry->memdesc;
}
- BUG_ON(memdesc->gpuaddr == 0);
- BUG_ON(gpuaddr == 0);
- physaddr = kgsl_get_realaddr(memdesc) + (gpuaddr - memdesc->gpuaddr);
-
- src = kgsl_gpuaddr_to_vaddr(memdesc, gpuaddr, &host_size);
- if (src == NULL || host_size < sizebytes) {
- KGSL_CORE_ERR("did not find mapping for "
+ src = (uint *)kgsl_gpuaddr_to_vaddr(memdesc, gpuaddr);
+ if (memdesc->hostptr == NULL) {
+ KGSL_CORE_ERR("no kernel mapping for "
"gpuaddr: 0x%08x, m->host: 0x%p, phys: 0x%08x\n",
gpuaddr, memdesc->hostptr, memdesc->physaddr);
return;
@@ -444,7 +428,6 @@
KGSL_CACHE_OP_INV);
}
- BUG_ON(physaddr > 0x66000000 && physaddr < 0x66ffffff);
while (sizebytes > 3) {
cffdump_printline(-1, CFF_OP_WRITE_MEM, gpuaddr, *(uint *)src,
0, 0, 0);
@@ -462,7 +445,6 @@
if (!kgsl_cff_dump_enable)
return;
- BUG_ON(addr > 0x66000000 && addr < 0x66ffffff);
while (sizebytes > 3) {
/* Use 32bit memory writes as long as there's at least
* 4 bytes left */
@@ -575,7 +557,6 @@
{
static uint level; /* recursion level */
bool ret = true;
- uint host_size;
uint *hostaddr, *hoststart;
int dwords_left = sizedwords; /* dwords left in the current command
buffer */
@@ -596,10 +577,9 @@
}
memdesc = &entry->memdesc;
}
-
- hostaddr = (uint *)kgsl_gpuaddr_to_vaddr(memdesc, gpuaddr, &host_size);
+ hostaddr = (uint *)kgsl_gpuaddr_to_vaddr(memdesc, gpuaddr);
if (hostaddr == NULL) {
- KGSL_CORE_ERR("did not find mapping for "
+ KGSL_CORE_ERR("no kernel mapping for "
"gpuaddr: 0x%08x\n", gpuaddr);
return true;
}
@@ -608,14 +588,9 @@
level++;
- if (!memdesc->physaddr) {
- KGSL_CORE_ERR("no physaddr");
- } else {
- mb();
- kgsl_cache_range_op((struct kgsl_memdesc *)memdesc,
+ mb();
+ kgsl_cache_range_op((struct kgsl_memdesc *)memdesc,
KGSL_CACHE_OP_INV);
- }
-
#ifdef DEBUG
pr_info("kgsl: cffdump: ib: gpuaddr:0x%08x, wc:%d, hptr:%p\n",
gpuaddr, sizedwords, hostaddr);
diff --git a/drivers/gpu/msm/kgsl_device.h b/drivers/gpu/msm/kgsl_device.h
index c88f16ef..3ef11ce 100644
--- a/drivers/gpu/msm/kgsl_device.h
+++ b/drivers/gpu/msm/kgsl_device.h
@@ -89,6 +89,7 @@
void (*power_stats)(struct kgsl_device *device,
struct kgsl_power_stats *stats);
void (*irqctrl)(struct kgsl_device *device, int state);
+ unsigned int (*gpuid)(struct kgsl_device *device);
/* Optional functions - these functions are not mandatory. The
driver will check that the function pointer is not NULL before
calling the hook */
@@ -240,6 +241,11 @@
return device->ftbl->idle(device, timeout);
}
+static inline unsigned int kgsl_gpuid(struct kgsl_device *device)
+{
+ return device->ftbl->gpuid(device);
+}
+
static inline int kgsl_create_device_sysfs_files(struct device *root,
const struct device_attribute **list)
{
@@ -277,10 +283,11 @@
static inline int kgsl_create_device_workqueue(struct kgsl_device *device)
{
- device->work_queue = create_workqueue(device->name);
+ device->work_queue = create_singlethread_workqueue(device->name);
if (!device->work_queue) {
- KGSL_DRV_ERR(device, "create_workqueue(%s) failed\n",
- device->name);
+ KGSL_DRV_ERR(device,
+ "create_singlethread_workqueue(%s) failed\n",
+ device->name);
return -EINVAL;
}
return 0;
diff --git a/drivers/gpu/msm/kgsl_mmu.c b/drivers/gpu/msm/kgsl_mmu.c
index 715b9d6..36248ef 100644
--- a/drivers/gpu/msm/kgsl_mmu.c
+++ b/drivers/gpu/msm/kgsl_mmu.c
@@ -22,6 +22,7 @@
#include "kgsl_mmu.h"
#include "kgsl_device.h"
#include "kgsl_sharedmem.h"
+#include "adreno_postmortem.h"
#define KGSL_MMU_ALIGN_SHIFT 13
#define KGSL_MMU_ALIGN_MASK (~((1 << KGSL_MMU_ALIGN_SHIFT) - 1))
diff --git a/drivers/gpu/msm/kgsl_sharedmem.c b/drivers/gpu/msm/kgsl_sharedmem.c
index b59761d..ec91b39 100644
--- a/drivers/gpu/msm/kgsl_sharedmem.c
+++ b/drivers/gpu/msm/kgsl_sharedmem.c
@@ -655,7 +655,7 @@
BUG_ON(memdesc == NULL || memdesc->hostptr == NULL);
BUG_ON(offsetbytes + sizeof(unsigned int) > memdesc->size);
- kgsl_cffdump_setmem(memdesc->physaddr + offsetbytes,
+ kgsl_cffdump_setmem(memdesc->gpuaddr + offsetbytes,
src, sizeof(uint));
writel_relaxed(src, memdesc->hostptr + offsetbytes);
return 0;
@@ -669,8 +669,8 @@
BUG_ON(memdesc == NULL || memdesc->hostptr == NULL);
BUG_ON(offsetbytes + sizebytes > memdesc->size);
- kgsl_cffdump_setmem(memdesc->physaddr + offsetbytes, value,
- sizebytes);
+ kgsl_cffdump_setmem(memdesc->gpuaddr + offsetbytes, value,
+ sizebytes);
memset(memdesc->hostptr + offsetbytes, value, sizebytes);
return 0;
}
diff --git a/drivers/gpu/msm/kgsl_trace.c b/drivers/gpu/msm/kgsl_trace.c
new file mode 100644
index 0000000..2bcca15
--- /dev/null
+++ b/drivers/gpu/msm/kgsl_trace.c
@@ -0,0 +1,19 @@
+/* Copyright (c) 2011, Code Aurora Forum. 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 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#include "kgsl.h"
+#include "kgsl_device.h"
+
+/* Instantiate tracepoints */
+#define CREATE_TRACE_POINTS
+#include "kgsl_trace.h"
diff --git a/drivers/gpu/msm/kgsl_trace.h b/drivers/gpu/msm/kgsl_trace.h
new file mode 100644
index 0000000..7c14ac1
--- /dev/null
+++ b/drivers/gpu/msm/kgsl_trace.h
@@ -0,0 +1,161 @@
+/* Copyright (c) 2011, Code Aurora Forum. 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 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#if !defined(_KGSL_TRACE_H) || defined(TRACE_HEADER_MULTI_READ)
+#define _KGSL_TRACE_H
+
+#undef TRACE_SYSTEM
+#define TRACE_SYSTEM kgsl
+#undef TRACE_INCLUDE_PATH
+#define TRACE_INCLUDE_PATH .
+#undef TRACE_INCLUDE_FILE
+#define TRACE_INCLUDE_FILE kgsl_trace
+
+#include <linux/tracepoint.h>
+
+struct kgsl_device;
+struct kgsl_ringbuffer_issueibcmds;
+struct kgsl_device_waittimestamp;
+
+/*
+ * Tracepoint for kgsl issue ib commands
+ */
+TRACE_EVENT(kgsl_issueibcmds,
+
+ TP_PROTO(struct kgsl_device *device,
+ struct kgsl_ringbuffer_issueibcmds *cmd, int result),
+
+ TP_ARGS(device, cmd, result),
+
+ TP_STRUCT__entry(
+ __string(device_name, device->name)
+ __field(unsigned int, drawctxt_id)
+ __field(unsigned int, ibdesc_addr)
+ __field(unsigned int, numibs)
+ __field(unsigned int, timestamp)
+ __field(unsigned int, flags)
+ __field(int, result)
+ ),
+
+ TP_fast_assign(
+ __assign_str(device_name, device->name);
+ __entry->drawctxt_id = cmd->drawctxt_id;
+ __entry->ibdesc_addr = cmd->ibdesc_addr;
+ __entry->numibs = cmd->numibs;
+ __entry->timestamp = cmd->timestamp;
+ __entry->flags = cmd->flags;
+ __entry->result = result;
+ ),
+
+ TP_printk(
+ "d_name=%s ctx=%u ib=%u numibs=%u timestamp=%u "
+ "flags=%u result=%d",
+ __get_str(device_name),
+ __entry->drawctxt_id,
+ __entry->ibdesc_addr,
+ __entry->numibs,
+ __entry->timestamp,
+ __entry->flags,
+ __entry->result
+ )
+);
+
+/*
+ * Tracepoint for kgsl readtimestamp
+ */
+TRACE_EVENT(kgsl_readtimestamp,
+
+ TP_PROTO(struct kgsl_device *device,
+ struct kgsl_cmdstream_readtimestamp *cmd),
+
+ TP_ARGS(device, cmd),
+
+ TP_STRUCT__entry(
+ __string(device_name, device->name)
+ __field(unsigned int, type)
+ __field(unsigned int, timestamp)
+ ),
+
+ TP_fast_assign(
+ __assign_str(device_name, device->name);
+ __entry->type = cmd->type;
+ __entry->timestamp = cmd->timestamp;
+ ),
+
+ TP_printk(
+ "d_name=%s type=%u timestamp=%u",
+ __get_str(device_name),
+ __entry->type,
+ __entry->timestamp
+ )
+);
+
+/*
+ * Tracepoint for kgsl waittimestamp entry
+ */
+TRACE_EVENT(kgsl_waittimestamp_entry,
+
+ TP_PROTO(struct kgsl_device *device,
+ struct kgsl_device_waittimestamp *cmd),
+
+ TP_ARGS(device, cmd),
+
+ TP_STRUCT__entry(
+ __string(device_name, device->name)
+ __field(unsigned int, timestamp)
+ __field(unsigned int, timeout)
+ ),
+
+ TP_fast_assign(
+ __assign_str(device_name, device->name);
+ __entry->timestamp = cmd->timestamp;
+ __entry->timeout = cmd->timeout;
+ ),
+
+ TP_printk(
+ "d_name=%s timestamp=%u timeout=%u",
+ __get_str(device_name),
+ __entry->timestamp,
+ __entry->timeout
+ )
+);
+
+/*
+ * Tracepoint for kgsl waittimestamp exit
+ */
+TRACE_EVENT(kgsl_waittimestamp_exit,
+
+ TP_PROTO(struct kgsl_device *device, int result),
+
+ TP_ARGS(device, result),
+
+ TP_STRUCT__entry(
+ __string(device_name, device->name)
+ __field(int, result)
+ ),
+
+ TP_fast_assign(
+ __assign_str(device_name, device->name);
+ __entry->result = result;
+ ),
+
+ TP_printk(
+ "d_name=%s result=%d",
+ __get_str(device_name),
+ __entry->result
+ )
+);
+#endif /* _KGSL_TRACE_H */
+
+/* This part must be outside protection */
+#include <trace/define_trace.h>
diff --git a/drivers/gpu/msm/z180.c b/drivers/gpu/msm/z180.c
index cdb9c23..cf74e64 100644
--- a/drivers/gpu/msm/z180.c
+++ b/drivers/gpu/msm/z180.c
@@ -18,6 +18,7 @@
#include "z180.h"
#include "z180_reg.h"
+#include "z180_trace.h"
#define DRIVER_VERSION_MAJOR 3
#define DRIVER_VERSION_MINOR 1
@@ -213,6 +214,8 @@
z180_regread(device, ADDR_VGC_IRQSTATUS >> 2, &status);
+ trace_kgsl_z180_irq_status(device, status);
+
if (status & GSL_VGC_INT_MASK) {
z180_regwrite(device,
ADDR_VGC_IRQSTATUS >> 2, status & GSL_VGC_INT_MASK);
@@ -885,6 +888,16 @@
}
}
+static unsigned int z180_gpuid(struct kgsl_device *device)
+{
+ /* Standard KGSL gpuid format:
+ * top word is 0x0002 for 2D or 0x0003 for 3D
+ * Bottom word is core specific identifer
+ */
+
+ return (0x0002 << 16) | 180;
+}
+
static const struct kgsl_functable z180_functable = {
/* Mandatory functions */
.regread = z180_regread,
@@ -902,6 +915,7 @@
.cleanup_pt = z180_cleanup_pt,
.power_stats = z180_power_stats,
.irqctrl = z180_irqctrl,
+ .gpuid = z180_gpuid,
/* Optional functions */
.drawctxt_create = NULL,
.drawctxt_destroy = z180_drawctxt_destroy,
diff --git a/drivers/gpu/msm/z180_trace.c b/drivers/gpu/msm/z180_trace.c
new file mode 100644
index 0000000..29b519c
--- /dev/null
+++ b/drivers/gpu/msm/z180_trace.c
@@ -0,0 +1,20 @@
+/* Copyright (c) 2011, Code Aurora Forum. 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 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#include "kgsl.h"
+#include "z180.h"
+#include "z180_reg.h"
+
+/* Instantiate tracepoints */
+#define CREATE_TRACE_POINTS
+#include "z180_trace.h"
diff --git a/drivers/gpu/msm/z180_trace.h b/drivers/gpu/msm/z180_trace.h
new file mode 100644
index 0000000..fbe1fe5
--- /dev/null
+++ b/drivers/gpu/msm/z180_trace.h
@@ -0,0 +1,60 @@
+/* Copyright (c) 2011, Code Aurora Forum. 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 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#if !defined(_Z180_TRACE_H) || defined(TRACE_HEADER_MULTI_READ)
+#define _Z180_TRACE_H
+
+#undef TRACE_SYSTEM
+#define TRACE_SYSTEM kgsl
+#undef TRACE_INCLUDE_PATH
+#define TRACE_INCLUDE_PATH .
+#undef TRACE_INCLUDE_FILE
+#define TRACE_INCLUDE_FILE z180_trace
+
+#include <linux/tracepoint.h>
+
+struct kgsl_device;
+
+/*
+ * Tracepoint for z180 irq. Includes status info
+ */
+TRACE_EVENT(kgsl_z180_irq_status,
+
+ TP_PROTO(struct kgsl_device *device, unsigned int status),
+
+ TP_ARGS(device, status),
+
+ TP_STRUCT__entry(
+ __string(device_name, device->name)
+ __field(unsigned int, status)
+ ),
+
+ TP_fast_assign(
+ __assign_str(device_name, device->name);
+ __entry->status = status;
+ ),
+
+ TP_printk(
+ "d_name=%s status=%s",
+ __get_str(device_name),
+ __entry->status ? __print_flags(__entry->status, "|",
+ { REG_VGC_IRQSTATUS__MH_MASK, "MH" },
+ { REG_VGC_IRQSTATUS__G2D_MASK, "G2D" },
+ { REG_VGC_IRQSTATUS__FIFO_MASK, "FIFO" }) : "None"
+ )
+);
+
+#endif /* _Z180_TRACE_H */
+
+/* This part must be outside protection */
+#include <trace/define_trace.h>
diff --git a/drivers/input/evdev.c b/drivers/input/evdev.c
index 5c5f9db..6e7dd68 100644
--- a/drivers/input/evdev.c
+++ b/drivers/input/evdev.c
@@ -400,7 +400,7 @@
struct evdev_client *client = file->private_data;
struct evdev *evdev = client->evdev;
struct input_event event;
- int retval;
+ int retval = 0;
if (count < input_event_size())
return -EINVAL;
diff --git a/drivers/input/misc/pmic8058-othc.c b/drivers/input/misc/pmic8058-othc.c
index a28e8e1..cac748a 100644
--- a/drivers/input/misc/pmic8058-othc.c
+++ b/drivers/input/misc/pmic8058-othc.c
@@ -536,19 +536,11 @@
struct pm8058_othc *dd =
container_of(work, struct pm8058_othc, detect_work.work);
- if (dd->othc_ir_state) {
- /* inserted */
- rc = pm8058_accessory_report(dd, 1);
- if (rc)
- pr_err("Accessory could not be detected\n");
- } else {
- /* removed */
- rc = pm8058_accessory_report(dd, 0);
- if (rc)
- pr_err("Accessory could not be detected\n");
- /* Clear existing switch state */
- dd->othc_sw_state = false;
- }
+ /* Accessory has been inserted */
+ rc = pm8058_accessory_report(dd, 1);
+ if (rc)
+ pr_err("Accessory insertion could not be detected\n");
+
enable_irq(dd->othc_irq_ir);
}
@@ -637,8 +629,6 @@
ktime_set((dd->switch_debounce_ms / 1000),
(dd->switch_debounce_ms % 1000) * 1000000), HRTIMER_MODE_REL);
- /* disable irq, this gets enabled in the workqueue */
- disable_irq_nosync(dd->othc_irq_ir);
/* Check the MIC_BIAS status, to check if inserted or removed */
rc = pm8xxx_read_irq_stat(dd->dev->parent, dd->othc_irq_ir);
@@ -648,8 +638,20 @@
}
dd->othc_ir_state = rc;
- schedule_delayed_work(&dd->detect_work,
+ if (dd->othc_ir_state) {
+ /* disable irq, this gets enabled in the workqueue */
+ disable_irq_nosync(dd->othc_irq_ir);
+ /* Accessory has been inserted, report with detection delay */
+ schedule_delayed_work(&dd->detect_work,
msecs_to_jiffies(dd->detection_delay_ms));
+ } else {
+ /* Accessory has been removed, report removal immediately */
+ rc = pm8058_accessory_report(dd, 0);
+ if (rc)
+ pr_err("Accessory removal could not be detected\n");
+ /* Clear existing switch state */
+ dd->othc_sw_state = false;
+ }
fail_ir:
return IRQ_HANDLED;
diff --git a/drivers/input/misc/pmic8xxx-pwrkey.c b/drivers/input/misc/pmic8xxx-pwrkey.c
index 2225b7a..f0da3e8 100644
--- a/drivers/input/misc/pmic8xxx-pwrkey.c
+++ b/drivers/input/misc/pmic8xxx-pwrkey.c
@@ -100,7 +100,9 @@
return -EINVAL;
}
- if (pdata->kpd_trigger_delay_us > 62500) {
+ /* Valid range of pwr key trigger delay is 1/64 sec to 2 seconds. */
+ if (pdata->kpd_trigger_delay_us > USEC_PER_SEC * 2 ||
+ pdata->kpd_trigger_delay_us < USEC_PER_SEC / 64) {
dev_err(&pdev->dev, "invalid power key trigger delay\n");
return -EINVAL;
}
@@ -124,8 +126,8 @@
pwr->phys = "pmic8xxx_pwrkey/input0";
pwr->dev.parent = &pdev->dev;
- delay = (pdata->kpd_trigger_delay_us << 10) / USEC_PER_SEC;
- delay = 1 + ilog2(delay);
+ delay = (pdata->kpd_trigger_delay_us << 6) / USEC_PER_SEC;
+ delay = ilog2(delay);
err = pm8xxx_readb(pdev->dev.parent, PON_CNTL_1, &pon_cntl);
if (err < 0) {
diff --git a/drivers/input/touchscreen/synaptics/rmi_f11.c b/drivers/input/touchscreen/synaptics/rmi_f11.c
index 9a23776..4caaf92 100644
--- a/drivers/input/touchscreen/synaptics/rmi_f11.c
+++ b/drivers/input/touchscreen/synaptics/rmi_f11.c
@@ -188,11 +188,7 @@
}
}
input_report_key(function_device->input,
- BTN_TOUCH, fingerDownCount);
- for (finger = 0; finger < (instanceData->sensorInfo->numberOfFingers - 1); finger++) {
- input_report_key(function_device->input,
- BTN_2 + finger, fingerDownCount >= (finger + 2));
- }
+ BTN_TOUCH, !!fingerDownCount);
for (finger = 0; finger < instanceData->sensorInfo->numberOfFingers; finger++) {
int reg;
@@ -269,14 +265,8 @@
}
#ifdef CONFIG_SYNA_MULTI_TOUCH
/* Report Multi-Touch events for each finger */
- /* major axis of touch area ellipse */
- input_report_abs(function_device->input, ABS_MT_TOUCH_MAJOR, Z);
- /* minor axis of touch area ellipse */
- input_report_abs(function_device->input, ABS_MT_WIDTH_MAJOR,
- max(Wx, Wy));
- /* Currently only 2 supported - 1 or 0 */
- input_report_abs(function_device->input, ABS_MT_ORIENTATION,
- (Wx > Wy ? 1 : 0));
+ input_report_abs(function_device->input,
+ ABS_MT_PRESSURE, Z);
input_report_abs(function_device->input, ABS_MT_POSITION_X, X);
input_report_abs(function_device->input, ABS_MT_POSITION_Y, Y);
@@ -284,7 +274,7 @@
/* Could be formed by keeping an id per position and assiging */
/* a new id when fingerStatus changes for that position.*/
input_report_abs(function_device->input, ABS_MT_TRACKING_ID,
- finger+1);
+ finger);
/* MT sync between fingers */
input_mt_sync(function_device->input);
#endif
@@ -297,17 +287,10 @@
instanceData->wasdown = false;
#ifdef CONFIG_SYNA_MULTI_TOUCH
- input_report_abs(function_device->input, ABS_MT_TOUCH_MAJOR, 0);
- input_report_abs(function_device->input, ABS_MT_WIDTH_MAJOR, 0);
- input_report_abs(function_device->input, ABS_MT_POSITION_X, instanceData->oldX);
- input_report_abs(function_device->input, ABS_MT_POSITION_Y, instanceData->oldY);
- input_report_abs(function_device->input, ABS_MT_TRACKING_ID, 1);
+ input_report_abs(function_device->input, ABS_MT_PRESSURE, 0);
+ input_report_key(function_device->input, BTN_TOUCH, 0);
input_mt_sync(function_device->input);
#endif
-
- input_report_abs(function_device->input, ABS_X, instanceData->oldX);
- input_report_abs(function_device->input, ABS_Y, instanceData->oldY);
- instanceData->oldX = instanceData->oldY = 0;
}
FN_11_relreport(rmifninfo);
@@ -468,10 +451,11 @@
input_set_abs_params(function_device->input, ABS_TOOL_WIDTH, 0, 15, 0, 0);
#ifdef CONFIG_SYNA_MULTI_TOUCH
- input_set_abs_params(function_device->input, ABS_MT_TOUCH_MAJOR, 0, 15, 0, 0);
- input_set_abs_params(function_device->input, ABS_MT_TOUCH_MINOR, 0, 15, 0, 0);
+ input_set_abs_params(function_device->input, ABS_MT_PRESSURE,
+ 0, 15, 0, 0);
input_set_abs_params(function_device->input, ABS_MT_ORIENTATION, 0, 1, 0, 0);
- input_set_abs_params(function_device->input, ABS_MT_TRACKING_ID, 1, 10, 0, 0);
+ input_set_abs_params(function_device->input, ABS_MT_TRACKING_ID,
+ 0, 10, 0, 0);
input_set_abs_params(function_device->input, ABS_MT_POSITION_X, xMin, xMax,
0, 0);
input_set_abs_params(function_device->input, ABS_MT_POSITION_Y, yMin, yMax,
@@ -536,8 +520,8 @@
set_bit(EV_ABS, function_device->input->evbit);
set_bit(EV_SYN, function_device->input->evbit);
set_bit(EV_KEY, function_device->input->evbit);
- set_bit(BTN_MISC, function_device->input->keybit);
- set_bit(KEY_OK, function_device->input->keybit);
+ set_bit(BTN_TOUCH, function_device->input->keybit);
+ set_bit(KEY_OK, function_device->input->keybit);
f11_set_abs_params(function_device);
diff --git a/drivers/media/radio/radio-iris-transport.c b/drivers/media/radio/radio-iris-transport.c
index ca98754..57b11c9 100644
--- a/drivers/media/radio/radio-iris-transport.c
+++ b/drivers/media/radio/radio-iris-transport.c
@@ -64,7 +64,7 @@
return;
}
- rc = smd_read_from_cb(hsmd->fm_channel, (void *)buf, len);
+ rc = smd_read(hsmd->fm_channel, (void *)buf, len);
memcpy(skb_put(skb, len), buf, len);
diff --git a/drivers/media/radio/radio-iris.c b/drivers/media/radio/radio-iris.c
index 5e70607..9a4a28c 100644
--- a/drivers/media/radio/radio-iris.c
+++ b/drivers/media/radio/radio-iris.c
@@ -648,6 +648,15 @@
return radio_hci_send_cmd(hdev, opcode, 0, NULL);
}
+static int hci_get_fm_trans_conf_req(struct radio_hci_dev *hdev,
+ unsigned long param)
+{
+ u16 opcode = 0;
+
+ opcode = hci_opcode_pack(HCI_OGF_FM_TRANS_CTRL_CMD_REQ,
+ HCI_OCF_FM_GET_TRANS_CONF_REQ);
+ return radio_hci_send_cmd(hdev, opcode, 0, NULL);
+}
static int hci_set_fm_recv_conf_req(struct radio_hci_dev *hdev,
unsigned long param)
{
@@ -1474,6 +1483,10 @@
msecs_to_jiffies(RADIO_HCI_TIMEOUT));
break;
+ case HCI_FM_GET_TX_CONFIG:
+ ret = radio_hci_request(hdev, hci_get_fm_trans_conf_req, arg,
+ msecs_to_jiffies(RADIO_HCI_TIMEOUT));
+ break;
default:
ret = -EINVAL;
break;
@@ -1502,6 +1515,7 @@
if (status)
return;
+
radio_hci_req_complete(hdev, status);
}
@@ -1531,6 +1545,19 @@
radio_hci_req_complete(hdev, rsp->status);
}
+static void hci_cc_fm_trans_get_conf_rsp(struct radio_hci_dev *hdev,
+ struct sk_buff *skb)
+{
+ struct hci_fm_get_trans_conf_rsp *rsp = (void *)skb->data;
+ struct iris_device *radio = video_get_drvdata(video_get_dev());
+
+ if (rsp->status)
+ return;
+ memcpy((void *)&radio->trans_conf, (void*)&rsp->trans_conf_rsp,
+ sizeof(rsp->trans_conf_rsp));
+ radio_hci_req_complete(hdev, rsp->status);
+}
+
static void hci_cc_fm_enable_rsp(struct radio_hci_dev *hdev,
struct sk_buff *skb)
{
@@ -1863,6 +1890,9 @@
hci_cc_do_calibration_rsp(hdev, skb);
break;
+ case hci_trans_ctrl_cmd_op_pack(HCI_OCF_FM_GET_TRANS_CONF_REQ):
+ hci_cc_fm_trans_get_conf_rsp(hdev, skb);
+ break;
default:
FMDERR("%s opcode 0x%x", hdev->name, opcode);
break;
@@ -2646,6 +2676,8 @@
retval = radio_hci_request(radio->fm_hdev,
hci_fm_tone_generator, arg,
msecs_to_jiffies(RADIO_HCI_TIMEOUT));
+ if (retval < 0)
+ FMDERR("Error while setting the tone %d", retval);
break;
case V4L2_CID_AUDIO_VOLUME:
break;
@@ -2673,12 +2705,12 @@
case FM_RECV:
retval = hci_cmd(HCI_FM_ENABLE_RECV_CMD,
radio->fm_hdev);
-
- radio->mode = FM_RECV;
-
- if (retval < 0)
+ if (retval < 0) {
FMDERR("Error while enabling RECV FM"
" %d\n", retval);
+ return retval;
+ }
+ radio->mode = FM_RECV;
radio->mute_mode.soft_mute = CTRL_ON;
retval = hci_set_fm_mute_mode(
&radio->mute_mode,
@@ -2715,10 +2747,14 @@
retval = hci_cmd(HCI_FM_ENABLE_TRANS_CMD,
radio->fm_hdev);
radio->mode = FM_TRANS;
-
- if (retval < 0)
+ if (retval < 0) {
FMDERR("Error while enabling TRANS FM"
" %d\n", retval);
+ return retval;
+ }
+ retval = hci_cmd(HCI_FM_GET_TX_CONFIG, radio->fm_hdev);
+ if (retval < 0)
+ FMDERR("get frequency failed %d\n", retval);
break;
case FM_OFF:
switch (radio->mode) {
@@ -2776,7 +2812,14 @@
case V4L2_CID_PRIVATE_IRIS_SRCH_CNT:
break;
case V4L2_CID_PRIVATE_IRIS_SPACING:
- radio->recv_conf.ch_spacing = ctrl->value;
+ if (radio->mode == FM_RECV) {
+ radio->recv_conf.ch_spacing = ctrl->value;
+ retval = hci_set_fm_recv_conf(
+ &radio->recv_conf,
+ radio->fm_hdev);
+ if (retval < 0)
+ FMDERR("Error in setting channel spacing");
+ }
break;
case V4L2_CID_PRIVATE_IRIS_EMPHASIS:
switch (radio->mode) {
@@ -2971,19 +3014,37 @@
if (tuner->index > 0)
return -EINVAL;
- retval = hci_cmd(HCI_FM_GET_STATION_PARAM_CMD, radio->fm_hdev);
- if (retval < 0)
- return retval;
+ if (radio->mode == FM_RECV) {
+ retval = hci_cmd(HCI_FM_GET_STATION_PARAM_CMD, radio->fm_hdev);
+ if (retval < 0) {
+ FMDERR("Failed to Get station params");
+ return retval;
+ }
+ tuner->type = V4L2_TUNER_RADIO;
+ tuner->rangelow =
+ radio->recv_conf.band_low_limit * TUNE_PARAM;
+ tuner->rangehigh =
+ radio->recv_conf.band_high_limit * TUNE_PARAM;
+ tuner->rxsubchans = V4L2_TUNER_SUB_MONO | V4L2_TUNER_SUB_STEREO;
+ tuner->capability = V4L2_TUNER_CAP_LOW;
+ tuner->signal = radio->fm_st_rsp.station_rsp.rssi;
+ tuner->audmode = radio->fm_st_rsp.station_rsp.stereo_prg;
+ tuner->afc = 0;
+ } else if (radio->mode == FM_TRANS) {
+ retval = hci_cmd(HCI_FM_GET_TX_CONFIG, radio->fm_hdev);
+ if (retval < 0) {
+ FMDERR("get Tx config failed %d\n", retval);
+ return retval;
+ } else {
+ tuner->type = V4L2_TUNER_RADIO;
+ tuner->rangelow =
+ radio->trans_conf.band_low_limit * TUNE_PARAM;
+ tuner->rangehigh =
+ radio->trans_conf.band_high_limit * TUNE_PARAM;
+ }
- tuner->type = V4L2_TUNER_RADIO;
- tuner->rangelow = radio->recv_conf.band_low_limit * TUNE_PARAM;
- tuner->rangehigh = radio->recv_conf.band_high_limit * TUNE_PARAM;
- tuner->rxsubchans = V4L2_TUNER_SUB_MONO | V4L2_TUNER_SUB_STEREO;
- tuner->capability = V4L2_TUNER_CAP_LOW;
- tuner->signal = radio->fm_st_rsp.station_rsp.rssi;
- tuner->audmode = radio->fm_st_rsp.station_rsp.stereo_prg;
- tuner->afc = 0;
-
+ } else
+ return -EINVAL;
return 0;
}
@@ -3013,16 +3074,13 @@
if (retval < 0)
FMDERR(": set tuner failed with %d\n", retval);
return retval;
- } else {
- if (radio->mode == FM_TRANS) {
+ } else if (radio->mode == FM_TRANS) {
radio->trans_conf.band_low_limit =
tuner->rangelow / TUNE_PARAM;
radio->trans_conf.band_high_limit =
tuner->rangehigh / TUNE_PARAM;
- } else {
- return -EINVAL;
- }
- }
+ } else
+ return -EINVAL;
return retval;
}
diff --git a/drivers/media/radio/radio-tavarua.c b/drivers/media/radio/radio-tavarua.c
index 5976424..d09f89f 100644
--- a/drivers/media/radio/radio-tavarua.c
+++ b/drivers/media/radio/radio-tavarua.c
@@ -118,6 +118,7 @@
int pi;
/*PS repeatcount for PS Tx */
int ps_repeatcount;
+ int enable_optimized_srch_alg;
};
/**************************************************************************
@@ -1162,6 +1163,169 @@
return 0;
}
+static int optimized_search_algorithm(struct tavarua_device *radio,
+ int region)
+{
+ unsigned char adie_type_bahma;
+ int retval = 0;
+ unsigned int rdsMask = 0;
+ unsigned char value;
+
+ adie_type_bahma = is_bahama();
+
+ switch (region) {
+ case TAVARUA_REGION_US:
+ /*
+ Radio band for all the 200KHz channel-spaced regions
+ coming under EUROPE too, have been set as TAVARUA_REGION_US.
+ */
+ FMDBG("%s: The region selected from APP is"
+ " : TAVARUA_REGION_US", __func__);
+ break;
+ case TAVARUA_REGION_EU:
+ /*
+ Radio band for all the 50KHz channel-spaced regions
+ coming under EUROPE, have been set as TAVARUA_REGION_EU.
+ */
+ FMDBG("%s: The region selected from APP is : "
+ "TAVARUA_REGION_EU", __func__);
+ break;
+ case TAVARUA_REGION_JAPAN:
+ /*
+ Radio band for the 100KHz channel-spaced JAPAN region
+ has been set as TAVARUA_REGION_JAPAN.
+ */
+ FMDBG("%s: The region selected from APP is"
+ " : TAVARUA_REGION_JAPAN", __func__);
+ break;
+ case TAVARUA_REGION_JAPAN_WIDE:
+ /*
+ Radio band for the 50KHz channel-spaced JAPAN WIDE region
+ has been set as TAVARUA_REGION_JAPAN_WIDE.
+ */
+ FMDBG("%s: The region selected from APP is"
+ " : TAVARUA_REGION_JAPAN_WIDE", __func__);
+ break;
+ case TAVARUA_REGION_OTHER:
+ /*
+ Radio band for all the 100KHz channel-spaced regions
+ including those coming under EUROPE have been set as
+ TAVARUA_REGION_OTHER.
+ */
+ FMDBG("%s: The region selected from APP is"
+ " : TAVARUA_REGION_OTHER", __func__);
+ break;
+ default:
+ pr_err("%s: Should not reach here.", __func__);
+ break;
+
+ }
+
+ /* Enable or Disable the 200KHz enforcer */
+ switch (region) {
+ case TAVARUA_REGION_US:
+ case TAVARUA_REGION_JAPAN:
+ case TAVARUA_REGION_OTHER:
+ /*
+ These are the 3 bands for which we need to enable the
+ 200KHz enforcer in ADVCTL reg.
+ */
+ if (adie_type_bahma) {
+ FMDBG("Adie type : Bahama\n");
+ FMDBG("%s: Enabling the 200KHz enforcer for"
+ " Region : %d", __func__, region);
+ /*Enable the 200KHz enforcer*/
+ retval = tavarua_read_registers(radio,
+ ADVCTRL, 1);
+ if (retval >= 0) {
+ rdsMask = radio->registers[ADVCTRL];
+ SET_REG_FIELD(rdsMask, ENF_SRCH200khz,
+ SRCH200KHZ_OFFSET, SRCH_MASK);
+ retval = tavarua_write_register(radio,
+ ADVCTRL, rdsMask);
+ } else
+ return retval;
+ } /* if Marimba do nothing */
+ break;
+ case TAVARUA_REGION_EU:
+ case TAVARUA_REGION_JAPAN_WIDE:
+ /*
+ These are the 2 bands for which we need to disable the
+ 200KHz enforcer in ADVCTL reg.
+ Radio band for all the 50KHz channel-spaced regions
+ coming under EUROPE have been set as TAVARUA_REGION_EU.
+ */
+ if (adie_type_bahma) {
+ FMDBG("Adie type : Bahama\n");
+ FMDBG("%s: Disabling the 200KHz enforcer for"
+ " Region : %d", __func__, region);
+ /*
+ Disable 200KHz enforcer for all 50 KHz
+ spaced regions.
+ */
+ retval = tavarua_read_registers(radio,
+ ADVCTRL, 1);
+ if (retval >= 0) {
+ rdsMask = radio->registers[ADVCTRL];
+ SET_REG_FIELD(rdsMask, NO_SRCH200khz,
+ SRCH200KHZ_OFFSET, SRCH_MASK);
+ retval = tavarua_write_register(radio,
+ ADVCTRL, rdsMask);
+ } else
+ return retval;
+ } /* if Marimba do nothing */
+ break;
+ default:
+ FMDBG("%s: Defaulting in case of Enabling/Disabling"
+ "the 200KHz Enforcer", __func__);
+ break;
+ }
+
+ /* Set channel spacing */
+ switch (region) {
+ case TAVARUA_REGION_US:
+ if (adie_type_bahma) {
+ FMDBG("Adie type : Bahama\n");
+ /*
+ Configuring all 200KHZ spaced regions as 100KHz due to
+ change in the new Bahma FM SoC search algorithm.
+ */
+ value = FM_CH_SPACE_100KHZ;
+ } else {
+ FMDBG("Adie type : Marimba\n");
+ value = FM_CH_SPACE_200KHZ;
+ }
+ break;
+ case TAVARUA_REGION_JAPAN:
+ case TAVARUA_REGION_OTHER:
+ if (adie_type_bahma) {
+ FMDBG("Adie type : Bahama\n");
+ FMDBG("%s: Configuring the channel-spacing as 50KHz"
+ "for the Region : %d", __func__, region);
+ /*
+ Configuring all 100KHZ spaced regions as 50KHz due to
+ change in the new Bahma FM SoC search algorithm.
+ */
+ value = FM_CH_SPACE_50KHZ;
+ } else {
+ FMDBG("Adie type : Marimba\n");
+ value = FM_CH_SPACE_100KHZ;
+ }
+ break;
+ case TAVARUA_REGION_EU:
+ case TAVARUA_REGION_JAPAN_WIDE:
+ value = FM_CH_SPACE_50KHZ;
+ break;
+ default:
+ FMDBG("%s: Defualting in case of Channel-Spacing", __func__);
+ break;
+ }
+
+ SET_REG_FIELD(radio->registers[RDCTRL], value,
+ RDCTRL_CHSPACE_OFFSET, RDCTRL_CHSPACE_MASK);
+
+ return retval;
+}
/*************************************************************************
* fops/IOCTL helper functions
************************************************************************/
@@ -1255,14 +1419,11 @@
switch (region) {
case TAVARUA_REGION_US:
case TAVARUA_REGION_EU:
- case TAVARUA_REGION_JAPAN_WIDE:
SET_REG_FIELD(radio->registers[RDCTRL], 0,
RDCTRL_BAND_OFFSET, RDCTRL_BAND_MASK);
break;
+ case TAVARUA_REGION_JAPAN_WIDE:
case TAVARUA_REGION_JAPAN:
- SET_REG_FIELD(radio->registers[RDCTRL], 1,
- RDCTRL_BAND_OFFSET, RDCTRL_BAND_MASK);
- break;
default:
retval = sync_read_xfr(radio, RADIO_CONFIG, xfr_buf);
if (retval < 0) {
@@ -1286,85 +1447,6 @@
break;
}
- /* Enable/Disable the 200KHz enforcer for respectiver regions */
- switch (region) {
- case TAVARUA_REGION_US:
- if (adie_type_bahma) {
- FMDBG("Adie type : Bahama\n");
- /*Enable the 200KHz enforcer*/
- retval = tavarua_read_registers(radio,
- ADVCTRL, 1);
- if (retval >= 0) {
- rdsMask = radio->registers[ADVCTRL];
- SET_REG_FIELD(rdsMask, ENF_SRCH200khz,
- SRCH200KHZ_OFFSET, SRCH_MASK);
- msleep(TAVARUA_DELAY);
- retval = tavarua_write_register(radio,
- ADVCTRL, rdsMask);
- } else
- return retval;
- } /* if Marimba do nothing */
- break;
- case TAVARUA_REGION_EU:
- case TAVARUA_REGION_JAPAN:
- case TAVARUA_REGION_JAPAN_WIDE:
- default:
- if (adie_type_bahma) {
- FMDBG("Adie type : Bahama\n");
- /*
- Disable 200KHz enforcer for all 100/50 KHz
- spaced regions.
- */
- retval = tavarua_read_registers(radio,
- ADVCTRL, 1);
- if (retval >= 0) {
- rdsMask = radio->registers[ADVCTRL];
- SET_REG_FIELD(rdsMask, NO_SRCH200khz,
- SRCH200KHZ_OFFSET, SRCH_MASK);
- msleep(TAVARUA_DELAY);
- retval = tavarua_write_register(radio,
- ADVCTRL, rdsMask);
- } else
- return retval;
- } /* if Marimba do nothing */
- break;
- }
-
- /* Set channel spacing */
- switch (region) {
- case TAVARUA_REGION_US:
- if (adie_type_bahma) {
- FMDBG("Adie type : Bahama\n");
- /*
- Configuring all 200KHZ spaced regions as
- 100KHz due to change in the new Bahma
- FM SoC search algorithm.
- */
- value = FM_CH_SPACE_100KHZ;
- } else {
- FMDBG("Adie type : Marimba\n");
- value = FM_CH_SPACE_200KHZ;
- }
- break;
- case TAVARUA_REGION_EU:
- case TAVARUA_REGION_JAPAN:
- value = FM_CH_SPACE_100KHZ;
- break;
- case TAVARUA_REGION_JAPAN_WIDE:
- value = FM_CH_SPACE_50KHZ;
- break;
- default:
- /*
- Set the channel spacing as configured from
- the upper layers.
- */
- value = radio->region_params.spacing;
- break;
- }
-
- SET_REG_FIELD(radio->registers[RDCTRL], value,
- RDCTRL_CHSPACE_OFFSET, RDCTRL_CHSPACE_MASK);
-
/* Set De-emphasis and soft band range*/
switch (region) {
case TAVARUA_REGION_US:
@@ -1403,13 +1485,6 @@
if (retval < 0)
return retval;
- FMDBG("RDCTRL: %x\n", radio->registers[RDCTRL]);
- retval = tavarua_write_register(radio, RDCTRL,
- radio->registers[RDCTRL]);
- if (retval < 0) {
- FMDERR("Could not set region in rdctrl\n");
- return retval;
- }
/* setting soft band */
switch (region) {
@@ -1430,6 +1505,101 @@
break;
}
radio->region_params.region = region;
+
+ /* Check for the FM Algorithm used */
+ if (radio->enable_optimized_srch_alg) {
+ FMDBG("Optimized Srch Algorithm!!!");
+ optimized_search_algorithm(radio, region);
+ } else {
+ FMDBG("Native Srch Algorithm!!!");
+ /* Enable/Disable the 200KHz enforcer */
+ switch (region) {
+ case TAVARUA_REGION_US:
+ if (adie_type_bahma) {
+ FMDBG("Adie type : Bahama\n");
+ /*Enable the 200KHz enforcer*/
+ retval = tavarua_read_registers(radio,
+ ADVCTRL, 1);
+ if (retval >= 0) {
+ rdsMask = radio->registers[ADVCTRL];
+ SET_REG_FIELD(rdsMask, ENF_SRCH200khz,
+ SRCH200KHZ_OFFSET, SRCH_MASK);
+ retval = tavarua_write_register(radio,
+ ADVCTRL, rdsMask);
+ } else
+ return retval;
+ } /* if Marimba do nothing */
+ break;
+ case TAVARUA_REGION_EU:
+ case TAVARUA_REGION_JAPAN:
+ case TAVARUA_REGION_JAPAN_WIDE:
+ default:
+ if (adie_type_bahma) {
+ FMDBG("Adie type : Bahama\n");
+ /*
+ Disable 200KHz enforcer for all 100/50 KHz
+ spaced regions.
+ */
+ retval = tavarua_read_registers(radio,
+ ADVCTRL, 1);
+ if (retval >= 0) {
+ rdsMask = radio->registers[ADVCTRL];
+ SET_REG_FIELD(rdsMask, NO_SRCH200khz,
+ SRCH200KHZ_OFFSET, SRCH_MASK);
+ retval = tavarua_write_register(radio,
+ ADVCTRL, rdsMask);
+ } else
+ return retval;
+ } /* if Marimba do nothing */
+ break;
+ }
+
+ /* Set channel spacing */
+ switch (region) {
+ case TAVARUA_REGION_US:
+ if (adie_type_bahma) {
+ FMDBG("Adie type : Bahama\n");
+ /*
+ Configuring all 200KHZ spaced regions as
+ 100KHz due to change in the new Bahma
+ FM SoC search algorithm.
+ */
+ value = FM_CH_SPACE_100KHZ;
+ } else {
+ FMDBG("Adie type : Marimba\n");
+ value = FM_CH_SPACE_200KHZ;
+ }
+ break;
+ case TAVARUA_REGION_JAPAN:
+ value = FM_CH_SPACE_100KHZ;
+ break;
+ case TAVARUA_REGION_EU:
+ case TAVARUA_REGION_JAPAN_WIDE:
+ value = FM_CH_SPACE_50KHZ;
+ break;
+ default:
+ /*
+ Set the channel spacing as configured from
+ the upper layers.
+ */
+ value = radio->region_params.spacing;
+ break;
+ }
+
+ SET_REG_FIELD(radio->registers[RDCTRL], value,
+ RDCTRL_CHSPACE_OFFSET, RDCTRL_CHSPACE_MASK);
+
+ }
+
+ /* Write the config values into RDCTL register */
+ FMDBG("RDCTRL: %x\n", radio->registers[RDCTRL]);
+ retval = tavarua_write_register(radio, RDCTRL,
+ radio->registers[RDCTRL]);
+ if (retval < 0) {
+ FMDERR("Could not set region in rdctrl\n");
+ return retval;
+ }
+
return retval;
}
@@ -2839,6 +3009,11 @@
}
}
break;
+ case V4L2_CID_PRIVATE_TAVARUA_SRCH_ALGORITHM:
+ radio->enable_optimized_srch_alg = ctrl->value;
+ FMDBG("V4L2_CID_PRIVATE_TAVARUA_SRCH_ALGORITHM : %d",
+ radio->enable_optimized_srch_alg);
+ break;
case V4L2_CID_PRIVATE_TAVARUA_REGION:
retval = tavarua_set_region(radio, ctrl->value);
break;
@@ -3658,7 +3833,7 @@
printk(KERN_INFO DRIVER_NAME "%s: radio suspend\n\n", __func__);
if (radio) {
users = atomic_read(&radio->users);
- if (users) {
+ if (!users) {
retval = tavarua_disable_interrupts(radio);
if (retval < 0) {
printk(KERN_INFO DRIVER_NAME
@@ -3690,7 +3865,7 @@
if (radio) {
users = atomic_read(&radio->users);
- if (users) {
+ if (!users) {
retval = tavarua_setup_interrupts(radio,
(radio->registers[RDCTRL] & 0x03));
if (retval < 0) {
diff --git a/drivers/media/video/msm/csi/msm_csid.c b/drivers/media/video/msm/csi/msm_csid.c
index fb809c9..7a0ee4d 100644
--- a/drivers/media/video/msm/csi/msm_csid.c
+++ b/drivers/media/video/msm/csi/msm_csid.c
@@ -97,6 +97,7 @@
val |= 0x1 << 10;
val |= 0x1 << 11;
val |= 0x1 << 12;
+ val |= 0x1 << 13;
val |= 0x1 << 28;
msm_io_w(val, csidbase + CSID_CORE_CTRL_ADDR);
diff --git a/drivers/media/video/msm/csi/msm_csiphy.c b/drivers/media/video/msm/csi/msm_csiphy.c
index b62ec84..109b3dd 100644
--- a/drivers/media/video/msm/csi/msm_csiphy.c
+++ b/drivers/media/video/msm/csi/msm_csiphy.c
@@ -79,7 +79,7 @@
msm_io_w(0x1, csiphybase + MIPI_CSIPHY_T_WAKEUP_CFG0_ADDR);
for (i = 0; i < csiphy_params->lane_cnt; i++) {
- msm_io_w(0x10, csiphybase + MIPI_CSIPHY_LNn_CFG1_ADDR + 0x40*i);
+ msm_io_w(0x00, csiphybase + MIPI_CSIPHY_LNn_CFG1_ADDR + 0x40*i);
msm_io_w(0x5F, csiphybase + MIPI_CSIPHY_LNn_CFG2_ADDR + 0x40*i);
msm_io_w(csiphy_params->settle_cnt,
csiphybase + MIPI_CSIPHY_LNn_CFG3_ADDR + 0x40*i);
diff --git a/drivers/media/video/msm/flash.c b/drivers/media/video/msm/flash.c
index f1a24cc..6985f3c 100644
--- a/drivers/media/video/msm/flash.c
+++ b/drivers/media/video/msm/flash.c
@@ -293,6 +293,7 @@
if (sc628a_client) {
gpio_set_value_cansleep(external->led_en, 1);
gpio_set_value_cansleep(external->led_flash_en, 1);
+ usleep_range(2000, 3000);
}
rc = sc628a_i2c_write_b_flash(0x02, 0x06);
break;
@@ -301,6 +302,7 @@
if (sc628a_client) {
gpio_set_value_cansleep(external->led_en, 1);
gpio_set_value_cansleep(external->led_flash_en, 1);
+ usleep_range(2000, 3000);
}
rc = sc628a_i2c_write_b_flash(0x02, 0x49);
break;
diff --git a/drivers/media/video/msm/io/msm_camera_i2c.c b/drivers/media/video/msm/io/msm_camera_i2c.c
index 019d6e1..23db5f6b 100644
--- a/drivers/media/video/msm/io/msm_camera_i2c.c
+++ b/drivers/media/video/msm/io/msm_camera_i2c.c
@@ -138,34 +138,155 @@
return rc;
}
+int32_t msm_camera_i2c_set_mask(struct msm_camera_i2c_client *client,
+ uint16_t addr, uint16_t mask,
+ enum msm_camera_i2c_data_type data_type, uint16_t set_mask)
+{
+ int32_t rc;
+ uint16_t reg_data;
+
+ rc = msm_camera_i2c_read(client, addr, ®_data, data_type);
+ if (rc < 0) {
+ S_I2C_DBG("%s read fail\n", __func__);
+ return rc;
+ }
+ S_I2C_DBG("%s addr: 0x%x data: 0x%x setmask: 0x%x\n",
+ __func__, addr, reg_data, mask);
+
+ if (set_mask)
+ reg_data |= mask;
+ else
+ reg_data &= ~mask;
+ S_I2C_DBG("%s write: 0x%x\n", __func__, reg_data);
+
+ rc = msm_camera_i2c_write(client, addr, reg_data, data_type);
+ if (rc < 0)
+ S_I2C_DBG("%s write fail\n", __func__);
+
+ return rc;
+}
+
+int32_t msm_camera_i2c_compare(struct msm_camera_i2c_client *client,
+ uint16_t addr, uint16_t data,
+ enum msm_camera_i2c_data_type data_type)
+{
+ int32_t rc = -EIO;
+ uint16_t reg_data = 0;
+ int data_len = 0;
+ switch (data_type) {
+ case MSM_CAMERA_I2C_BYTE_DATA:
+ case MSM_CAMERA_I2C_WORD_DATA:
+ data_len = data_type;
+ break;
+ case MSM_CAMERA_I2C_SET_BYTE_MASK:
+ case MSM_CAMERA_I2C_UNSET_BYTE_MASK:
+ data_len = MSM_CAMERA_I2C_BYTE_DATA;
+ break;
+ case MSM_CAMERA_I2C_SET_WORD_MASK:
+ case MSM_CAMERA_I2C_UNSET_WORD_MASK:
+ data_len = MSM_CAMERA_I2C_WORD_DATA;
+ break;
+ default:
+ pr_err("%s: Unsupport data type: %d\n", __func__, data_type);
+ break;
+ }
+
+ rc = msm_camera_i2c_read(client,
+ addr, ®_data, data_len);
+ if (rc < 0)
+ return rc;
+
+ rc = 0;
+ switch (data_type) {
+ case MSM_CAMERA_I2C_BYTE_DATA:
+ case MSM_CAMERA_I2C_WORD_DATA:
+ if (data == reg_data)
+ return rc;
+ break;
+ case MSM_CAMERA_I2C_SET_BYTE_MASK:
+ case MSM_CAMERA_I2C_SET_WORD_MASK:
+ if ((reg_data & data) == data)
+ return rc;
+ break;
+ case MSM_CAMERA_I2C_UNSET_BYTE_MASK:
+ case MSM_CAMERA_I2C_UNSET_WORD_MASK:
+ if (!(reg_data & data))
+ return rc;
+ break;
+ default:
+ pr_err("%s: Unsupport data type: %d\n", __func__, data_type);
+ break;
+ }
+
+ S_I2C_DBG("%s: Register and data does not match\n", __func__);
+ rc = 1;
+ return rc;
+}
+
+int32_t msm_camera_i2c_poll(struct msm_camera_i2c_client *client,
+ uint16_t addr, uint16_t data,
+ enum msm_camera_i2c_data_type data_type)
+{
+ int32_t rc = -EIO;
+ int i;
+ S_I2C_DBG("%s: addr: 0x%x data: 0x%x dt: %d\n",
+ __func__, addr, data, data_type);
+
+ for (i = 0; i < 20; i++) {
+ rc = msm_camera_i2c_compare(client,
+ addr, data, data_type);
+ if (rc == 0 || rc < 0)
+ break;
+ usleep_range(10000, 11000);
+ }
+ return rc;
+}
+
int32_t msm_camera_i2c_write_tbl(struct msm_camera_i2c_client *client,
- struct msm_camera_i2c_reg_conf *reg_conf_tbl, uint8_t size,
+ struct msm_camera_i2c_reg_conf *reg_conf_tbl, uint16_t size,
enum msm_camera_i2c_data_type data_type)
{
int i;
int32_t rc = -EFAULT;
for (i = 0; i < size; i++) {
- rc = msm_camera_i2c_write(
- client,
- reg_conf_tbl->reg_addr,
- reg_conf_tbl->reg_data, data_type);
- if (rc < 0)
- break;
- reg_conf_tbl++;
- }
- return rc;
-}
+ enum msm_camera_i2c_data_type dt;
+ if (reg_conf_tbl->dt == 0)
+ dt = data_type;
+ else
+ dt = reg_conf_tbl->dt;
-int32_t msm_camera_i2c_write_dt_tbl(struct msm_camera_i2c_client *client,
- struct msm_camera_i2c_reg_dt_conf *reg_conf_tbl, uint16_t size)
-{
- int i;
- int32_t rc = -EFAULT;
- for (i = 0; i < size; i++) {
- rc = msm_camera_i2c_write(
- client,
- reg_conf_tbl->reg_addr,
- reg_conf_tbl->reg_data, reg_conf_tbl->dt);
+ switch (dt) {
+ case MSM_CAMERA_I2C_BYTE_DATA:
+ case MSM_CAMERA_I2C_WORD_DATA:
+ rc = msm_camera_i2c_write(
+ client,
+ reg_conf_tbl->reg_addr,
+ reg_conf_tbl->reg_data, dt);
+ break;
+ case MSM_CAMERA_I2C_SET_BYTE_MASK:
+ rc = msm_camera_i2c_set_mask(client,
+ reg_conf_tbl->reg_addr, reg_conf_tbl->reg_data,
+ MSM_CAMERA_I2C_BYTE_DATA, 1);
+ break;
+ case MSM_CAMERA_I2C_UNSET_BYTE_MASK:
+ rc = msm_camera_i2c_set_mask(client,
+ reg_conf_tbl->reg_addr, reg_conf_tbl->reg_data,
+ MSM_CAMERA_I2C_BYTE_DATA, 0);
+ break;
+ case MSM_CAMERA_I2C_SET_WORD_MASK:
+ rc = msm_camera_i2c_set_mask(client,
+ reg_conf_tbl->reg_addr, reg_conf_tbl->reg_data,
+ MSM_CAMERA_I2C_WORD_DATA, 1);
+ break;
+ case MSM_CAMERA_I2C_UNSET_WORD_MASK:
+ rc = msm_camera_i2c_set_mask(client,
+ reg_conf_tbl->reg_addr, reg_conf_tbl->reg_data,
+ MSM_CAMERA_I2C_WORD_DATA, 0);
+ break;
+ default:
+ pr_err("%s: Unsupport data type: %d\n", __func__, dt);
+ break;
+ }
if (rc < 0)
break;
reg_conf_tbl++;
@@ -202,7 +323,7 @@
else
*data = buf[0] << 8 | buf[1];
- S_I2C_DBG("%s addr = 0x%x data: 0x%x", __func__, addr, *data);
+ S_I2C_DBG("%s addr = 0x%x data: 0x%x\n", __func__, addr, *data);
return rc;
}
@@ -243,15 +364,16 @@
struct msm_camera_i2c_conf_array *array, uint16_t index)
{
int32_t rc;
- if (array[index].data_type != MSM_CAMERA_I2C_HYBRID_DATA) {
- rc = msm_camera_i2c_write_tbl(client,
- (struct msm_camera_i2c_reg_conf *) array[index].conf,
- array[index].size, array[index].data_type);
- } else {
- rc = msm_camera_i2c_write_dt_tbl(client,
- (struct msm_camera_i2c_reg_dt_conf *) array[index].conf,
- array[index].size);
- }
+ if (array[index].pre_process != NULL)
+ array[index].pre_process();
+
+ rc = msm_camera_i2c_write_tbl(client,
+ (struct msm_camera_i2c_reg_conf *) array[index].conf,
+ array[index].size, array[index].data_type);
+
+ if (array[index].post_process != NULL)
+ array[index].post_process();
+
if (array[index].delay > 20)
msleep(array[index].delay);
else
diff --git a/drivers/media/video/msm/io/msm_camera_i2c.h b/drivers/media/video/msm/io/msm_camera_i2c.h
index 201cd03..05b3960 100644
--- a/drivers/media/video/msm/io/msm_camera_i2c.h
+++ b/drivers/media/video/msm/io/msm_camera_i2c.h
@@ -35,28 +35,28 @@
enum msm_camera_i2c_reg_addr_type addr_type;
};
-struct msm_camera_i2c_reg_conf {
- uint16_t reg_addr;
- uint16_t reg_data;
-};
-
enum msm_camera_i2c_data_type {
MSM_CAMERA_I2C_BYTE_DATA = 1,
MSM_CAMERA_I2C_WORD_DATA,
- MSM_CAMERA_I2C_HYBRID_DATA,
+ MSM_CAMERA_I2C_SET_BYTE_MASK,
+ MSM_CAMERA_I2C_UNSET_BYTE_MASK,
+ MSM_CAMERA_I2C_SET_WORD_MASK,
+ MSM_CAMERA_I2C_UNSET_WORD_MASK,
};
-struct msm_camera_i2c_reg_dt_conf {
+struct msm_camera_i2c_reg_conf {
uint16_t reg_addr;
uint16_t reg_data;
enum msm_camera_i2c_data_type dt;
};
struct msm_camera_i2c_conf_array {
- void *conf;
+ struct msm_camera_i2c_reg_conf *conf;
uint16_t size;
uint16_t delay;
enum msm_camera_i2c_data_type data_type;
+ int (*pre_process) (void);
+ int (*post_process) (void);
};
int32_t msm_camera_i2c_rxdata(struct msm_camera_i2c_client *client,
@@ -79,12 +79,21 @@
int32_t msm_camera_i2c_write_seq(struct msm_camera_i2c_client *client,
uint16_t addr, uint8_t *data, uint16_t num_byte);
-int32_t msm_camera_i2c_write_tbl(struct msm_camera_i2c_client *client,
- struct msm_camera_i2c_reg_conf *reg_conf_tbl, uint8_t size,
+int32_t msm_camera_i2c_set_mask(struct msm_camera_i2c_client *client,
+ uint16_t addr, uint16_t mask,
+ enum msm_camera_i2c_data_type data_type, uint16_t flag);
+
+int32_t msm_camera_i2c_compare(struct msm_camera_i2c_client *client,
+ uint16_t addr, uint16_t data,
enum msm_camera_i2c_data_type data_type);
-int32_t msm_camera_i2c_write_dt_tbl(struct msm_camera_i2c_client *client,
- struct msm_camera_i2c_reg_dt_conf *reg_conf_tbl, uint16_t size);
+int32_t msm_camera_i2c_poll(struct msm_camera_i2c_client *client,
+ uint16_t addr, uint16_t data,
+ enum msm_camera_i2c_data_type data_type);
+
+int32_t msm_camera_i2c_write_tbl(struct msm_camera_i2c_client *client,
+ struct msm_camera_i2c_reg_conf *reg_conf_tbl, uint16_t size,
+ enum msm_camera_i2c_data_type data_type);
int32_t msm_sensor_write_conf_array(struct msm_camera_i2c_client *client,
struct msm_camera_i2c_conf_array *array, uint16_t index);
diff --git a/drivers/media/video/msm/msm.h b/drivers/media/video/msm/msm.h
index f11e43f..3e3b9c8 100644
--- a/drivers/media/video/msm/msm.h
+++ b/drivers/media/video/msm/msm.h
@@ -485,6 +485,10 @@
int msm_mctl_pp_done(
struct msm_cam_media_controller *p_mctl,
void __user *arg);
+int msm_mctl_pp_divert_done(
+ struct msm_cam_media_controller *p_mctl,
+ void __user *arg);
+
#endif /* __KERNEL__ */
#endif /* _MSM_H */
diff --git a/drivers/media/video/msm/msm_io_7x27a.c b/drivers/media/video/msm/msm_io_7x27a.c
index b1f9532..7a83721 100644
--- a/drivers/media/video/msm/msm_io_7x27a.c
+++ b/drivers/media/video/msm/msm_io_7x27a.c
@@ -288,11 +288,6 @@
clk_set_rate(clk, rate);
}
-void msm_camio_clk_set_min_rate(struct clk *clk, int rate)
-{
- clk_set_min_rate(clk, rate);
-}
-
static irqreturn_t msm_io_csi_irq(int irq_num, void *data)
{
uint32_t irq;
diff --git a/drivers/media/video/msm/msm_io_8960.c b/drivers/media/video/msm/msm_io_8960.c
index 1293c7b..ec18a93 100644
--- a/drivers/media/video/msm/msm_io_8960.c
+++ b/drivers/media/video/msm/msm_io_8960.c
@@ -346,7 +346,7 @@
case CAMIO_JPEG_CLK:
camio_jpeg_clk =
clk = clk_get(NULL, "ijpeg_clk");
- clk_set_min_rate(clk, 144000000);
+ clk_set_rate(clk, 153600000);
break;
case CAMIO_JPEG_PCLK:
@@ -414,11 +414,6 @@
clk_set_rate(clk, rate);
}
-void msm_camio_clk_set_min_rate(struct clk *clk, int rate)
-{
- clk_set_min_rate(clk, rate);
-}
-
int msm_camio_jpeg_clk_disable(void)
{
int rc = 0;
diff --git a/drivers/media/video/msm/msm_io_8x60.c b/drivers/media/video/msm/msm_io_8x60.c
index 2262aa4..9620d8b 100644
--- a/drivers/media/video/msm/msm_io_8x60.c
+++ b/drivers/media/video/msm/msm_io_8x60.c
@@ -344,7 +344,8 @@
case CAMIO_VPE_CLK:
camio_vpe_clk =
clk = clk_get(NULL, "vpe_clk");
- msm_camio_clk_set_min_rate(camio_vpe_clk, vpe_clk_rate);
+ vpe_clk_rate = clk_round_rate(camio_vpe_clk, vpe_clk_rate);
+ clk_set_rate(camio_vpe_clk, vpe_clk_rate);
break;
case CAMIO_VPE_PCLK:
@@ -457,11 +458,6 @@
clk_set_rate(clk, rate);
}
-void msm_camio_clk_set_min_rate(struct clk *clk, int rate)
-{
- clk_set_min_rate(clk, rate);
-}
-
static irqreturn_t msm_io_csi_irq(int irq_num, void *data)
{
uint32_t irq;
diff --git a/drivers/media/video/msm/msm_io_vfe31.c b/drivers/media/video/msm/msm_io_vfe31.c
index f770ce9..91dbc8f 100644
--- a/drivers/media/video/msm/msm_io_vfe31.c
+++ b/drivers/media/video/msm/msm_io_vfe31.c
@@ -117,6 +117,7 @@
static struct resource *camifpadio, *csiio;
void __iomem *camifpadbase, *csibase;
static uint32_t vpe_clk_rate;
+static uint32_t jpeg_clk_rate;
static struct regulator_bulk_data regs[] = {
{ .supply = "gp2", .min_uV = 2600000, .max_uV = 2600000 },
@@ -317,7 +318,8 @@
case CAMIO_JPEG_CLK:
camio_jpeg_clk =
clk = clk_get(NULL, "jpeg_clk");
- clk_set_min_rate(clk, 144000000);
+ jpeg_clk_rate = clk_round_rate(clk, 144000000);
+ clk_set_rate(clk, jpeg_clk_rate);
break;
case CAMIO_JPEG_PCLK:
camio_jpeg_pclk =
@@ -326,7 +328,8 @@
case CAMIO_VPE_CLK:
camio_vpe_clk =
clk = clk_get(NULL, "vpe_clk");
- msm_camio_clk_set_min_rate(clk, vpe_clk_rate);
+ vpe_clk_rate = clk_round_rate(clk, vpe_clk_rate);
+ clk_set_rate(clk, vpe_clk_rate);
break;
default:
break;
@@ -420,11 +423,6 @@
clk_set_rate(clk, rate);
}
-void msm_camio_clk_set_min_rate(struct clk *clk, int rate)
-{
- clk_set_min_rate(clk, rate);
-}
-
static irqreturn_t msm_io_csi_irq(int irq_num, void *data)
{
uint32_t irq;
diff --git a/drivers/media/video/msm/msm_isp.c b/drivers/media/video/msm/msm_isp.c
index e4d4f27..0a1516b 100644
--- a/drivers/media/video/msm/msm_isp.c
+++ b/drivers/media/video/msm/msm_isp.c
@@ -268,6 +268,10 @@
struct msm_sync *sync =
(struct msm_sync *)v4l2_get_subdev_hostdata(sd);
struct msm_vpe_resp *vdata = (struct msm_vpe_resp *)arg;
+ if (sync == NULL) {
+ pr_err("%s: VPE subdev hostdata not set\n", __func__);
+ return -EINVAL;
+ }
msm_mctl_pp_notify(&sync->pcam_sync->mctl,
(struct msm_mctl_pp_frame_info *)vdata->extdata);
diff --git a/drivers/media/video/msm/msm_mctl.c b/drivers/media/video/msm/msm_mctl.c
index a3cf004..73fd383 100644
--- a/drivers/media/video/msm/msm_mctl.c
+++ b/drivers/media/video/msm/msm_mctl.c
@@ -299,6 +299,9 @@
case MSM_CAM_IOCTL_PICT_PP:
rc = msm_mctl_set_pp_key(p_mctl, (void __user *)arg);
break;
+ case MSM_CAM_IOCTL_PICT_PP_DIVERT_DONE:
+ rc = msm_mctl_pp_divert_done(p_mctl, (void __user *)arg);
+ break;
case MSM_CAM_IOCTL_PICT_PP_DONE:
rc = msm_mctl_pp_done(p_mctl, (void __user *)arg);
break;
diff --git a/drivers/media/video/msm/msm_mctl_buf.c b/drivers/media/video/msm/msm_mctl_buf.c
index c7c7cf6..7a0cc02 100644
--- a/drivers/media/video/msm/msm_mctl_buf.c
+++ b/drivers/media/video/msm/msm_mctl_buf.c
@@ -97,8 +97,15 @@
if (buf->state == MSM_BUFFER_STATE_INITIALIZED)
return rc;
- buf_type = (vb->num_planes == 1) ? VIDEOBUF2_SINGLE_PLANE
- : VIDEOBUF2_MULTIPLE_PLANES;
+ if (pcam_inst->plane_info.buffer_type ==
+ V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE)
+ buf_type = VIDEOBUF2_MULTIPLE_PLANES;
+ else if (pcam_inst->plane_info.buffer_type ==
+ V4L2_BUF_TYPE_VIDEO_CAPTURE)
+ buf_type = VIDEOBUF2_SINGLE_PLANE;
+ else
+ return -EINVAL;
+
if (buf_type == VIDEOBUF2_SINGLE_PLANE) {
offset.sp_off.y_off = pcam_inst->plane_info.sp_y_offset;
offset.sp_off.cbcr_off =
diff --git a/drivers/media/video/msm/msm_mctl_pp.c b/drivers/media/video/msm/msm_mctl_pp.c
index 8236dae..77f963c 100644
--- a/drivers/media/video/msm/msm_mctl_pp.c
+++ b/drivers/media/video/msm/msm_mctl_pp.c
@@ -49,7 +49,7 @@
return -ENOMEM;
}
D("%s: msm_cam_evt_divert_frame=%d",
- __func__, sizeof(struct msm_cam_evt_divert_frame));
+ __func__, sizeof(struct msm_cam_evt_divert_frame));
memset(&v4l2_evt, 0, sizeof(v4l2_evt));
v4l2_evt.type = V4L2_EVENT_PRIVATE_START +
MSM_CAM_RESP_DIV_FRAME_EVT_MSG;
@@ -82,7 +82,7 @@
image_mode = MSM_V4L2_EXT_CAPTURE_MODE_PREVIEW;
if (p_mctl->pp_info.pp_key & pp_key)
*pp_divert_type = OUTPUT_TYPE_P;
- if (p_mctl->pp_info.pp_ctrl.pp_msg_type == OUTPUT_TYPE_P)
+ if (p_mctl->pp_info.pp_ctrl.pp_msg_type & OUTPUT_TYPE_P)
*pp_type = OUTPUT_TYPE_P;
break;
case VFE_MSG_OUTPUT_S:
@@ -90,15 +90,15 @@
image_mode = MSM_V4L2_EXT_CAPTURE_MODE_MAIN;
if (p_mctl->pp_info.pp_key & pp_key)
*pp_divert_type = OUTPUT_TYPE_S;
- if (p_mctl->pp_info.pp_ctrl.pp_msg_type == OUTPUT_TYPE_S)
+ if (p_mctl->pp_info.pp_ctrl.pp_msg_type & OUTPUT_TYPE_S)
*pp_type = OUTPUT_TYPE_P;
break;
case VFE_MSG_OUTPUT_V:
- if (p_mctl->pp_info.pp_ctrl.pp_msg_type == OUTPUT_TYPE_V)
+ if (p_mctl->pp_info.pp_ctrl.pp_msg_type & OUTPUT_TYPE_V)
*pp_type = OUTPUT_TYPE_V;
break;
case VFE_MSG_OUTPUT_T:
- if (p_mctl->pp_info.pp_ctrl.pp_msg_type == OUTPUT_TYPE_T)
+ if (p_mctl->pp_info.pp_ctrl.pp_msg_type & OUTPUT_TYPE_T)
*pp_type = OUTPUT_TYPE_T;
break;
default:
@@ -142,10 +142,8 @@
div.op_mode = pcam_inst->pcam->op_mode;
div.inst_idx = pcam_inst->my_index;
div.node_idx = pcam_inst->pcam->vnode_id;
- p_mctl->pp_info.cur_frame_id[pcam_inst->image_mode]++;
- if (p_mctl->pp_info.cur_frame_id[pcam_inst->image_mode] == 0)
- p_mctl->pp_info.cur_frame_id[pcam_inst->image_mode]++;
- div.frame.frame_id =
+ p_mctl->pp_info.cur_frame_id[pcam_inst->image_mode] = frame_id;
+ div.frame.frame_id =
p_mctl->pp_info.cur_frame_id[pcam_inst->image_mode];
div.frame.handle = (uint32_t)vb;
msm_mctl_gettimeofday(&div.frame.timestamp);
@@ -160,7 +158,7 @@
/* This buffer contains only 1 plane. Use the
* single planar structure to store the info.*/
div.frame.num_planes = 1;
- div.frame.sp.phy_addr =
+ div.frame.sp.phy_addr =
videobuf2_to_pmem_contig(&vb->vidbuf, 0);
div.frame.sp.addr_offset = mem->addr_offset;
div.frame.sp.y_off = 0;
@@ -582,28 +580,17 @@
sizeof(divert_pp)))
return -EFAULT;
D("%s: PP_PATH, path=%d",
- __func__, divert_pp.path);
+ __func__, divert_pp.path);
spin_lock_irqsave(&p_mctl->pp_info.lock, flags);
- p_mctl->pp_info.pp_ctrl.pp_msg_type = divert_pp.path;
+ if (divert_pp.enable)
+ p_mctl->pp_info.pp_ctrl.pp_msg_type |= divert_pp.path;
+ else
+ p_mctl->pp_info.pp_ctrl.pp_msg_type &= ~divert_pp.path;
spin_unlock_irqrestore(&p_mctl->pp_info.lock, flags);
- D("%s: pp path = %d", __func__,
- p_mctl->pp_info.pp_ctrl.pp_msg_type);
+ D("%s: pp path = 0x%x", __func__,
+ p_mctl->pp_info.pp_ctrl.pp_msg_type);
break;
}
- case MCTL_CMD_DIVERT_FRAME_PP_DONE: {
- struct msm_frame_buffer *buf = NULL;
- if (copy_from_user(&pp_buffer, pp_cmd->value,
- sizeof(pp_buffer)))
- return -EFAULT;
- buf = (struct msm_frame_buffer *)pp_buffer.buf_handle;
- msg_type = msm_mctl_pp_path_to_msg_type(
- pp_buffer.path);
- if (msm_mctl_buf_del(p_mctl, msg_type, buf) == 0) {
- vb2_buffer_done(&buf->vidbuf,
- VB2_BUF_STATE_DONE);
- }
- }
- break;
default:
rc = -EPERM;
break;
@@ -843,7 +830,7 @@
memset(&p_mctl->pp_info.div_frame[image_mode],
0, sizeof(buf));
if (p_mctl->pp_info.cur_frame_id[image_mode] !=
- frame.frame_id) {
+ frame.frame_id) {
/* dirty frame. should not pass to app */
dirty = 1;
}
@@ -862,3 +849,49 @@
return rc;
}
+int msm_mctl_pp_divert_done(
+ struct msm_cam_media_controller *p_mctl,
+ void __user *arg)
+{
+ struct msm_pp_frame frame;
+ int msg_type, image_mode, rc = 0;
+ int dirty = 0;
+ struct msm_free_buf buf;
+ unsigned long flags;
+
+ if (copy_from_user(&frame, arg, sizeof(frame)))
+ return -EFAULT;
+
+ spin_lock_irqsave(&p_mctl->pp_info.lock, flags);
+ switch (frame.path) {
+ case OUTPUT_TYPE_P:
+ msg_type = VFE_MSG_OUTPUT_P;
+ image_mode = MSM_V4L2_EXT_CAPTURE_MODE_PREVIEW;
+ break;
+ case OUTPUT_TYPE_S:
+ msg_type = VFE_MSG_OUTPUT_S;
+ image_mode = MSM_V4L2_EXT_CAPTURE_MODE_MAIN;
+ break;
+ case OUTPUT_TYPE_V:
+ msg_type = VFE_MSG_OUTPUT_V;
+ image_mode = MSM_V4L2_EXT_CAPTURE_MODE_VIDEO;
+ break;
+ case OUTPUT_TYPE_T:
+ default:
+ rc = -EFAULT;
+ goto err;
+ }
+ if (frame.num_planes > 1)
+ buf.ch_paddr[0] = frame.mp[0].phy_addr;
+ else
+ buf.ch_paddr[0] = frame.sp.phy_addr;
+ spin_unlock_irqrestore(&p_mctl->pp_info.lock, flags);
+ /* here buf.addr is phy_addr */
+ rc = msm_mctl_buf_done_pp(p_mctl, msg_type, &buf, dirty);
+ return rc;
+err:
+ spin_unlock_irqrestore(&p_mctl->pp_info.lock, flags);
+ return rc;
+}
+
+
diff --git a/drivers/media/video/msm/msm_vfe32.c b/drivers/media/video/msm/msm_vfe32.c
index c5cc55c..d34d5b1 100644
--- a/drivers/media/video/msm/msm_vfe32.c
+++ b/drivers/media/video/msm/msm_vfe32.c
@@ -1461,6 +1461,45 @@
cmdp_local, (vfe32_cmd[cmd->id].length));
}
break;
+ case VFE_CMD_CHROMA_SUP_UPDATE:
+ case VFE_CMD_CHROMA_SUP_CFG:{
+ cmdp = kmalloc(cmd->length, GFP_ATOMIC);
+ if (!cmdp) {
+ rc = -ENOMEM;
+ goto proc_general_done;
+ }
+ if (copy_from_user(cmdp,
+ (void __user *)(cmd->value),
+ cmd->length)) {
+ rc = -EFAULT;
+ goto proc_general_done;
+ }
+ cmdp_local = cmdp;
+ msm_io_memcpy(vfe32_ctrl->vfebase + V32_CHROMA_SUP_OFF,
+ cmdp_local, 4);
+
+ cmdp_local += 1;
+ new_val = *cmdp_local;
+ /* Incrementing with 4 so as to point to the 2nd Register as
+ * the 2nd register has the mce_enable bit
+ */
+ old_val = msm_io_r(vfe32_ctrl->vfebase +
+ V32_CHROMA_SUP_OFF + 4);
+ old_val &= ~MCE_EN_MASK;
+ new_val = new_val | old_val;
+ msm_io_memcpy(vfe32_ctrl->vfebase + V32_CHROMA_SUP_OFF + 4,
+ &new_val, 4);
+ cmdp_local += 1;
+
+ old_val = msm_io_r(vfe32_ctrl->vfebase +
+ V32_CHROMA_SUP_OFF + 8);
+ new_val = *cmdp_local;
+ old_val &= ~MCE_Q_K_MASK;
+ new_val = new_val | old_val;
+ msm_io_memcpy(vfe32_ctrl->vfebase + V32_CHROMA_SUP_OFF + 8,
+ &new_val, 4);
+ }
+ break;
case VFE_CMD_BLACK_LEVEL_CFG:
rc = -EFAULT;
goto proc_general_done;
@@ -2223,17 +2262,17 @@
CDBG("%s: PCA Rolloff Ram0\n", __func__);
for (i = 0 ; i < V33_PCA_ROLL_OFF_TABLE_SIZE * 2; i++) {
- temp2 = (i == (V33_PCA_ROLL_OFF_TABLE_SIZE - 1));
+ temp2 = (i == (V33_PCA_ROLL_OFF_TABLE_SIZE));
if (old_val && temp2)
vfe32_program_dmi_cfg(ROLLOFF_RAM1_BANK1);
else if (!old_val && temp2)
vfe32_program_dmi_cfg(ROLLOFF_RAM1_BANK0);
+ *cmdp_local = msm_io_r(vfe32_ctrl->vfebase +
+ VFE33_DMI_DATA_LO);
*(cmdp_local + 1) =
msm_io_r(vfe32_ctrl->vfebase +
VFE33_DMI_DATA_HI);
- *cmdp_local = msm_io_r(vfe32_ctrl->vfebase +
- VFE33_DMI_DATA_LO);
CDBG("%s: %08x%08x\n", __func__,
*(cmdp_local + 1), *cmdp_local);
cmdp_local += 2;
diff --git a/drivers/media/video/msm/msm_vpe.c b/drivers/media/video/msm/msm_vpe.c
index 658f911..2f693ea 100644
--- a/drivers/media/video/msm/msm_vpe.c
+++ b/drivers/media/video/msm/msm_vpe.c
@@ -668,6 +668,7 @@
atomic_set(&vpe_init_done, 0);
return rc;
}
+ v4l2_set_subdev_hostdata(sd, data);
spin_lock_init(&vpe_ctrl->lock);
CDBG("%s:end", __func__);
return rc;
diff --git a/drivers/media/video/msm/sensors/imx074_v4l2.c b/drivers/media/video/msm/sensors/imx074_v4l2.c
index 2923e5d..f721441 100644
--- a/drivers/media/video/msm/sensors/imx074_v4l2.c
+++ b/drivers/media/video/msm/sensors/imx074_v4l2.c
@@ -51,8 +51,8 @@
{0x0383, 0x03}, /*x_odd_inc*/
{0x0385, 0x01}, /*y_even_inc*/
{0x0387, 0x03}, /*y_odd_inc*/
- {0x3001, 0x00}, /*hmodeadd*/
- {0x3016, 0x06}, /*vmodeadd*/
+ {0x3001, 0x80}, /*hmodeadd*/
+ {0x3016, 0x16}, /*vmodeadd*/
{0x3069, 0x24}, /*vapplinepos_start*/
{0x306b, 0x53}, /*vapplinepos_end*/
{0x3086, 0x00}, /*shutter*/
@@ -164,7 +164,7 @@
.frame_length_lines = 0x62D,
.vt_pixel_clk = 216000000,
.op_pixel_clk = 216000000,
- .binning_factor = 1,
+ .binning_factor = 2,
},
};
diff --git a/drivers/mfd/pm8921-core.c b/drivers/mfd/pm8921-core.c
index 51d2224..373aaf7 100644
--- a/drivers/mfd/pm8921-core.c
+++ b/drivers/mfd/pm8921-core.c
@@ -39,9 +39,11 @@
#define PM8921_VERSION_MASK 0xFFF0
#define PM8921_VERSION_VALUE 0x06F0
+#define PM8922_VERSION_VALUE 0x0AF0
#define PM8921_REVISION_MASK 0x000F
#define REG_PM8921_PON_CNTRL_3 0x01D
+#define REG_PM8921_PON_CNTRL_4 0x01E
#define PM8921_RESTART_REASON_MASK 0x07
#define SINGLE_IRQ_RESOURCE(_name, _irq) \
@@ -109,6 +111,9 @@
if ((pmic->rev_registers & PM8921_VERSION_MASK) == PM8921_VERSION_VALUE)
version = PM8XXX_VERSION_8921;
+ else if ((pmic->rev_registers & PM8921_VERSION_MASK)
+ == PM8922_VERSION_VALUE)
+ version = PM8XXX_VERSION_8922;
return version;
}
@@ -365,8 +370,11 @@
int ret = 0, irq_base = 0;
struct pm_irq_chip *irq_chip;
static struct mfd_cell *mfd_regulators;
+ enum pm8xxx_version version;
int i;
+ version = pm8xxx_get_version(pmic->dev);
+
if (pdata->irq_pdata) {
pdata->irq_pdata->irq_cdata.nirqs = PM8921_NR_IRQS;
pdata->irq_pdata->irq_cdata.base_addr = REG_IRQ_BASE;
@@ -619,6 +627,13 @@
[PM8XXX_REVISION_8921_3p0] = "3.0",
};
+static const char * const pm8922_rev_names[] = {
+ [PM8XXX_REVISION_8922_TEST] = "test",
+ [PM8XXX_REVISION_8922_1p0] = "1.0",
+ [PM8XXX_REVISION_8922_1p1] = "1.1",
+ [PM8XXX_REVISION_8922_2p0] = "2.0",
+};
+
static int __devinit pm8921_probe(struct platform_device *pdev)
{
const struct pm8921_platform_data *pdata = pdev->dev.platform_data;
@@ -665,13 +680,18 @@
/* Print out human readable version and revision names. */
version = pm8xxx_get_version(pmic->dev);
+ revision = pm8xxx_get_revision(pmic->dev);
if (version == PM8XXX_VERSION_8921) {
- revision = pm8xxx_get_revision(pmic->dev);
if (revision >= 0 && revision < ARRAY_SIZE(pm8921_rev_names))
revision_name = pm8921_rev_names[revision];
pr_info("PMIC version: PM8921 rev %s\n", revision_name);
+ } else if (version == PM8XXX_VERSION_8922) {
+ if (revision >= 0 && revision < ARRAY_SIZE(pm8922_rev_names))
+ revision_name = pm8922_rev_names[revision];
+ pr_info("PMIC version: PM8922 rev %s\n", revision_name);
} else {
- WARN_ON(version != PM8XXX_VERSION_8921);
+ WARN_ON(version != PM8XXX_VERSION_8921
+ && version != PM8XXX_VERSION_8922);
}
/* Log human readable restart reason */
@@ -683,6 +703,14 @@
val &= PM8921_RESTART_REASON_MASK;
pr_info("PMIC Restart Reason: %s\n", pm8921_restart_reason[val]);
+ /* Set power-on-reset to 3 seconds */
+ val = 0xBB;
+ rc = msm_ssbi_write(pdev->dev.parent, REG_PM8921_PON_CNTRL_4, &val, 1);
+ if (rc) {
+ pr_err("Cannot write power-on-reset rc=%d\n", rc);
+ goto err;
+ }
+
rc = pm8921_add_subdevices(pdata, pmic);
if (rc) {
pr_err("Cannot add subdevices rc=%d\n", rc);
diff --git a/drivers/mfd/pm8xxx-pwm.c b/drivers/mfd/pm8xxx-pwm.c
index 5b4f7e3..f65a183 100644
--- a/drivers/mfd/pm8xxx-pwm.c
+++ b/drivers/mfd/pm8xxx-pwm.c
@@ -1360,7 +1360,8 @@
version = pm8xxx_get_version(chip->dev->parent);
if (version == PM8XXX_VERSION_8921 ||
- version == PM8XXX_VERSION_8058) {
+ version == PM8XXX_VERSION_8058 ||
+ version == PM8XXX_VERSION_8922) {
chip->is_lpg_supported = 1;
}
if (chip->is_lpg_supported) {
diff --git a/drivers/misc/Makefile b/drivers/misc/Makefile
index 79f78bf..385f8ff 100644
--- a/drivers/misc/Makefile
+++ b/drivers/misc/Makefile
@@ -66,3 +66,4 @@
obj-$(CONFIG_PMIC8058_MISC) += pmic8058-misc.o
obj-$(CONFIG_PMIC8058_BATTALARM) += pmic8058-batt-alarm.o
obj-$(CONFIG_TZCOM) += tzcom.o
+obj-$(CONFIG_QFP_FUSE) += qfp_fuse.o
diff --git a/drivers/misc/isa1200.c b/drivers/misc/isa1200.c
index a58c7d6..31c79a0 100644
--- a/drivers/misc/isa1200.c
+++ b/drivers/misc/isa1200.c
@@ -187,7 +187,7 @@
rc = isa1200_write_reg(client, ISA1200_HCTRL1, value);
if (rc < 0) {
pr_err("%s: i2c write failure\n", __func__);
- return rc;
+ goto reset_gpios;
}
if (haptic->pdata->mode_ctrl == PWM_GEN_MODE) {
@@ -224,6 +224,10 @@
reset_hctrl1:
i2c_smbus_write_byte_data(client, ISA1200_HCTRL1,
ISA1200_HCTRL1_RESET);
+reset_gpios:
+ gpio_set_value_cansleep(haptic->pdata->hap_en_gpio, 0);
+ if (haptic->is_len_gpio_valid == true)
+ gpio_set_value_cansleep(haptic->pdata->hap_len_gpio, 0);
return rc;
}
@@ -449,6 +453,11 @@
return 0;
reset_hctrl0:
+ gpio_set_value_cansleep(haptic->pdata->hap_en_gpio, 0);
+ if (haptic->is_len_gpio_valid == true)
+ gpio_set_value_cansleep(haptic->pdata->hap_len_gpio, 0);
+ i2c_smbus_write_byte_data(client, ISA1200_HCTRL1,
+ ISA1200_HCTRL1_RESET);
i2c_smbus_write_byte_data(client, ISA1200_HCTRL0,
ISA1200_HCTRL0_RESET);
setup_fail:
@@ -490,6 +499,10 @@
timed_output_dev_unregister(&haptic->dev);
+ gpio_set_value_cansleep(haptic->pdata->hap_en_gpio, 0);
+ if (haptic->is_len_gpio_valid == true)
+ gpio_set_value_cansleep(haptic->pdata->hap_len_gpio, 0);
+
gpio_free(haptic->pdata->hap_en_gpio);
if (haptic->is_len_gpio_valid == true)
gpio_free(haptic->pdata->hap_len_gpio);
diff --git a/drivers/misc/pm8xxx-vibrator.c b/drivers/misc/pm8xxx-vibrator.c
index 4f22efe..62e7b45 100644
--- a/drivers/misc/pm8xxx-vibrator.c
+++ b/drivers/misc/pm8xxx-vibrator.c
@@ -145,9 +145,8 @@
timed_dev);
unsigned long flags;
- spin_lock_irqsave(&vib->lock, flags);
-
retry:
+ spin_lock_irqsave(&vib->lock, flags);
if (hrtimer_try_to_cancel(&vib->vib_timer) < 0) {
spin_unlock_irqrestore(&vib->lock, flags);
cpu_relax();
diff --git a/drivers/mmc/core/mmc.c b/drivers/mmc/core/mmc.c
index 71d0fa6..918fc9e 100644
--- a/drivers/mmc/core/mmc.c
+++ b/drivers/mmc/core/mmc.c
@@ -831,7 +831,7 @@
*
* WARNING: eMMC rules are NOT the same as SD DDR
*/
- if (ddr == EXT_CSD_CARD_TYPE_DDR_1_2V) {
+ if (ddr == MMC_1_2V_DDR_MODE) {
err = mmc_set_signal_voltage(host,
MMC_SIGNAL_VOLTAGE_120, 0);
if (err)
diff --git a/drivers/mmc/host/msm_sdcc.c b/drivers/mmc/host/msm_sdcc.c
index fa91b53..b46bee6 100644
--- a/drivers/mmc/host/msm_sdcc.c
+++ b/drivers/mmc/host/msm_sdcc.c
@@ -76,6 +76,7 @@
static int msmsdcc_dbg_init(void);
#endif
+static u64 dma_mask = DMA_BIT_MASK(32);
static unsigned int msmsdcc_pwrsave = 1;
static struct mmc_command dummy52cmd;
@@ -1529,7 +1530,7 @@
msmsdcc_do_cmdirq(host, status);
}
- if (data) {
+ if (host->curr.data) {
/* Check for data errors */
if (status & (MCI_DATACRCFAIL|MCI_DATATIMEOUT|
MCI_TXUNDERRUN|MCI_RXOVERRUN)) {
@@ -3929,6 +3930,7 @@
if (ret)
goto sps_exit;
}
+ mmc_dev(mmc)->dma_mask = &dma_mask;
/*
* Setup MMC host structure
diff --git a/drivers/net/msm_rmnet_bam.c b/drivers/net/msm_rmnet_bam.c
index bb20a3f..99a2c04 100644
--- a/drivers/net/msm_rmnet_bam.c
+++ b/drivers/net/msm_rmnet_bam.c
@@ -342,7 +342,12 @@
((struct net_device *)(dev))->name, p->stats.tx_packets,
skb->len, skb->mark);
dev_kfree_skb_any(skb);
- netif_wake_queue(dev);
+ if (netif_queue_stopped(dev) &&
+ msm_bam_dmux_is_ch_low(p->ch_id)) {
+ DBG0("%s: Low WM hit, waking queue=%p\n",
+ __func__, skb);
+ netif_wake_queue(dev);
+ }
}
static void bam_notify(void *dev, int event, unsigned long data)
@@ -452,7 +457,6 @@
return 0;
}
- netif_stop_queue(dev);
if (!ul_is_connected) {
p->waiting_for_ul = 1;
msm_bam_dmux_kickoff_ul_wakeup();
@@ -460,6 +464,11 @@
}
_rmnet_xmit(skb, dev);
+ if (msm_bam_dmux_is_ch_full(p->ch_id)) {
+ netif_stop_queue(dev);
+ DBG0("%s: High WM hit, stopping queue=%p\n", __func__, skb);
+ }
+
return 0;
}
diff --git a/drivers/net/wireless/wcnss/wcnss_wlan.c b/drivers/net/wireless/wcnss/wcnss_wlan.c
index 1c56f34..7453068 100644
--- a/drivers/net/wireless/wcnss/wcnss_wlan.c
+++ b/drivers/net/wireless/wcnss/wcnss_wlan.c
@@ -14,8 +14,8 @@
#include <linux/slab.h>
#include <linux/err.h>
#include <linux/platform_device.h>
-#include <linux/firmware.h>
-#include <linux/parser.h>
+#include <linux/miscdevice.h>
+#include <linux/fs.h>
#include <linux/wcnss_wlan.h>
#include <linux/platform_data/qcom_wcnss_device.h>
#include <linux/workqueue.h>
@@ -31,7 +31,7 @@
/* module params */
#define WCNSS_CONFIG_UNSPECIFIED (-1)
static int has_48mhz_xo = WCNSS_CONFIG_UNSPECIFIED;
-module_param(has_48mhz_xo, int, S_IRUGO);
+module_param(has_48mhz_xo, int, S_IWUSR | S_IRUGO);
MODULE_PARM_DESC(has_48mhz_xo, "Is an external 48 MHz XO present");
static struct {
@@ -42,6 +42,7 @@
struct resource *rx_irq_res;
struct resource *gpios_5wire;
const struct dev_pm_ops *pm_ops;
+ int triggered;
int smd_channel_ready;
struct wcnss_wlan_config wlan_config;
struct delayed_work wcnss_work;
@@ -191,25 +192,16 @@
return 0;
}
-static int __devinit
-wcnss_wlan_probe(struct platform_device *pdev)
+static int
+wcnss_trigger_config(struct platform_device *pdev)
{
int ret;
struct qcom_wcnss_opts *pdata;
- /* verify we haven't been called more than once */
- if (penv) {
- dev_err(&pdev->dev, "cannot handle multiple devices.\n");
- return -ENODEV;
- }
-
- /* create an environment to track the device */
- penv = kzalloc(sizeof(*penv), GFP_KERNEL);
- if (!penv) {
- dev_err(&pdev->dev, "cannot allocate device memory.\n");
- return -ENOMEM;
- }
- penv->pdev = pdev;
+ /* make sure we are only triggered once */
+ if (penv->triggered)
+ return 0;
+ penv->triggered = 1;
/* initialize the WCNSS device configuration */
pdata = pdev->dev.platform_data;
@@ -281,6 +273,75 @@
return ret;
}
+#ifndef MODULE
+static int wcnss_node_open(struct inode *inode, struct file *file)
+{
+ struct platform_device *pdev;
+
+ pr_info(DEVICE " triggered by userspace\n");
+
+ pdev = penv->pdev;
+ return wcnss_trigger_config(pdev);
+}
+
+static const struct file_operations wcnss_node_fops = {
+ .owner = THIS_MODULE,
+ .open = wcnss_node_open,
+};
+
+static struct miscdevice wcnss_misc = {
+ .minor = MISC_DYNAMIC_MINOR,
+ .name = DEVICE,
+ .fops = &wcnss_node_fops,
+};
+#endif /* ifndef MODULE */
+
+
+static int __devinit
+wcnss_wlan_probe(struct platform_device *pdev)
+{
+ /* verify we haven't been called more than once */
+ if (penv) {
+ dev_err(&pdev->dev, "cannot handle multiple devices.\n");
+ return -ENODEV;
+ }
+
+ /* create an environment to track the device */
+ penv = kzalloc(sizeof(*penv), GFP_KERNEL);
+ if (!penv) {
+ dev_err(&pdev->dev, "cannot allocate device memory.\n");
+ return -ENOMEM;
+ }
+ penv->pdev = pdev;
+
+#ifdef MODULE
+
+ /*
+ * Since we were built as a module, we are running because
+ * the module was loaded, therefore we assume userspace
+ * applications are available to service PIL, so we can
+ * trigger the WCNSS configuration now
+ */
+ pr_info(DEVICE " probed in MODULE mode\n");
+ return wcnss_trigger_config(pdev);
+
+#else
+
+ /*
+ * Since we were built into the kernel we'll be called as part
+ * of kernel initialization. We don't know if userspace
+ * applications are available to service PIL at this time
+ * (they probably are not), so we simply create a device node
+ * here. When userspace is available it should touch the
+ * device so that we know that WCNSS configuration can take
+ * place
+ */
+ pr_info(DEVICE " probed in built-in mode\n");
+ return misc_register(&wcnss_misc);
+
+#endif
+}
+
static int __devexit
wcnss_wlan_remove(struct platform_device *pdev)
{
diff --git a/drivers/platform/msm/Kconfig b/drivers/platform/msm/Kconfig
index 75a6b5e..26441cd 100644
--- a/drivers/platform/msm/Kconfig
+++ b/drivers/platform/msm/Kconfig
@@ -13,7 +13,7 @@
config SPS
bool "SPS support"
depends on (HAS_IOMEM && (ARCH_MSM8960 || ARCH_MSM8X60 \
- || ARCH_APQ8064 || ARCH_MSM9615))
+ || ARCH_APQ8064 || ARCH_MSM9615 || ARCH_MSMCOPPER))
select GENERIC_ALLOCATOR
default n
help
@@ -28,10 +28,17 @@
depends on SPS
default n
help
- The BAM-DMA is used for Memory-to-Memory transfers.
- The main use cases is RPC between processors.
- The BAM-DMA hardware has 2 registers sets:
- 1. A BAM HW like all the peripherals.
- 2. A DMA channel configuration (i.e. channel priority).
+ The BAM-DMA is used for Memory-to-Memory transfers.
+ The main use cases is RPC between processors.
+ The BAM-DMA hardware has 2 registers sets:
+ 1. A BAM HW like all the peripherals.
+ 2. A DMA channel configuration (i.e. channel priority).
+
+config SPS_SUPPORT_NDP_BAM
+ bool "SPS support NDP BAM"
+ depends on SPS
+ default n
+ help
+ No-Data-Path BAM is used to improve BAM performance.
endmenu
diff --git a/drivers/platform/msm/sps/bam.c b/drivers/platform/msm/sps/bam.c
index 2af4fa4..4279603 100644
--- a/drivers/platform/msm/sps/bam.c
+++ b/drivers/platform/msm/sps/bam.c
@@ -28,6 +28,286 @@
#define BAM_MIN_VERSION 2
#define BAM_MAX_VERSION 0x1f
+#ifdef CONFIG_SPS_SUPPORT_NDP_BAM
+
+/* Maximum number of execution environment */
+#define BAM_MAX_EES 8
+
+/**
+ * BAM Hardware registers.
+ *
+ */
+#define CTRL (0x0)
+#define REVISION (0x4)
+#define SW_REVISION (0x80)
+#define NUM_PIPES (0x3c)
+#define TIMER (0x40)
+#define TIMER_CTRL (0x44)
+#define DESC_CNT_TRSHLD (0x8)
+#define IRQ_SRCS (0xc)
+#define IRQ_SRCS_MSK (0x10)
+#define IRQ_SRCS_UNMASKED (0x30)
+#define IRQ_STTS (0x14)
+#define IRQ_CLR (0x18)
+#define IRQ_EN (0x1c)
+#define AHB_MASTER_ERR_CTRLS (0x24)
+#define AHB_MASTER_ERR_ADDR (0x28)
+#define AHB_MASTER_ERR_DATA (0x2c)
+#define TRUST_REG (0x70)
+#define TEST_BUS_SEL (0x74)
+#define TEST_BUS_REG (0x78)
+#define CNFG_BITS (0x7c)
+#define IRQ_SRCS_EE(n) (0x800 + 128 * (n))
+#define IRQ_SRCS_MSK_EE(n) (0x804 + 128 * (n))
+#define IRQ_SRCS_UNMASKED_EE(n) (0x808 + 128 * (n))
+
+#define P_CTRL(n) (0x1000 + 4096 * (n))
+#define P_RST(n) (0x1004 + 4096 * (n))
+#define P_HALT(n) (0x1008 + 4096 * (n))
+#define P_IRQ_STTS(n) (0x1010 + 4096 * (n))
+#define P_IRQ_CLR(n) (0x1014 + 4096 * (n))
+#define P_IRQ_EN(n) (0x1018 + 4096 * (n))
+#define P_TIMER(n) (0x101c + 4096 * (n))
+#define P_TIMER_CTRL(n) (0x1020 + 4096 * (n))
+#define P_PRDCR_SDBND(n) (0x1024 + 4096 * (n))
+#define P_CNSMR_SDBND(n) (0x1028 + 4096 * (n))
+#define P_TRUST_REG(n) (0x1030 + 4096 * (n))
+#define P_EVNT_DEST_ADDR(n) (0x182c + 4096 * (n))
+#define P_EVNT_REG(n) (0x1818 + 4096 * (n))
+#define P_SW_OFSTS(n) (0x1800 + 4096 * (n))
+#define P_DATA_FIFO_ADDR(n) (0x1824 + 4096 * (n))
+#define P_DESC_FIFO_ADDR(n) (0x181c + 4096 * (n))
+#define P_EVNT_GEN_TRSHLD(n) (0x1828 + 4096 * (n))
+#define P_FIFO_SIZES(n) (0x1820 + 4096 * (n))
+#define P_RETR_CNTXT(n) (0x1834 + 4096 * (n))
+#define P_SI_CNTXT(n) (0x1838 + 4096 * (n))
+#define P_DF_CNTXT(n) (0x1830 + 4096 * (n))
+#define P_AU_PSM_CNTXT_1(n) (0x1804 + 4096 * (n))
+#define P_PSM_CNTXT_2(n) (0x1808 + 4096 * (n))
+#define P_PSM_CNTXT_3(n) (0x180c + 4096 * (n))
+#define P_PSM_CNTXT_4(n) (0x1810 + 4096 * (n))
+#define P_PSM_CNTXT_5(n) (0x1814 + 4096 * (n))
+
+/**
+ * BAM Hardware registers bitmask.
+ * format: <register>_<field>
+ *
+ */
+/* CTRL */
+#define IBC_DISABLE 0x10000
+#define BAM_CACHED_DESC_STORE 0x8000
+#define BAM_DESC_CACHE_SEL 0x6000
+#define BAM_EN_ACCUM 0x10
+#define BAM_EN 0x2
+#define BAM_SW_RST 0x1
+
+/* REVISION */
+#define BAM_INACTIV_TMR_BASE 0xff000000
+#define BAM_CMD_DESC_EN 0x800000
+#define BAM_DESC_CACHE_DEPTH 0x600000
+#define BAM_NUM_INACTIV_TMRS 0x100000
+#define BAM_INACTIV_TMRS_EXST 0x80000
+#define BAM_HIGH_FREQUENCY_BAM 0x40000
+#define BAM_HAS_NO_BYPASS 0x20000
+#define BAM_SECURED 0x10000
+#define BAM_USE_VMIDMT 0x8000
+#define BAM_AXI_ACTIVE 0x4000
+#define BAM_CE_BUFFER_SIZE 0x2000
+#define BAM_NUM_EES 0xf00
+#define BAM_REVISION 0xff
+
+/* SW_REVISION */
+#define BAM_MAJOR 0xf0000000
+#define BAM_MINOR 0xfff0000
+#define BAM_STEP 0xffff
+
+/* NUM_PIPES */
+#define BAM_NON_PIPE_GRP 0xff000000
+#define BAM_PERIPH_NON_PIPE_GRP 0xff0000
+#define BAM_NUM_PIPES 0xff
+
+/* TIMER */
+#define BAM_TIMER 0xffff
+
+/* TIMER_CTRL */
+#define TIMER_RST 0x80000000
+#define TIMER_RUN 0x40000000
+#define TIMER_MODE 0x20000000
+#define TIMER_TRSHLD 0xffff
+
+/* DESC_CNT_TRSHLD */
+#define BAM_DESC_CNT_TRSHLD 0xffff
+
+/* IRQ_SRCS */
+#define BAM_IRQ 0x80000000
+#define P_IRQ 0x7fffffff
+
+/* IRQ_STTS */
+#define IRQ_STTS_BAM_TIMER_IRQ 0x10
+#define IRQ_STTS_BAM_EMPTY_IRQ 0x8
+#define IRQ_STTS_BAM_ERROR_IRQ 0x4
+#define IRQ_STTS_BAM_HRESP_ERR_IRQ 0x2
+
+/* IRQ_CLR */
+#define IRQ_CLR_BAM_TIMER_IRQ 0x10
+#define IRQ_CLR_BAM_EMPTY_CLR 0x8
+#define IRQ_CLR_BAM_ERROR_CLR 0x4
+#define IRQ_CLR_BAM_HRESP_ERR_CLR 0x2
+
+/* IRQ_EN */
+#define IRQ_EN_BAM_TIMER_IRQ 0x10
+#define IRQ_EN_BAM_EMPTY_EN 0x8
+#define IRQ_EN_BAM_ERROR_EN 0x4
+#define IRQ_EN_BAM_HRESP_ERR_EN 0x2
+
+/* AHB_MASTER_ERR_CTRLS */
+#define AHB_MASTER_ERR_CTRLS_BAM_ERR_HVMID 0x7c0000
+#define AHB_MASTER_ERR_CTRLS_BAM_ERR_DIRECT_MODE 0x20000
+#define AHB_MASTER_ERR_CTRLS_BAM_ERR_HCID 0x1f000
+#define AHB_MASTER_ERR_CTRLS_BAM_ERR_HPROT 0xf00
+#define AHB_MASTER_ERR_CTRLS_BAM_ERR_HBURST 0xe0
+#define AHB_MASTER_ERR_CTRLS_BAM_ERR_HSIZE 0x18
+#define AHB_MASTER_ERR_CTRLS_BAM_ERR_HWRITE 0x4
+#define AHB_MASTER_ERR_CTRLS_BAM_ERR_HTRANS 0x3
+
+/* TRUST_REG */
+#define BAM_VMID 0x1f00
+#define BAM_RST_BLOCK 0x80
+#define BAM_EE 0x7
+
+/* TEST_BUS_SEL */
+#define BAM_DATA_ERASE 0x40000
+#define BAM_DATA_FLUSH 0x20000
+#define BAM_CLK_ALWAYS_ON 0x10000
+#define BAM_TESTBUS_SEL 0x7f
+
+/* CNFG_BITS */
+#define CNFG_BITS_BAM_CD_ENABLE 0x8000000
+#define CNFG_BITS_BAM_AU_ACCUMED 0x4000000
+#define CNFG_BITS_BAM_PSM_P_HD_DATA 0x2000000
+#define CNFG_BITS_BAM_REG_P_EN 0x1000000
+#define CNFG_BITS_BAM_WB_DSC_AVL_P_RST 0x800000
+#define CNFG_BITS_BAM_WB_RETR_SVPNT 0x400000
+#define CNFG_BITS_BAM_WB_CSW_ACK_IDL 0x200000
+#define CNFG_BITS_BAM_WB_BLK_CSW 0x100000
+#define CNFG_BITS_BAM_WB_P_RES 0x80000
+#define CNFG_BITS_BAM_SI_P_RES 0x40000
+#define CNFG_BITS_BAM_AU_P_RES 0x20000
+#define CNFG_BITS_BAM_PSM_P_RES 0x10000
+#define CNFG_BITS_BAM_PSM_CSW_REQ 0x8000
+#define CNFG_BITS_BAM_SB_CLK_REQ 0x4000
+#define CNFG_BITS_BAM_IBC_DISABLE 0x2000
+#define CNFG_BITS_BAM_NO_EXT_P_RST 0x1000
+#define CNFG_BITS_BAM_FULL_PIPE 0x800
+#define CNFG_BITS_BAM_PIPE_CNFG 0x4
+
+/* P_ctrln */
+#define P_LOCK_GROUP 0x1f0000
+#define P_WRITE_NWD 0x800
+#define P_PREFETCH_LIMIT 0x600
+#define P_AUTO_EOB_SEL 0x180
+#define P_AUTO_EOB 0x40
+#define P_SYS_MODE 0x20
+#define P_SYS_STRM 0x10
+#define P_DIRECTION 0x8
+#define P_EN 0x2
+
+/* P_RSTn */
+#define P_RST_P_SW_RST 0x1
+
+/* P_HALTn */
+#define P_HALT_P_PROD_HALTED 0x2
+#define P_HALT_P_HALT 0x1
+
+/* P_TRUST_REGn */
+#define BAM_P_VMID 0x1f00
+#define BAM_P_EE 0x7
+
+/* P_IRQ_STTSn */
+#define P_IRQ_STTS_P_TRNSFR_END_IRQ 0x20
+#define P_IRQ_STTS_P_ERR_IRQ 0x10
+#define P_IRQ_STTS_P_OUT_OF_DESC_IRQ 0x8
+#define P_IRQ_STTS_P_WAKE_IRQ 0x4
+#define P_IRQ_STTS_P_TIMER_IRQ 0x2
+#define P_IRQ_STTS_P_PRCSD_DESC_IRQ 0x1
+
+/* P_IRQ_CLRn */
+#define P_IRQ_CLR_P_TRNSFR_END_CLR 0x20
+#define P_IRQ_CLR_P_ERR_CLR 0x10
+#define P_IRQ_CLR_P_OUT_OF_DESC_CLR 0x8
+#define P_IRQ_CLR_P_WAKE_CLR 0x4
+#define P_IRQ_CLR_P_TIMER_CLR 0x2
+#define P_IRQ_CLR_P_PRCSD_DESC_CLR 0x1
+
+/* P_IRQ_ENn */
+#define P_IRQ_EN_P_TRNSFR_END_EN 0x20
+#define P_IRQ_EN_P_ERR_EN 0x10
+#define P_IRQ_EN_P_OUT_OF_DESC_EN 0x8
+#define P_IRQ_EN_P_WAKE_EN 0x4
+#define P_IRQ_EN_P_TIMER_EN 0x2
+#define P_IRQ_EN_P_PRCSD_DESC_EN 0x1
+
+/* P_TIMERn */
+#define P_TIMER_P_TIMER 0xffff
+
+/* P_TIMER_ctrln */
+#define P_TIMER_RST 0x80000000
+#define P_TIMER_RUN 0x40000000
+#define P_TIMER_MODE 0x20000000
+#define P_TIMER_TRSHLD 0xffff
+
+/* P_PRDCR_SDBNDn */
+#define P_PRDCR_SDBNDn_BAM_P_SB_UPDATED 0x1000000
+#define P_PRDCR_SDBNDn_BAM_P_TOGGLE 0x100000
+#define P_PRDCR_SDBNDn_BAM_P_CTRL 0xf0000
+#define P_PRDCR_SDBNDn_BAM_P_BYTES_FREE 0xffff
+
+/* P_CNSMR_SDBNDn */
+#define P_CNSMR_SDBNDn_BAM_P_SB_UPDATED 0x1000000
+#define P_CNSMR_SDBNDn_BAM_P_WAIT_4_ACK 0x800000
+#define P_CNSMR_SDBNDn_BAM_P_ACK_TOGGLE 0x400000
+#define P_CNSMR_SDBNDn_BAM_P_ACK_TOGGLE_R 0x200000
+#define P_CNSMR_SDBNDn_BAM_P_TOGGLE 0x100000
+#define P_CNSMR_SDBNDn_BAM_P_CTRL 0xf0000
+#define P_CNSMR_SDBNDn_BAM_P_BYTES_AVAIL 0xffff
+
+/* P_EVNT_regn */
+#define P_BYTES_CONSUMED 0xffff0000
+#define P_DESC_FIFO_PEER_OFST 0xffff
+
+/* P_SW_ofstsn */
+#define SW_OFST_IN_DESC 0xffff0000
+#define SW_DESC_OFST 0xffff
+
+/* P_EVNT_GEN_TRSHLDn */
+#define P_EVNT_GEN_TRSHLD_P_TRSHLD 0xffff
+
+/* P_FIFO_sizesn */
+#define P_DATA_FIFO_SIZE 0xffff0000
+#define P_DESC_FIFO_SIZE 0xffff
+
+#define P_RETR_CNTXT_RETR_DESC_OFST 0xffff0000
+#define P_RETR_CNTXT_RETR_OFST_IN_DESC 0xffff
+#define P_SI_CNTXT_SI_DESC_OFST 0xffff
+#define P_DF_CNTXT_WB_ACCUMULATED 0xffff0000
+#define P_DF_CNTXT_DF_DESC_OFST 0xffff
+#define P_AU_PSM_CNTXT_1_AU_PSM_ACCUMED 0xffff0000
+#define P_AU_PSM_CNTXT_1_AU_ACKED 0xffff
+#define P_PSM_CNTXT_2_PSM_DESC_VALID 0x80000000
+#define P_PSM_CNTXT_2_PSM_DESC_IRQ 0x40000000
+#define P_PSM_CNTXT_2_PSM_DESC_IRQ_DONE 0x20000000
+#define P_PSM_CNTXT_2_PSM_GENERAL_BITS 0x1e000000
+#define P_PSM_CNTXT_2_PSM_CONS_STATE 0x1c00000
+#define P_PSM_CNTXT_2_PSM_PROD_SYS_STATE 0x380000
+#define P_PSM_CNTXT_2_PSM_PROD_B2B_STATE 0x70000
+#define P_PSM_CNTXT_2_PSM_DESC_SIZE 0xffff
+#define P_PSM_CNTXT_4_PSM_DESC_OFST 0xffff0000
+#define P_PSM_CNTXT_4_PSM_SAVED_ACCUMED_SIZE 0xffff
+#define P_PSM_CNTXT_5_PSM_BLOCK_BYTE_CNT 0xffff0000
+#define P_PSM_CNTXT_5_PSM_OFST_IN_DESC 0xffff
+
+#else
+
/* Maximum number of execution environment */
#define BAM_MAX_EES 4
@@ -263,6 +543,7 @@
#define P_PSM_CNTXT_4_PSM_SAVED_ACCUMED_SIZE 0xffff
#define P_PSM_CNTXT_5_PSM_BLOCK_BYTE_CNT 0xffff0000
#define P_PSM_CNTXT_5_PSM_OFST_IN_DESC 0xffff
+#endif
#define BAM_ERROR (-1)
@@ -658,9 +939,10 @@
void bam_pipe_satellite_mti(void *base, u32 pipe, u32 irq_gen_addr, u32 ee)
{
bam_write_reg(base, P_IRQ_EN(pipe), 0);
+#ifndef CONFIG_SPS_SUPPORT_NDP_BAM
bam_write_reg(base, P_IRQ_DEST_ADDR(pipe), irq_gen_addr);
-
bam_write_reg_field(base, IRQ_SIC_SEL, (1 << pipe), 1);
+#endif
bam_write_reg_field(base, IRQ_SRCS_MSK, (1 << pipe), 1);
}
@@ -680,9 +962,9 @@
* interrupt. Since the remote processor enable both SIC and interrupt,
* the interrupt enable mask must be set to zero for polling mode.
*/
-
+#ifndef CONFIG_SPS_SUPPORT_NDP_BAM
bam_write_reg(base, P_IRQ_DEST_ADDR(pipe), irq_gen_addr);
-
+#endif
if (!irq_en)
src_mask = 0;
diff --git a/drivers/platform/msm/sps/sps.c b/drivers/platform/msm/sps/sps.c
index e43166e..b002657 100644
--- a/drivers/platform/msm/sps/sps.c
+++ b/drivers/platform/msm/sps/sps.c
@@ -26,6 +26,7 @@
#include <linux/platform_device.h> /* platform_get_resource_byname() */
#include <linux/debugfs.h>
#include <linux/uaccess.h>
+#include <linux/of.h>
#include <mach/msm_sps.h> /* msm_sps_platform_data */
#include "sps_bam.h"
@@ -1428,13 +1429,74 @@
return 0;
}
+/**
+ * Read data from device tree
+ */
+static int get_device_tree_data(struct platform_device *pdev)
+{
+#ifdef CONFIG_SPS_SUPPORT_BAMDMA
+ struct resource *resource;
+
+ if (of_property_read_u32((&pdev->dev)->of_node,
+ "qcom,bam-dma-res-pipes",
+ &sps->bamdma_restricted_pipes))
+ return -EINVAL;
+ else
+ SPS_DBG("sps:bamdma_restricted_pipes=0x%x.",
+ sps->bamdma_restricted_pipes);
+
+ resource = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ if (resource) {
+ sps->bamdma_bam_phys_base = resource->start;
+ sps->bamdma_bam_size = resource_size(resource);
+ SPS_DBG("sps:bamdma_bam.base=0x%x,size=0x%x.",
+ sps->bamdma_bam_phys_base,
+ sps->bamdma_bam_size);
+ } else {
+ SPS_ERR("sps:BAM DMA BAM mem unavailable.");
+ return -ENODEV;
+ }
+
+ resource = platform_get_resource(pdev, IORESOURCE_MEM, 1);
+ if (resource) {
+ sps->bamdma_dma_phys_base = resource->start;
+ sps->bamdma_dma_size = resource_size(resource);
+ SPS_DBG("sps:bamdma_dma.base=0x%x,size=0x%x.",
+ sps->bamdma_dma_phys_base,
+ sps->bamdma_dma_size);
+ } else {
+ SPS_ERR("sps:BAM DMA mem unavailable.");
+ return -ENODEV;
+ }
+
+ resource = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
+ if (resource) {
+ sps->bamdma_irq = resource->start;
+ SPS_DBG("sps:bamdma_irq=%d.", sps->bamdma_irq);
+ } else {
+ SPS_ERR("sps:BAM DMA IRQ unavailable.");
+ return -ENODEV;
+ }
+#endif
+
+ return 0;
+}
+
static int __devinit msm_sps_probe(struct platform_device *pdev)
{
int ret;
SPS_DBG("sps:msm_sps_probe.");
- ret = get_platform_data(pdev);
+ if (pdev->dev.of_node) {
+ SPS_DBG("sps:get data from device tree.");
+ ret = get_device_tree_data(pdev);
+
+ } else {
+ SPS_DBG("sps:get platform data.");
+ ret = get_platform_data(pdev);
+ }
+
if (ret)
return -ENODEV;
@@ -1542,11 +1604,18 @@
return 0;
}
+static struct of_device_id msm_sps_match[] = {
+ { .compatible = "qcom,msm_sps",
+ },
+ {}
+};
+
static struct platform_driver msm_sps_driver = {
.probe = msm_sps_probe,
.driver = {
.name = SPS_DRV_NAME,
.owner = THIS_MODULE,
+ .of_match_table = msm_sps_match,
},
.remove = __exit_p(msm_sps_remove),
};
diff --git a/drivers/platform/msm/sps/sps_dma.c b/drivers/platform/msm/sps/sps_dma.c
index 9f42403..b650098 100644
--- a/drivers/platform/msm/sps/sps_dma.c
+++ b/drivers/platform/msm/sps/sps_dma.c
@@ -26,14 +26,24 @@
*/
#define DMA_ENBL (0x00000000)
+#ifdef CONFIG_SPS_SUPPORT_NDP_BAM
+#define DMA_REVISION (0x00000004)
+#define DMA_CONFIG (0x00000008)
+#define DMA_CHNL_CONFIG(n) (0x00001000 + 4096 * (n))
+#else
#define DMA_CHNL_CONFIG(n) (0x00000004 + 4 * (n))
#define DMA_CONFIG (0x00000040)
+#endif
/**
* masks
*/
/* DMA_CHNL_confign */
+#ifdef CONFIG_SPS_SUPPORT_NDP_BAM
+#define DMA_CHNL_PRODUCER_PIPE_ENABLED 0x40000
+#define DMA_CHNL_CONSUMER_PIPE_ENABLED 0x20000
+#endif
#define DMA_CHNL_HALT_DONE 0x10000
#define DMA_CHNL_HALT 0x1000
#define DMA_CHNL_ENABLE 0x100
diff --git a/drivers/platform/msm/sps/sps_mem.c b/drivers/platform/msm/sps/sps_mem.c
index 3aee4ba..31c1314 100644
--- a/drivers/platform/msm/sps/sps_mem.c
+++ b/drivers/platform/msm/sps/sps_mem.c
@@ -104,10 +104,13 @@
*/
int sps_mem_init(u32 pipemem_phys_base, u32 pipemem_size)
{
+#ifndef CONFIG_SPS_SUPPORT_NDP_BAM
int res;
+#endif
/* 2^8=128. The desc-fifo and data-fifo minimal allocation. */
int min_alloc_order = 8;
+#ifndef CONFIG_SPS_SUPPORT_NDP_BAM
iomem_phys = pipemem_phys_base;
iomem_size = pipemem_size;
@@ -125,11 +128,14 @@
iomem_offset = 0;
SPS_DBG("sps:sps_mem_init.iomem_phys=0x%x,iomem_virt=0x%x.",
iomem_phys, (u32) iomem_virt);
+#endif
pool = gen_pool_create(min_alloc_order, nid);
+#ifndef CONFIG_SPS_SUPPORT_NDP_BAM
res = gen_pool_add(pool, (u32) iomem_virt, iomem_size, nid);
if (res)
return res;
+#endif
return 0;
}
diff --git a/drivers/power/Kconfig b/drivers/power/Kconfig
index 7c8dfea..3dfa68e 100644
--- a/drivers/power/Kconfig
+++ b/drivers/power/Kconfig
@@ -338,6 +338,13 @@
help
Say Y here to enable support for pm8921 chip bms subdevice
+config LTC4088_CHARGER
+ tristate "LTC4088 Charger driver"
+ depends on GPIOLIB
+ help
+ Say Y here to enable support for ltc4088 chip charger. It controls the
+ operations through GPIO pins.
+
config PM8921_BMS
select PM8XXX_CCADC
tristate "PM8921 Battery Monitoring System driver"
diff --git a/drivers/power/Makefile b/drivers/power/Makefile
index e168590..03db839 100644
--- a/drivers/power/Makefile
+++ b/drivers/power/Makefile
@@ -48,3 +48,4 @@
obj-$(CONFIG_PM8XXX_CCADC) += pm8xxx-ccadc.o
obj-$(CONFIG_PM8921_BMS) += pm8921-bms.o
obj-$(CONFIG_PM8921_CHARGER) += pm8921-charger.o
+obj-$(CONFIG_LTC4088_CHARGER) += ltc4088-charger.o
diff --git a/drivers/power/ltc4088-charger.c b/drivers/power/ltc4088-charger.c
new file mode 100644
index 0000000..dbc75cd
--- /dev/null
+++ b/drivers/power/ltc4088-charger.c
@@ -0,0 +1,338 @@
+/*
+ * Copyright (c) 2011, Code Aurora Forum. 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 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+#define pr_fmt(fmt) "%s: " fmt, __func__
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/errno.h>
+#include <linux/power_supply.h>
+#include <linux/slab.h>
+#include <linux/gpio.h>
+#include <linux/power/ltc4088-charger.h>
+
+#define MAX_CURRENT_UA(n) (n)
+#define MAX_CURRENT_MA(n) (n * MAX_CURRENT_UA(1000))
+
+/**
+ * ltc4088_max_current - A typical current values supported by the charger
+ * @LTC4088_MAX_CURRENT_100mA: 100mA current
+ * @LTC4088_MAX_CURRENT_500mA: 500mA current
+ * @LTC4088_MAX_CURRENT_1A: 1A current
+ */
+enum ltc4088_max_current {
+ LTC4088_MAX_CURRENT_100mA = 100,
+ LTC4088_MAX_CURRENT_500mA = 500,
+ LTC4088_MAX_CURRENT_1A = 1000,
+};
+
+/**
+ * struct ltc4088_chg_chip - Device information
+ * @dev: Device pointer to access the parent
+ * @lock: Enable mutual exclusion
+ * @usb_psy: USB device information
+ * @gpio_mode_select_d0: GPIO #pin for D0 charger line
+ * @gpio_mode_select_d1: GPIO #pin for D1 charger line
+ * @gpio_mode_select_d2: GPIO #pin for D2 charger line
+ * @max_current: Maximum current that is supplied at this time
+ */
+struct ltc4088_chg_chip {
+ struct device *dev;
+ struct mutex lock;
+ struct power_supply usb_psy;
+ unsigned int gpio_mode_select_d0;
+ unsigned int gpio_mode_select_d1;
+ unsigned int gpio_mode_select_d2;
+ unsigned int max_current;
+};
+
+static enum power_supply_property pm_power_props[] = {
+ POWER_SUPPLY_PROP_CURRENT_MAX,
+ POWER_SUPPLY_PROP_ONLINE,
+};
+
+static char *pm_power_supplied_to[] = {
+ "battery",
+};
+
+static int ltc4088_set_charging(struct ltc4088_chg_chip *chip, bool enable)
+{
+ mutex_lock(&chip->lock);
+
+ if (enable) {
+ gpio_set_value_cansleep(chip->gpio_mode_select_d2, 0);
+ } else {
+ /* When disabling charger, set the max current to 0 also */
+ chip->max_current = 0;
+ gpio_set_value_cansleep(chip->gpio_mode_select_d0, 1);
+ gpio_set_value_cansleep(chip->gpio_mode_select_d1, 1);
+ gpio_set_value_cansleep(chip->gpio_mode_select_d2, 1);
+ }
+
+ mutex_unlock(&chip->lock);
+
+ return 0;
+}
+
+static void ltc4088_set_max_current(struct ltc4088_chg_chip *chip, int value)
+{
+ mutex_lock(&chip->lock);
+
+ /* If current is less than 100mA, we can not support that granularity */
+ if (value < MAX_CURRENT_MA(LTC4088_MAX_CURRENT_100mA)) {
+ chip->max_current = 0;
+ gpio_set_value_cansleep(chip->gpio_mode_select_d0, 1);
+ gpio_set_value_cansleep(chip->gpio_mode_select_d1, 1);
+ } else if (value < MAX_CURRENT_MA(LTC4088_MAX_CURRENT_500mA)) {
+ chip->max_current = MAX_CURRENT_MA(LTC4088_MAX_CURRENT_100mA);
+ gpio_set_value_cansleep(chip->gpio_mode_select_d0, 0);
+ gpio_set_value_cansleep(chip->gpio_mode_select_d1, 0);
+ } else if (value < MAX_CURRENT_MA(LTC4088_MAX_CURRENT_1A)) {
+ chip->max_current = MAX_CURRENT_MA(LTC4088_MAX_CURRENT_500mA);
+ gpio_set_value_cansleep(chip->gpio_mode_select_d0, 0);
+ gpio_set_value_cansleep(chip->gpio_mode_select_d1, 1);
+ } else {
+ chip->max_current = MAX_CURRENT_MA(LTC4088_MAX_CURRENT_1A);
+ gpio_set_value_cansleep(chip->gpio_mode_select_d0, 1);
+ gpio_set_value_cansleep(chip->gpio_mode_select_d1, 0);
+ }
+
+ mutex_unlock(&chip->lock);
+}
+
+static void ltc4088_set_charging_off(struct ltc4088_chg_chip *chip)
+{
+ gpio_set_value_cansleep(chip->gpio_mode_select_d0, 1);
+ gpio_set_value_cansleep(chip->gpio_mode_select_d1, 1);
+}
+
+static int ltc4088_set_initial_state(struct ltc4088_chg_chip *chip)
+{
+ int rc;
+
+ rc = gpio_request(chip->gpio_mode_select_d0, "ltc4088_D0");
+ if (rc) {
+ pr_err("gpio request failed for GPIO %d\n",
+ chip->gpio_mode_select_d0);
+ return rc;
+ }
+
+ rc = gpio_request(chip->gpio_mode_select_d1, "ltc4088_D1");
+ if (rc) {
+ pr_err("gpio request failed for GPIO %d\n",
+ chip->gpio_mode_select_d1);
+ goto gpio_err_d0;
+ }
+
+ rc = gpio_request(chip->gpio_mode_select_d2, "ltc4088_D2");
+ if (rc) {
+ pr_err("gpio request failed for GPIO %d\n",
+ chip->gpio_mode_select_d2);
+ goto gpio_err_d1;
+ }
+
+ rc = gpio_direction_output(chip->gpio_mode_select_d0, 0);
+ if (rc) {
+ pr_err("failed to set direction for GPIO %d\n",
+ chip->gpio_mode_select_d0);
+ goto gpio_err_d2;
+ }
+
+ rc = gpio_direction_output(chip->gpio_mode_select_d1, 0);
+ if (rc) {
+ pr_err("failed to set direction for GPIO %d\n",
+ chip->gpio_mode_select_d1);
+ goto gpio_err_d2;
+ }
+
+ rc = gpio_direction_output(chip->gpio_mode_select_d2, 1);
+ if (rc) {
+ pr_err("failed to set direction for GPIO %d\n",
+ chip->gpio_mode_select_d2);
+ goto gpio_err_d2;
+ }
+
+ return 0;
+
+gpio_err_d2:
+ gpio_free(chip->gpio_mode_select_d2);
+gpio_err_d1:
+ gpio_free(chip->gpio_mode_select_d1);
+gpio_err_d0:
+ gpio_free(chip->gpio_mode_select_d0);
+ return rc;
+}
+
+static int pm_power_get_property(struct power_supply *psy,
+ enum power_supply_property psp,
+ union power_supply_propval *val)
+{
+ struct ltc4088_chg_chip *chip;
+
+ if (psy->type == POWER_SUPPLY_TYPE_USB) {
+ chip = container_of(psy, struct ltc4088_chg_chip,
+ usb_psy);
+ switch (psp) {
+ case POWER_SUPPLY_PROP_ONLINE:
+ if (chip->max_current)
+ val->intval = 1;
+ else
+ val->intval = 0;
+ break;
+ case POWER_SUPPLY_PROP_CURRENT_MAX:
+ val->intval = chip->max_current;
+ break;
+ default:
+ return -EINVAL;
+ }
+ }
+ return 0;
+}
+
+static int pm_power_set_property(struct power_supply *psy,
+ enum power_supply_property psp,
+ const union power_supply_propval *val)
+{
+ struct ltc4088_chg_chip *chip;
+
+ if (psy->type == POWER_SUPPLY_TYPE_USB) {
+ chip = container_of(psy, struct ltc4088_chg_chip,
+ usb_psy);
+ switch (psp) {
+ case POWER_SUPPLY_PROP_ONLINE:
+ ltc4088_set_charging(chip, val->intval);
+ break;
+ case POWER_SUPPLY_PROP_CURRENT_MAX:
+ ltc4088_set_max_current(chip, val->intval);
+ break;
+ default:
+ return -EINVAL;
+ }
+ }
+ return 0;
+}
+
+static int __devinit ltc4088_charger_probe(struct platform_device *pdev)
+{
+ int rc;
+ struct ltc4088_chg_chip *chip;
+ const struct ltc4088_charger_platform_data *pdata
+ = pdev->dev.platform_data;
+
+ if (!pdata) {
+ pr_err("missing platform data\n");
+ return -EINVAL;
+ }
+
+ chip = kzalloc(sizeof(struct ltc4088_chg_chip),
+ GFP_KERNEL);
+ if (!chip) {
+ pr_err("Cannot allocate pm_chg_chip\n");
+ return -ENOMEM;
+ }
+
+ chip->dev = &pdev->dev;
+
+ if (pdata->gpio_mode_select_d0 < 0 ||
+ pdata->gpio_mode_select_d1 < 0 ||
+ pdata->gpio_mode_select_d2 < 0) {
+ pr_err("Invalid platform data supplied\n");
+ rc = -EINVAL;
+ goto free_chip;
+ }
+
+ mutex_init(&chip->lock);
+
+ chip->gpio_mode_select_d0 = pdata->gpio_mode_select_d0;
+ chip->gpio_mode_select_d1 = pdata->gpio_mode_select_d1;
+ chip->gpio_mode_select_d2 = pdata->gpio_mode_select_d2;
+
+ chip->usb_psy.name = "usb",
+ chip->usb_psy.type = POWER_SUPPLY_TYPE_USB,
+ chip->usb_psy.supplied_to = pm_power_supplied_to,
+ chip->usb_psy.num_supplicants = ARRAY_SIZE(pm_power_supplied_to),
+ chip->usb_psy.properties = pm_power_props,
+ chip->usb_psy.num_properties = ARRAY_SIZE(pm_power_props),
+ chip->usb_psy.get_property = pm_power_get_property,
+ chip->usb_psy.set_property = pm_power_set_property,
+
+ rc = power_supply_register(chip->dev, &chip->usb_psy);
+ if (rc < 0) {
+ pr_err("power_supply_register usb failed rc = %d\n", rc);
+ goto free_chip;
+ }
+
+ platform_set_drvdata(pdev, chip);
+
+ rc = ltc4088_set_initial_state(chip);
+ if (rc < 0) {
+ pr_err("setting initial state failed rc = %d\n", rc);
+ goto unregister_usb;
+ }
+
+ return 0;
+
+unregister_usb:
+ platform_set_drvdata(pdev, NULL);
+ power_supply_unregister(&chip->usb_psy);
+free_chip:
+ kfree(chip);
+
+ return rc;
+}
+
+static int __devexit ltc4088_charger_remove(struct platform_device *pdev)
+{
+ struct ltc4088_chg_chip *chip = platform_get_drvdata(pdev);
+
+ ltc4088_set_charging_off(chip);
+
+ gpio_free(chip->gpio_mode_select_d2);
+ gpio_free(chip->gpio_mode_select_d1);
+ gpio_free(chip->gpio_mode_select_d0);
+
+ power_supply_unregister(&chip->usb_psy);
+
+ platform_set_drvdata(pdev, NULL);
+ mutex_destroy(&chip->lock);
+ kfree(chip);
+
+ return 0;
+}
+
+static struct platform_driver ltc4088_charger_driver = {
+ .probe = ltc4088_charger_probe,
+ .remove = __devexit_p(ltc4088_charger_remove),
+ .driver = {
+ .name = LTC4088_CHARGER_DEV_NAME,
+ .owner = THIS_MODULE,
+ },
+};
+
+static int __init ltc4088_charger_init(void)
+{
+ return platform_driver_register(<c4088_charger_driver);
+}
+
+static void __exit ltc4088_charger_exit(void)
+{
+ platform_driver_unregister(<c4088_charger_driver);
+}
+
+subsys_initcall(ltc4088_charger_init);
+module_exit(ltc4088_charger_exit);
+
+MODULE_LICENSE("GPL v2");
+MODULE_DESCRIPTION("LTC4088 charger/battery driver");
+MODULE_VERSION("1.0");
+MODULE_ALIAS("platform:" LTC4088_CHARGER_DEV_NAME);
diff --git a/drivers/power/pm8921-bms.c b/drivers/power/pm8921-bms.c
index 6741ef4..f4c86d4 100644
--- a/drivers/power/pm8921-bms.c
+++ b/drivers/power/pm8921-bms.c
@@ -120,6 +120,15 @@
module_param_cb(last_ocv_uv, &bms_param_ops, &last_ocv_uv, 0644);
module_param_cb(last_soc, &bms_param_ops, &last_soc, 0644);
+/*
+ * bms_fake_battery is write only, this value is set in setups where a
+ * battery emulator is used instead of a real battery. This makes the
+ * bms driver report a higher value of charge regardless of the calculated
+ * state of charge.
+ */
+static int bms_fake_battery;
+module_param(bms_fake_battery, int, 0644);
+
static int interpolate_fcc(struct pm8921_bms_chip *chip, int batt_temp);
static void readjust_fcc_table(void)
{
@@ -1015,8 +1024,6 @@
* - unusable charge (due to battery resistance)
* SOC% = (remaining usable charge/ fcc - usable_charge);
*/
-#define BMS_BATT_NOMINAL 3700000
-#define MIN_OPERABLE_SOC 10
#define BATTERY_POWER_SUPPLY_SOC 53
static int calculate_state_of_charge(struct pm8921_bms_chip *chip,
int batt_temp, int chargecycles)
@@ -1040,22 +1047,10 @@
soc = 100;
pr_debug("SOC = %u%%\n", soc);
- if (soc < MIN_OPERABLE_SOC) {
- int ocv = 0, rc;
-
- rc = adc_based_ocv(chip, &ocv);
- if (rc == 0 && ocv >= BMS_BATT_NOMINAL) {
- /*
- * The ocv doesnt seem to have dropped for
- * soc to go negative.
- * The setup must be using a power supply
- * instead of real batteries.
- * Fake high enough soc to prevent userspace
- * shutdown for low battery
- */
- soc = BATTERY_POWER_SUPPLY_SOC;
- pr_debug("Adjusting SOC to %d\n", soc);
- }
+ if (bms_fake_battery) {
+ soc = BATTERY_POWER_SUPPLY_SOC;
+ pr_debug("setting SOC = %u%% bms_fake_battery = %d\n", soc,
+ bms_fake_battery);
}
if (soc < 0) {
@@ -1069,6 +1064,7 @@
last_ocv_uv, chargecycles, batt_temp,
fcc, soc);
update_userspace = 0;
+ soc = 0;
}
if (last_soc == -EINVAL || soc <= last_soc) {
diff --git a/drivers/power/pm8921-charger.c b/drivers/power/pm8921-charger.c
index a91630a..6b05643 100644
--- a/drivers/power/pm8921-charger.c
+++ b/drivers/power/pm8921-charger.c
@@ -250,7 +250,7 @@
int trkl_current;
int weak_current;
int vin_min;
- int *thermal_mitigation;
+ unsigned int *thermal_mitigation;
int thermal_levels;
struct delayed_work update_heartbeat_work;
struct delayed_work eoc_work;
@@ -1279,6 +1279,28 @@
}
EXPORT_SYMBOL(pm8921_is_battery_present);
+/*
+ * Disabling the charge current limit causes current
+ * current limits to have no monitoring. An adequate charger
+ * capable of supplying high current while sustaining VIN_MIN
+ * is required if the limiting is disabled.
+ */
+int pm8921_disable_input_current_limit(bool disable)
+{
+ if (!the_chip) {
+ pr_err("called before init\n");
+ return -EINVAL;
+ }
+ if (disable) {
+ pr_warn("Disabling input current limit!\n");
+
+ return pm8xxx_writeb(the_chip->dev->parent,
+ CHG_BUCK_CTRL_TEST3, 0xF2);
+ }
+ return 0;
+}
+EXPORT_SYMBOL(pm8921_disable_input_current_limit);
+
int pm8921_set_max_battery_charge_current(int ma)
{
if (!the_chip) {
@@ -1494,18 +1516,20 @@
static irqreturn_t vbatdet_low_irq_handler(int irq, void *data)
{
struct pm8921_chg_chip *chip = data;
+ int high_transition;
- pm8921_chg_disable_irq(chip, VBATDET_LOW_IRQ);
+ high_transition = pm_chg_get_rt_status(chip, VBATDET_LOW_IRQ);
- /* enable auto charging */
- pm_chg_auto_enable(chip, !charging_disabled);
+ if (high_transition) {
+ /* enable auto charging */
+ pm_chg_auto_enable(chip, !charging_disabled);
+ }
pr_debug("fsm_state=%d\n", pm_chg_get_fsm_state(data));
power_supply_changed(&chip->batt_psy);
power_supply_changed(&chip->usb_psy);
power_supply_changed(&chip->dc_psy);
- pm8921_chg_enable_irq(chip, FASTCHG_IRQ);
return IRQ_HANDLED;
}
@@ -1561,12 +1585,6 @@
chip->bms_notify.is_battery_full = 1;
bms_notify_check(chip);
- /*
- * since charging is now done, start monitoring for
- * battery voltage below resume voltage
- */
- pm8921_chg_enable_irq(chip, VBATDET_LOW_IRQ);
-
return IRQ_HANDLED;
}
@@ -1613,14 +1631,17 @@
static irqreturn_t fastchg_irq_handler(int irq, void *data)
{
struct pm8921_chg_chip *chip = data;
+ int high_transition;
- /* disable this irq now, reenable it when resuming charging */
- pm8921_chg_disable_irq(chip, FASTCHG_IRQ);
- power_supply_changed(&chip->batt_psy);
- wake_lock(&chip->eoc_wake_lock);
- schedule_delayed_work(&chip->eoc_work,
- round_jiffies_relative(msecs_to_jiffies
+ high_transition = pm_chg_get_rt_status(chip, FASTCHG_IRQ);
+ if (high_transition && !delayed_work_pending(&chip->eoc_work)) {
+ wake_lock(&chip->eoc_wake_lock);
+ schedule_delayed_work(&chip->eoc_work,
+ round_jiffies_relative(msecs_to_jiffies
(EOC_CHECK_PERIOD_MS)));
+ }
+ power_supply_changed(&chip->batt_psy);
+ bms_notify_check(chip);
return IRQ_HANDLED;
}
@@ -1834,7 +1855,6 @@
pr_debug("fast_chg = %d\n", fast_chg);
if (fast_chg == 0) {
/* enable fastchg irq */
- pm8921_chg_enable_irq(chip, FASTCHG_IRQ);
count = 0;
wake_unlock(&chip->eoc_wake_lock);
return;
@@ -1942,48 +1962,69 @@
DECLARE_WORK(btm_config_work, btm_configure_work);
+static void set_appropriate_battery_current(struct pm8921_chg_chip *chip)
+{
+ unsigned int chg_current = chip->max_bat_chg_current;
+
+ if (chip->is_bat_cool)
+ chg_current = min(chg_current, chip->cool_bat_chg_current);
+
+ if (chip->is_bat_warm)
+ chg_current = min(chg_current, chip->warm_bat_chg_current);
+
+ if (thermal_mitigation != 0 && !chip->thermal_mitigation)
+ chg_current = min(chg_current,
+ chip->thermal_mitigation[thermal_mitigation]);
+
+ pm_chg_ibatmax_set(the_chip, chg_current);
+}
+
#define TEMP_HYSTERISIS_DEGC 2
static void battery_cool(bool enter)
{
pr_debug("enter = %d\n", enter);
+ if (enter == the_chip->is_bat_cool)
+ return;
+ the_chip->is_bat_cool = enter;
if (enter) {
btm_config.low_thr_temp =
the_chip->cool_temp + TEMP_HYSTERISIS_DEGC;
- pm_chg_ibatmax_set(the_chip, the_chip->cool_bat_chg_current);
+ set_appropriate_battery_current(the_chip);
pm_chg_vddmax_set(the_chip, the_chip->cool_bat_voltage);
pm_chg_vbatdet_set(the_chip,
the_chip->cool_bat_voltage
- the_chip->resume_voltage_delta);
} else {
btm_config.low_thr_temp = the_chip->cool_temp;
- pm_chg_ibatmax_set(the_chip, the_chip->max_bat_chg_current);
+ set_appropriate_battery_current(the_chip);
pm_chg_vddmax_set(the_chip, the_chip->max_voltage);
pm_chg_vbatdet_set(the_chip,
the_chip->max_voltage - the_chip->resume_voltage_delta);
}
- the_chip->is_bat_cool = enter;
schedule_work(&btm_config_work);
}
static void battery_warm(bool enter)
{
pr_debug("enter = %d\n", enter);
+ if (enter == the_chip->is_bat_warm)
+ return;
+ the_chip->is_bat_warm = enter;
if (enter) {
btm_config.high_thr_temp =
the_chip->warm_temp - TEMP_HYSTERISIS_DEGC;
- pm_chg_ibatmax_set(the_chip, the_chip->warm_bat_chg_current);
+ set_appropriate_battery_current(the_chip);
pm_chg_vddmax_set(the_chip, the_chip->warm_bat_voltage);
pm_chg_vbatdet_set(the_chip,
the_chip->warm_bat_voltage
- the_chip->resume_voltage_delta);
} else {
btm_config.high_thr_temp = the_chip->warm_temp;
- pm_chg_ibatmax_set(the_chip, the_chip->max_bat_chg_current);
+ set_appropriate_battery_current(the_chip);
pm_chg_vddmax_set(the_chip, the_chip->max_voltage);
pm_chg_vbatdet_set(the_chip,
the_chip->max_voltage - the_chip->resume_voltage_delta);
}
- the_chip->is_bat_warm = enter;
schedule_work(&btm_config_work);
}
@@ -2096,8 +2137,7 @@
return -EINVAL;
}
- ret = pm_chg_ibatmax_set(chip,
- chip->thermal_mitigation[thermal_mitigation]);
+ set_appropriate_battery_current(chip);
return ret;
}
module_param_call(thermal_mitigation, set_therm_mitigation_level,
@@ -2143,6 +2183,7 @@
if (usb_chg_current) {
/* reissue a vbus draw call */
__pm8921_charger_vbus_draw(usb_chg_current);
+ fastchg_irq_handler(chip->pmic_chg_irq[FASTCHG_IRQ], chip);
}
spin_unlock_irqrestore(&vbus_lock, flags);
@@ -2181,7 +2222,8 @@
CHG_IRQ(USBIN_OV_IRQ, IRQF_TRIGGER_RISING, usbin_ov_irq_handler),
CHG_IRQ(BATT_INSERTED_IRQ, IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING,
batt_inserted_irq_handler),
- CHG_IRQ(VBATDET_LOW_IRQ, IRQF_TRIGGER_HIGH, vbatdet_low_irq_handler),
+ CHG_IRQ(VBATDET_LOW_IRQ, IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING,
+ vbatdet_low_irq_handler),
CHG_IRQ(USBIN_UV_IRQ, IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING,
usbin_uv_irq_handler),
CHG_IRQ(VBAT_OV_IRQ, IRQF_TRIGGER_RISING, vbat_ov_irq_handler),
@@ -2193,7 +2235,8 @@
CHG_IRQ(CHGFAIL_IRQ, IRQF_TRIGGER_RISING, chgfail_irq_handler),
CHG_IRQ(CHGSTATE_IRQ, IRQF_TRIGGER_RISING, chgstate_irq_handler),
CHG_IRQ(LOOP_CHANGE_IRQ, IRQF_TRIGGER_RISING, loop_change_irq_handler),
- CHG_IRQ(FASTCHG_IRQ, IRQF_TRIGGER_HIGH, fastchg_irq_handler),
+ CHG_IRQ(FASTCHG_IRQ, IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING,
+ fastchg_irq_handler),
CHG_IRQ(TRKLCHG_IRQ, IRQF_TRIGGER_RISING, trklchg_irq_handler),
CHG_IRQ(BATT_REMOVED_IRQ, IRQF_TRIGGER_RISING,
batt_removed_irq_handler),
@@ -2298,7 +2341,6 @@
return rc;
}
- /* TODO needs to be changed as per the temeperature of the battery */
rc = pm_chg_ibatmax_set(chip, chip->max_bat_chg_current);
if (rc) {
pr_err("Failed to set max current to 400 rc=%d\n", rc);
@@ -2438,6 +2480,12 @@
pm8xxx_writeb(chip->dev->parent, PSI_CONFIG_STATUS, 0x0C);
}
+ /* Workarounds for die 3.0 */
+ if (pm8xxx_get_revision(chip->dev->parent) == PM8XXX_REVISION_8921_3p0)
+ pm8xxx_writeb(chip->dev->parent, CHG_BUCK_CTRL_TEST3, 0xAC);
+
+ pm8xxx_writeb(chip->dev->parent, CHG_BUCK_CTRL_TEST3, 0xD9);
+
/* Disable EOC FSM processing */
pm8xxx_writeb(chip->dev->parent, CHG_BUCK_CTRL_TEST3, 0x91);
diff --git a/drivers/power/power_supply_core.c b/drivers/power/power_supply_core.c
index 03810ce..a184ab6 100644
--- a/drivers/power/power_supply_core.c
+++ b/drivers/power/power_supply_core.c
@@ -25,6 +25,44 @@
static struct device_type power_supply_dev_type;
+/**
+ * power_supply_set_current_limit - set current limit
+ * @psy: the power supply to control
+ * @limit: current limit in uA from the power supply.
+ * 0 will disable the power supply.
+ *
+ * This function will set a maximum supply current from a source
+ * and it will disable the charger when limit is 0.
+ */
+int power_supply_set_current_limit(struct power_supply *psy, int limit)
+{
+ const union power_supply_propval ret = {limit,};
+
+ if (psy->set_property)
+ return psy->set_property(psy, POWER_SUPPLY_PROP_CURRENT_MAX,
+ &ret);
+
+ return -ENXIO;
+}
+EXPORT_SYMBOL_GPL(power_supply_set_current_limit);
+
+/**
+ * power_supply_set_charging_by - set charging state of the charger
+ * @psy: the power supply to control
+ * @enable: enables or disables the charger
+ */
+int power_supply_set_charging_by(struct power_supply *psy, bool enable)
+{
+ const union power_supply_propval ret = {enable,};
+
+ if (psy->set_property)
+ return psy->set_property(psy, POWER_SUPPLY_PROP_ONLINE,
+ &ret);
+
+ return -ENXIO;
+}
+EXPORT_SYMBOL_GPL(power_supply_set_charging_by);
+
static int __power_supply_changed_work(struct device *dev, void *data)
{
struct power_supply *psy = (struct power_supply *)data;
diff --git a/drivers/slimbus/slim-msm-ctrl.c b/drivers/slimbus/slim-msm-ctrl.c
index 6aa111c..90e2687 100644
--- a/drivers/slimbus/slim-msm-ctrl.c
+++ b/drivers/slimbus/slim-msm-ctrl.c
@@ -993,8 +993,14 @@
e_addr[2] != QC_CHIPID_SL)
dev->pgdla = laddr;
if (!ret && !pm_runtime_enabled(dev->dev) &&
- laddr == (QC_MSM_DEVS - 1))
+ laddr == (QC_MSM_DEVS - 1)) {
pm_runtime_enable(dev->dev);
+ /*
+ * Avoid runtime-PM by default, but allow
+ * command line activation
+ */
+ pm_runtime_forbid(dev->dev);
+ }
} else if (mc == SLIM_MSG_MC_REPLY_INFORMATION ||
mc == SLIM_MSG_MC_REPLY_VALUE) {
diff --git a/drivers/tty/serial/msm_serial_hs_lite.c b/drivers/tty/serial/msm_serial_hs_lite.c
index 9ba7d2f..a094b4e 100644
--- a/drivers/tty/serial/msm_serial_hs_lite.c
+++ b/drivers/tty/serial/msm_serial_hs_lite.c
@@ -1138,7 +1138,7 @@
spin_unlock(&port->lock);
}
-static int __init msm_hsl_console_setup(struct console *co, char *options)
+static int msm_hsl_console_setup(struct console *co, char *options)
{
struct uart_port *port;
unsigned int vid;
@@ -1201,7 +1201,93 @@
};
#define MSM_HSL_CONSOLE (&msm_hsl_console)
+/*
+ * get_console_state - check the per-port serial console state.
+ * @port: uart_port structure describing the port
+ *
+ * Return the state of serial console availability on port.
+ * return 1: If serial console is enabled on particular UART port.
+ * return 0: If serial console is disabled on particular UART port.
+ */
+static int get_console_state(struct uart_port *port)
+{
+ if (is_console(port) && (port->cons->flags & CON_ENABLED))
+ return 1;
+ else
+ return 0;
+}
+/* show_msm_console - provide per-port serial console state. */
+static ssize_t show_msm_console(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ int enable;
+ struct uart_port *port;
+
+ struct platform_device *pdev = to_platform_device(dev);
+ port = get_port_from_line(pdev->id);
+
+ enable = get_console_state(port);
+
+ return snprintf(buf, sizeof(enable), "%d\n", enable);
+}
+
+/*
+ * set_msm_console - allow to enable/disable serial console on port.
+ *
+ * writing 1 enables serial console on UART port.
+ * writing 0 disables serial console on UART port.
+ */
+static ssize_t set_msm_console(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ int enable, cur_state;
+ struct uart_port *port;
+
+ struct platform_device *pdev = to_platform_device(dev);
+ port = get_port_from_line(pdev->id);
+
+ cur_state = get_console_state(port);
+ enable = buf[0] - '0';
+
+ if (enable == cur_state)
+ return count;
+
+ switch (enable) {
+ case 0:
+ pr_debug("%s(): Calling stop_console\n", __func__);
+ console_stop(port->cons);
+ pr_debug("%s(): Calling unregister_console\n", __func__);
+ unregister_console(port->cons);
+ pm_runtime_put_sync(&pdev->dev);
+ pm_runtime_disable(&pdev->dev);
+ /*
+ * Disable UART Core clk
+ * 3 - to disable the UART clock
+ * Thid parameter is not used here, but used in serial core.
+ */
+ msm_hsl_power(port, 3, 1);
+ break;
+ case 1:
+ pr_debug("%s(): Calling register_console\n", __func__);
+ /*
+ * Disable UART Core clk
+ * 0 - to enable the UART clock
+ * Thid parameter is not used here, but used in serial core.
+ */
+ msm_hsl_power(port, 0, 1);
+ pm_runtime_enable(&pdev->dev);
+ register_console(port->cons);
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ return count;
+}
+static DEVICE_ATTR(console, S_IWUSR | S_IRUGO, show_msm_console,
+ set_msm_console);
#else
#define MSM_HSL_CONSOLE NULL
#endif
@@ -1286,6 +1372,11 @@
device_set_wakeup_capable(&pdev->dev, 1);
platform_set_drvdata(pdev, port);
pm_runtime_enable(port->dev);
+#ifdef CONFIG_SERIAL_MSM_HSL_CONSOLE
+ ret = device_create_file(&pdev->dev, &dev_attr_console);
+ if (unlikely(ret))
+ pr_err("%s():Can't create console attribute\n", __func__);
+#endif
msm_hsl_debugfs_init(msm_hsl_port, pdev->id);
/* Temporarily increase the refcount on the GSBI clock to avoid a race
@@ -1305,6 +1396,9 @@
struct uart_port *port;
port = get_port_from_line(pdev->id);
+#ifdef CONFIG_SERIAL_MSM_HSL_CONSOLE
+ device_remove_file(&pdev->dev, &dev_attr_console);
+#endif
pm_runtime_put_sync(&pdev->dev);
pm_runtime_disable(&pdev->dev);
diff --git a/drivers/usb/gadget/Kconfig b/drivers/usb/gadget/Kconfig
index 117d3bf..94ed950 100644
--- a/drivers/usb/gadget/Kconfig
+++ b/drivers/usb/gadget/Kconfig
@@ -1089,6 +1089,12 @@
This csw hack feature is for increasing the performance of the mass
storage
+config USB_MSC_PROFILING
+ bool "USB MSC performance profiling"
+ help
+ If you say Y here, support will be added for collecting
+ Mass-storage performance numbers at the VFS level.
+
config MODEM_SUPPORT
boolean "modem support in generic serial function driver"
depends on USB_G_ANDROID
diff --git a/drivers/usb/gadget/android.c b/drivers/usb/gadget/android.c
index 1e3beac..af6f351 100644
--- a/drivers/usb/gadget/android.c
+++ b/drivers/usb/gadget/android.c
@@ -62,6 +62,7 @@
#include "f_serial.c"
//#include "f_acm.c"
#include "f_adb.c"
+#include "f_ccid.c"
#include "f_mtp.c"
#include "f_accessory.c"
#define USB_ETH_RNDIS y
@@ -498,6 +499,31 @@
.bind_config = adb_function_bind_config,
};
+/* CCID */
+static int ccid_function_init(struct android_usb_function *f,
+ struct usb_composite_dev *cdev)
+{
+ return ccid_setup();
+}
+
+static void ccid_function_cleanup(struct android_usb_function *f)
+{
+ ccid_cleanup();
+}
+
+static int ccid_function_bind_config(struct android_usb_function *f,
+ struct usb_configuration *c)
+{
+ return ccid_bind_config(c);
+}
+
+static struct android_usb_function ccid_function = {
+ .name = "ccid",
+ .init = ccid_function_init,
+ .cleanup = ccid_function_cleanup,
+ .bind_config = ccid_function_bind_config,
+};
+
#if 0
#define MAX_ACM_INSTANCES 4
struct acm_function_config {
@@ -941,6 +967,7 @@
&diag_function,
&serial_function,
&adb_function,
+ &ccid_function,
// &acm_function,
&mtp_function,
&ptp_function,
@@ -1063,6 +1090,32 @@
/*-------------------------------------------------------------------------*/
/* /sys/class/android_usb/android%d/ interface */
+static ssize_t remote_wakeup_show(struct device *pdev,
+ struct device_attribute *attr, char *buf)
+{
+ return snprintf(buf, PAGE_SIZE, "%d\n",
+ !!(android_config_driver.bmAttributes &
+ USB_CONFIG_ATT_WAKEUP));
+}
+
+static ssize_t remote_wakeup_store(struct device *pdev,
+ struct device_attribute *attr, const char *buff, size_t size)
+{
+ int enable = 0;
+
+ sscanf(buff, "%d", &enable);
+
+ pr_debug("android_usb: %s remote wakeup\n",
+ enable ? "enabling" : "disabling");
+
+ if (enable)
+ android_config_driver.bmAttributes |= USB_CONFIG_ATT_WAKEUP;
+ else
+ android_config_driver.bmAttributes &= ~USB_CONFIG_ATT_WAKEUP;
+
+ return size;
+}
+
static ssize_t
functions_show(struct device *pdev, struct device_attribute *attr, char *buf)
{
@@ -1218,6 +1271,8 @@
static DEVICE_ATTR(functions, S_IRUGO | S_IWUSR, functions_show, functions_store);
static DEVICE_ATTR(enable, S_IRUGO | S_IWUSR, enable_show, enable_store);
static DEVICE_ATTR(state, S_IRUGO, state_show, NULL);
+static DEVICE_ATTR(remote_wakeup, S_IRUGO | S_IWUSR,
+ remote_wakeup_show, remote_wakeup_store);
static struct device_attribute *android_usb_attributes[] = {
&dev_attr_idVendor,
@@ -1232,6 +1287,7 @@
&dev_attr_functions,
&dev_attr_enable,
&dev_attr_state,
+ &dev_attr_remote_wakeup,
NULL
};
diff --git a/drivers/usb/gadget/ci13xxx_udc.c b/drivers/usb/gadget/ci13xxx_udc.c
index 17fe820..e084278 100644
--- a/drivers/usb/gadget/ci13xxx_udc.c
+++ b/drivers/usb/gadget/ci13xxx_udc.c
@@ -2773,6 +2773,7 @@
unsigned long flags;
int i, j;
int retval = -ENOMEM;
+ bool put = false;
trace("%p", driver);
@@ -2877,18 +2878,21 @@
if (udc->udc_driver->flags & CI13XXX_REGS_SHARED)
hw_device_reset(udc);
} else {
+ put = true;
goto done;
}
}
- if (!udc->softconnect)
+ if (!udc->softconnect) {
+ put = true;
goto done;
+ }
retval = hw_device_state(udc->ep0out.qh.dma);
done:
spin_unlock_irqrestore(udc->lock, flags);
- if (retval)
+ if (retval || put)
pm_runtime_put_sync(&udc->gadget.dev);
return retval;
}
diff --git a/drivers/usb/gadget/f_ccid.c b/drivers/usb/gadget/f_ccid.c
new file mode 100644
index 0000000..a11f439
--- /dev/null
+++ b/drivers/usb/gadget/f_ccid.c
@@ -0,0 +1,1014 @@
+/*
+ * f_ccid.c -- CCID function Driver
+ *
+ * Copyright (c) 2011, Code Aurora Forum. 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 and
+ * only version 2 as published by the Free Software Foundation.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details
+ */
+
+#include <linux/slab.h>
+#include <linux/kernel.h>
+#include <linux/device.h>
+#include <linux/usb/android_composite.h>
+#include <linux/fs.h>
+#include <linux/usb/ccid_desc.h>
+#include <linux/miscdevice.h>
+
+#include "f_ccid.h"
+
+#define BULK_IN_BUFFER_SIZE sizeof(struct ccid_bulk_in_header)
+#define BULK_OUT_BUFFER_SIZE sizeof(struct ccid_bulk_out_header)
+#define CTRL_BUF_SIZE 4
+#define FUNCTION_NAME "ccid"
+#define CCID_NOTIFY_INTERVAL 5
+#define CCID_NOTIFY_MAXPACKET 4
+
+/* number of tx requests to allocate */
+#define TX_REQ_MAX 4
+
+struct ccid_descs {
+ struct usb_endpoint_descriptor *in;
+ struct usb_endpoint_descriptor *out;
+ struct usb_endpoint_descriptor *notify;
+};
+
+struct ccid_ctrl_dev {
+ atomic_t opened;
+ struct list_head tx_q;
+ wait_queue_head_t tx_wait_q;
+ unsigned char buf[CTRL_BUF_SIZE];
+ int tx_ctrl_done;
+};
+
+struct ccid_bulk_dev {
+ atomic_t error;
+ atomic_t opened;
+ atomic_t rx_req_busy;
+ wait_queue_head_t read_wq;
+ wait_queue_head_t write_wq;
+ struct usb_request *rx_req;
+ int rx_done;
+ struct list_head tx_idle;
+};
+
+struct f_ccid {
+ struct usb_function function;
+ struct usb_composite_dev *cdev;
+ int ifc_id;
+ spinlock_t lock;
+ atomic_t online;
+ /* usb descriptors */
+ struct ccid_descs fs;
+ struct ccid_descs hs;
+ /* usb eps*/
+ struct usb_ep *notify;
+ struct usb_ep *in;
+ struct usb_ep *out;
+ struct usb_endpoint_descriptor *in_desc;
+ struct usb_endpoint_descriptor *out_desc;
+ struct usb_endpoint_descriptor *notify_desc;
+ struct usb_request *notify_req;
+ struct ccid_ctrl_dev ctrl_dev;
+ struct ccid_bulk_dev bulk_dev;
+ int dtr_state;
+};
+
+static struct f_ccid *_ccid_dev;
+static struct miscdevice ccid_bulk_device;
+static struct miscdevice ccid_ctrl_device;
+
+/* Interface Descriptor: */
+static struct usb_interface_descriptor ccid_interface_desc = {
+ .bLength = USB_DT_INTERFACE_SIZE,
+ .bDescriptorType = USB_DT_INTERFACE,
+ .bNumEndpoints = 3,
+ .bInterfaceClass = USB_CLASS_CSCID,
+ .bInterfaceSubClass = 0,
+ .bInterfaceProtocol = 0,
+};
+/* CCID Class Descriptor */
+static struct usb_ccid_class_descriptor ccid_class_desc = {
+ .bLength = sizeof(ccid_class_desc),
+ .bDescriptorType = CCID_DECRIPTOR_TYPE,
+ .bcdCCID = CCID1_10,
+ .bMaxSlotIndex = 0,
+ /* This value indicates what voltages the CCID can supply to slots */
+ .bVoltageSupport = VOLTS_3_0,
+ .dwProtocols = PROTOCOL_TO,
+ /* Default ICC clock frequency in KHz */
+ .dwDefaultClock = 3580,
+ /* Maximum supported ICC clock frequency in KHz */
+ .dwMaximumClock = 3580,
+ .bNumClockSupported = 0,
+ /* Default ICC I/O data rate in bps */
+ .dwDataRate = 9600,
+ /* Maximum supported ICC I/O data rate in bps */
+ .dwMaxDataRate = 9600,
+ .bNumDataRatesSupported = 0,
+ .dwMaxIFSD = 0,
+ .dwSynchProtocols = 0,
+ .dwMechanical = 0,
+ /* This value indicates what intelligent features the CCID has */
+ .dwFeatures = CCID_FEATURES_EXC_SAPDU |
+ CCID_FEATURES_AUTO_PNEGO |
+ CCID_FEATURES_AUTO_BAUD |
+ CCID_FEATURES_AUTO_CLOCK |
+ CCID_FEATURES_AUTO_VOLT |
+ CCID_FEATURES_AUTO_ACTIV |
+ CCID_FEATURES_AUTO_PCONF,
+ /* extended APDU level Message Length */
+ .dwMaxCCIDMessageLength = 0x200,
+ .bClassGetResponse = 0x0,
+ .bClassEnvelope = 0x0,
+ .wLcdLayout = 0,
+ .bPINSupport = 0,
+ .bMaxCCIDBusySlots = 1
+};
+/* Full speed support: */
+static struct usb_endpoint_descriptor ccid_fs_notify_desc = {
+ .bLength = USB_DT_ENDPOINT_SIZE,
+ .bDescriptorType = USB_DT_ENDPOINT,
+ .bEndpointAddress = USB_DIR_IN,
+ .bmAttributes = USB_ENDPOINT_XFER_INT,
+ .wMaxPacketSize = __constant_cpu_to_le16(CCID_NOTIFY_MAXPACKET),
+ .bInterval = 1 << CCID_NOTIFY_INTERVAL,
+};
+
+static struct usb_endpoint_descriptor ccid_fs_in_desc = {
+ .bLength = USB_DT_ENDPOINT_SIZE,
+ .bDescriptorType = USB_DT_ENDPOINT,
+ .bEndpointAddress = USB_DIR_IN,
+ .bmAttributes = USB_ENDPOINT_XFER_BULK,
+ .wMaxPacketSize = __constant_cpu_to_le16(64),
+};
+
+static struct usb_endpoint_descriptor ccid_fs_out_desc = {
+ .bLength = USB_DT_ENDPOINT_SIZE,
+ .bDescriptorType = USB_DT_ENDPOINT,
+ .bEndpointAddress = USB_DIR_OUT,
+ .bmAttributes = USB_ENDPOINT_XFER_BULK,
+ .wMaxPacketSize = __constant_cpu_to_le16(64),
+};
+
+static struct usb_descriptor_header *ccid_fs_descs[] = {
+ (struct usb_descriptor_header *) &ccid_interface_desc,
+ (struct usb_descriptor_header *) &ccid_class_desc,
+ (struct usb_descriptor_header *) &ccid_fs_notify_desc,
+ (struct usb_descriptor_header *) &ccid_fs_in_desc,
+ (struct usb_descriptor_header *) &ccid_fs_out_desc,
+ NULL,
+};
+
+/* High speed support: */
+static struct usb_endpoint_descriptor ccid_hs_notify_desc = {
+ .bLength = USB_DT_ENDPOINT_SIZE,
+ .bDescriptorType = USB_DT_ENDPOINT,
+ .bEndpointAddress = USB_DIR_IN,
+ .bmAttributes = USB_ENDPOINT_XFER_INT,
+ .wMaxPacketSize = __constant_cpu_to_le16(CCID_NOTIFY_MAXPACKET),
+ .bInterval = CCID_NOTIFY_INTERVAL + 4,
+};
+
+static struct usb_endpoint_descriptor ccid_hs_in_desc = {
+ .bLength = USB_DT_ENDPOINT_SIZE,
+ .bDescriptorType = USB_DT_ENDPOINT,
+ .bEndpointAddress = USB_DIR_IN,
+ .bmAttributes = USB_ENDPOINT_XFER_BULK,
+ .wMaxPacketSize = __constant_cpu_to_le16(512),
+};
+
+static struct usb_endpoint_descriptor ccid_hs_out_desc = {
+ .bLength = USB_DT_ENDPOINT_SIZE,
+ .bDescriptorType = USB_DT_ENDPOINT,
+ .bEndpointAddress = USB_DIR_OUT,
+ .bmAttributes = USB_ENDPOINT_XFER_BULK,
+ .wMaxPacketSize = __constant_cpu_to_le16(512),
+};
+
+static struct usb_descriptor_header *ccid_hs_descs[] = {
+ (struct usb_descriptor_header *) &ccid_interface_desc,
+ (struct usb_descriptor_header *) &ccid_class_desc,
+ (struct usb_descriptor_header *) &ccid_hs_notify_desc,
+ (struct usb_descriptor_header *) &ccid_hs_in_desc,
+ (struct usb_descriptor_header *) &ccid_hs_out_desc,
+ NULL,
+};
+
+static inline struct f_ccid *func_to_ccid(struct usb_function *f)
+{
+ return container_of(f, struct f_ccid, function);
+}
+
+static void ccid_req_put(struct f_ccid *ccid_dev, struct list_head *head,
+ struct usb_request *req)
+{
+ unsigned long flags;
+
+ spin_lock_irqsave(&ccid_dev->lock, flags);
+ list_add_tail(&req->list, head);
+ spin_unlock_irqrestore(&ccid_dev->lock, flags);
+}
+
+static struct usb_request *ccid_req_get(struct f_ccid *ccid_dev,
+ struct list_head *head)
+{
+ unsigned long flags;
+ struct usb_request *req = NULL;
+
+ spin_lock_irqsave(&ccid_dev->lock, flags);
+ if (!list_empty(head)) {
+ req = list_first_entry(head, struct usb_request, list);
+ list_del(&req->list);
+ }
+ spin_unlock_irqrestore(&ccid_dev->lock, flags);
+ return req;
+}
+
+static void ccid_notify_complete(struct usb_ep *ep, struct usb_request *req)
+{
+ switch (req->status) {
+ case -ECONNRESET:
+ case -ESHUTDOWN:
+ case 0:
+ break;
+ default:
+ pr_err("CCID notify ep error %d\n", req->status);
+ }
+}
+
+static void ccid_bulk_complete_in(struct usb_ep *ep, struct usb_request *req)
+{
+ struct f_ccid *ccid_dev = _ccid_dev;
+ struct ccid_bulk_dev *bulk_dev = &ccid_dev->bulk_dev;
+
+ if (req->status != 0)
+ atomic_set(&bulk_dev->error, 1);
+
+ ccid_req_put(ccid_dev, &bulk_dev->tx_idle, req);
+ wake_up(&bulk_dev->write_wq);
+}
+
+static void ccid_bulk_complete_out(struct usb_ep *ep, struct usb_request *req)
+{
+ struct f_ccid *ccid_dev = _ccid_dev;
+ struct ccid_bulk_dev *bulk_dev = &ccid_dev->bulk_dev;
+ if (req->status != 0)
+ atomic_set(&bulk_dev->error, 1);
+
+ bulk_dev->rx_done = 1;
+ wake_up(&bulk_dev->read_wq);
+}
+
+static struct usb_request *
+ccid_request_alloc(struct usb_ep *ep, unsigned len, gfp_t kmalloc_flags)
+{
+ struct usb_request *req;
+
+ req = usb_ep_alloc_request(ep, kmalloc_flags);
+
+ if (req != NULL) {
+ req->length = len;
+ req->buf = kmalloc(len, kmalloc_flags);
+ if (req->buf == NULL) {
+ usb_ep_free_request(ep, req);
+ req = NULL;
+ }
+ }
+
+ return req ? req : ERR_PTR(-ENOMEM);
+}
+
+static void ccid_request_free(struct usb_request *req, struct usb_ep *ep)
+{
+ if (req) {
+ kfree(req->buf);
+ usb_ep_free_request(ep, req);
+ }
+}
+
+static int
+ccid_function_setup(struct usb_function *f, const struct usb_ctrlrequest *ctrl)
+{
+ struct f_ccid *ccid_dev = container_of(f, struct f_ccid, function);
+ struct ccid_ctrl_dev *ctrl_dev = &ccid_dev->ctrl_dev;
+ struct usb_composite_dev *cdev = f->config->cdev;
+ struct usb_request *req = cdev->req;
+ int ret = -EOPNOTSUPP;
+ u16 w_index = le16_to_cpu(ctrl->wIndex);
+ u16 w_value = le16_to_cpu(ctrl->wValue);
+ u16 w_length = le16_to_cpu(ctrl->wLength);
+
+ if (!atomic_read(&ccid_dev->online))
+ return -ENOTCONN;
+
+ switch ((ctrl->bRequestType << 8) | ctrl->bRequest) {
+
+ case ((USB_DIR_OUT | USB_TYPE_CLASS | USB_RECIP_INTERFACE) << 8)
+ | CCIDGENERICREQ_ABORT:
+ if (w_length != 0)
+ goto invalid;
+ ctrl_dev->buf[0] = CCIDGENERICREQ_ABORT;
+ ctrl_dev->buf[1] = w_value & 0xFF;
+ ctrl_dev->buf[2] = (w_value >> 8) & 0xFF;
+ ctrl_dev->buf[3] = 0x00;
+ ctrl_dev->tx_ctrl_done = 1;
+ wake_up(&ctrl_dev->tx_wait_q);
+ return 0;
+
+ case ((USB_DIR_IN | USB_TYPE_CLASS | USB_RECIP_INTERFACE) << 8)
+ | CCIDGENERICREQ_GET_CLOCK_FREQUENCIES:
+ if (w_length > req->length)
+ goto invalid;
+ *(u32 *) req->buf =
+ cpu_to_le32(ccid_class_desc.dwDefaultClock);
+ ret = min_t(u32, w_length,
+ sizeof(ccid_class_desc.dwDefaultClock));
+ break;
+
+ case ((USB_DIR_IN | USB_TYPE_CLASS | USB_RECIP_INTERFACE) << 8)
+ | CCIDGENERICREQ_GET_DATA_RATES:
+ if (w_length > req->length)
+ goto invalid;
+ *(u32 *) req->buf = cpu_to_le32(ccid_class_desc.dwDataRate);
+ ret = min_t(u32, w_length, sizeof(ccid_class_desc.dwDataRate));
+ break;
+
+ default:
+invalid:
+ pr_debug("invalid control req%02x.%02x v%04x i%04x l%d\n",
+ ctrl->bRequestType, ctrl->bRequest,
+ w_value, w_index, w_length);
+ }
+
+ /* respond with data transfer or status phase? */
+ if (ret >= 0) {
+ pr_debug("ccid req%02x.%02x v%04x i%04x l%d\n",
+ ctrl->bRequestType, ctrl->bRequest,
+ w_value, w_index, w_length);
+ req->length = ret;
+ ret = usb_ep_queue(cdev->gadget->ep0, req, GFP_ATOMIC);
+ if (ret < 0)
+ pr_err("ccid ep0 enqueue err %d\n", ret);
+ }
+
+ return ret;
+}
+
+static void ccid_function_disable(struct usb_function *f)
+{
+ struct f_ccid *ccid_dev = func_to_ccid(f);
+ struct ccid_bulk_dev *bulk_dev = &ccid_dev->bulk_dev;
+ struct ccid_ctrl_dev *ctrl_dev = &ccid_dev->ctrl_dev;
+ struct usb_request *req;
+
+ /* Disable endpoints */
+ usb_ep_disable(ccid_dev->notify);
+ usb_ep_disable(ccid_dev->in);
+ usb_ep_disable(ccid_dev->out);
+ /* Free endpoint related requests */
+ ccid_request_free(ccid_dev->notify_req, ccid_dev->notify);
+ if (!atomic_read(&bulk_dev->rx_req_busy))
+ ccid_request_free(bulk_dev->rx_req, ccid_dev->out);
+ while ((req = ccid_req_get(ccid_dev, &bulk_dev->tx_idle)))
+ ccid_request_free(req, ccid_dev->in);
+
+ ccid_dev->dtr_state = 0;
+ atomic_set(&ccid_dev->online, 0);
+ /* Wake up threads */
+ wake_up(&bulk_dev->write_wq);
+ wake_up(&bulk_dev->read_wq);
+ wake_up(&ctrl_dev->tx_wait_q);
+
+}
+
+static int
+ccid_function_set_alt(struct usb_function *f, unsigned intf, unsigned alt)
+{
+ struct f_ccid *ccid_dev = func_to_ccid(f);
+ struct usb_composite_dev *cdev = ccid_dev->cdev;
+ struct ccid_bulk_dev *bulk_dev = &ccid_dev->bulk_dev;
+ struct usb_request *req;
+ int ret = 0;
+ int i;
+
+ ccid_dev->notify_req = ccid_request_alloc(ccid_dev->notify,
+ sizeof(struct usb_ccid_notification), GFP_ATOMIC);
+ if (IS_ERR(ccid_dev->notify_req)) {
+ pr_err("%s: unable to allocate memory for notify req\n",
+ __func__);
+ return PTR_ERR(ccid_dev->notify_req);
+ }
+ ccid_dev->notify_req->complete = ccid_notify_complete;
+ ccid_dev->notify_req->context = ccid_dev;
+
+ /* now allocate requests for our endpoints */
+ req = ccid_request_alloc(ccid_dev->out, BULK_OUT_BUFFER_SIZE,
+ GFP_ATOMIC);
+ if (IS_ERR(req)) {
+ pr_err("%s: unable to allocate memory for out req\n",
+ __func__);
+ ret = PTR_ERR(req);
+ goto free_notify;
+ }
+ req->complete = ccid_bulk_complete_out;
+ req->context = ccid_dev;
+ bulk_dev->rx_req = req;
+
+ for (i = 0; i < TX_REQ_MAX; i++) {
+ req = ccid_request_alloc(ccid_dev->in, BULK_IN_BUFFER_SIZE,
+ GFP_ATOMIC);
+ if (IS_ERR(req)) {
+ pr_err("%s: unable to allocate memory for in req\n",
+ __func__);
+ ret = PTR_ERR(req);
+ goto free_bulk_out;
+ }
+ req->complete = ccid_bulk_complete_in;
+ req->context = ccid_dev;
+ ccid_req_put(ccid_dev, &bulk_dev->tx_idle, req);
+ }
+
+ /* choose the descriptors and enable endpoints */
+ ccid_dev->notify_desc = ep_choose(cdev->gadget,
+ ccid_dev->hs.notify,
+ ccid_dev->fs.notify);
+ ret = usb_ep_enable(ccid_dev->notify, ccid_dev->notify_desc);
+ if (ret) {
+ pr_err("%s: usb ep#%s enable failed, err#%d\n",
+ __func__, ccid_dev->notify->name, ret);
+ goto free_bulk_in;
+ }
+ ccid_dev->notify->driver_data = ccid_dev;
+
+ ccid_dev->in_desc = ep_choose(cdev->gadget,
+ ccid_dev->hs.in, ccid_dev->fs.in);
+ ret = usb_ep_enable(ccid_dev->in, ccid_dev->in_desc);
+ if (ret) {
+ pr_err("%s: usb ep#%s enable failed, err#%d\n",
+ __func__, ccid_dev->in->name, ret);
+ goto disable_ep_notify;
+ }
+
+ ccid_dev->out_desc = ep_choose(cdev->gadget,
+ ccid_dev->hs.out, ccid_dev->fs.out);
+ ret = usb_ep_enable(ccid_dev->out, ccid_dev->out_desc);
+ if (ret) {
+ pr_err("%s: usb ep#%s enable failed, err#%d\n",
+ __func__, ccid_dev->out->name, ret);
+ goto disable_ep_in;
+ }
+ ccid_dev->dtr_state = 1;
+ atomic_set(&ccid_dev->online, 1);
+ return ret;
+
+disable_ep_in:
+ usb_ep_disable(ccid_dev->in);
+disable_ep_notify:
+ usb_ep_disable(ccid_dev->notify);
+ ccid_dev->notify->driver_data = NULL;
+free_bulk_in:
+ while ((req = ccid_req_get(ccid_dev, &bulk_dev->tx_idle)))
+ ccid_request_free(req, ccid_dev->in);
+free_bulk_out:
+ ccid_request_free(bulk_dev->rx_req, ccid_dev->out);
+free_notify:
+ ccid_request_free(ccid_dev->notify_req, ccid_dev->notify);
+ return ret;
+}
+
+static void ccid_function_unbind(struct usb_configuration *c,
+ struct usb_function *f)
+{
+ if (gadget_is_dualspeed(c->cdev->gadget))
+ usb_free_descriptors(f->hs_descriptors);
+ usb_free_descriptors(f->descriptors);
+
+}
+
+static int ccid_function_bind(struct usb_configuration *c,
+ struct usb_function *f)
+{
+ struct f_ccid *ccid_dev = func_to_ccid(f);
+ struct usb_ep *ep;
+ struct usb_composite_dev *cdev = c->cdev;
+ int ret = -ENODEV;
+
+ ccid_dev->ifc_id = usb_interface_id(c, f);
+ if (ccid_dev->ifc_id < 0) {
+ pr_err("%s: unable to allocate ifc id, err:%d",
+ __func__, ccid_dev->ifc_id);
+ return ccid_dev->ifc_id;
+ }
+ ccid_interface_desc.bInterfaceNumber = ccid_dev->ifc_id;
+
+ ep = usb_ep_autoconfig(cdev->gadget, &ccid_fs_notify_desc);
+ if (!ep) {
+ pr_err("%s: usb epnotify autoconfig failed\n", __func__);
+ return -ENODEV;
+ }
+ ccid_dev->notify = ep;
+ ep->driver_data = cdev;
+
+ ep = usb_ep_autoconfig(cdev->gadget, &ccid_fs_in_desc);
+ if (!ep) {
+ pr_err("%s: usb epin autoconfig failed\n", __func__);
+ ret = -ENODEV;
+ goto ep_auto_in_fail;
+ }
+ ccid_dev->in = ep;
+ ep->driver_data = cdev;
+
+ ep = usb_ep_autoconfig(cdev->gadget, &ccid_fs_out_desc);
+ if (!ep) {
+ pr_err("%s: usb epout autoconfig failed\n", __func__);
+ ret = -ENODEV;
+ goto ep_auto_out_fail;
+ }
+ ccid_dev->out = ep;
+ ep->driver_data = cdev;
+
+ f->descriptors = usb_copy_descriptors(ccid_fs_descs);
+ if (!f->descriptors)
+ goto ep_auto_out_fail;
+
+ ccid_dev->fs.in = usb_find_endpoint(ccid_fs_descs,
+ f->descriptors,
+ &ccid_fs_in_desc);
+ ccid_dev->fs.out = usb_find_endpoint(ccid_fs_descs,
+ f->descriptors,
+ &ccid_fs_out_desc);
+ ccid_dev->fs.notify = usb_find_endpoint(ccid_fs_descs,
+ f->descriptors,
+ &ccid_fs_notify_desc);
+
+ if (gadget_is_dualspeed(cdev->gadget)) {
+ ccid_hs_in_desc.bEndpointAddress =
+ ccid_fs_in_desc.bEndpointAddress;
+ ccid_hs_out_desc.bEndpointAddress =
+ ccid_fs_out_desc.bEndpointAddress;
+ ccid_hs_notify_desc.bEndpointAddress =
+ ccid_fs_notify_desc.bEndpointAddress;
+
+ /* copy descriptors, and track endpoint copies */
+ f->hs_descriptors = usb_copy_descriptors(ccid_hs_descs);
+ if (!f->hs_descriptors)
+ goto ep_auto_out_fail;
+
+ ccid_dev->hs.in = usb_find_endpoint(ccid_hs_descs,
+ f->hs_descriptors, &ccid_hs_in_desc);
+ ccid_dev->hs.out = usb_find_endpoint(ccid_hs_descs,
+ f->hs_descriptors, &ccid_hs_out_desc);
+ ccid_dev->hs.notify = usb_find_endpoint(ccid_hs_descs,
+ f->hs_descriptors, &ccid_hs_notify_desc);
+ }
+
+ pr_debug("%s: CCID %s Speed, IN:%s OUT:%s\n", __func__,
+ gadget_is_dualspeed(cdev->gadget) ? "dual" : "full",
+ ccid_dev->in->name, ccid_dev->out->name);
+
+ return 0;
+
+ep_auto_out_fail:
+ ccid_dev->out->driver_data = NULL;
+ ccid_dev->out = NULL;
+ep_auto_in_fail:
+ ccid_dev->in->driver_data = NULL;
+ ccid_dev->in = NULL;
+
+ return ret;
+}
+
+static int ccid_bulk_open(struct inode *ip, struct file *fp)
+{
+ struct f_ccid *ccid_dev = _ccid_dev;
+ struct ccid_bulk_dev *bulk_dev = &ccid_dev->bulk_dev;
+ unsigned long flags;
+
+ pr_debug("ccid_bulk_open\n");
+ if (!atomic_read(&ccid_dev->online)) {
+ pr_debug("%s: USB cable not connected\n", __func__);
+ return -ENODEV;
+ }
+
+ if (atomic_read(&bulk_dev->opened)) {
+ pr_debug("%s: bulk device is already opened\n", __func__);
+ return -EBUSY;
+ }
+ atomic_set(&bulk_dev->opened, 1);
+ /* clear the error latch */
+ atomic_set(&bulk_dev->error, 0);
+ spin_lock_irqsave(&ccid_dev->lock, flags);
+ fp->private_data = ccid_dev;
+ spin_unlock_irqrestore(&ccid_dev->lock, flags);
+
+ return 0;
+}
+
+static int ccid_bulk_release(struct inode *ip, struct file *fp)
+{
+ struct f_ccid *ccid_dev = fp->private_data;
+ struct ccid_bulk_dev *bulk_dev = &ccid_dev->bulk_dev;
+
+ pr_debug("ccid_bulk_release\n");
+ atomic_set(&bulk_dev->opened, 0);
+ return 0;
+}
+
+static ssize_t ccid_bulk_read(struct file *fp, char __user *buf,
+ size_t count, loff_t *pos)
+{
+ struct f_ccid *ccid_dev = fp->private_data;
+ struct ccid_bulk_dev *bulk_dev = &ccid_dev->bulk_dev;
+ struct usb_request *req;
+ int r = count, xfer;
+ int ret;
+ unsigned long flags;
+
+ pr_debug("ccid_bulk_read(%d)\n", count);
+
+ if (count > BULK_OUT_BUFFER_SIZE) {
+ pr_err("%s: max_buffer_size:%d given_pkt_size:%d\n",
+ __func__, BULK_OUT_BUFFER_SIZE, count);
+ return -ENOMEM;
+ }
+
+ if (atomic_read(&bulk_dev->error)) {
+ r = -EIO;
+ pr_err("%s bulk_dev_error\n", __func__);
+ goto done;
+ }
+
+requeue_req:
+ spin_lock_irqsave(&ccid_dev->lock, flags);
+ if (!atomic_read(&ccid_dev->online)) {
+ pr_debug("%s: USB cable not connected\n", __func__);
+ return -ENODEV;
+ }
+ /* queue a request */
+ req = bulk_dev->rx_req;
+ req->length = count;
+ bulk_dev->rx_done = 0;
+ spin_unlock_irqrestore(&ccid_dev->lock, flags);
+ ret = usb_ep_queue(ccid_dev->out, req, GFP_KERNEL);
+ if (ret < 0) {
+ r = -EIO;
+ pr_err("%s usb ep queue failed\n", __func__);
+ atomic_set(&bulk_dev->error, 1);
+ goto done;
+ }
+ /* wait for a request to complete */
+ ret = wait_event_interruptible(bulk_dev->read_wq, bulk_dev->rx_done ||
+ atomic_read(&bulk_dev->error) ||
+ !atomic_read(&ccid_dev->online));
+ if (ret < 0) {
+ atomic_set(&bulk_dev->error, 1);
+ r = ret;
+ usb_ep_dequeue(ccid_dev->out, req);
+ goto done;
+ }
+ if (!atomic_read(&bulk_dev->error)) {
+ spin_lock_irqsave(&ccid_dev->lock, flags);
+ if (!atomic_read(&ccid_dev->online)) {
+ spin_unlock_irqrestore(&ccid_dev->lock, flags);
+ pr_debug("%s: USB cable not connected\n", __func__);
+ r = -ENODEV;
+ goto done;
+ }
+ /* If we got a 0-len packet, throw it back and try again. */
+ if (req->actual == 0) {
+ spin_unlock_irqrestore(&ccid_dev->lock, flags);
+ goto requeue_req;
+ }
+ xfer = (req->actual < count) ? req->actual : count;
+ atomic_set(&bulk_dev->rx_req_busy, 1);
+ spin_unlock_irqrestore(&ccid_dev->lock, flags);
+
+ if (copy_to_user(buf, req->buf, xfer))
+ r = -EFAULT;
+
+ spin_lock_irqsave(&ccid_dev->lock, flags);
+ atomic_set(&bulk_dev->rx_req_busy, 0);
+ if (!atomic_read(&ccid_dev->online)) {
+ ccid_request_free(bulk_dev->rx_req, ccid_dev->out);
+ spin_unlock_irqrestore(&ccid_dev->lock, flags);
+ pr_debug("%s: USB cable not connected\n", __func__);
+ r = -ENODEV;
+ goto done;
+ }
+ spin_unlock_irqrestore(&ccid_dev->lock, flags);
+ } else {
+ r = -EIO;
+ }
+done:
+ pr_debug("ccid_bulk_read returning %d\n", r);
+ return r;
+}
+
+static ssize_t ccid_bulk_write(struct file *fp, const char __user *buf,
+ size_t count, loff_t *pos)
+{
+ struct f_ccid *ccid_dev = fp->private_data;
+ struct ccid_bulk_dev *bulk_dev = &ccid_dev->bulk_dev;
+ struct usb_request *req = 0;
+ int r = count;
+ int ret;
+ unsigned long flags;
+
+ pr_debug("ccid_bulk_write(%d)\n", count);
+
+ if (!atomic_read(&ccid_dev->online)) {
+ pr_debug("%s: USB cable not connected\n", __func__);
+ return -ENODEV;
+ }
+
+ if (!count) {
+ pr_err("%s: zero length ctrl pkt\n", __func__);
+ return -ENODEV;
+ }
+ if (count > BULK_IN_BUFFER_SIZE) {
+ pr_err("%s: max_buffer_size:%d given_pkt_size:%d\n",
+ __func__, BULK_IN_BUFFER_SIZE, count);
+ return -ENOMEM;
+ }
+
+
+ /* get an idle tx request to use */
+ ret = wait_event_interruptible(bulk_dev->write_wq,
+ ((req = ccid_req_get(ccid_dev, &bulk_dev->tx_idle)) ||
+ atomic_read(&bulk_dev->error)));
+
+ if (ret < 0) {
+ r = ret;
+ goto done;
+ }
+
+ if (atomic_read(&bulk_dev->error)) {
+ pr_err(" %s dev->error\n", __func__);
+ r = -EIO;
+ goto done;
+ }
+ if (copy_from_user(req->buf, buf, count)) {
+ if (!atomic_read(&ccid_dev->online)) {
+ pr_debug("%s: USB cable not connected\n",
+ __func__);
+ ccid_request_free(req, ccid_dev->in);
+ r = -ENODEV;
+ } else {
+ ccid_req_put(ccid_dev, &bulk_dev->tx_idle, req);
+ r = -EFAULT;
+ }
+ goto done;
+ }
+ req->length = count;
+ ret = usb_ep_queue(ccid_dev->in, req, GFP_KERNEL);
+ if (ret < 0) {
+ pr_debug("ccid_bulk_write: xfer error %d\n", ret);
+ atomic_set(&bulk_dev->error, 1);
+ ccid_req_put(ccid_dev, &bulk_dev->tx_idle, req);
+ r = -EIO;
+ spin_lock_irqsave(&ccid_dev->lock, flags);
+ if (!atomic_read(&ccid_dev->online)) {
+ spin_unlock_irqrestore(&ccid_dev->lock, flags);
+ pr_debug("%s: USB cable not connected\n",
+ __func__);
+ while ((req = ccid_req_get(ccid_dev,
+ &bulk_dev->tx_idle)))
+ ccid_request_free(req, ccid_dev->in);
+ r = -ENODEV;
+ }
+ spin_unlock_irqrestore(&ccid_dev->lock, flags);
+ goto done;
+ }
+done:
+ pr_debug("ccid_bulk_write returning %d\n", r);
+ return r;
+}
+
+static const struct file_operations ccid_bulk_fops = {
+ .owner = THIS_MODULE,
+ .read = ccid_bulk_read,
+ .write = ccid_bulk_write,
+ .open = ccid_bulk_open,
+ .release = ccid_bulk_release,
+};
+
+static struct miscdevice ccid_bulk_device = {
+ .minor = MISC_DYNAMIC_MINOR,
+ .name = "ccid_bulk",
+ .fops = &ccid_bulk_fops,
+};
+
+static int ccid_bulk_device_init(struct f_ccid *dev)
+{
+ int ret;
+ struct ccid_bulk_dev *bulk_dev = &dev->bulk_dev;
+
+ init_waitqueue_head(&bulk_dev->read_wq);
+ init_waitqueue_head(&bulk_dev->write_wq);
+ INIT_LIST_HEAD(&bulk_dev->tx_idle);
+
+ ret = misc_register(&ccid_bulk_device);
+ if (ret) {
+ pr_err("%s: failed to register misc device\n", __func__);
+ return ret;
+ }
+
+ return 0;
+}
+
+static int ccid_ctrl_open(struct inode *inode, struct file *fp)
+{
+ struct f_ccid *ccid_dev = _ccid_dev;
+ struct ccid_ctrl_dev *ctrl_dev = &ccid_dev->ctrl_dev;
+ unsigned long flags;
+
+ if (!atomic_read(&ccid_dev->online)) {
+ pr_debug("%s: USB cable not connected\n", __func__);
+ return -ENODEV;
+ }
+ if (atomic_read(&ctrl_dev->opened)) {
+ pr_debug("%s: ctrl device is already opened\n", __func__);
+ return -EBUSY;
+ }
+ atomic_set(&ctrl_dev->opened, 1);
+ spin_lock_irqsave(&ccid_dev->lock, flags);
+ fp->private_data = ccid_dev;
+ spin_unlock_irqrestore(&ccid_dev->lock, flags);
+
+ return 0;
+}
+
+
+static int ccid_ctrl_release(struct inode *inode, struct file *fp)
+{
+ struct f_ccid *ccid_dev = fp->private_data;
+ struct ccid_ctrl_dev *ctrl_dev = &ccid_dev->ctrl_dev;
+
+ atomic_set(&ctrl_dev->opened, 0);
+
+ return 0;
+}
+
+static ssize_t ccid_ctrl_read(struct file *fp, char __user *buf,
+ size_t count, loff_t *ppos)
+{
+ struct f_ccid *ccid_dev = fp->private_data;
+ struct ccid_ctrl_dev *ctrl_dev = &ccid_dev->ctrl_dev;
+ int ret = 0;
+
+ if (!atomic_read(&ccid_dev->online)) {
+ pr_debug("%s: USB cable not connected\n", __func__);
+ return -ENODEV;
+ }
+ if (count > CTRL_BUF_SIZE)
+ count = CTRL_BUF_SIZE;
+
+ ret = wait_event_interruptible(ctrl_dev->tx_wait_q,
+ ctrl_dev->tx_ctrl_done);
+ if (ret < 0)
+ return ret;
+ ctrl_dev->tx_ctrl_done = 0;
+
+ if (!atomic_read(&ccid_dev->online)) {
+ pr_debug("%s: USB cable not connected\n", __func__);
+ return -ENODEV;
+ }
+ ret = copy_to_user(buf, ctrl_dev->buf, count);
+ if (ret)
+ return -EFAULT;
+
+ return count;
+}
+
+static long
+ccid_ctrl_ioctl(struct file *fp, unsigned cmd, u_long arg)
+{
+ struct f_ccid *ccid_dev = fp->private_data;
+ struct usb_request *req = ccid_dev->notify_req;
+ struct usb_ccid_notification *ccid_notify = req->buf;
+ void __user *argp = (void __user *)arg;
+ int ret = 0;
+
+ switch (cmd) {
+ case CCID_NOTIFY_CARD:
+ if (copy_from_user(ccid_notify, argp,
+ sizeof(struct usb_ccid_notification)))
+ return -EFAULT;
+ req->length = 2;
+ break;
+ case CCID_NOTIFY_HWERROR:
+ if (copy_from_user(ccid_notify, argp,
+ sizeof(struct usb_ccid_notification)))
+ return -EFAULT;
+ req->length = 4;
+ break;
+ case CCID_READ_DTR:
+ if (copy_to_user((int *)arg, &ccid_dev->dtr_state, sizeof(int)))
+ return -EFAULT;
+ return 0;
+ }
+ ret = usb_ep_queue(ccid_dev->notify, ccid_dev->notify_req, GFP_KERNEL);
+ if (ret < 0) {
+ pr_err("ccid notify ep enqueue error %d\n", ret);
+ return ret;
+ }
+ return 0;
+}
+
+static const struct file_operations ccid_ctrl_fops = {
+ .owner = THIS_MODULE,
+ .open = ccid_ctrl_open,
+ .release = ccid_ctrl_release,
+ .read = ccid_ctrl_read,
+ .unlocked_ioctl = ccid_ctrl_ioctl,
+};
+
+static struct miscdevice ccid_ctrl_device = {
+ .minor = MISC_DYNAMIC_MINOR,
+ .name = "ccid_ctrl",
+ .fops = &ccid_ctrl_fops,
+};
+
+static int ccid_ctrl_device_init(struct f_ccid *dev)
+{
+ int ret;
+ struct ccid_ctrl_dev *ctrl_dev = &dev->ctrl_dev;
+
+ INIT_LIST_HEAD(&ctrl_dev->tx_q);
+ init_waitqueue_head(&ctrl_dev->tx_wait_q);
+
+ ret = misc_register(&ccid_ctrl_device);
+ if (ret) {
+ pr_err("%s: failed to register misc device\n", __func__);
+ return ret;
+ }
+
+ return 0;
+}
+
+static int ccid_bind_config(struct usb_configuration *c)
+{
+ struct f_ccid *ccid_dev = _ccid_dev;
+
+ pr_debug("ccid_bind_config\n");
+ ccid_dev->cdev = c->cdev;
+ ccid_dev->function.name = FUNCTION_NAME;
+ ccid_dev->function.descriptors = ccid_fs_descs;
+ ccid_dev->function.hs_descriptors = ccid_hs_descs;
+ ccid_dev->function.bind = ccid_function_bind;
+ ccid_dev->function.unbind = ccid_function_unbind;
+ ccid_dev->function.set_alt = ccid_function_set_alt;
+ ccid_dev->function.setup = ccid_function_setup;
+ ccid_dev->function.disable = ccid_function_disable;
+
+ return usb_add_function(c, &ccid_dev->function);
+
+}
+
+static int ccid_setup(void)
+{
+ struct f_ccid *ccid_dev;
+ int ret;
+
+ ccid_dev = kzalloc(sizeof(*ccid_dev), GFP_KERNEL);
+ if (!ccid_dev)
+ return -ENOMEM;
+
+ _ccid_dev = ccid_dev;
+ spin_lock_init(&ccid_dev->lock);
+
+ ret = ccid_ctrl_device_init(ccid_dev);
+ if (ret) {
+ pr_err("%s: ccid_ctrl_device_init failed, err:%d\n",
+ __func__, ret);
+ goto err_ctrl_init;
+ }
+ ret = ccid_bulk_device_init(ccid_dev);
+ if (ret) {
+ pr_err("%s: ccid_bulk_device_init failed, err:%d\n",
+ __func__, ret);
+ goto err_bulk_init;
+ }
+
+ return 0;
+err_bulk_init:
+ misc_deregister(&ccid_ctrl_device);
+err_ctrl_init:
+ kfree(ccid_dev);
+ pr_err("ccid gadget driver failed to initialize\n");
+ return ret;
+}
+
+static void ccid_cleanup(void)
+{
+ misc_deregister(&ccid_bulk_device);
+ misc_deregister(&ccid_ctrl_device);
+ kfree(_ccid_dev);
+}
diff --git a/drivers/usb/gadget/f_ccid.h b/drivers/usb/gadget/f_ccid.h
new file mode 100644
index 0000000..4d6a0ea
--- /dev/null
+++ b/drivers/usb/gadget/f_ccid.h
@@ -0,0 +1,83 @@
+/*
+ * Copyright (c) 2011, Code Aurora Forum. 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 and
+ * only version 2 as published by the Free Software Foundation.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details
+ */
+
+#ifndef __F_CCID_H
+#define __F_CCID_H
+
+#define PROTOCOL_TO 0x01
+#define PROTOCOL_T1 0x02
+#define ABDATA_SIZE 512
+
+/* define for dwFeatures for Smart Card Device Class Descriptors */
+/* No special characteristics */
+#define CCID_FEATURES_NADA 0x00000000
+/* Automatic parameter configuration based on ATR data */
+#define CCID_FEATURES_AUTO_PCONF 0x00000002
+/* Automatic activation of ICC on inserting */
+#define CCID_FEATURES_AUTO_ACTIV 0x00000004
+/* Automatic ICC voltage selection */
+#define CCID_FEATURES_AUTO_VOLT 0x00000008
+/* Automatic ICC clock frequency change */
+#define CCID_FEATURES_AUTO_CLOCK 0x00000010
+/* Automatic baud rate change */
+#define CCID_FEATURES_AUTO_BAUD 0x00000020
+/*Automatic parameters negotiation made by the CCID */
+#define CCID_FEATURES_AUTO_PNEGO 0x00000040
+/* Automatic PPS made by the CCID according to the active parameters */
+#define CCID_FEATURES_AUTO_PPS 0x00000080
+/* CCID can set ICC in clock stop mode */
+#define CCID_FEATURES_ICCSTOP 0x00000100
+/* NAD value other than 00 accepted (T=1 protocol in use) */
+#define CCID_FEATURES_NAD 0x00000200
+/* Automatic IFSD exchange as first exchange (T=1 protocol in use) */
+#define CCID_FEATURES_AUTO_IFSD 0x00000400
+/* TPDU level exchanges with CCID */
+#define CCID_FEATURES_EXC_TPDU 0x00010000
+/* Short APDU level exchange with CCID */
+#define CCID_FEATURES_EXC_SAPDU 0x00020000
+/* Short and Extended APDU level exchange with CCID */
+#define CCID_FEATURES_EXC_APDU 0x00040000
+/* USB Wake up signaling supported on card insertion and removal */
+#define CCID_FEATURES_WAKEUP 0x00100000
+
+#define CCID_NOTIFY_CARD _IOW('C', 1, struct usb_ccid_notification)
+#define CCID_NOTIFY_HWERROR _IOW('C', 2, struct usb_ccid_notification)
+#define CCID_READ_DTR _IOR('C', 3, int)
+
+struct usb_ccid_notification {
+ unsigned char buf[4];
+} __packed;
+
+struct ccid_bulk_in_header {
+ unsigned char bMessageType;
+ unsigned long wLength;
+ unsigned char bSlot;
+ unsigned char bSeq;
+ unsigned char bStatus;
+ unsigned char bError;
+ unsigned char bSpecific;
+ unsigned char abData[ABDATA_SIZE];
+ unsigned char bSizeToSend;
+} __packed;
+
+struct ccid_bulk_out_header {
+ unsigned char bMessageType;
+ unsigned long wLength;
+ unsigned char bSlot;
+ unsigned char bSeq;
+ unsigned char bSpecific_0;
+ unsigned char bSpecific_1;
+ unsigned char bSpecific_2;
+ unsigned char APDU[ABDATA_SIZE];
+} __packed;
+#endif
diff --git a/drivers/usb/misc/mdm_ctrl_bridge.c b/drivers/usb/misc/mdm_ctrl_bridge.c
index 87adf2e..0397428 100644
--- a/drivers/usb/misc/mdm_ctrl_bridge.c
+++ b/drivers/usb/misc/mdm_ctrl_bridge.c
@@ -318,7 +318,7 @@
return;
dev = __dev[id];
- if (!dev && !dev->brdg)
+ if (!dev || !dev->brdg)
return;
dev_dbg(&dev->udev->dev, "%s:\n", __func__);
diff --git a/drivers/usb/misc/mdm_data_bridge.c b/drivers/usb/misc/mdm_data_bridge.c
index c41fcfb..7c44a9a 100644
--- a/drivers/usb/misc/mdm_data_bridge.c
+++ b/drivers/usb/misc/mdm_data_bridge.c
@@ -120,7 +120,7 @@
return -EINVAL;
dev = __dev[id];
- if (!dev && !dev->brdg)
+ if (!dev || !dev->brdg)
return -ENODEV;
dev->rx_unthrottled_cnt++;
@@ -321,7 +321,7 @@
return;
dev = __dev[id];
- if (!dev && !dev->brdg)
+ if (!dev || !dev->brdg)
return;
dev_dbg(&dev->udev->dev, "%s:\n", __func__);
@@ -872,7 +872,9 @@
}
static const struct usb_device_id bridge_ids[] = {
- { USB_DEVICE(0x5c6, 0x9001) },
+ { USB_DEVICE(0x5c6, 0x9001) },
+
+ { } /* Terminating entry */
};
MODULE_DEVICE_TABLE(usb, bridge_ids);
diff --git a/drivers/usb/otg/msm_otg.c b/drivers/usb/otg/msm_otg.c
index f8b320f..ec922f1 100644
--- a/drivers/usb/otg/msm_otg.c
+++ b/drivers/usb/otg/msm_otg.c
@@ -39,6 +39,7 @@
#include <linux/mfd/pm8xxx/pm8921-charger.h>
#include <mach/clk.h>
+#include <mach/msm_xo.h>
#define MSM_USB_BASE (motg->regs)
#define DRIVER_NAME "msm_otg"
@@ -506,14 +507,15 @@
return ret;
}
- ulpi_init(motg);
-
ret = msm_otg_link_reset(motg);
if (ret) {
dev_err(otg->dev, "link reset failed\n");
return ret;
}
msleep(100);
+
+ ulpi_init(motg);
+
/* Ensure that RESET operation is completed before turning off clock */
mb();
@@ -568,6 +570,7 @@
int cnt = 0;
bool session_active;
u32 phy_ctrl_val = 0;
+ unsigned ret;
if (atomic_read(&motg->in_lpm))
return 0;
@@ -661,6 +664,12 @@
if (!IS_ERR(motg->pclk_src))
clk_disable(motg->pclk_src);
+ /* usb phy no more require TCXO clock, hence vote for TCXO disable */
+ ret = msm_xo_mode_vote(motg->xo_handle, MSM_XO_MODE_OFF);
+ if (ret)
+ dev_err(otg->dev, "%s failed to devote for "
+ "TCXO D0 buffer%d\n", __func__, ret);
+
if (motg->caps & ALLOW_PHY_POWER_COLLAPSE && !session_active) {
msm_hsusb_ldo_enable(motg, 0);
motg->lpm_flags |= PHY_PWR_COLLAPSED;
@@ -695,11 +704,19 @@
int cnt = 0;
unsigned temp;
u32 phy_ctrl_val = 0;
+ unsigned ret;
if (!atomic_read(&motg->in_lpm))
return 0;
wake_lock(&motg->wlock);
+
+ /* Vote for TCXO when waking up the phy */
+ ret = msm_xo_mode_vote(motg->xo_handle, MSM_XO_MODE_ON);
+ if (ret)
+ dev_err(otg->dev, "%s failed to vote for "
+ "TCXO D0 buffer%d\n", __func__, ret);
+
if (!IS_ERR(motg->pclk_src))
clk_enable(motg->pclk_src);
@@ -2282,12 +2299,27 @@
goto free_regs;
}
+ motg->xo_handle = msm_xo_get(MSM_XO_TCXO_D0, "usb");
+ if (IS_ERR(motg->xo_handle)) {
+ dev_err(&pdev->dev, "%s not able to get the handle "
+ "to vote for TCXO D0 buffer\n", __func__);
+ ret = PTR_ERR(motg->xo_handle);
+ goto free_regs;
+ }
+
+ ret = msm_xo_mode_vote(motg->xo_handle, MSM_XO_MODE_ON);
+ if (ret) {
+ dev_err(&pdev->dev, "%s failed to vote for TCXO "
+ "D0 buffer%d\n", __func__, ret);
+ goto free_xo_handle;
+ }
+
clk_enable(motg->pclk);
ret = msm_hsusb_init_vddcx(motg, 1);
if (ret) {
dev_err(&pdev->dev, "hsusb vddcx init failed\n");
- goto free_regs;
+ goto devote_xo_handle;
}
ret = msm_hsusb_config_vddcx(1);
@@ -2403,6 +2435,10 @@
msm_hsusb_ldo_init(motg, 0);
free_init_vddcx:
msm_hsusb_init_vddcx(motg, 0);
+devote_xo_handle:
+ msm_xo_mode_vote(motg->xo_handle, MSM_XO_MODE_OFF);
+free_xo_handle:
+ msm_xo_put(motg->xo_handle);
free_regs:
iounmap(motg->regs);
put_core_clk:
@@ -2482,6 +2518,7 @@
clk_disable(motg->pclk_src);
clk_put(motg->pclk_src);
}
+ msm_xo_put(motg->xo_handle);
msm_hsusb_ldo_enable(motg, 0);
msm_hsusb_ldo_init(motg, 0);
msm_hsusb_init_vddcx(motg, 0);
diff --git a/drivers/video/msm/Kconfig b/drivers/video/msm/Kconfig
index f7bf993..35d1714 100644
--- a/drivers/video/msm/Kconfig
+++ b/drivers/video/msm/Kconfig
@@ -295,11 +295,11 @@
select FB_MSM_MIPI_DSI_SIMULATOR
default n
-config FB_MSM_OVERLAY_WRITEBACK
+config FB_MSM_OVERLAY0_WRITEBACK
depends on FB_MSM_OVERLAY
- bool "MDP overlay write back mode enable"
+ bool "MDP overlay0 write back mode enable"
---help---
- Support for MDP4 OVERLAY write back mode
+ Support for MDP4 OVERLAY0 write back mode
config FB_MSM_WRITEBACK_MSM_PANEL
depends on FB_MSM_OVERLAY
diff --git a/drivers/video/msm/hdmi_msm.c b/drivers/video/msm/hdmi_msm.c
index 8a1d56e..0f1d19b 100644
--- a/drivers/video/msm/hdmi_msm.c
+++ b/drivers/video/msm/hdmi_msm.c
@@ -51,6 +51,12 @@
static int msm_hdmi_sample_rate = MSM_HDMI_SAMPLE_RATE_48KHZ;
+/* HDMI/HDCP Registers */
+#define HDCP_DDC_STATUS 0x0128
+#define HDCP_DDC_CTRL_0 0x0120
+#define HDCP_DDC_CTRL_1 0x0124
+#define HDMI_DDC_CTRL 0x020C
+
struct workqueue_struct *hdmi_work_queue;
struct hdmi_msm_state_type *hdmi_msm_state;
@@ -1072,6 +1078,8 @@
DEV_DBG("calling reauthenticate from %s HDCP FAIL INT ",
__func__);
+ /* Clear AUTH_FAIL_INFO as well */
+ HDMI_OUTP(0x0118, (hdcp_int_val | (1 << 7)));
return IRQ_HANDLED;
}
/* [8] DDC_XFER_REQ_INT [R] HDCP DDC Transfer Request
@@ -2156,8 +2164,109 @@
if (hdcp_link_status & 0x00000004)
hdcp_auth_info((hdcp_link_status & 0x000000F0) >> 4);
+
+ /* Disable HDCP interrupts */
+ HDMI_OUTP(0x0118, 0x0);
}
+static void check_and_clear_HDCP_DDC_Failure(void)
+{
+ int hdcp_ddc_ctrl1_reg;
+ int hdcp_ddc_status;
+ int failure;
+ int nack0;
+
+ /*
+ * Check for any DDC transfer failures
+ * 0x0128 HDCP_DDC_STATUS
+ * [16] FAILED Indicates that the last HDCP HW DDC transer
+ * failed. This occurs when a transfer is
+ * attempted with HDCP DDC disabled
+ * (HDCP_DDC_DISABLE=1) or the number of retries
+ * match HDCP_DDC_RETRY_CNT
+ *
+ * [14] NACK0 Indicates that the last HDCP HW DDC transfer
+ * was aborted due to a NACK on the first
+ * transaction - cleared by writing 0 to GO bit
+ */
+ hdcp_ddc_status = HDMI_INP(HDCP_DDC_STATUS);
+ failure = (hdcp_ddc_status >> 16) & 0x1;
+ nack0 = (hdcp_ddc_status >> 14) & 0x1;
+ DEV_DBG("%s: On Entry: HDCP_DDC_STATUS = 0x%x, FAILURE = %d,"
+ "NACK0 = %d\n", __func__ , hdcp_ddc_status, failure, nack0);
+
+ if (failure == 0x1) {
+ /*
+ * Indicates that the last HDCP HW DDC transfer failed.
+ * This occurs when a transfer is attempted with HDCP DDC
+ * disabled (HDCP_DDC_DISABLE=1) or the number of retries
+ * matches HDCP_DDC_RETRY_CNT.
+ * Failure occured, let's clear it.
+ */
+ DEV_INFO("%s: DDC failure detected. HDCP_DDC_STATUS=0x%08x\n",
+ __func__, hdcp_ddc_status);
+ /*
+ * First, Disable DDC
+ * 0x0120 HDCP_DDC_CTRL_0
+ * [0] DDC_DISABLE Determines whether HDCP Ri and Pj reads
+ * are done unassisted by hardware or by
+ * software via HDMI_DDC (HDCP provides
+ * interrupts to request software
+ * transfers)
+ * 0 : Use Hardware DDC
+ * 1 : Use Software DDC
+ */
+ HDMI_OUTP(HDCP_DDC_CTRL_0, 0x1);
+
+ /*
+ * ACK the Failure to Clear it
+ * 0x0124 HDCP_DDC_CTRL_1
+ * [0] DDC_FAILED_ACK Write 1 to clear
+ * HDCP_STATUS.HDCP_DDC_FAILED
+ */
+ hdcp_ddc_ctrl1_reg = HDMI_INP(HDCP_DDC_CTRL_1);
+ HDMI_OUTP(HDCP_DDC_CTRL_1, hdcp_ddc_ctrl1_reg | 0x1);
+
+ /* Check if the FAILURE got Cleared */
+ hdcp_ddc_status = HDMI_INP(HDCP_DDC_STATUS);
+ hdcp_ddc_status = (hdcp_ddc_status >> 16) & 0x1;
+ if (hdcp_ddc_status == 0x0) {
+ DEV_INFO("%s: HDCP DDC Failure has been cleared\n",
+ __func__);
+ } else {
+ DEV_WARN("%s: Error: HDCP DDC Failure DID NOT get"
+ "cleared\n", __func__);
+ }
+
+ /* Re-Enable HDCP DDC */
+ HDMI_OUTP(HDCP_DDC_CTRL_0, 0x0);
+ }
+
+ if (nack0 == 0x1) {
+ /*
+ * 0x020C HDMI_DDC_CTRL
+ * [3] SW_STATUS_RESET Write 1 to reset HDMI_DDC_SW_STATUS
+ * flags, will reset SW_DONE, ABORTED,
+ * TIMEOUT, SW_INTERRUPTED,
+ * BUFFER_OVERFLOW, STOPPED_ON_NACK, NACK0,
+ * NACK1, NACK2, NACK3
+ */
+ HDMI_OUTP_ND(HDMI_DDC_CTRL,
+ HDMI_INP(HDMI_DDC_CTRL) | (0x1 << 3));
+ msleep(20);
+ HDMI_OUTP_ND(HDMI_DDC_CTRL,
+ HDMI_INP(HDMI_DDC_CTRL) & ~(0x1 << 3));
+ }
+
+ hdcp_ddc_status = HDMI_INP(HDCP_DDC_STATUS);
+
+ failure = (hdcp_ddc_status >> 16) & 0x1;
+ nack0 = (hdcp_ddc_status >> 14) & 0x1;
+ DEV_DBG("%s: On Exit: HDCP_DDC_STATUS = 0x%x, FAILURE = %d,"
+ "NACK0 = %d\n", __func__ , hdcp_ddc_status, failure, nack0);
+}
+
+
static int hdcp_authentication_part1(void)
{
int ret = 0;
@@ -2275,6 +2384,12 @@
/* encryption_enable | enable */
HDMI_OUTP(0x0110, (1 << 8) | (1 << 0));
+ /*
+ * Check to see if a HDCP DDC Failure is indicated in
+ * HDCP_DDC_STATUS. If yes, clear it.
+ */
+ check_and_clear_HDCP_DDC_Failure();
+
/* 0x0118 HDCP_INT_CTRL
* [2] AUTH_SUCCESS_MASK [R/W] Mask bit for\
* HDCP Authentication
@@ -2314,6 +2429,12 @@
goto error;
}
+ /*
+ * A small delay is needed here to avoid device crash observed
+ * during reauthentication in MSM8960
+ */
+ msleep(20);
+
/* 0x0168 HDCP_RCVPORT_DATA12
[23:8] BSTATUS
[7:0] BCAPS */
@@ -4338,6 +4459,9 @@
{
int rc;
+ if (cpu_is_msm8627())
+ return 0;
+
if (msm_fb_detect_client("hdmi_msm"))
return 0;
diff --git a/drivers/video/msm/mddi.c b/drivers/video/msm/mddi.c
index 9b9ee94..c6f9fb2 100644
--- a/drivers/video/msm/mddi.c
+++ b/drivers/video/msm/mddi.c
@@ -241,7 +241,8 @@
#ifdef ENABLE_FWD_LINK_SKEW_CALIBRATION
if (mddi_client_type < 2) {
/* For skew calibration, clock should be less than 50MHz */
- if (!clk_set_min_rate(mddi_clk, 49000000)) {
+ clk_rate = clk_round_rate(mddi_clk, 49000000);
+ if (!clk_set_rate(mddi_clk, clk_rate)) {
stat_reg = mddi_host_reg_in(STAT);
printk(KERN_DEBUG "\n stat_reg = 0x%x", stat_reg);
mddi_host_reg_out(CMD, MDDI_CMD_HIBERNATE);
@@ -253,7 +254,7 @@
mddi_host_reg_out(CMD, MDDI_CMD_SEND_RTD);
mddi_host_reg_out(CMD, MDDI_CMD_HIBERNATE | 1);
} else {
- printk(KERN_ERR "%s: clk_set_min_rate failed\n",
+ printk(KERN_ERR "%s: clk_set_rate failed\n",
__func__);
}
}
@@ -269,8 +270,9 @@
"%s: can't select mddi io clk targate rate = %d\n",
__func__, clk_rate);
- if (clk_set_min_rate(mddi_clk, clk_rate) < 0)
- printk(KERN_ERR "%s: clk_set_min_rate failed\n",
+ clk_rate = clk_round_rate(mddi_clk, clk_rate);
+ if (clk_set_rate(mddi_clk, clk_rate) < 0)
+ printk(KERN_ERR "%s: clk_set_rate failed\n",
__func__);
#ifdef CONFIG_MSM_BUS_SCALING
@@ -449,9 +451,6 @@
mddi_pad_ctrl = mddi_host_reg_in(PAD_CTL);
mddi_host_reg_out(PAD_CTL, 0x0);
- if (clk_set_min_rate(mddi_clk, 0) < 0)
- printk(KERN_ERR "%s: clk_set_min_rate failed\n", __func__);
-
pmdh_clk_disable();
if (mddi_pdata && mddi_pdata->mddi_power_save)
@@ -477,9 +476,6 @@
mddi_pad_ctrl = mddi_host_reg_in(PAD_CTL);
mddi_host_reg_out(PAD_CTL, 0x0);
- if (clk_set_min_rate(mddi_clk, 0) < 0)
- printk(KERN_ERR "%s: clk_set_min_rate failed\n", __func__);
-
pmdh_clk_disable();
return 0;
@@ -551,6 +547,7 @@
static int __init mddi_driver_init(void)
{
int ret;
+ unsigned long rate;
pmdh_clk_status = 0;
mddi_clk = clk_get(NULL, "mddi_clk");
@@ -558,9 +555,10 @@
printk(KERN_ERR "can't find mddi_clk\n");
return PTR_ERR(mddi_clk);
}
- ret = clk_set_min_rate(mddi_clk, 49000000);
+ rate = clk_round_rate(mddi_clk, 49000000);
+ ret = clk_set_rate(mddi_clk, rate);
if (ret)
- printk(KERN_ERR "Can't set mddi_clk min rate to 49000000\n");
+ printk(KERN_ERR "Can't set mddi_clk min rate to %lu\n", rate);
printk(KERN_INFO "mddi_clk init rate is %lu\n",
clk_get_rate(mddi_clk));
diff --git a/drivers/video/msm/mddi_ext.c b/drivers/video/msm/mddi_ext.c
index 0ecd593..677b46c 100644
--- a/drivers/video/msm/mddi_ext.c
+++ b/drivers/video/msm/mddi_ext.c
@@ -126,8 +126,9 @@
"%s: can't select mddi io clk targate rate = %d\n",
__func__, clk_rate);
- if (clk_set_min_rate(mddi_ext_clk, clk_rate) < 0)
- printk(KERN_ERR "%s: clk_set_min_rate failed\n",
+ clk_rate = clk_round_rate(mddi_ext_clk, clk_rate);
+ if (clk_set_rate(mddi_ext_clk, clk_rate) < 0)
+ printk(KERN_ERR "%s: clk_set_rate failed\n",
__func__);
mddi_host_start_ext_display();
@@ -265,9 +266,6 @@
mddi_ext_is_in_suspend = 1;
- if (clk_set_min_rate(mddi_ext_clk, 0) < 0)
- printk(KERN_ERR "%s: clk_set_min_rate failed\n", __func__);
-
clk_disable(mddi_ext_clk);
if (mddi_ext_pclk)
clk_disable(mddi_ext_pclk);
diff --git a/drivers/video/msm/mdp.c b/drivers/video/msm/mdp.c
index aeeb503..989b154 100644
--- a/drivers/video/msm/mdp.c
+++ b/drivers/video/msm/mdp.c
@@ -57,7 +57,7 @@
struct semaphore mdp_ppp_mutex;
struct semaphore mdp_pipe_ctrl_mutex;
-unsigned long mdp_timer_duration = (HZ/20); /* 50 msecond */
+unsigned long mdp_timer_duration = (HZ/50); /* 20 ms */
boolean mdp_ppp_waiting = FALSE;
uint32 mdp_tv_underflow_cnt;
@@ -1106,11 +1106,10 @@
{
uint8 count;
uint32 current_rate;
- if (mdp_clk && mdp_pdata
- && mdp_pdata->mdp_core_clk_table) {
- if (clk_set_min_rate(mdp_clk,
- min_clk_rate) < 0)
- printk(KERN_ERR "%s: clk_set_min_rate failed\n",
+ if (mdp_clk && mdp_pdata && mdp_pdata->mdp_core_clk_table) {
+ min_clk_rate = clk_round_rate(mdp_clk, min_clk_rate);
+ if (clk_set_rate(mdp_clk, min_clk_rate) < 0)
+ printk(KERN_ERR "%s: clk_set_rate failed\n",
__func__);
else {
count = 0;
@@ -1340,6 +1339,10 @@
/* link to the latest pdev */
mfd->pdev = msm_fb_dev;
+ mfd->mdp_rev = mdp_rev;
+
+ mfd->ov0_blt_state = 0;
+ mfd->use_ov0_blt = 0 ;
/* add panel data */
if (platform_device_add_data
diff --git a/drivers/video/msm/mdp4_overlay.c b/drivers/video/msm/mdp4_overlay.c
index 383a16d..84beb6a 100644
--- a/drivers/video/msm/mdp4_overlay.c
+++ b/drivers/video/msm/mdp4_overlay.c
@@ -1555,8 +1555,8 @@
pr_debug("fillratex100 %lu, mdp_pixels_produced %lu\n",
fillratex100, mdp_pixels_produced);
if (mdp_pixels_produced <= mfd->panel_info.xres) {
- pr_err("%s(): LCDC underflow detected during downscale\n",
- __func__);
+ pr_err("%s():display underflow detected with downscale"
+ " params\n", __func__);
return -ERANGE;
}
@@ -1833,7 +1833,6 @@
}
#endif
-#ifdef CONFIG_FB_MSM_OVERLAY_WRITEBACK
int mdp4_overlay_blt(struct fb_info *info, struct msmfb_overlay_blt *req)
{
struct msm_fb_data_type *mfd = (struct msm_fb_data_type *)info->par;
@@ -1876,7 +1875,6 @@
return ret;
}
-#endif
int mdp4_overlay_get(struct fb_info *info, struct mdp_overlay *req)
{
@@ -1968,6 +1966,60 @@
}
}
+static void mdp4_overlay_update_blt_mode(struct msm_fb_data_type *mfd)
+{
+ if (mfd->use_ov0_blt) {
+ if (mfd->panel_info.type == LCDC_PANEL)
+ mdp4_lcdc_overlay_blt_start(mfd);
+ else if (mfd->panel_info.type == MIPI_VIDEO_PANEL)
+ mdp4_dsi_video_blt_start(mfd);
+ else if (ctrl->panel_mode & MDP4_PANEL_DSI_CMD)
+ mdp4_dsi_overlay_blt_start(mfd);
+ } else {
+ if (mfd->panel_info.type == LCDC_PANEL)
+ mdp4_lcdc_overlay_blt_stop(mfd);
+ else if (mfd->panel_info.type == MIPI_VIDEO_PANEL)
+ mdp4_dsi_video_blt_stop(mfd);
+ else if (ctrl->panel_mode & MDP4_PANEL_DSI_CMD)
+ mdp4_dsi_overlay_blt_stop(mfd);
+ }
+}
+
+static u32 mdp4_overlay_blt_enable(struct mdp_overlay *req,
+ struct msm_fb_data_type *mfd, uint32 perf_level)
+{
+ u32 clk_rate = mfd->panel_info.clk_rate;
+ u32 pull_mode = 0, use_blt = 0;
+
+ if (mfd->panel_info.type == MIPI_VIDEO_PANEL)
+ clk_rate = (&mfd->panel_info.mipi)->dsi_pclk_rate;
+
+ if ((mfd->panel_info.type == LCDC_PANEL) ||
+ (mfd->panel_info.type == MIPI_VIDEO_PANEL))
+ pull_mode = 1;
+
+ if (pull_mode && (req->src_rect.h > req->dst_rect.h ||
+ req->src_rect.w > req->dst_rect.w)) {
+ if (mdp4_overlay_validate_downscale(req, mfd, perf_level,
+ clk_rate))
+ use_blt = 1;
+ }
+
+ if (mfd->mdp_rev == MDP_REV_41) {
+ /*
+ * writeback (blt) mode to provide work around for
+ * dsi cmd mode interface hardware bug.
+ */
+ if (ctrl->panel_mode & MDP4_PANEL_DSI_CMD) {
+ if (req->dst_rect.x != 0)
+ use_blt = 1;
+ }
+ if (mfd->panel_info.xres > 1280)
+ use_blt = 1;
+ }
+ return use_blt;
+}
+
int mdp4_overlay_set(struct fb_info *info, struct mdp_overlay *req)
{
struct msm_fb_data_type *mfd = (struct msm_fb_data_type *)info->par;
@@ -1992,22 +2044,6 @@
perf_level = mdp4_overlay_get_perf_level(req);
- if ((mfd->panel_info.type == LCDC_PANEL) &&
- (req->src_rect.h >
- req->dst_rect.h || req->src_rect.w > req->dst_rect.w)) {
- if (mdp4_overlay_validate_downscale(req, mfd,
- perf_level, mfd->panel_info.clk_rate))
- mdp4_lcdc_overlay_blt_start(mfd);
- }
-
- if ((mfd->panel_info.type == MIPI_VIDEO_PANEL) &&
- (req->src_rect.h >
- req->dst_rect.h || req->src_rect.w > req->dst_rect.w)) {
- if (mdp4_overlay_validate_downscale(req, mfd,
- perf_level, (&mfd->panel_info.mipi)->dsi_pclk_rate))
- mdp4_dsi_video_blt_start(mfd);
- }
-
mixer = mfd->panel_info.pdest; /* DISPLAY_1 or DISPLAY_2 */
ret = mdp4_overlay_req2pipe(req, mixer, &pipe, mfd);
@@ -2017,15 +2053,10 @@
return ret;
}
- /*
- * writeback (blt) mode to provide work around for
- * dsi cmd mode interface hardware bug.
- */
- if (ctrl->panel_mode & MDP4_PANEL_DSI_CMD) {
- if (mixer == MDP4_MIXER0 && req->dst_rect.x != 0) {
- mdp4_dsi_blt_dmap_busy_wait(mfd);
- mdp4_dsi_overlay_blt_start(mfd);
- }
+ if (mixer == MDP4_MIXER0) {
+ u32 use_blt = mdp4_overlay_blt_enable(req, mfd, perf_level);
+ mfd->use_ov0_blt &= ~(1 << (pipe->pipe_ndx-1));
+ mfd->use_ov0_blt |= (use_blt << (pipe->pipe_ndx-1));
}
/* return id back to user */
@@ -2136,11 +2167,11 @@
mdp4_mixer_stage_down(pipe);
if (pipe->mixer_num == MDP4_MIXER0) {
+
#ifdef CONFIG_FB_MSM_MIPI_DSI
if (ctrl->panel_mode & MDP4_PANEL_DSI_CMD) {
if (mfd->panel_power_on)
- if (mdp4_dsi_overlay_blt_stop(mfd) == 0)
- mdp4_dsi_cmd_overlay_restore();
+ mdp4_dsi_cmd_overlay_restore();
} else if (ctrl->panel_mode & MDP4_PANEL_DSI_VIDEO) {
mdp4_overlay_reg_flush(pipe, 1);
if (mfd->panel_power_on) {
@@ -2149,7 +2180,6 @@
mdp4_overlay_dsi_video_vsync_push(mfd, pipe);
pipe->flags = flags;
}
- mdp4_dsi_video_blt_stop(mfd);
}
#else
if (ctrl->panel_mode & MDP4_PANEL_MDDI) {
@@ -2168,8 +2198,12 @@
mdp4_overlay_lcdc_vsync_push(mfd, pipe);
pipe->flags = flags;
}
- mdp4_lcdc_overlay_blt_stop(mfd);
}
+
+ mfd->use_ov0_blt &= ~(1 << (pipe->pipe_ndx-1));
+ mdp4_overlay_update_blt_mode(mfd);
+ mfd->ov0_blt_state = mfd->use_ov0_blt;
+
}
#ifdef CONFIG_FB_MSM_DTV
else { /* mixer1, DTV, ATV */
@@ -2402,6 +2436,11 @@
}
}
+ if (mfd->use_ov0_blt != mfd->ov0_blt_state) {
+ mdp4_overlay_update_blt_mode(mfd);
+ mfd->ov0_blt_state = mfd->use_ov0_blt;
+ }
+
if (pipe->pipe_num >= OVERLAY_PIPE_VG1)
mdp4_overlay_vg_setup(pipe); /* video/graphic pipe */
else {
diff --git a/drivers/video/msm/mdp4_overlay_dsi_cmd.c b/drivers/video/msm/mdp4_overlay_dsi_cmd.c
index aecf554..d76e252 100644
--- a/drivers/video/msm/mdp4_overlay_dsi_cmd.c
+++ b/drivers/video/msm/mdp4_overlay_dsi_cmd.c
@@ -302,8 +302,6 @@
mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_OFF, FALSE);
}
-
-#ifdef CONFIG_FB_MSM_OVERLAY_WRITEBACK
int mdp4_dsi_overlay_blt_start(struct msm_fb_data_type *mfd)
{
unsigned long flag;
@@ -370,21 +368,6 @@
mdp4_dsi_overlay_blt_stop(mfd);
}
-#else
-int mdp4_dsi_overlay_blt_offset(struct msm_fb_data_type *mfd,
- struct msmfb_overlay_blt *req)
-{
- return 0;
-}
-int mdp4_dsi_overlay_blt_start(struct msm_fb_data_type *mfd)
-{
- return -EBUSY;
-}
-int mdp4_dsi_overlay_blt_stop(struct msm_fb_data_type *mfd)
-{
- return -EBUSY;
-}
-#endif
void mdp4_blt_xy_update(struct mdp4_overlay_pipe *pipe)
{
@@ -447,7 +430,6 @@
mdp_intr_mask &= ~INTR_DMA_P_DONE;
outp32(MDP_INTR_ENABLE, mdp_intr_mask);
}
- mdp_pipe_ctrl(MDP_OVERLAY0_BLOCK, MDP_BLOCK_POWER_OFF, TRUE);
mdp_disable_irq_nosync(MDP_DMA2_TERM); /* disable intr */
return;
}
@@ -467,8 +449,6 @@
mdp4_stat.kickoff_dmap++;
/* trigger dsi cmd engine */
mipi_dsi_cmd_mdp_start();
-
- mdp_pipe_ctrl(MDP_OVERLAY0_BLOCK, MDP_BLOCK_POWER_OFF, TRUE);
}
@@ -480,7 +460,6 @@
int diff;
if (dsi_pipe->blt_addr == 0) {
- mdp_pipe_ctrl(MDP_OVERLAY0_BLOCK, MDP_BLOCK_POWER_OFF, TRUE);
spin_lock(&mdp_spin_lock);
dma->busy = FALSE;
spin_unlock(&mdp_spin_lock);
diff --git a/drivers/video/msm/mdp4_overlay_dsi_video.c b/drivers/video/msm/mdp4_overlay_dsi_video.c
index 63beb88..938d7c6 100644
--- a/drivers/video/msm/mdp4_overlay_dsi_video.c
+++ b/drivers/video/msm/mdp4_overlay_dsi_video.c
@@ -479,30 +479,6 @@
mdp4_set_perf_level();
}
-static void mdp4_overlay_dsi_video_prefill(struct msm_fb_data_type *mfd)
-{
- unsigned long flag;
-
- if (dsi_pipe->blt_addr) {
- mdp4_overlay_dsi_video_dma_busy_wait(mfd);
-
- mdp4_dsi_video_blt_ov_update(dsi_pipe);
- dsi_pipe->ov_cnt++;
-
- spin_lock_irqsave(&mdp_spin_lock, flag);
- outp32(MDP_INTR_CLEAR, INTR_OVERLAY0_DONE);
- mdp_intr_mask |= INTR_OVERLAY0_DONE;
- outp32(MDP_INTR_ENABLE, mdp_intr_mask);
- mdp_enable_irq(MDP_OVERLAY0_TERM);
- mfd->dma->busy = TRUE;
- mb(); /* make sure all registers updated */
- spin_unlock_irqrestore(&mdp_spin_lock, flag);
- outpdw(MDP_BASE + 0x0004, 0); /* kickoff overlay engine */
- mdp4_stat.kickoff_ov0++;
- mb();
- }
-}
-
void mdp4_overlay_dsi_video_vsync_push(struct msm_fb_data_type *mfd,
struct mdp4_overlay_pipe *pipe)
{
@@ -569,7 +545,30 @@
complete(&dma->comp);
}
-#ifdef CONFIG_FB_MSM_OVERLAY_WRITEBACK
+static void mdp4_overlay_dsi_video_prefill(struct msm_fb_data_type *mfd)
+{
+ unsigned long flag;
+
+ if (dsi_pipe->blt_addr) {
+ mdp4_overlay_dsi_video_dma_busy_wait(mfd);
+
+ mdp4_dsi_video_blt_ov_update(dsi_pipe);
+ dsi_pipe->ov_cnt++;
+
+ spin_lock_irqsave(&mdp_spin_lock, flag);
+ outp32(MDP_INTR_CLEAR, INTR_OVERLAY0_DONE);
+ mdp_intr_mask |= INTR_OVERLAY0_DONE;
+ outp32(MDP_INTR_ENABLE, mdp_intr_mask);
+ mdp_enable_irq(MDP_OVERLAY0_TERM);
+ mfd->dma->busy = TRUE;
+ mb(); /* make sure all registers updated */
+ spin_unlock_irqrestore(&mdp_spin_lock, flag);
+ outpdw(MDP_BASE + 0x0004, 0); /* kickoff overlay engine */
+ mdp4_stat.kickoff_ov0++;
+ mb();
+ }
+}
+
/*
* make sure the MIPI_DSI_WRITEBACK_SIZE defined at boardfile
* has enough space h * w * 3 * 2
@@ -658,24 +657,6 @@
{
mdp4_dsi_video_do_blt(mfd, 0);
}
-#else
-int mdp4_dsi_video_overlay_blt_offset(struct msm_fb_data_type *mfd,
- struct msmfb_overlay_blt *req)
-{
- return 0;
-}
-void mdp4_dsi_video_overlay_blt(struct msm_fb_data_type *mfd,
- struct msmfb_overlay_blt *req)
-{
- return;
-}
-void mdp4_dsi_video_blt_start(struct msm_fb_data_type *mfd)
-{
-}
-void mdp4_dsi_video_blt_stop(struct msm_fb_data_type *mfd)
-{
-}
-#endif
void mdp4_dsi_video_overlay(struct msm_fb_data_type *mfd)
{
diff --git a/drivers/video/msm/mdp4_overlay_lcdc.c b/drivers/video/msm/mdp4_overlay_lcdc.c
index a8e39d0..f318691 100644
--- a/drivers/video/msm/mdp4_overlay_lcdc.c
+++ b/drivers/video/msm/mdp4_overlay_lcdc.c
@@ -464,7 +464,6 @@
complete(&dma->comp);
}
-#ifdef CONFIG_FB_MSM_OVERLAY_WRITEBACK
/*
* make sure the MIPI_DSI_WRITEBACK_SIZE defined at boardfile
* has enough space h * w * 3 * 2
@@ -531,24 +530,6 @@
{
mdp4_lcdc_do_blt(mfd, 0);
}
-#else
-int mdp4_lcdc_overlay_blt_offset(struct msm_fb_data_type *mfd,
- struct msmfb_overlay_blt *req)
-{
- return 0;
-}
-void mdp4_lcdc_overlay_blt(struct msm_fb_data_type *mfd,
- struct msmfb_overlay_blt *req)
-{
- return;
-}
-void mdp4_lcdc_overlay_blt_start(struct msm_fb_data_type *mfd)
-{
-}
-void mdp4_lcdc_overlay_blt_stop(struct msm_fb_data_type *mfd)
-{
-}
-#endif
void mdp4_lcdc_overlay(struct msm_fb_data_type *mfd)
{
diff --git a/drivers/video/msm/mipi_dsi_host.c b/drivers/video/msm/mipi_dsi_host.c
index f2e2f10..a177976 100644
--- a/drivers/video/msm/mipi_dsi_host.c
+++ b/drivers/video/msm/mipi_dsi_host.c
@@ -1202,7 +1202,7 @@
if (mfd->panel_info.mipi.no_max_pkt_size) {
/* Only support rlen = 4*n */
rlen += 3;
- rlen &= 0x03;
+ rlen &= ~0x03;
}
len = rlen;
@@ -1491,6 +1491,7 @@
if (isr & DSI_INTR_CMD_MDP_DONE) {
mipi_dsi_mdp_stat_inc(STAT_DSI_MDP);
+ mdp_pipe_ctrl(MDP_OVERLAY0_BLOCK, MDP_BLOCK_POWER_OFF, TRUE);
spin_lock(&dsi_mdp_lock);
dsi_mdp_busy = FALSE;
spin_unlock(&dsi_mdp_lock);
diff --git a/drivers/video/msm/mipi_tc358764_dsi2lvds.c b/drivers/video/msm/mipi_tc358764_dsi2lvds.c
index 2594c1d..8055bd0 100644
--- a/drivers/video/msm/mipi_tc358764_dsi2lvds.c
+++ b/drivers/video/msm/mipi_tc358764_dsi2lvds.c
@@ -236,10 +236,9 @@
mipi_dsi_buf_init(&d2l_tx_buf);
mipi_dsi_buf_init(&d2l_rx_buf);
- mutex_lock(&mfd->dma->ov_mutex);
+ /* mutex had been acquried at dsi_on */
len = mipi_dsi_cmds_rx(mfd, &d2l_tx_buf, &d2l_rx_buf,
&cmd_read_reg, len);
- mutex_unlock(&mfd->dma->ov_mutex);
data = *(u32 *)d2l_rx_buf.data;
@@ -269,9 +268,8 @@
payload.addr = reg;
payload.data = data;
- mutex_lock(&mfd->dma->ov_mutex);
+ /* mutex had been acquried at dsi_on */
mipi_dsi_cmds_tx(mfd, &d2l_tx_buf, &cmd_write_reg, 1);
- mutex_unlock(&mfd->dma->ov_mutex);
pr_debug("%s: reg=0x%x. data=0x%x.\n", __func__, reg, data);
diff --git a/drivers/video/msm/msm_fb.c b/drivers/video/msm/msm_fb.c
index 10e4156..59c2afe 100644
--- a/drivers/video/msm/msm_fb.c
+++ b/drivers/video/msm/msm_fb.c
@@ -2569,8 +2569,6 @@
return 0;
}
-
-#ifdef CONFIG_FB_MSM_OVERLAY_WRITEBACK
static int msmfb_overlay_blt(struct fb_info *info, unsigned long *argp)
{
int ret;
@@ -2607,16 +2605,6 @@
return ret;
}
-#else
-static int msmfb_overlay_blt(struct fb_info *info, unsigned long *argp)
-{
- return 0;
-}
-static int msmfb_overlay_blt_off(struct fb_info *info, unsigned long *argp)
-{
- return 0;
-}
-#endif
#ifdef CONFIG_FB_MSM_WRITEBACK_MSM_PANEL
static int msmfb_overlay_ioctl_writeback_init(struct fb_info *info)
diff --git a/drivers/video/msm/msm_fb.h b/drivers/video/msm/msm_fb.h
index bc25062..de2734d 100644
--- a/drivers/video/msm/msm_fb.h
+++ b/drivers/video/msm/msm_fb.h
@@ -166,7 +166,6 @@
struct completion msmfb_update_notify;
struct completion msmfb_no_update_notify;
u32 ov_start, ov_end;
-
struct mutex writeback_mutex;
struct mutex unregister_mutex;
struct list_head writeback_busy_queue;
@@ -174,6 +173,8 @@
struct list_head writeback_register_queue;
wait_queue_head_t wait_q;
struct ion_client *client;
+ u32 mdp_rev;
+ u32 use_ov0_blt, ov0_blt_state;
};
struct dentry *msm_fb_get_debugfs_root(void);
diff --git a/drivers/video/msm/vidc/1080p/ddl/vcd_ddl_vidc.c b/drivers/video/msm/vidc/1080p/ddl/vcd_ddl_vidc.c
index 8b293b6..cf8f712 100644
--- a/drivers/video/msm/vidc/1080p/ddl/vcd_ddl_vidc.c
+++ b/drivers/video/msm/vidc/1080p/ddl/vcd_ddl_vidc.c
@@ -242,7 +242,11 @@
decoder->hw_bufs.desc),
seq_start_param.descriptor_buffer_size =
decoder->hw_bufs.desc.buffer_size;
- if (decoder->codec.codec == VCD_CODEC_MPEG4)
+ if ((decoder->codec.codec == VCD_CODEC_MPEG4) ||
+ (decoder->codec.codec == VCD_CODEC_DIVX_4) ||
+ (decoder->codec.codec == VCD_CODEC_DIVX_5) ||
+ (decoder->codec.codec == VCD_CODEC_DIVX_6) ||
+ (decoder->codec.codec == VCD_CODEC_XVID))
vidc_sm_set_mpeg4_profile_override(
&ddl->shared_mem[ddl->command_channel],
VIDC_SM_PROFILE_INFO_ASP);
diff --git a/drivers/video/msm/vidc/common/vcd/vcd_sub.c b/drivers/video/msm/vidc/common/vcd/vcd_sub.c
index 3924088..75e0acf 100644
--- a/drivers/video/msm/vidc/common/vcd/vcd_sub.c
+++ b/drivers/video/msm/vidc/common/vcd/vcd_sub.c
@@ -1900,7 +1900,8 @@
VCD_MSG_HIGH("Got input done for EOS initiator");
transc->input_done = false;
transc->in_use = true;
- if (codec_config ||
+ if ((codec_config &&
+ (status != VCD_ERR_BITSTREAM_ERR)) ||
((status == VCD_ERR_BITSTREAM_ERR) &&
!(cctxt->status.mask & VCD_FIRST_IP_DONE) &&
(core_type == VCD_CORE_720P)))
diff --git a/fs/yaffs2/yaffs_vfs.c b/fs/yaffs2/yaffs_vfs.c
index a4db5cc..f56e12c 100644
--- a/fs/yaffs2/yaffs_vfs.c
+++ b/fs/yaffs2/yaffs_vfs.c
@@ -65,7 +65,7 @@
#define YPROC_ROOT NULL
-#define Y_INIT_TIMER(a) init_timer_on_stack(a)
+#define Y_INIT_TIMER(a, b, c) setup_deferrable_timer_on_stack(a, b, c)
#define WRITE_SIZE_STR "writesize"
#define WRITE_SIZE(mtd) ((mtd)->writesize)
@@ -1674,10 +1674,9 @@
if (time_before(expires, now))
expires = now + HZ;
- Y_INIT_TIMER(&timer);
+ Y_INIT_TIMER(&timer, yaffs_background_waker,
+ (unsigned long)current);
timer.expires = expires + 1;
- timer.data = (unsigned long)current;
- timer.function = yaffs_background_waker;
set_current_state(TASK_INTERRUPTIBLE);
add_timer(&timer);
diff --git a/include/linux/clk.h b/include/linux/clk.h
index 1d37f42..7213b52 100644
--- a/include/linux/clk.h
+++ b/include/linux/clk.h
@@ -11,6 +11,8 @@
#ifndef __LINUX_CLK_H
#define __LINUX_CLK_H
+#include <linux/kernel.h>
+
struct device;
/*
@@ -41,11 +43,31 @@
struct clk *clk_get(struct device *dev, const char *id);
/**
+ * clk_prepare - prepare a clock source
+ * @clk: clock source
+ *
+ * This prepares the clock source for use.
+ *
+ * Must not be called from within atomic context.
+ */
+#ifdef CONFIG_HAVE_CLK_PREPARE
+int clk_prepare(struct clk *clk);
+#else
+static inline int clk_prepare(struct clk *clk)
+{
+ might_sleep();
+ return 0;
+}
+#endif
+
+/**
* clk_enable - inform the system when the clock source should be running.
* @clk: clock source
*
* If the clock can not be enabled/disabled, this should return success.
*
+ * May be called from atomic contexts.
+ *
* Returns success (0) or negative errno.
*/
int clk_enable(struct clk *clk);
@@ -57,6 +79,8 @@
* Inform the system that a clock source is no longer required by
* a driver and may be shut down.
*
+ * May be called from atomic contexts.
+ *
* Implementation detail: if the clock source is shared between
* multiple drivers, clk_enable() calls must be balanced by the
* same number of clk_disable() calls for the clock source to be
@@ -64,6 +88,25 @@
*/
void clk_disable(struct clk *clk);
+
+/**
+ * clk_unprepare - undo preparation of a clock source
+ * @clk: clock source
+ *
+ * This undoes a previously prepared clock. The caller must balance
+ * the number of prepare and unprepare calls.
+ *
+ * Must not be called from within atomic context.
+ */
+#ifdef CONFIG_HAVE_CLK_PREPARE
+void clk_unprepare(struct clk *clk);
+#else
+static inline void clk_unprepare(struct clk *clk)
+{
+ might_sleep();
+}
+#endif
+
/**
* clk_get_rate - obtain the current clock rate (in Hz) for a clock source.
* This is only valid once the clock source has been enabled.
diff --git a/include/linux/cpu_pm.h b/include/linux/cpu_pm.h
index a165fd7..d399bf8 100644
--- a/include/linux/cpu_pm.h
+++ b/include/linux/cpu_pm.h
@@ -67,7 +67,13 @@
CPU_CLUSTER_PM_EXIT,
};
+#ifdef CONFIG_CPU_PM
int cpu_pm_register_notifier(struct notifier_block *nb);
+#else
+static inline int cpu_pm_register_notifier(struct notifier_block *nb)
+{ return 0; }
+#endif
+
int cpu_pm_unregister_notifier(struct notifier_block *nb);
/*
diff --git a/include/linux/ieee80211.h b/include/linux/ieee80211.h
index bf56b6f..1c4085e 100644
--- a/include/linux/ieee80211.h
+++ b/include/linux/ieee80211.h
@@ -1305,6 +1305,7 @@
WLAN_KEY_LEN_CCMP = 16,
WLAN_KEY_LEN_TKIP = 32,
WLAN_KEY_LEN_AES_CMAC = 16,
+ WLAN_KEY_LEN_WAPI_SMS4 = 32,
};
/**
@@ -1434,6 +1435,7 @@
#define WLAN_CIPHER_SUITE_CCMP 0x000FAC04
#define WLAN_CIPHER_SUITE_WEP104 0x000FAC05
#define WLAN_CIPHER_SUITE_AES_CMAC 0x000FAC06
+#define WLAN_CIPHER_SUITE_SMS4 0x00147201
/* AKM suite selectors */
#define WLAN_AKM_SUITE_8021X 0x000FAC01
diff --git a/include/linux/input/pmic8xxx-pwrkey.h b/include/linux/input/pmic8xxx-pwrkey.h
index 6d2974e..a32eafd 100644
--- a/include/linux/input/pmic8xxx-pwrkey.h
+++ b/include/linux/input/pmic8xxx-pwrkey.h
@@ -24,6 +24,13 @@
*/
struct pm8xxx_pwrkey_platform_data {
bool pull_up;
+ /* Time delay for pwr-key state change interrupt triggering in micro-
+ * second. The actual delay can only be one of these eight levels:
+ * 2 sec, 1 sec, 1/2 sec, 1/4 sec, 1/8 sec, 1/16 sec, 1/32 sec, and
+ * 1/64 sec. The valid range of kpd_trigger_delay_us is 1/64 second to
+ * 2 seconds. A value within the valid range will be rounded down to the
+ * closest level. Any value outside the valid range will be rejected.
+ */
u32 kpd_trigger_delay_us;
u32 wakeup;
};
diff --git a/include/linux/ion.h b/include/linux/ion.h
index 89ac992..b396369 100644
--- a/include/linux/ion.h
+++ b/include/linux/ion.h
@@ -35,6 +35,7 @@
ION_HEAP_TYPE_SYSTEM,
ION_HEAP_TYPE_SYSTEM_CONTIG,
ION_HEAP_TYPE_CARVEOUT,
+ ION_HEAP_TYPE_IOMMU,
ION_HEAP_TYPE_CUSTOM, /* must be last so device specific heaps always
are at the end of this enum */
ION_NUM_HEAPS,
@@ -59,6 +60,7 @@
ION_HEAP_SMI_ID,
ION_HEAP_ADSP_ID,
ION_HEAP_AUDIO_ID,
+ ION_HEAP_IOMMU_ID,
};
#define ION_KMALLOC_HEAP_NAME "kmalloc"
@@ -66,6 +68,7 @@
#define ION_EBI1_HEAP_NAME "EBI1"
#define ION_ADSP_HEAP_NAME "adsp"
#define ION_SMI_HEAP_NAME "smi"
+#define ION_IOMMU_HEAP_NAME "iommu"
#define CACHED 1
#define UNCACHED 0
@@ -99,6 +102,11 @@
* @name: used for debug purposes
* @base: base address of heap in physical memory if applicable
* @size: size of the heap in bytes if applicable
+ * @request_region: function to be called when the number of allocations goes
+ * from 0 -> 1
+ * @release_region: function to be called when the number of allocations goes
+ * from 1 -> 0
+ * @setup_region: function to be called upon ion registration
*
* Provided by the board file.
*/
@@ -109,6 +117,9 @@
ion_phys_addr_t base;
size_t size;
enum ion_memory_types memory_type;
+ void (*request_region)(void *);
+ void (*release_region)(void *);
+ void *(*setup_region)(void);
};
/**
@@ -298,6 +309,65 @@
int ion_handle_get_flags(struct ion_client *client, struct ion_handle *handle,
unsigned long *flags);
+
+/**
+ * ion_map_iommu - map the given handle into an iommu
+ *
+ * @client - client who allocated the handle
+ * @handle - handle to map
+ * @domain_num - domain number to map to
+ * @partition_num - partition number to allocate iova from
+ * @align - alignment for the iova
+ * @iova_length - length of iova to map. If the iova length is
+ * greater than the handle length, the remaining
+ * address space will be mapped to a dummy buffer.
+ * @iova - pointer to store the iova address
+ * @buffer_size - pointer to store the size of the buffer
+ * @flags - flags for options to map
+ *
+ * Maps the handle into the iova space specified via domain number. Iova
+ * will be allocated from the partition specified via partition_num.
+ * Returns 0 on success, negative value on error.
+ */
+int ion_map_iommu(struct ion_client *client, struct ion_handle *handle,
+ int domain_num, int partition_num, unsigned long align,
+ unsigned long iova_length, unsigned long *iova,
+ unsigned long *buffer_size,
+ unsigned long flags);
+
+
+/**
+ * ion_handle_get_size - get the allocated size of a given handle
+ *
+ * @client - client who allocated the handle
+ * @handle - handle to get the size
+ * @size - pointer to store the size
+ *
+ * gives the allocated size of a handle. returns 0 on success, negative
+ * value on error
+ *
+ * NOTE: This is intended to be used only to get a size to pass to map_iommu.
+ * You should *NOT* rely on this for any other usage.
+ */
+
+int ion_handle_get_size(struct ion_client *client, struct ion_handle *handle,
+ unsigned long *size);
+
+/**
+ * ion_unmap_iommu - unmap the handle from an iommu
+ *
+ * @client - client who allocated the handle
+ * @handle - handle to unmap
+ * @domain_num - domain to unmap from
+ * @partition_num - partition to unmap from
+ *
+ * Decrement the reference count on the iommu mapping. If the count is
+ * 0, the mapping will be removed from the iommu.
+ */
+void ion_unmap_iommu(struct ion_client *client, struct ion_handle *handle,
+ int domain_num, int partition_num);
+
+
#else
static inline struct ion_client *ion_client_create(struct ion_device *dev,
unsigned int heap_mask, const char *name)
@@ -370,6 +440,24 @@
{
return -ENODEV;
}
+
+static inline int ion_map_iommu(struct ion_client *client,
+ struct ion_handle *handle, int domain_num,
+ int partition_num, unsigned long align,
+ unsigned long iova_length, unsigned long *iova,
+ unsigned long flags)
+{
+ return -ENODEV;
+}
+
+static inline void ion_unmap_iommu(struct ion_client *client,
+ struct ion_handle *handle, int domain_num,
+ int partition_num)
+{
+ return;
+}
+
+
#endif /* CONFIG_ION */
#endif /* __KERNEL__ */
diff --git a/include/linux/mfd/pm8xxx/core.h b/include/linux/mfd/pm8xxx/core.h
index f0a3278..9a46128 100644
--- a/include/linux/mfd/pm8xxx/core.h
+++ b/include/linux/mfd/pm8xxx/core.h
@@ -26,6 +26,7 @@
PM8XXX_VERSION_8921,
PM8XXX_VERSION_8821,
PM8XXX_VERSION_8018,
+ PM8XXX_VERSION_8922,
};
/* PMIC version specific silicon revisions */
@@ -56,6 +57,11 @@
#define PM8XXX_REVISION_8018_1p1 2
#define PM8XXX_REVISION_8018_2p0 3
+#define PM8XXX_REVISION_8922_TEST 0
+#define PM8XXX_REVISION_8922_1p0 1
+#define PM8XXX_REVISION_8922_1p1 2
+#define PM8XXX_REVISION_8922_2p0 3
+
struct pm8xxx_drvdata {
int (*pmic_readb) (const struct device *dev,
u16 addr, u8 *val);
diff --git a/include/linux/mfd/pm8xxx/pm8921-charger.h b/include/linux/mfd/pm8xxx/pm8921-charger.h
index f39c00f..ef08c47 100644
--- a/include/linux/mfd/pm8xxx/pm8921-charger.h
+++ b/include/linux/mfd/pm8xxx/pm8921-charger.h
@@ -184,6 +184,18 @@
int pm8921_set_max_battery_charge_current(int ma);
/**
+ * pm8921_disable_input_current_limt - disable input current limit
+ *
+ * @disable: disable input curren_limit limit
+ *
+ * Disabling the charge current limit causes current
+ * current limits to have no monitoring. An adequate charger
+ * capable of supplying high current while sustaining VIN_MIN
+ * is required if input current limiting is disabled.
+ */
+int pm8921_disable_input_current_limit(bool disable);
+
+/**
* pm8921_disable_source_current - disable drawing current from source
* @disable: true to disable current drawing from source false otherwise
*
@@ -261,6 +273,10 @@
{
return -ENXIO;
}
+static inline int pm8921_disable_input_current_limit(bool disable)
+{
+ return -ENXIO;
+}
static inline int pm8921_set_max_battery_charge_current(int ma)
{
return -ENXIO;
diff --git a/include/linux/mm.h b/include/linux/mm.h
index 07890ac..c73fdf8 100644
--- a/include/linux/mm.h
+++ b/include/linux/mm.h
@@ -28,6 +28,9 @@
extern unsigned long num_physpages;
extern unsigned long totalram_pages;
+#ifdef CONFIG_FIX_MOVABLE_ZONE
+extern unsigned long total_unmovable_pages;
+#endif
extern void * high_memory;
extern int page_cluster;
diff --git a/include/linux/msm_audio_mvs.h b/include/linux/msm_audio_mvs.h
index c934aee..2813c8f 100644
--- a/include/linux/msm_audio_mvs.h
+++ b/include/linux/msm_audio_mvs.h
@@ -108,10 +108,18 @@
#define MVS_MAX_VOC_PKT_SIZE 640
+struct gsm_header {
+ uint8_t bfi;
+ uint8_t sid;
+ uint8_t taf;
+ uint8_t ufi;
+};
+
struct q6_msm_audio_mvs_frame {
union {
uint32_t frame_type;
uint32_t packet_rate;
+ struct gsm_header gsm_frame_type;
} header;
uint32_t len;
uint8_t voc_pkt[MVS_MAX_VOC_PKT_SIZE];
diff --git a/include/linux/perf_event.h b/include/linux/perf_event.h
index fc94089..473384b 100644
--- a/include/linux/perf_event.h
+++ b/include/linux/perf_event.h
@@ -55,6 +55,7 @@
PERF_COUNT_HW_BUS_CYCLES = 6,
PERF_COUNT_HW_STALLED_CYCLES_FRONTEND = 7,
PERF_COUNT_HW_STALLED_CYCLES_BACKEND = 8,
+ PERF_COUNT_HW_L2_CYCLES = 9,
PERF_COUNT_HW_MAX, /* non-ABI */
};
@@ -219,8 +220,9 @@
precise_ip : 2, /* skid constraint */
mmap_data : 1, /* non-exec mmap data */
sample_id_all : 1, /* sample_type all events */
+ single_instance:1, /* per-cpu event if unset */
- __reserved_1 : 45;
+ __reserved_1:44;
union {
__u32 wakeup_events; /* wakeup every n events */
diff --git a/include/linux/pmic8058-xoadc.h b/include/linux/pmic8058-xoadc.h
index f72ad66..5163b65 100644
--- a/include/linux/pmic8058-xoadc.h
+++ b/include/linux/pmic8058-xoadc.h
@@ -12,8 +12,8 @@
* Qualcomm XOADC Driver header file
*/
-#ifndef _XOADC_H
-#define _XOADC_H_
+#ifndef _PMIC8058_XOADC_H_
+#define _PMIC8058_XOADC_H_
#include <linux/kernel.h>
#include <linux/list.h>
diff --git a/include/linux/power/ltc4088-charger.h b/include/linux/power/ltc4088-charger.h
new file mode 100644
index 0000000..7a0bacf
--- /dev/null
+++ b/include/linux/power/ltc4088-charger.h
@@ -0,0 +1,30 @@
+/* Copyright (c) 2011, Code Aurora Forum. 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 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#ifndef LTC4088_CHARGER_H_
+#define LTC4088_CHARGER_H_
+
+#define LTC4088_CHARGER_DEV_NAME "ltc4088-charger"
+
+/**
+ * struct ltc4088_charger_platform_data - platform data for LTC4088 charger
+ * @gpio_mode_select_d0: GPIO #pin for D0 charger line
+ * @gpio_mode_select_d1: GPIO #pin for D1 charger line
+ * @gpio_mode_select_d2: GPIO #pin for D2 charger line
+ */
+struct ltc4088_charger_platform_data {
+ unsigned int gpio_mode_select_d0;
+ unsigned int gpio_mode_select_d1;
+ unsigned int gpio_mode_select_d2;
+};
+
+#endif /* LTC4088_CHARGER_H_ */
diff --git a/include/linux/power_supply.h b/include/linux/power_supply.h
index 2287c321..cab042b 100644
--- a/include/linux/power_supply.h
+++ b/include/linux/power_supply.h
@@ -157,6 +157,8 @@
enum power_supply_property psp);
void (*external_power_changed)(struct power_supply *psy);
void (*set_charged)(struct power_supply *psy);
+ int (*set_current_limit)(struct power_supply *psy, int limit);
+ int (*set_charging_by)(struct power_supply *psy, bool enable);
/* For APM emulation, think legacy userspace. */
int use_for_apm;
@@ -205,6 +207,8 @@
extern void power_supply_changed(struct power_supply *psy);
extern int power_supply_am_i_supplied(struct power_supply *psy);
extern int power_supply_set_battery_charged(struct power_supply *psy);
+extern int power_supply_set_current_limit(struct power_supply *psy, int limit);
+extern int power_supply_set_charging_by(struct power_supply *psy, bool enable);
#if defined(CONFIG_POWER_SUPPLY) || defined(CONFIG_POWER_SUPPLY_MODULE)
extern int power_supply_is_system_supplied(void);
diff --git a/include/linux/rfkill.h b/include/linux/rfkill.h
index c6c6084..3d049ab 100644
--- a/include/linux/rfkill.h
+++ b/include/linux/rfkill.h
@@ -199,8 +199,11 @@
* NOTE: not necessary for suspend/resume -- in that case the
* core stops polling anyway
*/
+#ifdef CONFIG_RFKILL_PM
void rfkill_resume_polling(struct rfkill *rfkill);
-
+#else
+static inline void rfkill_resume_polling(struct rfkill *rfkill) { }
+#endif
/**
* rfkill_unregister - Unregister a rfkill structure.
diff --git a/include/linux/usb/ccid_desc.h b/include/linux/usb/ccid_desc.h
new file mode 100644
index 0000000..2d1ae74
--- /dev/null
+++ b/include/linux/usb/ccid_desc.h
@@ -0,0 +1,112 @@
+/*
+ * Copyright (c) 2011, Code Aurora Forum. 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 and
+ * only version 2 as published by the Free Software Foundation.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details
+ */
+
+#ifndef __LINUX_USB_CCID_DESC_H
+#define __LINUX_USB_CCID_DESC_H
+
+/*CCID specification version 1.10*/
+#define CCID1_10 0x0110
+
+#define SMART_CARD_DEVICE_CLASS 0x0B
+/* Smart Card Device Class Descriptor Type */
+#define CCID_DECRIPTOR_TYPE 0x21
+
+/* Table 5.3-1 Summary of CCID Class Specific Request */
+#define CCIDGENERICREQ_ABORT 0x01
+#define CCIDGENERICREQ_GET_CLOCK_FREQUENCIES 0x02
+#define CCIDGENERICREQ_GET_DATA_RATES 0x03
+
+/* 6.1 Command Pipe, Bulk-OUT Messages */
+#define PC_TO_RDR_ICCPOWERON 0x62
+#define PC_TO_RDR_ICCPOWEROFF 0x63
+#define PC_TO_RDR_GETSLOTSTATUS 0x65
+#define PC_TO_RDR_XFRBLOCK 0x6F
+#define PC_TO_RDR_GETPARAMETERS 0x6C
+#define PC_TO_RDR_RESETPARAMETERS 0x6D
+#define PC_TO_RDR_SETPARAMETERS 0x61
+#define PC_TO_RDR_ESCAPE 0x6B
+#define PC_TO_RDR_ICCCLOCK 0x6E
+#define PC_TO_RDR_T0APDU 0x6A
+#define PC_TO_RDR_SECURE 0x69
+#define PC_TO_RDR_MECHANICAL 0x71
+#define PC_TO_RDR_ABORT 0x72
+#define PC_TO_RDR_SETDATARATEANDCLOCKFREQUENCY 0x73
+
+/* 6.2 Response Pipe, Bulk-IN Messages */
+#define RDR_TO_PC_DATABLOCK 0x80
+#define RDR_TO_PC_SLOTSTATUS 0x81
+#define RDR_TO_PC_PARAMETERS 0x82
+#define RDR_TO_PC_ESCAPE 0x83
+#define RDR_TO_PC_DATARATEANDCLOCKFREQUENCY 0x84
+
+/* 6.3 Interrupt-IN Messages */
+#define RDR_TO_PC_NOTIFYSLOTCHANGE 0x50
+#define RDR_TO_PC_HARDWAREERROR 0x51
+
+/* Table 6.2-2 Slot error register when bmCommandStatus = 1 */
+#define CMD_ABORTED 0xFF
+#define ICC_MUTE 0xFE
+#define XFR_PARITY_ERROR 0xFD
+#define XFR_OVERRUN 0xFC
+#define HW_ERROR 0xFB
+#define BAD_ATR_TS 0xF8
+#define BAD_ATR_TCK 0xF7
+#define ICC_PROTOCOL_NOT_SUPPORTED 0xF6
+#define ICC_CLASS_NOT_SUPPORTED 0xF5
+#define PROCEDURE_BYTE_CONFLICT 0xF4
+#define DEACTIVATED_PROTOCOL 0xF3
+#define BUSY_WITH_AUTO_SEQUENCE 0xF2
+#define PIN_TIMEOUT 0xF0
+#define PIN_CANCELLED 0xEF
+#define CMD_SLOT_BUSY 0xE0
+
+/* CCID rev 1.1, p.27 */
+#define VOLTS_AUTO 0x00
+#define VOLTS_5_0 0x01
+#define VOLTS_3_0 0x02
+#define VOLTS_1_8 0x03
+
+/* 6.3.1 RDR_to_PC_NotifySlotChange */
+#define ICC_NOT_PRESENT 0x00
+#define ICC_PRESENT 0x01
+#define ICC_CHANGE 0x02
+#define ICC_INSERTED_EVENT (ICC_PRESENT+ICC_CHANGE)
+
+/* Identifies the length of type of subordinate descriptors of a CCID device
+ * Table 5.1-1 Smart Card Device Class descriptors
+ */
+struct usb_ccid_class_descriptor {
+ unsigned char bLength;
+ unsigned char bDescriptorType;
+ unsigned short bcdCCID;
+ unsigned char bMaxSlotIndex;
+ unsigned char bVoltageSupport;
+ unsigned long dwProtocols;
+ unsigned long dwDefaultClock;
+ unsigned long dwMaximumClock;
+ unsigned char bNumClockSupported;
+ unsigned long dwDataRate;
+ unsigned long dwMaxDataRate;
+ unsigned char bNumDataRatesSupported;
+ unsigned long dwMaxIFSD;
+ unsigned long dwSynchProtocols;
+ unsigned long dwMechanical;
+ unsigned long dwFeatures;
+ unsigned long dwMaxCCIDMessageLength;
+ unsigned char bClassGetResponse;
+ unsigned char bClassEnvelope;
+ unsigned short wLcdLayout;
+ unsigned char bPINSupport;
+ unsigned char bMaxCCIDBusySlots;
+} __packed;
+#endif
diff --git a/include/linux/usb/msm_hsusb.h b/include/linux/usb/msm_hsusb.h
index 4c01f5b..a2251fe 100644
--- a/include/linux/usb/msm_hsusb.h
+++ b/include/linux/usb/msm_hsusb.h
@@ -189,6 +189,7 @@
* connected.
* @mA_port: The amount of current drawn by the attached B-device.
* @id_timer: The timer used for polling ID line to detect ACA states.
+ * @xo_handle: TCXO buffer handle
*/
struct msm_otg {
struct otg_transceiver otg;
@@ -220,6 +221,7 @@
unsigned mA_port;
struct timer_list id_timer;
unsigned long caps;
+ struct msm_xo_voter *xo_handle;
/*
* Allowing PHY power collpase turns off the HSUSB 3.3v and 1.8v
* analog regulators while going to low power mode.
diff --git a/include/linux/wakelock.h b/include/linux/wakelock.h
index a096d24..024b913 100644
--- a/include/linux/wakelock.h
+++ b/include/linux/wakelock.h
@@ -33,7 +33,6 @@
};
struct wake_lock {
-#ifdef CONFIG_HAS_WAKELOCK
struct list_head link;
int flags;
const char *name;
@@ -49,7 +48,6 @@
ktime_t last_time;
} stat;
#endif
-#endif
};
#ifdef CONFIG_HAS_WAKELOCK
diff --git a/include/media/msm_camera.h b/include/media/msm_camera.h
index 65ca534..4d5d697 100644
--- a/include/media/msm_camera.h
+++ b/include/media/msm_camera.h
@@ -156,6 +156,9 @@
#define MSM_CAM_IOCTL_RELEASE_FREE_FRAME \
_IOR(MSM_CAM_IOCTL_MAGIC, 46, struct msm_cam_evt_divert_frame *)
+#define MSM_CAM_IOCTL_PICT_PP_DIVERT_DONE \
+ _IOR(MSM_CAM_IOCTL_MAGIC, 47, struct msm_pp_frame *)
+
struct msm_mctl_pp_cmd {
int32_t id;
uint16_t length;
diff --git a/include/media/msm_isp.h b/include/media/msm_isp.h
index b4e1981..4694b78 100644
--- a/include/media/msm_isp.h
+++ b/include/media/msm_isp.h
@@ -203,7 +203,6 @@
#define MCTL_CMD_GET_FRAME_BUFFER 1 /* reserve a free frame buffer */
#define MCTL_CMD_PUT_FRAME_BUFFER 2 /* return the free frame buffer */
#define MCTL_CMD_DIVERT_FRAME_PP_PATH 3 /* divert frame for pp */
-#define MCTL_CMD_DIVERT_FRAME_PP_DONE 4 /* pp done. buf send to app */
/* event typese sending to MCTL PP module */
#define MCTL_PP_EVENT_NOTUSED 0
@@ -252,6 +251,7 @@
};
struct msm_mctl_pp_divert_pp {
int path;
+ int enable;
};
struct msm_vpe_clock_rate {
uint32_t rate;
diff --git a/include/media/radio-iris.h b/include/media/radio-iris.h
index dbdb651..130bc3d 100644
--- a/include/media/radio-iris.h
+++ b/include/media/radio-iris.h
@@ -198,6 +198,7 @@
#define HCI_FM_STATION_DBG_PARAM_CMD 12
#define HCI_FM_ENABLE_TRANS_CMD 13
#define HCI_FM_DISABLE_TRANS_CMD 14
+#define HCI_FM_GET_TX_CONFIG 15
/* Defines for FM TX*/
@@ -241,14 +242,6 @@
__u8 rt_data[TX_RT_DATA_LENGTH];
} __packed;
-struct hci_fm_get_trans_conf_rsp {
- __u8 status;
- __u8 emphasis;
- __u8 rds_std;
- __u32 band_low_limit;
- __u32 band_high_limit;
-} __packed;
-
struct hci_fm_mute_mode_req {
__u8 hard_mute;
__u8 soft_mute;
@@ -428,6 +421,10 @@
struct hci_fm_recv_conf_req recv_conf_rsp;
} __packed;
+struct hci_fm_get_trans_conf_rsp {
+ __u8 status;
+ struct hci_fm_trans_conf_req_struct trans_conf_rsp;
+} __packed;
struct hci_fm_sig_threshold_rsp {
__u8 status;
__u8 sig_threshold;
diff --git a/include/media/tavarua.h b/include/media/tavarua.h
index 43ce153..d40829e 100644
--- a/include/media/tavarua.h
+++ b/include/media/tavarua.h
@@ -148,13 +148,14 @@
V4L2_CID_PRIVATE_TAVARUA_RSSI_DELTA,
V4L2_CID_PRIVATE_TAVARUA_HLSI,
/*
- * Here We have IOCTl's that are specifici to IRIS
- * (V4L2_CID_PRIVATE_BASE+0x1D--V4L2_CID_PRIVATE_BASE+0x27)
+ * Here we have IOCTl's that are specific to IRIS
+ * (V4L2_CID_PRIVATE_BASE + 0x1E to V4L2_CID_PRIVATE_BASE + 0x27)
*/
V4L2_CID_PRIVATE_TAVARUA_SET_NOTCH_FILTER =
- V4L2_CID_PRIVATE_BASE + 0x28,
+ V4L2_CID_PRIVATE_BASE + 0x28, /* IRIS specific command */
V4L2_CID_PRIVATE_TAVARUA_SET_AUDIO_PATH,
- /*0x800002a is used for iris specific ioctl*/
+ V4L2_CID_PRIVATE_TAVARUA_DO_CALIBRATION, /* IRIS specific command */
+ V4L2_CID_PRIVATE_TAVARUA_SRCH_ALGORITHM,
V4L2_CID_PRIVATE_TAVARUA_ON_CHANNEL_THRESHOLD =
V4L2_CTRL_CLASS_USER + 0x92B,
diff --git a/include/net/bluetooth/hci_core.h b/include/net/bluetooth/hci_core.h
index 74e14fb..5a15cec 100644
--- a/include/net/bluetooth/hci_core.h
+++ b/include/net/bluetooth/hci_core.h
@@ -240,6 +240,9 @@
rwlock_t adv_entries_lock;
struct timer_list adv_timer;
+ struct timer_list disc_timer;
+ struct timer_list disc_le_timer;
+
struct hci_dev_stats stat;
struct sk_buff_head driver_init;
@@ -1034,6 +1037,7 @@
int mgmt_remote_name(u16 index, bdaddr_t *bdaddr, u8 status, u8 *name);
void mgmt_inquiry_started(u16 index);
void mgmt_inquiry_complete_evt(u16 index, u8 status);
+int mgmt_encrypt_change(u16 index, bdaddr_t *bdaddr, u8 status);
/* LE SMP Management interface */
int le_user_confirm_reply(struct hci_conn *conn, u16 mgmt_op, void *cp);
diff --git a/include/net/bluetooth/mgmt.h b/include/net/bluetooth/mgmt.h
index ce7ecf1..2d3028d 100644
--- a/include/net/bluetooth/mgmt.h
+++ b/include/net/bluetooth/mgmt.h
@@ -228,6 +228,12 @@
__le16 timeout_multiplier;
} __packed;
+#define MGMT_OP_ENCRYPT_LINK 0x0021
+struct mgmt_cp_encrypt_link {
+ bdaddr_t bdaddr;
+ __u8 enable;
+} __packed;
+
#define MGMT_EV_CMD_COMPLETE 0x0001
struct mgmt_ev_cmd_complete {
__le16 opcode;
@@ -329,3 +335,10 @@
bdaddr_t bdaddr;
} __packed;
+#define MGMT_EV_ENCRYPT_CHANGE 0x0016
+struct mgmt_ev_encrypt_change {
+ bdaddr_t bdaddr;
+ __u8 status;
+} __packed;
+
+
diff --git a/kernel/power/wakelock.c b/kernel/power/wakelock.c
index 23dfc40..2583856 100644
--- a/kernel/power/wakelock.c
+++ b/kernel/power/wakelock.c
@@ -52,8 +52,6 @@
struct wake_lock main_wake_lock;
suspend_state_t requested_suspend_state = PM_SUSPEND_MEM;
static struct wake_lock unknown_wakeup;
-/* flag to warn/bug if wakelocks are taken after suspend_noirq */
-static int msm_suspend_check_done;
static struct wake_lock suspend_backoff_lock;
#define SUSPEND_BACKOFF_THRESHOLD 10
@@ -412,21 +410,11 @@
#endif
if (debug_mask & DEBUG_SUSPEND)
pr_info("power_suspend_late return %d\n", ret);
-
- if (ret == 0)
- msm_suspend_check_done = 1;
return ret;
}
-static int power_resume_early(struct device *dev)
-{
- msm_suspend_check_done = 0;
- return 0;
-}
-
static struct dev_pm_ops power_driver_pm_ops = {
.suspend_noirq = power_suspend_late,
- .resume_noirq = power_resume_early,
};
static struct platform_driver power_driver = {
@@ -569,24 +557,12 @@
void wake_lock(struct wake_lock *lock)
{
- /*
- * if wake lock is being called too late in the suspend sequence,
- * call bug so we get to analyze the callstack
- */
- BUG_ON(msm_suspend_check_done);
-
wake_lock_internal(lock, 0, 0);
}
EXPORT_SYMBOL(wake_lock);
void wake_lock_timeout(struct wake_lock *lock, long timeout)
{
- /*
- * if wake lock is being called too late in the suspend sequence,
- * call bug so we get to analyze the callstack
- */
- BUG_ON(msm_suspend_check_done);
-
wake_lock_internal(lock, timeout, 1);
}
EXPORT_SYMBOL(wake_lock_timeout);
diff --git a/kernel/time/tick-sched.c b/kernel/time/tick-sched.c
index 2480d18..e54ba63 100644
--- a/kernel/time/tick-sched.c
+++ b/kernel/time/tick-sched.c
@@ -646,8 +646,6 @@
next = ktime_add(next, tick_period);
}
local_irq_enable();
-
- printk(KERN_INFO "Switched to NOHz mode on CPU #%d\n", smp_processor_id());
}
/*
@@ -857,10 +855,8 @@
}
#ifdef CONFIG_NO_HZ
- if (tick_nohz_enabled) {
+ if (tick_nohz_enabled)
ts->nohz_mode = NOHZ_MODE_HIGHRES;
- printk(KERN_INFO "Switched to NOHz mode on CPU #%d\n", smp_processor_id());
- }
#endif
}
#endif /* HIGH_RES_TIMERS */
diff --git a/mm/memory_hotplug.c b/mm/memory_hotplug.c
index 709dc6d..70ea0df 100644
--- a/mm/memory_hotplug.c
+++ b/mm/memory_hotplug.c
@@ -379,6 +379,10 @@
unsigned long pfn = page_to_pfn(page);
totalram_pages++;
+#ifdef CONFIG_FIX_MOVABLE_ZONE
+ if (zone_idx(page_zone(page)) != ZONE_MOVABLE)
+ total_unmovable_pages++;
+#endif
if (pfn >= num_physpages)
num_physpages = pfn + 1;
@@ -958,10 +962,17 @@
/* reset pagetype flags and makes migrate type to be MOVABLE */
undo_isolate_page_range(start_pfn, end_pfn);
/* removal success */
- zone->present_pages -= offlined_pages;
+ if (offlined_pages > zone->present_pages)
+ zone->present_pages = 0;
+ else
+ zone->present_pages -= offlined_pages;
zone->zone_pgdat->node_present_pages -= offlined_pages;
totalram_pages -= offlined_pages;
+#ifdef CONFIG_FIX_MOVABLE_ZONE
+ if (zone_idx(zone) != ZONE_MOVABLE)
+ total_unmovable_pages -= offlined_pages;
+#endif
init_per_zone_wmark_min();
if (!node_present_pages(node)) {
diff --git a/mm/page_alloc.c b/mm/page_alloc.c
index e6b53ea..60ad5e9 100644
--- a/mm/page_alloc.c
+++ b/mm/page_alloc.c
@@ -96,6 +96,9 @@
unsigned long totalram_pages __read_mostly;
unsigned long totalreserve_pages __read_mostly;
+#ifdef CONFIG_FIX_MOVABLE_ZONE
+unsigned long total_unmovable_pages __read_mostly;
+#endif
int percpu_pagelist_fraction;
gfp_t gfp_allowed_mask __read_mostly = GFP_BOOT_MASK;
@@ -174,6 +177,9 @@
};
EXPORT_SYMBOL(totalram_pages);
+#ifdef CONFIG_FIX_MOVABLE_ZONE
+EXPORT_SYMBOL(total_unmovable_pages);
+#endif
static char * const zone_names[MAX_NR_ZONES] = {
#ifdef CONFIG_ZONE_DMA
@@ -1485,8 +1491,9 @@
static bool __zone_watermark_ok(struct zone *z, int order, unsigned long mark,
int classzone_idx, int alloc_flags, long free_pages)
{
- /* free_pages my go negative - that's OK */
+ /* free_pages may go negative - that's OK */
long min = mark;
+ long lowmem_reserve = z->lowmem_reserve[classzone_idx];
int o;
free_pages -= (1 << order) + 1;
@@ -1495,7 +1502,7 @@
if (alloc_flags & ALLOC_HARDER)
min -= min / 4;
- if (free_pages <= min + z->lowmem_reserve[classzone_idx])
+ if (free_pages <= min + lowmem_reserve)
return false;
for (o = 0; o < order; o++) {
/* At the next order, this order's pages become unavailable */
diff --git a/mm/slub.c b/mm/slub.c
index adf609e..03bc30b 100644
--- a/mm/slub.c
+++ b/mm/slub.c
@@ -27,6 +27,7 @@
#include <linux/memory.h>
#include <linux/math64.h>
#include <linux/fault-inject.h>
+#include <linux/stacktrace.h>
#include <trace/events/kmem.h>
@@ -191,8 +192,12 @@
/*
* Tracking user of a slab.
*/
+#define TRACK_ADDRS_COUNT 16
struct track {
unsigned long addr; /* Called from address */
+#ifdef CONFIG_STACKTRACE
+ unsigned long addrs[TRACK_ADDRS_COUNT]; /* Called from address */
+#endif
int cpu; /* Was running on cpu */
int pid; /* Pid context */
unsigned long when; /* When did the operation occur */
@@ -420,6 +425,24 @@
struct track *p = get_track(s, object, alloc);
if (addr) {
+#ifdef CONFIG_STACKTRACE
+ struct stack_trace trace;
+ int i;
+
+ trace.nr_entries = 0;
+ trace.max_entries = TRACK_ADDRS_COUNT;
+ trace.entries = p->addrs;
+ trace.skip = 3;
+ save_stack_trace(&trace);
+
+ /* See rant in lockdep.c */
+ if (trace.nr_entries != 0 &&
+ trace.entries[trace.nr_entries - 1] == ULONG_MAX)
+ trace.nr_entries--;
+
+ for (i = trace.nr_entries; i < TRACK_ADDRS_COUNT; i++)
+ p->addrs[i] = 0;
+#endif
p->addr = addr;
p->cpu = smp_processor_id();
p->pid = current->pid;
@@ -444,6 +467,16 @@
printk(KERN_ERR "INFO: %s in %pS age=%lu cpu=%u pid=%d\n",
s, (void *)t->addr, jiffies - t->when, t->cpu, t->pid);
+#ifdef CONFIG_STACKTRACE
+ {
+ int i;
+ for (i = 0; i < TRACK_ADDRS_COUNT; i++)
+ if (t->addrs[i])
+ printk(KERN_ERR "\t%pS\n", (void *)t->addrs[i]);
+ else
+ break;
+ }
+#endif
}
static void print_tracking(struct kmem_cache *s, void *object)
diff --git a/mm/vmalloc.c b/mm/vmalloc.c
index 45ece89..c33d2ae 100644
--- a/mm/vmalloc.c
+++ b/mm/vmalloc.c
@@ -1611,9 +1611,14 @@
struct vm_struct *area;
void *addr;
unsigned long real_size = size;
+#ifdef CONFIG_FIX_MOVABLE_ZONE
+ unsigned long total_pages = total_unmovable_pages;
+#else
+ unsigned long total_pages = totalram_pages;
+#endif
size = PAGE_ALIGN(size);
- if (!size || (size >> PAGE_SHIFT) > totalram_pages)
+ if (!size || (size >> PAGE_SHIFT) > total_pages)
return NULL;
area = __get_vm_area_node(size, align, VM_ALLOC, start, end, node,
diff --git a/net/bluetooth/bnep/bnep.h b/net/bluetooth/bnep/bnep.h
index 8e6c061..e7ee531 100644
--- a/net/bluetooth/bnep/bnep.h
+++ b/net/bluetooth/bnep/bnep.h
@@ -155,6 +155,7 @@
unsigned int role;
unsigned long state;
unsigned long flags;
+ atomic_t terminate;
struct task_struct *task;
struct ethhdr eh;
diff --git a/net/bluetooth/bnep/core.c b/net/bluetooth/bnep/core.c
index dfadb65..61c946c 100644
--- a/net/bluetooth/bnep/core.c
+++ b/net/bluetooth/bnep/core.c
@@ -484,9 +484,11 @@
init_waitqueue_entry(&wait, current);
add_wait_queue(sk_sleep(sk), &wait);
- while (!kthread_should_stop()) {
+ while (1) {
set_current_state(TASK_INTERRUPTIBLE);
+ if (atomic_read(&s->terminate))
+ break;
/* RX */
while ((skb = skb_dequeue(&sk->sk_receive_queue))) {
skb_orphan(skb);
@@ -643,9 +645,10 @@
down_read(&bnep_session_sem);
s = __bnep_get_session(req->dst);
- if (s)
- kthread_stop(s->task);
- else
+ if (s) {
+ atomic_inc(&s->terminate);
+ wake_up_process(s->task);
+ } else
err = -ENOENT;
up_read(&bnep_session_sem);
diff --git a/net/bluetooth/hci_core.c b/net/bluetooth/hci_core.c
index a27358f..e1a90f8 100644
--- a/net/bluetooth/hci_core.c
+++ b/net/bluetooth/hci_core.c
@@ -581,8 +581,11 @@
set_bit(HCI_UP, &hdev->flags);
hci_notify(hdev, HCI_DEV_UP);
if (!test_bit(HCI_SETUP, &hdev->flags) &&
- hdev->dev_type == HCI_BREDR)
+ hdev->dev_type == HCI_BREDR) {
+ hci_dev_lock_bh(hdev);
mgmt_powered(hdev->id, 1);
+ hci_dev_unlock_bh(hdev);
+ }
} else {
/* Init failed, cleanup */
tasklet_kill(&hdev->rx_task);
@@ -668,8 +671,11 @@
* and no tasks are scheduled. */
hdev->close(hdev);
- if (hdev->dev_type == HCI_BREDR)
+ if (hdev->dev_type == HCI_BREDR) {
+ hci_dev_lock_bh(hdev);
mgmt_powered(hdev->id, 0);
+ hci_dev_unlock_bh(hdev);
+ }
/* Clear only non-persistent flags */
if (test_bit(HCI_MGMT, &hdev->flags))
@@ -1547,8 +1553,11 @@
if (!test_bit(HCI_INIT, &hdev->flags) &&
!test_bit(HCI_SETUP, &hdev->flags) &&
- hdev->dev_type == HCI_BREDR)
+ hdev->dev_type == HCI_BREDR) {
+ hci_dev_lock_bh(hdev);
mgmt_index_removed(hdev->id);
+ hci_dev_unlock_bh(hdev);
+ }
if (!IS_ERR(hdev->tfm))
crypto_free_blkcipher(hdev->tfm);
diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c
index a6e3485..13d9b71 100644
--- a/net/bluetooth/hci_event.c
+++ b/net/bluetooth/hci_event.c
@@ -223,12 +223,13 @@
sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_LOCAL_NAME);
if (!sent)
return;
-
+ hci_dev_lock(hdev);
if (!status)
memcpy(hdev->dev_name, sent, HCI_MAX_NAME_LENGTH);
if (test_bit(HCI_MGMT, &hdev->flags))
mgmt_set_local_name_complete(hdev->id, sent, status);
+ hci_dev_unlock(hdev);
}
static void hci_cc_read_local_name(struct hci_dev *hdev, struct sk_buff *skb)
@@ -303,6 +304,7 @@
if (!status) {
__u8 param = *((__u8 *) sent);
int old_pscan, old_iscan;
+ hci_dev_lock(hdev);
old_pscan = test_and_clear_bit(HCI_PSCAN, &hdev->flags);
old_iscan = test_and_clear_bit(HCI_ISCAN, &hdev->flags);
@@ -320,6 +322,7 @@
mgmt_connectable(hdev->id, 1);
} else if (old_pscan)
mgmt_connectable(hdev->id, 0);
+ hci_dev_unlock(hdev);
}
hci_req_complete(hdev, HCI_OP_WRITE_SCAN_ENABLE, status);
@@ -859,20 +862,23 @@
struct hci_conn *conn;
BT_DBG("%s status 0x%x", hdev->name, rp->status);
+ hci_dev_lock(hdev);
if (test_bit(HCI_MGMT, &hdev->flags))
mgmt_pin_code_reply_complete(hdev->id, &rp->bdaddr, rp->status);
if (rp->status != 0)
- return;
+ goto unlock;
cp = hci_sent_cmd_data(hdev, HCI_OP_PIN_CODE_REPLY);
if (!cp)
- return;
+ goto unlock;
conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &cp->bdaddr);
if (conn)
conn->pin_length = cp->pin_len;
+unlock:
+ hci_dev_unlock(hdev);
}
static void hci_cc_pin_code_neg_reply(struct hci_dev *hdev, struct sk_buff *skb)
@@ -880,10 +886,12 @@
struct hci_rp_pin_code_neg_reply *rp = (void *) skb->data;
BT_DBG("%s status 0x%x", hdev->name, rp->status);
+ hci_dev_lock(hdev);
if (test_bit(HCI_MGMT, &hdev->flags))
mgmt_pin_code_neg_reply_complete(hdev->id, &rp->bdaddr,
rp->status);
+ hci_dev_unlock(hdev);
}
static void hci_cc_le_read_buffer_size(struct hci_dev *hdev,
struct sk_buff *skb)
@@ -910,10 +918,12 @@
struct hci_rp_user_confirm_reply *rp = (void *) skb->data;
BT_DBG("%s status 0x%x", hdev->name, rp->status);
+ hci_dev_lock(hdev);
if (test_bit(HCI_MGMT, &hdev->flags))
mgmt_user_confirm_reply_complete(hdev->id, &rp->bdaddr,
rp->status);
+ hci_dev_unlock(hdev);
}
static void hci_cc_user_confirm_neg_reply(struct hci_dev *hdev,
@@ -922,10 +932,12 @@
struct hci_rp_user_confirm_reply *rp = (void *) skb->data;
BT_DBG("%s status 0x%x", hdev->name, rp->status);
+ hci_dev_lock(hdev);
if (test_bit(HCI_MGMT, &hdev->flags))
mgmt_user_confirm_neg_reply_complete(hdev->id, &rp->bdaddr,
rp->status);
+ hci_dev_unlock(hdev);
}
static void hci_cc_read_local_oob_data_reply(struct hci_dev *hdev,
@@ -934,9 +946,11 @@
struct hci_rp_read_local_oob_data *rp = (void *) skb->data;
BT_DBG("%s status 0x%x", hdev->name, rp->status);
+ hci_dev_lock(hdev);
mgmt_read_local_oob_data_reply_complete(hdev->id, rp->hash,
rp->randomizer, rp->status);
+ hci_dev_unlock(hdev);
}
static void hci_cc_le_ltk_reply(struct hci_dev *hdev, struct sk_buff *skb)
@@ -995,8 +1009,10 @@
hci_conn_check_pending(hdev);
} else {
set_bit(HCI_INQUIRY, &hdev->flags);
+ hci_dev_lock(hdev);
if (test_bit(HCI_MGMT, &hdev->flags))
mgmt_inquiry_started(hdev->id);
+ hci_dev_unlock(hdev);
}
}
@@ -1506,9 +1522,11 @@
clear_bit(HCI_INQUIRY, &hdev->flags);
hci_req_complete(hdev, HCI_OP_INQUIRY, status);
+ hci_dev_lock(hdev);
if (test_bit(HCI_MGMT, &hdev->flags))
mgmt_inquiry_complete_evt(hdev->id, status);
+ hci_dev_unlock(hdev);
if (!lmp_le_capable(hdev))
hci_conn_check_pending(hdev);
@@ -1709,7 +1727,9 @@
BT_DBG("%s status %d", hdev->name, ev->status);
if (ev->status) {
+ hci_dev_lock(hdev);
mgmt_disconnect_failed(hdev->id);
+ hci_dev_unlock(hdev);
return;
}
@@ -1860,6 +1880,9 @@
hci_conn_put(conn);
} else
hci_encrypt_cfm(conn, ev->status, ev->encrypt);
+
+ if (test_bit(HCI_MGMT, &hdev->flags))
+ mgmt_encrypt_change(hdev->id, &conn->dst, ev->status);
}
hci_dev_unlock(hdev);
diff --git a/net/bluetooth/l2cap_core.c b/net/bluetooth/l2cap_core.c
index d63dd1a..4c50713 100644
--- a/net/bluetooth/l2cap_core.c
+++ b/net/bluetooth/l2cap_core.c
@@ -3749,9 +3749,9 @@
/* Initialize rfc in case no rfc option is received */
rfc.mode = pi->mode;
- rfc.retrans_timeout = L2CAP_DEFAULT_RETRANS_TO;
- rfc.monitor_timeout = L2CAP_DEFAULT_MONITOR_TO;
- rfc.max_pdu_size = L2CAP_DEFAULT_MAX_PDU_SIZE;
+ rfc.retrans_timeout = cpu_to_le16(L2CAP_DEFAULT_RETRANS_TO);
+ rfc.monitor_timeout = cpu_to_le16(L2CAP_DEFAULT_MONITOR_TO);
+ rfc.max_pdu_size = cpu_to_le16(L2CAP_DEFAULT_MAX_PDU_SIZE);
while (len >= L2CAP_CONF_OPT_SIZE) {
len -= l2cap_get_conf_opt(&rsp, &type, &olen, &val);
@@ -3849,9 +3849,9 @@
/* Initialize rfc in case no rfc option is received */
rfc.mode = pi->mode;
- rfc.retrans_timeout = L2CAP_DEFAULT_RETRANS_TO;
- rfc.monitor_timeout = L2CAP_DEFAULT_MONITOR_TO;
- rfc.max_pdu_size = L2CAP_DEFAULT_MAX_PDU_SIZE;
+ rfc.retrans_timeout = cpu_to_le16(L2CAP_DEFAULT_RETRANS_TO);
+ rfc.monitor_timeout = cpu_to_le16(L2CAP_DEFAULT_MONITOR_TO);
+ rfc.max_pdu_size = cpu_to_le16(L2CAP_DEFAULT_MAX_PDU_SIZE);
if ((pi->mode != L2CAP_MODE_ERTM) && (pi->mode != L2CAP_MODE_STREAMING))
return;
@@ -5494,6 +5494,7 @@
/* TODO MM/PK - What to do if connection is LOCAL_BUSY? */
if (l2cap_pi(sk)->ampchan == chan) {
l2cap_pi(sk)->ampchan = NULL;
+ l2cap_pi(sk)->ampcon = NULL;
l2cap_amp_move_init(sk);
}
bh_unlock_sock(sk);
diff --git a/net/bluetooth/mgmt.c b/net/bluetooth/mgmt.c
index 0e7ff51..b413a9c 100644
--- a/net/bluetooth/mgmt.c
+++ b/net/bluetooth/mgmt.c
@@ -41,8 +41,6 @@
};
struct disco_interleave {
- struct timer_list timer;
- struct timer_list le_timer;
u16 index;
enum scan_mode mode;
int int_phase;
@@ -208,7 +206,7 @@
hci_del_off_timer(hdev);
- hci_dev_lock(hdev);
+ hci_dev_lock_bh(hdev);
set_bit(HCI_MGMT, &hdev->flags);
@@ -237,7 +235,7 @@
memcpy(rp.name, hdev->dev_name, sizeof(hdev->dev_name));
- hci_dev_unlock(hdev);
+ hci_dev_unlock_bh(hdev);
hci_dev_put(hdev);
return cmd_complete(sk, index, MGMT_OP_READ_INFO, &rp, sizeof(rp));
@@ -377,7 +375,7 @@
if (!hdev)
return cmd_status(sk, index, MGMT_OP_SET_POWERED, ENODEV);
- hci_dev_lock(hdev);
+ hci_dev_lock_bh(hdev);
up = test_bit(HCI_UP, &hdev->flags);
if ((cp->val && up) || (!cp->val && !up)) {
@@ -404,7 +402,7 @@
err = 0;
failed:
- hci_dev_unlock(hdev);
+ hci_dev_unlock_bh(hdev);
hci_dev_put(hdev);
return err;
}
@@ -467,7 +465,7 @@
return cmd_status(sk, index, MGMT_OP_SET_LIMIT_DISCOVERABLE,
ENODEV);
- hci_dev_lock(hdev);
+ hci_dev_lock_bh(hdev);
if (!test_bit(HCI_UP, &hdev->flags)) {
err = cmd_status(sk, index, MGMT_OP_SET_LIMIT_DISCOVERABLE,
@@ -521,7 +519,7 @@
mgmt_pending_remove(cmd);
failed:
- hci_dev_unlock(hdev);
+ hci_dev_unlock_bh(hdev);
hci_dev_put(hdev);
return err;
@@ -547,7 +545,7 @@
if (!hdev)
return cmd_status(sk, index, MGMT_OP_SET_DISCOVERABLE, ENODEV);
- hci_dev_lock(hdev);
+ hci_dev_lock_bh(hdev);
if (!test_bit(HCI_UP, &hdev->flags)) {
err = cmd_status(sk, index, MGMT_OP_SET_DISCOVERABLE, ENETDOWN);
@@ -582,7 +580,7 @@
mgmt_pending_remove(cmd);
failed:
- hci_dev_unlock(hdev);
+ hci_dev_unlock_bh(hdev);
hci_dev_put(hdev);
return err;
@@ -608,7 +606,7 @@
if (!hdev)
return cmd_status(sk, index, MGMT_OP_SET_CONNECTABLE, ENODEV);
- hci_dev_lock(hdev);
+ hci_dev_lock_bh(hdev);
if (!test_bit(HCI_UP, &hdev->flags)) {
err = cmd_status(sk, index, MGMT_OP_SET_CONNECTABLE, ENETDOWN);
@@ -642,7 +640,7 @@
mgmt_pending_remove(cmd);
failed:
- hci_dev_unlock(hdev);
+ hci_dev_unlock_bh(hdev);
hci_dev_put(hdev);
return err;
@@ -703,7 +701,7 @@
if (!hdev)
return cmd_status(sk, index, MGMT_OP_SET_PAIRABLE, ENODEV);
- hci_dev_lock(hdev);
+ hci_dev_lock_bh(hdev);
if (cp->val)
set_bit(HCI_PAIRABLE, &hdev->flags);
@@ -719,7 +717,7 @@
err = mgmt_event(MGMT_EV_PAIRABLE, index, &ev, sizeof(ev), sk);
failed:
- hci_dev_unlock(hdev);
+ hci_dev_unlock_bh(hdev);
hci_dev_put(hdev);
return err;
@@ -887,7 +885,7 @@
if (!hdev)
return cmd_status(sk, index, MGMT_OP_ADD_UUID, ENODEV);
- hci_dev_lock(hdev);
+ hci_dev_lock_bh(hdev);
uuid = kmalloc(sizeof(*uuid), GFP_ATOMIC);
if (!uuid) {
@@ -911,7 +909,7 @@
err = cmd_complete(sk, index, MGMT_OP_ADD_UUID, NULL, 0);
failed:
- hci_dev_unlock(hdev);
+ hci_dev_unlock_bh(hdev);
hci_dev_put(hdev);
return err;
@@ -936,7 +934,7 @@
if (!hdev)
return cmd_status(sk, index, MGMT_OP_REMOVE_UUID, ENODEV);
- hci_dev_lock(hdev);
+ hci_dev_lock_bh(hdev);
if (memcmp(cp->uuid, bt_uuid_any, 16) == 0) {
err = hci_uuids_clear(hdev);
@@ -971,7 +969,7 @@
err = cmd_complete(sk, index, MGMT_OP_REMOVE_UUID, NULL, 0);
unlock:
- hci_dev_unlock(hdev);
+ hci_dev_unlock_bh(hdev);
hci_dev_put(hdev);
return err;
@@ -995,7 +993,7 @@
if (!hdev)
return cmd_status(sk, index, MGMT_OP_SET_DEV_CLASS, ENODEV);
- hci_dev_lock(hdev);
+ hci_dev_lock_bh(hdev);
hdev->major_class &= ~MGMT_MAJOR_CLASS_MASK;
hdev->major_class |= cp->major & MGMT_MAJOR_CLASS_MASK;
@@ -1006,7 +1004,7 @@
if (err == 0)
err = cmd_complete(sk, index, MGMT_OP_SET_DEV_CLASS, NULL, 0);
- hci_dev_unlock(hdev);
+ hci_dev_unlock_bh(hdev);
hci_dev_put(hdev);
return err;
@@ -1028,7 +1026,7 @@
if (!hdev)
return cmd_status(sk, index, MGMT_OP_SET_SERVICE_CACHE, ENODEV);
- hci_dev_lock(hdev);
+ hci_dev_lock_bh(hdev);
BT_DBG("hci%u enable %d", index, cp->enable);
@@ -1046,7 +1044,7 @@
err = cmd_complete(sk, index, MGMT_OP_SET_SERVICE_CACHE, NULL,
0);
- hci_dev_unlock(hdev);
+ hci_dev_unlock_bh(hdev);
hci_dev_put(hdev);
return err;
@@ -1080,7 +1078,7 @@
BT_DBG("hci%u debug_keys %u key_count %u", index, cp->debug_keys,
key_count);
- hci_dev_lock(hdev);
+ hci_dev_lock_bh(hdev);
hci_link_keys_clear(hdev);
@@ -1118,7 +1116,7 @@
err = cmd_complete(sk, index, MGMT_OP_LOAD_KEYS, NULL, 0);
- hci_dev_unlock(hdev);
+ hci_dev_unlock_bh(hdev);
hci_dev_put(hdev);
return err;
@@ -1140,7 +1138,7 @@
if (!hdev)
return cmd_status(sk, index, MGMT_OP_REMOVE_KEY, ENODEV);
- hci_dev_lock(hdev);
+ hci_dev_lock_bh(hdev);
err = hci_remove_link_key(hdev, &cp->bdaddr);
if (err < 0) {
@@ -1163,7 +1161,7 @@
}
unlock:
- hci_dev_unlock(hdev);
+ hci_dev_unlock_bh(hdev);
hci_dev_put(hdev);
return err;
@@ -1189,7 +1187,7 @@
if (!hdev)
return cmd_status(sk, index, MGMT_OP_DISCONNECT, ENODEV);
- hci_dev_lock(hdev);
+ hci_dev_lock_bh(hdev);
if (!test_bit(HCI_UP, &hdev->flags)) {
err = cmd_status(sk, index, MGMT_OP_DISCONNECT, ENETDOWN);
@@ -1225,7 +1223,7 @@
mgmt_pending_remove(cmd);
failed:
- hci_dev_unlock(hdev);
+ hci_dev_unlock_bh(hdev);
hci_dev_put(hdev);
return err;
@@ -1246,7 +1244,7 @@
if (!hdev)
return cmd_status(sk, index, MGMT_OP_GET_CONNECTIONS, ENODEV);
- hci_dev_lock(hdev);
+ hci_dev_lock_bh(hdev);
count = 0;
list_for_each(p, &hdev->conn_hash.list) {
@@ -1277,7 +1275,7 @@
unlock:
kfree(rp);
- hci_dev_unlock(hdev);
+ hci_dev_unlock_bh(hdev);
hci_dev_put(hdev);
return err;
}
@@ -1302,7 +1300,7 @@
if (!hdev)
return cmd_status(sk, index, MGMT_OP_PIN_CODE_REPLY, ENODEV);
- hci_dev_lock(hdev);
+ hci_dev_lock_bh(hdev);
if (!test_bit(HCI_UP, &hdev->flags)) {
err = cmd_status(sk, index, MGMT_OP_PIN_CODE_REPLY, ENETDOWN);
@@ -1324,12 +1322,70 @@
mgmt_pending_remove(cmd);
failed:
+ hci_dev_unlock_bh(hdev);
+ hci_dev_put(hdev);
+
+ return err;
+}
+
+static int encrypt_link(struct sock *sk, u16 index, unsigned char *data,
+ u16 len)
+{
+ struct hci_dev *hdev;
+ struct mgmt_cp_encrypt_link *cp;
+ struct hci_cp_set_conn_encrypt enc;
+ struct hci_conn *conn;
+ int err = 0;
+
+ BT_DBG("");
+
+ cp = (void *) data;
+
+ if (len != sizeof(*cp))
+ return cmd_status(sk, index, MGMT_OP_ENCRYPT_LINK, EINVAL);
+
+ hdev = hci_dev_get(index);
+ if (!hdev)
+ return cmd_status(sk, index, MGMT_OP_ENCRYPT_LINK, ENODEV);
+
+ hci_dev_lock(hdev);
+
+ if (!test_bit(HCI_UP, &hdev->flags)) {
+ err = cmd_status(sk, index, MGMT_OP_ENCRYPT_LINK, ENETDOWN);
+ goto failed;
+ }
+
+ conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK,
+ &cp->bdaddr);
+ if (!conn)
+ return cmd_status(sk, index, MGMT_OP_ENCRYPT_LINK, ENOTCONN);
+
+ if (test_and_set_bit(HCI_CONN_ENCRYPT_PEND, &conn->pend))
+ return cmd_status(sk, index, MGMT_OP_ENCRYPT_LINK, EINPROGRESS);
+
+ if (conn->link_mode & HCI_LM_AUTH) {
+ enc.handle = cpu_to_le16(conn->handle);
+ enc.encrypt = cp->enable;
+ err = hci_send_cmd(hdev,
+ HCI_OP_SET_CONN_ENCRYPT, sizeof(enc), &enc);
+ } else {
+ conn->auth_initiator = 1;
+ if (!test_and_set_bit(HCI_CONN_AUTH_PEND, &conn->pend)) {
+ struct hci_cp_auth_requested cp;
+ cp.handle = cpu_to_le16(conn->handle);
+ err = hci_send_cmd(conn->hdev,
+ HCI_OP_AUTH_REQUESTED, sizeof(cp), &cp);
+ }
+ }
+
+failed:
hci_dev_unlock(hdev);
hci_dev_put(hdev);
return err;
}
+
static int pin_code_neg_reply(struct sock *sk, u16 index, unsigned char *data,
u16 len)
{
@@ -1351,7 +1407,7 @@
return cmd_status(sk, index, MGMT_OP_PIN_CODE_NEG_REPLY,
ENODEV);
- hci_dev_lock(hdev);
+ hci_dev_lock_bh(hdev);
if (!test_bit(HCI_UP, &hdev->flags)) {
err = cmd_status(sk, index, MGMT_OP_PIN_CODE_NEG_REPLY,
@@ -1372,7 +1428,7 @@
mgmt_pending_remove(cmd);
failed:
- hci_dev_unlock(hdev);
+ hci_dev_unlock_bh(hdev);
hci_dev_put(hdev);
return err;
@@ -1395,14 +1451,14 @@
if (!hdev)
return cmd_status(sk, index, MGMT_OP_SET_IO_CAPABILITY, ENODEV);
- hci_dev_lock(hdev);
+ hci_dev_lock_bh(hdev);
hdev->io_capability = cp->io_capability;
BT_DBG("%s IO capability set to 0x%02x", hdev->name,
hdev->io_capability);
- hci_dev_unlock(hdev);
+ hci_dev_unlock_bh(hdev);
hci_dev_put(hdev);
return cmd_complete(sk, index, MGMT_OP_SET_IO_CAPABILITY, NULL, 0);
@@ -1507,12 +1563,19 @@
static void discovery_terminated(struct pending_cmd *cmd, void *data)
{
+ struct hci_dev *hdev;
struct mgmt_mode ev = {0};
- struct disco_interleave *ilp = cmd->param;
BT_DBG("");
- del_timer_sync(&ilp->le_timer);
- del_timer_sync(&ilp->timer);
+ hdev = hci_dev_get(cmd->index);
+ if (!hdev)
+ goto not_found;
+
+ del_timer_sync(&hdev->disc_le_timer);
+ del_timer_sync(&hdev->disc_timer);
+ hci_dev_put(hdev);
+
+not_found:
mgmt_event(MGMT_EV_DISCOVERING, cmd->index, &ev, sizeof(ev), NULL);
list_del(&cmd->list);
@@ -1542,7 +1605,7 @@
if (!hdev)
return cmd_status(sk, index, MGMT_OP_PAIR_DEVICE, ENODEV);
- hci_dev_lock(hdev);
+ hci_dev_lock_bh(hdev);
BT_DBG("SSP Cap is %d", cp->ssp_cap);
io_cap = cp->io_cap;
@@ -1597,7 +1660,7 @@
err = 0;
unlock:
- hci_dev_unlock(hdev);
+ hci_dev_unlock_bh(hdev);
hci_dev_put(hdev);
return err;
@@ -1627,7 +1690,7 @@
if (!hdev)
return cmd_status(sk, index, mgmt_op, ENODEV);
- hci_dev_lock(hdev);
+ hci_dev_lock_bh(hdev);
if (!test_bit(HCI_UP, &hdev->flags)) {
err = cmd_status(sk, index, mgmt_op, ENETDOWN);
@@ -1653,7 +1716,7 @@
mgmt_pending_remove(cmd);
done:
- hci_dev_unlock(hdev);
+ hci_dev_unlock_bh(hdev);
hci_dev_put(hdev);
return err;
@@ -1677,7 +1740,7 @@
if (!hdev)
return cmd_status(sk, index, MGMT_OP_RESOLVE_NAME, ENODEV);
- hci_dev_lock(hdev);
+ hci_dev_lock_bh(hdev);
cmd = mgmt_pending_add(sk, MGMT_OP_RESOLVE_NAME, index, data, len);
if (!cmd) {
@@ -1693,7 +1756,7 @@
mgmt_pending_remove(cmd);
failed:
- hci_dev_unlock(hdev);
+ hci_dev_unlock_bh(hdev);
hci_dev_put(hdev);
return err;
@@ -1718,7 +1781,7 @@
return cmd_status(sk, index, MGMT_OP_SET_CONNECTION_PARAMS,
ENODEV);
- hci_dev_lock(hdev);
+ hci_dev_lock_bh(hdev);
conn = hci_conn_hash_lookup_ba(hdev, LE_LINK, &cp->bdaddr);
if (!conn) {
@@ -1735,7 +1798,7 @@
err = cmd_status(sk, index, MGMT_OP_SET_CONNECTION_PARAMS, 0);
failed:
- hci_dev_unlock(hdev);
+ hci_dev_unlock_bh(hdev);
hci_dev_put(hdev);
return err;
@@ -1759,7 +1822,7 @@
if (!hdev)
return cmd_status(sk, index, MGMT_OP_SET_LOCAL_NAME, ENODEV);
- hci_dev_lock(hdev);
+ hci_dev_lock_bh(hdev);
cmd = mgmt_pending_add(sk, MGMT_OP_SET_LOCAL_NAME, index, data, len);
if (!cmd) {
@@ -1774,7 +1837,7 @@
mgmt_pending_remove(cmd);
failed:
- hci_dev_unlock(hdev);
+ hci_dev_unlock_bh(hdev);
hci_dev_put(hdev);
return err;
@@ -1793,10 +1856,12 @@
cmd_complete(cmd->sk, cmd->index, MGMT_OP_STOP_DISCOVERY,
NULL, 0);
if (cmd->opcode == MGMT_OP_STOP_DISCOVERY) {
- struct disco_interleave *ilp = cmd->param;
-
- del_timer_sync(&ilp->le_timer);
- del_timer_sync(&ilp->timer);
+ struct hci_dev *hdev = hci_dev_get(cmd->index);
+ if (hdev) {
+ del_timer_sync(&hdev->disc_le_timer);
+ del_timer_sync(&hdev->disc_timer);
+ hci_dev_put(hdev);
+ }
}
}
@@ -1825,9 +1890,6 @@
hdev = hci_dev_get(index);
- if (hdev)
- hci_dev_lock(hdev);
-
if (!hdev || !lmp_le_capable(hdev)) {
struct mgmt_mode cp = {0};
@@ -1848,8 +1910,8 @@
err = hci_send_cmd(hdev, HCI_OP_LE_SET_SCAN_ENABLE,
sizeof(le_cp), &le_cp);
- if (err >= 0) {
- mod_timer(&ilp->le_timer, jiffies +
+ if (err >= 0 && hdev) {
+ mod_timer(&hdev->disc_le_timer, jiffies +
msecs_to_jiffies(ilp->int_phase * 1000));
ilp->mode = SCAN_LE;
} else
@@ -1861,7 +1923,6 @@
discovery_terminated, NULL);
done:
- hci_dev_unlock(hdev);
hci_dev_put(hdev);
}
@@ -1873,11 +1934,11 @@
BT_DBG("hci%d", ilp->index);
- del_timer_sync(&ilp->le_timer);
hdev = hci_dev_get(ilp->index);
if (hdev) {
- hci_dev_lock(hdev);
+ hci_dev_lock_bh(hdev);
+ del_timer_sync(&hdev->disc_le_timer);
cmd = mgmt_pending_find(MGMT_OP_STOP_DISCOVERY, ilp->index);
@@ -1902,7 +1963,7 @@
mgmt_pending_remove(cmd);
}
- hci_dev_unlock(hdev);
+ hci_dev_unlock_bh(hdev);
hci_dev_put(hdev);
}
}
@@ -1919,7 +1980,7 @@
hdev = hci_dev_get(ilp->index);
if (hdev) {
- hci_dev_lock(hdev);
+ hci_dev_lock_bh(hdev);
cmd = mgmt_pending_find(MGMT_OP_STOP_DISCOVERY, ilp->index);
@@ -1938,7 +1999,7 @@
} else
ilp->mode = SCAN_IDLE;
- hci_dev_unlock(hdev);
+ hci_dev_unlock_bh(hdev);
hci_dev_put(hdev);
}
}
@@ -1956,7 +2017,7 @@
if (!hdev)
return cmd_status(sk, index, MGMT_OP_START_DISCOVERY, ENODEV);
- hci_dev_lock(hdev);
+ hci_dev_lock_bh(hdev);
cmd = mgmt_pending_add(sk, MGMT_OP_START_DISCOVERY, index, NULL, 0);
if (!cmd) {
@@ -2002,16 +2063,17 @@
cmd = mgmt_pending_find(MGMT_OP_STOP_DISCOVERY, index);
if (cmd) {
ilp = cmd->param;
- setup_timer(&ilp->le_timer, disco_le_to,
+ setup_timer(&hdev->disc_le_timer, disco_le_to,
(unsigned long) ilp);
- setup_timer(&ilp->timer, disco_to, (unsigned long) ilp);
- mod_timer(&ilp->timer,
+ setup_timer(&hdev->disc_timer, disco_to,
+ (unsigned long) ilp);
+ mod_timer(&hdev->disc_timer,
jiffies + msecs_to_jiffies(20000));
}
}
failed:
- hci_dev_unlock(hdev);
+ hci_dev_unlock_bh(hdev);
hci_dev_put(hdev);
return err;
@@ -2032,7 +2094,7 @@
if (!hdev)
return cmd_status(sk, index, MGMT_OP_STOP_DISCOVERY, ENODEV);
- hci_dev_lock(hdev);
+ hci_dev_lock_bh(hdev);
if (lmp_le_capable(hdev)) {
cmd = mgmt_pending_find(MGMT_OP_STOP_DISCOVERY, index);
@@ -2056,8 +2118,8 @@
if (ilp) {
ilp->mode = SCAN_IDLE;
- del_timer_sync(&ilp->le_timer);
- del_timer_sync(&ilp->timer);
+ del_timer_sync(&hdev->disc_le_timer);
+ del_timer_sync(&hdev->disc_timer);
}
if (err < 0 && cmd)
@@ -2066,7 +2128,7 @@
mgmt_event(MGMT_EV_DISCOVERING, index, &mode_cp, sizeof(mode_cp), NULL);
failed:
- hci_dev_unlock(hdev);
+ hci_dev_unlock_bh(hdev);
hci_dev_put(hdev);
if (err < 0)
@@ -2088,7 +2150,7 @@
return cmd_status(sk, index, MGMT_OP_READ_LOCAL_OOB_DATA,
ENODEV);
- hci_dev_lock(hdev);
+ hci_dev_lock_bh(hdev);
if (!test_bit(HCI_UP, &hdev->flags)) {
err = cmd_status(sk, index, MGMT_OP_READ_LOCAL_OOB_DATA,
@@ -2118,7 +2180,7 @@
mgmt_pending_remove(cmd);
unlock:
- hci_dev_unlock(hdev);
+ hci_dev_unlock_bh(hdev);
hci_dev_put(hdev);
return err;
@@ -2142,7 +2204,7 @@
return cmd_status(sk, index, MGMT_OP_ADD_REMOTE_OOB_DATA,
ENODEV);
- hci_dev_lock(hdev);
+ hci_dev_lock_bh(hdev);
err = hci_add_remote_oob_data(hdev, &cp->bdaddr, cp->hash,
cp->randomizer);
@@ -2152,7 +2214,7 @@
err = cmd_complete(sk, index, MGMT_OP_ADD_REMOTE_OOB_DATA, NULL,
0);
- hci_dev_unlock(hdev);
+ hci_dev_unlock_bh(hdev);
hci_dev_put(hdev);
return err;
@@ -2176,7 +2238,7 @@
return cmd_status(sk, index, MGMT_OP_REMOVE_REMOTE_OOB_DATA,
ENODEV);
- hci_dev_lock(hdev);
+ hci_dev_lock_bh(hdev);
err = hci_remove_remote_oob_data(hdev, &cp->bdaddr);
if (err < 0)
@@ -2186,7 +2248,7 @@
err = cmd_complete(sk, index, MGMT_OP_REMOVE_REMOTE_OOB_DATA,
NULL, 0);
- hci_dev_unlock(hdev);
+ hci_dev_unlock_bh(hdev);
hci_dev_put(hdev);
return err;
@@ -2317,6 +2379,9 @@
err = remove_remote_oob_data(sk, index, buf + sizeof(*hdr),
len);
break;
+ case MGMT_OP_ENCRYPT_LINK:
+ err = encrypt_link(sk, index, buf + sizeof(*hdr), len);
+ break;
default:
BT_DBG("Unknown op %u", opcode);
@@ -2704,9 +2769,7 @@
hdev = hci_dev_get(index);
if (hdev) {
- hci_dev_lock_bh(hdev);
update_eir(hdev);
- hci_dev_unlock_bh(hdev);
hci_dev_put(hdev);
}
@@ -2804,7 +2867,7 @@
hci_send_cmd(hdev, HCI_OP_INQUIRY,
sizeof(cp), &cp);
ilp->mode = SCAN_BR;
- del_timer_sync(&ilp->le_timer);
+ del_timer_sync(&hdev->disc_le_timer);
}
}
@@ -2828,3 +2891,17 @@
return mgmt_event(MGMT_EV_REMOTE_NAME, index, &ev, sizeof(ev), NULL);
}
+
+int mgmt_encrypt_change(u16 index, bdaddr_t *bdaddr, u8 status)
+{
+ struct mgmt_ev_encrypt_change ev;
+
+ BT_DBG("hci%u", index);
+
+ bacpy(&ev.bdaddr, bdaddr);
+ ev.status = status;
+
+ return mgmt_event(MGMT_EV_ENCRYPT_CHANGE, index, &ev, sizeof(ev),
+ NULL);
+}
+
diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c
index 1ac9443..584a7cd 100644
--- a/net/wireless/nl80211.c
+++ b/net/wireless/nl80211.c
@@ -92,7 +92,7 @@
[NL80211_ATTR_KEY_IDX] = { .type = NLA_U8 },
[NL80211_ATTR_KEY_CIPHER] = { .type = NLA_U32 },
[NL80211_ATTR_KEY_DEFAULT] = { .type = NLA_FLAG },
- [NL80211_ATTR_KEY_SEQ] = { .type = NLA_BINARY, .len = 8 },
+ [NL80211_ATTR_KEY_SEQ] = { .type = NLA_BINARY, .len = 16 },
[NL80211_ATTR_KEY_TYPE] = { .type = NLA_U32 },
[NL80211_ATTR_BEACON_INTERVAL] = { .type = NLA_U32 },
@@ -183,7 +183,7 @@
[NL80211_KEY_DATA] = { .type = NLA_BINARY, .len = WLAN_MAX_KEY_LEN },
[NL80211_KEY_IDX] = { .type = NLA_U8 },
[NL80211_KEY_CIPHER] = { .type = NLA_U32 },
- [NL80211_KEY_SEQ] = { .type = NLA_BINARY, .len = 8 },
+ [NL80211_KEY_SEQ] = { .type = NLA_BINARY, .len = 16 },
[NL80211_KEY_DEFAULT] = { .type = NLA_FLAG },
[NL80211_KEY_DEFAULT_MGMT] = { .type = NLA_FLAG },
[NL80211_KEY_TYPE] = { .type = NLA_U32 },
@@ -3878,7 +3878,8 @@
cipher == WLAN_CIPHER_SUITE_WEP104 ||
cipher == WLAN_CIPHER_SUITE_TKIP ||
cipher == WLAN_CIPHER_SUITE_CCMP ||
- cipher == WLAN_CIPHER_SUITE_AES_CMAC;
+ cipher == WLAN_CIPHER_SUITE_AES_CMAC ||
+ cipher == WLAN_CIPHER_SUITE_SMS4;
}
diff --git a/net/wireless/util.c b/net/wireless/util.c
index 4d7b83f..c00a511 100644
--- a/net/wireless/util.c
+++ b/net/wireless/util.c
@@ -199,6 +199,10 @@
if (params->key_len != WLAN_KEY_LEN_AES_CMAC)
return -EINVAL;
break;
+ case WLAN_CIPHER_SUITE_SMS4:
+ if (params->key_len != WLAN_KEY_LEN_WAPI_SMS4)
+ return -EINVAL;
+ break;
default:
/*
* We don't know anything about this algorithm,
diff --git a/sound/core/pcm_native.c b/sound/core/pcm_native.c
index 34712cb..6dd815d 100644
--- a/sound/core/pcm_native.c
+++ b/sound/core/pcm_native.c
@@ -27,6 +27,8 @@
#include <linux/dma-mapping.h>
#include <sound/core.h>
#include <sound/control.h>
+#include <sound/snd_compress_params.h>
+#include <sound/compress_offload.h>
#include <sound/info.h>
#include <sound/pcm.h>
#include <sound/pcm_params.h>
@@ -1519,6 +1521,21 @@
return result;
}
+static int snd_compressed_ioctl(struct snd_pcm_substream *substream,
+ unsigned int cmd, void __user *arg)
+{
+ struct snd_pcm_runtime *runtime;
+ int err = 0;
+
+ if (PCM_RUNTIME_CHECK(substream))
+ return -ENXIO;
+ runtime = substream->runtime;
+ if (runtime->status->state != SNDRV_PCM_STATE_OPEN)
+ return -EBADFD;
+ pr_err("%s called with cmd = %d\n", __func__, cmd);
+ err = substream->ops->ioctl(substream, cmd, arg);
+ return err;
+}
/*
* drop ioctl
*
@@ -2573,6 +2590,12 @@
snd_pcm_stream_unlock_irq(substream);
return res;
}
+ case SNDRV_COMPRESS_GET_CAPS:
+ case SNDRV_COMPRESS_GET_CODEC_CAPS:
+ case SNDRV_COMPRESS_SET_PARAMS:
+ case SNDRV_COMPRESS_GET_PARAMS:
+ case SNDRV_COMPRESS_TSTAMP:
+ return snd_compressed_ioctl(substream, cmd, arg);
}
snd_printd("unknown ioctl = 0x%x\n", cmd);
return -ENOTTY;
@@ -2745,7 +2768,7 @@
pcm_file = file->private_data;
- if (((cmd >> 8) & 0xff) != 'A')
+ if ((((cmd >> 8) & 0xff) != 'A') && (((cmd >> 8) & 0xff) != 'C'))
return -ENOTTY;
return snd_pcm_playback_ioctl1(file, pcm_file->substream, cmd,
diff --git a/sound/soc/codecs/wcd9310.c b/sound/soc/codecs/wcd9310.c
index 3b83532..ba59920 100644
--- a/sound/soc/codecs/wcd9310.c
+++ b/sound/soc/codecs/wcd9310.c
@@ -39,6 +39,8 @@
#define BITS_PER_REG 8
#define TABLA_RX_DAI_ID 1
#define TABLA_TX_DAI_ID 2
+#define TABLA_CFILT_FAST_MODE 0x00
+#define TABLA_CFILT_SLOW_MODE 0x40
#define TABLA_JACK_MASK (SND_JACK_HEADSET | SND_JACK_OC_HPHL | SND_JACK_OC_HPHR)
@@ -60,6 +62,7 @@
u16 mbhc_reg;
u16 int_rbias;
u16 ctl_reg;
+ u8 cfilt_sel;
};
/* Codec supports 2 IIR filters */
@@ -90,6 +93,7 @@
bool clock_active;
bool config_mode_active;
bool mbhc_polling_active;
+ bool fake_insert_context;
int buttons_pressed;
struct tabla_mbhc_calibration *calibration;
@@ -464,13 +468,6 @@
SOC_SINGLE_TLV("LINEOUT5 Volume", TABLA_A_RX_LINE_5_GAIN, 0, 12, 1,
line_gain),
- SOC_SINGLE("RX1 CHAIN INVERT Switch", TABLA_A_CDC_RX1_B6_CTL, 4, 1, 0),
- SOC_SINGLE("RX2 CHAIN INVERT Switch", TABLA_A_CDC_RX2_B6_CTL, 4, 1, 0),
- SOC_SINGLE("RX3 CHAIN INVERT Switch", TABLA_A_CDC_RX3_B6_CTL, 4, 1, 0),
- SOC_SINGLE("RX4 CHAIN INVERT Switch", TABLA_A_CDC_RX4_B6_CTL, 4, 1, 0),
- SOC_SINGLE("RX5 CHAIN INVERT Switch", TABLA_A_CDC_RX5_B6_CTL, 4, 1, 0),
- SOC_SINGLE("RX6 CHAIN INVERT Switch", TABLA_A_CDC_RX6_B6_CTL, 4, 1, 0),
-
SOC_SINGLE_TLV("HPHL Volume", TABLA_A_RX_HPH_L_GAIN, 0, 12, 1,
line_gain),
SOC_SINGLE_TLV("HPHR Volume", TABLA_A_RX_HPH_R_GAIN, 0, 12, 1,
@@ -617,6 +614,10 @@
"RX5", "RX6", "RX7"
};
+static const char *rx_dsm_text[] = {
+ "CIC_OUT", "DSM_INV"
+};
+
static const char *sb_tx1_mux_text[] = {
"ZERO", "RMIX1", "RMIX2", "RMIX3", "RMIX4", "RMIX5", "RMIX6", "RMIX7",
"DEC1"
@@ -734,6 +735,12 @@
static const struct soc_enum rx7_mix1_inp2_chain_enum =
SOC_ENUM_SINGLE(TABLA_A_CDC_CONN_RX7_B1_CTL, 4, 12, rx_mix1_text);
+static const struct soc_enum rx4_dsm_enum =
+ SOC_ENUM_SINGLE(TABLA_A_CDC_RX4_B6_CTL, 4, 2, rx_dsm_text);
+
+static const struct soc_enum rx6_dsm_enum =
+ SOC_ENUM_SINGLE(TABLA_A_CDC_RX6_B6_CTL, 4, 2, rx_dsm_text);
+
static const struct soc_enum sb_tx5_mux_enum =
SOC_ENUM_SINGLE(TABLA_A_CDC_CONN_TX_SB_B5_CTL, 0, 9, sb_tx5_mux_text);
@@ -835,6 +842,12 @@
static const struct snd_kcontrol_new rx7_mix1_inp2_mux =
SOC_DAPM_ENUM("RX7 MIX1 INP2 Mux", rx7_mix1_inp2_chain_enum);
+static const struct snd_kcontrol_new rx4_dsm_mux =
+ SOC_DAPM_ENUM("RX4 DSM MUX Mux", rx4_dsm_enum);
+
+static const struct snd_kcontrol_new rx6_dsm_mux =
+ SOC_DAPM_ENUM("RX6 DSM MUX Mux", rx6_dsm_enum);
+
static const struct snd_kcontrol_new sb_tx5_mux =
SOC_DAPM_ENUM("SLIM TX5 MUX Mux", sb_tx5_mux_enum);
@@ -897,24 +910,12 @@
static const struct snd_kcontrol_new hphl_switch[] = {
SOC_DAPM_SINGLE("Switch", TABLA_A_RX_HPH_L_DAC_CTL, 6, 1, 0)
};
-static const struct snd_kcontrol_new hphr_switch[] = {
- SOC_DAPM_SINGLE("Switch", TABLA_A_RX_HPH_R_DAC_CTL, 6, 1, 0)
-};
-static const struct snd_kcontrol_new lineout1_switch[] = {
- SOC_DAPM_SINGLE("Switch", TABLA_A_RX_LINE_1_DAC_CTL, 6, 1, 0)
-};
-static const struct snd_kcontrol_new lineout2_switch[] = {
- SOC_DAPM_SINGLE("Switch", TABLA_A_RX_LINE_2_DAC_CTL, 6, 1, 0)
-};
-static const struct snd_kcontrol_new lineout3_switch[] = {
- SOC_DAPM_SINGLE("Switch", TABLA_A_RX_LINE_3_DAC_CTL, 6, 1, 0)
-};
-static const struct snd_kcontrol_new lineout4_switch[] = {
- SOC_DAPM_SINGLE("Switch", TABLA_A_RX_LINE_4_DAC_CTL, 6, 1, 0)
-};
-static const struct snd_kcontrol_new lineout5_switch[] = {
- SOC_DAPM_SINGLE("Switch", TABLA_A_RX_LINE_5_DAC_CTL, 6, 1, 0)
-};
+
+static const struct snd_kcontrol_new lineout3_ground_switch =
+ SOC_DAPM_SINGLE("Switch", TABLA_A_RX_LINE_3_DAC_CTL, 6, 1, 0);
+
+static const struct snd_kcontrol_new lineout4_ground_switch =
+ SOC_DAPM_SINGLE("Switch", TABLA_A_RX_LINE_4_DAC_CTL, 6, 1, 0);
static void tabla_codec_enable_adc_block(struct snd_soc_codec *codec,
int enable)
@@ -1184,41 +1185,6 @@
return 0;
}
-static void tabla_codec_update_cfilt_usage(struct snd_soc_codec *codec,
- u8 cfilt_sel, int inc)
-{
- struct tabla_priv *tabla = snd_soc_codec_get_drvdata(codec);
- u32 *cfilt_cnt_ptr = NULL;
- u16 micb_cfilt_reg;
-
- switch (cfilt_sel) {
- case TABLA_CFILT1_SEL:
- cfilt_cnt_ptr = &tabla->cfilt1_cnt;
- micb_cfilt_reg = TABLA_A_MICB_CFILT_1_CTL;
- break;
- case TABLA_CFILT2_SEL:
- cfilt_cnt_ptr = &tabla->cfilt2_cnt;
- micb_cfilt_reg = TABLA_A_MICB_CFILT_2_CTL;
- break;
- case TABLA_CFILT3_SEL:
- cfilt_cnt_ptr = &tabla->cfilt3_cnt;
- micb_cfilt_reg = TABLA_A_MICB_CFILT_3_CTL;
- break;
- default:
- return; /* should not happen */
- }
-
- if (inc) {
- if (!(*cfilt_cnt_ptr)++)
- snd_soc_update_bits(codec, micb_cfilt_reg, 0x80, 0x80);
- } else {
- /* check if count not zero, decrement
- * then check if zero, go ahead disable cfilter
- */
- if ((*cfilt_cnt_ptr) && !--(*cfilt_cnt_ptr))
- snd_soc_update_bits(codec, micb_cfilt_reg, 0x80, 0);
- }
-}
static void tabla_codec_disable_button_presses(struct snd_soc_codec *codec)
{
@@ -1256,6 +1222,84 @@
}
}
+static void tabla_codec_switch_cfilt_mode(struct snd_soc_codec *codec,
+ int mode)
+{
+ struct tabla_priv *tabla = snd_soc_codec_get_drvdata(codec);
+ u8 reg_mode_val, cur_mode_val;
+ bool mbhc_was_polling = false;
+
+ if (mode)
+ reg_mode_val = TABLA_CFILT_FAST_MODE;
+ else
+ reg_mode_val = TABLA_CFILT_SLOW_MODE;
+
+ cur_mode_val = snd_soc_read(codec,
+ tabla->mbhc_bias_regs.cfilt_ctl) & 0x40;
+
+ if (cur_mode_val != reg_mode_val) {
+ if (tabla->mbhc_polling_active) {
+ tabla_codec_pause_hs_polling(codec);
+ mbhc_was_polling = true;
+ }
+ snd_soc_update_bits(codec,
+ tabla->mbhc_bias_regs.cfilt_ctl, 0x40, reg_mode_val);
+ if (mbhc_was_polling)
+ tabla_codec_start_hs_polling(codec);
+ pr_debug("%s: CFILT mode change (%x to %x)\n", __func__,
+ cur_mode_val, reg_mode_val);
+ } else {
+ pr_debug("%s: CFILT Value is already %x\n",
+ __func__, cur_mode_val);
+ }
+}
+
+static void tabla_codec_update_cfilt_usage(struct snd_soc_codec *codec,
+ u8 cfilt_sel, int inc)
+{
+ struct tabla_priv *tabla = snd_soc_codec_get_drvdata(codec);
+ u32 *cfilt_cnt_ptr = NULL;
+ u16 micb_cfilt_reg;
+
+ switch (cfilt_sel) {
+ case TABLA_CFILT1_SEL:
+ cfilt_cnt_ptr = &tabla->cfilt1_cnt;
+ micb_cfilt_reg = TABLA_A_MICB_CFILT_1_CTL;
+ break;
+ case TABLA_CFILT2_SEL:
+ cfilt_cnt_ptr = &tabla->cfilt2_cnt;
+ micb_cfilt_reg = TABLA_A_MICB_CFILT_2_CTL;
+ break;
+ case TABLA_CFILT3_SEL:
+ cfilt_cnt_ptr = &tabla->cfilt3_cnt;
+ micb_cfilt_reg = TABLA_A_MICB_CFILT_3_CTL;
+ break;
+ default:
+ return; /* should not happen */
+ }
+
+ if (inc) {
+ if (!(*cfilt_cnt_ptr)++) {
+ /* Switch CFILT to slow mode if MBHC CFILT being used */
+ if (cfilt_sel == tabla->mbhc_bias_regs.cfilt_sel)
+ tabla_codec_switch_cfilt_mode(codec, 0);
+
+ snd_soc_update_bits(codec, micb_cfilt_reg, 0x80, 0x80);
+ }
+ } else {
+ /* check if count not zero, decrement
+ * then check if zero, go ahead disable cfilter
+ */
+ if ((*cfilt_cnt_ptr) && !--(*cfilt_cnt_ptr)) {
+ snd_soc_update_bits(codec, micb_cfilt_reg, 0x80, 0);
+
+ /* Switch CFILT to fast mode if MBHC CFILT being used */
+ if (cfilt_sel == tabla->mbhc_bias_regs.cfilt_sel)
+ tabla_codec_switch_cfilt_mode(codec, 1);
+ }
+ }
+}
+
static int tabla_find_k_value(unsigned int ldoh_v, unsigned int cfilt_mv)
{
int rc = -EINVAL;
@@ -1309,10 +1353,13 @@
{
struct tabla_priv *tabla = snd_soc_codec_get_drvdata(codec);
int cfilt_k_val;
+ bool mbhc_was_polling = false;
switch (vddio_switch) {
case 1:
if (tabla->mbhc_polling_active) {
+
+ tabla_codec_pause_hs_polling(codec);
/* Enable Mic Bias switch to VDDIO */
tabla->cfilt_k_value = snd_soc_read(codec,
tabla->mbhc_bias_regs.cfilt_val);
@@ -1326,6 +1373,7 @@
tabla->mbhc_bias_regs.mbhc_reg, 0x80, 0x80);
snd_soc_update_bits(codec,
tabla->mbhc_bias_regs.mbhc_reg, 0x10, 0x00);
+ tabla_codec_start_hs_polling(codec);
tabla->mbhc_micbias_switched = true;
pr_debug("%s: Enabled MBHC Mic bias to VDDIO Switch\n",
@@ -1335,6 +1383,10 @@
case 0:
if (tabla->mbhc_micbias_switched) {
+ if (tabla->mbhc_polling_active) {
+ tabla_codec_pause_hs_polling(codec);
+ mbhc_was_polling = true;
+ }
/* Disable Mic Bias switch to VDDIO */
if (tabla->cfilt_k_value != 0)
snd_soc_update_bits(codec,
@@ -1345,6 +1397,9 @@
snd_soc_update_bits(codec,
tabla->mbhc_bias_regs.mbhc_reg, 0x10, 0x00);
+ if (mbhc_was_polling)
+ tabla_codec_start_hs_polling(codec);
+
tabla->mbhc_micbias_switched = false;
pr_debug("%s: Disabled MBHC Mic bias to VDDIO Switch\n",
__func__);
@@ -1470,6 +1525,8 @@
{
struct snd_soc_codec *codec = w->codec;
+ pr_debug("%s %d %s\n", __func__, event, w->name);
+
switch (event) {
case SND_SOC_DAPM_PRE_PMU:
snd_soc_update_bits(codec, TABLA_A_CDC_CLK_RX_RESET_CTL,
@@ -1528,6 +1585,23 @@
}
return 0;
}
+static int tabla_hphr_dac_event(struct snd_soc_dapm_widget *w,
+ struct snd_kcontrol *kcontrol, int event)
+{
+ struct snd_soc_codec *codec = w->codec;
+
+ pr_debug("%s %s %d\n", __func__, w->name, event);
+
+ switch (event) {
+ case SND_SOC_DAPM_PRE_PMU:
+ snd_soc_update_bits(codec, w->reg, 0x40, 0x40);
+ break;
+ case SND_SOC_DAPM_POST_PMD:
+ snd_soc_update_bits(codec, w->reg, 0x40, 0x00);
+ break;
+ }
+ return 0;
+}
static void hphocp_off_report(struct tabla_priv *tabla,
u32 jack_status, int irq)
@@ -1645,6 +1719,8 @@
pr_err("%s: Invalid MIC BIAS for MBHC\n", __func__);
}
+ micbias_regs->cfilt_sel = cfilt;
+
switch (cfilt) {
case TABLA_CFILT1_SEL:
micbias_regs->cfilt_val = TABLA_A_MICB_CFILT_1_VAL;
@@ -1667,6 +1743,25 @@
0, NULL, 0),
};
+static int tabla_lineout_dac_event(struct snd_soc_dapm_widget *w,
+ struct snd_kcontrol *kcontrol, int event)
+{
+ struct snd_soc_codec *codec = w->codec;
+
+ pr_debug("%s %s %d\n", __func__, w->name, event);
+
+ switch (event) {
+ case SND_SOC_DAPM_PRE_PMU:
+ snd_soc_update_bits(codec, w->reg, 0x40, 0x40);
+ break;
+
+ case SND_SOC_DAPM_POST_PMD:
+ snd_soc_update_bits(codec, w->reg, 0x40, 0x00);
+ break;
+ }
+ return 0;
+}
+
static const struct snd_soc_dapm_widget tabla_dapm_widgets[] = {
/*RX stuff */
SND_SOC_DAPM_OUTPUT("EAR"),
@@ -1692,8 +1787,10 @@
SND_SOC_DAPM_PGA_E("HPHR", TABLA_A_RX_HPH_CNP_EN, 4, 0, NULL, 0,
tabla_hph_pa_event, SND_SOC_DAPM_PRE_PMU |
SND_SOC_DAPM_POST_PMD),
- SND_SOC_DAPM_MIXER("HPHR DAC", TABLA_A_RX_HPH_R_DAC_CTL, 7, 0,
- hphr_switch, ARRAY_SIZE(hphr_switch)),
+
+ SND_SOC_DAPM_DAC_E("HPHR DAC", NULL, TABLA_A_RX_HPH_R_DAC_CTL, 7, 0,
+ tabla_hphr_dac_event,
+ SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
/* Speaker */
SND_SOC_DAPM_OUTPUT("LINEOUT1"),
@@ -1718,16 +1815,25 @@
tabla_codec_enable_lineout, SND_SOC_DAPM_PRE_PMU |
SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
- SND_SOC_DAPM_MIXER("LINEOUT1 DAC", TABLA_A_RX_LINE_1_DAC_CTL, 7, 0,
- lineout1_switch, ARRAY_SIZE(lineout1_switch)),
- SND_SOC_DAPM_MIXER("LINEOUT2 DAC", TABLA_A_RX_LINE_2_DAC_CTL, 7, 0,
- lineout2_switch, ARRAY_SIZE(lineout2_switch)),
- SND_SOC_DAPM_MIXER("LINEOUT3 DAC", TABLA_A_RX_LINE_3_DAC_CTL, 7, 0,
- lineout3_switch, ARRAY_SIZE(lineout3_switch)),
- SND_SOC_DAPM_MIXER("LINEOUT4 DAC", TABLA_A_RX_LINE_4_DAC_CTL, 7, 0,
- lineout4_switch, ARRAY_SIZE(lineout4_switch)),
- SND_SOC_DAPM_MIXER("LINEOUT5 DAC", TABLA_A_RX_LINE_5_DAC_CTL, 7, 0,
- lineout5_switch, ARRAY_SIZE(lineout5_switch)),
+ SND_SOC_DAPM_DAC_E("LINEOUT1 DAC", NULL, TABLA_A_RX_LINE_1_DAC_CTL, 7, 0
+ , tabla_lineout_dac_event,
+ SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
+ SND_SOC_DAPM_DAC_E("LINEOUT2 DAC", NULL, TABLA_A_RX_LINE_2_DAC_CTL, 7, 0
+ , tabla_lineout_dac_event,
+ SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
+ SND_SOC_DAPM_DAC_E("LINEOUT3 DAC", NULL, TABLA_A_RX_LINE_3_DAC_CTL, 7, 0
+ , tabla_lineout_dac_event,
+ SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
+ SND_SOC_DAPM_SWITCH("LINEOUT3 DAC GROUND", SND_SOC_NOPM, 0, 0,
+ &lineout3_ground_switch),
+ SND_SOC_DAPM_DAC_E("LINEOUT4 DAC", NULL, TABLA_A_RX_LINE_4_DAC_CTL, 7, 0
+ , tabla_lineout_dac_event,
+ SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
+ SND_SOC_DAPM_SWITCH("LINEOUT4 DAC GROUND", SND_SOC_NOPM, 0, 0,
+ &lineout4_ground_switch),
+ SND_SOC_DAPM_DAC_E("LINEOUT5 DAC", NULL, TABLA_A_RX_LINE_5_DAC_CTL, 7, 0
+ , tabla_lineout_dac_event,
+ SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
SND_SOC_DAPM_MIXER_E("RX1 MIX1", TABLA_A_CDC_CLK_RX_B1_CTL, 0, 0, NULL,
0, tabla_codec_reset_interpolator, SND_SOC_DAPM_PRE_PMU),
@@ -1744,6 +1850,15 @@
SND_SOC_DAPM_MIXER_E("RX7 MIX1", TABLA_A_CDC_CLK_RX_B1_CTL, 6, 0, NULL,
0, tabla_codec_reset_interpolator, SND_SOC_DAPM_PRE_PMU),
+
+ SND_SOC_DAPM_MUX_E("RX4 DSM MUX", TABLA_A_CDC_CLK_RX_B1_CTL, 3, 0,
+ &rx4_dsm_mux, tabla_codec_reset_interpolator,
+ SND_SOC_DAPM_PRE_PMU),
+
+ SND_SOC_DAPM_MUX_E("RX6 DSM MUX", TABLA_A_CDC_CLK_RX_B1_CTL, 5, 0,
+ &rx6_dsm_mux, tabla_codec_reset_interpolator,
+ SND_SOC_DAPM_PRE_PMU),
+
SND_SOC_DAPM_MIXER("RX1 CHAIN", TABLA_A_CDC_RX1_B6_CTL, 5, 0, NULL, 0),
SND_SOC_DAPM_MIXER("RX2 CHAIN", TABLA_A_CDC_RX2_B6_CTL, 5, 0, NULL, 0),
@@ -2022,7 +2137,7 @@
{"DAC1", "Switch", "RX1 CHAIN"},
{"HPHL DAC", "Switch", "RX1 CHAIN"},
- {"HPHR DAC", "Switch", "RX2 CHAIN"},
+ {"HPHR DAC", NULL, "RX2 CHAIN"},
{"LINEOUT1", NULL, "LINEOUT1 PA"},
{"LINEOUT2", NULL, "LINEOUT2 PA"},
@@ -2036,21 +2151,20 @@
{"LINEOUT4 PA", NULL, "LINEOUT4 DAC"},
{"LINEOUT5 PA", NULL, "LINEOUT5 DAC"},
+ {"LINEOUT1 DAC", NULL, "RX3 MIX1"},
+ {"LINEOUT5 DAC", NULL, "RX7 MIX1"},
+
{"RX1 CHAIN", NULL, "RX1 MIX1"},
{"RX2 CHAIN", NULL, "RX2 MIX1"},
{"RX1 CHAIN", NULL, "ANC"},
{"RX2 CHAIN", NULL, "ANC"},
- {"LINEOUT1 DAC", "Switch", "RX3 MIX1"},
- {"LINEOUT2 DAC", "Switch", "RX4 MIX1"},
- {"LINEOUT3 DAC", "Switch", "RX3 MIX1"},
- {"LINEOUT4 DAC", "Switch", "RX4 MIX1"},
- {"LINEOUT5 DAC", "Switch", "RX7 MIX1"},
{"CP", NULL, "RX_BIAS"},
{"LINEOUT1 DAC", NULL, "RX_BIAS"},
{"LINEOUT2 DAC", NULL, "RX_BIAS"},
{"LINEOUT3 DAC", NULL, "RX_BIAS"},
{"LINEOUT4 DAC", NULL, "RX_BIAS"},
+ {"LINEOUT5 DAC", NULL, "RX_BIAS"},
{"RX1 MIX1", NULL, "RX1 MIX1 INP1"},
{"RX1 MIX1", NULL, "RX1 MIX1 INP2"},
@@ -2200,6 +2314,41 @@
{"MIC BIAS4 External", NULL, "LDO_H"},
};
+static const struct snd_soc_dapm_route tabla_1_x_lineout_2_to_4_map[] = {
+
+ {"RX4 DSM MUX", "DSM_INV", "RX3 MIX1"},
+ {"RX4 DSM MUX", "CIC_OUT", "RX4 MIX1"},
+
+ {"LINEOUT2 DAC", NULL, "RX4 DSM MUX"},
+
+ {"LINEOUT3 DAC", NULL, "RX5 MIX1"},
+ {"LINEOUT3 DAC GROUND", "Switch", "RX3 MIX1"},
+ {"LINEOUT3 DAC", NULL, "LINEOUT3 DAC GROUND"},
+
+ {"RX6 DSM MUX", "DSM_INV", "RX5 MIX1"},
+ {"RX6 DSM MUX", "CIC_OUT", "RX6 MIX1"},
+
+ {"LINEOUT4 DAC", NULL, "RX6 DSM MUX"},
+ {"LINEOUT4 DAC GROUND", "Switch", "RX4 DSM MUX"},
+ {"LINEOUT4 DAC", NULL, "LINEOUT4 DAC GROUND"},
+};
+
+
+static const struct snd_soc_dapm_route tabla_2_x_lineout_2_to_4_map[] = {
+
+ {"RX4 DSM MUX", "DSM_INV", "RX3 MIX1"},
+ {"RX4 DSM MUX", "CIC_OUT", "RX4 MIX1"},
+
+ {"LINEOUT3 DAC", NULL, "RX4 DSM MUX"},
+
+ {"LINEOUT2 DAC", NULL, "RX5 MIX1"},
+
+ {"RX6 DSM MUX", "DSM_INV", "RX5 MIX1"},
+ {"RX6 DSM MUX", "CIC_OUT", "RX6 MIX1"},
+
+ {"LINEOUT4 DAC", NULL, "RX6 DSM MUX"},
+};
+
static int tabla_readable(struct snd_soc_codec *ssc, unsigned int reg)
{
return tabla_reg_readable[reg];
@@ -2227,12 +2376,10 @@
unsigned int value)
{
int ret;
- pr_debug("%s: write reg %x val %x\n", __func__, reg, value);
BUG_ON(reg > TABLA_MAX_REGISTER);
if (!tabla_volatile(codec, reg)) {
- pr_debug("writing to cache\n");
ret = snd_soc_cache_write(codec, reg, value);
if (ret != 0)
dev_err(codec->dev, "Cache write to %x failed: %d\n",
@@ -2251,10 +2398,8 @@
if (!tabla_volatile(codec, reg) && tabla_readable(codec, reg) &&
reg < codec->driver->reg_cache_size) {
- pr_debug("reading from cache\n");
ret = snd_soc_cache_read(codec, reg, &val);
if (ret >= 0) {
- pr_debug("register %x, value %x\n", reg, val);
return val;
} else
dev_err(codec->dev, "Cache read from %x failed: %d\n",
@@ -2262,7 +2407,6 @@
}
val = tabla_reg_read(codec->control_data, reg);
- pr_debug("%s: read reg %x val %x\n", __func__, reg, val);
return val;
}
@@ -2769,6 +2913,7 @@
struct tabla_priv *tabla = snd_soc_codec_get_drvdata(codec);
struct tabla_mbhc_calibration *calibration = tabla->calibration;
short bias_value;
+ u8 cfilt_mode;
if (!calibration) {
pr_err("Error, no tabla calibration\n");
@@ -2787,9 +2932,11 @@
snd_soc_update_bits(codec, TABLA_A_TX_COM_BIAS, 0xE0, 0xE0);
-
- snd_soc_update_bits(codec,
- tabla->mbhc_bias_regs.cfilt_ctl, 0x70, 0x00);
+ /* Make sure CFILT is in fast mode, save current mode */
+ cfilt_mode = snd_soc_read(codec,
+ tabla->mbhc_bias_regs.cfilt_ctl);
+ snd_soc_update_bits(codec, tabla->mbhc_bias_regs.cfilt_ctl,
+ 0x70, 0x00);
snd_soc_update_bits(codec,
tabla->mbhc_bias_regs.ctl_reg, 0x1F, 0x16);
@@ -2812,7 +2959,7 @@
bias_value = tabla_codec_measure_micbias_voltage(codec, 0);
snd_soc_update_bits(codec,
- tabla->mbhc_bias_regs.cfilt_ctl, 0x40, 0x40);
+ tabla->mbhc_bias_regs.cfilt_ctl, 0x40, cfilt_mode);
snd_soc_update_bits(codec, TABLA_A_MBHC_HPH, 0x13, 0x00);
return bias_value;
@@ -2824,6 +2971,7 @@
struct tabla_priv *tabla = snd_soc_codec_get_drvdata(codec);
struct tabla_mbhc_calibration *calibration = tabla->calibration;
int central_bias_enabled = 0;
+ u8 wg_time;
if (!calibration) {
pr_err("Error, no tabla calibration\n");
@@ -2840,20 +2988,28 @@
0x81, 0x01);
snd_soc_update_bits(codec, tabla->mbhc_bias_regs.mbhc_reg,
0x90, 0x00);
+ wg_time = snd_soc_read(codec, TABLA_A_RX_HPH_CNP_WG_TIME) ;
+ wg_time += 1;
/* Enable HPH Schmitt Trigger */
- snd_soc_update_bits(codec, TABLA_A_MBHC_HPH, 0x13, 0x13);
+ snd_soc_update_bits(codec, TABLA_A_MBHC_HPH, 0x11, 0x11);
snd_soc_update_bits(codec, TABLA_A_MBHC_HPH, 0x0C,
calibration->hph_current << 2);
- /* Turn off HPH PAs during insertion detection to avoid false
- * insertion interrupts
+ /* Turn off HPH PAs and DAC's during insertion detection to
+ * avoid false insertion interrupts
*/
if (tabla->mbhc_micbias_switched)
tabla_codec_switch_micbias(codec, 0);
snd_soc_update_bits(codec, TABLA_A_RX_HPH_CNP_EN, 0x30, 0x00);
+ snd_soc_update_bits(codec, TABLA_A_RX_HPH_L_DAC_CTL,
+ 0xC0, 0x00);
+ snd_soc_update_bits(codec, TABLA_A_RX_HPH_R_DAC_CTL,
+ 0xC0, 0x00);
+ usleep_range(wg_time * 1000, wg_time * 1000);
/* setup for insetion detection */
+ snd_soc_update_bits(codec, TABLA_A_MBHC_HPH, 0x02, 0x02);
snd_soc_update_bits(codec, TABLA_A_CDC_MBHC_INT_CTL, 0x2, 0);
} else {
/* Make sure the HPH schmitt trigger is OFF */
@@ -2953,6 +3109,10 @@
tabla->calibration = calibration;
tabla_get_mbhc_micbias_regs(codec, &tabla->mbhc_bias_regs);
+ /* Put CFILT in fast mode by default */
+ snd_soc_update_bits(codec, tabla->mbhc_bias_regs.cfilt_ctl,
+ 0x40, TABLA_CFILT_FAST_MODE);
+
INIT_DELAYED_WORK(&tabla->btn0_dwork, btn0_lpress_fn);
INIT_WORK(&tabla->hphlocp_work, hphlocp_off_report);
INIT_WORK(&tabla->hphrocp_work, hphrocp_off_report);
@@ -3162,6 +3322,16 @@
0x90, 0x00);
snd_soc_update_bits(codec, TABLA_A_MBHC_HPH, 0x13, 0x00);
+ if (priv->fake_insert_context) {
+ pr_debug("%s: fake context interrupt, reset insertion\n",
+ __func__);
+ priv->fake_insert_context = false;
+ tabla_codec_shutdown_hs_polling(codec);
+ tabla_codec_enable_hs_detect(codec, 1);
+ return IRQ_HANDLED;
+ }
+
+
ldo_h_on = snd_soc_read(codec, TABLA_A_LDO_H_MODE_1) & 0x80;
micb_cfilt_on = snd_soc_read(codec,
priv->mbhc_bias_regs.cfilt_ctl) & 0x80;
@@ -3204,7 +3374,25 @@
if (mic_voltage > threshold_fake_insert) {
pr_debug("%s: Fake insertion interrupt, mic_voltage = %x\n",
__func__, mic_voltage);
- tabla_codec_enable_hs_detect(codec, 1);
+
+ /* Disable HPH trigger and enable MIC line trigger */
+ snd_soc_update_bits(codec, TABLA_A_MBHC_HPH, 0x12, 0x00);
+
+ snd_soc_update_bits(codec, priv->mbhc_bias_regs.mbhc_reg, 0x60,
+ priv->calibration->mic_current << 5);
+ snd_soc_update_bits(codec, priv->mbhc_bias_regs.mbhc_reg,
+ 0x80, 0x80);
+ usleep_range(priv->calibration->mic_pid,
+ priv->calibration->mic_pid);
+ snd_soc_update_bits(codec, priv->mbhc_bias_regs.mbhc_reg,
+ 0x10, 0x10);
+
+ /* Setup for insertion detection */
+ snd_soc_update_bits(codec, TABLA_A_CDC_MBHC_INT_CTL, 0x2, 0);
+ priv->fake_insert_context = true;
+ tabla_enable_irq(codec->control_data, TABLA_IRQ_MBHC_INSERTION);
+ snd_soc_update_bits(codec, TABLA_A_CDC_MBHC_INT_CTL, 0x1, 0x1);
+
} else if (mic_voltage < threshold_no_mic) {
pr_debug("%s: Headphone Detected, mic_voltage = %x\n",
__func__, mic_voltage);
@@ -3548,6 +3736,7 @@
struct snd_soc_dapm_context *dapm = &codec->dapm;
int ret = 0;
int i;
+ u8 tabla_version;
codec->control_data = dev_get_drvdata(codec->dev->parent);
control = codec->control_data;
@@ -3571,6 +3760,7 @@
tabla->clock_active = false;
tabla->config_mode_active = false;
tabla->mbhc_polling_active = false;
+ tabla->fake_insert_context = false;
tabla->no_mic_headset_override = false;
tabla->codec = codec;
tabla->pdata = dev_get_platdata(codec->dev->parent);
@@ -3600,6 +3790,27 @@
ARRAY_SIZE(audio_i2s_map));
}
snd_soc_dapm_add_routes(dapm, audio_map, ARRAY_SIZE(audio_map));
+
+ tabla_version = snd_soc_read(codec, TABLA_A_CHIP_VERSION);
+ pr_info("%s : Tabla version reg 0x%2x\n", __func__, (u32)tabla_version);
+
+ tabla_version &= 0x1F;
+ pr_info("%s : Tabla version %u\n", __func__, (u32)tabla_version);
+
+ if ((tabla_version == TABLA_VERSION_1_0) ||
+ (tabla_version == TABLA_VERSION_1_1)) {
+ snd_soc_dapm_add_routes(dapm, tabla_1_x_lineout_2_to_4_map,
+ ARRAY_SIZE(tabla_1_x_lineout_2_to_4_map));
+
+ } else if (tabla_version == TABLA_VERSION_2_0) {
+ snd_soc_dapm_add_routes(dapm, tabla_2_x_lineout_2_to_4_map,
+ ARRAY_SIZE(tabla_2_x_lineout_2_to_4_map));
+ } else {
+ pr_err("%s : ERROR. Unsupported Tabla version 0x%2x\n",
+ __func__, (u32)tabla_version);
+ goto err_pdata;
+ }
+
snd_soc_dapm_sync(dapm);
ret = tabla_request_irq(codec->control_data, TABLA_IRQ_MBHC_INSERTION,
diff --git a/sound/soc/codecs/wcd9310.h b/sound/soc/codecs/wcd9310.h
index 8c6555b..32fc48f 100644
--- a/sound/soc/codecs/wcd9310.h
+++ b/sound/soc/codecs/wcd9310.h
@@ -12,6 +12,10 @@
#include <sound/soc.h>
+#define TABLA_VERSION_1_0 0
+#define TABLA_VERSION_1_1 1
+#define TABLA_VERSION_2_0 2
+
#define TABLA_NUM_REGISTERS 0x400
#define TABLA_MAX_REGISTER (TABLA_NUM_REGISTERS-1)
#define TABLA_CACHE_SIZE TABLA_NUM_REGISTERS
diff --git a/sound/soc/msm/Kconfig b/sound/soc/msm/Kconfig
index ced46de..9e0549b 100644
--- a/sound/soc/msm/Kconfig
+++ b/sound/soc/msm/Kconfig
@@ -113,8 +113,8 @@
To add support for MSM QDSP6 Soc Audio.
config SND_SOC_MSM8960
- tristate "SoC Machine driver for MSM8960 boards"
- depends on ARCH_MSM8960
+ tristate "SoC Machine driver for MSM8960 and APQ8064 boards"
+ depends on ARCH_MSM8960 || ARCH_APQ8064
select SND_SOC_VOICE
select SND_SOC_QDSP6
select SND_SOC_MSM_STUB
@@ -122,7 +122,7 @@
select SND_SOC_MSM_HOSTLESS_PCM
default n
help
- To add support for SoC audio on MSM8960 boards
+ To add support for SoC audio on MSM8960 and APQ8064 boards
config SND_SOC_MSM8660_APQ
tristate "Soc Machine driver for APQ8060 WM8903 codec"
diff --git a/sound/soc/msm/Makefile b/sound/soc/msm/Makefile
index 568fd40..3b257a6 100644
--- a/sound/soc/msm/Makefile
+++ b/sound/soc/msm/Makefile
@@ -56,7 +56,7 @@
obj-$(CONFIG_SND_SOC_MSM_QDSP6_INTF) += qdsp6/
-snd-soc-qdsp6-objs := msm-dai-q6.o msm-pcm-q6.o msm-pcm-routing.o msm-dai-fe.o
+snd-soc-qdsp6-objs := msm-dai-q6.o msm-pcm-q6.o msm-pcm-routing.o msm-dai-fe.o msm-compr-q6.o
obj-$(CONFIG_SND_SOC_VOICE) += msm-pcm-voice.o msm-pcm-voip.o
snd-soc-qdsp6-objs += msm-pcm-lpa.o msm-pcm-afe.o
obj-$(CONFIG_SND_SOC_QDSP6) += snd-soc-qdsp6.o
diff --git a/sound/soc/msm/msm-compr-q6.c b/sound/soc/msm/msm-compr-q6.c
new file mode 100644
index 0000000..cf6f1e7
--- /dev/null
+++ b/sound/soc/msm/msm-compr-q6.c
@@ -0,0 +1,567 @@
+/* Copyright (c) 2011, Code Aurora Forum. 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 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+
+#include <linux/init.h>
+#include <linux/err.h>
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/time.h>
+#include <linux/wait.h>
+#include <linux/platform_device.h>
+#include <linux/slab.h>
+#include <sound/core.h>
+#include <sound/soc.h>
+#include <sound/soc-dapm.h>
+#include <sound/pcm.h>
+#include <sound/initval.h>
+#include <sound/control.h>
+#include <asm/dma.h>
+#include <linux/dma-mapping.h>
+#include <linux/android_pmem.h>
+
+#include "msm-compr-q6.h"
+#include "msm-pcm-routing.h"
+
+static struct audio_locks the_locks;
+
+static struct snd_pcm_hardware msm_compr_hardware_playback = {
+ .info = (SNDRV_PCM_INFO_MMAP |
+ SNDRV_PCM_INFO_BLOCK_TRANSFER |
+ SNDRV_PCM_INFO_MMAP_VALID |
+ SNDRV_PCM_INFO_INTERLEAVED |
+ SNDRV_PCM_INFO_PAUSE | SNDRV_PCM_INFO_RESUME),
+ .formats = SNDRV_PCM_FMTBIT_S16_LE,
+ .rates = SNDRV_PCM_RATE_8000_48000,
+ .rate_min = 8000,
+ .rate_max = 48000,
+ .channels_min = 1,
+ .channels_max = 2,
+ .buffer_bytes_max = 1200 * 1024 * 2,
+ .period_bytes_min = 60 * 1024,
+ .period_bytes_max = 1200 * 1024,
+ .periods_min = 2,
+ .periods_max = 40,
+ .fifo_size = 0,
+};
+
+/* Conventional and unconventional sample rate supported */
+static unsigned int supported_sample_rates[] = {
+ 8000, 11025, 12000, 16000, 22050, 24000, 32000, 44100, 48000
+};
+
+static struct snd_pcm_hw_constraint_list constraints_sample_rates = {
+ .count = ARRAY_SIZE(supported_sample_rates),
+ .list = supported_sample_rates,
+ .mask = 0,
+};
+
+static void compr_event_handler(uint32_t opcode,
+ uint32_t token, uint32_t *payload, void *priv)
+{
+ struct compr_audio *compr = priv;
+ struct msm_audio *prtd = &compr->prtd;
+ struct snd_pcm_substream *substream = prtd->substream;
+ struct snd_pcm_runtime *runtime = substream->runtime;
+ struct audio_aio_write_param param;
+ struct audio_buffer *buf = NULL;
+ int i = 0;
+
+ pr_debug("%s opcode =%08x\n", __func__, opcode);
+ switch (opcode) {
+ case ASM_DATA_EVENT_WRITE_DONE: {
+ uint32_t *ptrmem = (uint32_t *)¶m;
+ pr_debug("ASM_DATA_EVENT_WRITE_DONE\n");
+ pr_debug("Buffer Consumed = 0x%08x\n", *ptrmem);
+ prtd->pcm_irq_pos += prtd->pcm_count;
+ if (atomic_read(&prtd->start))
+ snd_pcm_period_elapsed(substream);
+ atomic_inc(&prtd->out_count);
+ wake_up(&the_locks.write_wait);
+ if (!atomic_read(&prtd->start)) {
+ prtd->pending_buffer = 1;
+ break;
+ } else
+ prtd->pending_buffer = 0;
+
+ if (runtime->status->hw_ptr >= runtime->control->appl_ptr)
+ break;
+ buf = prtd->audio_client->port[IN].buf;
+ pr_debug("%s:writing %d bytes of buffer[%d] to dsp 2\n",
+ __func__, prtd->pcm_count, prtd->out_head);
+ pr_debug("%s:writing buffer[%d] from 0x%08x\n",
+ __func__, prtd->out_head,
+ ((unsigned int)buf[0].phys
+ + (prtd->out_head * prtd->pcm_count)));
+
+ param.paddr = (unsigned long)buf[0].phys
+ + (prtd->out_head * prtd->pcm_count);
+ param.len = prtd->pcm_count;
+ param.msw_ts = 0;
+ param.lsw_ts = 0;
+ param.flags = NO_TIMESTAMP;
+ param.uid = (unsigned long)buf[0].phys
+ + (prtd->out_head * prtd->pcm_count);
+ for (i = 0; i < sizeof(struct audio_aio_write_param)/4;
+ i++, ++ptrmem)
+ pr_debug("cmd[%d]=0x%08x\n", i, *ptrmem);
+ if (q6asm_async_write(prtd->audio_client,
+ ¶m) < 0)
+ pr_err("%s:q6asm_async_write failed\n",
+ __func__);
+ else
+ prtd->out_head =
+ (prtd->out_head + 1) & (runtime->periods - 1);
+ break;
+ }
+ case ASM_DATA_CMDRSP_EOS:
+ pr_debug("ASM_DATA_CMDRSP_EOS\n");
+ prtd->cmd_ack = 1;
+ wake_up(&the_locks.eos_wait);
+ break;
+ case APR_BASIC_RSP_RESULT: {
+ switch (payload[0]) {
+ case ASM_SESSION_CMD_RUN: {
+ if (!prtd->pending_buffer &&
+ !atomic_read(&prtd->start))
+ break;
+ pr_debug("%s:writing %d bytes"
+ " of buffer[%d] to dsp\n",
+ __func__, prtd->pcm_count, prtd->out_head);
+ buf = prtd->audio_client->port[IN].buf;
+ pr_debug("%s:writing buffer[%d] from 0x%08x\n",
+ __func__, prtd->out_head,
+ ((unsigned int)buf[0].phys
+ + (prtd->out_head * prtd->pcm_count)));
+ param.paddr = (unsigned long)buf[prtd->out_head].phys;
+ param.len = prtd->pcm_count;
+ param.msw_ts = 0;
+ param.lsw_ts = 0;
+ param.flags = NO_TIMESTAMP;
+ param.uid = (unsigned long)buf[prtd->out_head].phys;
+ if (q6asm_async_write(prtd->audio_client,
+ ¶m) < 0)
+ pr_err("%s:q6asm_async_write failed\n",
+ __func__);
+ else
+ prtd->out_head =
+ (prtd->out_head + 1)
+ & (runtime->periods - 1);
+ }
+ break;
+ case ASM_STREAM_CMD_FLUSH:
+ pr_debug("ASM_STREAM_CMD_FLUSH\n");
+ prtd->cmd_ack = 1;
+ wake_up(&the_locks.eos_wait);
+ break;
+ default:
+ break;
+ }
+ break;
+ }
+ default:
+ pr_debug("Not Supported Event opcode[0x%x]\n", opcode);
+ break;
+ }
+}
+
+static int msm_compr_playback_prepare(struct snd_pcm_substream *substream)
+{
+ struct snd_pcm_runtime *runtime = substream->runtime;
+ struct compr_audio *compr = runtime->private_data;
+ struct msm_audio *prtd = &compr->prtd;
+ int ret;
+
+ pr_debug("%s\n", __func__);
+ prtd->pcm_size = snd_pcm_lib_buffer_bytes(substream);
+ prtd->pcm_count = snd_pcm_lib_period_bytes(substream);
+ prtd->pcm_irq_pos = 0;
+ /* rate and channels are sent to audio driver */
+ prtd->samp_rate = runtime->rate;
+ prtd->channel_mode = runtime->channels;
+ prtd->out_head = 0;
+ if (prtd->enabled)
+ return 0;
+
+ ret = q6asm_media_format_block(prtd->audio_client, compr->codec);
+ if (ret < 0)
+ pr_info("%s: CMD Format block failed\n", __func__);
+
+ atomic_set(&prtd->out_count, runtime->periods);
+
+ prtd->enabled = 1;
+ prtd->cmd_ack = 0;
+
+ return 0;
+}
+
+static int msm_compr_trigger(struct snd_pcm_substream *substream, int cmd)
+{
+ int ret = 0;
+ struct snd_pcm_runtime *runtime = substream->runtime;
+ struct compr_audio *compr = runtime->private_data;
+ struct msm_audio *prtd = &compr->prtd;
+
+ pr_debug("%s\n", __func__);
+ switch (cmd) {
+ case SNDRV_PCM_TRIGGER_START:
+ prtd->pcm_irq_pos = 0;
+ case SNDRV_PCM_TRIGGER_RESUME:
+ case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
+ pr_debug("%s: Trigger start\n", __func__);
+ q6asm_run_nowait(prtd->audio_client, 0, 0, 0);
+ atomic_set(&prtd->start, 1);
+ break;
+ case SNDRV_PCM_TRIGGER_STOP:
+ pr_debug("SNDRV_PCM_TRIGGER_STOP\n");
+ atomic_set(&prtd->start, 0);
+ break;
+ case SNDRV_PCM_TRIGGER_SUSPEND:
+ case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
+ pr_debug("SNDRV_PCM_TRIGGER_PAUSE\n");
+ q6asm_cmd_nowait(prtd->audio_client, CMD_PAUSE);
+ atomic_set(&prtd->start, 0);
+ break;
+ default:
+ ret = -EINVAL;
+ break;
+ }
+
+ return ret;
+}
+
+static void populate_codec_list(struct compr_audio *compr,
+ struct snd_pcm_runtime *runtime)
+{
+ pr_debug("%s\n", __func__);
+ /* MP3 Block */
+ compr->info.compr_cap.num_codecs = 1;
+ compr->info.compr_cap.min_fragment_size = runtime->hw.period_bytes_min;
+ compr->info.compr_cap.max_fragment_size = runtime->hw.period_bytes_max;
+ compr->info.compr_cap.min_fragments = runtime->hw.periods_min;
+ compr->info.compr_cap.max_fragments = runtime->hw.periods_max;
+ compr->info.compr_cap.codecs[0] = SND_AUDIOCODEC_MP3;
+ /* Add new codecs here */
+}
+
+static int msm_compr_open(struct snd_pcm_substream *substream)
+{
+ struct snd_pcm_runtime *runtime = substream->runtime;
+ struct snd_soc_pcm_runtime *soc_prtd = substream->private_data;
+ struct compr_audio *compr;
+ struct msm_audio *prtd;
+ int ret = 0;
+
+ /* Capture path */
+ if (substream->stream == SNDRV_PCM_STREAM_CAPTURE)
+ return -EINVAL;
+
+ pr_debug("%s\n", __func__);
+ compr = kzalloc(sizeof(struct compr_audio), GFP_KERNEL);
+ if (compr == NULL) {
+ pr_err("Failed to allocate memory for msm_audio\n");
+ return -ENOMEM;
+ }
+ prtd = &compr->prtd;
+ prtd->substream = substream;
+ prtd->audio_client = q6asm_audio_client_alloc(
+ (app_cb)compr_event_handler, compr);
+ if (!prtd->audio_client) {
+ pr_info("%s: Could not allocate memory\n", __func__);
+ kfree(prtd);
+ return -ENOMEM;
+ }
+ runtime->hw = msm_compr_hardware_playback;
+
+ pr_info("%s: session ID %d\n", __func__, prtd->audio_client->session);
+
+ prtd->session_id = prtd->audio_client->session;
+ msm_pcm_routing_reg_phy_stream(soc_prtd->dai_link->be_id,
+ prtd->session_id, substream->stream);
+
+ prtd->cmd_ack = 1;
+
+ ret = snd_pcm_hw_constraint_list(runtime, 0,
+ SNDRV_PCM_HW_PARAM_RATE,
+ &constraints_sample_rates);
+ if (ret < 0)
+ pr_info("snd_pcm_hw_constraint_list failed\n");
+ /* Ensure that buffer size is a multiple of period size */
+ ret = snd_pcm_hw_constraint_integer(runtime,
+ SNDRV_PCM_HW_PARAM_PERIODS);
+ if (ret < 0)
+ pr_info("snd_pcm_hw_constraint_integer failed\n");
+
+ prtd->dsp_cnt = 0;
+ prtd->pending_buffer = 1;
+ compr->codec = FORMAT_MP3;
+ populate_codec_list(compr, runtime);
+ runtime->private_data = compr;
+
+ return 0;
+}
+
+static int msm_compr_playback_close(struct snd_pcm_substream *substream)
+{
+ struct snd_pcm_runtime *runtime = substream->runtime;
+ struct snd_soc_pcm_runtime *soc_prtd = substream->private_data;
+ struct compr_audio *compr = runtime->private_data;
+ struct msm_audio *prtd = &compr->prtd;
+ int dir = 0;
+
+ pr_debug("%s\n", __func__);
+
+ dir = IN;
+
+ q6asm_cmd(prtd->audio_client, CMD_CLOSE);
+ q6asm_audio_client_buf_free_contiguous(dir,
+ prtd->audio_client);
+
+ msm_pcm_routing_dereg_phy_stream(soc_prtd->dai_link->be_id,
+ SNDRV_PCM_STREAM_PLAYBACK);
+ q6asm_audio_client_free(prtd->audio_client);
+ kfree(prtd);
+ return 0;
+}
+
+static int msm_compr_close(struct snd_pcm_substream *substream)
+{
+ int ret = 0;
+
+ if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
+ ret = msm_compr_playback_close(substream);
+ else if (substream->stream == SNDRV_PCM_STREAM_CAPTURE)
+ ret = EINVAL;
+ return ret;
+}
+static int msm_compr_prepare(struct snd_pcm_substream *substream)
+{
+ int ret = 0;
+
+ if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
+ ret = msm_compr_playback_prepare(substream);
+ else if (substream->stream == SNDRV_PCM_STREAM_CAPTURE)
+ ret = EINVAL;
+ return ret;
+}
+
+static snd_pcm_uframes_t msm_compr_pointer(struct snd_pcm_substream *substream)
+{
+
+ struct snd_pcm_runtime *runtime = substream->runtime;
+ struct compr_audio *compr = runtime->private_data;
+ struct msm_audio *prtd = &compr->prtd;
+
+ if (prtd->pcm_irq_pos >= prtd->pcm_size)
+ prtd->pcm_irq_pos = 0;
+
+ pr_debug("pcm_irq_pos = %d\n", prtd->pcm_irq_pos);
+ return bytes_to_frames(runtime, (prtd->pcm_irq_pos));
+}
+
+static int msm_compr_mmap(struct snd_pcm_substream *substream,
+ struct vm_area_struct *vma)
+{
+ int result = 0;
+ struct snd_pcm_runtime *runtime = substream->runtime;
+ struct compr_audio *compr = runtime->private_data;
+ struct msm_audio *prtd = &compr->prtd;
+
+ pr_debug("%s\n", __func__);
+ prtd->mmap_flag = 1;
+ if (runtime->dma_addr && runtime->dma_bytes) {
+ vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot);
+ result = remap_pfn_range(vma, vma->vm_start,
+ runtime->dma_addr >> PAGE_SHIFT,
+ runtime->dma_bytes,
+ vma->vm_page_prot);
+ } else {
+ pr_err("Physical address or size of buf is NULL");
+ return -EINVAL;
+ }
+ return result;
+}
+
+static int msm_compr_hw_params(struct snd_pcm_substream *substream,
+ struct snd_pcm_hw_params *params)
+{
+ struct snd_pcm_runtime *runtime = substream->runtime;
+ struct compr_audio *compr = runtime->private_data;
+ struct msm_audio *prtd = &compr->prtd;
+ struct snd_dma_buffer *dma_buf = &substream->dma_buffer;
+ struct audio_buffer *buf;
+ int dir, ret;
+
+ pr_debug("%s\n", __func__);
+ if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
+ dir = IN;
+ else
+ return -EINVAL;
+
+ ret = q6asm_open_write(prtd->audio_client, compr->codec);
+ if (ret < 0) {
+ pr_err("%s: Session out open failed\n", __func__);
+ return -ENOMEM;
+ }
+ ret = q6asm_set_io_mode(prtd->audio_client, ASYNC_IO_MODE);
+ if (ret < 0) {
+ pr_err("%s: Set IO mode failed\n", __func__);
+ return -ENOMEM;
+ }
+
+ ret = q6asm_audio_client_buf_alloc_contiguous(dir,
+ prtd->audio_client,
+ runtime->hw.period_bytes_min,
+ runtime->hw.periods_max);
+ if (ret < 0) {
+ pr_err("Audio Start: Buffer Allocation failed "
+ "rc = %d\n", ret);
+ return -ENOMEM;
+ }
+ buf = prtd->audio_client->port[dir].buf;
+
+ pr_debug("%s:buf = %p\n", __func__, buf);
+ dma_buf->dev.type = SNDRV_DMA_TYPE_DEV;
+ dma_buf->dev.dev = substream->pcm->card->dev;
+ dma_buf->private_data = NULL;
+ dma_buf->area = buf[0].data;
+ dma_buf->addr = buf[0].phys;
+ dma_buf->bytes = runtime->hw.buffer_bytes_max;
+ if (!dma_buf->area)
+ return -ENOMEM;
+
+ snd_pcm_set_runtime_buffer(substream, &substream->dma_buffer);
+ return 0;
+}
+
+static int msm_compr_ioctl(struct snd_pcm_substream *substream,
+ unsigned int cmd, void *arg)
+{
+ int rc = 0;
+ struct snd_pcm_runtime *runtime = substream->runtime;
+ struct compr_audio *compr = runtime->private_data;
+ struct msm_audio *prtd = &compr->prtd;
+
+ switch (cmd) {
+ case SNDRV_COMPRESS_GET_CAPS:
+ pr_debug("SNDRV_COMPRESS_GET_CAPS\n");
+ if (copy_to_user((void *) arg, &compr->info.compr_cap,
+ sizeof(struct snd_compr_caps))) {
+ rc = -EFAULT;
+ pr_err("%s: ERROR: copy to user\n", __func__);
+ return rc;
+ }
+ return 0;
+ case SNDRV_COMPRESS_SET_PARAMS:
+ pr_debug("SNDRV_COMPRESS_SET_PARAMS: ");
+ if (copy_from_user(&compr->info.codec_param, (void *) arg,
+ sizeof(struct snd_compr_params))) {
+ rc = -EFAULT;
+ pr_err("%s: ERROR: copy from user\n", __func__);
+ return rc;
+ }
+ switch (compr->info.codec_param.codec.id) {
+ case SND_AUDIOCODEC_MP3:
+ /* For MP3 we dont need any other parameter */
+ pr_debug("SND_AUDIOCODEC_MP3\n");
+ compr->codec = FORMAT_MP3;
+ break;
+ default:
+ pr_debug("FORMAT_LINEAR_PCM\n");
+ compr->codec = FORMAT_LINEAR_PCM;
+ break;
+ }
+ return 0;
+ case SNDRV_PCM_IOCTL1_RESET:
+ prtd->cmd_ack = 0;
+ rc = q6asm_cmd(prtd->audio_client, CMD_FLUSH);
+ if (rc < 0)
+ pr_err("%s: flush cmd failed rc=%d\n", __func__, rc);
+ rc = wait_event_timeout(the_locks.eos_wait,
+ prtd->cmd_ack, 5 * HZ);
+ if (rc < 0)
+ pr_err("Flush cmd timeout\n");
+ prtd->pcm_irq_pos = 0;
+ break;
+ default:
+ break;
+ }
+ return snd_pcm_lib_ioctl(substream, cmd, arg);
+}
+
+static struct snd_pcm_ops msm_compr_ops = {
+ .open = msm_compr_open,
+ .hw_params = msm_compr_hw_params,
+ .close = msm_compr_close,
+ .ioctl = msm_compr_ioctl,
+ .prepare = msm_compr_prepare,
+ .trigger = msm_compr_trigger,
+ .pointer = msm_compr_pointer,
+ .mmap = msm_compr_mmap,
+};
+
+static int msm_asoc_pcm_new(struct snd_soc_pcm_runtime *rtd)
+{
+ struct snd_card *card = rtd->card->snd_card;
+ int ret = 0;
+
+ if (!card->dev->coherent_dma_mask)
+ card->dev->coherent_dma_mask = DMA_BIT_MASK(32);
+ return ret;
+}
+
+static struct snd_soc_platform_driver msm_soc_platform = {
+ .ops = &msm_compr_ops,
+ .pcm_new = msm_asoc_pcm_new,
+};
+
+static __devinit int msm_compr_probe(struct platform_device *pdev)
+{
+ pr_info("%s: dev name %s\n", __func__, dev_name(&pdev->dev));
+ return snd_soc_register_platform(&pdev->dev,
+ &msm_soc_platform);
+}
+
+static int msm_compr_remove(struct platform_device *pdev)
+{
+ snd_soc_unregister_platform(&pdev->dev);
+ return 0;
+}
+
+static struct platform_driver msm_compr_driver = {
+ .driver = {
+ .name = "msm-compr-dsp",
+ .owner = THIS_MODULE,
+ },
+ .probe = msm_compr_probe,
+ .remove = __devexit_p(msm_compr_remove),
+};
+
+static int __init msm_soc_platform_init(void)
+{
+ init_waitqueue_head(&the_locks.enable_wait);
+ init_waitqueue_head(&the_locks.eos_wait);
+ init_waitqueue_head(&the_locks.write_wait);
+ init_waitqueue_head(&the_locks.read_wait);
+
+ return platform_driver_register(&msm_compr_driver);
+}
+module_init(msm_soc_platform_init);
+
+static void __exit msm_soc_platform_exit(void)
+{
+ platform_driver_unregister(&msm_compr_driver);
+}
+module_exit(msm_soc_platform_exit);
+
+MODULE_DESCRIPTION("PCM module platform driver");
+MODULE_LICENSE("GPL v2");
diff --git a/sound/soc/msm/msm-compr-q6.h b/sound/soc/msm/msm-compr-q6.h
new file mode 100644
index 0000000..6dfbcce
--- /dev/null
+++ b/sound/soc/msm/msm-compr-q6.h
@@ -0,0 +1,36 @@
+/*
+ * Copyright (c) 2011, Code Aurora Forum. 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 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#ifndef _MSM_COMPR_H
+#define _MSM_COMPR_H
+#include <sound/apr_audio.h>
+#include <sound/q6asm.h>
+#include <sound/snd_compress_params.h>
+#include <sound/compress_offload.h>
+#include <sound/compress_driver.h>
+
+#include "msm-pcm-q6.h"
+
+struct compr_info {
+ struct snd_compr_caps compr_cap;
+ struct snd_compr_codec_caps codec_caps;
+ struct snd_compr_params codec_param;
+};
+
+struct compr_audio {
+ struct msm_audio prtd;
+ struct compr_info info;
+ uint32_t codec;
+};
+
+#endif /*_MSM_COMPR_H*/
diff --git a/sound/soc/msm/msm-dai-fe.c b/sound/soc/msm/msm-dai-fe.c
index 401c1a9..16d149e 100644
--- a/sound/soc/msm/msm-dai-fe.c
+++ b/sound/soc/msm/msm-dai-fe.c
@@ -151,6 +151,20 @@
.ops = &msm_fe_Multimedia_dai_ops,
.name = "MultiMedia3",
},
+ {
+ .playback = {
+ .stream_name = "MultiMedia4 Playback",
+ .rates = (SNDRV_PCM_RATE_8000_48000 |
+ SNDRV_PCM_RATE_KNOT),
+ .formats = SNDRV_PCM_FMTBIT_S16_LE,
+ .channels_min = 1,
+ .channels_max = 2,
+ .rate_min = 8000,
+ .rate_max = 48000,
+ },
+ .ops = &msm_fe_Multimedia_dai_ops,
+ .name = "MultiMedia4",
+ },
/* FE DAIs created for hostless operation purpose */
{
.playback = {
diff --git a/sound/soc/msm/msm-pcm-lpa.c b/sound/soc/msm/msm-pcm-lpa.c
index 29f89ce..f644722 100644
--- a/sound/soc/msm/msm-pcm-lpa.c
+++ b/sound/soc/msm/msm-pcm-lpa.c
@@ -131,7 +131,8 @@
case APR_BASIC_RSP_RESULT: {
switch (payload[0]) {
case ASM_SESSION_CMD_RUN: {
- if (!prtd->pending_buffer)
+ if (!prtd->pending_buffer &&
+ !atomic_read(&prtd->start))
break;
pr_debug("%s:writing %d bytes"
" of buffer to dsp\n",
diff --git a/sound/soc/msm/msm-pcm-routing.c b/sound/soc/msm/msm-pcm-routing.c
index 97d0760..3573169 100644
--- a/sound/soc/msm/msm-pcm-routing.c
+++ b/sound/soc/msm/msm-pcm-routing.c
@@ -125,6 +125,8 @@
{INVALID_SESSION, INVALID_SESSION},
/* MULTIMEDIA3 */
{INVALID_SESSION, INVALID_SESSION},
+ /* MULTIMEDIA4 */
+ {INVALID_SESSION, INVALID_SESSION},
};
static void msm_pcm_routing_build_matrix(int fedai_id, int dspst_id,
@@ -615,6 +617,9 @@
SOC_SINGLE_EXT("MultiMedia3", MSM_BACKEND_DAI_PRI_I2S_RX,
MSM_FRONTEND_DAI_MULTIMEDIA3, 1, 0, msm_routing_get_audio_mixer,
msm_routing_put_audio_mixer),
+ SOC_SINGLE_EXT("MultiMedia4", MSM_BACKEND_DAI_PRI_I2S_RX,
+ MSM_FRONTEND_DAI_MULTIMEDIA4, 1, 0, msm_routing_get_audio_mixer,
+ msm_routing_put_audio_mixer),
};
static const struct snd_kcontrol_new slimbus_rx_mixer_controls[] = {
@@ -627,6 +632,9 @@
SOC_SINGLE_EXT("MultiMedia3", MSM_BACKEND_DAI_SLIMBUS_0_RX,
MSM_FRONTEND_DAI_MULTIMEDIA3, 1, 0, msm_routing_get_audio_mixer,
msm_routing_put_audio_mixer),
+ SOC_SINGLE_EXT("MultiMedia4", MSM_BACKEND_DAI_SLIMBUS_0_RX,
+ MSM_FRONTEND_DAI_MULTIMEDIA4, 1, 0, msm_routing_get_audio_mixer,
+ msm_routing_put_audio_mixer),
};
static const struct snd_kcontrol_new hdmi_mixer_controls[] = {
@@ -639,6 +647,9 @@
SOC_SINGLE_EXT("MultiMedia3", MSM_BACKEND_DAI_HDMI_RX,
MSM_FRONTEND_DAI_MULTIMEDIA3, 1, 0, msm_routing_get_audio_mixer,
msm_routing_put_audio_mixer),
+ SOC_SINGLE_EXT("MultiMedia4", MSM_BACKEND_DAI_HDMI_RX,
+ MSM_FRONTEND_DAI_MULTIMEDIA4, 1, 0, msm_routing_get_audio_mixer,
+ msm_routing_put_audio_mixer),
};
static const struct snd_kcontrol_new int_bt_sco_rx_mixer_controls[] = {
@@ -651,6 +662,9 @@
SOC_SINGLE_EXT("MultiMedia3", MSM_BACKEND_DAI_INT_BT_SCO_RX,
MSM_FRONTEND_DAI_MULTIMEDIA3, 1, 0, msm_routing_get_audio_mixer,
msm_routing_put_audio_mixer),
+ SOC_SINGLE_EXT("MultiMedia4", MSM_BACKEND_DAI_INT_BT_SCO_RX,
+ MSM_FRONTEND_DAI_MULTIMEDIA4, 1, 0, msm_routing_get_audio_mixer,
+ msm_routing_put_audio_mixer),
};
static const struct snd_kcontrol_new int_fm_rx_mixer_controls[] = {
@@ -663,6 +677,9 @@
SOC_SINGLE_EXT("MultiMedia3", MSM_BACKEND_DAI_INT_FM_RX,
MSM_FRONTEND_DAI_MULTIMEDIA3, 1, 0, msm_routing_get_audio_mixer,
msm_routing_put_audio_mixer),
+ SOC_SINGLE_EXT("MultiMedia4", MSM_BACKEND_DAI_INT_FM_RX,
+ MSM_FRONTEND_DAI_MULTIMEDIA4, 1, 0, msm_routing_get_audio_mixer,
+ msm_routing_put_audio_mixer),
};
static const struct snd_kcontrol_new afe_pcm_rx_mixer_controls[] = {
@@ -675,6 +692,9 @@
SOC_SINGLE_EXT("MultiMedia3", MSM_BACKEND_DAI_AFE_PCM_RX,
MSM_FRONTEND_DAI_MULTIMEDIA3, 1, 0, msm_routing_get_audio_mixer,
msm_routing_put_audio_mixer),
+ SOC_SINGLE_EXT("MultiMedia4", MSM_BACKEND_DAI_AFE_PCM_RX,
+ MSM_FRONTEND_DAI_MULTIMEDIA4, 1, 0, msm_routing_get_audio_mixer,
+ msm_routing_put_audio_mixer),
};
static const struct snd_kcontrol_new auxpcm_rx_mixer_controls[] = {
@@ -687,6 +707,9 @@
SOC_SINGLE_EXT("MultiMedia3", MSM_BACKEND_DAI_AUXPCM_RX,
MSM_FRONTEND_DAI_MULTIMEDIA3, 1, 0, msm_routing_get_audio_mixer,
msm_routing_put_audio_mixer),
+ SOC_SINGLE_EXT("MultiMedia4", MSM_BACKEND_DAI_AUXPCM_RX,
+ MSM_FRONTEND_DAI_MULTIMEDIA4, 1, 0, msm_routing_get_audio_mixer,
+ msm_routing_put_audio_mixer),
};
static const struct snd_kcontrol_new mmul1_mixer_controls[] = {
@@ -1014,6 +1037,7 @@
SND_SOC_DAPM_AIF_IN("MM_DL1", "MultiMedia1 Playback", 0, 0, 0, 0),
SND_SOC_DAPM_AIF_IN("MM_DL2", "MultiMedia2 Playback", 0, 0, 0, 0),
SND_SOC_DAPM_AIF_IN("MM_DL3", "MultiMedia3 Playback", 0, 0, 0, 0),
+ SND_SOC_DAPM_AIF_IN("MM_DL4", "MultiMedia4 Playback", 0, 0, 0, 0),
SND_SOC_DAPM_AIF_IN("VOIP_DL", "VoIP Playback", 0, 0, 0, 0),
SND_SOC_DAPM_AIF_OUT("MM_UL1", "MultiMedia1 Capture", 0, 0, 0, 0),
SND_SOC_DAPM_AIF_OUT("MM_UL2", "MultiMedia2 Capture", 0, 0, 0, 0),
@@ -1111,16 +1135,19 @@
{"PRI_RX Audio Mixer", "MultiMedia1", "MM_DL1"},
{"PRI_RX Audio Mixer", "MultiMedia2", "MM_DL2"},
{"PRI_RX Audio Mixer", "MultiMedia3", "MM_DL3"},
+ {"PRI_RX Audio Mixer", "MultiMedia4", "MM_DL4"},
{"PRI_I2S_RX", NULL, "PRI_RX Audio Mixer"},
{"SLIMBUS_0_RX Audio Mixer", "MultiMedia1", "MM_DL1"},
{"SLIMBUS_0_RX Audio Mixer", "MultiMedia2", "MM_DL2"},
{"SLIMBUS_0_RX Audio Mixer", "MultiMedia3", "MM_DL3"},
+ {"SLIMBUS_0_RX Audio Mixer", "MultiMedia4", "MM_DL4"},
{"SLIMBUS_0_RX", NULL, "SLIMBUS_0_RX Audio Mixer"},
{"HDMI Mixer", "MultiMedia1", "MM_DL1"},
{"HDMI Mixer", "MultiMedia2", "MM_DL2"},
{"HDMI Mixer", "MultiMedia3", "MM_DL3"},
+ {"HDMI Mixer", "MultiMedia4", "MM_DL4"},
{"HDMI", NULL, "HDMI Mixer"},
{"MultiMedia1 Mixer", "PRI_TX", "PRI_I2S_TX"},
@@ -1130,16 +1157,19 @@
{"INTERNAL_BT_SCO_RX Audio Mixer", "MultiMedia1", "MM_DL1"},
{"INTERNAL_BT_SCO_RX Audio Mixer", "MultiMedia2", "MM_DL2"},
{"INTERNAL_BT_SCO_RX Audio Mixer", "MultiMedia3", "MM_DL3"},
+ {"INTERNAL_BT_SCO_RX Audio Mixer", "MultiMedia4", "MM_DL4"},
{"INT_BT_SCO_RX", NULL, "INTERNAL_BT_SCO_RX Audio Mixer"},
{"INTERNAL_FM_RX Audio Mixer", "MultiMedia1", "MM_DL1"},
{"INTERNAL_FM_RX Audio Mixer", "MultiMedia2", "MM_DL2"},
{"INTERNAL_FM_RX Audio Mixer", "MultiMedia3", "MM_DL3"},
+ {"INTERNAL_FM_RX Audio Mixer", "MultiMedia4", "MM_DL4"},
{"INT_FM_RX", NULL, "INTERNAL_FM_RX Audio Mixer"},
{"AFE_PCM_RX Audio Mixer", "MultiMedia1", "MM_DL1"},
{"AFE_PCM_RX Audio Mixer", "MultiMedia2", "MM_DL2"},
{"AFE_PCM_RX Audio Mixer", "MultiMedia3", "MM_DL3"},
+ {"AFE_PCM_RX Audio Mixer", "MultiMedia4", "MM_DL4"},
{"PCM_RX", NULL, "AFE_PCM_RX Audio Mixer"},
{"MultiMedia1 Mixer", "INTERNAL_BT_SCO_TX", "INT_BT_SCO_TX"},
@@ -1153,6 +1183,7 @@
{"AUX_PCM_RX Audio Mixer", "MultiMedia1", "MM_DL1"},
{"AUX_PCM_RX Audio Mixer", "MultiMedia2", "MM_DL2"},
{"AUX_PCM_RX Audio Mixer", "MultiMedia3", "MM_DL3"},
+ {"AUX_PCM_RX Audio Mixer", "MultiMedia4", "MM_DL4"},
{"AUX_PCM_RX", NULL, "AUX_PCM_RX Audio Mixer"},
{"PRI_RX_Voice Mixer", "CSVoice", "CS-VOICE_DL1"},
diff --git a/sound/soc/msm/msm-pcm-routing.h b/sound/soc/msm/msm-pcm-routing.h
index db7552d..b7fc82a 100644
--- a/sound/soc/msm/msm-pcm-routing.h
+++ b/sound/soc/msm/msm-pcm-routing.h
@@ -31,6 +31,7 @@
MSM_FRONTEND_DAI_MULTIMEDIA1 = 0,
MSM_FRONTEND_DAI_MULTIMEDIA2,
MSM_FRONTEND_DAI_MULTIMEDIA3,
+ MSM_FRONTEND_DAI_MULTIMEDIA4,
MSM_FRONTEND_DAI_CS_VOICE,
MSM_FRONTEND_DAI_VOIP,
MSM_FRONTEND_DAI_AFE_RX,
diff --git a/sound/soc/msm/qdsp6/q6asm.c b/sound/soc/msm/qdsp6/q6asm.c
index 268d2e5..ab7f9f7 100644
--- a/sound/soc/msm/qdsp6/q6asm.c
+++ b/sound/soc/msm/qdsp6/q6asm.c
@@ -1202,6 +1202,9 @@
case FORMAT_WMA_V10PRO:
open.format = WMA_V10PRO;
break;
+ case FORMAT_MP3:
+ open.format = MP3;
+ break;
default:
pr_err("%s: Invalid format[%d]\n", __func__, format);
goto fail_cmd;
@@ -1865,7 +1868,26 @@
q6asm_add_hdr(ac, &fmt.hdr, sizeof(fmt), TRUE);
fmt.hdr.opcode = ASM_DATA_CMD_MEDIA_FORMAT_UPDATE;
- fmt.format = format;
+ switch (format) {
+ case FORMAT_V13K:
+ fmt.format = V13K_FS;
+ break;
+ case FORMAT_EVRC:
+ fmt.format = EVRC_FS;
+ break;
+ case FORMAT_AMRWB:
+ fmt.format = AMRWB_FS;
+ break;
+ case FORMAT_AMRNB:
+ fmt.format = AMRNB_FS;
+ break;
+ case FORMAT_MP3:
+ fmt.format = MP3;
+ break;
+ default:
+ pr_err("Invalid format[%d]\n", format);
+ goto fail_cmd;
+ }
fmt.cfg_size = 0;
rc = apr_send_pkt(ac->apr, (uint32_t *) &fmt);
diff --git a/sound/soc/soc-dsp.c b/sound/soc/soc-dsp.c
index 6b0c215..706954b 100644
--- a/sound/soc/soc-dsp.c
+++ b/sound/soc/soc-dsp.c
@@ -627,6 +627,10 @@
struct snd_soc_dsp_params *dsp_params;
int ret = 0;
+ if ((cmd == SNDRV_PCM_TRIGGER_PAUSE_RELEASE) ||
+ (cmd == SNDRV_PCM_TRIGGER_PAUSE_PUSH))
+ return ret;
+
list_for_each_entry(dsp_params, &fe->dsp[stream].be_clients, list_be) {
struct snd_pcm_substream *be_substream =
diff --git a/tools/perf/Makefile b/tools/perf/Makefile
index c168366..225b292 100644
--- a/tools/perf/Makefile
+++ b/tools/perf/Makefile
@@ -366,6 +366,7 @@
BUILTIN_OBJS += $(OUTPUT)builtin-record.o
BUILTIN_OBJS += $(OUTPUT)builtin-report.o
BUILTIN_OBJS += $(OUTPUT)builtin-stat.o
+BUILTIN_OBJS += $(OUTPUT)builtin-periodic.o
BUILTIN_OBJS += $(OUTPUT)builtin-timechart.o
BUILTIN_OBJS += $(OUTPUT)builtin-top.o
BUILTIN_OBJS += $(OUTPUT)builtin-script.o
diff --git a/tools/perf/builtin-periodic.c b/tools/perf/builtin-periodic.c
new file mode 100644
index 0000000..70a0e2b
--- /dev/null
+++ b/tools/perf/builtin-periodic.c
@@ -0,0 +1,483 @@
+/*
+ * Copyright (c) 2011, Code Aurora Forum. 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 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+/*
+ * A very simple perf program to periodically print the performance
+ * counter reqested on the command line to standard out at the rate
+ * specified.
+ *
+ * This is valuable for showing the output in a simple plot or
+ * exporting the counter data for post processing. No attempt
+ * to process the data is made.
+ *
+ * Scaling is not supported, use only as many counters as are
+ * provided by the hardware.
+ *
+ * Math functions are support to combine counter results by using
+ * the -m flag.
+ *
+ * The -r -w flags supports user signalling for input. This assumes
+ * that a pipe/fifo is needed so the -rw cmd line arg is a string
+ * that is the name of the named pipe to open for read/write. User
+ * sends data on the read pipe to the process to collect a sample.
+ * Commands are also supported on the pipe.
+ *
+ */
+
+#include "perf.h"
+#include "builtin.h"
+#include "util/util.h"
+#include "util/parse-options.h"
+#include "util/parse-events.h"
+#include "util/event.h"
+#include "util/evsel.h"
+#include "util/evlist.h"
+#include "util/debug.h"
+#include "util/header.h"
+#include "util/cpumap.h"
+#include "util/thread.h"
+#include <signal.h>
+#include <sys/types.h>
+
+#define PERF_PERIODIC_ERROR -1
+
+/* number of pieces of data on each read. */
+#define DATA_SIZE 2
+
+#define DEFAULT_FIFO_NAME "xxbadFiFo"
+#define MAX_NAMELEN 50
+
+struct perf_evlist *evsel_list;
+
+/*
+ * command line variables and settings
+ * Default to current process, no_inherit, process
+ */
+static pid_t target_pid = -1; /* all */
+static bool system_wide;
+static int cpumask = -1; /* all */
+static int ncounts;
+static int ms_sleep = 1000; /* 1 second */
+static char const *operations = "nnnnnnnnnnnnnnnn"; /* nop */
+static bool math_enabled;
+static bool calc_delta;
+static double old_accum, accum;
+static int math_op_index;
+static char const *wfifo_name = DEFAULT_FIFO_NAME;
+static char const *rfifo_name = DEFAULT_FIFO_NAME;
+static bool use_fifo;
+static bool is_ratio;
+static FILE *fd_in, *fd_out;
+
+static FILE *tReadFifo, *tWriteFifo;
+
+/*
+ * Raw results from perf, we track the current value and
+ * the old value.
+ */
+struct perf_raw_results_s {
+ u64 values;
+ u64 old_value;
+};
+
+/*
+ * Everything we need to support a perf counter across multiple
+ * CPUs. We need to support multiple file descriptors (perf_fd)
+ * because perf requires a fd per counter, so 1 per core enabled.
+ *
+ * Raw results values are calculated across all the cores as they
+ * are read.
+ */
+struct perf_setup_s {
+ int event_index;
+ struct perf_event_attr *attr;
+ int perf_fd[MAX_NR_CPUS];
+ pid_t pid;
+ int cpu;
+ int flags;
+ int group;
+ struct perf_raw_results_s data;
+ struct perf_raw_results_s totals;
+ struct perf_raw_results_s output;
+};
+
+static void do_cleanup(void)
+{
+ if (fd_in) {
+ if (0 != fclose(fd_in))
+ error("Error closing fd_in\n");
+ }
+ if (fd_out) {
+ if (0 != fclose(fd_out))
+ error("Error closing fd_out\n");
+ }
+ if (use_fifo) {
+ if (0 != unlink(rfifo_name))
+ error("Error unlinking rfifo\n");
+ if (0 != unlink(wfifo_name))
+ error("Error unlinking wfifo\n");
+ }
+}
+
+/*
+ * Unexpected signal for error indication, cleanup
+ */
+static int sig_dummy;
+static void sig_do_cleanup(int sig)
+{
+ sig_dummy = sig;
+ do_cleanup();
+ exit(0);
+}
+
+#define PERIODIC_MAX_STRLEN 100
+/*
+ * Delay for either a timed period or the wait on the read_fifo
+ */
+static void delay(unsigned long milli)
+{
+ char tmp_stg[PERIODIC_MAX_STRLEN];
+ int done;
+ int ret;
+
+ if (use_fifo) {
+ do {
+ done = true;
+ ret = fscanf(tReadFifo, "%s", tmp_stg);
+ if (ret == 0)
+ return;
+ /*
+ * Look for a command request, and if we get a command
+ * Need to process and then wait again w/o sending data.
+ */
+ if (strncmp(tmp_stg, "PID", strnlen(tmp_stg,
+ PERIODIC_MAX_STRLEN)) == 0) {
+ fprintf(fd_out, " %u\n", getpid());
+ fflush(fd_out);
+ done = false;
+ } else if (strncmp(tmp_stg, "EXIT",
+ strnlen(tmp_stg, PERIODIC_MAX_STRLEN))
+ == 0) {
+ do_cleanup();
+ exit(0);
+ }
+
+ } while (done != true);
+ } else
+ usleep(milli*1000);
+}
+
+/*
+ * Create a perf counter event.
+ * Some interesting behaviour that is not documented anywhere else:
+ * the CPU will not work if out of range.
+ * The CPU will only work for a single CPU, so to collect the counts
+ * on the system in SMP based systems a counter needs to be created
+ * for each CPU.
+ */
+static int create_perf_counter(struct perf_setup_s *p)
+{
+ struct cpu_map *cpus;
+ int cpu;
+
+ cpus = cpu_map__new(NULL);
+ if (p == NULL)
+ return PERF_PERIODIC_ERROR;
+ for (cpu = 0; cpu < cpus->nr; cpu++) {
+ p->perf_fd[cpu] = sys_perf_event_open(p->attr, target_pid, cpu,
+ -1, 0);
+ if (p->perf_fd[cpu] < 0)
+ return PERF_PERIODIC_ERROR;
+ }
+ return 0;
+}
+
+/*
+ * Perf init setup
+ */
+static int perf_setup_init(struct perf_setup_s *p)
+{
+ if (p == NULL)
+ return PERF_PERIODIC_ERROR;
+
+ bzero(p, sizeof(struct perf_setup_s));
+ p->group = -1;
+ p->flags = 0;
+
+ p->output.values = 0;
+ p->output.old_value = 0;
+ p->data.values = 0;
+ p->data.old_value = 0;
+ p->totals.old_value = 0;
+ p->totals.values = 0;
+
+ return 0;
+}
+
+/*
+ * Read in ALL the performance counters configured for the CPU,
+ * one performance monitor per core that was configured during
+ * "all" mode
+ */
+static int perf_setup_read(struct perf_setup_s *p)
+{
+ u64 data[DATA_SIZE];
+ int i, status;
+
+ p->totals.values = 0;
+ p->data.values = 0;
+ for (i = 0; i < MAX_NR_CPUS; i++) {
+ if (p->perf_fd[i] == 0)
+ continue;
+ status = read(p->perf_fd[i], &data, sizeof(data));
+ p->data.values += data[0];
+ p->totals.values += data[0];
+ }
+
+ /*
+ * Normally we show totals, we want to support
+ * showing deltas from the previous value so external apps do not have
+ * to do this...
+ */
+ if (calc_delta) {
+ p->output.values = p->data.values - p->data.old_value;
+ p->data.old_value = p->data.values;
+ } else
+ p->output.values = p->totals.values;
+ return 0;
+}
+
+static int perf_setup_show(struct perf_setup_s *p)
+{
+ if (p == NULL)
+ return PERF_PERIODIC_ERROR;
+ fprintf(fd_out, " %llu", p->output.values);
+ return 0;
+}
+
+
+static const char * const periodic_usage[] = {
+ "perf periodic [<options>]",
+ NULL
+};
+
+static const struct option options[] = {
+ OPT_CALLBACK('e', "event", &evsel_list, "event",
+ "event selector. use 'perf list' to list available events",
+ parse_events),
+ OPT_STRING('m', "math-operations", &operations, "nnnnnn",
+ "math operation to perform on values collected asmd in order"),
+ OPT_STRING('r', "readpipe", &rfifo_name, "xxbadFiFo",
+ "wait for a user input fifo - will be created"),
+ OPT_STRING('w', "writepipe", &wfifo_name, "xxbadFifo",
+ "write data out on this pipe - pipe is created"),
+ OPT_INTEGER('i', "increment", &ncounts,
+ "number of times periods to count/iterate (default 0-forever)"),
+ OPT_INTEGER('p', "pid", &target_pid,
+ "stat events on existing process id"),
+ OPT_INTEGER('c', "cpumask", &cpumask,
+ "cpumask to enable counters, default all (-1)"),
+ OPT_INTEGER('s', "sleep", &ms_sleep,
+ "how long to sleep in ms between each sample (default 1000)"),
+ OPT_BOOLEAN('a', "all-cpus", &system_wide,
+ "system-wide collection from all CPUs overrides cpumask"),
+ OPT_BOOLEAN('d', "delta", &calc_delta,
+ "calculate and display the delta values math funcs will use delta"),
+ OPT_INCR('v', "verbose", &verbose,
+ "be more verbose (show counter open errors, etc)"),
+ OPT_END()
+};
+
+/*
+ * After every period we reset any math that was performed.
+ */
+static void reset_math(void)
+{
+ math_op_index = 0;
+ old_accum = accum;
+ accum = 0;
+}
+
+static void do_math_op(struct perf_setup_s *p)
+{
+ if (!math_enabled)
+ return;
+ switch (operations[math_op_index++]) {
+ case 'm':
+ accum *= (double)p->output.values; break;
+ case 'a':
+ accum += (double)p->output.values; break;
+ case 's':
+ accum -= (double)p->output.values; break;
+ case 'd':
+ accum /= (double)p->output.values; break;
+ case 'z':
+ accum = 0; break;
+ case 't':
+ accum = (double)p->output.values; break; /*transfer*/
+ case 'T':
+ accum += old_accum; break; /*total*/
+ case 'i': /* ignore */
+ default:
+ break;
+ }
+}
+
+int cmd_periodic(int argc, const char **argv, const char *prefix __used)
+{
+ int status = 0;
+ int c, i;
+ struct perf_setup_s *p[MAX_COUNTERS];
+ struct perf_evsel *counter;
+ FILE *fp;
+ int nr_counters = 0;
+
+ evsel_list = perf_evlist__new(NULL, NULL);
+ if (evsel_list == NULL)
+ return -ENOMEM;
+
+ argc = parse_options(argc, argv, options, periodic_usage,
+ PARSE_OPT_STOP_AT_NON_OPTION);
+
+ if (system_wide)
+ cpumask = -1;
+
+ /*
+ * The r & w option redirects stdout to a newly created pipe and
+ * waits for input on the read pipe before continuing
+ */
+ fd_in = stdin;
+ fd_out = stdout;
+ if (strncmp(rfifo_name, DEFAULT_FIFO_NAME,
+ strnlen(rfifo_name, MAX_NAMELEN))) {
+ fp = fopen(rfifo_name, "r");
+ if (fp != NULL) {
+ fclose(fp);
+ remove(rfifo_name);
+ }
+ if (mkfifo(rfifo_name, 0777) == -1) {
+ error("Could not open read fifo\n");
+ do_cleanup();
+ return PERF_PERIODIC_ERROR;
+ }
+ tReadFifo = fopen(rfifo_name, "r+");
+ if (tReadFifo == 0) {
+ do_cleanup();
+ error("Could not open read fifo file\n");
+ return PERF_PERIODIC_ERROR;
+ }
+ use_fifo = true;
+ }
+ if (strncmp(wfifo_name, DEFAULT_FIFO_NAME,
+ strnlen(wfifo_name, MAX_NAMELEN))) {
+ fp = fopen(wfifo_name, "r");
+ if (fp != NULL) {
+ fclose(fp);
+ remove(wfifo_name);
+ }
+ if (mkfifo(wfifo_name, 0777) == -1) {
+ do_cleanup();
+ error("Could not open write fifo\n");
+ return PERF_PERIODIC_ERROR;
+ }
+ fd_out = fopen(wfifo_name, "w+");
+ if (fd_out == 0) {
+ do_cleanup();
+ error("Could not open write fifo file\n");
+ return PERF_PERIODIC_ERROR;
+ }
+ tWriteFifo = fd_out;
+ }
+
+ math_enabled = (operations[0] != 'n');
+
+ /*
+ * If we don't ignore SIG_PIPE then when the other side
+ * of a pipe closes we shutdown too...
+ */
+ signal(SIGPIPE, SIG_IGN);
+ signal(SIGINT, sig_do_cleanup);
+ signal(SIGQUIT, sig_do_cleanup);
+ signal(SIGKILL, sig_do_cleanup);
+ signal(SIGTERM, sig_do_cleanup);
+
+ i = 0;
+ list_for_each_entry(counter, &evsel_list->entries, node) {
+ p[i] = malloc(sizeof(struct perf_setup_s));
+ if (p[i] == NULL) {
+ error("Error allocating perf_setup_s\n");
+ do_cleanup();
+ return PERF_PERIODIC_ERROR;
+ }
+ bzero(p[i], sizeof(struct perf_setup_s));
+ perf_setup_init(p[i]);
+ p[i]->attr = &(counter->attr);
+ p[i]->event_index = counter->idx;
+ if (create_perf_counter(p[i]) < 0) {
+ do_cleanup();
+ die("Not all events could be opened.\n");
+ return PERF_PERIODIC_ERROR;
+ }
+ i++;
+ nr_counters++;
+ }
+ i = 0;
+ while (1) {
+
+ /*
+ * Wait first otherwise single sample will print w/o signal
+ * when using the -u (user signal) flag
+ */
+ delay(ms_sleep);
+
+ /*
+ * Do the collection, read and then perform any math operations
+ */
+ for (c = 0; c < nr_counters; c++) {
+ status = perf_setup_read(p[c]);
+ do_math_op(p[c]);
+ }
+
+ /*
+ * After all collection and math, we perform one last math
+ * to allow totaling, if enabled etc, then either printout
+ * a single float value when the math is enabled or ...
+ */
+ if (math_enabled) {
+ do_math_op(p[c]);
+ if (is_ratio)
+ fprintf(fd_out, "%#f\n", accum*100);
+ else
+ fprintf(fd_out, "%#f\n", accum);
+ } else {
+ /*
+ * ... print out one integer value for each counter
+ */
+ for (c = 0; c < nr_counters; c++)
+ status = perf_setup_show(p[c]);
+ fprintf(fd_out, "\n");
+ }
+
+ /*
+ * Did the user give us an iteration count?
+ */
+ if ((ncounts != 0) && (++i >= ncounts))
+ break;
+ reset_math();
+ fflush(fd_out); /* make sure data is flushed out the pipe*/
+ }
+
+ do_cleanup();
+
+ return status;
+}
diff --git a/tools/perf/builtin.h b/tools/perf/builtin.h
index 4702e24..889ff68 100644
--- a/tools/perf/builtin.h
+++ b/tools/perf/builtin.h
@@ -26,6 +26,7 @@
extern int cmd_record(int argc, const char **argv, const char *prefix);
extern int cmd_report(int argc, const char **argv, const char *prefix);
extern int cmd_stat(int argc, const char **argv, const char *prefix);
+extern int cmd_periodic(int argc, const char **argv, const char *prefix);
extern int cmd_timechart(int argc, const char **argv, const char *prefix);
extern int cmd_top(int argc, const char **argv, const char *prefix);
extern int cmd_script(int argc, const char **argv, const char *prefix);
diff --git a/tools/perf/perf.c b/tools/perf/perf.c
index ec635b7..32f6673 100644
--- a/tools/perf/perf.c
+++ b/tools/perf/perf.c
@@ -320,6 +320,7 @@
{ "report", cmd_report, 0 },
{ "bench", cmd_bench, 0 },
{ "stat", cmd_stat, 0 },
+ { "periodic", cmd_periodic, 0 },
{ "timechart", cmd_timechart, 0 },
{ "top", cmd_top, 0 },
{ "annotate", cmd_annotate, 0 },