Merge "hwmon: pm8xxx-adc: Vote for a PMIC clock buffer"
diff --git a/Documentation/arm/msm/adsprpc-drv.txt b/Documentation/arm/msm/adsprpc-drv.txt
new file mode 100644
index 0000000..f468ddb
--- /dev/null
+++ b/Documentation/arm/msm/adsprpc-drv.txt
@@ -0,0 +1,198 @@
+Introduction
+============
+
+The MSM ADSPRPC driver implements an IPC (Inter-Processor Communication)
+mechanism that allows for clients to transparently make remote method
+invocations across processor boundaries.
+
+The below diagram depicts invocation of a single method where the client
+and objects reside on different processors. An object could expose
+multiple methods which can be grouped together and referred to as an
+interface.
+
+: ,--------, ,------, ,-----------, ,------, ,--------,
+: | | method | | | | | | method | |
+: | Client |------->| Stub |->| Transport |->| Skel |------->| Object |
+: | | | | | | | | | |
+: `--------` `------` `-----------` `------` `--------`
+
+Client: Linux user mode process that initiates the remote invocation
+Stub: Auto generated code linked in with the user mode process that
+ takes care of marshaling parameters
+Transport: Involved in carrying an invocation from a client to an
+ object. This involves two portions: 1) MSM ADSPRPC Linux
+ kernel driver that receives the remote invocation, queues
+ them up and then waits for the response after signaling the
+ remote side. 2) Service running on the remote side that
+ dequeues the messages from the queue and dispatches them for
+ processing.
+Skel: Auto generated code that takes care of un-marshaling
+ parameters
+Object: Method implementation
+
+Hardware description
+====================
+
+The driver interfaces with the components in the DSP subsystem and does
+not drive or manage any hardware resources.
+
+Software description
+====================
+
+The MSM ADSPRPC driver uses SMD (Shared Memory Driver) to send and
+receive messages with the remote processor. The SMD channel used for
+communication is opened during initialization of the driver and is
+closed when the driver module is unloaded. The driver does not expose
+HLOS memory to the remote processor but rather communication of
+invocation parameters happen over ION allocated buffers.
+
+The driver receives remote call invocations via an ioctl call. When a
+remote call invocation is received, the driver does the following:
+- Retrieves the invocation parameters
+- Copies input buffers in HLOS memory to ION allocated buffers
+- Allocates ION buffers for output buffers in HLOS memory as required
+- Scatter-gathers list of pages for ION allocated input and output
+ buffers
+- Coalesces information about the contiguous page buffers
+- Builds up a message with the received information
+- Sends the message to a remote processor through an SMD channel
+- Waits for a response from the remote processor through the SMD channel
+- Reads the message available from the shared memory SMD channel
+- Copies back from ION buffers to HLOS memory for output buffers
+- Returns the response of the remote invocation
+
+Design
+======
+
+The design goals of this transport mechanism are:
+- Fast and efficient ways to transfer huge buffers across
+ inter-processor boundaries
+- Zero copy of ION allocated buffers passed during invocations
+
+To achieve the zero copy approach of ION allocated user space buffers,
+the driver scatter-gathers the list of pages of the buffers being passed
+in. This information is then sent over to the remote processor for it
+to map into its address space.
+
+The invocation requests sent over the SMD channel carry context
+information as to whom the request is originating from. The responses
+received over the SMD channel have context information in the message
+which is then used to wake the thread waiting for a response.
+
+If the remote processor goes down and gets restarted, the SMD channel
+is re-initialized when the remote processor comes back up. An
+error code would be returned to the client for all invocations that
+happen before the SMD channel could get completely re-initialized.
+
+Power Management
+================
+
+None
+
+SMP/multi-core
+==============
+
+The driver uses semaphores to wake up clients waiting for a remote
+invocation response.
+
+Security
+========
+
+Use of the zero copy approach results in a page-size granularity of
+all buffers being passed to the remote processor. The objects that will
+be manipulating these buffers on the remote processor will be signed
+and trusted entities, thereby alleviating any fear of intentional
+scribbling of these buffers.
+
+Performance
+===========
+
+In order to minimize latencies across remote invocations:
+- messages exchanged between the remote processors are kept short
+- zero copy approach for ION allocated user space buffers
+
+Interface
+=========
+
+The driver exposes a user space interface through /dev/adsprpc-smd and
+the user space clients send commands to the driver by using the
+following ioctl command:
+
+- FASTRPC_IOCTL_INVOKE: Parameters passed in includes the buffers and
+ data related to remote invocation.
+
+ /*
+ * Information about the input/output buffer or an handle to the
+ * object being passed in the remote invocation
+ *
+ * @pv: Pointer to input/output buffer
+ * @len: Length of the input/output buffer
+ * @handle: Handle to the remote object
+ */
+ typedef union {
+ struct remote_buf {
+ void *pv;
+ int len;
+ } buf;
+ unsigned int handle;
+ } remote_arg;
+
+ /*
+ * Invocation parameters passed via ioctl call by the client
+ *
+ * @handle: Handle to the object on which the method is to be
+ * invoked
+ * @sc: Scalars detailing the parameters being passed in
+ * bits 0-3: Number of output handles
+ * bits 4-7: Number of input handles
+ * bits 8-15: Number of output buffers
+ * bits 16-23: Number of input buffers
+ * bits 24-28: Method to be invoked
+ * bits 29-31: Method attributes
+ * @pra: Remote arguments to be passed for method invocation
+ */
+ struct fastrpc_ioctl_invoke {
+ unsigned int handle;
+ unsigned int sc;
+ remote_arg *pra;
+ };
+
+Driver parameters
+=================
+
+None
+
+Config options
+==============
+
+None
+
+Dependencies
+============
+
+The ADSPRPC driver requires that the ADSP RPC SMD channel be created and
+the SMD subsystem be initialized. During initialization, the driver
+opens an existing SMD edge channel between ADSP and Apps processor. On
+success, the driver waits for the "channel opened" event from SMD,
+acknowledging the channel availability from the remote SMD driver for
+communication to begin.
+
+User space utilities
+====================
+
+None
+
+Other
+=====
+
+None
+
+Known issues
+============
+
+None
+
+To do
+=====
+
+None
diff --git a/Documentation/devicetree/bindings/platform/msm/qpnp-power-on.txt b/Documentation/devicetree/bindings/platform/msm/qpnp-power-on.txt
index 46b39ec..21d376a 100644
--- a/Documentation/devicetree/bindings/platform/msm/qpnp-power-on.txt
+++ b/Documentation/devicetree/bindings/platform/msm/qpnp-power-on.txt
@@ -13,7 +13,7 @@
- interrupts: Specifies the interrupt associated with PON.
Optional properties:
-- qcom,pon-dbc-delay: The debouce delay for the power-key interrupt
+- qcom,pon-dbc-delay The debouce delay for the power-key interrupt
specifed in us. The value ranges from 2 seconds
to 1/64 of a second. Possible values are -
- 2, 1, 1/2, 1/4, 1/8, 1/16, 1/32, 1/64
@@ -24,11 +24,15 @@
reset source. All the child nodes are optional,
if none of them are specified the driver fails
to register.
+- qcom,system-reset Specifies that this PON peripheral can be used
+ to reset the system. This property can only be
+ used by one device on the system. It is an error
+ to include it more than once.
All the below properties are in the sub-node section (properties of the child
node).
-- qcom,pull-up: The initial state of the reset pin under
+- qcom,pull-up The initial state of the reset pin under
consideration.
0 = No pull-up
1 = pull-up enabled
diff --git a/arch/arm/boot/dts/msm-pm8941.dtsi b/arch/arm/boot/dts/msm-pm8941.dtsi
index 0f5fd1c..facb1a8 100644
--- a/arch/arm/boot/dts/msm-pm8941.dtsi
+++ b/arch/arm/boot/dts/msm-pm8941.dtsi
@@ -30,6 +30,7 @@
<0x0 0x8 0x4>;
interrupt-names = "kpdpwr", "resin", "resin-bark";
qcom,pon-dbc-delay = <15625>;
+ qcom,system-reset;
qcom,pon_1 {
qcom,pon-type = <0>;
diff --git a/arch/arm/boot/dts/msm8974-gpio.dtsi b/arch/arm/boot/dts/msm8974-gpio.dtsi
index e7c742c..dac87a3 100644
--- a/arch/arm/boot/dts/msm8974-gpio.dtsi
+++ b/arch/arm/boot/dts/msm8974-gpio.dtsi
@@ -109,6 +109,13 @@
gpio@d200 {
status = "ok";
+ qcom,mode = <1>; /* QPNP_PIN_MODE_DIG_OUT */
+ qcom,output-type = <0>; /* QPNP_PIN_OUT_BUF_CMOS */
+ qcom,pull = <5>; /* QPNP_PIN_PULL_NO */
+ qcom,vin-sel = <2>; /* QPNP_PIN_VIN2 */
+ qcom,out-strength = <2>; /* QPNP_PIN_OUT_STRENGTH_MED */
+ qcom,src-select = <0>; /* QPNP_PIN_SEL_FUNC_CONSTANT */
+ qcom,master-en = <1>;
};
gpio@d300 {
diff --git a/arch/arm/configs/msm7627a-perf_defconfig b/arch/arm/configs/msm7627a-perf_defconfig
index 1b792d9..7f10641 100644
--- a/arch/arm/configs/msm7627a-perf_defconfig
+++ b/arch/arm/configs/msm7627a-perf_defconfig
@@ -283,6 +283,7 @@
CONFIG_ION=y
CONFIG_ION_MSM=y
CONFIG_MSM_KGSL=y
+CONFIG_MSM_KGSL_DISABLE_SHADOW_WRITES=y
CONFIG_FB=y
CONFIG_FB_MSM=y
# CONFIG_FB_MSM_BACKLIGHT is not set
diff --git a/arch/arm/configs/msm7627a_defconfig b/arch/arm/configs/msm7627a_defconfig
index aeb59af..0e0653f 100644
--- a/arch/arm/configs/msm7627a_defconfig
+++ b/arch/arm/configs/msm7627a_defconfig
@@ -285,6 +285,7 @@
CONFIG_ION=y
CONFIG_ION_MSM=y
CONFIG_MSM_KGSL=y
+CONFIG_MSM_KGSL_DISABLE_SHADOW_WRITES=y
CONFIG_FB=y
CONFIG_FB_MSM=y
# CONFIG_FB_MSM_BACKLIGHT is not set
diff --git a/arch/arm/configs/msm8960-perf_defconfig b/arch/arm/configs/msm8960-perf_defconfig
index db184cd..afe528d 100644
--- a/arch/arm/configs/msm8960-perf_defconfig
+++ b/arch/arm/configs/msm8960-perf_defconfig
@@ -391,6 +391,7 @@
CONFIG_FB_MSM_WRITEBACK_MSM_PANEL=y
CONFIG_FB_MSM_LVDS_MIPI_PANEL_DETECT=y
CONFIG_FB_MSM_HDMI_MSM_PANEL=y
+CONFIG_FB_MSM_HDMI_MHL_8334=y
CONFIG_BACKLIGHT_LCD_SUPPORT=y
CONFIG_BACKLIGHT_CLASS_DEVICE=y
CONFIG_SOUND=y
diff --git a/arch/arm/configs/msm8960_defconfig b/arch/arm/configs/msm8960_defconfig
index 5415425..4c9383d 100644
--- a/arch/arm/configs/msm8960_defconfig
+++ b/arch/arm/configs/msm8960_defconfig
@@ -394,6 +394,7 @@
CONFIG_FB_MSM_WRITEBACK_MSM_PANEL=y
CONFIG_FB_MSM_LVDS_MIPI_PANEL_DETECT=y
CONFIG_FB_MSM_HDMI_MSM_PANEL=y
+CONFIG_FB_MSM_HDMI_MHL_8334=y
CONFIG_BACKLIGHT_LCD_SUPPORT=y
CONFIG_BACKLIGHT_CLASS_DEVICE=y
CONFIG_SOUND=y
diff --git a/arch/arm/configs/msm8974_defconfig b/arch/arm/configs/msm8974_defconfig
index 471ecd9..10d2f4d 100644
--- a/arch/arm/configs/msm8974_defconfig
+++ b/arch/arm/configs/msm8974_defconfig
@@ -20,14 +20,18 @@
CONFIG_BLK_DEV_INITRD=y
CONFIG_RD_BZIP2=y
CONFIG_RD_LZMA=y
+CONFIG_CC_OPTIMIZE_FOR_SIZE=y
+CONFIG_PANIC_TIMEOUT=5
CONFIG_KALLSYMS_ALL=y
CONFIG_ASHMEM=y
CONFIG_EMBEDDED=y
CONFIG_PROFILING=y
-CONFIG_OPROFILE=m
+CONFIG_OPROFILE=y
+CONFIG_KPROBES=y
CONFIG_MODULES=y
CONFIG_MODULE_UNLOAD=y
CONFIG_MODULE_FORCE_UNLOAD=y
+CONFIG_MODVERSIONS=y
CONFIG_PARTITION_ADVANCED=y
CONFIG_EFI_PARTITION=y
CONFIG_ARCH_MSM=y
@@ -35,39 +39,41 @@
CONFIG_ARCH_MSM8226=y
CONFIG_MSM_KRAIT_TBB_ABORT_HANDLER=y
# CONFIG_MSM_STACKED_MEMORY is not set
-CONFIG_KERNEL_PMEM_EBI_REGION=y
CONFIG_CPU_HAS_L2_PMU=y
# 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_BAM_DMUX=y
CONFIG_MSM_IPC_ROUTER=y
CONFIG_MSM_IPC_ROUTER_SMD_XPRT=y
# CONFIG_MSM_HW3D is not set
+CONFIG_MSM_SUBSYSTEM_RESTART=y
CONFIG_MSM_PIL_LPASS_QDSP6V5=y
CONFIG_MSM_PIL_MSS_QDSP6V5=y
CONFIG_MSM_PIL_MBA=y
CONFIG_MSM_PIL_VENUS=y
CONFIG_MSM_PIL_PRONTO=y
-CONFIG_MSM_SUBSYSTEM_RESTART=y
CONFIG_MSM_MODEM_SSR_8974=y
CONFIG_MSM_ADSP_SSR_8974=y
CONFIG_MSM_TZ_LOG=y
CONFIG_MSM_DIRECT_SCLK_ACCESS=y
-CONFIG_MSM_QDSS=y
+CONFIG_MSM_BUS_SCALING=y
+CONFIG_MSM_WATCHDOG_V2=y
+CONFIG_MSM_MEMORY_DUMP=y
+CONFIG_MSM_DLOAD_MODE=y
+CONFIG_MSM_ADSP_LOADER=m
CONFIG_MSM_OCMEM=y
CONFIG_MSM_OCMEM_LOCAL_POWER_CTRL=y
CONFIG_MSM_OCMEM_DEBUG=y
CONFIG_MSM_OCMEM_NONSECURE=y
-CONFIG_MSM_MEMORY_DUMP=y
-CONFIG_MSM_WATCHDOG_V2=y
-CONFIG_MSM_DLOAD_MODE=y
-CONFIG_PANIC_TIMEOUT=5
CONFIG_MSM_CACHE_ERP=y
CONFIG_MSM_L1_ERR_PANIC=y
+CONFIG_MSM_L1_ERR_LOG=y
CONFIG_MSM_L2_ERP_PRINT_ACCESS_ERRORS=y
+CONFIG_MSM_L2_ERP_1BIT_PANIC=y
CONFIG_MSM_L2_ERP_2BIT_PANIC=y
-CONFIG_MSM_ADSP_LOADER=m
+CONFIG_STRICT_MEMORY_RWX=y
CONFIG_NO_HZ=y
CONFIG_HIGH_RES_TIMERS=y
CONFIG_SMP=y
@@ -77,6 +83,8 @@
CONFIG_AEABI=y
CONFIG_HIGHMEM=y
CONFIG_VMALLOC_RESERVE=0x19000000
+CONFIG_CC_STACKPROTECTOR=y
+CONFIG_CP_ACCESS=y
CONFIG_USE_OF=y
CONFIG_CPU_FREQ=y
CONFIG_CPU_FREQ_GOV_POWERSAVE=y
@@ -113,10 +121,100 @@
CONFIG_IPV6_MIP6=y
CONFIG_IPV6_MULTIPLE_TABLES=y
CONFIG_IPV6_SUBTREES=y
+CONFIG_NETFILTER=y
+CONFIG_NETFILTER_NETLINK_LOG=y
+CONFIG_NF_CONNTRACK=y
+CONFIG_NF_CONNTRACK_EVENTS=y
+CONFIG_NF_CT_PROTO_DCCP=y
+CONFIG_NF_CT_PROTO_SCTP=y
+CONFIG_NF_CT_PROTO_UDPLITE=y
+CONFIG_NF_CONNTRACK_AMANDA=y
+CONFIG_NF_CONNTRACK_FTP=y
+CONFIG_NF_CONNTRACK_H323=y
+CONFIG_NF_CONNTRACK_IRC=y
+CONFIG_NF_CONNTRACK_NETBIOS_NS=y
+CONFIG_NF_CONNTRACK_PPTP=y
+CONFIG_NF_CONNTRACK_SANE=y
+CONFIG_NF_CONNTRACK_SIP=y
+CONFIG_NF_CONNTRACK_TFTP=y
+CONFIG_NF_CT_NETLINK=y
+CONFIG_NETFILTER_TPROXY=y
+CONFIG_NETFILTER_XT_TARGET_CLASSIFY=y
+CONFIG_NETFILTER_XT_TARGET_CONNMARK=y
+CONFIG_NETFILTER_XT_TARGET_LOG=y
+CONFIG_NETFILTER_XT_TARGET_MARK=y
+CONFIG_NETFILTER_XT_TARGET_NFQUEUE=y
+CONFIG_NETFILTER_XT_MATCH_COMMENT=y
+CONFIG_NETFILTER_XT_MATCH_CONNLIMIT=y
+CONFIG_NETFILTER_XT_MATCH_CONNMARK=y
+CONFIG_NETFILTER_XT_MATCH_CONNTRACK=y
+CONFIG_NETFILTER_XT_MATCH_HASHLIMIT=y
+CONFIG_NETFILTER_XT_MATCH_HELPER=y
+CONFIG_NETFILTER_XT_MATCH_IPRANGE=y
+CONFIG_NETFILTER_XT_MATCH_LENGTH=y
+CONFIG_NETFILTER_XT_MATCH_LIMIT=y
+CONFIG_NETFILTER_XT_MATCH_MAC=y
+CONFIG_NETFILTER_XT_MATCH_MARK=y
+CONFIG_NETFILTER_XT_MATCH_MULTIPORT=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_QUOTA2=y
+CONFIG_NETFILTER_XT_MATCH_QUOTA2_LOG=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
+CONFIG_NETFILTER_XT_MATCH_TIME=y
+CONFIG_NETFILTER_XT_MATCH_U32=y
+CONFIG_NF_CONNTRACK_IPV4=y
+CONFIG_IP_NF_IPTABLES=y
+CONFIG_IP_NF_MATCH_AH=y
+CONFIG_IP_NF_MATCH_ECN=y
+CONFIG_IP_NF_MATCH_TTL=y
+CONFIG_IP_NF_FILTER=y
+CONFIG_IP_NF_TARGET_REJECT=y
+CONFIG_NF_NAT=y
+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_RAW=y
+CONFIG_IP_NF_ARPTABLES=y
+CONFIG_IP_NF_ARPFILTER=y
+CONFIG_IP_NF_ARP_MANGLE=y
+CONFIG_NF_CONNTRACK_IPV6=y
+CONFIG_IP6_NF_IPTABLES=y
+CONFIG_IP6_NF_FILTER=y
+CONFIG_IP6_NF_TARGET_REJECT=y
+CONFIG_IP6_NF_MANGLE=y
+CONFIG_IP6_NF_RAW=y
CONFIG_NET_SCHED=y
CONFIG_NET_SCH_HTB=y
CONFIG_NET_SCH_PRIO=y
CONFIG_NET_CLS_FW=y
+CONFIG_NET_CLS_U32=y
+CONFIG_CLS_U32_MARK=y
+CONFIG_NET_CLS_FLOW=y
+CONFIG_NET_EMATCH=y
+CONFIG_NET_EMATCH_CMP=y
+CONFIG_NET_EMATCH_NBYTE=y
+CONFIG_NET_EMATCH_U32=y
+CONFIG_NET_EMATCH_META=y
+CONFIG_NET_EMATCH_TEXT=y
+CONFIG_NET_CLS_ACT=y
+CONFIG_BT=y
+CONFIG_BT_RFCOMM=y
+CONFIG_BT_RFCOMM_TTY=y
+CONFIG_BT_BNEP=y
+CONFIG_BT_BNEP_MC_FILTER=y
+CONFIG_BT_BNEP_PROTO_FILTER=y
+CONFIG_BT_HIDP=y
+CONFIG_BT_HCISMD=y
+CONFIG_MSM_BT_POWER=y
+CONFIG_CFG80211=m
+CONFIG_RFKILL=y
CONFIG_GENLOCK=y
CONFIG_GENLOCK_MISCDEVICE=y
CONFIG_BLK_DEV_LOOP=y
@@ -136,15 +234,20 @@
CONFIG_DM_CRYPT=y
CONFIG_NETDEVICES=y
CONFIG_DUMMY=y
+CONFIG_TUN=y
CONFIG_KS8851=m
# CONFIG_MSM_RMNET is not set
CONFIG_MSM_RMNET_BAM=y
+CONFIG_SLIP=y
+CONFIG_SLIP_COMPRESSED=y
+CONFIG_SLIP_MODE_SLIP6=y
+CONFIG_WCNSS_CORE=y
+CONFIG_WCNSS_CORE_PRONTO=y
CONFIG_INPUT_EVDEV=y
CONFIG_INPUT_EVBUG=m
CONFIG_KEYBOARD_GPIO=y
CONFIG_INPUT_JOYSTICK=y
CONFIG_INPUT_TOUCHSCREEN=y
-CONFIG_TOUCHSCREEN_ATMEL_MAXTOUCH=n
CONFIG_TOUCHSCREEN_ATMEL_MXT=y
CONFIG_INPUT_MISC=y
CONFIG_INPUT_UINPUT=y
@@ -156,14 +259,12 @@
CONFIG_I2C=y
CONFIG_I2C_CHARDEV=y
CONFIG_I2C_QUP=y
-CONFIG_MSM_BUS_SCALING=y
CONFIG_SPI=y
CONFIG_SPI_QUP=y
CONFIG_SPI_SPIDEV=m
CONFIG_SPMI=y
CONFIG_SPMI_MSM_PMIC_ARB=y
CONFIG_MSM_QPNP_INT=y
-CONFIG_SLIMBUS=y
CONFIG_SLIMBUS_MSM_CTRL=y
CONFIG_DEBUG_GPIO=y
CONFIG_GPIO_SYSFS=y
@@ -171,11 +272,11 @@
CONFIG_GPIO_QPNP_PIN_DEBUG=y
CONFIG_POWER_SUPPLY=y
# CONFIG_BATTERY_MSM is not set
-CONFIG_HWMON=y
CONFIG_SENSORS_QPNP_ADC_VOLTAGE=y
CONFIG_SENSORS_QPNP_ADC_CURRENT=y
CONFIG_THERMAL=y
CONFIG_THERMAL_TSENS8974=y
+CONFIG_WCD9320_CODEC=y
CONFIG_REGULATOR_FIXED_VOLTAGE=y
CONFIG_REGULATOR_STUB=y
CONFIG_REGULATOR_QPNP=y
@@ -186,9 +287,10 @@
CONFIG_VIDEOBUF2_MSM_MEM=y
CONFIG_V4L_PLATFORM_DRIVERS=y
CONFIG_MSM_CAMERA_V4L2=y
+CONFIG_OV2720=y
CONFIG_MSM_CAMERA_SENSOR=y
CONFIG_MSM_ACTUATOR=y
-CONFIG_MSM_CAM_IRQ_ROUTER=n
+CONFIG_MSM_JPEG=y
CONFIG_MSM_CCI=y
CONFIG_MSM_CSI30_HEADER=y
CONFIG_MSM_CSIPHY=y
@@ -196,11 +298,8 @@
CONFIG_MSM_CSI2_REGISTER=y
CONFIG_MSM_ISPIF=y
CONFIG_S5K3L1YX=y
-CONFIG_OV2720=y
-CONFIG_MSM_JPEG=y
CONFIG_RADIO_IRIS=y
CONFIG_RADIO_IRIS_TRANSPORT=m
-CONFIG_RADIO_ADAPTERS=y
CONFIG_ION=y
CONFIG_ION_MSM=y
CONFIG_MSM_KGSL=y
@@ -218,7 +317,6 @@
CONFIG_SND=y
CONFIG_SND_SOC=y
CONFIG_SND_SOC_MSM8974=y
-CONFIG_WCD9320_CODEC=y
CONFIG_USB=y
CONFIG_USB_XHCI_HCD=y
CONFIG_USB_STORAGE=y
@@ -248,8 +346,6 @@
CONFIG_MMC_TEST=m
CONFIG_MMC_MSM=y
CONFIG_MMC_MSM_SPS_SUPPORT=y
-CONFIG_NEW_LEDS=y
-CONFIG_LEDS_CLASS=y
CONFIG_LEDS_QPNP=y
CONFIG_LEDS_TRIGGERS=y
CONFIG_LEDS_TRIGGER_BACKLIGHT=y
@@ -273,6 +369,7 @@
CONFIG_QPNP_POWER_ON=y
CONFIG_QPNP_CLKDIV=y
CONFIG_MSM_IOMMU=y
+CONFIG_MSM_QDSS=y
CONFIG_EXT2_FS=y
CONFIG_EXT2_FS_XATTR=y
CONFIG_EXT3_FS=y
@@ -286,48 +383,34 @@
CONFIG_NLS_ISO8859_1=y
CONFIG_PRINTK_TIME=y
CONFIG_MAGIC_SYSRQ=y
-CONFIG_DEBUG_FS=y
+CONFIG_LOCKUP_DETECTOR=y
+# CONFIG_DETECT_HUNG_TASK is not set
# CONFIG_SCHED_DEBUG is not set
CONFIG_TIMER_STATS=y
+CONFIG_DEBUG_KMEMLEAK=y
+CONFIG_DEBUG_KMEMLEAK_DEFAULT_OFF=y
# CONFIG_DEBUG_PREEMPT is not set
+CONFIG_DEBUG_SPINLOCK=y
+CONFIG_DEBUG_MUTEXES=y
+CONFIG_DEBUG_ATOMIC_SLEEP=y
+CONFIG_DEBUG_STACK_USAGE=y
CONFIG_DEBUG_INFO=y
CONFIG_DEBUG_MEMORY_INIT=y
+CONFIG_DEBUG_LIST=y
+CONFIG_FAULT_INJECTION=y
+CONFIG_FAIL_PAGE_ALLOC=y
+CONFIG_FAULT_INJECTION_DEBUG_FS=y
+CONFIG_FAULT_INJECTION_STACKTRACE_FILTER=y
+CONFIG_DEBUG_PAGEALLOC=y
CONFIG_ENABLE_DEFAULT_TRACERS=y
CONFIG_DYNAMIC_DEBUG=y
CONFIG_DEBUG_USER=y
+CONFIG_PID_IN_CONTEXTIDR=y
CONFIG_KEYS=y
CONFIG_CRYPTO_MD4=y
-CONFIG_CRYPTO_SHA256=y
-CONFIG_CRYPTO_AES=y
CONFIG_CRYPTO_ARC4=y
CONFIG_CRYPTO_TWOFISH=y
CONFIG_CRYPTO_DEV_QCRYPTO=m
CONFIG_CRYPTO_DEV_QCE=m
CONFIG_CRYPTO_DEV_QCEDEV=m
CONFIG_CRC_CCITT=y
-CONFIG_LIBCRC32C=y
-
-CONFIG_BT=y
-CONFIG_BT_L2CAP=y
-CONFIG_BT_SCO=y
-CONFIG_BT_RFCOMM=y
-CONFIG_BT_RFCOMM_TTY=y
-CONFIG_BT_BNEP=y
-CONFIG_BT_BNEP_MC_FILTER=y
-CONFIG_BT_BNEP_PROTO_FILTER=y
-CONFIG_BT_HIDP=y
-
-CONFIG_BT_HCISMD=y
-CONFIG_MSM_BT_POWER=y
-
-CONFIG_RADIO_IRIS=y
-CONFIG_RADIO_IRIS_TRANSPORT=m
-CONFIG_MSM_BAM_DMUX=y
-CONFIG_WCNSS_CORE=y
-CONFIG_WCNSS_CORE_PRONTO=y
-CONFIG_CFG80211=m
-CONFIG_RFKILL=y
-CONFIG_VIDEO_V4L2=y
-CONFIG_VIDEO_DEV=y
-CONFIG_VIDEO_V4L2_COMMON=y
-CONFIG_VIDEO_MEDIA=y
diff --git a/arch/arm/kernel/traps.c b/arch/arm/kernel/traps.c
index 63d402f..1e9504b 100644
--- a/arch/arm/kernel/traps.c
+++ b/arch/arm/kernel/traps.c
@@ -37,6 +37,8 @@
#include "signal.h"
+#include <trace/events/exception.h>
+
static const char *handler[]= { "prefetch abort", "data abort", "address exception", "interrupt" };
void *vectors_page;
@@ -410,6 +412,8 @@
if (call_undef_hook(regs, instr) == 0)
return;
+ trace_undef_instr(regs, (void *)pc);
+
#ifdef CONFIG_DEBUG_USER
if (user_debug & UDBG_UNDEFINED) {
printk(KERN_INFO "%s (%d): undefined instruction: pc=%p\n",
diff --git a/arch/arm/mach-msm/acpuclock-8064.c b/arch/arm/mach-msm/acpuclock-8064.c
index 3c80875..06c2579 100644
--- a/arch/arm/mach-msm/acpuclock-8064.c
+++ b/arch/arm/mach-msm/acpuclock-8064.c
@@ -219,7 +219,7 @@
.l2_freq_tbl = l2_freq_tbl,
.l2_freq_tbl_size = sizeof(l2_freq_tbl),
.bus_scale = &bus_scale_data,
- .qfprom_phys_base = 0x00700000,
+ .pte_efuse_phys = 0x007000C0,
.stby_khz = 384000,
};
diff --git a/arch/arm/mach-msm/acpuclock-8627.c b/arch/arm/mach-msm/acpuclock-8627.c
index 07a7f8f..9e6662d 100644
--- a/arch/arm/mach-msm/acpuclock-8627.c
+++ b/arch/arm/mach-msm/acpuclock-8627.c
@@ -138,7 +138,7 @@
.l2_freq_tbl = l2_freq_tbl,
.l2_freq_tbl_size = sizeof(l2_freq_tbl),
.bus_scale = &bus_scale_data,
- .qfprom_phys_base = 0x00700000,
+ .pte_efuse_phys = 0x007000C0,
.stby_khz = 384000,
};
diff --git a/arch/arm/mach-msm/acpuclock-8930.c b/arch/arm/mach-msm/acpuclock-8930.c
index 77876ee..b8ca865 100644
--- a/arch/arm/mach-msm/acpuclock-8930.c
+++ b/arch/arm/mach-msm/acpuclock-8930.c
@@ -221,7 +221,7 @@
.l2_freq_tbl = l2_freq_tbl,
.l2_freq_tbl_size = sizeof(l2_freq_tbl),
.bus_scale = &bus_scale_data,
- .qfprom_phys_base = 0x00700000,
+ .pte_efuse_phys = 0x007000C0,
.stby_khz = 384000,
};
diff --git a/arch/arm/mach-msm/acpuclock-8930aa.c b/arch/arm/mach-msm/acpuclock-8930aa.c
index dbc3e32..d589f1a 100644
--- a/arch/arm/mach-msm/acpuclock-8930aa.c
+++ b/arch/arm/mach-msm/acpuclock-8930aa.c
@@ -200,7 +200,7 @@
.l2_freq_tbl = l2_freq_tbl,
.l2_freq_tbl_size = sizeof(l2_freq_tbl),
.bus_scale = &bus_scale_data,
- .qfprom_phys_base = 0x00700000,
+ .pte_efuse_phys = 0x007000C0,
.stby_khz = 384000,
};
diff --git a/arch/arm/mach-msm/acpuclock-8960.c b/arch/arm/mach-msm/acpuclock-8960.c
index 0fccb64..e16c6b6 100644
--- a/arch/arm/mach-msm/acpuclock-8960.c
+++ b/arch/arm/mach-msm/acpuclock-8960.c
@@ -206,7 +206,7 @@
.l2_freq_tbl = l2_freq_tbl,
.l2_freq_tbl_size = sizeof(l2_freq_tbl),
.bus_scale = &bus_scale_data,
- .qfprom_phys_base = 0x00700000,
+ .pte_efuse_phys = 0x007000C0,
.stby_khz = 384000,
};
diff --git a/arch/arm/mach-msm/acpuclock-8960ab.c b/arch/arm/mach-msm/acpuclock-8960ab.c
index 63bff55..628e1ba 100644
--- a/arch/arm/mach-msm/acpuclock-8960ab.c
+++ b/arch/arm/mach-msm/acpuclock-8960ab.c
@@ -146,7 +146,7 @@
.l2_freq_tbl = l2_freq_tbl,
.l2_freq_tbl_size = sizeof(l2_freq_tbl),
.bus_scale = &bus_scale_data,
- .qfprom_phys_base = 0x00700000,
+ .pte_efuse_phys = 0x007000C0,
.stby_khz = 384000,
};
diff --git a/arch/arm/mach-msm/acpuclock-8974.c b/arch/arm/mach-msm/acpuclock-8974.c
index 16f77ba..ee2ca45 100644
--- a/arch/arm/mach-msm/acpuclock-8974.c
+++ b/arch/arm/mach-msm/acpuclock-8974.c
@@ -179,7 +179,7 @@
.l2_freq_tbl = l2_freq_tbl,
.l2_freq_tbl_size = sizeof(l2_freq_tbl),
.bus_scale = &bus_scale_data,
- .qfprom_phys_base = 0xFC4A8000,
+ .pte_efuse_phys = 0xFC4B80B0,
.stby_khz = 300000,
};
diff --git a/arch/arm/mach-msm/acpuclock-krait.c b/arch/arm/mach-msm/acpuclock-krait.c
index a487195..2951c1a 100644
--- a/arch/arm/mach-msm/acpuclock-krait.c
+++ b/arch/arm/mach-msm/acpuclock-krait.c
@@ -45,9 +45,6 @@
#define SEC_SRC_SEL_L2PLL 1
#define SEC_SRC_SEL_AUX 2
-/* PTE EFUSE register offset. */
-#define PTE_EFUSE 0xC0
-
static DEFINE_MUTEX(driver_lock);
static DEFINE_SPINLOCK(l2_lock);
@@ -946,20 +943,20 @@
}
}
-static int __init select_freq_plan(u32 qfprom_phys)
+static int __init select_freq_plan(u32 pte_efuse_phys)
{
- void __iomem *qfprom_base;
- u32 pte_efuse, pvs, tbl_idx;
+ void __iomem *pte_efuse;
+ u32 pte_efuse_val, pvs, tbl_idx;
char *pvs_names[] = { "Slow", "Nominal", "Fast", "Faster", "Unknown" };
- qfprom_base = ioremap(qfprom_phys, SZ_256);
+ pte_efuse = ioremap(pte_efuse_phys, 4);
/* Select frequency tables. */
- if (qfprom_base) {
- pte_efuse = readl_relaxed(qfprom_base + PTE_EFUSE);
- pvs = (pte_efuse >> 10) & 0x7;
- iounmap(qfprom_base);
+ if (pte_efuse) {
+ pte_efuse_val = readl_relaxed(pte_efuse);
+ pvs = (pte_efuse_val >> 10) & 0x7;
+ iounmap(pte_efuse);
if (pvs == 0x7)
- pvs = (pte_efuse >> 13) & 0x7;
+ pvs = (pte_efuse_val >> 13) & 0x7;
switch (pvs) {
case 0x0:
@@ -1020,7 +1017,7 @@
GFP_KERNEL);
BUG_ON(!drv.bus_scale->usecase);
- tbl_idx = select_freq_plan(params->qfprom_phys_base);
+ tbl_idx = select_freq_plan(params->pte_efuse_phys);
drv.acpu_freq_tbl = kmemdup(params->pvs_tables[tbl_idx].table,
params->pvs_tables[tbl_idx].size,
GFP_KERNEL);
diff --git a/arch/arm/mach-msm/acpuclock-krait.h b/arch/arm/mach-msm/acpuclock-krait.h
index 352fef8..d615b85 100644
--- a/arch/arm/mach-msm/acpuclock-krait.h
+++ b/arch/arm/mach-msm/acpuclock-krait.h
@@ -240,7 +240,7 @@
* @pvs_tables: CPU frequency tables.
* @l2_freq_tbl: L2 frequency table.
* @l2_freq_tbl_size: Size of @l2_freq_tbl.
- * @qfprom_phys_base: Physical base address of QFPROM.
+ * @pte_efuse_phys: Physical address of PTE EFUSE.
* @bus_scale: MSM bus driver parameters.
* @stby_khz: KHz value corresponding to an always-on clock source.
*/
@@ -251,7 +251,7 @@
struct pvs_table *pvs_tables;
struct l2_level *l2_freq_tbl;
size_t l2_freq_tbl_size;
- phys_addr_t qfprom_phys_base;
+ phys_addr_t pte_efuse_phys;
struct msm_bus_scale_pdata *bus_scale;
unsigned long stby_khz;
};
diff --git a/arch/arm/mach-msm/board-8064-regulator.c b/arch/arm/mach-msm/board-8064-regulator.c
index bbb9a81..6cdafbc 100644
--- a/arch/arm/mach-msm/board-8064-regulator.c
+++ b/arch/arm/mach-msm/board-8064-regulator.c
@@ -189,6 +189,7 @@
REGULATOR_SUPPLY("vcc_i2c", "3-0024"),
REGULATOR_SUPPLY("vddp", "0-0048"),
REGULATOR_SUPPLY("hdmi_lvl_tsl", "hdmi_msm.0"),
+ REGULATOR_SUPPLY("vdd-io", "spi0.2"),
};
VREG_CONSUMERS(S5) = {
REGULATOR_SUPPLY("8921_s5", NULL),
@@ -252,7 +253,7 @@
};
VREG_CONSUMERS(EXT_3P3V) = {
REGULATOR_SUPPLY("ext_3p3v", NULL),
- REGULATOR_SUPPLY("vdd_io", "spi0.2"),
+ REGULATOR_SUPPLY("vdd-phy", "spi0.2"),
REGULATOR_SUPPLY("mhl_usb_hs_switch", "msm_otg"),
REGULATOR_SUPPLY("lvds_vccs_3p3v", "lvds.0"),
REGULATOR_SUPPLY("dsi1_vccs_3p3v", "mipi_dsi.1"),
diff --git a/arch/arm/mach-msm/clock-8960.c b/arch/arm/mach-msm/clock-8960.c
index 01bc9dd..6ddb462 100644
--- a/arch/arm/mach-msm/clock-8960.c
+++ b/arch/arm/mach-msm/clock-8960.c
@@ -6430,16 +6430,16 @@
is_pll_enabled = readl_relaxed(BB_PLL14_STATUS_REG) & BIT(16);
if (!is_pll_enabled)
/* Ref clk = 27MHz and program pll14 to 480MHz */
- configure_pll(&pll14_config, &pll14_regs, 1);
+ configure_sr_pll(&pll14_config, &pll14_regs, 1);
/* Program PLL15 to 975MHz with ref clk = 27MHz */
- configure_pll(&pll15_config, &pll15_regs, 0);
+ configure_sr_pll(&pll15_config, &pll15_regs, 0);
/* Check if PLL4 is active */
is_pll_enabled = readl_relaxed(LCC_PLL0_STATUS_REG) & BIT(16);
if (!is_pll_enabled)
/* Ref clk = 27MHz and program pll4 to 393.2160MHz */
- configure_pll(&pll4_config_393, &pll4_regs, 1);
+ configure_sr_pll(&pll4_config_393, &pll4_regs, 1);
/* Enable PLL4 source on the LPASS Primary PLL Mux */
writel_relaxed(0x1, LCC_PRI_PLL_CLK_CTL_REG);
@@ -6457,7 +6457,7 @@
pll15_config.l = 0x21 | BVAL(31, 7, 0x600);
pll15_config.m = 0x1;
pll15_config.n = 0x3;
- configure_pll(&pll15_config, &pll15_regs, 0);
+ configure_sr_pll(&pll15_config, &pll15_regs, 0);
/* Disable AUX and BIST outputs */
writel_relaxed(0, MM_PLL3_TEST_CTL_REG);
}
diff --git a/arch/arm/mach-msm/clock-8974.c b/arch/arm/mach-msm/clock-8974.c
index b054e08..62e8f0f 100644
--- a/arch/arm/mach-msm/clock-8974.c
+++ b/arch/arm/mach-msm/clock-8974.c
@@ -5594,16 +5594,16 @@
if (!(readl_relaxed(GCC_REG_BASE(GPLL0_STATUS_REG))
& gpll0_clk_src.status_mask))
- configure_pll(&gpll0_config, &gpll0_regs, 1);
+ configure_sr_hpm_lp_pll(&gpll0_config, &gpll0_regs, 1);
if (!(readl_relaxed(GCC_REG_BASE(GPLL1_STATUS_REG))
& gpll1_clk_src.status_mask))
- configure_pll(&gpll1_config, &gpll1_regs, 1);
+ configure_sr_hpm_lp_pll(&gpll1_config, &gpll1_regs, 1);
- configure_pll(&mmpll0_config, &mmpll0_regs, 1);
- configure_pll(&mmpll1_config, &mmpll1_regs, 1);
- configure_pll(&mmpll3_config, &mmpll3_regs, 0);
- configure_pll(&lpapll0_config, &lpapll0_regs, 1);
+ configure_sr_hpm_lp_pll(&mmpll0_config, &mmpll0_regs, 1);
+ configure_sr_hpm_lp_pll(&mmpll1_config, &mmpll1_regs, 1);
+ configure_sr_hpm_lp_pll(&mmpll3_config, &mmpll3_regs, 0);
+ configure_sr_hpm_lp_pll(&lpapll0_config, &lpapll0_regs, 1);
/* Enable GPLL0's aux outputs. */
regval = readl_relaxed(GCC_REG_BASE(GPLL0_USER_CTL_REG));
@@ -5769,7 +5769,7 @@
if (!virt_bases[APCS_BASE])
panic("clock-8974: Unable to ioremap APCS_GCC_CC memory!");
- clk_ops_local_pll.enable = msm8974_pll_clk_enable;
+ clk_ops_local_pll.enable = sr_hpm_lp_pll_clk_enable;
vdd_dig_reg = rpm_regulator_get(NULL, "vdd_dig");
if (IS_ERR(vdd_dig_reg))
diff --git a/arch/arm/mach-msm/clock-9615.c b/arch/arm/mach-msm/clock-9615.c
index 648a8d4..15eaa4b 100644
--- a/arch/arm/mach-msm/clock-9615.c
+++ b/arch/arm/mach-msm/clock-9615.c
@@ -1807,14 +1807,14 @@
regval |= BIT(12);
writel_relaxed(regval, BB_PLL0_TEST_CTL_REG);
- configure_pll(&pll0_config, &pll0_regs, 1);
+ configure_sr_pll(&pll0_config, &pll0_regs, 1);
}
/* Check if PLL14 is enabled in FSM mode */
is_pll_enabled = readl_relaxed(BB_PLL14_STATUS_REG) & BIT(16);
if (!is_pll_enabled)
- configure_pll(&pll14_config, &pll14_regs, 1);
+ configure_sr_pll(&pll14_config, &pll14_regs, 1);
else if (!(readl_relaxed(BB_PLL14_MODE_REG) & BIT(20)))
WARN(1, "PLL14 enabled in non-FSM mode!\n");
diff --git a/arch/arm/mach-msm/clock-local2.c b/arch/arm/mach-msm/clock-local2.c
index 3f19b2a..2beb990 100644
--- a/arch/arm/mach-msm/clock-local2.c
+++ b/arch/arm/mach-msm/clock-local2.c
@@ -474,10 +474,10 @@
if (branch->has_sibling == 1)
return -ENXIO;
- if (branch->parent)
- return rcg_clk_list_rate(branch->parent, n);
+ if (branch->parent && branch->parent->ops->list_rate)
+ return branch->parent->ops->list_rate(branch->parent, n);
else
- return 0;
+ return -ENXIO;
}
static enum handoff branch_clk_handoff(struct clk *c)
diff --git a/arch/arm/mach-msm/clock-pll.c b/arch/arm/mach-msm/clock-pll.c
index d5831e2..23941d7 100644
--- a/arch/arm/mach-msm/clock-pll.c
+++ b/arch/arm/mach-msm/clock-pll.c
@@ -247,7 +247,7 @@
#define PLL_LOCKED_BIT BIT(16)
-int msm8974_pll_clk_enable(struct clk *c)
+int sr_hpm_lp_pll_clk_enable(struct clk *c)
{
unsigned long flags;
struct pll_clk *pll = to_pll_clk(c);
@@ -255,23 +255,12 @@
int ret = 0;
spin_lock_irqsave(&pll_reg_lock, flags);
- mode = readl_relaxed(PLL_MODE_REG(pll));
- /* Disable PLL bypass mode. */
- mode |= PLL_BYPASSNL;
+
+ /* Disable PLL bypass mode and de-assert reset. */
+ mode = PLL_BYPASSNL | PLL_RESET_N;
writel_relaxed(mode, PLL_MODE_REG(pll));
- /*
- * H/W requires a 5us delay between disabling the bypass and
- * de-asserting the reset. Delay 10us just to be safe.
- */
- mb();
- udelay(10);
-
- /* De-assert active-low PLL reset. */
- mode |= PLL_RESET_N;
- writel_relaxed(mode, PLL_MODE_REG(pll));
-
- /* Wait for pll to enable. */
+ /* Wait for pll to lock. */
for (count = ENABLE_WAIT_MAX_LOOPS; count > 0; count--) {
if (readl_relaxed(PLL_STATUS_REG(pll)) & PLL_LOCKED_BIT)
break;
@@ -453,7 +442,8 @@
.is_enabled = pll_clk_is_enabled,
};
-static void __init __set_fsm_mode(void __iomem *mode_reg)
+static void __init __set_fsm_mode(void __iomem *mode_reg,
+ u32 bias_count, u32 lock_count)
{
u32 regval = readl_relaxed(mode_reg);
@@ -463,12 +453,12 @@
/* Program bias count */
regval &= ~BM(19, 14);
- regval |= BVAL(19, 14, 0x1);
+ regval |= BVAL(19, 14, bias_count);
writel_relaxed(regval, mode_reg);
/* Program lock count */
regval &= ~BM(13, 8);
- regval |= BVAL(13, 8, 0x8);
+ regval |= BVAL(13, 8, lock_count);
writel_relaxed(regval, mode_reg);
/* Enable PLL FSM voting */
@@ -476,7 +466,7 @@
writel_relaxed(regval, mode_reg);
}
-void __init configure_pll(struct pll_config *config,
+void __init __configure_pll(struct pll_config *config,
struct pll_config_regs *regs, u32 ena_fsm_mode)
{
u32 regval;
@@ -509,8 +499,21 @@
regval &= ~config->vco_mask;
regval |= config->vco_val;
writel_relaxed(regval, PLL_CONFIG_REG(regs));
-
- /* Configure in FSM mode if necessary */
- if (ena_fsm_mode)
- __set_fsm_mode(PLL_MODE_REG(regs));
}
+
+void __init configure_sr_pll(struct pll_config *config,
+ struct pll_config_regs *regs, u32 ena_fsm_mode)
+{
+ __configure_pll(config, regs, ena_fsm_mode);
+ if (ena_fsm_mode)
+ __set_fsm_mode(PLL_MODE_REG(regs), 0x1, 0x8);
+}
+
+void __init configure_sr_hpm_lp_pll(struct pll_config *config,
+ struct pll_config_regs *regs, u32 ena_fsm_mode)
+{
+ __configure_pll(config, regs, ena_fsm_mode);
+ if (ena_fsm_mode)
+ __set_fsm_mode(PLL_MODE_REG(regs), 0x1, 0x0);
+}
+
diff --git a/arch/arm/mach-msm/clock-pll.h b/arch/arm/mach-msm/clock-pll.h
index 90f8a95..30f595b 100644
--- a/arch/arm/mach-msm/clock-pll.h
+++ b/arch/arm/mach-msm/clock-pll.h
@@ -111,7 +111,7 @@
}
int sr_pll_clk_enable(struct clk *c);
-int msm8974_pll_clk_enable(struct clk *c);
+int sr_hpm_lp_pll_clk_enable(struct clk *c);
/*
* PLL vote clock APIs
@@ -146,6 +146,8 @@
void *const __iomem *base;
};
-void __init configure_pll(struct pll_config *, struct pll_config_regs *, u32);
-
+void configure_sr_pll(struct pll_config *config, struct pll_config_regs *regs,
+ u32 ena_fsm_mode);
+void configure_sr_hpm_lp_pll(struct pll_config *config,
+ struct pll_config_regs *, u32 ena_fsm_mode);
#endif
diff --git a/arch/arm/mach-msm/cpufreq.c b/arch/arm/mach-msm/cpufreq.c
index 05bd56ef..6c9b413 100644
--- a/arch/arm/mach-msm/cpufreq.c
+++ b/arch/arm/mach-msm/cpufreq.c
@@ -32,19 +32,6 @@
#include "acpuclock.h"
-#ifdef CONFIG_SMP
-struct cpufreq_work_struct {
- struct work_struct work;
- struct cpufreq_policy *policy;
- struct completion complete;
- int frequency;
- int status;
-};
-
-static DEFINE_PER_CPU(struct cpufreq_work_struct, cpufreq_work);
-static struct workqueue_struct *msm_cpufreq_wq;
-#endif
-
struct cpufreq_suspend_t {
struct mutex suspend_mutex;
int device_suspended;
@@ -91,45 +78,6 @@
return ret;
}
-#ifdef CONFIG_SMP
-static int __cpuinit msm_cpufreq_cpu_callback(struct notifier_block *nfb,
- unsigned long action, void *hcpu)
-{
- unsigned int cpu = (unsigned long)hcpu;
-
- switch (action) {
- case CPU_ONLINE:
- case CPU_ONLINE_FROZEN:
- per_cpu(cpufreq_suspend, cpu).device_suspended = 0;
- break;
- case CPU_DOWN_PREPARE:
- case CPU_DOWN_PREPARE_FROZEN:
- mutex_lock(&per_cpu(cpufreq_suspend, cpu).suspend_mutex);
- per_cpu(cpufreq_suspend, cpu).device_suspended = 1;
- mutex_unlock(&per_cpu(cpufreq_suspend, cpu).suspend_mutex);
- break;
- case CPU_DOWN_FAILED:
- case CPU_DOWN_FAILED_FROZEN:
- per_cpu(cpufreq_suspend, cpu).device_suspended = 0;
- break;
- }
- return NOTIFY_OK;
-}
-
-static struct notifier_block __refdata msm_cpufreq_cpu_notifier = {
- .notifier_call = msm_cpufreq_cpu_callback,
-};
-
-static void set_cpu_work(struct work_struct *work)
-{
- struct cpufreq_work_struct *cpu_work =
- container_of(work, struct cpufreq_work_struct, work);
-
- cpu_work->status = set_cpu_freq(cpu_work->policy, cpu_work->frequency);
- complete(&cpu_work->complete);
-}
-#endif
-
static int msm_cpufreq_target(struct cpufreq_policy *policy,
unsigned int target_freq,
unsigned int relation)
@@ -137,19 +85,12 @@
int ret = -EFAULT;
int index;
struct cpufreq_frequency_table *table;
-#ifdef CONFIG_SMP
- struct cpufreq_work_struct *cpu_work = NULL;
- cpumask_var_t mask;
if (!cpu_active(policy->cpu)) {
pr_info("cpufreq: cpu %d is not active.\n", policy->cpu);
return -ENODEV;
}
- if (!alloc_cpumask_var(&mask, GFP_KERNEL))
- return -ENOMEM;
-#endif
-
mutex_lock(&per_cpu(cpufreq_suspend, policy->cpu).suspend_mutex);
if (per_cpu(cpufreq_suspend, policy->cpu).device_suspended) {
@@ -167,39 +108,13 @@
goto done;
}
-#ifdef CONFIG_CPU_FREQ_DEBUG
pr_debug("CPU[%d] target %d relation %d (%d-%d) selected %d\n",
policy->cpu, target_freq, relation,
policy->min, policy->max, table[index].frequency);
-#endif
-#ifdef CONFIG_SMP
- cpu_work = &per_cpu(cpufreq_work, policy->cpu);
- cpu_work->policy = policy;
- cpu_work->frequency = table[index].frequency;
- cpu_work->status = -ENODEV;
-
- cpumask_clear(mask);
- cpumask_set_cpu(policy->cpu, mask);
- if (cpumask_equal(mask, ¤t->cpus_allowed)) {
- ret = set_cpu_freq(cpu_work->policy, cpu_work->frequency);
- goto done;
- } else {
- cancel_work_sync(&cpu_work->work);
- INIT_COMPLETION(cpu_work->complete);
- queue_work_on(policy->cpu, msm_cpufreq_wq, &cpu_work->work);
- wait_for_completion(&cpu_work->complete);
- }
-
- ret = cpu_work->status;
-#else
ret = set_cpu_freq(policy, table[index].frequency);
-#endif
done:
-#ifdef CONFIG_SMP
- free_cpumask_var(mask);
-#endif
mutex_unlock(&per_cpu(cpufreq_suspend, policy->cpu).suspend_mutex);
return ret;
}
@@ -282,10 +197,6 @@
int cur_freq;
int index;
struct cpufreq_frequency_table *table;
-#ifdef CONFIG_SMP
- struct cpufreq_work_struct *cpu_work = NULL;
-#endif
-
table = cpufreq_frequency_get_table(policy->cpu);
if (table == NULL)
@@ -314,7 +225,7 @@
CPUFREQ_RELATION_H, &index) &&
cpufreq_frequency_table_target(policy, table, cur_freq,
CPUFREQ_RELATION_L, &index)) {
- pr_info("cpufreq: cpu%d at invalid freq: %d\n",
+ pr_info("%s: cpu%d at invalid freq: %d\n", __func__,
policy->cpu, cur_freq);
return -EINVAL;
}
@@ -334,15 +245,39 @@
policy->cpuinfo.transition_latency =
acpuclk_get_switch_time() * NSEC_PER_USEC;
-#ifdef CONFIG_SMP
- cpu_work = &per_cpu(cpufreq_work, policy->cpu);
- INIT_WORK(&cpu_work->work, set_cpu_work);
- init_completion(&cpu_work->complete);
-#endif
return 0;
}
+static int __cpuinit msm_cpufreq_cpu_callback(struct notifier_block *nfb,
+ unsigned long action, void *hcpu)
+{
+ unsigned int cpu = (unsigned long)hcpu;
+
+ switch (action) {
+ case CPU_ONLINE:
+ case CPU_ONLINE_FROZEN:
+ per_cpu(cpufreq_suspend, cpu).device_suspended = 0;
+ break;
+ case CPU_DOWN_PREPARE:
+ case CPU_DOWN_PREPARE_FROZEN:
+ mutex_lock(&per_cpu(cpufreq_suspend, cpu).suspend_mutex);
+ per_cpu(cpufreq_suspend, cpu).device_suspended = 1;
+ mutex_unlock(&per_cpu(cpufreq_suspend, cpu).suspend_mutex);
+ break;
+ case CPU_DOWN_FAILED:
+ case CPU_DOWN_FAILED_FROZEN:
+ per_cpu(cpufreq_suspend, cpu).device_suspended = 0;
+ break;
+ }
+
+ return NOTIFY_OK;
+}
+
+static struct notifier_block __refdata msm_cpufreq_cpu_notifier = {
+ .notifier_call = msm_cpufreq_cpu_callback,
+};
+
static int msm_cpufreq_suspend(void)
{
int cpu;
@@ -382,6 +317,10 @@
}
}
+static struct notifier_block msm_cpufreq_pm_notifier = {
+ .notifier_call = msm_cpufreq_pm_event,
+};
+
static struct freq_attr *msm_freq_attr[] = {
&cpufreq_freq_attr_scaling_available_freqs,
NULL,
@@ -398,10 +337,6 @@
.attr = msm_freq_attr,
};
-static struct notifier_block msm_cpufreq_pm_notifier = {
- .notifier_call = msm_cpufreq_pm_event,
-};
-
static int __init msm_cpufreq_register(void)
{
int cpu;
@@ -411,10 +346,7 @@
per_cpu(cpufreq_suspend, cpu).device_suspended = 0;
}
-#ifdef CONFIG_SMP
- msm_cpufreq_wq = create_workqueue("msm-cpufreq");
register_hotcpu_notifier(&msm_cpufreq_cpu_notifier);
-#endif
register_pm_notifier(&msm_cpufreq_pm_notifier);
return cpufreq_register_driver(&msm_cpufreq_driver);
diff --git a/arch/arm/mach-msm/include/mach/msm_iomap-9625.h b/arch/arm/mach-msm/include/mach/msm_iomap-9625.h
index 493cf36..eecdd67 100644
--- a/arch/arm/mach-msm/include/mach/msm_iomap-9625.h
+++ b/arch/arm/mach-msm/include/mach/msm_iomap-9625.h
@@ -23,7 +23,7 @@
*
*/
-#define MSM9625_SHARED_RAM_PHYS 0x18D00000
+#define MSM9625_SHARED_RAM_PHYS 0x00000000
#define MSM9625_APCS_GCC_PHYS 0xF9011000
#define MSM9625_APCS_GCC_SIZE SZ_4K
diff --git a/arch/arm/mach-msm/include/mach/msm_iomap.h b/arch/arm/mach-msm/include/mach/msm_iomap.h
index 21bea4f..6f925d4 100644
--- a/arch/arm/mach-msm/include/mach/msm_iomap.h
+++ b/arch/arm/mach-msm/include/mach/msm_iomap.h
@@ -105,7 +105,7 @@
#if defined(CONFIG_ARCH_MSM9615) || defined(CONFIG_ARCH_MSM7X27) \
- || defined(CONFIG_ARCH_MSM7X30)
+ || defined(CONFIG_ARCH_MSM7X30) || defined(CONFIG_ARCH_MSM9625)
#define MSM_SHARED_RAM_SIZE SZ_1M
#else
#define MSM_SHARED_RAM_SIZE SZ_2M
diff --git a/arch/arm/mach-msm/lpm_levels.c b/arch/arm/mach-msm/lpm_levels.c
index f7456ef..8218a42 100644
--- a/arch/arm/mach-msm/lpm_levels.c
+++ b/arch/arm/mach-msm/lpm_levels.c
@@ -92,8 +92,8 @@
}
static void *msm_lpm_lowest_limits(bool from_idle,
- enum msm_pm_sleep_mode sleep_mode, uint32_t latency_us,
- uint32_t sleep_us, uint32_t *power)
+ enum msm_pm_sleep_mode sleep_mode,
+ struct msm_pm_time_params *time_param, uint32_t *power)
{
unsigned int cpu = smp_processor_id();
struct msm_rpmrs_level *best_level = NULL;
@@ -114,20 +114,22 @@
if (sleep_mode != level->sleep_mode)
continue;
- if (latency_us < level->latency_us)
+ if (time_param->latency_us < level->latency_us)
continue;
- if (sleep_us <= 1) {
+ if (time_param->sleep_us <= 1) {
pwr = level->energy_overhead;
- } else if (sleep_us <= level->time_overhead_us) {
- pwr = level->energy_overhead / sleep_us;
- } else if ((sleep_us >> 10) > level->time_overhead_us) {
+ } else if (time_param->sleep_us <= level->time_overhead_us) {
+ pwr = level->energy_overhead / time_param->sleep_us;
+ } else if ((time_param->sleep_us >> 10)
+ > level->time_overhead_us) {
pwr = level->steady_state_power;
} else {
pwr = level->steady_state_power;
pwr -= (level->time_overhead_us *
- level->steady_state_power)/sleep_us;
- pwr += level->energy_overhead / sleep_us;
+ level->steady_state_power) /
+ time_param->sleep_us;
+ pwr += level->energy_overhead / time_param->sleep_us;
}
if (!best_level || best_level->rs_limits.power[cpu] >= pwr) {
diff --git a/arch/arm/mach-msm/pil-riva.c b/arch/arm/mach-msm/pil-riva.c
index ba0e242..3040a31 100644
--- a/arch/arm/mach-msm/pil-riva.c
+++ b/arch/arm/mach-msm/pil-riva.c
@@ -21,7 +21,6 @@
#include <linux/regulator/consumer.h>
#include <linux/clk.h>
-#include <asm/mach-types.h>
#include <mach/msm_iomap.h>
#include "peripheral-loader.h"
@@ -359,18 +358,12 @@
static int __init pil_riva_init(void)
{
- if (machine_is_mpq8064_hrd()) {
- pr_err("pil_riva not supported on this target\n");
- return 0;
- }
return platform_driver_register(&pil_riva_driver);
}
module_init(pil_riva_init);
static void __exit pil_riva_exit(void)
{
- if (machine_is_mpq8064_hrd())
- return;
platform_driver_unregister(&pil_riva_driver);
}
module_exit(pil_riva_exit);
diff --git a/arch/arm/mach-msm/pm-8x60.c b/arch/arm/mach-msm/pm-8x60.c
index dbb23d5..60ee8f0 100644
--- a/arch/arm/mach-msm/pm-8x60.c
+++ b/arch/arm/mach-msm/pm-8x60.c
@@ -49,6 +49,7 @@
#include "spm.h"
#include "timer.h"
#include "pm-boot.h"
+#include <mach/event_timer.h>
/******************************************************************************
* Debug Definitions
@@ -112,6 +113,7 @@
"standalone_power_collapse",
};
+static struct hrtimer pm_hrtimer;
static struct msm_pm_sleep_ops pm_sleep_ops;
/*
* Write out the attribute.
@@ -645,6 +647,28 @@
return time;
}
+/**
+ * pm_hrtimer_cb() : Callback function for hrtimer created if the
+ * core needs to be awake to handle an event.
+ * @hrtimer : Pointer to hrtimer
+ */
+static enum hrtimer_restart pm_hrtimer_cb(struct hrtimer *hrtimer)
+{
+ return HRTIMER_NORESTART;
+}
+
+/**
+ * msm_pm_set_timer() : Set an hrtimer to wakeup the core in time
+ * to handle an event.
+ */
+static void msm_pm_set_timer(uint32_t modified_time_us)
+{
+ u64 modified_time_ns = modified_time_us * NSEC_PER_USEC;
+ ktime_t modified_ktime = ns_to_ktime(modified_time_ns);
+ pm_hrtimer.function = pm_hrtimer_cb;
+ hrtimer_start(&pm_hrtimer, modified_ktime, HRTIMER_MODE_ABS);
+}
+
/******************************************************************************
* External Idle/Suspend Functions
*****************************************************************************/
@@ -657,15 +681,25 @@
int msm_pm_idle_prepare(struct cpuidle_device *dev,
struct cpuidle_driver *drv, int index)
{
- uint32_t latency_us;
- uint32_t sleep_us;
int i;
unsigned int power_usage = -1;
int ret = 0;
+ uint32_t modified_time_us = 0;
+ struct msm_pm_time_params time_param;
- latency_us = (uint32_t) pm_qos_request(PM_QOS_CPU_DMA_LATENCY);
- sleep_us = (uint32_t) ktime_to_ns(tick_nohz_get_sleep_length());
- sleep_us = DIV_ROUND_UP(sleep_us, 1000);
+ time_param.latency_us =
+ (uint32_t) pm_qos_request(PM_QOS_CPU_DMA_LATENCY);
+ time_param.sleep_us =
+ (uint32_t) (ktime_to_us(tick_nohz_get_sleep_length())
+ & UINT_MAX);
+ time_param.modified_time_us = 0;
+
+ if (!dev->cpu)
+ time_param.next_event_us =
+ (uint32_t) (ktime_to_us(get_next_event_time())
+ & UINT_MAX);
+ else
+ time_param.next_event_us = 0;
for (i = 0; i < dev->state_count; i++) {
struct cpuidle_state *state = &drv->states[i];
@@ -702,17 +736,18 @@
case MSM_PM_SLEEP_MODE_WAIT_FOR_INTERRUPT:
if (!allow)
break;
+ /* fall through */
if (pm_sleep_ops.lowest_limits)
rs_limits = pm_sleep_ops.lowest_limits(true,
- mode, latency_us, sleep_us,
- &power);
+ mode, &time_param, &power);
if (MSM_PM_DEBUG_IDLE & msm_pm_debug_mask)
pr_info("CPU%u: %s: %s, latency %uus, "
"sleep %uus, limit %p\n",
dev->cpu, __func__, state->desc,
- latency_us, sleep_us, rs_limits);
+ time_param.latency_us,
+ time_param.sleep_us, rs_limits);
if (!rs_limits)
allow = false;
@@ -730,6 +765,7 @@
if (allow) {
if (power < power_usage) {
power_usage = power;
+ modified_time_us = time_param.modified_time_us;
ret = mode;
}
@@ -738,6 +774,8 @@
}
}
+ if (modified_time_us && !dev->cpu)
+ msm_pm_set_timer(modified_time_us);
return ret;
}
@@ -850,6 +888,11 @@
int i;
int64_t period = 0;
int64_t time = msm_pm_timer_enter_suspend(&period);
+ struct msm_pm_time_params time_param;
+
+ time_param.latency_us = -1;
+ time_param.sleep_us = -1;
+ time_param.next_event_us = 0;
if (MSM_PM_DEBUG_SUSPEND & msm_pm_debug_mask)
pr_info("%s\n", __func__);
@@ -887,8 +930,7 @@
#endif /* CONFIG_MSM_SLEEP_TIME_OVERRIDE */
if (pm_sleep_ops.lowest_limits)
rs_limits = pm_sleep_ops.lowest_limits(false,
- MSM_PM_SLEEP_MODE_POWER_COLLAPSE, -1,
- -1, &power);
+ MSM_PM_SLEEP_MODE_POWER_COLLAPSE, &time_param, &power);
if (rs_limits) {
if (pm_sleep_ops.enter_sleep)
@@ -1046,6 +1088,7 @@
suspend_set_ops(&msm_pm_ops);
msm_pm_qtimer_available();
+ hrtimer_init(&pm_hrtimer, CLOCK_MONOTONIC, HRTIMER_MODE_ABS);
msm_cpuidle_init();
platform_driver_register(&msm_pc_counter_driver);
diff --git a/arch/arm/mach-msm/pm.h b/arch/arm/mach-msm/pm.h
index e2553e2..51256ca 100644
--- a/arch/arm/mach-msm/pm.h
+++ b/arch/arm/mach-msm/pm.h
@@ -57,6 +57,13 @@
#define MSM_PM_MODE(cpu, mode_nr) ((cpu) * MSM_PM_SLEEP_MODE_NR + (mode_nr))
+struct msm_pm_time_params {
+ uint32_t latency_us;
+ uint32_t sleep_us;
+ uint32_t next_event_us;
+ uint32_t modified_time_us;
+};
+
struct msm_pm_platform_data {
u8 idle_supported; /* Allow device to enter mode during idle */
u8 suspend_supported; /* Allow device to enter mode during suspend */
@@ -72,8 +79,8 @@
struct msm_pm_sleep_ops {
void *(*lowest_limits)(bool from_idle,
- enum msm_pm_sleep_mode sleep_mode, uint32_t latency_us,
- uint32_t sleep_us, uint32_t *power);
+ enum msm_pm_sleep_mode sleep_mode,
+ struct msm_pm_time_params *time_param, uint32_t *power);
int (*enter_sleep)(uint32_t sclk_count, void *limits,
bool from_idle, bool notify_rpm);
void (*exit_sleep)(void *limits, bool from_idle,
diff --git a/arch/arm/mach-msm/qdsp6v2/Makefile b/arch/arm/mach-msm/qdsp6v2/Makefile
index 0c75f66..ed8cb345 100644
--- a/arch/arm/mach-msm/qdsp6v2/Makefile
+++ b/arch/arm/mach-msm/qdsp6v2/Makefile
@@ -26,3 +26,4 @@
obj-$(CONFIG_MSM_QDSP6V2_CODECS) += audio_mp3.o audio_amrnb.o audio_amrwb.o audio_evrc.o audio_qcelp.o amrwb_in.o
obj-$(CONFIG_MSM_ADSP_LOADER) += adsp-loader.o
obj-$(CONFIG_MSM_ULTRASOUND) += ultrasound/
+obj-m += adsprpc.o
diff --git a/arch/arm/mach-msm/qdsp6v2/adsprpc.c b/arch/arm/mach-msm/qdsp6v2/adsprpc.c
new file mode 100644
index 0000000..6e6f8e8
--- /dev/null
+++ b/arch/arm/mach-msm/qdsp6v2/adsprpc.c
@@ -0,0 +1,706 @@
+/*
+ * Copyright (c) 2012, The Linux Foundation. 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 "adsprpc.h"
+
+struct smq_invoke_ctx {
+ struct completion work;
+ int retval;
+ atomic_t free;
+};
+
+struct smq_context_list {
+ struct smq_invoke_ctx *ls;
+ int size;
+ int last;
+};
+
+struct fastrpc_apps {
+ smd_channel_t *chan;
+ struct smq_context_list clst;
+ struct completion work;
+ struct ion_client *iclient;
+ struct cdev cdev;
+ dev_t dev_no;
+ spinlock_t wrlock;
+ spinlock_t hlock;
+ struct hlist_head htbl[RPC_HASH_SZ];
+};
+
+struct fastrpc_buf {
+ struct ion_handle *handle;
+ void *virt;
+ ion_phys_addr_t phys;
+ int size;
+ int used;
+};
+
+struct fastrpc_device {
+ uint32_t tgid;
+ struct hlist_node hn;
+ struct fastrpc_buf buf;
+};
+
+static struct fastrpc_apps gfa;
+
+static void free_mem(struct fastrpc_buf *buf)
+{
+ struct fastrpc_apps *me = &gfa;
+
+ if (buf->handle) {
+ if (buf->virt) {
+ ion_unmap_kernel(me->iclient, buf->handle);
+ buf->virt = 0;
+ }
+ ion_free(me->iclient, buf->handle);
+ buf->handle = 0;
+ }
+}
+
+static int alloc_mem(struct fastrpc_buf *buf)
+{
+ struct ion_client *clnt = gfa.iclient;
+ int err = 0;
+
+ buf->handle = ion_alloc(clnt, buf->size, SZ_4K,
+ ION_HEAP(ION_AUDIO_HEAP_ID));
+ VERIFY(0 == IS_ERR_OR_NULL(buf->handle));
+ buf->virt = 0;
+ VERIFY(0 != (buf->virt = ion_map_kernel(clnt, buf->handle,
+ ION_SET_CACHE(CACHED))));
+ VERIFY(0 == ion_phys(clnt, buf->handle, &buf->phys, &buf->size));
+ bail:
+ if (err && !IS_ERR_OR_NULL(buf->handle))
+ free_mem(buf);
+ return err;
+}
+
+static int context_list_ctor(struct smq_context_list *me, int size)
+{
+ int err = 0;
+ VERIFY(0 != (me->ls = kzalloc(size, GFP_KERNEL)));
+ me->size = size / sizeof(*me->ls);
+ me->last = 0;
+ bail:
+ return err;
+}
+
+static void context_list_dtor(struct smq_context_list *me)
+{
+ kfree(me->ls);
+ me->ls = 0;
+}
+
+static void context_list_alloc_ctx(struct smq_context_list *me,
+ struct smq_invoke_ctx **po)
+{
+ int ii = me->last;
+ struct smq_invoke_ctx *ctx;
+
+ for (;;) {
+ ii = ii % me->size;
+ ctx = &me->ls[ii];
+ if (atomic_read(&ctx->free) == 0)
+ if (0 == atomic_cmpxchg(&ctx->free, 0, 1))
+ break;
+ ii++;
+ }
+ me->last = ii;
+ ctx->retval = -1;
+ init_completion(&ctx->work);
+ *po = ctx;
+}
+
+static void context_free(struct smq_invoke_ctx *me)
+{
+ if (me)
+ atomic_set(&me->free, 0);
+}
+
+static void context_notify_user(struct smq_invoke_ctx *me, int retval)
+{
+ me->retval = retval;
+ complete(&me->work);
+}
+
+static void context_notify_all_users(struct smq_context_list *me)
+{
+ int ii;
+
+ if (!me->ls)
+ return;
+ for (ii = 0; ii < me->size; ++ii) {
+ if (atomic_read(&me->ls[ii].free) != 0)
+ complete(&me->ls[ii].work);
+ }
+}
+
+static int get_page_list(uint32_t kernel, uint32_t sc, remote_arg_t *pra,
+ struct fastrpc_buf *ibuf, struct fastrpc_buf *obuf)
+{
+ struct smq_phy_page *pgstart, *pages;
+ struct smq_invoke_buf *list;
+ int ii, rlen, err = 0;
+ int inbufs = REMOTE_SCALARS_INBUFS(sc);
+ int outbufs = REMOTE_SCALARS_OUTBUFS(sc);
+
+ VERIFY(0 != try_module_get(THIS_MODULE));
+ LOCK_MMAP(kernel);
+ *obuf = *ibuf;
+ retry:
+ list = smq_invoke_buf_start((remote_arg_t *)obuf->virt, sc);
+ pgstart = smq_phy_page_start(sc, list);
+ pages = pgstart + 1;
+ rlen = obuf->size - ((uint32_t)pages - (uint32_t)obuf->virt);
+ if (rlen < 0) {
+ rlen = ((uint32_t)pages - (uint32_t)obuf->virt) - obuf->size;
+ obuf->size += buf_page_size(rlen);
+ obuf->handle = 0;
+ VERIFY(0 == alloc_mem(obuf));
+ goto retry;
+ }
+ pgstart->addr = obuf->phys;
+ pgstart->size = obuf->size;
+ for (ii = 0; ii < inbufs + outbufs; ++ii) {
+ void *buf;
+ int len, num;
+
+ len = pra[ii].buf.len;
+ if (!len)
+ continue;
+ buf = pra[ii].buf.pv;
+ num = buf_num_pages(buf, len);
+ if (!kernel)
+ list[ii].num = buf_get_pages(buf, len, num,
+ ii >= inbufs, pages, rlen / sizeof(*pages));
+ else
+ list[ii].num = 0;
+ VERIFY(list[ii].num >= 0);
+ if (list[ii].num) {
+ list[ii].pgidx = pages - pgstart;
+ pages = pages + list[ii].num;
+ } else if (rlen > sizeof(*pages)) {
+ list[ii].pgidx = pages - pgstart;
+ pages = pages + 1;
+ } else {
+ if (obuf->handle != ibuf->handle)
+ free_mem(obuf);
+ obuf->size += buf_page_size(sizeof(*pages));
+ obuf->handle = 0;
+ VERIFY(0 == alloc_mem(obuf));
+ goto retry;
+ }
+ rlen = obuf->size - ((uint32_t) pages - (uint32_t) obuf->virt);
+ }
+ obuf->used = obuf->size - rlen;
+ bail:
+ if (err && (obuf->handle != ibuf->handle))
+ free_mem(obuf);
+ UNLOCK_MMAP(kernel);
+ module_put(THIS_MODULE);
+ return err;
+}
+
+static int get_args(uint32_t kernel, uint32_t sc, remote_arg_t *pra,
+ remote_arg_t *rpra, remote_arg_t *upra,
+ struct fastrpc_buf *ibuf, struct fastrpc_buf **abufs,
+ int *nbufs)
+{
+ struct smq_invoke_buf *list;
+ struct fastrpc_buf *pbuf = ibuf, *obufs = 0;
+ struct smq_phy_page *pages;
+ void *args;
+ int ii, rlen, size, used, inh, bufs = 0, err = 0;
+ int inbufs = REMOTE_SCALARS_INBUFS(sc);
+ int outbufs = REMOTE_SCALARS_OUTBUFS(sc);
+
+ list = smq_invoke_buf_start(rpra, sc);
+ pages = smq_phy_page_start(sc, list);
+ used = ALIGN_8(pbuf->used);
+ args = (void *)((char *)pbuf->virt + used);
+ rlen = pbuf->size - used;
+ for (ii = 0; ii < inbufs + outbufs; ++ii) {
+ int num;
+
+ rpra[ii].buf.len = pra[ii].buf.len;
+ if (list[ii].num) {
+ rpra[ii].buf.pv = pra[ii].buf.pv;
+ continue;
+ }
+ if (rlen < pra[ii].buf.len) {
+ struct fastrpc_buf *b;
+ pbuf->used = pbuf->size - rlen;
+ VERIFY(0 != (b = krealloc(obufs,
+ (bufs + 1) * sizeof(*obufs), GFP_KERNEL)));
+ obufs = b;
+ pbuf = obufs + bufs;
+ pbuf->size = buf_num_pages(0, pra[ii].buf.len) *
+ PAGE_SIZE;
+ VERIFY(0 == alloc_mem(pbuf));
+ bufs++;
+ args = pbuf->virt;
+ rlen = pbuf->size;
+ }
+ num = buf_num_pages(args, pra[ii].buf.len);
+ if (pbuf == ibuf) {
+ list[ii].num = num;
+ list[ii].pgidx = 0;
+ } else {
+ list[ii].num = 1;
+ pages[list[ii].pgidx].addr =
+ buf_page_start((void *)(pbuf->phys +
+ (pbuf->size - rlen)));
+ pages[list[ii].pgidx].size =
+ buf_page_size(pra[ii].buf.len);
+ }
+ if (ii < inbufs) {
+ if (!kernel)
+ VERIFY(0 == copy_from_user(args, pra[ii].buf.pv,
+ pra[ii].buf.len));
+ else
+ memmove(args, pra[ii].buf.pv, pra[ii].buf.len);
+ }
+ rpra[ii].buf.pv = args;
+ args = (void *)((char *)args + ALIGN_8(pra[ii].buf.len));
+ rlen -= ALIGN_8(pra[ii].buf.len);
+ }
+ for (ii = 0; ii < inbufs; ++ii) {
+ if (rpra[ii].buf.len)
+ dmac_flush_range(rpra[ii].buf.pv,
+ (char *)rpra[ii].buf.pv + rpra[ii].buf.len);
+ }
+ pbuf->used = pbuf->size - rlen;
+ size = sizeof(*rpra) * REMOTE_SCALARS_INHANDLES(sc);
+ if (size) {
+ inh = inbufs + outbufs;
+ if (!kernel)
+ VERIFY(0 == copy_from_user(&rpra[inh], &upra[inh],
+ size));
+ else
+ memmove(&rpra[inh], &upra[inh], size);
+ }
+ dmac_flush_range(rpra, (char *)rpra + used);
+ bail:
+ *abufs = obufs;
+ *nbufs = bufs;
+ return err;
+}
+
+static int put_args(uint32_t kernel, uint32_t sc, remote_arg_t *pra,
+ remote_arg_t *rpra, remote_arg_t *upra)
+{
+ int ii, inbufs, outbufs, outh, size;
+ int err = 0;
+
+ inbufs = REMOTE_SCALARS_INBUFS(sc);
+ outbufs = REMOTE_SCALARS_OUTBUFS(sc);
+ for (ii = inbufs; ii < inbufs + outbufs; ++ii) {
+ if (rpra[ii].buf.pv != pra[ii].buf.pv)
+ VERIFY(0 == copy_to_user(pra[ii].buf.pv,
+ rpra[ii].buf.pv, rpra[ii].buf.len));
+ }
+ size = sizeof(*rpra) * REMOTE_SCALARS_OUTHANDLES(sc);
+ if (size) {
+ outh = inbufs + outbufs + REMOTE_SCALARS_INHANDLES(sc);
+ if (!kernel)
+ VERIFY(0 == copy_to_user(&upra[outh], &rpra[outh],
+ size));
+ else
+ memmove(&upra[outh], &rpra[outh], size);
+ }
+ bail:
+ return err;
+}
+
+static void inv_args(uint32_t sc, remote_arg_t *rpra, int used)
+{
+ int ii, inbufs, outbufs;
+ int inv = 0;
+
+ inbufs = REMOTE_SCALARS_INBUFS(sc);
+ outbufs = REMOTE_SCALARS_OUTBUFS(sc);
+ for (ii = inbufs; ii < inbufs + outbufs; ++ii) {
+ if (buf_page_start(rpra) == buf_page_start(rpra[ii].buf.pv))
+ inv = 1;
+ else
+ dmac_inv_range(rpra[ii].buf.pv,
+ (char *)rpra[ii].buf.pv + rpra[ii].buf.len);
+ }
+
+ if (inv || REMOTE_SCALARS_OUTHANDLES(sc))
+ dmac_inv_range(rpra, (char *)rpra + used);
+}
+
+static int fastrpc_invoke_send(struct fastrpc_apps *me, remote_handle_t handle,
+ uint32_t sc, struct smq_invoke_ctx *ctx,
+ struct fastrpc_buf *buf)
+{
+ struct smq_msg msg;
+ int err = 0, len;
+
+ msg.pid = current->tgid;
+ msg.tid = current->pid;
+ msg.invoke.header.ctx = ctx;
+ msg.invoke.header.handle = handle;
+ msg.invoke.header.sc = sc;
+ msg.invoke.page.addr = buf->phys;
+ msg.invoke.page.size = buf_page_size(buf->used);
+ spin_lock(&me->wrlock);
+ len = smd_write(me->chan, &msg, sizeof(msg));
+ spin_unlock(&me->wrlock);
+ VERIFY(len == sizeof(msg));
+ bail:
+ return err;
+}
+
+static void fastrpc_deinit(void)
+{
+ struct fastrpc_apps *me = &gfa;
+
+ if (me->chan)
+ (void)smd_close(me->chan);
+ context_list_dtor(&me->clst);
+ ion_client_destroy(me->iclient);
+ me->iclient = 0;
+ me->chan = 0;
+}
+
+static void fastrpc_read_handler(void)
+{
+ struct fastrpc_apps *me = &gfa;
+ struct smq_invoke_rsp rsp;
+ int err = 0;
+
+ do {
+ VERIFY(sizeof(rsp) ==
+ smd_read_from_cb(me->chan, &rsp, sizeof(rsp)));
+ context_notify_user(rsp.ctx, rsp.retval);
+ } while (!err);
+ bail:
+ return;
+}
+
+static void smd_event_handler(void *priv, unsigned event)
+{
+ struct fastrpc_apps *me = (struct fastrpc_apps *)priv;
+
+ switch (event) {
+ case SMD_EVENT_OPEN:
+ complete(&(me->work));
+ break;
+ case SMD_EVENT_CLOSE:
+ context_notify_all_users(&me->clst);
+ break;
+ case SMD_EVENT_DATA:
+ fastrpc_read_handler();
+ break;
+ }
+}
+
+static int fastrpc_init(void)
+{
+ int err = 0;
+ struct fastrpc_apps *me = &gfa;
+
+ if (me->chan == 0) {
+ int ii;
+ spin_lock_init(&me->hlock);
+ spin_lock_init(&me->wrlock);
+ init_completion(&me->work);
+ for (ii = 0; ii < RPC_HASH_SZ; ++ii)
+ INIT_HLIST_HEAD(&me->htbl[ii]);
+ VERIFY(0 == context_list_ctor(&me->clst, SZ_4K));
+ me->iclient = msm_ion_client_create(ION_HEAP_CARVEOUT_MASK,
+ DEVICE_NAME);
+ VERIFY(0 == IS_ERR_OR_NULL(me->iclient));
+ VERIFY(0 == smd_named_open_on_edge(FASTRPC_SMD_GUID,
+ SMD_APPS_QDSP, &me->chan,
+ me, smd_event_handler));
+ VERIFY(0 != wait_for_completion_timeout(&me->work,
+ RPC_TIMEOUT));
+ }
+ bail:
+ if (err)
+ fastrpc_deinit();
+ return err;
+}
+
+static void free_dev(struct fastrpc_device *dev)
+{
+ if (dev) {
+ module_put(THIS_MODULE);
+ free_mem(&dev->buf);
+ kfree(dev);
+ }
+}
+
+static int alloc_dev(struct fastrpc_device **dev)
+{
+ int err = 0;
+ struct fastrpc_device *fd = 0;
+
+ VERIFY(0 != try_module_get(THIS_MODULE));
+ VERIFY(0 != (fd = kzalloc(sizeof(*fd), GFP_KERNEL)));
+ fd->buf.size = PAGE_SIZE;
+ VERIFY(0 == alloc_mem(&fd->buf));
+ fd->tgid = current->tgid;
+ INIT_HLIST_NODE(&fd->hn);
+ *dev = fd;
+ bail:
+ if (err)
+ free_dev(fd);
+ return err;
+}
+
+static int get_dev(struct fastrpc_apps *me, struct fastrpc_device **rdev)
+{
+ struct hlist_head *head;
+ struct fastrpc_device *dev = 0;
+ struct hlist_node *n;
+ uint32_t h = hash_32(current->tgid, RPC_HASH_BITS);
+ int err = 0;
+
+ spin_lock(&me->hlock);
+ head = &me->htbl[h];
+ hlist_for_each_entry(dev, n, head, hn) {
+ if (dev->tgid == current->tgid) {
+ hlist_del(&dev->hn);
+ break;
+ }
+ }
+ spin_unlock(&me->hlock);
+ VERIFY(dev != 0);
+ *rdev = dev;
+ bail:
+ if (err) {
+ free_dev(dev);
+ err = alloc_dev(rdev);
+ }
+ return err;
+}
+
+static void add_dev(struct fastrpc_apps *me, struct fastrpc_device *dev)
+{
+ struct hlist_head *head;
+ uint32_t h = hash_32(current->tgid, RPC_HASH_BITS);
+
+ spin_lock(&me->hlock);
+ head = &me->htbl[h];
+ hlist_add_head(&dev->hn, head);
+ spin_unlock(&me->hlock);
+ return;
+}
+
+static int fastrpc_release_current_dsp_process(void);
+
+static int fastrpc_internal_invoke(struct fastrpc_apps *me, uint32_t kernel,
+ struct fastrpc_ioctl_invoke *invoke, remote_arg_t *pra)
+{
+ remote_arg_t *rpra = 0;
+ struct fastrpc_device *dev = 0;
+ struct smq_invoke_ctx *ctx = 0;
+ struct fastrpc_buf obuf, *abufs = 0, *b;
+ int interrupted = 0;
+ uint32_t sc;
+ int ii, nbufs = 0, err = 0;
+
+ sc = invoke->sc;
+ obuf.handle = 0;
+ if (REMOTE_SCALARS_LENGTH(sc)) {
+ VERIFY(0 == get_dev(me, &dev));
+ VERIFY(0 == get_page_list(kernel, sc, pra, &dev->buf, &obuf));
+ rpra = (remote_arg_t *)obuf.virt;
+ VERIFY(0 == get_args(kernel, sc, pra, rpra, invoke->pra, &obuf,
+ &abufs, &nbufs));
+ }
+
+ context_list_alloc_ctx(&me->clst, &ctx);
+ VERIFY(0 == fastrpc_invoke_send(me, invoke->handle, sc, ctx, &obuf));
+ inv_args(sc, rpra, obuf.used);
+ VERIFY(0 == (interrupted =
+ wait_for_completion_interruptible(&ctx->work)));
+ VERIFY(0 == (err = ctx->retval));
+ VERIFY(0 == put_args(kernel, sc, pra, rpra, invoke->pra));
+ bail:
+ if (interrupted) {
+ init_completion(&ctx->work);
+ if (!kernel)
+ (void)fastrpc_release_current_dsp_process();
+ wait_for_completion(&ctx->work);
+ }
+ context_free(ctx);
+ for (ii = 0, b = abufs; ii < nbufs; ++ii, ++b)
+ free_mem(b);
+ kfree(abufs);
+ if (dev) {
+ add_dev(me, dev);
+ if (obuf.handle != dev->buf.handle)
+ free_mem(&obuf);
+ }
+ return err;
+}
+
+static int fastrpc_create_current_dsp_process(void)
+{
+ int err = 0;
+ struct fastrpc_ioctl_invoke ioctl;
+ struct fastrpc_apps *me = &gfa;
+ remote_arg_t ra[1];
+ int tgid = 0;
+
+ tgid = current->tgid;
+ ra[0].buf.pv = &tgid;
+ ra[0].buf.len = sizeof(tgid);
+ ioctl.handle = 1;
+ ioctl.sc = REMOTE_SCALARS_MAKE(0, 1, 0);
+ ioctl.pra = ra;
+ VERIFY(0 == fastrpc_internal_invoke(me, 1, &ioctl, ra));
+ bail:
+ return err;
+}
+
+static int fastrpc_release_current_dsp_process(void)
+{
+ int err = 0;
+ struct fastrpc_apps *me = &gfa;
+ struct fastrpc_ioctl_invoke ioctl;
+ remote_arg_t ra[1];
+ int tgid = 0;
+
+ tgid = current->tgid;
+ ra[0].buf.pv = &tgid;
+ ra[0].buf.len = sizeof(tgid);
+ ioctl.handle = 1;
+ ioctl.sc = REMOTE_SCALARS_MAKE(1, 1, 0);
+ ioctl.pra = ra;
+ VERIFY(0 == fastrpc_internal_invoke(me, 1, &ioctl, ra));
+ bail:
+ return err;
+}
+
+static void cleanup_current_dev(void)
+{
+ struct fastrpc_apps *me = &gfa;
+ uint32_t h = hash_32(current->tgid, RPC_HASH_BITS);
+ struct hlist_head *head;
+ struct hlist_node *pos;
+ struct fastrpc_device *dev;
+
+ rnext:
+ dev = 0;
+ spin_lock(&me->hlock);
+ head = &me->htbl[h];
+ hlist_for_each_entry(dev, pos, head, hn) {
+ if (dev->tgid == current->tgid) {
+ hlist_del(&dev->hn);
+ break;
+ }
+ }
+ spin_unlock(&me->hlock);
+ if (dev) {
+ free_dev(dev);
+ goto rnext;
+ }
+ return;
+}
+
+static int fastrpc_device_release(struct inode *inode, struct file *file)
+{
+ (void)fastrpc_release_current_dsp_process();
+ cleanup_current_dev();
+ return 0;
+}
+
+static int fastrpc_device_open(struct inode *inode, struct file *filp)
+{
+ int err = 0;
+
+ if (0 != try_module_get(THIS_MODULE)) {
+ /* This call will cause a dev to be created
+ * which will addref this module
+ */
+ VERIFY(0 == fastrpc_create_current_dsp_process());
+ bail:
+ if (err)
+ cleanup_current_dev();
+ module_put(THIS_MODULE);
+ }
+ return err;
+}
+
+
+static long fastrpc_device_ioctl(struct file *file, unsigned int ioctl_num,
+ unsigned long ioctl_param)
+{
+ struct fastrpc_apps *me = &gfa;
+ struct fastrpc_ioctl_invoke invoke;
+ remote_arg_t *pra = 0;
+ void *param = (char *)ioctl_param;
+ int bufs, err = 0;
+
+ switch (ioctl_num) {
+ case FASTRPC_IOCTL_INVOKE:
+ VERIFY(0 == copy_from_user(&invoke, param, sizeof(invoke)));
+ bufs = REMOTE_SCALARS_INBUFS(invoke.sc) +
+ REMOTE_SCALARS_OUTBUFS(invoke.sc);
+ if (bufs) {
+ bufs = bufs * sizeof(*pra);
+ VERIFY(0 != (pra = kmalloc(bufs, GFP_KERNEL)));
+ }
+ VERIFY(0 == copy_from_user(pra, invoke.pra, bufs));
+ VERIFY(0 == (err = fastrpc_internal_invoke(me, 0, &invoke,
+ pra)));
+ break;
+ default:
+ err = -EINVAL;
+ break;
+ }
+ bail:
+ kfree(pra);
+ return err;
+}
+
+static const struct file_operations fops = {
+ .open = fastrpc_device_open,
+ .release = fastrpc_device_release,
+ .unlocked_ioctl = fastrpc_device_ioctl,
+};
+
+static int __init fastrpc_device_init(void)
+{
+ struct fastrpc_apps *me = &gfa;
+ int err = 0;
+
+ VERIFY(0 == fastrpc_init());
+ VERIFY(0 == alloc_chrdev_region(&me->dev_no, 0, 1, DEVICE_NAME));
+ cdev_init(&me->cdev, &fops);
+ me->cdev.owner = THIS_MODULE;
+ VERIFY(0 == cdev_add(&me->cdev, MKDEV(MAJOR(me->dev_no), 0), 1));
+ pr_info("'mknod /dev/%s c %d 0'\n", DEVICE_NAME, MAJOR(me->dev_no));
+ bail:
+ return err;
+}
+
+static void __exit fastrpc_device_exit(void)
+{
+ struct fastrpc_apps *me = &gfa;
+
+ fastrpc_deinit();
+ cdev_del(&me->cdev);
+ unregister_chrdev_region(me->dev_no, 1);
+}
+
+module_init(fastrpc_device_init);
+module_exit(fastrpc_device_exit);
+
+MODULE_LICENSE("GPL v2");
diff --git a/arch/arm/mach-msm/qdsp6v2/adsprpc.h b/arch/arm/mach-msm/qdsp6v2/adsprpc.h
new file mode 100644
index 0000000..368b8e6
--- /dev/null
+++ b/arch/arm/mach-msm/qdsp6v2/adsprpc.h
@@ -0,0 +1,106 @@
+/*
+ * Copyright (c) 2012, The Linux Foundation. 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 ADSPRPC_H
+#define ADSPRPC_H
+
+#include <linux/slab.h>
+#include <linux/completion.h>
+#include <linux/pagemap.h>
+#include <linux/mm.h>
+#include <linux/fs.h>
+#include <linux/sched.h>
+#include <linux/module.h>
+#include <linux/cdev.h>
+#include <linux/list.h>
+#include <linux/hash.h>
+#include <linux/ion.h>
+#include <mach/msm_smd.h>
+#include <mach/ion.h>
+#include "adsprpc_shared.h"
+
+#ifndef ION_ADSPRPC_HEAP_ID
+#define ION_ADSPRPC_HEAP_ID ION_AUDIO_HEAP_ID
+#endif
+
+#define RPC_TIMEOUT (5 * HZ)
+#define RPC_HASH_BITS 5
+#define RPC_HASH_SZ (1 << RPC_HASH_BITS)
+
+#define ALIGN_8(a) ALIGN(a, 8)
+
+#define LOCK_MMAP(kernel)\
+ do {\
+ if (!kernel)\
+ down_read(¤t->mm->mmap_sem);\
+ } while (0)
+
+#define UNLOCK_MMAP(kernel)\
+ do {\
+ if (!kernel)\
+ up_read(¤t->mm->mmap_sem);\
+ } while (0)
+
+
+static inline uint32_t buf_page_start(void *buf)
+{
+ uint32_t start = (uint32_t) buf & PAGE_MASK;
+ return start;
+}
+
+static inline uint32_t buf_page_offset(void *buf)
+{
+ uint32_t offset = (uint32_t) buf & (PAGE_SIZE - 1);
+ return offset;
+}
+
+static inline int buf_num_pages(void *buf, int len)
+{
+ uint32_t start = buf_page_start(buf) >> PAGE_SHIFT;
+ uint32_t end = (((uint32_t) buf + len - 1) & PAGE_MASK) >> PAGE_SHIFT;
+ int nPages = end - start + 1;
+ return nPages;
+}
+
+static inline uint32_t buf_page_size(uint32_t size)
+{
+ uint32_t sz = (size + (PAGE_SIZE - 1)) & PAGE_MASK;
+ return sz > PAGE_SIZE ? sz : PAGE_SIZE;
+}
+
+static inline int buf_get_pages(void *addr, int sz, int nr_pages, int access,
+ struct smq_phy_page *pages, int nr_elems)
+{
+ struct vm_area_struct *vma;
+ uint32_t start = buf_page_start(addr);
+ uint32_t len = nr_pages << PAGE_SHIFT;
+ uint32_t pfn;
+ int n = -1, err = 0;
+
+ VERIFY(0 != access_ok(access ? VERIFY_WRITE : VERIFY_READ,
+ (void __user *)start, len));
+ VERIFY(0 != (vma = find_vma(current->mm, start)));
+ VERIFY(((uint32_t)addr + sz) <= vma->vm_end);
+ n = 0;
+ VERIFY(0 != (vma->vm_flags & VM_PFNMAP));
+ VERIFY(0 != (vma->vm_flags & VM_PFN_AT_MMAP));
+ VERIFY(nr_elems > 0);
+ pfn = vma->vm_pgoff + ((start - vma->vm_start) >> PAGE_SHIFT);
+ pages->addr = __pfn_to_phys(pfn);
+ pages->size = len;
+ n++;
+ bail:
+ return n;
+}
+
+#endif
diff --git a/arch/arm/mach-msm/qdsp6v2/adsprpc_shared.h b/arch/arm/mach-msm/qdsp6v2/adsprpc_shared.h
new file mode 100644
index 0000000..04b1d4a
--- /dev/null
+++ b/arch/arm/mach-msm/qdsp6v2/adsprpc_shared.h
@@ -0,0 +1,147 @@
+/*
+ * Copyright (c) 2012, The Linux Foundation. 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 ADSPRPC_SHARED_H
+#define ADSPRPC_SHARED_H
+
+#define FASTRPC_IOCTL_INVOKE _IOWR('R', 1, struct fastrpc_ioctl_invoke)
+#define FASTRPC_SMD_GUID "fastrpcsmd-apps-dsp"
+#define DEVICE_NAME "adsprpc-smd"
+
+/* Retrives number of input buffers from the scalars parameter */
+#define REMOTE_SCALARS_INBUFS(sc) (((sc) >> 16) & 0x0ff)
+
+/* Retrives number of output buffers from the scalars parameter */
+#define REMOTE_SCALARS_OUTBUFS(sc) (((sc) >> 8) & 0x0ff)
+
+/* Retrives number of input handles from the scalars parameter */
+#define REMOTE_SCALARS_INHANDLES(sc) (((sc) >> 4) & 0x0f)
+
+/* Retrives number of output handles from the scalars parameter */
+#define REMOTE_SCALARS_OUTHANDLES(sc) ((sc) & 0x0f)
+
+#define REMOTE_SCALARS_LENGTH(sc) (REMOTE_SCALARS_INBUFS(sc) +\
+ REMOTE_SCALARS_OUTBUFS(sc) +\
+ REMOTE_SCALARS_INHANDLES(sc) +\
+ REMOTE_SCALARS_OUTHANDLES(sc))
+
+#define REMOTE_SCALARS_MAKEX(attr, method, in, out, oin, oout) \
+ ((((uint32_t) (attr) & 0x7) << 29) | \
+ (((uint32_t) (method) & 0x1f) << 24) | \
+ (((uint32_t) (in) & 0xff) << 16) | \
+ (((uint32_t) (out) & 0xff) << 8) | \
+ (((uint32_t) (oin) & 0x0f) << 4) | \
+ ((uint32_t) (oout) & 0x0f))
+
+#define REMOTE_SCALARS_MAKE(method, in, out) \
+ REMOTE_SCALARS_MAKEX(0, method, in, out, 0, 0)
+
+
+#ifndef VERIFY_PRINT_ERROR
+#define VERIFY_EPRINTF(format, args) (void)0
+#endif
+
+#ifndef VERIFY_PRINT_INFO
+#define VERIFY_IPRINTF(args) (void)0
+#endif
+
+#ifndef VERIFY
+#define __STR__(x) #x ":"
+#define __TOSTR__(x) __STR__(x)
+#define __FILE_LINE__ __FILE__ ":" __TOSTR__(__LINE__)
+
+#define VERIFY(val) \
+do {\
+ VERIFY_IPRINTF(__FILE_LINE__"info: calling: " #val "\n");\
+ if (0 == (val)) {\
+ err = err == 0 ? -1 : err;\
+ VERIFY_EPRINTF(__FILE_LINE__"error: %d: " #val "\n", err);\
+ goto bail;\
+ } else {\
+ VERIFY_IPRINTF(__FILE_LINE__"info: passed: " #val "\n");\
+ } \
+} while (0)
+#endif
+
+#define remote_handle_t uint32_t
+#define remote_arg_t union remote_arg
+
+struct remote_buf {
+ void *pv; /* buffer pointer */
+ int len; /* length of buffer */
+};
+
+union remote_arg {
+ struct remote_buf buf; /* buffer info */
+ remote_handle_t h; /* remote handle */
+};
+
+struct fastrpc_ioctl_invoke {
+ remote_handle_t handle; /* remote handle */
+ uint32_t sc; /* scalars describing the data */
+ remote_arg_t *pra; /* remote arguments list */
+};
+
+struct smq_null_invoke {
+ struct smq_invoke_ctx *ctx; /* invoke caller context */
+ remote_handle_t handle; /* handle to invoke */
+ uint32_t sc; /* scalars structure describing the data */
+};
+
+struct smq_phy_page {
+ uint32_t addr; /* physical address */
+ uint32_t size; /* size of contiguous region */
+};
+
+struct smq_invoke_buf {
+ int num; /* number of contiguous regions */
+ int pgidx; /* index to start of contiguous region */
+};
+
+struct smq_invoke {
+ struct smq_null_invoke header;
+ struct smq_phy_page page; /* remote arg and list of pages address */
+};
+
+struct smq_msg {
+ uint32_t pid; /* process group id */
+ uint32_t tid; /* thread id */
+ struct smq_invoke invoke;
+};
+
+struct smq_invoke_rsp {
+ struct smq_invoke_ctx *ctx; /* invoke caller context */
+ int retval; /* invoke return value */
+};
+
+static inline struct smq_invoke_buf *smq_invoke_buf_start(remote_arg_t *pra,
+ uint32_t sc)
+{
+ int len = REMOTE_SCALARS_LENGTH(sc);
+ return (struct smq_invoke_buf *)(&pra[len]);
+}
+
+static inline struct smq_phy_page *smq_phy_page_start(uint32_t sc,
+ struct smq_invoke_buf *buf)
+{
+ int nTotal = REMOTE_SCALARS_INBUFS(sc) + REMOTE_SCALARS_OUTBUFS(sc);
+ return (struct smq_phy_page *)(&buf[nTotal]);
+}
+
+static inline int smq_invoke_buf_size(uint32_t sc, int nPages)
+{
+ struct smq_phy_page *start = smq_phy_page_start(sc, 0);
+ return (int)(&(start[nPages]));
+}
+
+#endif
diff --git a/arch/arm/mach-msm/restart.c b/arch/arm/mach-msm/restart.c
index 53736ac..5883b0c 100644
--- a/arch/arm/mach-msm/restart.c
+++ b/arch/arm/mach-msm/restart.c
@@ -24,6 +24,7 @@
#include <linux/mfd/pmic8058.h>
#include <linux/mfd/pmic8901.h>
#include <linux/mfd/pm8xxx/misc.h>
+#include <linux/qpnp/power-on.h>
#include <asm/mach-types.h>
#include <asm/cacheflush.h>
@@ -128,6 +129,7 @@
set_dload_mode(0);
#endif
pm8xxx_reset_pwr_off(0);
+ qpnp_pon_system_pwr_off(0);
if (lower_pshold) {
if (!use_restart_v2())
@@ -208,6 +210,7 @@
#endif
pm8xxx_reset_pwr_off(1);
+ qpnp_pon_system_pwr_off(1);
if (cmd != NULL) {
if (!strncmp(cmd, "bootloader", 10)) {
diff --git a/arch/arm/mach-msm/rpm_resources.c b/arch/arm/mach-msm/rpm_resources.c
index 9d794e7..2a835f7 100644
--- a/arch/arm/mach-msm/rpm_resources.c
+++ b/arch/arm/mach-msm/rpm_resources.c
@@ -20,6 +20,7 @@
#include <linux/proc_fs.h>
#include <linux/spinlock.h>
#include <linux/cpu.h>
+#include <linux/hrtimer.h>
#include <mach/rpm.h>
#include <mach/msm_iomap.h>
#include <asm/mach-types.h>
@@ -37,6 +38,7 @@
enum {
MSM_RPMRS_DEBUG_OUTPUT = BIT(0),
MSM_RPMRS_DEBUG_BUFFER = BIT(1),
+ MSM_RPMRS_DEBUG_EVENT_TIMER = BIT(2),
};
static int msm_rpmrs_debug_mask;
@@ -891,8 +893,8 @@
}
static void *msm_rpmrs_lowest_limits(bool from_idle,
- enum msm_pm_sleep_mode sleep_mode, uint32_t latency_us,
- uint32_t sleep_us, uint32_t *power)
+ enum msm_pm_sleep_mode sleep_mode,
+ struct msm_pm_time_params *time_param, uint32_t *power)
{
unsigned int cpu = smp_processor_id();
struct msm_rpmrs_level *best_level = NULL;
@@ -900,6 +902,8 @@
bool gpio_detectable = false;
int i;
uint32_t pwr;
+ uint32_t next_wakeup_us = time_param->sleep_us;
+ bool modify_event_timer;
if (sleep_mode == MSM_PM_SLEEP_MODE_POWER_COLLAPSE) {
irqs_detectable = msm_mpm_irqs_detectable(from_idle);
@@ -909,16 +913,32 @@
for (i = 0; i < msm_rpmrs_level_count; i++) {
struct msm_rpmrs_level *level = &msm_rpmrs_levels[i];
+ modify_event_timer = false;
+
if (!level->available)
continue;
if (sleep_mode != level->sleep_mode)
continue;
- if (latency_us < level->latency_us)
+ if (time_param->latency_us < level->latency_us)
continue;
- if (sleep_us <= level->time_overhead_us)
+ if (time_param->next_event_us &&
+ time_param->next_event_us < level->latency_us)
+ continue;
+
+ if (time_param->next_event_us) {
+ if ((time_param->next_event_us < time_param->sleep_us)
+ || ((time_param->next_event_us - level->latency_us) <
+ time_param->sleep_us)) {
+ modify_event_timer = true;
+ next_wakeup_us = time_param->next_event_us -
+ level->latency_us;
+ }
+ }
+
+ if (next_wakeup_us <= level->time_overhead_us)
continue;
if (!msm_rpmrs_irqs_detectable(&level->rs_limits,
@@ -929,18 +949,17 @@
if (!cpu && msm_rpm_local_request_is_outstanding())
break;
-
- if (sleep_us <= 1) {
+ if (next_wakeup_us <= 1) {
pwr = level->energy_overhead;
- } else if (sleep_us <= level->time_overhead_us) {
- pwr = level->energy_overhead / sleep_us;
- } else if ((sleep_us >> 10) > level->time_overhead_us) {
+ } else if (next_wakeup_us <= level->time_overhead_us) {
+ pwr = level->energy_overhead / next_wakeup_us;
+ } else if ((next_wakeup_us >> 10) > level->time_overhead_us) {
pwr = level->steady_state_power;
} else {
pwr = level->steady_state_power;
pwr -= (level->time_overhead_us *
- level->steady_state_power)/sleep_us;
- pwr += level->energy_overhead / sleep_us;
+ level->steady_state_power)/next_wakeup_us;
+ pwr += level->energy_overhead / next_wakeup_us;
}
if (!best_level ||
@@ -950,6 +969,12 @@
best_level = level;
if (power)
*power = pwr;
+ if (modify_event_timer && best_level->latency_us > 1)
+ time_param->modified_time_us =
+ time_param->next_event_us -
+ best_level->latency_us;
+ else
+ time_param->modified_time_us = 0;
}
}
diff --git a/arch/arm/mach-msm/smd_pkt.c b/arch/arm/mach-msm/smd_pkt.c
index 30acebf..928e59b 100644
--- a/arch/arm/mach-msm/smd_pkt.c
+++ b/arch/arm/mach-msm/smd_pkt.c
@@ -35,6 +35,7 @@
#include <mach/msm_smd.h>
#include <mach/peripheral-loader.h>
+#include <mach/msm_ipc_logging.h>
#include "smd_private.h"
#ifdef CONFIG_ARCH_FSM9XXX
@@ -89,6 +90,9 @@
static void check_and_wakeup_writer(struct smd_pkt_dev *smd_pkt_devp);
static uint32_t is_modem_smsm_inited(void);
+#define SMD_PKT_IPC_LOG_PAGE_CNT 2
+static void *smd_pkt_ilctxt;
+
static int msm_smd_pkt_debug_mask;
module_param_named(debug_mask, msm_smd_pkt_debug_mask,
int, S_IRUGO | S_IWUSR | S_IWGRP);
@@ -105,22 +109,44 @@
#define DEBUG
#ifdef DEBUG
+
+#define SMD_PKT_LOG_STRING(x...) \
+do { \
+ if (smd_pkt_ilctxt) \
+ ipc_log_string(smd_pkt_ilctxt, "<SMD_PKT>: "x); \
+} while (0)
+
+#define SMD_PKT_LOG_BUF(buf, cnt) \
+do { \
+ char log_buf[128]; \
+ int i; \
+ if (smd_pkt_ilctxt) { \
+ i = cnt < 16 ? cnt : 16; \
+ hex_dump_to_buffer(buf, i, 16, 1, log_buf, \
+ sizeof(log_buf), false); \
+ ipc_log_string(smd_pkt_ilctxt, "<SMD_PKT>: %s", log_buf); \
+ } \
+} while (0)
+
#define D_STATUS(x...) \
do { \
if (msm_smd_pkt_debug_mask & SMD_PKT_STATUS) \
pr_info("Status: "x); \
+ SMD_PKT_LOG_STRING(x); \
} while (0)
#define D_READ(x...) \
do { \
if (msm_smd_pkt_debug_mask & SMD_PKT_READ) \
pr_info("Read: "x); \
+ SMD_PKT_LOG_STRING(x); \
} while (0)
#define D_WRITE(x...) \
do { \
if (msm_smd_pkt_debug_mask & SMD_PKT_WRITE) \
pr_info("Write: "x); \
+ SMD_PKT_LOG_STRING(x); \
} while (0)
#define D_READ_DUMP_BUFFER(prestr, cnt, buf) \
@@ -129,6 +155,7 @@
print_hex_dump(KERN_INFO, prestr, \
DUMP_PREFIX_NONE, 16, 1, \
buf, cnt, 1); \
+ SMD_PKT_LOG_BUF(buf, cnt); \
} while (0)
#define D_WRITE_DUMP_BUFFER(prestr, cnt, buf) \
@@ -137,12 +164,14 @@
print_hex_dump(KERN_INFO, prestr, \
DUMP_PREFIX_NONE, 16, 1, \
buf, cnt, 1); \
+ SMD_PKT_LOG_BUF(buf, cnt); \
} while (0)
#define D_POLL(x...) \
do { \
if (msm_smd_pkt_debug_mask & SMD_PKT_POLL) \
pr_info("Poll: "x); \
+ SMD_PKT_LOG_STRING(x); \
} while (0)
#define E_SMD_PKT_SSR(x) \
@@ -1032,6 +1061,9 @@
INIT_DELAYED_WORK(&loopback_work, loopback_probe_worker);
+ smd_pkt_ilctxt = ipc_log_context_create(SMD_PKT_IPC_LOG_PAGE_CNT,
+ "smd_pkt");
+
D_STATUS("SMD Packet Port Driver Initialized.\n");
return 0;
diff --git a/arch/arm/mach-msm/subsystem_restart.c b/arch/arm/mach-msm/subsystem_restart.c
index 0318a70..bae1ab0 100644
--- a/arch/arm/mach-msm/subsystem_restart.c
+++ b/arch/arm/mach-msm/subsystem_restart.c
@@ -58,11 +58,13 @@
enum subsys_state {
SUBSYS_OFFLINE,
SUBSYS_ONLINE,
+ SUBSYS_CRASHED,
};
static const char * const subsys_states[] = {
[SUBSYS_OFFLINE] = "OFFLINE",
[SUBSYS_ONLINE] = "ONLINE",
+ [SUBSYS_CRASHED] = "CRASHED",
};
struct subsys_device {
@@ -71,7 +73,7 @@
char wlname[64];
struct work_struct work;
spinlock_t restart_lock;
- int restart_count;
+ bool restarting;
void *notify;
struct device dev;
@@ -107,6 +109,21 @@
return snprintf(buf, PAGE_SIZE, "%s\n", subsys_states[state]);
}
+static void subsys_set_state(struct subsys_device *subsys,
+ enum subsys_state state)
+{
+ unsigned long flags;
+
+ spin_lock_irqsave(&subsys->restart_lock, flags);
+ if (subsys->state != state) {
+ subsys->state = state;
+ spin_unlock_irqrestore(&subsys->restart_lock, flags);
+ sysfs_notify(&subsys->dev.kobj, NULL, "state");
+ return;
+ }
+ spin_unlock_irqrestore(&subsys->restart_lock, flags);
+}
+
static struct device_attribute subsys_attrs[] = {
__ATTR_RO(name),
__ATTR_RO(state),
@@ -333,6 +350,7 @@
if (dev->desc->shutdown(dev->desc) < 0)
panic("subsys-restart: [%p]: Failed to shutdown %s!",
current, name);
+ subsys_set_state(dev, SUBSYS_OFFLINE);
}
static void subsystem_ramdump(struct subsys_device *dev, void *data)
@@ -351,6 +369,7 @@
pr_info("[%p]: Powering up %s\n", current, name);
if (dev->desc->powerup(dev->desc) < 0)
panic("[%p]: Failed to powerup %s!", current, name);
+ subsys_set_state(dev, SUBSYS_ONLINE);
}
static int __find_subsys(struct device *dev, void *data)
@@ -418,7 +437,10 @@
* Now that we've acquired the shutdown lock, either we're the first to
* restart these subsystems or some other thread is doing the powerup
* sequence for these subsystems. In the latter case, panic and bail
- * out, since a subsystem died in its powerup sequence.
+ * out, since a subsystem died in its powerup sequence. This catches
+ * the case where a subsystem in a restart order isn't the one
+ * who initiated the original restart but has crashed while the restart
+ * order is being rebooted.
*/
if (!mutex_trylock(powerup_lock))
panic("%s[%p]: Subsystem died during powerup!",
@@ -465,32 +487,36 @@
out:
spin_lock_irqsave(&dev->restart_lock, flags);
- dev->restart_count--;
- if (!dev->restart_count)
- wake_unlock(&dev->wake_lock);
+ dev->restarting = false;
+ wake_unlock(&dev->wake_lock);
spin_unlock_irqrestore(&dev->restart_lock, flags);
}
static void __subsystem_restart_dev(struct subsys_device *dev)
{
struct subsys_desc *desc = dev->desc;
+ const char *name = dev->desc->name;
unsigned long flags;
pr_debug("Restarting %s [level=%d]!\n", desc->name, restart_level);
+ /*
+ * We want to allow drivers to call subsystem_restart{_dev}() as many
+ * times as they want up until the point where the subsystem is
+ * shutdown.
+ */
spin_lock_irqsave(&dev->restart_lock, flags);
- if (!dev->restart_count)
- wake_lock(&dev->wake_lock);
- dev->restart_count++;
- spin_unlock_irqrestore(&dev->restart_lock, flags);
-
- if (!queue_work(ssr_wq, &dev->work)) {
- spin_lock_irqsave(&dev->restart_lock, flags);
- dev->restart_count--;
- if (!dev->restart_count)
- wake_unlock(&dev->wake_lock);
- spin_unlock_irqrestore(&dev->restart_lock, flags);
+ if (dev->state != SUBSYS_CRASHED) {
+ if (dev->state == SUBSYS_ONLINE && !dev->restarting) {
+ dev->restarting = true;
+ dev->state = SUBSYS_CRASHED;
+ wake_lock(&dev->wake_lock);
+ queue_work(ssr_wq, &dev->work);
+ } else {
+ panic("Subsystem %s crashed during SSR!", name);
+ }
}
+ spin_unlock_irqrestore(&dev->restart_lock, flags);
}
int subsystem_restart_dev(struct subsys_device *dev)
@@ -644,6 +670,7 @@
subsys->dev.parent = desc->dev;
subsys->dev.bus = &subsys_bus_type;
subsys->dev.release = subsys_device_release;
+ subsys->state = SUBSYS_ONLINE; /* Until proper refcounting appears */
subsys->notify = subsys_notif_add_subsys(desc->name);
subsys->restart_order = update_restart_order(subsys);
diff --git a/arch/arm/mm/fault.c b/arch/arm/mm/fault.c
index ed03b33..19ef5a6 100644
--- a/arch/arm/mm/fault.c
+++ b/arch/arm/mm/fault.c
@@ -37,6 +37,9 @@
#include "fault.h"
+#define CREATE_TRACE_POINTS
+#include <trace/events/exception.h>
+
#ifdef CONFIG_MMU
#ifdef CONFIG_KPROBES
@@ -173,6 +176,8 @@
{
struct siginfo si;
+ trace_user_fault(tsk, addr, fsr);
+
#ifdef CONFIG_DEBUG_USER
if (((user_debug & UDBG_SEGV) && (sig == SIGSEGV)) ||
((user_debug & UDBG_BUS) && (sig == SIGBUS))) {
diff --git a/drivers/char/diag/diagfwd.c b/drivers/char/diag/diagfwd.c
index c827ec7..a669b45 100644
--- a/drivers/char/diag/diagfwd.c
+++ b/drivers/char/diag/diagfwd.c
@@ -1124,6 +1124,7 @@
driver->apps_rsp_buf[2] = 0x0;
driver->apps_rsp_buf[3] = 0x0;
*(int *)(driver->apps_rsp_buf + 4) = 0x0;
+ *(int *)(driver->apps_rsp_buf + 8) = 0x0; /* status */
if (driver->ch_cntl)
diag_send_log_mask_update(driver->ch_cntl,
ALL_EQUIP_ID);
@@ -1133,7 +1134,7 @@
if (driver->ch_wcnss_cntl)
diag_send_log_mask_update(driver->ch_wcnss_cntl,
ALL_EQUIP_ID);
- ENCODE_RSP_AND_SEND(7);
+ ENCODE_RSP_AND_SEND(11);
return 0;
}
#endif
diff --git a/drivers/coresight/Kconfig b/drivers/coresight/Kconfig
index 1219af1..a23fff0 100644
--- a/drivers/coresight/Kconfig
+++ b/drivers/coresight/Kconfig
@@ -30,3 +30,12 @@
For production builds, you should probably say 'N' here to avoid
potential power, performance and memory penalty.
+
+config CONTROL_TRACE
+ tristate "Turn on to control tracing"
+ help
+ Builds module to abort tracing on a user space data, instruction
+ or prefetch abort.
+
+ For production builds, you should probably say 'N' here to avoid
+ potential power, performance and memory penalty.
diff --git a/drivers/coresight/Makefile b/drivers/coresight/Makefile
index 4ee93cf..a2815de 100644
--- a/drivers/coresight/Makefile
+++ b/drivers/coresight/Makefile
@@ -1,3 +1,3 @@
-
+obj-$(CONFIG_CONTROL_TRACE) += control_trace.o
obj-$(CONFIG_OF) += of_coresight.o
obj-$(CONFIG_MSM_QDSS) += coresight.o coresight-csr.o coresight-tmc.o coresight-tpiu.o coresight-etb.o coresight-funnel.o coresight-replicator.o coresight-stm.o coresight-etm.o
diff --git a/drivers/coresight/control_trace.c b/drivers/coresight/control_trace.c
new file mode 100644
index 0000000..aa8bfc5
--- /dev/null
+++ b/drivers/coresight/control_trace.c
@@ -0,0 +1,71 @@
+/* Copyright (c) 2012, The Linux Foundation. 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.
+ */
+
+/*
+ * DLKM to register a callback with a ftrace event
+ */
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/slab.h>
+#include <linux/init.h>
+#include <linux/sched.h>
+#include <linux/tracepoint.h>
+#include <linux/coresight.h>
+
+#include <trace/events/exception.h>
+
+static void abort_coresight_tracing(void *ignore, struct task_struct *task,\
+ unsigned long addr, unsigned int fsr)
+{
+ coresight_abort();
+ pr_debug("control_trace: task_name: %s, addr: %lu, fsr:%u",\
+ (char *)task->comm, addr, fsr);
+}
+
+static void abort_tracing_undef_instr(void *ignore, struct pt_regs *regs,\
+ void *pc)
+{
+ if (user_mode(regs)) {
+ coresight_abort();
+ pr_debug("control_trace: pc: %p", pc);
+ }
+}
+
+static int __init control_trace_init(void)
+{
+ int ret_user_fault, ret_undef_instr;
+ ret_user_fault = register_trace_user_fault(abort_coresight_tracing,\
+ NULL);
+ ret_undef_instr = register_trace_undef_instr(abort_tracing_undef_instr,\
+ NULL);
+ if (ret_user_fault != 0 || ret_undef_instr != 0) {
+ pr_info("control_trace: Module Not Registered\n");
+ return (ret_user_fault < 0 ?\
+ ret_user_fault : ret_undef_instr);
+ }
+ pr_info("control_trace: Module Registered\n");
+ return 0;
+}
+
+module_init(control_trace_init);
+
+static void __exit control_trace_exit(void)
+{
+ unregister_trace_user_fault(abort_coresight_tracing, NULL);
+ unregister_trace_undef_instr(abort_tracing_undef_instr, NULL);
+ pr_info("control_trace: Module Removed\n");
+}
+
+module_exit(control_trace_exit);
+
+MODULE_LICENSE("GPL v2");
+MODULE_DESCRIPTION("Kernel Module to abort tracing");
diff --git a/drivers/gpu/msm/adreno_a2xx.c b/drivers/gpu/msm/adreno_a2xx.c
index 1f32e54..2388fff 100644
--- a/drivers/gpu/msm/adreno_a2xx.c
+++ b/drivers/gpu/msm/adreno_a2xx.c
@@ -1574,8 +1574,6 @@
return;
}
- KGSL_CTXT_INFO(device, "context flags %08x\n", context->flags);
-
cmds[0] = cp_nop_packet(1);
cmds[1] = KGSL_CONTEXT_TO_MEM_IDENTIFIER;
cmds[2] = cp_type3_packet(CP_MEM_WRITE, 2);
@@ -1710,18 +1708,24 @@
if (status & CP_INT_CNTL__RB_INT_MASK) {
/* signal intr completion event */
- unsigned int context_id;
- kgsl_sharedmem_readl(&device->memstore,
- &context_id,
+ unsigned int context_id, timestamp;
+ kgsl_sharedmem_readl(&device->memstore, &context_id,
KGSL_MEMSTORE_OFFSET(KGSL_MEMSTORE_GLOBAL,
current_context));
+
+ kgsl_sharedmem_readl(&device->memstore, ×tamp,
+ KGSL_MEMSTORE_OFFSET(context_id,
+ eoptimestamp));
+
if (context_id < KGSL_MEMSTORE_MAX) {
kgsl_sharedmem_writel(&rb->device->memstore,
KGSL_MEMSTORE_OFFSET(context_id,
ts_cmp_enable), 0);
wmb();
}
- KGSL_CMD_WARN(rb->device, "ringbuffer rb interrupt\n");
+
+ KGSL_CMD_WARN(device, "<%d:0x%x> ringbuffer interrupt\n",
+ context_id, timestamp);
}
for (i = 0; i < ARRAY_SIZE(kgsl_cp_error_irqs); i++) {
@@ -1743,7 +1747,6 @@
adreno_regwrite(device, REG_CP_INT_ACK, status);
if (status & (CP_INT_CNTL__IB1_INT_MASK | CP_INT_CNTL__RB_INT_MASK)) {
- KGSL_CMD_WARN(rb->device, "ringbuffer ib1/rb interrupt\n");
queue_work(device->work_queue, &device->ts_expired_ws);
wake_up_interruptible_all(&device->wait_queue);
atomic_notifier_call_chain(&(device->ts_notifier_list),
diff --git a/drivers/gpu/msm/adreno_a3xx.c b/drivers/gpu/msm/adreno_a3xx.c
index d89e882..b8fca38 100644
--- a/drivers/gpu/msm/adreno_a3xx.c
+++ b/drivers/gpu/msm/adreno_a3xx.c
@@ -2409,8 +2409,6 @@
return;
}
- KGSL_CTXT_INFO(device, "context flags %08x\n", context->flags);
-
cmds[0] = cp_nop_packet(1);
cmds[1] = KGSL_CONTEXT_TO_MEM_IDENTIFIER;
cmds[2] = cp_type3_packet(CP_MEM_WRITE, 2);
@@ -2565,17 +2563,24 @@
struct kgsl_device *device = &adreno_dev->dev;
if (irq == A3XX_INT_CP_RB_INT) {
- unsigned int context_id;
+ unsigned int context_id, timestamp;
kgsl_sharedmem_readl(&device->memstore, &context_id,
KGSL_MEMSTORE_OFFSET(KGSL_MEMSTORE_GLOBAL,
current_context));
+
+ kgsl_sharedmem_readl(&device->memstore, ×tamp,
+ KGSL_MEMSTORE_OFFSET(context_id,
+ eoptimestamp));
+
if (context_id < KGSL_MEMSTORE_MAX) {
kgsl_sharedmem_writel(&device->memstore,
KGSL_MEMSTORE_OFFSET(context_id,
ts_cmp_enable), 0);
wmb();
}
- KGSL_CMD_WARN(device, "ringbuffer rb interrupt\n");
+
+ KGSL_CMD_WARN(device, "<%d:0x%x> ringbuffer interrupt\n",
+ context_id, timestamp);
}
wake_up_interruptible_all(&device->wait_queue);
diff --git a/drivers/gpu/msm/adreno_drawctxt.c b/drivers/gpu/msm/adreno_drawctxt.c
index b51342f..70ad81c 100644
--- a/drivers/gpu/msm/adreno_drawctxt.c
+++ b/drivers/gpu/msm/adreno_drawctxt.c
@@ -288,8 +288,10 @@
return;
}
- KGSL_CTXT_INFO(device, "from %p to %p flags %d\n",
- adreno_dev->drawctxt_active, drawctxt, flags);
+ KGSL_CTXT_INFO(device, "from %d to %d flags %d\n",
+ adreno_dev->drawctxt_active ?
+ adreno_dev->drawctxt_active->id : 0,
+ drawctxt ? drawctxt->id : 0, flags);
/* Save the old context */
adreno_dev->gpudev->ctxt_save(adreno_dev, adreno_dev->drawctxt_active);
diff --git a/drivers/gpu/msm/adreno_postmortem.c b/drivers/gpu/msm/adreno_postmortem.c
index 620b82c..daa78ed 100644
--- a/drivers/gpu/msm/adreno_postmortem.c
+++ b/drivers/gpu/msm/adreno_postmortem.c
@@ -50,6 +50,7 @@
{CP_DRAW_INDX, "DRW_NDX_"},
{CP_DRAW_INDX_BIN, "DRW_NDXB"},
{CP_EVENT_WRITE, "EVENT_WT"},
+ {CP_MEM_WRITE, "MEM_WRIT"},
{CP_IM_LOAD, "IN__LOAD"},
{CP_IM_LOAD_IMMEDIATE, "IM_LOADI"},
{CP_IM_STORE, "IM_STORE"},
diff --git a/drivers/gpu/msm/adreno_ringbuffer.c b/drivers/gpu/msm/adreno_ringbuffer.c
index db913a5..1ff219b 100644
--- a/drivers/gpu/msm/adreno_ringbuffer.c
+++ b/drivers/gpu/msm/adreno_ringbuffer.c
@@ -969,8 +969,8 @@
drawctxt, 0,
&link[0], (cmds - link));
- KGSL_CMD_INFO(device, "ctxt %d g %08x numibs %d ts %d\n",
- context->id, (unsigned int)ibdesc, numibs, *timestamp);
+ KGSL_CMD_INFO(device, "<%d:0x%x> g %08x numibs %d\n",
+ context->id, *timestamp, (unsigned int)ibdesc, numibs);
kfree(link);
diff --git a/drivers/gpu/msm/kgsl.c b/drivers/gpu/msm/kgsl.c
index f630f2a..21227a0 100644
--- a/drivers/gpu/msm/kgsl.c
+++ b/drivers/gpu/msm/kgsl.c
@@ -1107,9 +1107,6 @@
}
if (param->flags & KGSL_CONTEXT_SUBMIT_IB_LIST) {
- KGSL_DRV_INFO(dev_priv->device,
- "Using IB list mode for ib submission, numibs: %d\n",
- param->numibs);
if (!param->numibs) {
KGSL_DRV_ERR(dev_priv->device,
"Invalid numibs as parameter: %d\n",
diff --git a/drivers/platform/msm/qpnp-power-on.c b/drivers/platform/msm/qpnp-power-on.c
index 996456f..33b12ae 100644
--- a/drivers/platform/msm/qpnp-power-on.c
+++ b/drivers/platform/msm/qpnp-power-on.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2012, Code Aurora Forum. All rights reserved.
+/* Copyright (c) 2012, The Linux Foundation. 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
@@ -35,6 +35,7 @@
#define QPNP_PON_RESIN_S1_TIMER(base) (base + 0x44)
#define QPNP_PON_RESIN_S2_TIMER(base) (base + 0x45)
#define QPNP_PON_RESIN_S2_CNTL(base) (base + 0x46)
+#define QPNP_PON_PS_HOLD_RST_CTL(base) (base + 0x5A)
#define QPNP_PON_RESIN_PULL_UP BIT(0)
#define QPNP_PON_KPDPWR_PULL_UP BIT(1)
@@ -50,6 +51,10 @@
#define QPNP_PON_RESIN_N_SET BIT(1)
#define QPNP_PON_RESIN_BARK_N_SET BIT(4)
+#define QPNP_PON_RESET_EN BIT(7)
+#define QPNP_PON_WARM_RESET BIT(0)
+#define QPNP_PON_SHUTDOWN BIT(2)
+
/* Ranges */
#define QPNP_PON_S1_TIMER_MAX 10256
#define QPNP_PON_S2_TIMER_MAX 2000
@@ -84,6 +89,8 @@
struct delayed_work bark_work;
};
+static struct qpnp_pon *sys_reset_dev;
+
static u32 s1_delay[PON_S1_COUNT_MAX + 1] = {
0 , 32, 56, 80, 138, 184, 272, 408, 608, 904, 1352, 2048,
3072, 4480, 6720, 10256
@@ -113,6 +120,57 @@
return rc;
}
+/**
+ * qpnp_pon_system_pwr_off - Configure system-reset PMIC for shutdown or reset
+ * @reset: Configures for shutdown if 0, or reset if 1.
+ *
+ * This function will only configure a single PMIC. The other PMICs in the
+ * system are slaved off of it and require no explicit configuration. Once
+ * the system-reset PMIC is configured properly, the MSM can drop PS_HOLD to
+ * activate the specified configuration.
+ */
+int qpnp_pon_system_pwr_off(bool reset)
+{
+ int rc;
+ struct qpnp_pon *pon = sys_reset_dev;
+
+ if (!pon)
+ return -ENODEV;
+
+ rc = qpnp_pon_masked_write(pon, QPNP_PON_PS_HOLD_RST_CTL(pon->base),
+ QPNP_PON_RESET_EN, 0);
+ if (rc)
+ dev_err(&pon->spmi->dev,
+ "Unable to write to addr=%x, rc(%d)\n",
+ QPNP_PON_PS_HOLD_RST_CTL(pon->base), rc);
+
+ /*
+ * We need 10 sleep clock cycles here. But since the clock is
+ * internally generated, we need to add 50% tolerance to be
+ * conservative.
+ */
+ udelay(500);
+
+ rc = qpnp_pon_masked_write(pon, QPNP_PON_PS_HOLD_RST_CTL(pon->base),
+ QPNP_PON_WARM_RESET | QPNP_PON_SHUTDOWN,
+ reset ? QPNP_PON_WARM_RESET : QPNP_PON_SHUTDOWN);
+ if (rc)
+ dev_err(&pon->spmi->dev,
+ "Unable to write to addr=%x, rc(%d)\n",
+ QPNP_PON_PS_HOLD_RST_CTL(pon->base), rc);
+
+ rc = qpnp_pon_masked_write(pon, QPNP_PON_PS_HOLD_RST_CTL(pon->base),
+ QPNP_PON_RESET_EN,
+ QPNP_PON_RESET_EN);
+ if (rc)
+ dev_err(&pon->spmi->dev,
+ "Unable to write to addr=%x, rc(%d)\n",
+ QPNP_PON_PS_HOLD_RST_CTL(pon->base), rc);
+
+ return rc;
+}
+EXPORT_SYMBOL(qpnp_pon_system_pwr_off);
+
static struct qpnp_pon_config *
qpnp_get_cfg(struct qpnp_pon *pon, u32 pon_type)
{
@@ -662,7 +720,7 @@
struct resource *pon_resource;
struct device_node *itr = NULL;
u32 delay = 0;
- int rc = 0;
+ int rc, sys_reset;
pon = devm_kzalloc(&spmi->dev, sizeof(struct qpnp_pon),
GFP_KERNEL);
@@ -671,6 +729,15 @@
return -ENOMEM;
}
+ sys_reset = of_property_read_bool(spmi->dev.of_node,
+ "qcom,system-reset");
+ if (sys_reset && sys_reset_dev) {
+ dev_err(&spmi->dev, "qcom,system-reset property can only be specified for one device on the system\n");
+ return -EINVAL;
+ } else if (sys_reset) {
+ sys_reset_dev = pon;
+ }
+
pon->spmi = spmi;
/* get the total number of pon configurations */
diff --git a/drivers/platform/msm/sps/bam.c b/drivers/platform/msm/sps/bam.c
index eb9e8ee..bcb4cdb 100644
--- a/drivers/platform/msm/sps/bam.c
+++ b/drivers/platform/msm/sps/bam.c
@@ -679,7 +679,7 @@
bam_write_reg_field(base, CTRL, BAM_EN, 1);
#ifdef CONFIG_SPS_SUPPORT_NDP_BAM
- bam_write_reg_field(base, CTRL, CACHE_MISS_ERR_RESP_EN, 1);
+ bam_write_reg_field(base, CTRL, CACHE_MISS_ERR_RESP_EN, 0);
bam_write_reg_field(base, CTRL, LOCAL_CLK_GATING, 1);
#endif
diff --git a/drivers/slimbus/slim-msm-ctrl.c b/drivers/slimbus/slim-msm-ctrl.c
index 6cddf2d..e2f37cc 100644
--- a/drivers/slimbus/slim-msm-ctrl.c
+++ b/drivers/slimbus/slim-msm-ctrl.c
@@ -699,7 +699,8 @@
for (i = 0; i < 6; i++)
e_addr[i] = buf[7-i];
- ret = slim_assign_laddr(&dev->ctrl, e_addr, 6, &laddr);
+ ret = slim_assign_laddr(&dev->ctrl, e_addr, 6, &laddr,
+ false);
/* Is this Qualcomm ported generic device? */
if (!ret && e_addr[5] == QC_MFGID_LSB &&
e_addr[4] == QC_MFGID_MSB &&
diff --git a/drivers/slimbus/slimbus.c b/drivers/slimbus/slimbus.c
index da2a30d..bd25875 100644
--- a/drivers/slimbus/slimbus.c
+++ b/drivers/slimbus/slimbus.c
@@ -681,13 +681,13 @@
}
static int ctrl_getlogical_addr(struct slim_controller *ctrl, const u8 *eaddr,
- u8 e_len, u8 *laddr)
+ u8 e_len, u8 *entry)
{
u8 i;
for (i = 0; i < ctrl->num_dev; i++) {
if (ctrl->addrt[i].valid &&
memcmp(ctrl->addrt[i].eaddr, eaddr, e_len) == 0) {
- *laddr = i;
+ *entry = i;
return 0;
}
}
@@ -699,23 +699,28 @@
* @ctrl: Controller with which device is enumerated.
* @e_addr: 6-byte elemental address of the device.
* @e_len: buffer length for e_addr
- * @laddr: Return logical address.
+ * @laddr: Return logical address (if valid flag is false)
+ * @valid: true if laddr holds a valid address that controller wants to
+ * set for this enumeration address. Otherwise framework sets index into
+ * address table as logical address.
* Called by controller in response to REPORT_PRESENT. Framework will assign
* a logical address to this enumeration address.
* Function returns -EXFULL to indicate that all logical addresses are already
* taken.
*/
int slim_assign_laddr(struct slim_controller *ctrl, const u8 *e_addr,
- u8 e_len, u8 *laddr)
+ u8 e_len, u8 *laddr, bool valid)
{
int ret;
u8 i = 0;
+ bool exists = false;
struct slim_device *sbdev;
mutex_lock(&ctrl->m_ctrl);
/* already assigned */
- if (ctrl_getlogical_addr(ctrl, e_addr, e_len, laddr) == 0)
- i = *laddr;
- else {
+ if (ctrl_getlogical_addr(ctrl, e_addr, e_len, &i) == 0) {
+ *laddr = ctrl->addrt[i].laddr;
+ exists = true;
+ } else {
if (ctrl->num_dev >= 254) {
ret = -EXFULL;
goto ret_assigned_laddr;
@@ -737,22 +742,26 @@
}
memcpy(ctrl->addrt[i].eaddr, e_addr, e_len);
ctrl->addrt[i].valid = true;
+ /* Preferred address is index into table */
+ if (!valid)
+ *laddr = i;
}
- ret = ctrl->set_laddr(ctrl, ctrl->addrt[i].eaddr, 6, i);
+ ret = ctrl->set_laddr(ctrl, (const u8 *)&ctrl->addrt[i].eaddr, 6,
+ *laddr);
if (ret) {
ctrl->addrt[i].valid = false;
goto ret_assigned_laddr;
}
- *laddr = i;
+ ctrl->addrt[i].laddr = *laddr;
- dev_dbg(&ctrl->dev, "setting slimbus l-addr:%x\n", i);
+ dev_dbg(&ctrl->dev, "setting slimbus l-addr:%x\n", *laddr);
ret_assigned_laddr:
mutex_unlock(&ctrl->m_ctrl);
- if (ret)
+ if (exists || ret)
return ret;
- pr_info("slimbus laddr:0x%x, EAPC:0x%x:0x%x", i,
+ pr_info("slimbus:%d laddr:0x%x, EAPC:0x%x:0x%x", ctrl->nr, *laddr,
e_addr[1], e_addr[2]);
mutex_lock(&ctrl->m_ctrl);
list_for_each_entry(sbdev, &ctrl->devs, dev_list) {
@@ -785,12 +794,21 @@
u8 e_len, u8 *laddr)
{
int ret = 0;
+ u8 entry;
struct slim_controller *ctrl = sb->ctrl;
if (!ctrl || !laddr || !e_addr || e_len != 6)
return -EINVAL;
mutex_lock(&ctrl->m_ctrl);
- ret = ctrl_getlogical_addr(ctrl, e_addr, e_len, laddr);
+ ret = ctrl_getlogical_addr(ctrl, e_addr, e_len, &entry);
+ if (!ret)
+ *laddr = ctrl->addrt[entry].laddr;
mutex_unlock(&ctrl->m_ctrl);
+ if (ret == -ENXIO && ctrl->get_laddr) {
+ ret = ctrl->get_laddr(ctrl, e_addr, e_len, laddr);
+ if (!ret)
+ ret = slim_assign_laddr(ctrl, e_addr, e_len, laddr,
+ true);
+ }
return ret;
}
EXPORT_SYMBOL_GPL(slim_get_logical_addr);
@@ -943,8 +961,6 @@
u16 ec;
u8 tid, mlen = 6;
- if (sbdev->laddr != SLIM_LA_MANAGER && sbdev->laddr >= ctrl->num_dev)
- return -ENXIO;
ret = slim_ele_access_sanity(msg, mc, rbuf, wbuf, len);
if (ret)
goto xfer_err;
@@ -2641,7 +2657,15 @@
slc->state = SLIM_CH_SUSPENDED;
}
- ret = slim_allocbw(sb, &subframe, &clkgear);
+ /*
+ * Controller can override default channel scheduling algorithm.
+ * (e.g. if controller needs to use fixed channel scheduling based
+ * on number of channels)
+ */
+ if (ctrl->allocbw)
+ ret = ctrl->allocbw(sb, &subframe, &clkgear);
+ else
+ ret = slim_allocbw(sb, &subframe, &clkgear);
if (!ret) {
ret = slim_processtxn(ctrl, SLIM_MSG_DEST_BROADCAST,
diff --git a/drivers/usb/misc/ks_bridge.c b/drivers/usb/misc/ks_bridge.c
index 8753c0d..87f43e1c 100644
--- a/drivers/usb/misc/ks_bridge.c
+++ b/drivers/usb/misc/ks_bridge.c
@@ -262,6 +262,8 @@
return;
}
+ usb_free_urb(urb);
+
spin_lock_irqsave(&ksb->lock, flags);
}
spin_unlock_irqrestore(&ksb->lock, flags);
diff --git a/drivers/usb/otg/msm_otg.c b/drivers/usb/otg/msm_otg.c
index 5637f19..998978c 100644
--- a/drivers/usb/otg/msm_otg.c
+++ b/drivers/usb/otg/msm_otg.c
@@ -69,6 +69,13 @@
#define USB_SUSPEND_DELAY_TIME (500 * HZ/1000) /* 500 msec */
+enum msm_otg_phy_reg_mode {
+ USB_PHY_REG_OFF,
+ USB_PHY_REG_ON,
+ USB_PHY_REG_LPM_ON,
+ USB_PHY_REG_LPM_OFF,
+};
+
static DECLARE_COMPLETION(pmic_vbus_init);
static struct msm_otg *the_msm_otg;
static bool debug_aca_enabled;
@@ -168,7 +175,8 @@
return ret;
}
-static int msm_hsusb_ldo_enable(struct msm_otg *motg, int on)
+static int msm_hsusb_ldo_enable(struct msm_otg *motg,
+ enum msm_otg_phy_reg_mode mode)
{
int ret = 0;
@@ -182,7 +190,8 @@
return -ENODEV;
}
- if (on) {
+ switch (mode) {
+ case USB_PHY_REG_ON:
ret = regulator_set_optimum_mode(hsusb_1p8,
USB_PHY_1P8_HPM_LOAD);
if (ret < 0) {
@@ -219,7 +228,9 @@
return ret;
}
- } else {
+ break;
+
+ case USB_PHY_REG_OFF:
ret = regulator_disable(hsusb_1p8);
if (ret) {
dev_err(motg->phy.dev, "%s: unable to disable the hsusb 1p8\n",
@@ -242,9 +253,55 @@
if (ret < 0)
pr_err("%s: Unable to set LPM of the regulator:"
"HSUSB_3p3\n", __func__);
+
+ break;
+
+ case USB_PHY_REG_LPM_ON:
+ ret = regulator_set_optimum_mode(hsusb_1p8,
+ USB_PHY_1P8_LPM_LOAD);
+ if (ret < 0) {
+ pr_err("%s: Unable to set LPM of the regulator: HSUSB_1p8\n",
+ __func__);
+ return ret;
+ }
+
+ ret = regulator_set_optimum_mode(hsusb_3p3,
+ USB_PHY_3P3_LPM_LOAD);
+ if (ret < 0) {
+ pr_err("%s: Unable to set LPM of the regulator: HSUSB_3p3\n",
+ __func__);
+ regulator_set_optimum_mode(hsusb_1p8, USB_PHY_REG_ON);
+ return ret;
+ }
+
+ break;
+
+ case USB_PHY_REG_LPM_OFF:
+ ret = regulator_set_optimum_mode(hsusb_1p8,
+ USB_PHY_1P8_HPM_LOAD);
+ if (ret < 0) {
+ pr_err("%s: Unable to set HPM of the regulator: HSUSB_1p8\n",
+ __func__);
+ return ret;
+ }
+
+ ret = regulator_set_optimum_mode(hsusb_3p3,
+ USB_PHY_3P3_HPM_LOAD);
+ if (ret < 0) {
+ pr_err("%s: Unable to set HPM of the regulator: HSUSB_3p3\n",
+ __func__);
+ regulator_set_optimum_mode(hsusb_1p8, USB_PHY_REG_ON);
+ return ret;
+ }
+
+ break;
+
+ default:
+ pr_err("%s: Unsupported mode (%d).", __func__, mode);
+ return -ENOTSUPP;
}
- pr_debug("reg (%s)\n", on ? "HPM" : "LPM");
+ pr_debug("%s: USB reg mode (%d) (OFF/HPM/LPM)\n", __func__, mode);
return ret < 0 ? ret : 0;
}
@@ -881,8 +938,12 @@
if (motg->caps & ALLOW_PHY_POWER_COLLAPSE &&
!host_bus_suspend && !dcp) {
- msm_hsusb_ldo_enable(motg, 0);
+ msm_hsusb_ldo_enable(motg, USB_PHY_REG_OFF);
motg->lpm_flags |= PHY_PWR_COLLAPSED;
+ } else if (motg->caps & ALLOW_PHY_REGULATORS_LPM &&
+ !host_bus_suspend && !device_bus_suspend && !dcp) {
+ msm_hsusb_ldo_enable(motg, USB_PHY_REG_LPM_ON);
+ motg->lpm_flags |= PHY_REGULATORS_LPM;
}
if (motg->lpm_flags & PHY_RETENTIONED) {
@@ -946,8 +1007,11 @@
}
if (motg->lpm_flags & PHY_PWR_COLLAPSED) {
- msm_hsusb_ldo_enable(motg, 1);
+ msm_hsusb_ldo_enable(motg, USB_PHY_REG_ON);
motg->lpm_flags &= ~PHY_PWR_COLLAPSED;
+ } else if (motg->lpm_flags & PHY_REGULATORS_LPM) {
+ msm_hsusb_ldo_enable(motg, USB_PHY_REG_LPM_OFF);
+ motg->lpm_flags &= ~PHY_REGULATORS_LPM;
}
if (motg->lpm_flags & PHY_RETENTIONED) {
@@ -3622,7 +3686,7 @@
}
}
- ret = msm_hsusb_ldo_enable(motg, 1);
+ ret = msm_hsusb_ldo_enable(motg, USB_PHY_REG_ON);
if (ret) {
dev_err(&pdev->dev, "hsusb vreg enable failed\n");
goto free_ldo_init;
@@ -3724,7 +3788,8 @@
ALLOW_PHY_RETENTION;
if (motg->pdata->otg_control == OTG_PHY_CONTROL)
- motg->caps = ALLOW_PHY_RETENTION;
+ motg->caps = ALLOW_PHY_RETENTION |
+ ALLOW_PHY_REGULATORS_LPM;
}
if (motg->pdata->enable_lpm_on_dev_suspend)
@@ -3756,7 +3821,7 @@
destroy_wlock:
wake_lock_destroy(&motg->wlock);
clk_disable_unprepare(motg->core_clk);
- msm_hsusb_ldo_enable(motg, 0);
+ msm_hsusb_ldo_enable(motg, USB_PHY_REG_OFF);
free_ldo_init:
msm_hsusb_ldo_init(motg, 0);
free_hsusb_vddcx:
@@ -3843,7 +3908,7 @@
clk_disable_unprepare(motg->pclk);
clk_disable_unprepare(motg->core_clk);
msm_xo_put(motg->xo_handle);
- msm_hsusb_ldo_enable(motg, 0);
+ msm_hsusb_ldo_enable(motg, USB_PHY_REG_OFF);
msm_hsusb_ldo_init(motg, 0);
regulator_disable(hsusb_vddcx);
regulator_set_voltage(hsusb_vddcx,
diff --git a/drivers/video/msm/mdp.c b/drivers/video/msm/mdp.c
index 6e3567f..f6d9eb7 100644
--- a/drivers/video/msm/mdp.c
+++ b/drivers/video/msm/mdp.c
@@ -606,7 +606,7 @@
static int mdp_hist_init_mgmt(struct mdp_hist_mgmt *mgmt, uint32_t block)
{
- uint32_t bins, extra, index, term = 0;
+ uint32_t bins, extra, index, intr = 0, term = 0;
init_completion(&mgmt->mdp_hist_comp);
mutex_init(&mgmt->mdp_hist_mutex);
mutex_init(&mgmt->mdp_do_hist_mutex);
@@ -622,6 +622,8 @@
switch (block) {
case MDP_BLOCK_DMA_P:
term = MDP_HISTOGRAM_TERM_DMA_P;
+ intr = (mdp_rev >= MDP_REV_40) ? INTR_DMA_P_HISTOGRAM :
+ MDP_HIST_DONE;
bins = (mdp_rev >= MDP_REV_42) ? MDP_REV42_HIST_MAX_BIN :
MDP_REV41_HIST_MAX_BIN;
extra = 2;
@@ -630,6 +632,7 @@
break;
case MDP_BLOCK_DMA_S:
term = MDP_HISTOGRAM_TERM_DMA_S;
+ intr = INTR_DMA_S_HISTOGRAM;
bins = MDP_REV42_HIST_MAX_BIN;
extra = 2;
mgmt->base += 0x5000;
@@ -637,6 +640,7 @@
break;
case MDP_BLOCK_VG_1:
term = MDP_HISTOGRAM_TERM_VG_1;
+ intr = INTR_VG1_HISTOGRAM;
bins = MDP_REV42_HIST_MAX_BIN;
extra = 1;
mgmt->base += 0x6000;
@@ -644,6 +648,7 @@
break;
case MDP_BLOCK_VG_2:
term = MDP_HISTOGRAM_TERM_VG_2;
+ intr = INTR_VG2_HISTOGRAM;
bins = MDP_REV42_HIST_MAX_BIN;
extra = 1;
mgmt->base += 0x6000;
@@ -651,6 +656,8 @@
break;
default:
term = MDP_HISTOGRAM_TERM_DMA_P;
+ intr = (mdp_rev >= MDP_REV_40) ? INTR_DMA_P_HISTOGRAM :
+ MDP_HIST_DONE;
bins = (mdp_rev >= MDP_REV_42) ? MDP_REV42_HIST_MAX_BIN :
MDP_REV41_HIST_MAX_BIN;
extra = 2;
@@ -658,6 +665,7 @@
index = MDP_HIST_MGMT_DMA_P;
}
mgmt->irq_term = term;
+ mgmt->intr = intr;
mgmt->c0 = kmalloc(bins * sizeof(uint32_t), GFP_KERNEL);
if (mgmt->c0 == NULL)
@@ -802,20 +810,45 @@
static int mdp_histogram_enable(struct mdp_hist_mgmt *mgmt)
{
uint32_t base;
+ unsigned long flag;
if (mgmt->mdp_is_hist_data == TRUE) {
pr_err("%s histogram already started\n", __func__);
return -EINVAL;
}
mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_ON, FALSE);
- mdp_enable_irq(mgmt->irq_term);
+ base = (uint32_t) (MDP_BASE + mgmt->base);
+ /*First make sure that device is not collecting histogram*/
+ mgmt->mdp_is_hist_data = FALSE;
+ mgmt->mdp_is_hist_valid = FALSE;
+ mgmt->mdp_is_hist_init = FALSE;
+ spin_lock_irqsave(&mdp_spin_lock, flag);
+ outp32(MDP_INTR_CLEAR, mgmt->intr);
+ mdp_intr_mask &= ~mgmt->intr;
+ outp32(MDP_INTR_ENABLE, mdp_intr_mask);
+ MDP_OUTP(base + 0x001C, 0);
+ MDP_OUTP(base + 0x0018, INTR_HIST_DONE | INTR_HIST_RESET_SEQ_DONE);
+ MDP_OUTP(base + 0x0024, 0);
+ spin_unlock_irqrestore(&mdp_spin_lock, flag);
+
+ mutex_unlock(&mgmt->mdp_hist_mutex);
+ cancel_work_sync(&mgmt->mdp_histogram_worker);
+ mutex_lock(&mgmt->mdp_hist_mutex);
+
+ /*Then initialize histogram*/
INIT_COMPLETION(mgmt->mdp_hist_comp);
- base = (uint32_t) (MDP_BASE + mgmt->base);
+ spin_lock_irqsave(&mdp_spin_lock, flag);
MDP_OUTP(base + 0x0018, INTR_HIST_DONE | INTR_HIST_RESET_SEQ_DONE);
MDP_OUTP(base + 0x0010, 1);
MDP_OUTP(base + 0x001C, INTR_HIST_DONE | INTR_HIST_RESET_SEQ_DONE);
+ outp32(MDP_INTR_CLEAR, mgmt->intr);
+ mdp_intr_mask |= mgmt->intr;
+ outp32(MDP_INTR_ENABLE, mdp_intr_mask);
+ mdp_enable_irq(mgmt->irq_term);
+ spin_unlock_irqrestore(&mdp_spin_lock, flag);
+
MDP_OUTP(base + 0x0004, mgmt->frame_cnt);
if (mgmt->block != MDP_BLOCK_VG_1 && mgmt->block != MDP_BLOCK_VG_2)
MDP_OUTP(base + 0x0008, mgmt->bit_mask);
@@ -830,6 +863,7 @@
static int mdp_histogram_disable(struct mdp_hist_mgmt *mgmt)
{
uint32_t base, status;
+ unsigned long flag;
if (mgmt->mdp_is_hist_data == FALSE) {
pr_err("%s histogram already stopped\n", __func__);
return -EINVAL;
@@ -842,6 +876,13 @@
base = (uint32_t) (MDP_BASE + mgmt->base);
mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_ON, FALSE);
+ spin_lock_irqsave(&mdp_spin_lock, flag);
+ outp32(MDP_INTR_CLEAR, mgmt->intr);
+ mdp_intr_mask &= ~mgmt->intr;
+ outp32(MDP_INTR_ENABLE, mdp_intr_mask);
+ mdp_disable_irq(mgmt->irq_term);
+ spin_unlock_irqrestore(&mdp_spin_lock, flag);
+
if (mdp_rev >= MDP_REV_42)
MDP_OUTP(base + 0x0020, 1);
status = inpdw(base + 0x001C);
@@ -856,7 +897,6 @@
complete(&mgmt->mdp_hist_comp);
}
- mdp_disable_irq(mgmt->irq_term);
return 0;
}
@@ -1102,6 +1142,7 @@
struct mdp_hist_mgmt *mgmt = container_of(data, struct mdp_hist_mgmt,
mdp_histogram_worker);
int ret = 0;
+ bool hist_ready;
mutex_lock(&mgmt->mdp_hist_mutex);
if (mgmt->mdp_is_hist_data == FALSE) {
pr_debug("%s, Histogram disabled before read.\n", __func__);
@@ -1116,8 +1157,9 @@
pr_err("mgmt->hist invalid NULL\n");
ret = -EINVAL;
}
+ hist_ready = (mgmt->mdp_is_hist_init && mgmt->mdp_is_hist_valid);
- if (!ret) {
+ if (!ret && hist_ready) {
switch (mgmt->block) {
case MDP_BLOCK_DMA_P:
case MDP_BLOCK_DMA_S:
@@ -1138,7 +1180,7 @@
* if read was triggered by an underrun or failed copying,
* don't wake up readers
*/
- if (!ret && mgmt->mdp_is_hist_valid && mgmt->mdp_is_hist_init) {
+ if (!ret && hist_ready) {
mgmt->hist = NULL;
if (waitqueue_active(&mgmt->mdp_hist_comp.wait))
complete(&mgmt->mdp_hist_comp);
@@ -1150,7 +1192,7 @@
mgmt->mdp_is_hist_init = TRUE;
mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_ON, FALSE);
- if (!ret)
+ if (!ret && hist_ready)
__mdp_histogram_kickoff(mgmt);
else
__mdp_histogram_reset(mgmt);
@@ -1728,10 +1770,8 @@
isr &= mask;
if (isr & INTR_HIST_RESET_SEQ_DONE)
__mdp_histogram_kickoff(mgmt);
-
- if (isr & INTR_HIST_DONE) {
+ else if (isr & INTR_HIST_DONE)
queue_work(mdp_hist_wq, &mgmt->mdp_histogram_worker);
- }
}
#ifndef CONFIG_FB_MSM_MDP40
@@ -1741,7 +1781,6 @@
struct mdp_dma_data *dma;
unsigned long flag;
struct mdp_hist_mgmt *mgmt = NULL;
- char *base_addr;
int i, ret;
int vsync_isr;
/* Ensure all the register write are complete */
@@ -1813,13 +1852,7 @@
mgmt = mdp_hist_mgmt_array[i];
if (!mgmt)
continue;
-
- base_addr = MDP_BASE + mgmt->base;
- outpdw(base_addr + 0x010, 1);
- outpdw(base_addr + 0x01C, INTR_HIST_DONE |
- INTR_HIST_RESET_SEQ_DONE);
mgmt->mdp_is_hist_valid = FALSE;
- __mdp_histogram_reset(mgmt);
}
}
diff --git a/drivers/video/msm/mdp.h b/drivers/video/msm/mdp.h
index 1397507..371174c 100644
--- a/drivers/video/msm/mdp.h
+++ b/drivers/video/msm/mdp.h
@@ -256,6 +256,7 @@
struct mdp_hist_mgmt {
uint32_t block;
uint32_t irq_term;
+ uint32_t intr;
uint32_t base;
struct completion mdp_hist_comp;
struct mutex mdp_hist_mutex;
@@ -323,6 +324,14 @@
#define TV_OUT_DMA3_START BIT(13)
#define MDP_HIST_DONE BIT(20)
+/*MDP4 MDP histogram interrupts*/
+/*note: these are only applicable on MDP4+ targets*/
+#define INTR_VG1_HISTOGRAM BIT(5)
+#define INTR_VG2_HISTOGRAM BIT(6)
+#define INTR_DMA_P_HISTOGRAM BIT(17)
+#define INTR_DMA_S_HISTOGRAM BIT(26)
+/*end MDP4 MDP histogram interrupts*/
+
/* histogram interrupts */
#define INTR_HIST_DONE BIT(1)
#define INTR_HIST_RESET_SEQ_DONE BIT(0)
@@ -337,7 +346,6 @@
MDP_DMA_S_DONE| \
MDP_DMA_E_DONE| \
LCDC_UNDERFLOW| \
- MDP_HIST_DONE| \
TV_ENC_UNDERRUN)
#endif
diff --git a/drivers/video/msm/mdp4.h b/drivers/video/msm/mdp4.h
index 6fc83df..005e87c 100644
--- a/drivers/video/msm/mdp4.h
+++ b/drivers/video/msm/mdp4.h
@@ -111,33 +111,23 @@
};
/* system interrupts */
+/*note histogram interrupts defined in mdp.h*/
#define INTR_OVERLAY0_DONE BIT(0)
#define INTR_OVERLAY1_DONE BIT(1)
#define INTR_DMA_S_DONE BIT(2)
#define INTR_DMA_E_DONE BIT(3)
#define INTR_DMA_P_DONE BIT(4)
-#define INTR_VG1_HISTOGRAM BIT(5)
-#define INTR_VG2_HISTOGRAM BIT(6)
#define INTR_PRIMARY_VSYNC BIT(7)
#define INTR_PRIMARY_INTF_UDERRUN BIT(8)
#define INTR_EXTERNAL_VSYNC BIT(9)
#define INTR_EXTERNAL_INTF_UDERRUN BIT(10)
#define INTR_PRIMARY_RDPTR BIT(11) /* read pointer */
-#define INTR_DMA_P_HISTOGRAM BIT(17)
-#define INTR_DMA_S_HISTOGRAM BIT(26)
#define INTR_OVERLAY2_DONE BIT(30)
#ifdef CONFIG_FB_MSM_OVERLAY
-#define MDP4_ANY_INTR_MASK (INTR_DMA_P_HISTOGRAM | \
- INTR_DMA_S_HISTOGRAM | \
- INTR_VG1_HISTOGRAM | \
- INTR_VG2_HISTOGRAM)
+#define MDP4_ANY_INTR_MASK (0)
#else
-#define MDP4_ANY_INTR_MASK (INTR_DMA_P_DONE| \
- INTR_DMA_P_HISTOGRAM | \
- INTR_DMA_S_HISTOGRAM | \
- INTR_VG1_HISTOGRAM | \
- INTR_VG2_HISTOGRAM)
+#define MDP4_ANY_INTR_MASK (INTR_DMA_P_DONE)
#endif
enum {
diff --git a/drivers/video/msm/mdp4_overlay.c b/drivers/video/msm/mdp4_overlay.c
index 63f0aa1..18cf817 100644
--- a/drivers/video/msm/mdp4_overlay.c
+++ b/drivers/video/msm/mdp4_overlay.c
@@ -3092,6 +3092,7 @@
int mdp4_overlay_unset_mixer(int mixer)
{
struct mdp4_overlay_pipe *pipe;
+ struct mdp4_overlay_pipe *orgpipe;
int i, cnt = 0;
/* free pipe besides base layer pipe */
@@ -3103,6 +3104,10 @@
mdp4_overlay_reg_flush(pipe, 1);
mdp4_mixer_stage_down(pipe, 1);
mdp4_overlay_pipe_free(pipe);
+ /*Clear real pipe attributes as well */
+ orgpipe = mdp4_overlay_ndx2pipe(pipe->pipe_ndx);
+ if (orgpipe != NULL)
+ orgpipe->pipe_used = 0;
cnt++;
}
diff --git a/drivers/video/msm/mdp4_overlay_dsi_video.c b/drivers/video/msm/mdp4_overlay_dsi_video.c
index fcdccca..2d21929 100644
--- a/drivers/video/msm/mdp4_overlay_dsi_video.c
+++ b/drivers/video/msm/mdp4_overlay_dsi_video.c
@@ -677,6 +677,11 @@
/* adb stop */
if (pipe->pipe_type == OVERLAY_TYPE_BF)
mdp4_overlay_borderfill_stage_down(pipe);
+
+ /* base pipe may change after borderfill_stage_down */
+ pipe = vctrl->base_pipe;
+ mdp4_mixer_stage_down(pipe, 1);
+ mdp4_overlay_pipe_free(pipe);
vctrl->base_pipe = NULL;
} else {
/* system suspending */
diff --git a/drivers/video/msm/mdp4_overlay_dtv.c b/drivers/video/msm/mdp4_overlay_dtv.c
index f3bd775..f01543b 100644
--- a/drivers/video/msm/mdp4_overlay_dtv.c
+++ b/drivers/video/msm/mdp4_overlay_dtv.c
@@ -579,6 +579,10 @@
if (pipe->pipe_type == OVERLAY_TYPE_BF)
mdp4_overlay_borderfill_stage_down(pipe);
+ /* base pipe may change after borderfill_stage_down */
+ pipe = vctrl->base_pipe;
+ mdp4_mixer_stage_down(pipe, 1);
+ mdp4_overlay_pipe_free(pipe);
/* pipe == rgb2 */
vctrl->base_pipe = NULL;
} else {
@@ -1009,6 +1013,8 @@
}
mutex_lock(&mfd->dma->ov_mutex);
+ mdp4_overlay_mdp_perf_upd(mfd, 1);
mdp4_dtv_pipe_commit();
+ mdp4_overlay_mdp_perf_upd(mfd, 0);
mutex_unlock(&mfd->dma->ov_mutex);
}
diff --git a/drivers/video/msm/mdp4_overlay_lcdc.c b/drivers/video/msm/mdp4_overlay_lcdc.c
index 323a8fe..bc8ded5 100644
--- a/drivers/video/msm/mdp4_overlay_lcdc.c
+++ b/drivers/video/msm/mdp4_overlay_lcdc.c
@@ -664,6 +664,11 @@
/* adb stop */
if (pipe->pipe_type == OVERLAY_TYPE_BF)
mdp4_overlay_borderfill_stage_down(pipe);
+
+ /* base pipe may change after borderfill_stage_down */
+ pipe = vctrl->base_pipe;
+ mdp4_mixer_stage_down(pipe, 1);
+ mdp4_overlay_pipe_free(pipe);
vctrl->base_pipe = NULL;
} else {
/* system suspending */
diff --git a/drivers/video/msm/mdp4_util.c b/drivers/video/msm/mdp4_util.c
index 359f37e..b35acfb 100644
--- a/drivers/video/msm/mdp4_util.c
+++ b/drivers/video/msm/mdp4_util.c
@@ -500,7 +500,6 @@
uint32 isr, mask, panel;
struct mdp_dma_data *dma;
struct mdp_hist_mgmt *mgmt = NULL;
- char *base_addr;
int i, ret;
mdp_is_in_isr = TRUE;
@@ -528,12 +527,7 @@
mgmt = mdp_hist_mgmt_array[i];
if (!mgmt)
continue;
- base_addr = MDP_BASE + mgmt->base;
- MDP_OUTP(base_addr + 0x010, 1);
- outpdw(base_addr + 0x01c, INTR_HIST_DONE |
- INTR_HIST_RESET_SEQ_DONE);
mgmt->mdp_is_hist_valid = FALSE;
- __mdp_histogram_reset(mgmt);
}
}
diff --git a/drivers/video/msm/mdss/mdss_mdp_wb.c b/drivers/video/msm/mdss/mdss_mdp_wb.c
index bd5f464..b0a67938 100644
--- a/drivers/video/msm/mdss/mdss_mdp_wb.c
+++ b/drivers/video/msm/mdss/mdss_mdp_wb.c
@@ -388,7 +388,7 @@
ret = -ENOBUFS;
}
mutex_unlock(&wb->lock);
- return 0;
+ return ret;
}
static void mdss_mdp_wb_callback(void *arg)
diff --git a/include/linux/qpnp/power-on.h b/include/linux/qpnp/power-on.h
new file mode 100644
index 0000000..85dbce9
--- /dev/null
+++ b/include/linux/qpnp/power-on.h
@@ -0,0 +1,24 @@
+/* Copyright (c) 2012, The Linux Foundation. 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 QPNP_PON_H
+#define QPNP_PON_H
+
+#include <linux/errno.h>
+
+#ifdef CONFIG_QPNP_POWER_ON
+int qpnp_pon_system_pwr_off(bool reset);
+#else
+static int qpnp_pon_system_pwr_off(bool reset) { return -ENODEV; }
+#endif
+
+#endif
diff --git a/include/linux/slimbus/slimbus.h b/include/linux/slimbus/slimbus.h
index d365b15..e333235 100644
--- a/include/linux/slimbus/slimbus.h
+++ b/include/linux/slimbus/slimbus.h
@@ -143,10 +143,15 @@
* struct slim_addrt: slimbus address used internally by the slimbus framework.
* @valid: If the device is still there or if the address can be reused.
* @eaddr: 6-bytes-long elemental address
+ * @laddr: It is possible that controller will set a predefined logical address
+ * rather than the one assigned by framework. (i.e. logical address may
+ * not be same as index into this table). This entry will store the
+ * logical address value for this enumeration address.
*/
struct slim_addrt {
bool valid;
u8 eaddr[6];
+ u8 laddr;
};
/*
@@ -498,6 +503,11 @@
* @set_laddr: Setup logical address at laddr for the slave with elemental
* address e_addr. Drivers implementing controller will be expected to
* send unicast message to this device with its logical address.
+ * @allocbw: Controller can override default reconfiguration and channel
+ * scheduling algorithm.
+ * @get_laddr: It is possible that controller needs to set fixed logical
+ * address table and get_laddr can be used in that case so that controller
+ * can do this assignment.
* @wakeup: This function pointer implements controller-specific procedure
* to wake it up from clock-pause. Framework will call this to bring
* the controller out of clock pause.
@@ -542,6 +552,10 @@
struct slim_msg_txn *txn);
int (*set_laddr)(struct slim_controller *ctrl,
const u8 *ea, u8 elen, u8 laddr);
+ int (*allocbw)(struct slim_device *sb,
+ int *subfrmc, int *clkgear);
+ int (*get_laddr)(struct slim_controller *ctrl,
+ const u8 *ea, u8 elen, u8 *laddr);
int (*wakeup)(struct slim_controller *ctrl);
int (*config_port)(struct slim_controller *ctrl,
u8 port);
@@ -979,14 +993,17 @@
* @ctrl: Controller with which device is enumerated.
* @e_addr: 6-byte elemental address of the device.
* @e_len: buffer length for e_addr
- * @laddr: Return logical address.
+ * @laddr: Return logical address (if valid flag is false)
+ * @valid: true if laddr holds a valid address that controller wants to
+ * set for this enumeration address. Otherwise framework sets index into
+ * address table as logical address.
* Called by controller in response to REPORT_PRESENT. Framework will assign
* a logical address to this enumeration address.
* Function returns -EXFULL to indicate that all logical addresses are already
* taken.
*/
extern int slim_assign_laddr(struct slim_controller *ctrl, const u8 *e_addr,
- u8 e_len, u8 *laddr);
+ u8 e_len, u8 *laddr, bool valid);
/*
* slim_msg_response: Deliver Message response received from a device to the
diff --git a/include/linux/usb/msm_hsusb.h b/include/linux/usb/msm_hsusb.h
index adcc450..8e6550f 100644
--- a/include/linux/usb/msm_hsusb.h
+++ b/include/linux/usb/msm_hsusb.h
@@ -348,7 +348,7 @@
/*
* Allowing PHY power collpase turns off the HSUSB 3.3v and 1.8v
* analog regulators while going to low power mode.
- * Currently only 8960(28nm PHY) has the support to allowing PHY
+ * Currently only 28nm PHY has the support to allowing PHY
* power collapse since it doesn't have leakage currents while
* turning off the power rails.
*/
@@ -362,12 +362,18 @@
* Allow putting the core in Low Power mode, when
* USB bus is suspended but cable is connected.
*/
-#define ALLOW_LPM_ON_DEV_SUSPEND BIT(2)
+#define ALLOW_LPM_ON_DEV_SUSPEND BIT(2)
+ /*
+ * Allowing PHY regulators LPM puts the HSUSB 3.3v and 1.8v
+ * analog regulators into LPM while going to USB low power mode.
+ */
+#define ALLOW_PHY_REGULATORS_LPM BIT(3)
unsigned long lpm_flags;
#define PHY_PWR_COLLAPSED BIT(0)
#define PHY_RETENTIONED BIT(1)
#define XO_SHUTDOWN BIT(2)
#define CLOCKS_DOWN BIT(3)
+#define PHY_REGULATORS_LPM BIT(4)
int reset_counter;
unsigned long b_last_se0_sess;
unsigned long tmouts;
diff --git a/include/trace/events/exception.h b/include/trace/events/exception.h
new file mode 100644
index 0000000..110e920
--- /dev/null
+++ b/include/trace/events/exception.h
@@ -0,0 +1,68 @@
+/* Copyright (c) 2012, The Linux Foundation. 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.
+ */
+
+#undef TRACE_SYSTEM
+#define TRACE_SYSTEM exception
+
+#if !defined(_TRACE_EXCEPTION_H) || defined(TRACE_HEADER_MULTI_READ)
+#define _TRACE_EXCEPTION_H
+
+#include <linux/tracepoint.h>
+
+struct task_struct;
+
+TRACE_EVENT(user_fault,
+
+ TP_PROTO(struct task_struct *tsk, unsigned long addr, unsigned int fsr),
+
+ TP_ARGS(tsk, addr, fsr),
+
+ TP_STRUCT__entry(
+ __string(task_name, tsk->comm)
+ __field(unsigned long, addr)
+ __field(unsigned int, fsr)
+ ),
+
+ TP_fast_assign(
+ __assign_str(task_name, tsk->comm)
+ __entry->addr = addr;
+ __entry->fsr = fsr;
+ ),
+
+ TP_printk("task_name:%s addr:%lu, fsr:%u", __get_str(task_name),\
+ __entry->addr, __entry->fsr)
+);
+
+struct pt_regs;
+
+TRACE_EVENT(undef_instr,
+
+ TP_PROTO(struct pt_regs *regs, void *prog_cnt),
+
+ TP_ARGS(regs, prog_cnt),
+
+ TP_STRUCT__entry(
+ __field(void *, prog_cnt)
+ __field(struct pt_regs *, regs)
+ ),
+
+ TP_fast_assign(
+ __entry->regs = regs;
+ __entry->prog_cnt = prog_cnt;
+ ),
+
+ TP_printk("pc:%p", __entry->prog_cnt)
+);
+
+#endif
+
+#include <trace/define_trace.h>
diff --git a/sound/soc/msm/apq8064.c b/sound/soc/msm/apq8064.c
index 9bc565e..80d6e5d 100644
--- a/sound/soc/msm/apq8064.c
+++ b/sound/soc/msm/apq8064.c
@@ -1310,6 +1310,24 @@
return 0;
}
+static int msm_slim_4_rx_be_hw_params_fixup(struct snd_soc_pcm_runtime *rtd,
+ struct snd_pcm_hw_params *params)
+{
+ struct snd_interval *rate = hw_param_interval(params,
+ SNDRV_PCM_HW_PARAM_RATE);
+
+ struct snd_interval *channels = hw_param_interval(params,
+ SNDRV_PCM_HW_PARAM_CHANNELS);
+
+ rate->min = rate->max = 48000;
+ channels->min = channels->max = 1;
+
+ pr_debug("%s channels->min %u channels->max %u ()\n", __func__,
+ channels->min, channels->max);
+ return 0;
+}
+
+
static int msm_be_hw_params_fixup(struct snd_soc_pcm_runtime *rtd,
struct snd_pcm_hw_params *params)
{
@@ -2002,7 +2020,7 @@
.codec_dai_name = "msm-stub-rx",
.no_pcm = 1,
.be_id = MSM_BACKEND_DAI_SLIMBUS_4_RX,
- .be_hw_params_fixup = msm_be_hw_params_fixup,
+ .be_hw_params_fixup = msm_slim_4_rx_be_hw_params_fixup,
.ops = &msm_slimbus_4_be_ops,
.ignore_pmdown_time = 1, /* this dainlink has playback support */
},