Merge "Asoc: msm: Reduce capture buffer size." into msm-3.0
diff --git a/Documentation/devicetree/bindings/usb/msm-hsusb.txt b/Documentation/devicetree/bindings/usb/msm-hsusb.txt
new file mode 100644
index 0000000..c1399ae
--- /dev/null
+++ b/Documentation/devicetree/bindings/usb/msm-hsusb.txt
@@ -0,0 +1,51 @@
+MSM SoC HSUSB controllers
+
+OTG:
+
+Required properties :
+- compatible : should be "qcom,hsusb-otg"
+- regs : offset and length of the register set in the memory map
+- interrupts: IRQ line
+- qcom,hsusb-otg-phy-type: PHY type can be one of
+ 1 - Chipidea 45nm PHY
+ 2 - Synopsis 28nm PHY
+- qcom,hsusb-otg-mode: Operational mode. Can be one of
+ 1 - Peripheral only mode
+ 2 - Host only mode
+ 3 - OTG mode
+ Based on the mode, OTG driver registers platform devices for
+ gadget and host.
+- qcom,hsusb-otg-control: OTG control (VBUS and ID notifications)
+ can be one of
+ 1 - PHY control
+ 2 - PMIC control
+ 3 - User control (via debugfs)
+
+Optional properties :
+- qcom,hsusb-otg-default-mode: The default USB mode after boot-up.
+ Applicable only when OTG is controlled by user. Can be one of
+ 0 - None. Low power mode
+ 1 - Peripheral
+ 2 - Host
+- qcom,hsusb-otg-phy-init-seq: PHY configuration sequence. val, reg pairs
+ terminate with -1
+- qcom,hsusb-otg-power-budget: VBUS power budget in mA
+ 0 will be treated as 500mA
+- qcom,hsusb-otg-pclk-src-name: The source of pclk
+- qcom,hsusb-otg-pmic-id-irq: ID, routed to PMIC IRQ number
+
+Example HSUSB OTG controller device node :
+ usb@F9690000 {
+ compatible = "qcom,hsusb-otg";
+ reg = <0xF9690000 0x400>;
+ interrupts = <134>;
+
+ qcom,hsusb-otg-phy-type = <2>;
+ qcom,hsusb-otg-mode = <1>;
+ qcom,hsusb-otg-otg-control = <1>;
+ qcom,hsusb-otg-default-mode = <2>;
+ qcom,hsusb-otg-phy-init-seq = <0x01 0x90 0xFFFFFFFF>;
+ qcom,hsusb-otg-power-budget = <500>;
+ qcom,hsusb-otg-pclk-src-name = "dfab_usb_clk";
+ qcom,hsusb-otg-pmic-id-irq = <47>
+ };
diff --git a/arch/arm/boot/dts/msmcopper.dts b/arch/arm/boot/dts/msmcopper.dts
index 52c0b66..74fc5a9 100644
--- a/arch/arm/boot/dts/msmcopper.dts
+++ b/arch/arm/boot/dts/msmcopper.dts
@@ -20,4 +20,14 @@
reg = <0xF9684000 0x1000>;
interrupts = <109>;
};
+
+ usb@F9690000 {
+ compatible = "qcom,hsusb-otg";
+ reg = <0xF9690000 0x400>;
+ interrupts = <134>;
+
+ qcom,hsusb-otg-phy-type = <2>;
+ qcom,hsusb-otg-mode = <1>;
+ qcom,hsusb-otg-otg-control = <1>;
+ };
};
diff --git a/arch/arm/configs/fsm9xxx-perf_defconfig b/arch/arm/configs/fsm9xxx-perf_defconfig
index b6bc4f1..5717577 100644
--- a/arch/arm/configs/fsm9xxx-perf_defconfig
+++ b/arch/arm/configs/fsm9xxx-perf_defconfig
@@ -134,6 +134,8 @@
CONFIG_POWER_SUPPLY=y
CONFIG_SENSORS_MSM_ADC=y
CONFIG_PMIC8058=y
+# CONFIG_MFD_PM8XXX_PWM is not set
+# CONFIG_MFD_PM8XXX_MISC is not set
CONFIG_REGULATOR=y
CONFIG_REGULATOR_PM8058_XO=y
# CONFIG_USB_SUPPORT is not set
diff --git a/arch/arm/configs/fsm9xxx_defconfig b/arch/arm/configs/fsm9xxx_defconfig
index dd9797a..ebff2d2 100644
--- a/arch/arm/configs/fsm9xxx_defconfig
+++ b/arch/arm/configs/fsm9xxx_defconfig
@@ -132,6 +132,8 @@
CONFIG_POWER_SUPPLY=y
CONFIG_SENSORS_MSM_ADC=y
CONFIG_PMIC8058=y
+# CONFIG_MFD_PM8XXX_PWM is not set
+# CONFIG_MFD_PM8XXX_MISC is not set
CONFIG_REGULATOR=y
CONFIG_REGULATOR_PM8058_XO=y
# CONFIG_USB_SUPPORT is not set
diff --git a/arch/arm/configs/msm-copper_defconfig b/arch/arm/configs/msm-copper_defconfig
index 9fb4615..6c50ae9 100644
--- a/arch/arm/configs/msm-copper_defconfig
+++ b/arch/arm/configs/msm-copper_defconfig
@@ -95,7 +95,9 @@
# CONFIG_HWMON is not set
# CONFIG_MFD_SUPPORT is not set
# CONFIG_HID_SUPPORT is not set
-# CONFIG_USB_SUPPORT is not set
+CONFIG_USB_GADGET=y
+CONFIG_USB_GADGET_CI13XXX_MSM=y
+CONFIG_USB_G_ANDROID=y
CONFIG_NEW_LEDS=y
CONFIG_LEDS_CLASS=y
# CONFIG_LEDS_MSM_PMIC is not set
diff --git a/arch/arm/configs/msm7627a-perf_defconfig b/arch/arm/configs/msm7627a-perf_defconfig
index 162fc04..83d0828 100644
--- a/arch/arm/configs/msm7627a-perf_defconfig
+++ b/arch/arm/configs/msm7627a-perf_defconfig
@@ -273,6 +273,7 @@
CONFIG_MMC=y
CONFIG_MMC_PERF_PROFILING=y
CONFIG_MMC_UNSAFE_RESUME=y
+CONFIG_MMC_CLKGATE=y
CONFIG_MMC_PARANOID_SD_INIT=y
CONFIG_MMC_BLOCK_MINORS=32
# CONFIG_MMC_BLOCK_BOUNCE is not set
diff --git a/arch/arm/configs/msm7627a_defconfig b/arch/arm/configs/msm7627a_defconfig
index d19fa3d..dcbca79 100644
--- a/arch/arm/configs/msm7627a_defconfig
+++ b/arch/arm/configs/msm7627a_defconfig
@@ -268,6 +268,7 @@
CONFIG_MMC=y
CONFIG_MMC_PERF_PROFILING=y
CONFIG_MMC_UNSAFE_RESUME=y
+CONFIG_MMC_CLKGATE=y
CONFIG_MMC_PARANOID_SD_INIT=y
CONFIG_MMC_BLOCK_MINORS=32
# CONFIG_MMC_BLOCK_BOUNCE is not set
diff --git a/arch/arm/configs/msm7630-perf_defconfig b/arch/arm/configs/msm7630-perf_defconfig
index 56710d7..042d751 100644
--- a/arch/arm/configs/msm7630-perf_defconfig
+++ b/arch/arm/configs/msm7630-perf_defconfig
@@ -187,7 +187,7 @@
CONFIG_BLK_DEV_RAM_SIZE=16384
CONFIG_MISC_DEVICES=y
CONFIG_HAPTIC_ISA1200=y
-CONFIG_PMIC8058_UPL=y
+CONFIG_PMIC8XXX_UPL=y
CONFIG_SCSI=y
CONFIG_SCSI_TGT=y
CONFIG_BLK_DEV_SD=y
@@ -216,6 +216,8 @@
CONFIG_INPUT_EVDEV=y
CONFIG_INPUT_EVBUG=m
# CONFIG_KEYBOARD_ATKBD is not set
+CONFIG_KEYBOARD_PMIC8XXX=y
+# CONFIG_KEYBOARD_PMIC8058 is not set
# CONFIG_INPUT_MOUSE is not set
CONFIG_INPUT_TOUCHSCREEN=y
CONFIG_TOUCHSCREEN_MSM=y
@@ -249,6 +251,9 @@
CONFIG_MARIMBA_CORE=y
CONFIG_MARIMBA_CODEC=y
CONFIG_TIMPANI_CODEC=y
+# CONFIG_MFD_PM8XXX_DEBUG is not set
+# CONFIG_MFD_PM8XXX_PWM is not set
+# CONFIG_MFD_PM8XXX_MISC is not set
CONFIG_MEDIA_SUPPORT=y
CONFIG_VIDEO_DEV=y
# CONFIG_MEDIA_TUNER_CUSTOMISE is not set
diff --git a/arch/arm/configs/msm7630_defconfig b/arch/arm/configs/msm7630_defconfig
index 115ce98..362babe 100644
--- a/arch/arm/configs/msm7630_defconfig
+++ b/arch/arm/configs/msm7630_defconfig
@@ -186,7 +186,7 @@
CONFIG_BLK_DEV_RAM_SIZE=16384
CONFIG_MISC_DEVICES=y
CONFIG_HAPTIC_ISA1200=y
-CONFIG_PMIC8058_UPL=y
+CONFIG_PMIC8XXX_UPL=y
CONFIG_SCSI=y
CONFIG_SCSI_TGT=y
CONFIG_BLK_DEV_SD=y
@@ -215,6 +215,8 @@
CONFIG_INPUT_EVDEV=y
CONFIG_INPUT_EVBUG=m
# CONFIG_KEYBOARD_ATKBD is not set
+CONFIG_KEYBOARD_PMIC8XXX=y
+# CONFIG_KEYBOARD_PMIC8058 is not set
# CONFIG_INPUT_MOUSE is not set
CONFIG_INPUT_TOUCHSCREEN=y
CONFIG_TOUCHSCREEN_MSM=y
@@ -248,6 +250,9 @@
CONFIG_MARIMBA_CORE=y
CONFIG_MARIMBA_CODEC=y
CONFIG_TIMPANI_CODEC=y
+# CONFIG_MFD_PM8XXX_DEBUG is not set
+# CONFIG_MFD_PM8XXX_PWM is not set
+# CONFIG_MFD_PM8XXX_MISC is not set
CONFIG_MSM_KGSL=y
CONFIG_VIDEO_OUTPUT_CONTROL=y
CONFIG_FB=y
diff --git a/arch/arm/configs/msm8660-perf_defconfig b/arch/arm/configs/msm8660-perf_defconfig
index 51c64d3..dcdf9e5 100644
--- a/arch/arm/configs/msm8660-perf_defconfig
+++ b/arch/arm/configs/msm8660-perf_defconfig
@@ -222,10 +222,9 @@
CONFIG_TSIF=m
CONFIG_TSIF_CHRDEV=m
CONFIG_HAPTIC_ISA1200=y
-CONFIG_PMIC8058_VIBRATOR=y
-CONFIG_PMIC8058_UPL=y
+CONFIG_PMIC8XXX_VIBRATOR=y
+CONFIG_PMIC8XXX_UPL=y
CONFIG_PMIC8058_XOADC=y
-CONFIG_PMIC8058_MISC=y
CONFIG_TZCOM=y
CONFIG_SCSI=y
CONFIG_SCSI_TGT=y
@@ -262,6 +261,8 @@
CONFIG_INPUT_KEYRESET=y
CONFIG_KEYBOARD_GPIO=y
CONFIG_KEYBOARD_MATRIX=y
+CONFIG_KEYBOARD_PMIC8XXX=y
+# CONFIG_KEYBOARD_PMIC8058 is not set
CONFIG_INPUT_JOYSTICK=y
CONFIG_INPUT_TOUCHSCREEN=y
CONFIG_TOUCHSCREEN_ATMEL_MAXTOUCH=y
@@ -269,7 +270,7 @@
CONFIG_TOUCHSCREEN_CYTTSP_I2C=y
CONFIG_INPUT_MISC=y
CONFIG_INPUT_UINPUT=y
-CONFIG_PMIC8058_PWRKEY=y
+CONFIG_INPUT_PMIC8XXX_PWRKEY=y
CONFIG_PMIC8058_OTHC=y
CONFIG_SERIAL_MSM_HS=y
CONFIG_SERIAL_MSM_HSL=y
@@ -300,11 +301,13 @@
CONFIG_THERMAL=y
CONFIG_THERMAL_HWMON=y
CONFIG_THERMAL_PM8901=y
-CONFIG_THERMAL_PM8058=y
CONFIG_THERMAL_TSENS=y
+CONFIG_THERMAL_PM8XXX=y
CONFIG_PMIC8058=y
CONFIG_MARIMBA_CORE=y
CONFIG_TIMPANI_CODEC=y
+# CONFIG_MFD_PM8XXX_PWM is not set
+CONFIG_MFD_PM8XXX_BATT_ALARM=y
CONFIG_MEDIA_SUPPORT=y
CONFIG_VIDEO_DEV=y
# CONFIG_MEDIA_TUNER_CUSTOMISE is not set
@@ -367,6 +370,7 @@
CONFIG_MMC_EMBEDDED_SDIO=y
CONFIG_MMC_PARANOID_SD_INIT=y
CONFIG_MMC_BLOCK_MINORS=32
+# CONFIG_MMC_BLOCK_BOUNCE is not set
CONFIG_MMC_MSM=y
CONFIG_MMC_MSM_SDIO_SUPPORT=y
CONFIG_MMC_MSM_CARD_HW_DETECTION=y
@@ -386,7 +390,7 @@
CONFIG_SWITCH_GPIO=y
CONFIG_RTC_CLASS=y
# CONFIG_RTC_DRV_MSM is not set
-CONFIG_RTC_PM8058=y
+CONFIG_RTC_DRV_PM8XXX=y
CONFIG_STAGING=y
CONFIG_ANDROID=y
CONFIG_ANDROID_BINDER_IPC=y
diff --git a/arch/arm/configs/msm8660_defconfig b/arch/arm/configs/msm8660_defconfig
index e8708f3..8f049a5 100644
--- a/arch/arm/configs/msm8660_defconfig
+++ b/arch/arm/configs/msm8660_defconfig
@@ -214,10 +214,9 @@
CONFIG_TSIF=m
CONFIG_TSIF_CHRDEV=m
CONFIG_HAPTIC_ISA1200=y
-CONFIG_PMIC8058_VIBRATOR=y
-CONFIG_PMIC8058_UPL=y
+CONFIG_PMIC8XXX_VIBRATOR=y
+CONFIG_PMIC8XXX_UPL=y
CONFIG_PMIC8058_XOADC=y
-CONFIG_PMIC8058_MISC=y
CONFIG_TZCOM=y
CONFIG_SCSI=y
CONFIG_SCSI_TGT=y
@@ -254,6 +253,8 @@
CONFIG_INPUT_KEYRESET=y
CONFIG_KEYBOARD_GPIO=y
CONFIG_KEYBOARD_MATRIX=y
+CONFIG_KEYBOARD_PMIC8XXX=y
+# CONFIG_KEYBOARD_PMIC8058 is not set
CONFIG_INPUT_JOYSTICK=y
CONFIG_INPUT_TOUCHSCREEN=y
CONFIG_TOUCHSCREEN_ATMEL_MAXTOUCH=y
@@ -261,7 +262,7 @@
CONFIG_TOUCHSCREEN_CYTTSP_I2C=y
CONFIG_INPUT_MISC=y
CONFIG_INPUT_UINPUT=y
-CONFIG_PMIC8058_PWRKEY=y
+CONFIG_INPUT_PMIC8XXX_PWRKEY=y
CONFIG_PMIC8058_OTHC=y
CONFIG_SERIAL_MSM_HS=y
CONFIG_SERIAL_MSM_HSL=y
@@ -291,11 +292,13 @@
CONFIG_SENSORS_MSM_ADC=y
CONFIG_THERMAL=y
CONFIG_THERMAL_PM8901=y
-CONFIG_THERMAL_PM8058=y
CONFIG_THERMAL_TSENS=y
+CONFIG_THERMAL_PM8XXX=y
CONFIG_PMIC8058=y
CONFIG_MARIMBA_CORE=y
CONFIG_TIMPANI_CODEC=y
+# CONFIG_MFD_PM8XXX_PWM is not set
+CONFIG_MFD_PM8XXX_BATT_ALARM=y
CONFIG_MEDIA_SUPPORT=y
CONFIG_VIDEO_DEV=y
# CONFIG_MEDIA_TUNER_CUSTOMISE is not set
@@ -354,6 +357,7 @@
CONFIG_MMC_EMBEDDED_SDIO=y
CONFIG_MMC_PARANOID_SD_INIT=y
CONFIG_MMC_BLOCK_MINORS=32
+# CONFIG_MMC_BLOCK_BOUNCE is not set
CONFIG_MMC_MSM=y
CONFIG_MMC_MSM_SDIO_SUPPORT=y
CONFIG_MMC_MSM_CARD_HW_DETECTION=y
@@ -373,7 +377,7 @@
CONFIG_SWITCH_GPIO=y
CONFIG_RTC_CLASS=y
# CONFIG_RTC_DRV_MSM is not set
-CONFIG_RTC_PM8058=y
+CONFIG_RTC_DRV_PM8XXX=y
CONFIG_STAGING=y
CONFIG_ANDROID=y
CONFIG_ANDROID_BINDER_IPC=y
diff --git a/arch/arm/configs/msm8960_defconfig b/arch/arm/configs/msm8960_defconfig
index be98991..c41f64c 100755
--- a/arch/arm/configs/msm8960_defconfig
+++ b/arch/arm/configs/msm8960_defconfig
@@ -202,6 +202,7 @@
CONFIG_BLK_DEV_LOOP=y
CONFIG_BLK_DEV_RAM=y
CONFIG_MISC_DEVICES=y
+CONFIG_HAPTIC_ISA1200=y
CONFIG_PMIC8XXX_VIBRATOR=y
CONFIG_TZCOM=y
CONFIG_SCSI=y
@@ -336,6 +337,7 @@
CONFIG_USB_SERIAL=y
CONFIG_USB_SERIAL_QUALCOMM=y
CONFIG_USB_EHSET_TEST_FIXTURE=y
+CONFIG_USB_QCOM_DIAG_BRIDGE=y
CONFIG_USB_QCOM_DUN_BRIDGE=y
CONFIG_USB_GADGET=y
CONFIG_USB_GADGET_DEBUG_FILES=y
@@ -348,6 +350,7 @@
CONFIG_MMC_CLKGATE=y
CONFIG_MMC_PARANOID_SD_INIT=y
CONFIG_MMC_BLOCK_MINORS=32
+# CONFIG_MMC_BLOCK_BOUNCE is not set
CONFIG_MMC_MSM=y
CONFIG_MMC_MSM_CARD_HW_DETECTION=y
CONFIG_MMC_MSM_SDC1_8_BIT_SUPPORT=y
diff --git a/arch/arm/configs/msm9615_defconfig b/arch/arm/configs/msm9615_defconfig
index 4275140..67d0057 100644
--- a/arch/arm/configs/msm9615_defconfig
+++ b/arch/arm/configs/msm9615_defconfig
@@ -44,6 +44,10 @@
CONFIG_MSM_BAM_DMUX=y
CONFIG_MSM_IPC_ROUTER=y
CONFIG_MSM_IPC_ROUTER_SMD_XPRT=y
+CONFIG_MSM_SUBSYSTEM_RESTART=y
+# CONFIG_MSM_SYSMON_COMM is not set
+CONFIG_MSM_MODEM_8960=y
+CONFIG_MSM_LPASS_8960=y
CONFIG_MSM_DIRECT_SCLK_ACCESS=y
CONFIG_MSM_WATCHDOG=y
CONFIG_MSM_DLOAD_MODE=y
diff --git a/arch/arm/include/asm/mach/mmc.h b/arch/arm/include/asm/mach/mmc.h
index 6e55bf3..c86fad9 100644
--- a/arch/arm/include/asm/mach/mmc.h
+++ b/arch/arm/include/asm/mach/mmc.h
@@ -140,7 +140,6 @@
bool nonremovable;
bool pclk_src_dfab;
int (*cfg_mpm_sdiowakeup)(struct device *, unsigned);
- bool sdcc_v4_sup;
unsigned int wpswitch_gpio;
unsigned char wpswitch_polarity;
struct msm_mmc_slot_reg_data *vreg_data;
diff --git a/arch/arm/include/asm/perf_event.h b/arch/arm/include/asm/perf_event.h
index 0e1fd19..87d1bed 100644
--- a/arch/arm/include/asm/perf_event.h
+++ b/arch/arm/include/asm/perf_event.h
@@ -24,6 +24,8 @@
ARM_PERF_PMU_ID_V6MP,
ARM_PERF_PMU_ID_CA8,
ARM_PERF_PMU_ID_CA9,
+ ARM_PERF_PMU_ID_CA5,
+ ARM_PERF_PMU_ID_CA15,
ARM_PERF_PMU_ID_SCORPION,
ARM_PERF_PMU_ID_SCORPIONMP,
ARM_PERF_PMU_ID_KRAIT,
diff --git a/arch/arm/kernel/perf_event.c b/arch/arm/kernel/perf_event.c
index c9982829..c8f963c 100644
--- a/arch/arm/kernel/perf_event.c
+++ b/arch/arm/kernel/perf_event.c
@@ -680,6 +680,12 @@
case 0xC090: /* Cortex-A9 */
armpmu = armv7_a9_pmu_init();
break;
+ case 0xC050: /* Cortex-A5 */
+ armpmu = armv7_a5_pmu_init();
+ break;
+ case 0xC0F0: /* Cortex-A15 */
+ armpmu = armv7_a15_pmu_init();
+ break;
}
/* Intel CPUs [xscale]. */
} else if (0x69 == implementor) {
diff --git a/arch/arm/kernel/perf_event_msm.c b/arch/arm/kernel/perf_event_msm.c
index fb53650..579cd3b 100644
--- a/arch/arm/kernel/perf_event_msm.c
+++ b/arch/arm/kernel/perf_event_msm.c
@@ -215,15 +215,15 @@
[C(BPU)] = {
[C(OP_READ)] = {
[C(RESULT_ACCESS)]
- = ARMV7_PERFCTR_PC_BRANCH_MIS_USED,
+ = ARMV7_PERFCTR_PC_BRANCH_PRED,
[C(RESULT_MISS)]
- = ARMV7_PERFCTR_PC_BRANCH_MIS_USED,
+ = ARMV7_PERFCTR_PC_BRANCH_PRED,
},
[C(OP_WRITE)] = {
[C(RESULT_ACCESS)]
- = ARMV7_PERFCTR_PC_BRANCH_MIS_USED,
+ = ARMV7_PERFCTR_PC_BRANCH_PRED,
[C(RESULT_MISS)]
- = ARMV7_PERFCTR_PC_BRANCH_MIS_USED,
+ = ARMV7_PERFCTR_PC_BRANCH_PRED,
},
[C(OP_PREFETCH)] = {
[C(RESULT_ACCESS)] = CACHE_OP_UNSUPPORTED,
diff --git a/arch/arm/kernel/perf_event_msm_krait.c b/arch/arm/kernel/perf_event_msm_krait.c
index 62509b4..1e77489 100644
--- a/arch/arm/kernel/perf_event_msm_krait.c
+++ b/arch/arm/kernel/perf_event_msm_krait.c
@@ -122,15 +122,15 @@
[C(BPU)] = {
[C(OP_READ)] = {
[C(RESULT_ACCESS)]
- = ARMV7_PERFCTR_PC_BRANCH_MIS_USED,
+ = ARMV7_PERFCTR_PC_BRANCH_PRED,
[C(RESULT_MISS)]
- = ARMV7_PERFCTR_PC_BRANCH_MIS_USED,
+ = ARMV7_PERFCTR_PC_BRANCH_PRED,
},
[C(OP_WRITE)] = {
[C(RESULT_ACCESS)]
- = ARMV7_PERFCTR_PC_BRANCH_MIS_USED,
+ = ARMV7_PERFCTR_PC_BRANCH_PRED,
[C(RESULT_MISS)]
- = ARMV7_PERFCTR_PC_BRANCH_MIS_USED,
+ = ARMV7_PERFCTR_PC_BRANCH_PRED,
},
[C(OP_PREFETCH)] = {
[C(RESULT_ACCESS)] = CACHE_OP_UNSUPPORTED,
@@ -365,7 +365,7 @@
static struct arm_pmu krait_pmu = {
.handle_irq = armv7pmu_handle_irq,
-#ifdef CONFIG_MSM_SMP
+#ifdef CONFIG_SMP
.secondary_enable = scorpion_secondary_enable,
.secondary_disable = scorpion_secondary_disable,
#endif
diff --git a/arch/arm/kernel/perf_event_v7.c b/arch/arm/kernel/perf_event_v7.c
index 4960686..9633178 100644
--- a/arch/arm/kernel/perf_event_v7.c
+++ b/arch/arm/kernel/perf_event_v7.c
@@ -17,17 +17,23 @@
*/
#ifdef CONFIG_CPU_V7
-/* Common ARMv7 event types */
+/*
+ * Common ARMv7 event types
+ *
+ * Note: An implementation may not be able to count all of these events
+ * but the encodings are considered to be `reserved' in the case that
+ * they are not available.
+ */
enum armv7_perf_types {
ARMV7_PERFCTR_PMNC_SW_INCR = 0x00,
ARMV7_PERFCTR_IFETCH_MISS = 0x01,
ARMV7_PERFCTR_ITLB_MISS = 0x02,
- ARMV7_PERFCTR_DCACHE_REFILL = 0x03,
- ARMV7_PERFCTR_DCACHE_ACCESS = 0x04,
+ ARMV7_PERFCTR_DCACHE_REFILL = 0x03, /* L1 */
+ ARMV7_PERFCTR_DCACHE_ACCESS = 0x04, /* L1 */
ARMV7_PERFCTR_DTLB_REFILL = 0x05,
ARMV7_PERFCTR_DREAD = 0x06,
ARMV7_PERFCTR_DWRITE = 0x07,
-
+ ARMV7_PERFCTR_INSTR_EXECUTED = 0x08,
ARMV7_PERFCTR_EXC_TAKEN = 0x09,
ARMV7_PERFCTR_EXC_EXECUTED = 0x0A,
ARMV7_PERFCTR_CID_WRITE = 0x0B,
@@ -39,21 +45,30 @@
*/
ARMV7_PERFCTR_PC_WRITE = 0x0C,
ARMV7_PERFCTR_PC_IMM_BRANCH = 0x0D,
+ ARMV7_PERFCTR_PC_PROC_RETURN = 0x0E,
ARMV7_PERFCTR_UNALIGNED_ACCESS = 0x0F,
+
+ /* These events are defined by the PMUv2 supplement (ARM DDI 0457A). */
ARMV7_PERFCTR_PC_BRANCH_MIS_PRED = 0x10,
ARMV7_PERFCTR_CLOCK_CYCLES = 0x11,
-
- ARMV7_PERFCTR_PC_BRANCH_MIS_USED = 0x12,
+ ARMV7_PERFCTR_PC_BRANCH_PRED = 0x12,
+ ARMV7_PERFCTR_MEM_ACCESS = 0x13,
+ ARMV7_PERFCTR_L1_ICACHE_ACCESS = 0x14,
+ ARMV7_PERFCTR_L1_DCACHE_WB = 0x15,
+ ARMV7_PERFCTR_L2_DCACHE_ACCESS = 0x16,
+ ARMV7_PERFCTR_L2_DCACHE_REFILL = 0x17,
+ ARMV7_PERFCTR_L2_DCACHE_WB = 0x18,
+ ARMV7_PERFCTR_BUS_ACCESS = 0x19,
+ ARMV7_PERFCTR_MEMORY_ERROR = 0x1A,
+ ARMV7_PERFCTR_INSTR_SPEC = 0x1B,
+ ARMV7_PERFCTR_TTBR_WRITE = 0x1C,
+ ARMV7_PERFCTR_BUS_CYCLES = 0x1D,
ARMV7_PERFCTR_CPU_CYCLES = 0xFF
};
/* ARMv7 Cortex-A8 specific event types */
enum armv7_a8_perf_types {
- ARMV7_PERFCTR_INSTR_EXECUTED = 0x08,
-
- ARMV7_PERFCTR_PC_PROC_RETURN = 0x0E,
-
ARMV7_PERFCTR_WRITE_BUFFER_FULL = 0x40,
ARMV7_PERFCTR_L2_STORE_MERGED = 0x41,
ARMV7_PERFCTR_L2_STORE_BUFF = 0x42,
@@ -138,6 +153,39 @@
ARMV7_PERFCTR_PLE_RQST_PROG = 0xA5
};
+/* ARMv7 Cortex-A5 specific event types */
+enum armv7_a5_perf_types {
+ ARMV7_PERFCTR_IRQ_TAKEN = 0x86,
+ ARMV7_PERFCTR_FIQ_TAKEN = 0x87,
+
+ ARMV7_PERFCTR_EXT_MEM_RQST = 0xc0,
+ ARMV7_PERFCTR_NC_EXT_MEM_RQST = 0xc1,
+ ARMV7_PERFCTR_PREFETCH_LINEFILL = 0xc2,
+ ARMV7_PERFCTR_PREFETCH_LINEFILL_DROP = 0xc3,
+ ARMV7_PERFCTR_ENTER_READ_ALLOC = 0xc4,
+ ARMV7_PERFCTR_READ_ALLOC = 0xc5,
+
+ ARMV7_PERFCTR_STALL_SB_FULL = 0xc9,
+};
+
+/* ARMv7 Cortex-A15 specific event types */
+enum armv7_a15_perf_types {
+ ARMV7_PERFCTR_L1_DCACHE_READ_ACCESS = 0x40,
+ ARMV7_PERFCTR_L1_DCACHE_WRITE_ACCESS = 0x41,
+ ARMV7_PERFCTR_L1_DCACHE_READ_REFILL = 0x42,
+ ARMV7_PERFCTR_L1_DCACHE_WRITE_REFILL = 0x43,
+
+ ARMV7_PERFCTR_L1_DTLB_READ_REFILL = 0x4C,
+ ARMV7_PERFCTR_L1_DTLB_WRITE_REFILL = 0x4D,
+
+ ARMV7_PERFCTR_L2_DCACHE_READ_ACCESS = 0x50,
+ ARMV7_PERFCTR_L2_DCACHE_WRITE_ACCESS = 0x51,
+ ARMV7_PERFCTR_L2_DCACHE_READ_REFILL = 0x52,
+ ARMV7_PERFCTR_L2_DCACHE_WRITE_REFILL = 0x53,
+
+ ARMV7_PERFCTR_SPEC_PC_WRITE = 0x76,
+};
+
/*
* Cortex-A8 HW events mapping
*
@@ -207,11 +255,6 @@
},
},
[C(DTLB)] = {
- /*
- * Only ITLB misses and DTLB refills are supported.
- * If users want the DTLB refills misses a raw counter
- * must be used.
- */
[C(OP_READ)] = {
[C(RESULT_ACCESS)] = CACHE_OP_UNSUPPORTED,
[C(RESULT_MISS)] = ARMV7_PERFCTR_DTLB_REFILL,
@@ -323,11 +366,6 @@
},
},
[C(DTLB)] = {
- /*
- * Only ITLB misses and DTLB refills are supported.
- * If users want the DTLB refills misses a raw counter
- * must be used.
- */
[C(OP_READ)] = {
[C(RESULT_ACCESS)] = CACHE_OP_UNSUPPORTED,
[C(RESULT_MISS)] = ARMV7_PERFCTR_DTLB_REFILL,
@@ -374,6 +412,242 @@
};
/*
+ * Cortex-A5 HW events mapping
+ */
+static const unsigned armv7_a5_perf_map[PERF_COUNT_HW_MAX] = {
+ [PERF_COUNT_HW_CPU_CYCLES] = ARMV7_PERFCTR_CPU_CYCLES,
+ [PERF_COUNT_HW_INSTRUCTIONS] = ARMV7_PERFCTR_INSTR_EXECUTED,
+ [PERF_COUNT_HW_CACHE_REFERENCES] = HW_OP_UNSUPPORTED,
+ [PERF_COUNT_HW_CACHE_MISSES] = HW_OP_UNSUPPORTED,
+ [PERF_COUNT_HW_BRANCH_INSTRUCTIONS] = ARMV7_PERFCTR_PC_WRITE,
+ [PERF_COUNT_HW_BRANCH_MISSES] = ARMV7_PERFCTR_PC_BRANCH_MIS_PRED,
+ [PERF_COUNT_HW_BUS_CYCLES] = HW_OP_UNSUPPORTED,
+};
+
+static const unsigned armv7_a5_perf_cache_map[PERF_COUNT_HW_CACHE_MAX]
+ [PERF_COUNT_HW_CACHE_OP_MAX]
+ [PERF_COUNT_HW_CACHE_RESULT_MAX] = {
+ [C(L1D)] = {
+ [C(OP_READ)] = {
+ [C(RESULT_ACCESS)]
+ = ARMV7_PERFCTR_DCACHE_ACCESS,
+ [C(RESULT_MISS)]
+ = ARMV7_PERFCTR_DCACHE_REFILL,
+ },
+ [C(OP_WRITE)] = {
+ [C(RESULT_ACCESS)]
+ = ARMV7_PERFCTR_DCACHE_ACCESS,
+ [C(RESULT_MISS)]
+ = ARMV7_PERFCTR_DCACHE_REFILL,
+ },
+ [C(OP_PREFETCH)] = {
+ [C(RESULT_ACCESS)]
+ = ARMV7_PERFCTR_PREFETCH_LINEFILL,
+ [C(RESULT_MISS)]
+ = ARMV7_PERFCTR_PREFETCH_LINEFILL_DROP,
+ },
+ },
+ [C(L1I)] = {
+ [C(OP_READ)] = {
+ [C(RESULT_ACCESS)] = ARMV7_PERFCTR_L1_ICACHE_ACCESS,
+ [C(RESULT_MISS)] = ARMV7_PERFCTR_IFETCH_MISS,
+ },
+ [C(OP_WRITE)] = {
+ [C(RESULT_ACCESS)] = ARMV7_PERFCTR_L1_ICACHE_ACCESS,
+ [C(RESULT_MISS)] = ARMV7_PERFCTR_IFETCH_MISS,
+ },
+ /*
+ * The prefetch counters don't differentiate between the I
+ * side and the D side.
+ */
+ [C(OP_PREFETCH)] = {
+ [C(RESULT_ACCESS)]
+ = ARMV7_PERFCTR_PREFETCH_LINEFILL,
+ [C(RESULT_MISS)]
+ = ARMV7_PERFCTR_PREFETCH_LINEFILL_DROP,
+ },
+ },
+ [C(LL)] = {
+ [C(OP_READ)] = {
+ [C(RESULT_ACCESS)] = CACHE_OP_UNSUPPORTED,
+ [C(RESULT_MISS)] = CACHE_OP_UNSUPPORTED,
+ },
+ [C(OP_WRITE)] = {
+ [C(RESULT_ACCESS)] = CACHE_OP_UNSUPPORTED,
+ [C(RESULT_MISS)] = CACHE_OP_UNSUPPORTED,
+ },
+ [C(OP_PREFETCH)] = {
+ [C(RESULT_ACCESS)] = CACHE_OP_UNSUPPORTED,
+ [C(RESULT_MISS)] = CACHE_OP_UNSUPPORTED,
+ },
+ },
+ [C(DTLB)] = {
+ [C(OP_READ)] = {
+ [C(RESULT_ACCESS)] = CACHE_OP_UNSUPPORTED,
+ [C(RESULT_MISS)] = ARMV7_PERFCTR_DTLB_REFILL,
+ },
+ [C(OP_WRITE)] = {
+ [C(RESULT_ACCESS)] = CACHE_OP_UNSUPPORTED,
+ [C(RESULT_MISS)] = ARMV7_PERFCTR_DTLB_REFILL,
+ },
+ [C(OP_PREFETCH)] = {
+ [C(RESULT_ACCESS)] = CACHE_OP_UNSUPPORTED,
+ [C(RESULT_MISS)] = CACHE_OP_UNSUPPORTED,
+ },
+ },
+ [C(ITLB)] = {
+ [C(OP_READ)] = {
+ [C(RESULT_ACCESS)] = CACHE_OP_UNSUPPORTED,
+ [C(RESULT_MISS)] = ARMV7_PERFCTR_ITLB_MISS,
+ },
+ [C(OP_WRITE)] = {
+ [C(RESULT_ACCESS)] = CACHE_OP_UNSUPPORTED,
+ [C(RESULT_MISS)] = ARMV7_PERFCTR_ITLB_MISS,
+ },
+ [C(OP_PREFETCH)] = {
+ [C(RESULT_ACCESS)] = CACHE_OP_UNSUPPORTED,
+ [C(RESULT_MISS)] = CACHE_OP_UNSUPPORTED,
+ },
+ },
+ [C(BPU)] = {
+ [C(OP_READ)] = {
+ [C(RESULT_ACCESS)] = ARMV7_PERFCTR_PC_BRANCH_PRED,
+ [C(RESULT_MISS)]
+ = ARMV7_PERFCTR_PC_BRANCH_MIS_PRED,
+ },
+ [C(OP_WRITE)] = {
+ [C(RESULT_ACCESS)] = ARMV7_PERFCTR_PC_BRANCH_PRED,
+ [C(RESULT_MISS)]
+ = ARMV7_PERFCTR_PC_BRANCH_MIS_PRED,
+ },
+ [C(OP_PREFETCH)] = {
+ [C(RESULT_ACCESS)] = CACHE_OP_UNSUPPORTED,
+ [C(RESULT_MISS)] = CACHE_OP_UNSUPPORTED,
+ },
+ },
+};
+
+/*
+ * Cortex-A15 HW events mapping
+ */
+static const unsigned armv7_a15_perf_map[PERF_COUNT_HW_MAX] = {
+ [PERF_COUNT_HW_CPU_CYCLES] = ARMV7_PERFCTR_CPU_CYCLES,
+ [PERF_COUNT_HW_INSTRUCTIONS] = ARMV7_PERFCTR_INSTR_EXECUTED,
+ [PERF_COUNT_HW_CACHE_REFERENCES] = HW_OP_UNSUPPORTED,
+ [PERF_COUNT_HW_CACHE_MISSES] = HW_OP_UNSUPPORTED,
+ [PERF_COUNT_HW_BRANCH_INSTRUCTIONS] = ARMV7_PERFCTR_SPEC_PC_WRITE,
+ [PERF_COUNT_HW_BRANCH_MISSES] = ARMV7_PERFCTR_PC_BRANCH_MIS_PRED,
+ [PERF_COUNT_HW_BUS_CYCLES] = ARMV7_PERFCTR_BUS_CYCLES,
+};
+
+static const unsigned armv7_a15_perf_cache_map[PERF_COUNT_HW_CACHE_MAX]
+ [PERF_COUNT_HW_CACHE_OP_MAX]
+ [PERF_COUNT_HW_CACHE_RESULT_MAX] = {
+ [C(L1D)] = {
+ [C(OP_READ)] = {
+ [C(RESULT_ACCESS)]
+ = ARMV7_PERFCTR_L1_DCACHE_READ_ACCESS,
+ [C(RESULT_MISS)]
+ = ARMV7_PERFCTR_L1_DCACHE_READ_REFILL,
+ },
+ [C(OP_WRITE)] = {
+ [C(RESULT_ACCESS)]
+ = ARMV7_PERFCTR_L1_DCACHE_WRITE_ACCESS,
+ [C(RESULT_MISS)]
+ = ARMV7_PERFCTR_L1_DCACHE_WRITE_REFILL,
+ },
+ [C(OP_PREFETCH)] = {
+ [C(RESULT_ACCESS)] = CACHE_OP_UNSUPPORTED,
+ [C(RESULT_MISS)] = CACHE_OP_UNSUPPORTED,
+ },
+ },
+ [C(L1I)] = {
+ /*
+ * Not all performance counters differentiate between read
+ * and write accesses/misses so we're not always strictly
+ * correct, but it's the best we can do. Writes and reads get
+ * combined in these cases.
+ */
+ [C(OP_READ)] = {
+ [C(RESULT_ACCESS)] = ARMV7_PERFCTR_L1_ICACHE_ACCESS,
+ [C(RESULT_MISS)] = ARMV7_PERFCTR_IFETCH_MISS,
+ },
+ [C(OP_WRITE)] = {
+ [C(RESULT_ACCESS)] = ARMV7_PERFCTR_L1_ICACHE_ACCESS,
+ [C(RESULT_MISS)] = ARMV7_PERFCTR_IFETCH_MISS,
+ },
+ [C(OP_PREFETCH)] = {
+ [C(RESULT_ACCESS)] = CACHE_OP_UNSUPPORTED,
+ [C(RESULT_MISS)] = CACHE_OP_UNSUPPORTED,
+ },
+ },
+ [C(LL)] = {
+ [C(OP_READ)] = {
+ [C(RESULT_ACCESS)]
+ = ARMV7_PERFCTR_L2_DCACHE_READ_ACCESS,
+ [C(RESULT_MISS)]
+ = ARMV7_PERFCTR_L2_DCACHE_READ_REFILL,
+ },
+ [C(OP_WRITE)] = {
+ [C(RESULT_ACCESS)]
+ = ARMV7_PERFCTR_L2_DCACHE_WRITE_ACCESS,
+ [C(RESULT_MISS)]
+ = ARMV7_PERFCTR_L2_DCACHE_WRITE_REFILL,
+ },
+ [C(OP_PREFETCH)] = {
+ [C(RESULT_ACCESS)] = CACHE_OP_UNSUPPORTED,
+ [C(RESULT_MISS)] = CACHE_OP_UNSUPPORTED,
+ },
+ },
+ [C(DTLB)] = {
+ [C(OP_READ)] = {
+ [C(RESULT_ACCESS)] = CACHE_OP_UNSUPPORTED,
+ [C(RESULT_MISS)]
+ = ARMV7_PERFCTR_L1_DTLB_READ_REFILL,
+ },
+ [C(OP_WRITE)] = {
+ [C(RESULT_ACCESS)] = CACHE_OP_UNSUPPORTED,
+ [C(RESULT_MISS)]
+ = ARMV7_PERFCTR_L1_DTLB_WRITE_REFILL,
+ },
+ [C(OP_PREFETCH)] = {
+ [C(RESULT_ACCESS)] = CACHE_OP_UNSUPPORTED,
+ [C(RESULT_MISS)] = CACHE_OP_UNSUPPORTED,
+ },
+ },
+ [C(ITLB)] = {
+ [C(OP_READ)] = {
+ [C(RESULT_ACCESS)] = CACHE_OP_UNSUPPORTED,
+ [C(RESULT_MISS)] = ARMV7_PERFCTR_ITLB_MISS,
+ },
+ [C(OP_WRITE)] = {
+ [C(RESULT_ACCESS)] = CACHE_OP_UNSUPPORTED,
+ [C(RESULT_MISS)] = ARMV7_PERFCTR_ITLB_MISS,
+ },
+ [C(OP_PREFETCH)] = {
+ [C(RESULT_ACCESS)] = CACHE_OP_UNSUPPORTED,
+ [C(RESULT_MISS)] = CACHE_OP_UNSUPPORTED,
+ },
+ },
+ [C(BPU)] = {
+ [C(OP_READ)] = {
+ [C(RESULT_ACCESS)] = ARMV7_PERFCTR_PC_BRANCH_PRED,
+ [C(RESULT_MISS)]
+ = ARMV7_PERFCTR_PC_BRANCH_MIS_PRED,
+ },
+ [C(OP_WRITE)] = {
+ [C(RESULT_ACCESS)] = ARMV7_PERFCTR_PC_BRANCH_PRED,
+ [C(RESULT_MISS)]
+ = ARMV7_PERFCTR_PC_BRANCH_MIS_PRED,
+ },
+ [C(OP_PREFETCH)] = {
+ [C(RESULT_ACCESS)] = CACHE_OP_UNSUPPORTED,
+ [C(RESULT_MISS)] = CACHE_OP_UNSUPPORTED,
+ },
+ },
+};
+
+/*
* Perf Events counters
*/
enum armv7_counters {
@@ -905,6 +1179,26 @@
armv7pmu.num_events = armv7_read_num_pmnc_events();
return &armv7pmu;
}
+
+static const struct arm_pmu *__init armv7_a5_pmu_init(void)
+{
+ armv7pmu.id = ARM_PERF_PMU_ID_CA5;
+ armv7pmu.name = "ARMv7 Cortex-A5";
+ armv7pmu.cache_map = &armv7_a5_perf_cache_map;
+ armv7pmu.event_map = &armv7_a5_perf_map;
+ armv7pmu.num_events = armv7_read_num_pmnc_events();
+ return &armv7pmu;
+}
+
+static const struct arm_pmu *__init armv7_a15_pmu_init(void)
+{
+ armv7pmu.id = ARM_PERF_PMU_ID_CA15;
+ armv7pmu.name = "ARMv7 Cortex-A15";
+ armv7pmu.cache_map = &armv7_a15_perf_cache_map;
+ armv7pmu.event_map = &armv7_a15_perf_map;
+ armv7pmu.num_events = armv7_read_num_pmnc_events();
+ return &armv7pmu;
+}
#else
static const struct arm_pmu *__init armv7_a8_pmu_init(void)
{
@@ -915,4 +1209,14 @@
{
return NULL;
}
+
+static const struct arm_pmu *__init armv7_a5_pmu_init(void)
+{
+ return NULL;
+}
+
+static const struct arm_pmu *__init armv7_a15_pmu_init(void)
+{
+ return NULL;
+}
#endif /* CONFIG_CPU_V7 */
diff --git a/arch/arm/kernel/process.c b/arch/arm/kernel/process.c
index 34fca2e..26959d5 100644
--- a/arch/arm/kernel/process.c
+++ b/arch/arm/kernel/process.c
@@ -142,6 +142,9 @@
/* Push out any further dirty data, and ensure cache is empty */
flush_cache_all();
+ /*Push out the dirty data from external caches */
+ outer_disable();
+
/*
* Now call the architecture specific reboot code.
*/
diff --git a/arch/arm/mach-msm/Kconfig b/arch/arm/mach-msm/Kconfig
index f3ae47e..2d681fa 100644
--- a/arch/arm/mach-msm/Kconfig
+++ b/arch/arm/mach-msm/Kconfig
@@ -133,6 +133,7 @@
select MSM_AUDIO_QDSP6 if SND_SOC
select CPU_HAS_L2_PMU
select MSM_SPM_V2
+ select HAS_QDSS
select MSM_L2_SPM
select MSM_NATIVE_RESTART
select DONT_MAP_HOLE_AFTER_MEMBANK0
@@ -711,28 +712,52 @@
bool "6.2.20 + New ADSP"
endchoice
-config MSM_DEBUG_UART
- int
- default 1 if MSM_DEBUG_UART1
- default 2 if MSM_DEBUG_UART2
- default 3 if MSM_DEBUG_UART3
+config DEBUG_MSM8930_UART
+ bool "Kernel low-level debugging messages via MSM 8930 UART"
+ depends on ARCH_MSM8930 && DEBUG_LL
+ help
+ Say Y here if you want the debug print routines to direct
+ their output to the serial port on MSM 8930 devices.
choice
prompt "Debug UART"
+ depends on DEBUG_LL
- default MSM_DEBUG_UART_NONE
+ config DEBUG_MSM_UART1
+ bool "Kernel low-level debugging messages via MSM UART1"
+ depends on ARCH_MSM7X00A || ARCH_MSM7X30 || ARCH_QSD8X50
+ help
+ Say Y here if you want the debug print routines to direct
+ their output to the first serial port on MSM devices.
- config MSM_DEBUG_UART_NONE
- bool "None"
+ config DEBUG_MSM_UART2
+ bool "Kernel low-level debugging messages via MSM UART2"
+ depends on ARCH_MSM7X00A || ARCH_MSM7X30 || ARCH_QSD8X50
+ help
+ Say Y here if you want the debug print routines to direct
+ their output to the second serial port on MSM devices.
- config MSM_DEBUG_UART1
- bool "UART1"
+ config DEBUG_MSM_UART3
+ bool "Kernel low-level debugging messages via MSM UART3"
+ depends on ARCH_MSM7X00A || ARCH_MSM7X30 || ARCH_QSD8X50
+ help
+ Say Y here if you want the debug print routines to direct
+ their output to the third serial port on MSM devices.
- config MSM_DEBUG_UART2
- bool "UART2"
+ config DEBUG_MSM8660_UART
+ bool "Kernel low-level debugging messages via MSM 8660 UART"
+ depends on ARCH_MSM8X60
+ help
+ Say Y here if you want the debug print routines to direct
+ their output to the serial port on MSM 8660 devices.
- config MSM_DEBUG_UART3
- bool "UART3"
+ config DEBUG_MSM8960_UART
+ bool "Kernel low-level debugging messages via MSM 8960 UART"
+ depends on ARCH_MSM8960
+ select DEBUG_MSM8930_UART
+ help
+ Say Y here if you want the debug print routines to direct
+ their output to the serial port on MSM 8960 devices.
endchoice
choice
@@ -869,13 +894,6 @@
help
Select this if the L2 cache controller has a Performance Monitoring Unit.
-config MSM_JTAG_V7
- depends on CPU_V7
- default y if DEBUG_KERNEL
- bool "JTAG debug support"
- help
- Add additional support for JTAG kernel debugging.
-
config HTC_HEADSET
tristate "HTC 2 Wire detection driver"
default n
@@ -1524,7 +1542,7 @@
config MSM_SUBSYSTEM_RESTART
bool "MSM Subsystem Restart Driver"
- depends on (ARCH_MSM8X60 || ARCH_MSM8960)
+ depends on (ARCH_MSM8X60 || ARCH_MSM8960 || ARCH_MSM9615)
default n
help
This option enables the MSM subsystem restart driver, which provides
@@ -1541,19 +1559,19 @@
config MSM_MODEM_8960
bool "MSM 8960 Modem driver"
- depends on (ARCH_MSM8960)
+ depends on (ARCH_MSM8960 || ARCH_MSM9615)
help
- This option enables the modem driver for the MSM8960, which monitors
+ This option enables the modem driver for the MSM8960 and MSM9615, which monitors
modem hardware watchdog interrupt lines and plugs into the subsystem
- restart and PIL drivers.
+ restart and PIL drivers. For MSM9615, it only supports a full chip reset.
config MSM_LPASS_8960
tristate "MSM 8960 Lpass driver"
- depends on (ARCH_MSM8960)
+ depends on (ARCH_MSM8960 || ARCH_MSM9615)
help
- This option enables the lpass driver for the MSM8960, which monitors
+ This option enables the lpass driver for the MSM8960 and MSM9615. This monitors
lpass hardware watchdog interrupt lines and plugs into the subsystem
- restart and PIL drivers.
+ restart and PIL drivers. For MSM9615, it only supports a full chip reset.
config MSM_WCNSS_SSR_8960
tristate "MSM 8960 WCNSS restart module"
@@ -1682,25 +1700,43 @@
make the kernel reboot on a kernel panic - that must be
enabled via another mechanism.
+config HAS_QDSS
+ bool "QDSS Present"
+ help
+ Select this if the chip has Qualcomm Debug Subsystem implemented.
+
+config MSM_DEBUG_ACROSS_PC
+ bool "Debug support across power collapse"
+ help
+ Enables debug state to be saved and restored across power collapse.
+
+config MSM_JTAG_V7
+ depends on CPU_V7 && !HAS_QDSS
+ default y if DEBUG_KERNEL
+ bool "JTAG debug support"
+ select MSM_DEBUG_ACROSS_PC
+ help
+ Add additional support for JTAG kernel debugging.
+
config MSM_TRACE_ACROSS_PC
bool "Trace support across power collapse"
- depends on ARCH_MSM8X60 || ARCH_MSM8960
help
Enables trace state to be saved and restored across power collapse.
config MSM_ETM
tristate "Enable MSM ETM and ETB"
- depends on ARCH_MSM8X60
+ depends on ARCH_MSM8X60 && !HAS_QDSS
select MSM_TRACE_ACROSS_PC
help
Enables embedded trace collection on Qualcomm v7 CPUs.
config MSM_QDSS
- bool "Coresight tracing support"
- depends on ARCH_MSM8960
+ bool "Qualcomm Debug Subsystem"
+ depends on HAS_QDSS
+ select MSM_DEBUG_ACROSS_PC
select MSM_TRACE_ACROSS_PC
help
- Enables support for Qualcomm debug subsystem.
+ Enables support for Qualcomm Debug Subsystem.
config MSM_SLEEP_STATS
bool "Enable exporting of MSM sleep stats to userspace"
diff --git a/arch/arm/mach-msm/Makefile b/arch/arm/mach-msm/Makefile
index 74f312a..604989d 100644
--- a/arch/arm/mach-msm/Makefile
+++ b/arch/arm/mach-msm/Makefile
@@ -45,7 +45,13 @@
msm-etm-objs := cp14.o etm.o
obj-$(CONFIG_MSM_ETM) += msm-etm.o
-obj-$(CONFIG_MSM_QDSS) += qdss-etb.o qdss-tpiu.o qdss-funnel.o qdss-ptm.o
+
+ifdef CONFIG_MSM_QDSS
+ obj-y += qdss-debug.o
+ obj-y += qdss-etb.o qdss-tpiu.o
+ obj-y += qdss-funnel.o
+ obj-y += qdss-ptm.o
+endif
quiet_cmd_mkrpcsym = MKCAP $@
cmd_mkrpcsym = $(PERL) $(srctree)/$(src)/mkrpcsym.pl $< $@
@@ -247,7 +253,6 @@
obj-$(CONFIG_HTC_HEADSET) += htc_headset.o
obj-$(CONFIG_MSM_RMT_STORAGE_CLIENT) += rmt_storage_client.o
obj-$(CONFIG_MSM_SDIO_SMEM) += sdio_smem.o
-obj-$(CONFIG_PMIC8058) += pmic8058-gpio.o pmic8058-mpp.o
obj-$(CONFIG_MSM_RPM) += rpm.o rpm_resources.o
obj-$(CONFIG_MSM_MPM) += mpm.o
obj-$(CONFIG_MSM_RPM_STATS_LOG) += rpm_stats.o
diff --git a/arch/arm/mach-msm/acpuclock-7x30.c b/arch/arm/mach-msm/acpuclock-7x30.c
index 24c910e..7ee4e5b 100644
--- a/arch/arm/mach-msm/acpuclock-7x30.c
+++ b/arch/arm/mach-msm/acpuclock-7x30.c
@@ -231,8 +231,7 @@
* increasing the ACPU frequency, since voting for high AXI rates
* implicitly takes care of increasing the MSMC1 voltage, as needed. */
if (tgt_s->axi_clk_hz > strt_s->axi_clk_hz) {
- rc = clk_set_min_rate(drv_state.ebi1_clk,
- tgt_s->axi_clk_hz);
+ rc = clk_set_rate(drv_state.ebi1_clk, tgt_s->axi_clk_hz);
if (rc < 0) {
pr_err("Setting AXI min rate failed (%d)\n", rc);
goto out;
@@ -277,8 +276,7 @@
/* Decrease the AXI bus frequency if we can. */
if (tgt_s->axi_clk_hz < strt_s->axi_clk_hz) {
- res = clk_set_min_rate(drv_state.ebi1_clk,
- tgt_s->axi_clk_hz);
+ res = clk_set_rate(drv_state.ebi1_clk, tgt_s->axi_clk_hz);
if (res < 0)
pr_warning("Setting AXI min rate failed (%d)\n", res);
}
@@ -385,7 +383,7 @@
if (s->src >= 0)
clk_enable(acpuclk_sources[s->src]);
- res = clk_set_min_rate(drv_state.ebi1_clk, s->axi_clk_hz);
+ res = clk_set_rate(drv_state.ebi1_clk, s->axi_clk_hz);
if (res < 0)
pr_warning("Setting AXI min rate failed!\n");
diff --git a/arch/arm/mach-msm/bam_dmux.c b/arch/arm/mach-msm/bam_dmux.c
index d82a6bf..80f5803 100644
--- a/arch/arm/mach-msm/bam_dmux.c
+++ b/arch/arm/mach-msm/bam_dmux.c
@@ -523,12 +523,18 @@
int rc = 0;
DBG("%s: opening ch %d\n", __func__, id);
- if (!bam_mux_initialized)
+ if (!bam_mux_initialized) {
+ DBG("%s: not inititialized\n", __func__);
return -ENODEV;
- if (id >= BAM_DMUX_NUM_CHANNELS)
+ }
+ if (id >= BAM_DMUX_NUM_CHANNELS) {
+ pr_err("%s: invalid channel id %d\n", __func__, id);
return -EINVAL;
- if (notify == NULL)
+ }
+ if (notify == NULL) {
+ pr_err("%s: notify function is NULL\n", __func__);
return -EINVAL;
+ }
hdr = kmalloc(sizeof(struct bam_mux_hdr), GFP_KERNEL);
if (hdr == NULL) {
@@ -546,8 +552,7 @@
DBG("%s: Remote not open; ch: %d\n", __func__, id);
spin_unlock_irqrestore(&bam_ch[id].lock, flags);
kfree(hdr);
- rc = -ENODEV;
- goto open_done;
+ return -ENODEV;
}
bam_ch[id].notify = notify;
@@ -1024,6 +1029,7 @@
a2_props.virt_addr = a2_virt_addr;
a2_props.virt_size = A2_PHYS_SIZE;
a2_props.irq = A2_BAM_IRQ;
+ a2_props.options = SPS_BAM_OPT_IRQ_WAKEUP;
a2_props.num_pipes = A2_NUM_PIPES;
a2_props.summing_threshold = A2_SUMMING_THRESHOLD;
/* need to free on tear down */
diff --git a/arch/arm/mach-msm/board-9615.c b/arch/arm/mach-msm/board-9615.c
index 7ee30ef..d863b5d 100644
--- a/arch/arm/mach-msm/board-9615.c
+++ b/arch/arm/mach-msm/board-9615.c
@@ -301,7 +301,6 @@
* This is a gpio-regulator and does not support
* regulator_set_voltage and regulator_set_optimum_mode
*/
- .set_voltage_sup = false,
.high_vol_level = 2950000,
.low_vol_level = 2950000,
.hpm_uA = 600000, /* 600mA */
@@ -313,7 +312,6 @@
/* SDCC1 : External card slot connected */
[SDCC1] = {
.name = "sdc_vddp",
- .set_voltage_sup = true,
.high_vol_level = 2950000,
.low_vol_level = 1850000,
.always_on = true,
@@ -501,7 +499,6 @@
.sup_clk_table = sdc1_sup_clk_rates,
.sup_clk_cnt = ARRAY_SIZE(sdc1_sup_clk_rates),
.pclk_src_dfab = true,
- .sdcc_v4_sup = true,
.vreg_data = &mmc_slot_vreg_data[SDCC1],
.pin_data = &mmc_slot_pin_data[SDCC1],
#ifdef CONFIG_MMC_MSM_CARD_HW_DETECTION
@@ -529,7 +526,6 @@
.sup_clk_table = sdc2_sup_clk_rates,
.sup_clk_cnt = ARRAY_SIZE(sdc2_sup_clk_rates),
.pclk_src_dfab = 1,
- .sdcc_v4_sup = true,
.pin_data = &mmc_slot_pin_data[SDCC2],
#ifdef CONFIG_MMC_MSM_SDIO_SUPPORT
.sdiowakeup_irq = MSM_GPIO_TO_INT(GPIO_SDC2_DAT1_WAKEUP),
@@ -701,7 +697,6 @@
pm8018_platform_data.num_regulators = msm_pm8018_regulator_pdata_len;
msm_device_otg.dev.platform_data = &msm_otg_pdata;
- msm_device_gadget_peripheral.dev.parent = &msm_device_otg.dev;
platform_add_devices(common_devices, ARRAY_SIZE(common_devices));
msm_clock_init(&msm9615_clock_init_data);
diff --git a/arch/arm/mach-msm/board-apq8064.c b/arch/arm/mach-msm/board-apq8064.c
index 5ae388f..b131989 100644
--- a/arch/arm/mach-msm/board-apq8064.c
+++ b/arch/arm/mach-msm/board-apq8064.c
@@ -228,7 +228,6 @@
/* SDCC1 : eMMC card connected */
[SDCC1] = {
.name = "sdc_vdd",
- .set_voltage_sup = 1,
.high_vol_level = 2950000,
.low_vol_level = 2950000,
.always_on = 1,
@@ -239,7 +238,6 @@
/* SDCC3 : External card slot connected */
[SDCC3] = {
.name = "sdc_vdd",
- .set_voltage_sup = 1,
.high_vol_level = 2950000,
.low_vol_level = 2950000,
.hpm_uA = 600000, /* 600mA */
@@ -251,7 +249,6 @@
/* SDCC1 : eMMC card connected */
[SDCC1] = {
.name = "sdc_vccq",
- .set_voltage_sup = 1,
.always_on = 1,
.high_vol_level = 1800000,
.low_vol_level = 1800000,
@@ -264,7 +261,6 @@
/* SDCC3 : External card slot connected */
[SDCC3] = {
.name = "sdc_vddp",
- .set_voltage_sup = 1,
.high_vol_level = 2950000,
.low_vol_level = 1850000,
.always_on = 1,
@@ -405,7 +401,6 @@
.sup_clk_cnt = ARRAY_SIZE(sdc1_sup_clk_rates),
.pin_data = &mmc_slot_pin_data[SDCC1],
.vreg_data = &mmc_slot_vreg_data[SDCC1],
- .sdcc_v4_sup = true,
};
static struct mmc_platform_data *apq8064_sdc1_pdata = &sdc1_data;
#else
@@ -424,7 +419,6 @@
.sup_clk_cnt = ARRAY_SIZE(sdc3_sup_clk_rates),
.pin_data = &mmc_slot_pin_data[SDCC3],
.vreg_data = &mmc_slot_vreg_data[SDCC3],
- .sdcc_v4_sup = true,
};
static struct mmc_platform_data *apq8064_sdc3_pdata = &sdc3_data;
#else
@@ -760,7 +754,6 @@
apq8064_device_ssbi_pmic2.dev.platform_data =
&apq8064_ssbi_pm8821_pdata;
apq8064_device_otg.dev.platform_data = &msm_otg_pdata;
- apq8064_device_gadget_peripheral.dev.parent = &apq8064_device_otg.dev;
apq8064_pm8921_platform_data.num_regulators =
msm8064_pm8921_regulator_pdata_len;
platform_add_devices(common_devices, ARRAY_SIZE(common_devices));
diff --git a/arch/arm/mach-msm/board-copper.c b/arch/arm/mach-msm/board-copper.c
index f35d493..a2ddeb4 100644
--- a/arch/arm/mach-msm/board-copper.c
+++ b/arch/arm/mach-msm/board-copper.c
@@ -76,6 +76,13 @@
static struct clk_lookup msm_clocks_dummy[] = {
CLK_DUMMY("core_clk", BLSP2_UART_CLK, "msm_serial_hsl.0", OFF),
CLK_DUMMY("iface_clk", BLSP2_UART_CLK, "msm_serial_hsl.0", OFF),
+ CLK_DUMMY("core_clk", SDC1_CLK, NULL, OFF),
+ CLK_DUMMY("iface_clk", SDC1_P_CLK, NULL, OFF),
+ CLK_DUMMY("core_clk", SDC3_CLK, NULL, OFF),
+ CLK_DUMMY("iface_clk", SDC3_P_CLK, NULL, OFF),
+ CLK_DUMMY("usb_phy_clk", NULL, NULL, OFF),
+ CLK_DUMMY("usb_hs_clk", NULL, NULL, OFF),
+ CLK_DUMMY("usb_hs_pclk", NULL, NULL, OFF),
};
struct clock_init_data msm_dummy_clock_init_data __initdata = {
diff --git a/arch/arm/mach-msm/board-fsm9xxx.c b/arch/arm/mach-msm/board-fsm9xxx.c
index eb936e4..333d366 100644
--- a/arch/arm/mach-msm/board-fsm9xxx.c
+++ b/arch/arm/mach-msm/board-fsm9xxx.c
@@ -28,15 +28,12 @@
#include <asm/mach/arch.h>
#include <asm/setup.h>
-#include <mach/mpp.h>
#include <mach/board.h>
#include <mach/memory.h>
#include <mach/msm_iomap.h>
#include <mach/dma.h>
#include <mach/sirc.h>
-#include <mach/pmic.h>
-#include <mach/vreg.h>
#include <mach/socinfo.h>
#include "devices.h"
#include "timer.h"
@@ -46,7 +43,6 @@
#include <linux/regulator/consumer.h>
#include <linux/regulator/machine.h>
#include <linux/msm_adc.h>
-#include <linux/pmic8058-xoadc.h>
#include <linux/m_adcproc.h>
#include <linux/platform_data/qcom_crypto_device.h>
@@ -89,8 +85,11 @@
#define FPGA_SDCC_STATUS 0x8E0001A8
/* Macros assume PMIC GPIOs start at 0 */
-#define PM8058_GPIO_PM_TO_SYS(pm_gpio) (pm_gpio + NR_MSM_GPIOS)
-#define PM8058_GPIO_SYS_TO_PM(sys_gpio) (sys_gpio - NR_MSM_GPIOS)
+#define PM8058_GPIO_PM_TO_SYS(pm_gpio) (pm_gpio + NR_MSM_GPIOS)
+#define PM8058_GPIO_SYS_TO_PM(sys_gpio) (sys_gpio - NR_MSM_GPIOS)
+#define PM8058_MPP_BASE (NR_MSM_GPIOS + PM8058_GPIOS)
+#define PM8058_MPP_PM_TO_SYS(pm_gpio) (pm_gpio + PM8058_MPP_BASE)
+#define PM8058_MPP_SYS_TO_PM(sys_gpio) (sys_gpio - PM8058_MPP_BASE)
#define PMIC_GPIO_5V_PA_PWR 21 /* PMIC GPIO Number 22 */
#define PMIC_GPIO_4_2V_PA_PWR 22 /* PMIC GPIO Number 23 */
@@ -102,19 +101,33 @@
/*
* PM8058
*/
+struct pm8xxx_mpp_init_info {
+ unsigned mpp;
+ struct pm8xxx_mpp_config_data config;
+};
+
+#define PM8XXX_MPP_INIT(_mpp, _type, _level, _control) \
+{ \
+ .mpp = PM8058_MPP_PM_TO_SYS(_mpp), \
+ .config = { \
+ .type = PM8XXX_MPP_TYPE_##_type, \
+ .level = _level, \
+ .control = PM8XXX_MPP_##_control, \
+ } \
+}
static int pm8058_gpios_init(void)
{
int i;
int rc;
struct pm8058_gpio_cfg {
- int gpio;
- struct pm8058_gpio cfg;
+ int gpio;
+ struct pm_gpio cfg;
};
struct pm8058_gpio_cfg gpio_cfgs[] = {
{ /* 5V PA Power */
- PMIC_GPIO_5V_PA_PWR,
+ PM8058_GPIO_PM_TO_SYS(PMIC_GPIO_5V_PA_PWR),
{
.vin_sel = 0,
.direction = PM_GPIO_DIR_BOTH,
@@ -127,7 +140,7 @@
},
},
{ /* 4.2V PA Power */
- PMIC_GPIO_4_2V_PA_PWR,
+ PM8058_GPIO_PM_TO_SYS(PMIC_GPIO_4_2V_PA_PWR),
{
.vin_sel = 0,
.direction = PM_GPIO_DIR_BOTH,
@@ -142,7 +155,7 @@
};
for (i = 0; i < ARRAY_SIZE(gpio_cfgs); ++i) {
- rc = pm8058_gpio_config(gpio_cfgs[i].gpio, &gpio_cfgs[i].cfg);
+ rc = pm8xxx_gpio_config(gpio_cfgs[i].gpio, &gpio_cfgs[i].cfg);
if (rc < 0) {
pr_err("%s pmic gpio config failed\n", __func__);
return rc;
@@ -154,37 +167,28 @@
static int pm8058_mpps_init(void)
{
- int rc;
+ int rc, i;
- /* Set up MPP 3 and 6 as analog outputs at 1.25V */
- rc = pm8058_mpp_config_analog_output(PMIC_MPP_3,
- PM_MPP_AOUT_LVL_1V25_2, PM_MPP_AOUT_CTL_ENABLE);
- if (rc) {
- pr_err("%s: Config mpp3 on pmic 8058 failed\n", __func__);
- return rc;
+ struct pm8xxx_mpp_init_info pm8058_mpps[] = {
+ PM8XXX_MPP_INIT(PMIC_MPP_3, A_OUTPUT,
+ PM8XXX_MPP_AOUT_LVL_1V25_2, AOUT_CTRL_ENABLE),
+ PM8XXX_MPP_INIT(PMIC_MPP_6, A_OUTPUT,
+ PM8XXX_MPP_AOUT_LVL_1V25_2, AOUT_CTRL_ENABLE),
+ };
+
+ for (i = 0; i < ARRAY_SIZE(pm8058_mpps); i++) {
+ rc = pm8xxx_mpp_config(pm8058_mpps[i].mpp,
+ &pm8058_mpps[i].config);
+ if (rc) {
+ pr_err("%s: Config %d mpp pm 8058 failed\n",
+ __func__, pm8058_mpps[i].mpp);
+ return rc;
+ }
}
- rc = pm8058_mpp_config_analog_output(PMIC_MPP_6,
- PM_MPP_AOUT_LVL_1V25_2, PM_MPP_AOUT_CTL_ENABLE);
- if (rc) {
- pr_err("%s: Config mpp5 on pmic 8058 failed\n", __func__);
- return rc;
- }
return 0;
}
-static struct pm8058_gpio_platform_data pm8058_gpio_data = {
- .gpio_base = PM8058_GPIO_PM_TO_SYS(0),
- .irq_base = PM8058_GPIO_IRQ(PMIC8058_IRQ_BASE, 0),
- .init = pm8058_gpios_init,
-};
-
-static struct pm8058_gpio_platform_data pm8058_mpp_data = {
- .gpio_base = PM8058_GPIO_PM_TO_SYS(PM8058_GPIOS),
- .irq_base = PM8058_MPP_IRQ(PMIC8058_IRQ_BASE, 0),
- .init = pm8058_mpps_init,
-};
-
static struct regulator_consumer_supply pm8058_vreg_supply[PM8058_VREG_MAX] = {
[PM8058_VREG_ID_L3] = REGULATOR_SUPPLY("8058_l3", NULL),
[PM8058_VREG_ID_L8] = REGULATOR_SUPPLY("8058_l8", NULL),
@@ -199,7 +203,7 @@
#define PM8058_VREG_INIT(_id, _min_uV, _max_uV, _modes, _ops, _apply_uV, \
_always_on, _pull_down) \
- [_id] = { \
+ { \
.init_data = { \
.constraints = { \
.valid_modes_mask = _modes, \
@@ -212,6 +216,7 @@
.num_consumer_supplies = 1, \
.consumer_supplies = &pm8058_vreg_supply[_id], \
}, \
+ .id = _id, \
.pull_down_enable = _pull_down, \
.pin_ctrl = 0, \
.pin_fn = PM8058_VREG_PIN_FN_ENABLE, \
@@ -233,7 +238,7 @@
PM8058_VREG_INIT(_id, _min_uV, _min_uV, REGULATOR_MODE_NORMAL, \
REGULATOR_CHANGE_STATUS, 0, 0, 1)
-static struct pm8058_vreg_pdata pm8058_vreg_init[PM8058_VREG_MAX] = {
+static struct pm8058_vreg_pdata pm8058_vreg_init[] = {
PM8058_VREG_INIT_LDO(PM8058_VREG_ID_L3, 1800000, 1800000),
PM8058_VREG_INIT_LDO(PM8058_VREG_ID_L8, 2200000, 2200000),
PM8058_VREG_INIT_LDO(PM8058_VREG_ID_L9, 2050000, 2050000),
@@ -244,22 +249,7 @@
PM8058_VREG_INIT_SMPS(PM8058_VREG_ID_S4, 1300000, 1300000),
};
-#define PM8058_VREG(_id) { \
- .name = "pm8058-regulator", \
- .id = _id, \
- .platform_data = &pm8058_vreg_init[_id], \
- .pdata_size = sizeof(pm8058_vreg_init[_id]), \
-}
-
#ifdef CONFIG_SENSORS_MSM_ADC
-static struct resource resources_adc[] = {
- {
- .start = PM8058_ADC_IRQ(PMIC8058_IRQ_BASE),
- .end = PM8058_ADC_IRQ(PMIC8058_IRQ_BASE),
- .flags = IORESOURCE_IRQ,
- },
-};
-
static struct adc_access_fn xoadc_fn = {
pm8058_xoadc_select_chan_and_start_conv,
pm8058_xoadc_read_adc_code,
@@ -298,17 +288,21 @@
static void pmic8058_xoadc_mpp_config(void)
{
- int rc;
-
- rc = pm8058_mpp_config_analog_input(XOADC_MPP_7,
- PM_MPP_AIN_AMUX_CH5, PM_MPP_AOUT_CTL_DISABLE);
- if (rc)
- pr_err("%s: Config mpp7 on pmic 8058 failed\n", __func__);
-
- rc = pm8058_mpp_config_analog_input(XOADC_MPP_10,
- PM_MPP_AIN_AMUX_CH6, PM_MPP_AOUT_CTL_DISABLE);
- if (rc)
- pr_err("%s: Config mpp10 on pmic 8058 failed\n", __func__);
+ int rc, i;
+ struct pm8xxx_mpp_init_info xoadc_mpps[] = {
+ PM8XXX_MPP_INIT(PMIC_MPP_7, A_INPUT, PM8XXX_MPP_AIN_AMUX_CH5,
+ AOUT_CTRL_DISABLE),
+ PM8XXX_MPP_INIT(PMIC_MPP_10, A_INPUT, PM8XXX_MPP_AIN_AMUX_CH6,
+ AOUT_CTRL_DISABLE),
+ };
+ for (i = 0; i < ARRAY_SIZE(xoadc_mpps); i++) {
+ rc = pm8xxx_mpp_config(xoadc_mpps[i].mpp,
+ &xoadc_mpps[i].config);
+ if (rc) {
+ pr_err("%s: Config MPP %d of PM8058 failed\n",
+ __func__, xoadc_mpps[i].mpp);
+ }
+ }
}
static struct regulator *vreg_ldo18_adc;
@@ -373,7 +367,7 @@
.conversiontime = 54,
};
-static struct xoadc_platform_data xoadc_pdata = {
+static struct xoadc_platform_data pm8058_xoadc_pdata = {
.xoadc_prop = &pm8058_xoadc_data,
.xoadc_mpp_config = pmic8058_xoadc_mpp_config,
.xoadc_vreg_set = pmic8058_xoadc_vreg_config,
@@ -400,7 +394,7 @@
};
#define PM8058_XO_INIT(_id, _modes, _ops, _always_on) \
- [PM8058_XO_ID_##_id] = { \
+ { \
.init_data = { \
.constraints = { \
.valid_modes_mask = _modes, \
@@ -412,63 +406,44 @@
ARRAY_SIZE(xo_consumers_##_id),\
.consumer_supplies = xo_consumers_##_id, \
}, \
+ .id = PM8058_XO_ID_##_id, \
}
#define PM8058_XO_INIT_AX(_id) \
PM8058_XO_INIT(_id, REGULATOR_MODE_NORMAL, REGULATOR_CHANGE_STATUS, 0)
-static struct pm8058_xo_pdata pm8058_xo_init_pdata[PM8058_XO_ID_MAX] = {
+static struct pm8058_xo_pdata pm8058_xo_init_pdata[] = {
PM8058_XO_INIT_AX(A0),
PM8058_XO_INIT_AX(A1),
};
-#define PM8058_XO(_id) { \
- .name = PM8058_XO_BUFFER_DEV_NAME, \
- .id = _id, \
- .platform_data = &pm8058_xo_init_pdata[_id], \
- .pdata_size = sizeof(pm8058_xo_init_pdata[_id]), \
-}
+#define PM8058_GPIO_INT 47
-/* Put sub devices with fixed location first in sub_devices array */
-static struct mfd_cell pm8058_subdevs[] = {
- { .name = "pm8058-mpp",
- .platform_data = &pm8058_mpp_data,
- .pdata_size = sizeof(pm8058_mpp_data),
- },
- {
- .name = "pm8058-gpio",
- .id = -1,
- .platform_data = &pm8058_gpio_data,
- .pdata_size = sizeof(pm8058_gpio_data),
- },
-#ifdef CONFIG_SENSORS_MSM_ADC
- {
- .name = "pm8058-xoadc",
- .id = -1,
- .num_resources = ARRAY_SIZE(resources_adc),
- .resources = resources_adc,
- .platform_data = &xoadc_pdata,
- .pdata_size =sizeof(xoadc_pdata),
- },
-#endif
- PM8058_VREG(PM8058_VREG_ID_L3),
- PM8058_VREG(PM8058_VREG_ID_L8),
- PM8058_VREG(PM8058_VREG_ID_L9),
- PM8058_VREG(PM8058_VREG_ID_L14),
- PM8058_VREG(PM8058_VREG_ID_L15),
- PM8058_VREG(PM8058_VREG_ID_L18),
- PM8058_VREG(PM8058_VREG_ID_S4),
- PM8058_VREG(PM8058_VREG_ID_LVS0),
- PM8058_XO(PM8058_XO_ID_A0),
- PM8058_XO(PM8058_XO_ID_A1),
+static struct pm8xxx_irq_platform_data pm8xxx_irq_pdata = {
+ .irq_base = PMIC8058_IRQ_BASE,
+ .devirq = MSM_GPIO_TO_INT(PM8058_GPIO_INT),
+ .irq_trigger_flag = IRQF_TRIGGER_LOW,
+};
+
+static struct pm8xxx_gpio_platform_data pm8xxx_gpio_pdata = {
+ .gpio_base = PM8058_GPIO_PM_TO_SYS(0),
+};
+
+static struct pm8xxx_mpp_platform_data pm8xxx_mpp_pdata = {
+ .mpp_base = PM8058_MPP_PM_TO_SYS(0),
};
static struct pm8058_platform_data pm8058_fsm9xxx_data = {
- .irq_base = PMIC8058_IRQ_BASE,
- .irq = MSM_GPIO_TO_INT(47),
-
- .num_subdevs = ARRAY_SIZE(pm8058_subdevs),
- .sub_devices = pm8058_subdevs,
+ .irq_pdata = &pm8xxx_irq_pdata,
+ .gpio_pdata = &pm8xxx_gpio_pdata,
+ .mpp_pdata = &pm8xxx_mpp_pdata,
+ .regulator_pdatas = pm8058_vreg_init,
+ .num_regulators = ARRAY_SIZE(pm8058_vreg_init),
+ .xo_buffer_pdata = pm8058_xo_init_pdata,
+ .num_xo_buffers = ARRAY_SIZE(pm8058_xo_init_pdata),
+#ifdef CONFIG_SENSORS_MSM_ADC
+ .xoadc_pdata = &pm8058_xoadc_pdata,
+#endif
};
#ifdef CONFIG_MSM_SSBI
@@ -882,13 +857,15 @@
msm_device_ssbi_pmic1.dev.platform_data =
&fsm9xxx_ssbi_pm8058_pdata;
#endif
+ buses_init();
platform_add_devices(devices, ARRAY_SIZE(devices));
#ifdef CONFIG_MSM_SPM
msm_spm_init(&msm_spm_data, 1);
#endif
- buses_init();
+ pm8058_gpios_init();
+ pm8058_mpps_init();
phy_init();
grfc_init();
user_gpios_init();
diff --git a/arch/arm/mach-msm/board-msm7x30.c b/arch/arm/mach-msm/board-msm7x30.c
index 9155e0c..eda29cd 100644
--- a/arch/arm/mach-msm/board-msm7x30.c
+++ b/arch/arm/mach-msm/board-msm7x30.c
@@ -23,16 +23,14 @@
#endif
#include <linux/msm_ssbi.h>
#include <linux/mfd/pmic8058.h>
+#include <linux/leds.h>
#include <linux/mfd/marimba.h>
#include <linux/i2c.h>
#include <linux/input.h>
#include <linux/smsc911x.h>
#include <linux/ofn_atlab.h>
#include <linux/power_supply.h>
-#include <linux/input/pmic8058-keypad.h>
#include <linux/i2c/isa1200.h>
-#include <linux/pwm.h>
-#include <linux/pmic8058-pwm.h>
#include <linux/i2c/tsc2007.h>
#include <linux/input/kp_flip_switch.h>
#include <linux/leds-pmic8058.h>
@@ -123,6 +121,8 @@
/* Macros assume PMIC GPIOs start at 0 */
#define PM8058_GPIO_PM_TO_SYS(pm_gpio) (pm_gpio + NR_GPIO_IRQS)
#define PM8058_GPIO_SYS_TO_PM(sys_gpio) (sys_gpio - NR_GPIO_IRQS)
+#define PM8058_MPP_BASE PM8058_GPIO_PM_TO_SYS(PM8058_GPIOS)
+#define PM8058_MPP_PM_TO_SYS(pm_gpio) (pm_gpio + PM8058_MPP_BASE)
#define PMIC_GPIO_FLASH_BOOST_ENABLE 15 /* PMIC GPIO Number 16 */
#define PMIC_GPIO_HAP_ENABLE 16 /* PMIC GPIO Number 17 */
@@ -136,61 +136,71 @@
#define PMIC_GPIO_QUICKVX_CLK 37 /* PMIC GPIO 38 */
#define PM_FLIP_MPP 5 /* PMIC MPP 06 */
+
+struct pm8xxx_gpio_init_info {
+ unsigned gpio;
+ struct pm_gpio config;
+};
+
static int pm8058_gpios_init(void)
{
int rc;
- int pmic_gpio_hdmi_5v_en;
-#ifdef CONFIG_MMC_MSM_CARD_HW_DETECTION
- struct pm8058_gpio sdcc_det = {
- .direction = PM_GPIO_DIR_IN,
- .pull = PM_GPIO_PULL_UP_1P5,
- .vin_sel = 2,
- .function = PM_GPIO_FUNC_NORMAL,
- .inv_int_pol = 0,
- };
-#endif
- struct pm8058_gpio sdc4_en = {
- .direction = PM_GPIO_DIR_OUT,
- .pull = PM_GPIO_PULL_NO,
- .vin_sel = PM_GPIO_VIN_L5,
- .function = PM_GPIO_FUNC_NORMAL,
- .inv_int_pol = 0,
- .out_strength = PM_GPIO_STRENGTH_LOW,
- .output_value = 0,
+ struct pm8xxx_gpio_init_info sdc4_en = {
+ PM8058_GPIO_PM_TO_SYS(PMIC_GPIO_SDC4_EN_N),
+ {
+ .direction = PM_GPIO_DIR_OUT,
+ .pull = PM_GPIO_PULL_NO,
+ .vin_sel = PM8058_GPIO_VIN_L5,
+ .function = PM_GPIO_FUNC_NORMAL,
+ .inv_int_pol = 0,
+ .out_strength = PM_GPIO_STRENGTH_LOW,
+ .output_value = 0,
+ },
};
- struct pm8058_gpio haptics_enable = {
- .direction = PM_GPIO_DIR_OUT,
- .pull = PM_GPIO_PULL_NO,
- .out_strength = PM_GPIO_STRENGTH_HIGH,
- .function = PM_GPIO_FUNC_NORMAL,
- .inv_int_pol = 0,
- .vin_sel = 2,
- .output_buffer = PM_GPIO_OUT_BUF_CMOS,
- .output_value = 0,
+ struct pm8xxx_gpio_init_info haptics_enable = {
+ PM8058_GPIO_PM_TO_SYS(PMIC_GPIO_HAP_ENABLE),
+ {
+ .direction = PM_GPIO_DIR_OUT,
+ .pull = PM_GPIO_PULL_NO,
+ .out_strength = PM_GPIO_STRENGTH_HIGH,
+ .function = PM_GPIO_FUNC_NORMAL,
+ .inv_int_pol = 0,
+ .vin_sel = 2,
+ .output_buffer = PM_GPIO_OUT_BUF_CMOS,
+ .output_value = 0,
+ },
};
- struct pm8058_gpio hdmi_5V_en = {
- .direction = PM_GPIO_DIR_OUT,
- .pull = PM_GPIO_PULL_NO,
- .vin_sel = PM_GPIO_VIN_VPH,
- .function = PM_GPIO_FUNC_NORMAL,
- .out_strength = PM_GPIO_STRENGTH_LOW,
- .output_value = 0,
+ struct pm8xxx_gpio_init_info hdmi_5V_en = {
+ PM8058_GPIO_PM_TO_SYS(PMIC_GPIO_HDMI_5V_EN_V3),
+ {
+ .direction = PM_GPIO_DIR_OUT,
+ .pull = PM_GPIO_PULL_NO,
+ .vin_sel = PM8058_GPIO_VIN_VPH,
+ .function = PM_GPIO_FUNC_NORMAL,
+ .out_strength = PM_GPIO_STRENGTH_LOW,
+ .output_value = 0,
+ },
};
- struct pm8058_gpio flash_boost_enable = {
- .direction = PM_GPIO_DIR_OUT,
- .output_buffer = PM_GPIO_OUT_BUF_CMOS,
- .output_value = 0,
- .pull = PM_GPIO_PULL_NO,
- .vin_sel = PM_GPIO_VIN_S3,
- .out_strength = PM_GPIO_STRENGTH_HIGH,
- .function = PM_GPIO_FUNC_2,
+ struct pm8xxx_gpio_init_info flash_boost_enable = {
+ PM8058_GPIO_PM_TO_SYS(PMIC_GPIO_FLASH_BOOST_ENABLE),
+ {
+ .direction = PM_GPIO_DIR_OUT,
+ .output_buffer = PM_GPIO_OUT_BUF_CMOS,
+ .output_value = 0,
+ .pull = PM_GPIO_PULL_NO,
+ .vin_sel = PM8058_GPIO_VIN_S3,
+ .out_strength = PM_GPIO_STRENGTH_HIGH,
+ .function = PM_GPIO_FUNC_2,
+ },
};
- struct pm8058_gpio gpio23 = {
+ struct pm8xxx_gpio_init_info gpio23 = {
+ PM8058_GPIO_PM_TO_SYS(PMIC_GPIO_WLAN_EXT_POR),
+ {
.direction = PM_GPIO_DIR_OUT,
.output_buffer = PM_GPIO_OUT_BUF_CMOS,
.output_value = 0,
@@ -198,71 +208,83 @@
.vin_sel = 2,
.out_strength = PM_GPIO_STRENGTH_LOW,
.function = PM_GPIO_FUNC_NORMAL,
+ }
};
-
- if (machine_is_msm8x55_svlte_surf() || machine_is_msm8x55_svlte_ffa() ||
- machine_is_msm7x30_fluid())
- pmic_gpio_hdmi_5v_en = PMIC_GPIO_HDMI_5V_EN_V2 ;
- else
- pmic_gpio_hdmi_5v_en = PMIC_GPIO_HDMI_5V_EN_V3 ;
-
- if (machine_is_msm7x30_fluid()) {
- rc = pm8058_gpio_config(PMIC_GPIO_HAP_ENABLE, &haptics_enable);
- if (rc) {
- pr_err("%s: PMIC GPIO %d write failed\n", __func__,
- (PMIC_GPIO_HAP_ENABLE + 1));
- return rc;
- }
- rc = pm8058_gpio_config(PMIC_GPIO_FLASH_BOOST_ENABLE,
- &flash_boost_enable);
- if (rc) {
- pr_err("%s: PMIC GPIO %d write failed\n", __func__,
- (PMIC_GPIO_FLASH_BOOST_ENABLE + 1));
- return rc;
- }
- }
-
#ifdef CONFIG_MMC_MSM_CARD_HW_DETECTION
- if (machine_is_msm7x30_fluid())
- sdcc_det.inv_int_pol = 1;
+ struct pm8xxx_gpio_init_info sdcc_det = {
+ PM8058_GPIO_PM_TO_SYS(PMIC_GPIO_SD_DET - 1),
+ {
+ .direction = PM_GPIO_DIR_IN,
+ .pull = PM_GPIO_PULL_UP_1P5,
+ .vin_sel = 2,
+ .function = PM_GPIO_FUNC_NORMAL,
+ .inv_int_pol = 0,
+ },
+ };
- rc = pm8058_gpio_config(PMIC_GPIO_SD_DET - 1, &sdcc_det);
+ if (machine_is_msm7x30_fluid())
+ sdcc_det.config.inv_int_pol = 1;
+
+ rc = pm8xxx_gpio_config(sdcc_det.gpio, &sdcc_det.config);
if (rc) {
pr_err("%s PMIC_GPIO_SD_DET config failed\n", __func__);
return rc;
}
#endif
- rc = pm8058_gpio_config(pmic_gpio_hdmi_5v_en, &hdmi_5V_en);
+ if (machine_is_msm8x55_svlte_surf() || machine_is_msm8x55_svlte_ffa() ||
+ machine_is_msm7x30_fluid())
+ hdmi_5V_en.gpio = PMIC_GPIO_HDMI_5V_EN_V2;
+ else
+ hdmi_5V_en.gpio = PMIC_GPIO_HDMI_5V_EN_V3;
+
+ hdmi_5V_en.gpio = PM8058_GPIO_PM_TO_SYS(hdmi_5V_en.gpio);
+
+ rc = pm8xxx_gpio_config(hdmi_5V_en.gpio, &hdmi_5V_en.config);
if (rc) {
pr_err("%s PMIC_GPIO_HDMI_5V_EN config failed\n", __func__);
return rc;
}
/* Deassert GPIO#23 (source for Ext_POR on WLAN-Volans) */
- rc = pm8058_gpio_config(PMIC_GPIO_WLAN_EXT_POR, &gpio23);
+ rc = pm8xxx_gpio_config(gpio23.gpio, &gpio23.config);
if (rc) {
pr_err("%s PMIC_GPIO_WLAN_EXT_POR config failed\n", __func__);
return rc;
}
if (machine_is_msm7x30_fluid()) {
- rc = pm8058_gpio_config(PMIC_GPIO_SDC4_EN_N, &sdc4_en);
+ /* Haptics gpio */
+ rc = pm8xxx_gpio_config(haptics_enable.gpio,
+ &haptics_enable.config);
+ if (rc) {
+ pr_err("%s: PMIC GPIO %d write failed\n", __func__,
+ haptics_enable.gpio);
+ return rc;
+ }
+ /* Flash boost gpio */
+ rc = pm8xxx_gpio_config(flash_boost_enable.gpio,
+ &flash_boost_enable.config);
+ if (rc) {
+ pr_err("%s: PMIC GPIO %d write failed\n", __func__,
+ flash_boost_enable.gpio);
+ return rc;
+ }
+ /* SCD4 gpio */
+ rc = pm8xxx_gpio_config(sdc4_en.gpio, &sdc4_en.config);
if (rc) {
pr_err("%s PMIC_GPIO_SDC4_EN_N config failed\n",
__func__);
return rc;
}
- rc = gpio_request(PM8058_GPIO_PM_TO_SYS(PMIC_GPIO_SDC4_EN_N),
- "sdc4_en");
+ rc = gpio_request(sdc4_en.gpio, "sdc4_en");
if (rc) {
pr_err("%s PMIC_GPIO_SDC4_EN_N gpio_request failed\n",
__func__);
return rc;
}
- gpio_set_value_cansleep(
- PM8058_GPIO_PM_TO_SYS(PMIC_GPIO_SDC4_EN_N), 0);
+ gpio_set_value_cansleep(sdc4_en.gpio, 0);
}
return 0;
@@ -450,12 +472,12 @@
static int pm8058_pwm_config(struct pwm_device *pwm, int ch, int on)
{
- struct pm8058_gpio pwm_gpio_config = {
+ struct pm_gpio pwm_gpio_config = {
.direction = PM_GPIO_DIR_OUT,
.output_buffer = PM_GPIO_OUT_BUF_CMOS,
.output_value = 0,
.pull = PM_GPIO_PULL_NO,
- .vin_sel = PM_GPIO_VIN_S3,
+ .vin_sel = PM8058_GPIO_VIN_S3,
.out_strength = PM_GPIO_STRENGTH_HIGH,
.function = PM_GPIO_FUNC_2,
};
@@ -469,9 +491,10 @@
case 2:
if (on) {
id = 24 + ch;
- rc = pm8058_gpio_config(id - 1, &pwm_gpio_config);
+ rc = pm8xxx_gpio_config(PM8058_GPIO_PM_TO_SYS(id - 1),
+ &pwm_gpio_config);
if (rc)
- pr_err("%s: pm8058_gpio_config(%d): rc=%d\n",
+ pr_err("%s: pm8xxx_gpio_config(%d): rc=%d\n",
__func__, id, rc);
}
break;
@@ -660,78 +683,47 @@
KEY(11, 7, KEY_RIGHTSHIFT),
};
-static struct resource resources_keypad[] = {
- {
- .start = PM8058_KEYPAD_IRQ(PMIC8058_IRQ_BASE),
- .end = PM8058_KEYPAD_IRQ(PMIC8058_IRQ_BASE),
- .flags = IORESOURCE_IRQ,
- },
- {
- .start = PM8058_KEYSTUCK_IRQ(PMIC8058_IRQ_BASE),
- .end = PM8058_KEYSTUCK_IRQ(PMIC8058_IRQ_BASE),
- .flags = IORESOURCE_IRQ,
- },
-};
-
static struct matrix_keymap_data surf_keymap_data = {
- .keymap_size = ARRAY_SIZE(surf_keymap),
- .keymap = surf_keymap,
+ .keymap_size = ARRAY_SIZE(surf_keymap),
+ .keymap = surf_keymap,
};
-
-static struct pmic8058_keypad_data surf_keypad_data = {
+static struct pm8xxx_keypad_platform_data surf_keypad_data = {
.input_name = "surf_keypad",
.input_phys_device = "surf_keypad/input0",
.num_rows = 12,
.num_cols = 8,
- .rows_gpio_start = 8,
- .cols_gpio_start = 0,
- .debounce_ms = {8, 10},
+ .rows_gpio_start = PM8058_GPIO_PM_TO_SYS(8),
+ .cols_gpio_start = PM8058_GPIO_PM_TO_SYS(0),
+ .debounce_ms = 15,
.scan_delay_ms = 32,
.row_hold_ns = 91500,
.wakeup = 1,
- .keymap_data = &surf_keymap_data,
+ .keymap_data = &surf_keymap_data,
};
static struct matrix_keymap_data fluid_keymap_data = {
- .keymap_size = ARRAY_SIZE(fluid_keymap),
- .keymap = fluid_keymap,
+ .keymap_size = ARRAY_SIZE(fluid_keymap),
+ .keymap = fluid_keymap,
};
-
-
-static struct pmic8058_keypad_data fluid_keypad_data = {
+static struct pm8xxx_keypad_platform_data fluid_keypad_data = {
.input_name = "fluid-keypad",
.input_phys_device = "fluid-keypad/input0",
.num_rows = 5,
.num_cols = 5,
- .rows_gpio_start = 8,
- .cols_gpio_start = 0,
- .debounce_ms = {8, 10},
+ .rows_gpio_start = PM8058_GPIO_PM_TO_SYS(8),
+ .cols_gpio_start = PM8058_GPIO_PM_TO_SYS(0),
+ .debounce_ms = 15,
.scan_delay_ms = 32,
.row_hold_ns = 91500,
.wakeup = 1,
- .keymap_data = &fluid_keymap_data,
+ .keymap_data = &fluid_keymap_data,
};
static struct pm8058_pwm_pdata pm8058_pwm_data = {
- .config = pm8058_pwm_config,
- .enable = pm8058_pwm_enable,
-};
-
-/* Put sub devices with fixed location first in sub_devices array */
-#define PM8058_SUBDEV_KPD 0
-#define PM8058_SUBDEV_LED 1
-
-static struct pm8058_gpio_platform_data pm8058_gpio_data = {
- .gpio_base = PM8058_GPIO_PM_TO_SYS(0),
- .irq_base = PM8058_GPIO_IRQ(PMIC8058_IRQ_BASE, 0),
- .init = pm8058_gpios_init,
-};
-
-static struct pm8058_gpio_platform_data pm8058_mpp_data = {
- .gpio_base = PM8058_GPIO_PM_TO_SYS(PM8058_GPIOS),
- .irq_base = PM8058_MPP_IRQ(PMIC8058_IRQ_BASE, 0),
+ .config = pm8058_pwm_config,
+ .enable = pm8058_pwm_enable,
};
static struct pmic8058_led pmic8058_ffa_leds[] = {
@@ -765,38 +757,6 @@
},
};
-static struct mfd_cell pm8058_subdevs[] = {
- { .name = "pm8058-keypad",
- .id = -1,
- .num_resources = ARRAY_SIZE(resources_keypad),
- .resources = resources_keypad,
- },
- { .name = "pm8058-led",
- .id = -1,
- },
- { .name = "pm8058-gpio",
- .id = -1,
- .platform_data = &pm8058_gpio_data,
- .pdata_size = sizeof(pm8058_gpio_data),
- },
- { .name = "pm8058-mpp",
- .id = -1,
- .platform_data = &pm8058_mpp_data,
- .pdata_size = sizeof(pm8058_mpp_data),
- },
- { .name = "pm8058-pwm",
- .id = -1,
- .platform_data = &pm8058_pwm_data,
- .pdata_size = sizeof(pm8058_pwm_data),
- },
- { .name = "pm8058-nfc",
- .id = -1,
- },
- { .name = "pm8058-upl",
- .id = -1,
- },
-};
-
static struct pmic8058_leds_platform_data pm8058_surf_leds_data = {
.num_leds = ARRAY_SIZE(pmic8058_surf_leds),
.leds = pmic8058_surf_leds,
@@ -825,13 +785,25 @@
.leds = pmic8058_fluid_leds,
};
-static struct pm8058_platform_data pm8058_7x30_data = {
- .irq_base = PMIC8058_IRQ_BASE,
- .irq = MSM_GPIO_TO_INT(PMIC_GPIO_INT),
+static struct pm8xxx_irq_platform_data pm8xxx_irq_pdata = {
+ .irq_base = PMIC8058_IRQ_BASE,
+ .devirq = MSM_GPIO_TO_INT(PMIC_GPIO_INT),
+ .irq_trigger_flag = IRQF_TRIGGER_LOW,
+};
- .num_subdevs = ARRAY_SIZE(pm8058_subdevs),
- .sub_devices = pm8058_subdevs,
- .irq_trigger_flags = IRQF_TRIGGER_LOW,
+static struct pm8xxx_gpio_platform_data pm8xxx_gpio_pdata = {
+ .gpio_base = PM8058_GPIO_PM_TO_SYS(0),
+};
+
+static struct pm8xxx_mpp_platform_data pm8xxx_mpp_pdata = {
+ .mpp_base = PM8058_MPP_PM_TO_SYS(0),
+};
+
+static struct pm8058_platform_data pm8058_7x30_data = {
+ .irq_pdata = &pm8xxx_irq_pdata,
+ .gpio_pdata = &pm8xxx_gpio_pdata,
+ .mpp_pdata = &pm8xxx_mpp_pdata,
+ .pwm_pdata = &pm8058_pwm_data,
};
#ifdef CONFIG_MSM_SSBI
@@ -1611,15 +1583,10 @@
pr_err("%s: gpio_tlmm_config (gpio=%d) failed\n",
__func__, PMIC_GPIO_INT);
- if (machine_is_msm7x30_fluid()) {
- pm8058_7x30_data.sub_devices[PM8058_SUBDEV_KPD].platform_data
- = &fluid_keypad_data;
- } else {
- pm8058_7x30_data.sub_devices[PM8058_SUBDEV_KPD].platform_data
- = &surf_keypad_data;
- pm8058_7x30_data.sub_devices[PM8058_SUBDEV_KPD].pdata_size
- = sizeof(surf_keypad_data);
- }
+ if (machine_is_msm8x60_fluid())
+ pm8058_7x30_data.keypad_pdata = &fluid_keypad_data;
+ else
+ pm8058_7x30_data.keypad_pdata = &surf_keypad_data;
return 0;
}
@@ -3246,24 +3213,27 @@
{
int rc;
static int vbus_is_on;
- struct pm8058_gpio usb_vbus = {
- .direction = PM_GPIO_DIR_OUT,
- .pull = PM_GPIO_PULL_NO,
- .output_buffer = PM_GPIO_OUT_BUF_CMOS,
- .output_value = 1,
- .vin_sel = 2,
- .out_strength = PM_GPIO_STRENGTH_MED,
- .function = PM_GPIO_FUNC_NORMAL,
- .inv_int_pol = 0,
- };
+ struct pm8xxx_gpio_init_info usb_vbus = {
+ PM8058_GPIO_PM_TO_SYS(36),
+ {
+ .direction = PM_GPIO_DIR_OUT,
+ .pull = PM_GPIO_PULL_NO,
+ .output_buffer = PM_GPIO_OUT_BUF_CMOS,
+ .output_value = 1,
+ .vin_sel = 2,
+ .out_strength = PM_GPIO_STRENGTH_MED,
+ .function = PM_GPIO_FUNC_NORMAL,
+ .inv_int_pol = 0,
+ },
+ };
/* If VBUS is already on (or off), do nothing. */
if (unlikely(on == vbus_is_on))
return;
if (on) {
- rc = pm8058_gpio_config(36, &usb_vbus);
- if (rc) {
+ rc = pm8xxx_gpio_config(usb_vbus.gpio, &usb_vbus.config);
+ if (rc) {
pr_err("%s PMIC GPIO 36 write failed\n", __func__);
return;
}
@@ -4041,14 +4011,17 @@
static unsigned quickvx_vlp_gpio =
GPIO_CFG(97, 0, GPIO_CFG_OUTPUT, GPIO_CFG_NO_PULL, GPIO_CFG_2MA);
-static struct pm8058_gpio pmic_quickvx_clk_gpio = {
- .direction = PM_GPIO_DIR_OUT,
- .output_buffer = PM_GPIO_OUT_BUF_CMOS,
- .output_value = 1,
- .pull = PM_GPIO_PULL_NO,
- .vin_sel = PM_GPIO_VIN_S3,
- .out_strength = PM_GPIO_STRENGTH_HIGH,
- .function = PM_GPIO_FUNC_2,
+static struct pm8xxx_gpio_init_info pmic_quickvx_clk_gpio = {
+ PM8058_GPIO_PM_TO_SYS(PMIC_GPIO_QUICKVX_CLK),
+ {
+ .direction = PM_GPIO_DIR_OUT,
+ .output_buffer = PM_GPIO_OUT_BUF_CMOS,
+ .output_value = 1,
+ .pull = PM_GPIO_PULL_NO,
+ .vin_sel = PM8058_GPIO_VIN_S3,
+ .out_strength = PM_GPIO_STRENGTH_HIGH,
+ .function = PM_GPIO_FUNC_2,
+ },
};
static int display_common_power(int on)
@@ -4088,11 +4061,11 @@
/* bring QuickVX VLP line low */
gpio_set_value(97, 0);
- rc = pm8058_gpio_config(PMIC_GPIO_QUICKVX_CLK,
- &pmic_quickvx_clk_gpio);
+ rc = pm8xxx_gpio_config(pmic_quickvx_clk_gpio.gpio,
+ &pmic_quickvx_clk_gpio.config);
if (rc) {
- pr_err("%s: pm8058_gpio_config(%#x)=%d\n",
- __func__, PMIC_GPIO_QUICKVX_CLK + 1,
+ pr_err("%s: pm8xxx_gpio_config(%#x)=%d\n",
+ __func__, pmic_quickvx_clk_gpio.gpio,
rc);
return rc;
}
@@ -6452,16 +6425,12 @@
static void __init pmic8058_leds_init(void)
{
- if (machine_is_msm7x30_surf()) {
- pm8058_7x30_data.sub_devices[PM8058_SUBDEV_LED].platform_data
- = &pm8058_surf_leds_data;
- } else if (!machine_is_msm7x30_fluid()) {
- pm8058_7x30_data.sub_devices[PM8058_SUBDEV_LED].platform_data
- = &pm8058_ffa_leds_data;
- } else if (machine_is_msm7x30_fluid()) {
- pm8058_7x30_data.sub_devices[PM8058_SUBDEV_LED].platform_data
- = &pm8058_fluid_leds_data;
- }
+ if (machine_is_msm7x30_surf())
+ pm8058_7x30_data.leds_pdata = &pm8058_surf_leds_data;
+ else if (!machine_is_msm7x30_fluid())
+ pm8058_7x30_data.leds_pdata = &pm8058_ffa_leds_data;
+ else if (machine_is_msm7x30_fluid())
+ pm8058_7x30_data.leds_pdata = &pm8058_fluid_leds_data;
}
static struct msm_spm_platform_data msm_spm_data __initdata = {
@@ -6780,8 +6749,14 @@
static int kp_flip_mpp_config(void)
{
- return pm8058_mpp_config_digital_in(PM_FLIP_MPP,
- PM8058_MPP_DIG_LEVEL_S3, PM_MPP_DIN_TO_INT);
+ struct pm8xxx_mpp_config_data kp_flip_mpp = {
+ .type = PM8XXX_MPP_TYPE_D_INPUT,
+ .level = PM8018_MPP_DIG_LEVEL_S3,
+ .control = PM8XXX_MPP_DIN_TO_INT,
+ };
+
+ return pm8xxx_mpp_config(PM8058_MPP_PM_TO_SYS(PM_FLIP_MPP),
+ &kp_flip_mpp);
}
static struct flip_switch_pdata flip_switch_data = {
@@ -6992,6 +6967,10 @@
msm_adc_pdata.num_adc = ARRAY_SIZE(msm_adc_surf_device_names);
}
+ pmic8058_leds_init();
+
+ buses_init();
+
#ifdef CONFIG_MSM_SSBI
msm_device_ssbi_pmic1.dev.platform_data =
&msm7x30_ssbi_pm8058_pdata;
@@ -7023,7 +7002,6 @@
msm_device_i2c_init();
msm_device_i2c_2_init();
qup_device_i2c_init();
- buses_init();
msm7x30_init_marimba();
#ifdef CONFIG_MSM7KV2_AUDIO
snddev_poweramp_gpio_init();
@@ -7071,7 +7049,8 @@
if (machine_is_msm7x30_surf())
platform_device_register(&flip_switch_device);
- pmic8058_leds_init();
+
+ pm8058_gpios_init();
if (machine_is_msm7x30_fluid()) {
/* Initialize platform data for fluid v2 hardware */
diff --git a/arch/arm/mach-msm/board-msm8960-regulator.c b/arch/arm/mach-msm/board-msm8960-regulator.c
index de2a94e..c67e100 100644
--- a/arch/arm/mach-msm/board-msm8960-regulator.c
+++ b/arch/arm/mach-msm/board-msm8960-regulator.c
@@ -165,6 +165,7 @@
REGULATOR_SUPPLY("CDC_VDDA_RX", "tabla2x-slim"),
REGULATOR_SUPPLY("vcc_i2c", "3-005b"),
REGULATOR_SUPPLY("EXT_HUB_VDDIO", "msm_hsic_host"),
+ REGULATOR_SUPPLY("vcc_i2c", "10-0048"),
};
VREG_CONSUMERS(S5) = {
REGULATOR_SUPPLY("8921_s5", NULL),
diff --git a/arch/arm/mach-msm/board-msm8960.c b/arch/arm/mach-msm/board-msm8960.c
index 3636963..ece65f3 100644
--- a/arch/arm/mach-msm/board-msm8960.c
+++ b/arch/arm/mach-msm/board-msm8960.c
@@ -39,6 +39,7 @@
#include <linux/i2c/atmel_mxt_ts.h>
#include <linux/msm_tsens.h>
#include <linux/ks8851.h>
+#include <linux/i2c/isa1200.h>
#include <asm/mach-types.h>
#include <asm/mach/arch.h>
@@ -776,6 +777,30 @@
};
#endif
+#define HAP_SHIFT_LVL_OE_GPIO 47
+
+static struct gpiomux_setting hap_lvl_shft_suspended_config = {
+ .func = GPIOMUX_FUNC_GPIO,
+ .drv = GPIOMUX_DRV_2MA,
+ .pull = GPIOMUX_PULL_DOWN,
+};
+
+static struct gpiomux_setting hap_lvl_shft_active_config = {
+ .func = GPIOMUX_FUNC_GPIO,
+ .drv = GPIOMUX_DRV_8MA,
+ .pull = GPIOMUX_PULL_UP,
+};
+
+static struct msm_gpiomux_config hap_lvl_shft_config[] __initdata = {
+ {
+ .gpio = HAP_SHIFT_LVL_OE_GPIO,
+ .settings = {
+ [GPIOMUX_SUSPENDED] = &hap_lvl_shft_suspended_config,
+ [GPIOMUX_ACTIVE] = &hap_lvl_shft_active_config,
+ },
+ },
+};
+
#if defined(CONFIG_GPIO_SX150X) || defined(CONFIG_GPIO_SX150X_MODULE)
enum {
SX150X_CAM,
@@ -818,7 +843,6 @@
#endif
#endif
-#define MSM_PMEM_KERNEL_EBI1_SIZE 0x110C000
#define MSM_PMEM_ADSP_SIZE 0x3800000
#define MSM_PMEM_AUDIO_SIZE 0x28B000
#ifdef CONFIG_FB_MSM_HDMI_AS_PRIMARY
@@ -829,10 +853,12 @@
#ifdef CONFIG_MSM_MULTIMEDIA_USE_ION
-#define MSM_ION_EBI_SIZE MSM_PMEM_SIZE
+#define MSM_PMEM_KERNEL_EBI1_SIZE 0xB0C000
+#define MSM_ION_EBI_SIZE (MSM_PMEM_SIZE + 0x600000)
#define MSM_ION_ADSP_SIZE MSM_PMEM_ADSP_SIZE
#define MSM_ION_HEAP_NUM 4
#else
+#define MSM_PMEM_KERNEL_EBI1_SIZE 0x110C000
#define MSM_ION_HEAP_NUM 2
#endif
@@ -1419,6 +1445,14 @@
msm_get_cam_resources(s_info);
platform_device_register(cam_dev[i]);
}
+
+ platform_device_register(&msm8960_device_csiphy0);
+ platform_device_register(&msm8960_device_csiphy1);
+ platform_device_register(&msm8960_device_csid0);
+ platform_device_register(&msm8960_device_csid1);
+ platform_device_register(&msm8960_device_ispif);
+ platform_device_register(&msm8960_device_vfe);
+ platform_device_register(&msm8960_device_vpe);
}
#endif
@@ -2691,6 +2725,10 @@
msm_gpiomux_install(wcnss_5wire_interface,
ARRAY_SIZE(wcnss_5wire_interface));
+ if (machine_is_msm8960_mtp() || machine_is_msm8960_fluid() ||
+ machine_is_msm8960_liquid() || machine_is_msm8960_cdp())
+ msm_gpiomux_install(hap_lvl_shft_config,
+ ARRAY_SIZE(hap_lvl_shft_config));
return 0;
}
@@ -2803,7 +2841,6 @@
/* SDCC1 : eMMC card connected */
[SDCC1] = {
.name = "sdc_vdd",
- .set_voltage_sup = 1,
.high_vol_level = 2950000,
.low_vol_level = 2950000,
.always_on = 1,
@@ -2814,7 +2851,6 @@
/* SDCC3 : External card slot connected */
[SDCC3] = {
.name = "sdc_vdd",
- .set_voltage_sup = 1,
.high_vol_level = 2950000,
.low_vol_level = 2950000,
.hpm_uA = 600000, /* 600mA */
@@ -2826,7 +2862,6 @@
/* SDCC1 : eMMC card connected */
[SDCC1] = {
.name = "sdc_vccq",
- .set_voltage_sup = 1,
.always_on = 1,
.high_vol_level = 1800000,
.low_vol_level = 1800000,
@@ -2839,7 +2874,6 @@
/* SDCC3 : External card slot connected */
[SDCC3] = {
.name = "sdc_vddp",
- .set_voltage_sup = 1,
.high_vol_level = 2950000,
.low_vol_level = 1850000,
.always_on = 1,
@@ -2994,7 +3028,6 @@
.sup_clk_cnt = ARRAY_SIZE(sdc1_sup_clk_rates),
.pclk_src_dfab = 1,
.nonremovable = 1,
- .sdcc_v4_sup = true,
.vreg_data = &mmc_slot_vreg_data[SDCC1],
.pin_data = &mmc_slot_pin_data[SDCC1]
};
@@ -3010,7 +3043,6 @@
#ifdef CONFIG_MMC_MSM_SDC3_WP_SUPPORT
.wpswitch_gpio = PM8921_GPIO_PM_TO_SYS(16),
#endif
- .sdcc_v4_sup = true,
.vreg_data = &mmc_slot_vreg_data[SDCC3],
.pin_data = &mmc_slot_pin_data[SDCC3],
#ifdef CONFIG_MMC_MSM_CARD_HW_DETECTION
@@ -3318,6 +3350,132 @@
},
};
+#define PM_HAP_EN_GPIO PM8921_GPIO_PM_TO_SYS(33)
+#define PM_HAP_LEN_GPIO PM8921_GPIO_PM_TO_SYS(20)
+
+static struct msm_xo_voter *xo_handle_d1;
+
+static int isa1200_power(int on)
+{
+ int rc = 0;
+
+ gpio_set_value(HAP_SHIFT_LVL_OE_GPIO, !!on);
+
+ rc = on ? msm_xo_mode_vote(xo_handle_d1, MSM_XO_MODE_ON) :
+ msm_xo_mode_vote(xo_handle_d1, MSM_XO_MODE_OFF);
+ if (rc < 0) {
+ pr_err("%s: failed to %svote for TCXO D1 buffer%d\n",
+ __func__, on ? "" : "de-", rc);
+ goto err_xo_vote;
+ }
+
+ return 0;
+
+err_xo_vote:
+ gpio_set_value(HAP_SHIFT_LVL_OE_GPIO, !on);
+ return rc;
+}
+
+static int isa1200_dev_setup(bool enable)
+{
+ int rc = 0;
+
+ struct pm_gpio hap_gpio_config = {
+ .direction = PM_GPIO_DIR_OUT,
+ .pull = PM_GPIO_PULL_NO,
+ .out_strength = PM_GPIO_STRENGTH_HIGH,
+ .function = PM_GPIO_FUNC_NORMAL,
+ .inv_int_pol = 0,
+ .vin_sel = 2,
+ .output_buffer = PM_GPIO_OUT_BUF_CMOS,
+ .output_value = 0,
+ };
+
+ if (enable == true) {
+ rc = pm8xxx_gpio_config(PM_HAP_EN_GPIO, &hap_gpio_config);
+ if (rc) {
+ pr_err("%s: pm8921 gpio %d config failed(%d)\n",
+ __func__, PM_HAP_EN_GPIO, rc);
+ return rc;
+ }
+
+ rc = pm8xxx_gpio_config(PM_HAP_LEN_GPIO, &hap_gpio_config);
+ if (rc) {
+ pr_err("%s: pm8921 gpio %d config failed(%d)\n",
+ __func__, PM_HAP_LEN_GPIO, rc);
+ return rc;
+ }
+
+ rc = gpio_request(HAP_SHIFT_LVL_OE_GPIO, "hap_shft_lvl_oe");
+ if (rc) {
+ pr_err("%s: unable to request gpio %d (%d)\n",
+ __func__, HAP_SHIFT_LVL_OE_GPIO, rc);
+ return rc;
+ }
+
+ rc = gpio_direction_output(HAP_SHIFT_LVL_OE_GPIO, 0);
+ if (rc) {
+ pr_err("%s: Unable to set direction\n", __func__);
+ goto free_gpio;
+ }
+
+ xo_handle_d1 = msm_xo_get(MSM_XO_TCXO_D1, "isa1200");
+ if (IS_ERR(xo_handle_d1)) {
+ rc = PTR_ERR(xo_handle_d1);
+ pr_err("%s: failed to get the handle for D1(%d)\n",
+ __func__, rc);
+ goto gpio_set_dir;
+ }
+ } else {
+ gpio_free(HAP_SHIFT_LVL_OE_GPIO);
+
+ msm_xo_put(xo_handle_d1);
+ }
+
+ return 0;
+
+gpio_set_dir:
+ gpio_set_value(HAP_SHIFT_LVL_OE_GPIO, 0);
+free_gpio:
+ gpio_free(HAP_SHIFT_LVL_OE_GPIO);
+ return rc;
+}
+
+static struct isa1200_regulator isa1200_reg_data[] = {
+ {
+ .name = "vcc_i2c",
+ .min_uV = ISA_I2C_VTG_MIN_UV,
+ .max_uV = ISA_I2C_VTG_MAX_UV,
+ .load_uA = ISA_I2C_CURR_UA,
+ },
+};
+
+static struct isa1200_platform_data isa1200_1_pdata = {
+ .name = "vibrator",
+ .dev_setup = isa1200_dev_setup,
+ .power_on = isa1200_power,
+ .hap_en_gpio = PM_HAP_EN_GPIO,
+ .hap_len_gpio = PM_HAP_LEN_GPIO,
+ .max_timeout = 15000,
+ .mode_ctrl = PWM_GEN_MODE,
+ .pwm_fd = {
+ .pwm_div = 256,
+ },
+ .is_erm = false,
+ .smart_en = true,
+ .ext_clk_en = true,
+ .chip_en = 1,
+ .regulator_info = isa1200_reg_data,
+ .num_regulators = ARRAY_SIZE(isa1200_reg_data),
+};
+
+static struct i2c_board_info msm_isa1200_board_info[] __initdata = {
+ {
+ I2C_BOARD_INFO("isa1200_1", 0x90>>1),
+ .platform_data = &isa1200_1_pdata,
+ },
+};
+
#define CYTTSP_TS_GPIO_IRQ 11
#define CYTTSP_TS_SLEEP_GPIO 50
#define CYTTSP_TS_RESOUT_N_GPIO 52
@@ -3787,6 +3945,7 @@
&msm_etb_device,
&msm_tpiu_device,
&msm_funnel_device,
+ &msm_debug_device,
&msm_ptm_device,
#endif
&msm_device_dspcrashd_8960,
@@ -4514,7 +4673,12 @@
mxt_device_info,
ARRAY_SIZE(mxt_device_info),
},
-
+ {
+ I2C_LIQUID,
+ MSM_8960_GSBI10_QUP_I2C_BUS_ID,
+ msm_isa1200_board_info,
+ ARRAY_SIZE(msm_isa1200_board_info),
+ },
};
#endif /* CONFIG_I2C */
@@ -4570,8 +4734,6 @@
pm8921_platform_data.keypad_pdata = &keypad_data_sim;
msm8960_device_otg.dev.platform_data = &msm_otg_pdata;
- msm8960_device_gadget_peripheral.dev.parent = &msm8960_device_otg.dev;
- msm_device_hsusb_host.dev.parent = &msm8960_device_otg.dev;
gpiomux_init();
msm8960_i2c_init();
msm_spm_init(msm_spm_data, ARRAY_SIZE(msm_spm_data));
@@ -4648,8 +4810,6 @@
if (machine_is_msm8960_liquid())
msm_otg_pdata.mhl_enable = true;
msm8960_device_otg.dev.platform_data = &msm_otg_pdata;
- msm8960_device_gadget_peripheral.dev.parent = &msm8960_device_otg.dev;
- msm_device_hsusb_host.dev.parent = &msm8960_device_otg.dev;
#ifdef CONFIG_USB_EHCI_MSM_HSIC
if (machine_is_msm8960_liquid()) {
if (SOCINFO_VERSION_MAJOR(socinfo_get_version()) >= 2)
diff --git a/arch/arm/mach-msm/board-msm8x60.c b/arch/arm/mach-msm/board-msm8x60.c
index b217b41..090605f 100644
--- a/arch/arm/mach-msm/board-msm8x60.c
+++ b/arch/arm/mach-msm/board-msm8x60.c
@@ -19,21 +19,11 @@
#include <linux/msm_ssbi.h>
#include <linux/mfd/pmic8058.h>
-#include <linux/input/pmic8058-keypad.h>
-#include <linux/pmic8058-batt-alarm.h>
-#include <linux/pmic8058-pwrkey.h>
-#include <linux/rtc/rtc-pm8058.h>
-#include <linux/pmic8058-vibrator.h>
#include <linux/leds.h>
#include <linux/pmic8058-othc.h>
#include <linux/mfd/pmic8901.h>
-#include <linux/regulator/pmic8058-regulator.h>
#include <linux/regulator/pmic8901-regulator.h>
#include <linux/bootmem.h>
-#include <linux/pwm.h>
-#include <linux/pmic8058-pwm.h>
-#include <linux/leds-pmic8058.h>
-#include <linux/pmic8058-xoadc.h>
#include <linux/msm_adc.h>
#include <linux/m_adcproc.h>
#include <linux/mfd/marimba.h>
@@ -274,6 +264,21 @@
GPIO_EPM_EXPANDER_IO15,
};
+struct pm8xxx_mpp_init_info {
+ unsigned mpp;
+ struct pm8xxx_mpp_config_data config;
+};
+
+#define PM8XXX_MPP_INIT(_mpp, _type, _level, _control) \
+{ \
+ .mpp = PM8058_MPP_PM_TO_SYS(_mpp), \
+ .config = { \
+ .type = PM8XXX_MPP_TYPE_##_type, \
+ .level = _level, \
+ .control = PM8XXX_MPP_##_control, \
+ } \
+}
+
/*
* The UI_INTx_N lines are pmic gpio lines which connect i2c
* gpio expanders to the pm8058.
@@ -993,6 +998,7 @@
static struct regulator *ldo7_1p8;
static struct regulator *vdd_cx;
#define PMICID_INT PM8058_GPIO_IRQ(PM8058_IRQ_BASE, 36)
+#define PMIC_ID_GPIO 36
notify_vbus_state notify_vbus_state_func_ptr;
static int usb_phy_susp_dig_vol = 750000;
static int pmic_id_notif_supported;
@@ -1031,10 +1037,42 @@
return IRQ_HANDLED;
}
+static int msm_hsusb_phy_id_setup_init(int init)
+{
+ unsigned ret;
+
+ if (init) {
+ ret = pm8901_mpp_config_digital_out(1,
+ PM8901_MPP_DIG_LEVEL_L5, 1);
+ if (ret < 0)
+ pr_err("%s:MPP2 configuration failed\n", __func__);
+ } else {
+ ret = pm8901_mpp_config_digital_out(1,
+ PM8901_MPP_DIG_LEVEL_L5, 0);
+ if (ret < 0)
+ pr_err("%s:MPP2 un config failed\n", __func__);
+ }
+ return ret;
+}
+
static int msm_hsusb_pmic_id_notif_init(void (*callback)(int online), int init)
{
unsigned ret = -ENODEV;
+ struct pm_gpio pmic_id_cfg = {
+ .direction = PM_GPIO_DIR_IN,
+ .pull = PM_GPIO_PULL_UP_1P5,
+ .function = PM_GPIO_FUNC_NORMAL,
+ .vin_sel = 2,
+ .inv_int_pol = 0,
+ };
+ struct pm_gpio pmic_id_uncfg = {
+ .direction = PM_GPIO_DIR_IN,
+ .pull = PM_GPIO_PULL_NO,
+ .function = PM_GPIO_FUNC_NORMAL,
+ .vin_sel = 2,
+ .inv_int_pol = 0,
+ };
if (!callback)
return -EINVAL;
@@ -1058,37 +1096,36 @@
if (init) {
notify_vbus_state_func_ptr = callback;
- ret = pm8901_mpp_config_digital_out(1,
- PM8901_MPP_DIG_LEVEL_L5, 1);
- if (ret) {
- pr_err("%s: MPP2 configuration failed\n", __func__);
- return -ENODEV;
- }
INIT_DELAYED_WORK(&pmic_id_det, pmic_id_detect);
+ ret = pm8xxx_gpio_config(PM8058_GPIO_PM_TO_SYS(PMIC_ID_GPIO),
+ &pmic_id_cfg);
+ if (ret) {
+ pr_err("%s:return val of pm8xxx_gpio_config: %d\n",
+ __func__, ret);
+ return ret;
+ }
ret = request_threaded_irq(PMICID_INT, NULL, pmic_id_on_irq,
(IRQF_TRIGGER_RISING|IRQF_TRIGGER_FALLING),
"msm_otg_id", NULL);
if (ret) {
- pm8901_mpp_config_digital_out(1,
- PM8901_MPP_DIG_LEVEL_L5, 0);
pr_err("%s:pmic_usb_id interrupt registration failed",
__func__);
return ret;
}
- /* Notify the initial Id status */
- pmic_id_detect(&pmic_id_det.work);
msm_otg_pdata.pmic_id_irq = PMICID_INT;
} else {
+ usb_phy_susp_dig_vol = 750000;
free_irq(PMICID_INT, 0);
+ ret = pm8xxx_gpio_config(PM8058_GPIO_PM_TO_SYS(PMIC_ID_GPIO),
+ &pmic_id_uncfg);
+ if (ret) {
+ pr_err("%s: return val of pm8xxx_gpio_config: %d\n",
+ __func__, ret);
+ return ret;
+ }
msm_otg_pdata.pmic_id_irq = 0;
cancel_delayed_work_sync(&pmic_id_det);
notify_vbus_state_func_ptr = NULL;
- ret = pm8901_mpp_config_digital_out(1,
- PM8901_MPP_DIG_LEVEL_L5, 0);
- if (ret) {
- pr_err("%s:MPP2 configuration failed\n", __func__);
- return -ENODEV;
- }
}
return 0;
}
@@ -1393,6 +1430,7 @@
.bam_disable = 1,
#ifdef CONFIG_USB_EHCI_MSM_72K
.pmic_id_notif_init = msm_hsusb_pmic_id_notif_init,
+ .phy_id_setup_init = msm_hsusb_phy_id_setup_init,
#endif
#ifdef CONFIG_USB_EHCI_MSM_72K
.vbus_power = msm_hsusb_vbus_power,
@@ -4451,13 +4489,6 @@
#endif
#ifdef CONFIG_SENSORS_MSM_ADC
-static struct resource resources_adc[] = {
- {
- .start = PM8058_ADC_IRQ(PM8058_IRQ_BASE),
- .end = PM8058_ADC_IRQ(PM8058_IRQ_BASE),
- .flags = IORESOURCE_IRQ,
- },
-};
static struct adc_access_fn xoadc_fn = {
pm8058_xoadc_select_chan_and_start_conv,
@@ -4806,37 +4837,33 @@
static void pmic8058_xoadc_mpp_config(void)
{
- int rc;
+ int rc, i;
+ struct pm8xxx_mpp_init_info xoadc_mpps[] = {
+ PM8XXX_MPP_INIT(XOADC_MPP_3, A_INPUT, PM8XXX_MPP_AIN_AMUX_CH5,
+ AOUT_CTRL_DISABLE),
+ PM8XXX_MPP_INIT(XOADC_MPP_5, A_INPUT, PM8XXX_MPP_AIN_AMUX_CH9,
+ AOUT_CTRL_DISABLE),
+ PM8XXX_MPP_INIT(XOADC_MPP_7, A_INPUT, PM8XXX_MPP_AIN_AMUX_CH6,
+ AOUT_CTRL_DISABLE),
+ PM8XXX_MPP_INIT(XOADC_MPP_8, A_INPUT, PM8XXX_MPP_AIN_AMUX_CH8,
+ AOUT_CTRL_DISABLE),
+ PM8XXX_MPP_INIT(XOADC_MPP_10, A_INPUT, PM8XXX_MPP_AIN_AMUX_CH7,
+ AOUT_CTRL_DISABLE),
+ };
rc = pm8901_mpp_config_digital_out(XOADC_MPP_4,
PM8901_MPP_DIG_LEVEL_S4, PM_MPP_DOUT_CTL_LOW);
if (rc)
pr_err("%s: Config mpp4 on pmic 8901 failed\n", __func__);
- rc = pm8058_mpp_config_analog_input(XOADC_MPP_3,
- PM_MPP_AIN_AMUX_CH5, PM_MPP_AOUT_CTL_DISABLE);
- if (rc)
- pr_err("%s: Config mpp3 on pmic 8058 failed\n", __func__);
-
- rc = pm8058_mpp_config_analog_input(XOADC_MPP_5,
- PM_MPP_AIN_AMUX_CH9, PM_MPP_AOUT_CTL_DISABLE);
- if (rc)
- pr_err("%s: Config mpp5 on pmic 8058 failed\n", __func__);
-
- rc = pm8058_mpp_config_analog_input(XOADC_MPP_7,
- PM_MPP_AIN_AMUX_CH6, PM_MPP_AOUT_CTL_DISABLE);
- if (rc)
- pr_err("%s: Config mpp7 on pmic 8058 failed\n", __func__);
-
- rc = pm8058_mpp_config_analog_input(XOADC_MPP_8,
- PM_MPP_AIN_AMUX_CH8, PM_MPP_AOUT_CTL_DISABLE);
- if (rc)
- pr_err("%s: Config mpp8 on pmic 8058 failed\n", __func__);
-
- rc = pm8058_mpp_config_analog_input(XOADC_MPP_10,
- PM_MPP_AIN_AMUX_CH7, PM_MPP_AOUT_CTL_DISABLE);
- if (rc)
- pr_err("%s: Config mpp10 on pmic 8058 failed\n", __func__);
+ for (i = 0; i < ARRAY_SIZE(xoadc_mpps); i++) {
+ rc = pm8xxx_mpp_config(xoadc_mpps[i].mpp,
+ &xoadc_mpps[i].config);
+ if (rc) {
+ pr_err("%s: Config MPP %d of PM8058 failed\n",
+ __func__, xoadc_mpps[i].mpp);
+ }
+ }
}
static struct regulator *vreg_ldo18_adc;
@@ -4901,7 +4928,7 @@
.conversiontime = 54,
};
-static struct xoadc_platform_data xoadc_pdata = {
+static struct xoadc_platform_data pm8058_xoadc_pdata = {
.xoadc_prop = &pm8058_xoadc_data,
.xoadc_mpp_config = pmic8058_xoadc_mpp_config,
.xoadc_vreg_set = pmic8058_xoadc_vreg_config,
@@ -5283,18 +5310,28 @@
#define EXT_CHG_VALID_MPP 10
#define EXT_CHG_VALID_MPP_2 11
+static struct pm8xxx_mpp_init_info isl_mpp[] = {
+ PM8XXX_MPP_INIT(EXT_CHG_VALID_MPP, D_INPUT,
+ PM8058_MPP_DIG_LEVEL_S3, DIN_TO_INT),
+ PM8XXX_MPP_INIT(EXT_CHG_VALID_MPP_2, D_BI_DIR,
+ PM8058_MPP_DIG_LEVEL_S3, BI_PULLUP_10KOHM),
+};
+
#ifdef CONFIG_ISL9519_CHARGER
static int isl_detection_setup(void)
{
- int ret = 0;
+ int ret = 0, i;
- ret = pm8058_mpp_config_digital_in(EXT_CHG_VALID_MPP,
- PM8058_MPP_DIG_LEVEL_S3,
- PM_MPP_DIN_TO_INT);
- ret |= pm8058_mpp_config_bi_dir(EXT_CHG_VALID_MPP_2,
- PM8058_MPP_DIG_LEVEL_S3,
- PM_MPP_BI_PULLUP_10KOHM
- );
+ for (i = 0; i < ARRAY_SIZE(isl_mpp); i++) {
+ ret = pm8xxx_mpp_config(isl_mpp[i].mpp,
+ &isl_mpp[i].config);
+ if (ret) {
+ pr_err("%s: Config MPP %d of PM8058 failed\n",
+ __func__, isl_mpp[i].mpp);
+ return ret;
+ }
+ }
+
return ret;
}
@@ -5311,7 +5348,7 @@
static struct i2c_board_info isl_charger_i2c_info[] __initdata = {
{
I2C_BOARD_INFO("isl9519q", 0x9),
- .irq = PM8058_CBLPWR_IRQ(PM8058_IRQ_BASE),
+ .irq = PM8058_IRQ_BASE + PM8058_CBLPWR_IRQ,
.platform_data = &isl_data,
},
};
@@ -5320,14 +5357,18 @@
#if defined(CONFIG_SMB137B_CHARGER) || defined(CONFIG_SMB137B_CHARGER_MODULE)
static int smb137b_detection_setup(void)
{
- int ret = 0;
+ int ret = 0, i;
- ret = pm8058_mpp_config_digital_in(EXT_CHG_VALID_MPP,
- PM8058_MPP_DIG_LEVEL_S3,
- PM_MPP_DIN_TO_INT);
- ret |= pm8058_mpp_config_bi_dir(EXT_CHG_VALID_MPP_2,
- PM8058_MPP_DIG_LEVEL_S3,
- PM_MPP_BI_PULLUP_10KOHM);
+ for (i = 0; i < ARRAY_SIZE(isl_mpp); i++) {
+ ret = pm8xxx_mpp_config(isl_mpp[i].mpp,
+ &isl_mpp[i].config);
+ if (ret) {
+ pr_err("%s: Config MPP %d of PM8058 failed\n",
+ __func__, isl_mpp[i].mpp);
+ return ret;
+ }
+ }
+
return ret;
}
@@ -5340,7 +5381,7 @@
static struct i2c_board_info smb137b_charger_i2c_info[] __initdata = {
{
I2C_BOARD_INFO("smb137b", 0x08),
- .irq = PM8058_CBLPWR_IRQ(PM8058_IRQ_BASE),
+ .irq = PM8058_IRQ_BASE + PM8058_CBLPWR_IRQ,
.platform_data = &smb137b_data,
},
};
@@ -5356,12 +5397,12 @@
int rc;
struct pm8058_gpio_cfg {
int gpio;
- struct pm8058_gpio cfg;
+ struct pm_gpio cfg;
};
struct pm8058_gpio_cfg gpio_cfgs[] = {
{ /* FFA ethernet */
- 6,
+ PM8058_GPIO_PM_TO_SYS(6),
{
.direction = PM_GPIO_DIR_IN,
.pull = PM_GPIO_PULL_DN,
@@ -5372,7 +5413,7 @@
},
#ifdef CONFIG_MMC_MSM_CARD_HW_DETECTION
{
- PMIC_GPIO_SDC3_DET - 1,
+ PM8058_GPIO_PM_TO_SYS(PMIC_GPIO_SDC3_DET - 1),
{
.direction = PM_GPIO_DIR_IN,
.pull = PM_GPIO_PULL_UP_30,
@@ -5383,37 +5424,37 @@
},
#endif
{ /* core&surf gpio expander */
- UI_INT1_N,
+ PM8058_GPIO_PM_TO_SYS(UI_INT1_N),
{
.direction = PM_GPIO_DIR_IN,
.pull = PM_GPIO_PULL_NO,
- .vin_sel = PM_GPIO_VIN_S3,
+ .vin_sel = PM8058_GPIO_VIN_S3,
.function = PM_GPIO_FUNC_NORMAL,
.inv_int_pol = 0,
},
},
{ /* docking gpio expander */
- UI_INT2_N,
+ PM8058_GPIO_PM_TO_SYS(UI_INT2_N),
{
.direction = PM_GPIO_DIR_IN,
.pull = PM_GPIO_PULL_NO,
- .vin_sel = PM_GPIO_VIN_S3,
+ .vin_sel = PM8058_GPIO_VIN_S3,
.function = PM_GPIO_FUNC_NORMAL,
.inv_int_pol = 0,
},
},
{ /* FHA/keypad gpio expanders */
- UI_INT3_N,
+ PM8058_GPIO_PM_TO_SYS(UI_INT3_N),
{
.direction = PM_GPIO_DIR_IN,
.pull = PM_GPIO_PULL_NO,
- .vin_sel = PM_GPIO_VIN_S3,
+ .vin_sel = PM8058_GPIO_VIN_S3,
.function = PM_GPIO_FUNC_NORMAL,
.inv_int_pol = 0,
},
},
{ /* Timpani Reset */
- 20,
+ PM8058_GPIO_PM_TO_SYS(20),
{
.direction = PM_GPIO_DIR_OUT,
.output_value = 1,
@@ -5426,10 +5467,10 @@
}
},
{ /* PMIC ID interrupt */
- 36,
+ PM8058_GPIO_PM_TO_SYS(36),
{
.direction = PM_GPIO_DIR_IN,
- .pull = PM_GPIO_PULL_UP_1P5,
+ .pull = PM_GPIO_PULL_NO,
.function = PM_GPIO_FUNC_NORMAL,
.vin_sel = 2,
.inv_int_pol = 0,
@@ -5439,7 +5480,7 @@
#if defined(CONFIG_TOUCHDISC_VTD518_SHINETSU) || \
defined(CONFIG_TOUCHDISC_VTD518_SHINETSU_MODULE)
- struct pm8058_gpio touchdisc_intr_gpio_cfg = {
+ struct pm_gpio touchdisc_intr_gpio_cfg = {
.direction = PM_GPIO_DIR_IN,
.pull = PM_GPIO_PULL_UP_1P5,
.vin_sel = 2,
@@ -5449,7 +5490,7 @@
#if defined(CONFIG_HAPTIC_ISA1200) || \
defined(CONFIG_HAPTIC_ISA1200_MODULE)
- struct pm8058_gpio en_hap_gpio_cfg = {
+ struct pm_gpio en_hap_gpio_cfg = {
.direction = PM_GPIO_DIR_OUT,
.pull = PM_GPIO_PULL_NO,
.out_strength = PM_GPIO_STRENGTH_HIGH,
@@ -5463,7 +5504,7 @@
#if defined(CONFIG_PMIC8058_OTHC) || defined(CONFIG_PMIC8058_OTHC_MODULE)
struct pm8058_gpio_cfg line_in_gpio_cfg = {
- 18,
+ PM8058_GPIO_PM_TO_SYS(18),
{
.direction = PM_GPIO_DIR_IN,
.pull = PM_GPIO_PULL_UP_1P5,
@@ -5477,7 +5518,7 @@
#if defined(CONFIG_QS_S5K4E1)
{
struct pm8058_gpio_cfg qs_hc37_cam_pd_gpio_cfg = {
- 26,
+ PM8058_GPIO_PM_TO_SYS(26),
{
.direction = PM_GPIO_DIR_OUT,
.output_value = 0,
@@ -5492,32 +5533,33 @@
#endif
#ifdef CONFIG_FB_MSM_LCDC_NT35582_WVGA
struct pm8058_gpio_cfg pmic_lcdc_nt35582_gpio_cfg = {
- GPIO_NT35582_BL_EN_HW_PIN - 1,
+ PM8058_GPIO_PM_TO_SYS(GPIO_NT35582_BL_EN_HW_PIN - 1),
{
.direction = PM_GPIO_DIR_OUT,
.output_buffer = PM_GPIO_OUT_BUF_CMOS,
.output_value = 1,
.pull = PM_GPIO_PULL_UP_30,
/* 2.9V PM_GPIO_VIN_L2, which gives 2.6V */
- .vin_sel = PM_GPIO_VIN_L5,
+ .vin_sel = PM8058_GPIO_VIN_L5,
.out_strength = PM_GPIO_STRENGTH_HIGH,
.function = PM_GPIO_FUNC_NORMAL,
.inv_int_pol = 0,
}
};
#endif
-
#if defined(CONFIG_HAPTIC_ISA1200) || \
defined(CONFIG_HAPTIC_ISA1200_MODULE)
if (machine_is_msm8x60_fluid()) {
- rc = pm8058_gpio_config(PMIC_GPIO_HAP_ENABLE,
- &en_hap_gpio_cfg);
+ rc = pm8xxx_gpio_config(
+ PM8058_GPIO_PM_TO_SYS(PMIC_GPIO_HAP_ENABLE),
+ &en_hap_gpio_cfg);
if (rc < 0) {
pr_err("%s: pmic haptics gpio config failed\n",
__func__);
}
- rc = pm8058_gpio_config(PMIC_GPIO_HAP_LDO_ENABLE,
- &en_hap_gpio_cfg);
+ rc = pm8xxx_gpio_config(
+ PM8058_GPIO_PM_TO_SYS(PMIC_GPIO_HAP_LDO_ENABLE),
+ &en_hap_gpio_cfg);
if (rc < 0) {
pr_err("%s: pmic haptics ldo gpio config failed\n",
__func__);
@@ -5530,8 +5572,9 @@
defined(CONFIG_TOUCHDISC_VTD518_SHINETSU_MODULE)
if (machine_is_msm8x60_ffa() || machine_is_msm8x60_surf() ||
machine_is_msm8x60_fusion() || machine_is_msm8x60_fusn_ffa()) {
- rc = pm8058_gpio_config(PMIC_GPIO_TOUCH_DISC_INTR,
- &touchdisc_intr_gpio_cfg);
+ rc = pm8xxx_gpio_config(
+ PM8058_GPIO_PM_TO_SYS(PMIC_GPIO_TOUCH_DISC_INTR),
+ &touchdisc_intr_gpio_cfg);
if (rc < 0) {
pr_err("%s: Touchdisc interrupt gpio config failed\n",
__func__);
@@ -5544,7 +5587,7 @@
if (machine_is_msm8x60_ffa() || machine_is_msm8x60_surf() ||
machine_is_msm8x60_fusion() || machine_is_msm8x60_dragon() ||
machine_is_msm8x60_fusn_ffa()) {
- rc = pm8058_gpio_config(line_in_gpio_cfg.gpio,
+ rc = pm8xxx_gpio_config(line_in_gpio_cfg.gpio,
&line_in_gpio_cfg.cfg);
if (rc < 0) {
pr_err("%s pmic line_in gpio config failed\n",
@@ -5556,7 +5599,7 @@
#ifdef CONFIG_FB_MSM_LCDC_NT35582_WVGA
if (machine_is_msm8x60_dragon()) {
- rc = pm8058_gpio_config(pmic_lcdc_nt35582_gpio_cfg.gpio,
+ rc = pm8xxx_gpio_config(pmic_lcdc_nt35582_gpio_cfg.gpio,
&pmic_lcdc_nt35582_gpio_cfg.cfg);
if (rc < 0) {
pr_err("%s pmic gpio config failed\n", __func__);
@@ -5568,7 +5611,7 @@
#if defined(CONFIG_QS_S5K4E1)
/* qs_cam_hc37_cam_pd only for 8660 fluid qs camera*/
if (machine_is_msm8x60_fluid()) {
- rc = pm8058_gpio_config(qs_hc37_cam_pd_gpio_cfg.gpio,
+ rc = pm8xxx_gpio_config(qs_hc37_cam_pd_gpio_cfg.gpio,
&qs_hc37_cam_pd_gpio_cfg.cfg);
if (rc < 0) {
pr_err("%s pmic qs_hc37_cam_pd gpio config failed\n",
@@ -5580,7 +5623,7 @@
#endif
for (i = 0; i < ARRAY_SIZE(gpio_cfgs); ++i) {
- rc = pm8058_gpio_config(gpio_cfgs[i].gpio,
+ rc = pm8xxx_gpio_config(gpio_cfgs[i].gpio,
&gpio_cfgs[i].cfg);
if (rc < 0) {
pr_err("%s pmic gpio config failed\n",
@@ -5648,32 +5691,19 @@
KEY(4, 3, KEY_KBDILLUMTOGGLE),
};
-static struct resource resources_keypad[] = {
- {
- .start = PM8058_KEYPAD_IRQ(PM8058_IRQ_BASE),
- .end = PM8058_KEYPAD_IRQ(PM8058_IRQ_BASE),
- .flags = IORESOURCE_IRQ,
- },
- {
- .start = PM8058_KEYSTUCK_IRQ(PM8058_IRQ_BASE),
- .end = PM8058_KEYSTUCK_IRQ(PM8058_IRQ_BASE),
- .flags = IORESOURCE_IRQ,
- },
-};
-
static struct matrix_keymap_data ffa_keymap_data = {
.keymap_size = ARRAY_SIZE(ffa_keymap),
.keymap = ffa_keymap,
};
-static struct pmic8058_keypad_data ffa_keypad_data = {
+static struct pm8xxx_keypad_platform_data ffa_keypad_data = {
.input_name = "ffa-keypad",
.input_phys_device = "ffa-keypad/input0",
.num_rows = 6,
.num_cols = 5,
- .rows_gpio_start = 8,
- .cols_gpio_start = 0,
- .debounce_ms = {8, 10},
+ .rows_gpio_start = PM8058_GPIO_PM_TO_SYS(8),
+ .cols_gpio_start = PM8058_GPIO_PM_TO_SYS(0),
+ .debounce_ms = 15,
.scan_delay_ms = 32,
.row_hold_ns = 91500,
.wakeup = 1,
@@ -5685,19 +5715,20 @@
.keymap = dragon_keymap,
};
-static struct pmic8058_keypad_data dragon_keypad_data = {
+static struct pm8xxx_keypad_platform_data dragon_keypad_data = {
.input_name = "dragon-keypad",
.input_phys_device = "dragon-keypad/input0",
.num_rows = 6,
.num_cols = 5,
- .rows_gpio_start = 8,
- .cols_gpio_start = 0,
- .debounce_ms = {8, 10},
+ .rows_gpio_start = PM8058_GPIO_PM_TO_SYS(8),
+ .cols_gpio_start = PM8058_GPIO_PM_TO_SYS(0),
+ .debounce_ms = 15,
.scan_delay_ms = 32,
.row_hold_ns = 91500,
.wakeup = 1,
.keymap_data = &dragon_keymap_data,
};
+
static const unsigned int fluid_keymap[] = {
KEY(0, 0, KEY_FN_F1), /* LS - PUSH1 */
KEY(0, 1, KEY_UP), /* NAV - UP */
@@ -5729,50 +5760,37 @@
.keymap = fluid_keymap,
};
-static struct pmic8058_keypad_data fluid_keypad_data = {
+static struct pm8xxx_keypad_platform_data fluid_keypad_data = {
.input_name = "fluid-keypad",
.input_phys_device = "fluid-keypad/input0",
.num_rows = 6,
.num_cols = 5,
- .rows_gpio_start = 8,
- .cols_gpio_start = 0,
- .debounce_ms = {8, 10},
+ .rows_gpio_start = PM8058_GPIO_PM_TO_SYS(8),
+ .cols_gpio_start = PM8058_GPIO_PM_TO_SYS(0),
+ .debounce_ms = 15,
.scan_delay_ms = 32,
.row_hold_ns = 91500,
.wakeup = 1,
.keymap_data = &fluid_keymap_data,
};
-static struct resource resources_pwrkey[] = {
- {
- .start = PM8058_PWRKEY_REL_IRQ(PM8058_IRQ_BASE),
- .end = PM8058_PWRKEY_REL_IRQ(PM8058_IRQ_BASE),
- .flags = IORESOURCE_IRQ,
- },
- {
- .start = PM8058_PWRKEY_PRESS_IRQ(PM8058_IRQ_BASE),
- .end = PM8058_PWRKEY_PRESS_IRQ(PM8058_IRQ_BASE),
- .flags = IORESOURCE_IRQ,
- },
-};
-
-static struct pmic8058_pwrkey_pdata pwrkey_pdata = {
- .pull_up = 1,
- .kpd_trigger_delay_us = 970,
- .wakeup = 1,
- .pwrkey_time_ms = 500,
-};
-
-static struct pmic8058_vibrator_pdata pmic_vib_pdata = {
+static struct pm8xxx_vibrator_platform_data pm8058_vib_pdata = {
.initial_vibrate_ms = 500,
.level_mV = 3000,
.max_timeout_ms = 15000,
};
-#if defined(CONFIG_PMIC8058_OTHC) || defined(CONFIG_PMIC8058_OTHC_MODULE)
-#define PM8058_OTHC_CNTR_BASE0 0xA0
-#define PM8058_OTHC_CNTR_BASE1 0x134
-#define PM8058_OTHC_CNTR_BASE2 0x137
+static struct pm8xxx_rtc_platform_data pm8058_rtc_pdata = {
+ .rtc_write_enable = false,
+ .rtc_alarm_powerup = false,
+};
+
+static struct pm8xxx_pwrkey_platform_data pm8058_pwrkey_pdata = {
+ .pull_up = 1,
+ .kpd_trigger_delay_us = 970,
+ .wakeup = 1,
+};
+
#define PM8058_LINE_IN_DET_GPIO PM8058_GPIO_PM_TO_SYS(18)
static struct othc_accessory_info othc_accessories[] = {
@@ -5919,42 +5937,6 @@
.micbias_regulator = &othc_reg,
};
-static struct resource resources_othc_0[] = {
- {
- .name = "othc_base",
- .start = PM8058_OTHC_CNTR_BASE0,
- .end = PM8058_OTHC_CNTR_BASE0,
- .flags = IORESOURCE_IO,
- },
-};
-
-static struct resource resources_othc_1[] = {
- {
- .start = PM8058_SW_1_IRQ(PM8058_IRQ_BASE),
- .end = PM8058_SW_1_IRQ(PM8058_IRQ_BASE),
- .flags = IORESOURCE_IRQ,
- },
- {
- .start = PM8058_IR_1_IRQ(PM8058_IRQ_BASE),
- .end = PM8058_IR_1_IRQ(PM8058_IRQ_BASE),
- .flags = IORESOURCE_IRQ,
- },
- {
- .name = "othc_base",
- .start = PM8058_OTHC_CNTR_BASE1,
- .end = PM8058_OTHC_CNTR_BASE1,
- .flags = IORESOURCE_IO,
- },
-};
-
-static struct resource resources_othc_2[] = {
- {
- .name = "othc_base",
- .start = PM8058_OTHC_CNTR_BASE2,
- .end = PM8058_OTHC_CNTR_BASE2,
- .flags = IORESOURCE_IO,
- },
-};
static void __init msm8x60_init_pm8058_othc(void)
{
@@ -5992,143 +5974,16 @@
}
}
}
-#endif
-static struct resource resources_pm8058_charger[] = {
- { .name = "CHGVAL",
- .start = PM8058_CHGVAL_IRQ(PM8058_IRQ_BASE),
- .end = PM8058_CHGVAL_IRQ(PM8058_IRQ_BASE),
- .flags = IORESOURCE_IRQ,
- },
- { .name = "CHGINVAL",
- .start = PM8058_CHGINVAL_IRQ(PM8058_IRQ_BASE),
- .end = PM8058_CHGINVAL_IRQ(PM8058_IRQ_BASE),
- .flags = IORESOURCE_IRQ,
- },
- {
- .name = "CHGILIM",
- .start = PM8058_CHGILIM_IRQ(PM8058_IRQ_BASE),
- .end = PM8058_CHGILIM_IRQ(PM8058_IRQ_BASE),
- .flags = IORESOURCE_IRQ,
- },
- {
- .name = "VCP",
- .start = PM8058_VCP_IRQ(PM8058_IRQ_BASE),
- .end = PM8058_VCP_IRQ(PM8058_IRQ_BASE),
- .flags = IORESOURCE_IRQ,
- },
- {
- .name = "ATC_DONE",
- .start = PM8058_ATC_DONE_IRQ(PM8058_IRQ_BASE),
- .end = PM8058_ATC_DONE_IRQ(PM8058_IRQ_BASE),
- .flags = IORESOURCE_IRQ,
- },
- {
- .name = "ATCFAIL",
- .start = PM8058_ATCFAIL_IRQ(PM8058_IRQ_BASE),
- .end = PM8058_ATCFAIL_IRQ(PM8058_IRQ_BASE),
- .flags = IORESOURCE_IRQ,
- },
- {
- .name = "AUTO_CHGDONE",
- .start = PM8058_AUTO_CHGDONE_IRQ(PM8058_IRQ_BASE),
- .end = PM8058_AUTO_CHGDONE_IRQ(PM8058_IRQ_BASE),
- .flags = IORESOURCE_IRQ,
- },
- {
- .name = "AUTO_CHGFAIL",
- .start = PM8058_AUTO_CHGFAIL_IRQ(PM8058_IRQ_BASE),
- .end = PM8058_AUTO_CHGFAIL_IRQ(PM8058_IRQ_BASE),
- .flags = IORESOURCE_IRQ,
- },
- {
- .name = "CHGSTATE",
- .start = PM8058_CHGSTATE_IRQ(PM8058_IRQ_BASE),
- .end = PM8058_CHGSTATE_IRQ(PM8058_IRQ_BASE),
- .flags = IORESOURCE_IRQ,
- },
- {
- .name = "FASTCHG",
- .start = PM8058_FASTCHG_IRQ(PM8058_IRQ_BASE),
- .end = PM8058_FASTCHG_IRQ(PM8058_IRQ_BASE),
- .flags = IORESOURCE_IRQ,
- },
- {
- .name = "CHG_END",
- .start = PM8058_CHG_END_IRQ(PM8058_IRQ_BASE),
- .end = PM8058_CHG_END_IRQ(PM8058_IRQ_BASE),
- .flags = IORESOURCE_IRQ,
- },
- {
- .name = "BATTTEMP",
- .start = PM8058_BATTTEMP_IRQ(PM8058_IRQ_BASE),
- .end = PM8058_BATTTEMP_IRQ(PM8058_IRQ_BASE),
- .flags = IORESOURCE_IRQ,
- },
- {
- .name = "CHGHOT",
- .start = PM8058_CHGHOT_IRQ(PM8058_IRQ_BASE),
- .end = PM8058_CHGHOT_IRQ(PM8058_IRQ_BASE),
- .flags = IORESOURCE_IRQ,
- },
- {
- .name = "CHGTLIMIT",
- .start = PM8058_CHGTLIMIT_IRQ(PM8058_IRQ_BASE),
- .end = PM8058_CHGTLIMIT_IRQ(PM8058_IRQ_BASE),
- .flags = IORESOURCE_IRQ,
- },
- {
- .name = "CHG_GONE",
- .start = PM8058_CHG_GONE_IRQ(PM8058_IRQ_BASE),
- .end = PM8058_CHG_GONE_IRQ(PM8058_IRQ_BASE),
- .flags = IORESOURCE_IRQ,
- },
- {
- .name = "VCPMAJOR",
- .start = PM8058_VCPMAJOR_IRQ(PM8058_IRQ_BASE),
- .end = PM8058_VCPMAJOR_IRQ(PM8058_IRQ_BASE),
- .flags = IORESOURCE_IRQ,
- },
- {
- .name = "VBATDET",
- .start = PM8058_VBATDET_IRQ(PM8058_IRQ_BASE),
- .end = PM8058_VBATDET_IRQ(PM8058_IRQ_BASE),
- .flags = IORESOURCE_IRQ,
- },
- {
- .name = "BATFET",
- .start = PM8058_BATFET_IRQ(PM8058_IRQ_BASE),
- .end = PM8058_BATFET_IRQ(PM8058_IRQ_BASE),
- .flags = IORESOURCE_IRQ,
- },
- {
- .name = "BATT_REPLACE",
- .start = PM8058_BATT_REPLACE_IRQ(PM8058_IRQ_BASE),
- .end = PM8058_BATT_REPLACE_IRQ(PM8058_IRQ_BASE),
- .flags = IORESOURCE_IRQ,
- },
- {
- .name = "BATTCONNECT",
- .start = PM8058_BATTCONNECT_IRQ(PM8058_IRQ_BASE),
- .end = PM8058_BATTCONNECT_IRQ(PM8058_IRQ_BASE),
- .flags = IORESOURCE_IRQ,
- },
- {
- .name = "VBATDET_LOW",
- .start = PM8058_VBATDET_LOW_IRQ(PM8058_IRQ_BASE),
- .end = PM8058_VBATDET_LOW_IRQ(PM8058_IRQ_BASE),
- .flags = IORESOURCE_IRQ,
- },
-};
static int pm8058_pwm_config(struct pwm_device *pwm, int ch, int on)
{
- struct pm8058_gpio pwm_gpio_config = {
+ struct pm_gpio pwm_gpio_config = {
.direction = PM_GPIO_DIR_OUT,
.output_buffer = PM_GPIO_OUT_BUF_CMOS,
.output_value = 0,
.pull = PM_GPIO_PULL_NO,
- .vin_sel = PM_GPIO_VIN_VPH,
+ .vin_sel = PM8058_GPIO_VIN_VPH,
.out_strength = PM_GPIO_STRENGTH_HIGH,
.function = PM_GPIO_FUNC_2,
};
@@ -6143,9 +5998,10 @@
case 2:
if (on) {
id = 24 + ch;
- rc = pm8058_gpio_config(id - 1, &pwm_gpio_config);
+ rc = pm8xxx_gpio_config(PM8058_GPIO_PM_TO_SYS(id - 1),
+ &pwm_gpio_config);
if (rc)
- pr_err("%s: pm8058_gpio_config(%d): rc=%d\n",
+ pr_err("%s: pm8xxx_gpio_config(%d): rc=%d\n",
__func__, id, rc);
}
break;
@@ -6186,34 +6042,6 @@
#define PM8058_GPIO_INT 88
-static struct pm8058_gpio_platform_data pm8058_gpio_data = {
- .gpio_base = PM8058_GPIO_PM_TO_SYS(0),
- .irq_base = PM8058_GPIO_IRQ(PM8058_IRQ_BASE, 0),
- .init = pm8058_gpios_init,
-};
-
-static struct pm8058_gpio_platform_data pm8058_mpp_data = {
- .gpio_base = PM8058_GPIO_PM_TO_SYS(PM8058_GPIOS),
- .irq_base = PM8058_MPP_IRQ(PM8058_IRQ_BASE, 0),
-};
-
-static struct resource resources_rtc[] = {
- {
- .start = PM8058_RTC_IRQ(PM8058_IRQ_BASE),
- .end = PM8058_RTC_IRQ(PM8058_IRQ_BASE),
- .flags = IORESOURCE_IRQ,
- },
- {
- .start = PM8058_RTC_ALARM_IRQ(PM8058_IRQ_BASE),
- .end = PM8058_RTC_ALARM_IRQ(PM8058_IRQ_BASE),
- .flags = IORESOURCE_IRQ,
- },
-};
-
-static struct pm8058_rtc_platform_data pm8058_rtc_pdata = {
- .rtc_alarm_powerup = false,
-};
-
static struct pmic8058_led pmic8058_flash_leds[] = {
[0] = {
.name = "camera:flash0",
@@ -6291,156 +6119,48 @@
.leds = pmic8058_fluid_flash_leds,
};
-static struct resource resources_temp_alarm[] = {
- {
- .start = PM8058_TEMP_ALARM_IRQ(PM8058_IRQ_BASE),
- .end = PM8058_TEMP_ALARM_IRQ(PM8058_IRQ_BASE),
- .flags = IORESOURCE_IRQ,
- },
-};
-
-static struct resource resources_pm8058_misc[] = {
- {
- .start = PM8058_OSCHALT_IRQ(PM8058_IRQ_BASE),
- .end = PM8058_OSCHALT_IRQ(PM8058_IRQ_BASE),
- .flags = IORESOURCE_IRQ,
- },
-};
-
-static struct resource resources_pm8058_batt_alarm[] = {
- {
- .start = PM8058_BATT_ALARM_IRQ(PM8058_IRQ_BASE),
- .end = PM8058_BATT_ALARM_IRQ(PM8058_IRQ_BASE),
- .flags = IORESOURCE_IRQ,
- },
-};
-
-#define PM8058_SUBDEV_KPD 0
-#define PM8058_SUBDEV_LED 1
-#define PM8058_SUBDEV_VIB 2
-
-static struct mfd_cell pm8058_subdevs[] = {
- {
- .name = "pm8058-keypad",
- .id = -1,
- .num_resources = ARRAY_SIZE(resources_keypad),
- .resources = resources_keypad,
- },
- { .name = "pm8058-led",
- .id = -1,
- },
- {
- .name = "pm8058-vib",
- .id = -1,
- },
- { .name = "pm8058-gpio",
- .id = -1,
- .platform_data = &pm8058_gpio_data,
- .pdata_size = sizeof(pm8058_gpio_data),
- },
- { .name = "pm8058-mpp",
- .id = -1,
- .platform_data = &pm8058_mpp_data,
- .pdata_size = sizeof(pm8058_mpp_data),
- },
- { .name = "pm8058-pwrkey",
- .id = -1,
- .resources = resources_pwrkey,
- .num_resources = ARRAY_SIZE(resources_pwrkey),
- .platform_data = &pwrkey_pdata,
- .pdata_size = sizeof(pwrkey_pdata),
- },
- {
- .name = "pm8058-pwm",
- .id = -1,
- .platform_data = &pm8058_pwm_data,
- .pdata_size = sizeof(pm8058_pwm_data),
- },
-#ifdef CONFIG_SENSORS_MSM_ADC
- {
- .name = "pm8058-xoadc",
- .id = -1,
- .num_resources = ARRAY_SIZE(resources_adc),
- .resources = resources_adc,
- .platform_data = &xoadc_pdata,
- .pdata_size = sizeof(xoadc_pdata),
- },
-#endif
-#if defined(CONFIG_PMIC8058_OTHC) || defined(CONFIG_PMIC8058_OTHC_MODULE)
- {
- .name = "pm8058-othc",
- .id = 0,
- .platform_data = &othc_config_pdata_0,
- .pdata_size = sizeof(othc_config_pdata_0),
- .num_resources = ARRAY_SIZE(resources_othc_0),
- .resources = resources_othc_0,
- },
- {
- /* OTHC1 module has headset/switch dection */
- .name = "pm8058-othc",
- .id = 1,
- .num_resources = ARRAY_SIZE(resources_othc_1),
- .resources = resources_othc_1,
- .platform_data = &othc_config_pdata_1,
- .pdata_size = sizeof(othc_config_pdata_1),
- },
- {
- .name = "pm8058-othc",
- .id = 2,
- .platform_data = &othc_config_pdata_2,
- .pdata_size = sizeof(othc_config_pdata_2),
- .num_resources = ARRAY_SIZE(resources_othc_2),
- .resources = resources_othc_2,
- },
-#endif
- {
- .name = "pm8058-rtc",
- .id = -1,
- .num_resources = ARRAY_SIZE(resources_rtc),
- .resources = resources_rtc,
- .platform_data = &pm8058_rtc_pdata,
- },
- {
- .name = "pm8058-tm",
- .id = -1,
- .num_resources = ARRAY_SIZE(resources_temp_alarm),
- .resources = resources_temp_alarm,
- },
- { .name = "pm8058-upl",
- .id = -1,
- },
- {
- .name = "pm8058-misc",
- .id = -1,
- .num_resources = ARRAY_SIZE(resources_pm8058_misc),
- .resources = resources_pm8058_misc,
- },
- { .name = "pm8058-batt-alarm",
- .id = -1,
- .num_resources = ARRAY_SIZE(resources_pm8058_batt_alarm),
- .resources = resources_pm8058_batt_alarm,
- },
-};
-
static struct pmic8058_charger_data pmic8058_charger_dragon = {
+ .charger_data_valid = true,
.max_source_current = 1800,
.charger_type = CHG_TYPE_AC,
};
-static struct mfd_cell pm8058_charger_sub_dev = {
- .name = "pm8058-charger",
- .id = -1,
- .num_resources = ARRAY_SIZE(resources_pm8058_charger),
- .resources = resources_pm8058_charger,
+static struct pmic8058_charger_data pmic8058_charger_ffa_surf = {
+ .charger_data_valid = false,
+};
+
+static struct pm8xxx_misc_platform_data pm8058_misc_pdata = {
+ .priority = 0,
+};
+
+static struct pm8xxx_irq_platform_data pm8058_irq_pdata = {
+ .irq_base = PM8058_IRQ_BASE,
+ .devirq = MSM_GPIO_TO_INT(PM8058_GPIO_INT),
+ .irq_trigger_flag = IRQF_TRIGGER_LOW,
+};
+
+static struct pm8xxx_gpio_platform_data pm8058_gpio_pdata = {
+ .gpio_base = PM8058_GPIO_PM_TO_SYS(0),
+};
+
+static struct pm8xxx_mpp_platform_data pm8058_mpp_pdata = {
+ .mpp_base = PM8058_MPP_PM_TO_SYS(0),
};
static struct pm8058_platform_data pm8058_platform_data = {
- .irq_base = PM8058_IRQ_BASE,
- .irq = MSM_GPIO_TO_INT(PM8058_GPIO_INT),
-
- .num_subdevs = ARRAY_SIZE(pm8058_subdevs),
- .sub_devices = pm8058_subdevs,
- .irq_trigger_flags = IRQF_TRIGGER_LOW,
+ .irq_pdata = &pm8058_irq_pdata,
+ .gpio_pdata = &pm8058_gpio_pdata,
+ .mpp_pdata = &pm8058_mpp_pdata,
+ .rtc_pdata = &pm8058_rtc_pdata,
+ .pwrkey_pdata = &pm8058_pwrkey_pdata,
+ .othc0_pdata = &othc_config_pdata_0,
+ .othc1_pdata = &othc_config_pdata_1,
+ .othc2_pdata = &othc_config_pdata_2,
+ .pwm_pdata = &pm8058_pwm_data,
+ .misc_pdata = &pm8058_misc_pdata,
+#ifdef CONFIG_SENSORS_MSM_ADC
+ .xoadc_pdata = &pm8058_xoadc_pdata,
+#endif
};
#ifdef CONFIG_MSM_SSBI
@@ -7077,10 +6797,10 @@
static int fm_radio_setup(struct marimba_fm_platform_data *pdata)
{
int rc = 0;
- struct pm8058_gpio cfg = {
+ struct pm_gpio cfg = {
.direction = PM_GPIO_DIR_IN,
.pull = PM_GPIO_PULL_NO,
- .vin_sel = PM_GPIO_VIN_S3,
+ .vin_sel = PM8058_GPIO_VIN_S3,
.function = PM_GPIO_FUNC_NORMAL,
.inv_int_pol = 0,
};
@@ -7128,9 +6848,9 @@
}
/*GPIO 18 on PMIC is FM_IRQ*/
- rc = pm8058_gpio_config(FM_GPIO, &cfg);
+ rc = pm8xxx_gpio_config(PM8058_GPIO_PM_TO_SYS(FM_GPIO), &cfg);
if (rc) {
- printk(KERN_ERR "%s: return val of pm8058_gpio_config: %d\n",
+ printk(KERN_ERR "%s: return val of pm8xxx_gpio_config: %d\n",
__func__, rc);
goto fm_fail_clock;
}
@@ -10195,7 +9915,7 @@
{
uint32_t soc_platform_version;
- pmic_reset_irq = PM8058_RESOUT_IRQ(PM8058_IRQ_BASE);
+ pmic_reset_irq = PM8058_IRQ_BASE + PM8058_RESOUT_IRQ;
/*
* Initialize RPM first as other drivers and devices may need
@@ -10291,28 +10011,12 @@
msm8x60_init_pm8058_othc();
#endif
- if (machine_is_msm8x60_fluid()) {
- pm8058_platform_data.sub_devices[PM8058_SUBDEV_KPD].
- platform_data = &fluid_keypad_data;
- pm8058_platform_data.sub_devices[PM8058_SUBDEV_KPD].pdata_size
- = sizeof(fluid_keypad_data);
- } else if (machine_is_msm8x60_dragon()) {
- pm8058_platform_data.sub_devices[PM8058_SUBDEV_KPD].
- platform_data = &dragon_keypad_data;
- pm8058_platform_data.sub_devices[PM8058_SUBDEV_KPD].pdata_size
- = sizeof(dragon_keypad_data);
- } else {
- pm8058_platform_data.sub_devices[PM8058_SUBDEV_KPD].
- platform_data = &ffa_keypad_data;
- pm8058_platform_data.sub_devices[PM8058_SUBDEV_KPD].pdata_size
- = sizeof(ffa_keypad_data);
-
- }
-
- /* Disable END_CALL simulation function of powerkey on fluid */
- if (machine_is_msm8x60_fluid()) {
- pwrkey_pdata.pwrkey_time_ms = 0;
- }
+ if (machine_is_msm8x60_fluid())
+ pm8058_platform_data.keypad_pdata = &fluid_keypad_data;
+ else if (machine_is_msm8x60_dragon())
+ pm8058_platform_data.keypad_pdata = &dragon_keypad_data;
+ else
+ pm8058_platform_data.keypad_pdata = &ffa_keypad_data;
/* Specify reset pin for OV9726 */
if (machine_is_msm8x60_dragon()) {
@@ -10320,6 +10024,31 @@
ov9726_sensor_8660_info.mount_angle = 270;
}
+#ifdef CONFIG_BATTERY_MSM8X60
+ if (machine_is_msm8x60_surf() || machine_is_msm8x60_ffa() ||
+ machine_is_msm8x60_fusion() || machine_is_msm8x60_dragon() ||
+ machine_is_msm8x60_fusn_ffa() || machine_is_msm8x60_fluid())
+ platform_device_register(&msm_charger_device);
+#endif
+
+ if (machine_is_msm8x60_dragon())
+ pm8058_platform_data.charger_pdata = &pmic8058_charger_dragon;
+ if (!machine_is_msm8x60_fluid())
+ pm8058_platform_data.charger_pdata = &pmic8058_charger_ffa_surf;
+
+ /* configure pmic leds */
+ if (machine_is_msm8x60_fluid())
+ pm8058_platform_data.leds_pdata = &pm8058_fluid_flash_leds_data;
+ else if (machine_is_msm8x60_dragon())
+ pm8058_platform_data.leds_pdata = &pm8058_dragon_leds_data;
+ else
+ pm8058_platform_data.leds_pdata = &pm8058_flash_leds_data;
+
+ if (machine_is_msm8x60_ffa() || machine_is_msm8x60_fusn_ffa() ||
+ machine_is_msm8x60_dragon()) {
+ pm8058_platform_data.vibrator_pdata = &pm8058_vib_pdata;
+ }
+
if (machine_is_msm8x60_surf() || machine_is_msm8x60_ffa() ||
machine_is_msm8x60_fluid() || machine_is_msm8x60_fusion() ||
machine_is_msm8x60_fusn_ffa() || machine_is_msm8x60_dragon()) {
@@ -10367,25 +10096,10 @@
machine_is_msm8x60_dragon())
msm8x60_cfg_isp1763();
#endif
-#ifdef CONFIG_BATTERY_MSM8X60
- if (machine_is_msm8x60_surf() || machine_is_msm8x60_ffa() ||
- machine_is_msm8x60_fusion() || machine_is_msm8x60_dragon() ||
- machine_is_msm8x60_fusn_ffa() || machine_is_msm8x60_fluid())
- platform_device_register(&msm_charger_device);
-#endif
if (machine_is_msm8x60_fusion() || machine_is_msm8x60_fusn_ffa())
platform_add_devices(charm_devices, ARRAY_SIZE(charm_devices));
- if (machine_is_msm8x60_dragon()) {
- pm8058_charger_sub_dev.platform_data
- = &pmic8058_charger_dragon;
- pm8058_charger_sub_dev.pdata_size
- = sizeof(pmic8058_charger_dragon);
- }
- if (!machine_is_msm8x60_fluid())
- pm8058_platform_data.charger_sub_device
- = &pm8058_charger_sub_dev;
#if defined(CONFIG_SPI_QUP) || defined(CONFIG_SPI_QUP_MODULE)
if (machine_is_msm8x60_fluid())
@@ -10442,6 +10156,8 @@
msm_pm_data);
BUG_ON(msm_pm_boot_init(MSM_PM_BOOT_CONFIG_TZ, NULL));
+ pm8058_gpios_init();
+
#ifdef CONFIG_SENSORS_MSM_ADC
if (machine_is_msm8x60_fluid()) {
msm_adc_pdata.dev_names = msm_adc_fluid_device_names;
@@ -10463,32 +10179,6 @@
platform_device_register(&gpio_leds);
#endif
- /* configure pmic leds */
- if (machine_is_msm8x60_fluid()) {
- pm8058_platform_data.sub_devices[PM8058_SUBDEV_LED].
- platform_data = &pm8058_fluid_flash_leds_data;
- pm8058_platform_data.sub_devices[PM8058_SUBDEV_LED].pdata_size
- = sizeof(pm8058_fluid_flash_leds_data);
- } else if (machine_is_msm8x60_dragon()) {
- pm8058_platform_data.sub_devices[PM8058_SUBDEV_LED].
- platform_data = &pm8058_dragon_leds_data;
- pm8058_platform_data.sub_devices[PM8058_SUBDEV_LED].pdata_size
- = sizeof(pm8058_dragon_leds_data);
- } else {
- pm8058_platform_data.sub_devices[PM8058_SUBDEV_LED].
- platform_data = &pm8058_flash_leds_data;
- pm8058_platform_data.sub_devices[PM8058_SUBDEV_LED].pdata_size
- = sizeof(pm8058_flash_leds_data);
- }
-
- if (machine_is_msm8x60_ffa() || machine_is_msm8x60_fusn_ffa() ||
- machine_is_msm8x60_dragon()) {
- pm8058_platform_data.sub_devices[PM8058_SUBDEV_VIB].
- platform_data = &pmic_vib_pdata;
- pm8058_platform_data.sub_devices[PM8058_SUBDEV_VIB].
- pdata_size = sizeof(pmic_vib_pdata);
- }
-
msm8x60_multi_sdio_init();
if (machine_is_msm8x60_fusion() || machine_is_msm8x60_fusn_ffa())
diff --git a/arch/arm/mach-msm/board-qrd7627a.c b/arch/arm/mach-msm/board-qrd7627a.c
index dbceae8..95b69e6 100644
--- a/arch/arm/mach-msm/board-qrd7627a.c
+++ b/arch/arm/mach-msm/board-qrd7627a.c
@@ -51,6 +51,7 @@
#include "devices-msm7x2xa.h"
#include "pm.h"
#include "timer.h"
+#include "pm-boot.h"
#define PMEM_KERNEL_EBI1_SIZE 0x3A000
#define MSM_PMEM_AUDIO_SIZE 0x5B000
@@ -2531,6 +2532,9 @@
#endif
msm_pm_set_platform_data(msm7627a_pm_data,
ARRAY_SIZE(msm7627a_pm_data));
+ BUG_ON(msm_pm_boot_init(MSM_PM_BOOT_CONFIG_RESET_VECTOR,
+ ioremap(0, PAGE_SIZE)));
+
msm_fb_add_devices();
#if defined(CONFIG_BT) && defined(CONFIG_MARIMBA_CORE)
diff --git a/arch/arm/mach-msm/clock-8960.c b/arch/arm/mach-msm/clock-8960.c
index 60ddc52..393528b 100644
--- a/arch/arm/mach-msm/clock-8960.c
+++ b/arch/arm/mach-msm/clock-8960.c
@@ -57,6 +57,8 @@
#define CLK_HALT_SFPB_MISC_STATE_REG REG(0x2FD8)
#define CLK_HALT_AFAB_SFAB_STATEB_REG REG(0x2FC4)
#define CLK_TEST_REG REG(0x2FA0)
+#define GPn_MD_REG(n) REG(0x2D00+(0x20*(n)))
+#define GPn_NS_REG(n) REG(0x2D24+(0x20*(n)))
#define GSBIn_HCLK_CTL_REG(n) REG(0x29C0+(0x20*((n)-1)))
#define GSBIn_QUP_APPS_MD_REG(n) REG(0x29C8+(0x20*((n)-1)))
#define GSBIn_QUP_APPS_NS_REG(n) REG(0x29CC+(0x20*((n)-1)))
@@ -319,7 +321,7 @@
/* MUX source input identifiers. */
#define pxo_to_bb_mux 0
-#define cxo_to_bb_mux pxo_to_bb_mux
+#define cxo_to_bb_mux 5
#define pll0_to_bb_mux 2
#define pll8_to_bb_mux 3
#define pll6_to_bb_mux 4
@@ -1222,6 +1224,55 @@
/*
* Peripheral Clocks
*/
+#define CLK_GP(i, n, h_r, h_b) \
+ struct rcg_clk i##_clk = { \
+ .b = { \
+ .ctl_reg = GPn_NS_REG(n), \
+ .en_mask = BIT(9), \
+ .halt_reg = h_r, \
+ .halt_bit = h_b, \
+ }, \
+ .ns_reg = GPn_NS_REG(n), \
+ .md_reg = GPn_MD_REG(n), \
+ .root_en_mask = BIT(11), \
+ .ns_mask = (BM(23, 16) | BM(6, 0)), \
+ .set_rate = set_rate_mnd, \
+ .freq_tbl = clk_tbl_gp, \
+ .current_freq = &rcg_dummy_freq, \
+ .c = { \
+ .dbg_name = #i "_clk", \
+ .ops = &clk_ops_rcg_8960, \
+ VDD_DIG_FMAX_MAP2(LOW, 100000000, NOMINAL, 200000000), \
+ CLK_INIT(i##_clk.c), \
+ }, \
+ }
+#define F_GP(f, s, d, m, n) \
+ { \
+ .freq_hz = f, \
+ .src_clk = &s##_clk.c, \
+ .md_val = MD8(16, m, 0, n), \
+ .ns_val = NS(23, 16, n, m, 5, 4, 3, d, 2, 0, s##_to_bb_mux), \
+ .mnd_en_mask = BIT(8) * !!(n), \
+ }
+static struct clk_freq_tbl clk_tbl_gp[] = {
+ F_GP( 0, gnd, 1, 0, 0),
+ F_GP( 9600000, cxo, 2, 0, 0),
+ F_GP( 13500000, pxo, 2, 0, 0),
+ F_GP( 19200000, cxo, 1, 0, 0),
+ F_GP( 27000000, pxo, 1, 0, 0),
+ F_GP( 64000000, pll8, 2, 1, 3),
+ F_GP( 76800000, pll8, 1, 1, 5),
+ F_GP( 96000000, pll8, 4, 0, 0),
+ F_GP(128000000, pll8, 3, 0, 0),
+ F_GP(192000000, pll8, 2, 0, 0),
+ F_GP(384000000, pll8, 1, 0, 0),
+ F_END
+};
+
+static CLK_GP(gp0, 0, CLK_HALT_SFPB_MISC_STATE_REG, 7);
+static CLK_GP(gp1, 1, CLK_HALT_SFPB_MISC_STATE_REG, 6);
+static CLK_GP(gp2, 2, CLK_HALT_SFPB_MISC_STATE_REG, 5);
+
#define CLK_GSBI_UART(i, n, h_r, h_b) \
struct rcg_clk i##_clk = { \
.b = { \
@@ -4681,6 +4732,9 @@
{ TEST_PER_LS(0x19), &sdc4_clk.c },
{ TEST_PER_LS(0x1A), &sdc5_p_clk.c },
{ TEST_PER_LS(0x1B), &sdc5_clk.c },
+ { TEST_PER_LS(0x1F), &gp0_clk.c },
+ { TEST_PER_LS(0x20), &gp1_clk.c },
+ { TEST_PER_LS(0x21), &gp2_clk.c },
{ TEST_PER_LS(0x25), &dfab_clk.c },
{ TEST_PER_LS(0x25), &dfab_a_clk.c },
{ TEST_PER_LS(0x26), &pmem_clk.c },
@@ -5070,6 +5124,9 @@
CLK_DUMMY("sfpb_clk", SFPB_CLK, NULL, 0),
CLK_DUMMY("sfpb_a_clk", SFPB_A_CLK, NULL, 0),
+ CLK_LOOKUP("core_clk", gp0_clk.c, NULL),
+ CLK_LOOKUP("core_clk", gp1_clk.c, NULL),
+ CLK_LOOKUP("core_clk", gp2_clk.c, NULL),
CLK_LOOKUP("core_clk", gsbi1_uart_clk.c, NULL),
CLK_LOOKUP("core_clk", gsbi2_uart_clk.c, NULL),
CLK_LOOKUP("core_clk", gsbi3_uart_clk.c, NULL),
@@ -5298,6 +5355,9 @@
CLK_LOOKUP("sfpb_clk", sfpb_clk.c, NULL),
CLK_LOOKUP("sfpb_a_clk", sfpb_a_clk.c, NULL),
+ CLK_LOOKUP("core_clk", gp0_clk.c, NULL),
+ CLK_LOOKUP("core_clk", gp1_clk.c, NULL),
+ CLK_LOOKUP("core_clk", gp2_clk.c, NULL),
CLK_LOOKUP("core_clk", gsbi1_uart_clk.c, NULL),
CLK_LOOKUP("core_clk", gsbi2_uart_clk.c, NULL),
CLK_LOOKUP("core_clk", gsbi3_uart_clk.c, NULL),
@@ -5379,26 +5439,20 @@
CLK_LOOKUP("cam_clk", cam0_clk.c, "msm_camera_imx074.0"),
CLK_LOOKUP("cam_clk", cam0_clk.c, "msm_camera_ov2720.0"),
CLK_LOOKUP("cam_clk", cam0_clk.c, "msm_camera_qs_mt9p017.0"),
- CLK_LOOKUP("csi_src_clk", csi0_src_clk.c, NULL),
- CLK_LOOKUP("csi_src_clk", csi1_src_clk.c, NULL),
- CLK_LOOKUP("csi_src_clk", csi0_src_clk.c, "msm_camera_imx074.0"),
- CLK_LOOKUP("csi_src_clk", csi0_src_clk.c, "msm_camera_qs_mt9p017.0"),
- CLK_LOOKUP("csi_src_clk", csi1_src_clk.c, "msm_camera_ov2720.0"),
- CLK_LOOKUP("csi_clk", csi0_clk.c, NULL),
- CLK_LOOKUP("csi_clk", csi1_clk.c, NULL),
- CLK_LOOKUP("csi_clk", csi0_clk.c, "msm_camera_imx074.0"),
- CLK_LOOKUP("csi_clk", csi0_clk.c, "msm_camera_qs_mt9p017.0"),
- CLK_LOOKUP("csi_clk", csi1_clk.c, "msm_camera_ov2720.0"),
- CLK_LOOKUP("csi_phy_clk", csi0_phy_clk.c, NULL),
- CLK_LOOKUP("csi_phy_clk", csi1_phy_clk.c, NULL),
- CLK_LOOKUP("csi_phy_clk", csi0_phy_clk.c, "msm_camera_imx074.0"),
- CLK_LOOKUP("csi_phy_clk", csi0_phy_clk.c, "msm_camera_qs_mt9p017.0"),
- CLK_LOOKUP("csi_phy_clk", csi1_phy_clk.c, "msm_camera_ov2720.0"),
- CLK_LOOKUP("csi_pix_clk", csi_pix_clk.c, NULL),
- CLK_LOOKUP("csi_rdi_clk", csi_rdi_clk.c, NULL),
- CLK_LOOKUP("csiphy_timer_src_clk", csiphy_timer_src_clk.c, NULL),
- CLK_LOOKUP("csi0phy_timer_clk", csi0phy_timer_clk.c, NULL),
- CLK_LOOKUP("csi1phy_timer_clk", csi1phy_timer_clk.c, NULL),
+ CLK_LOOKUP("csi_src_clk", csi0_src_clk.c, "msm_csid.0"),
+ CLK_LOOKUP("csi_src_clk", csi1_src_clk.c, "msm_csid.1"),
+ CLK_LOOKUP("csi_clk", csi0_clk.c, "msm_csid.0"),
+ CLK_LOOKUP("csi_clk", csi1_clk.c, "msm_csid.1"),
+ CLK_LOOKUP("csi_phy_clk", csi0_phy_clk.c, "msm_csid.0"),
+ CLK_LOOKUP("csi_phy_clk", csi1_phy_clk.c, "msm_csid.1"),
+ CLK_LOOKUP("csi_pix_clk", csi_pix_clk.c, "msm_ispif.0"),
+ CLK_LOOKUP("csi_rdi_clk", csi_rdi_clk.c, "msm_ispif.0"),
+ CLK_LOOKUP("csiphy_timer_src_clk",
+ csiphy_timer_src_clk.c, "msm_csiphy.0"),
+ CLK_LOOKUP("csiphy_timer_src_clk",
+ csiphy_timer_src_clk.c, "msm_csiphy.1"),
+ CLK_LOOKUP("csiphy_timer_clk", csi0phy_timer_clk.c, "msm_csiphy.0"),
+ CLK_LOOKUP("csiphy_timer_clk", csi1phy_timer_clk.c, "msm_csiphy.1"),
CLK_LOOKUP("dsi_byte_div_clk", dsi1_byte_clk.c, NULL),
CLK_LOOKUP("dsi_byte_div_clk", dsi2_byte_clk.c, NULL),
CLK_LOOKUP("dsi_esc_clk", dsi1_esc_clk.c, NULL),
@@ -5434,11 +5488,11 @@
CLK_LOOKUP("mdp_tv_clk", mdp_tv_clk.c, NULL),
CLK_LOOKUP("hdmi_clk", hdmi_tv_clk.c, NULL),
CLK_LOOKUP("core_clk", hdmi_app_clk.c, "hdmi_msm.1"),
- CLK_LOOKUP("vpe_clk", vpe_clk.c, NULL),
+ CLK_LOOKUP("vpe_clk", vpe_clk.c, "msm_vpe.0"),
CLK_LOOKUP("core_clk", vpe_clk.c, "footswitch-8x60.9"),
- CLK_LOOKUP("vfe_clk", vfe_clk.c, NULL),
+ CLK_LOOKUP("vfe_clk", vfe_clk.c, "msm_vfe.0"),
CLK_LOOKUP("core_clk", vfe_clk.c, "footswitch-8x60.8"),
- CLK_LOOKUP("csi_vfe_clk", csi_vfe_clk.c, NULL),
+ CLK_LOOKUP("csi_vfe_clk", csi_vfe_clk.c, "msm_vfe.0"),
CLK_LOOKUP("bus_clk", vfe_axi_clk.c, "footswitch-8x60.8"),
CLK_LOOKUP("bus_clk", mdp_axi_clk.c, "footswitch-8x60.4"),
CLK_LOOKUP("bus_clk", rot_axi_clk.c, "footswitch-8x60.6"),
@@ -5447,7 +5501,8 @@
CLK_LOOKUP("bus_b_clk", vcodec_axi_b_clk.c, "footswitch-8x60.7"),
CLK_LOOKUP("bus_clk", vpe_axi_clk.c, "footswitch-8x60.9"),
CLK_LOOKUP("amp_pclk", amp_p_clk.c, NULL),
- CLK_LOOKUP("csi_pclk", csi_p_clk.c, NULL),
+ CLK_LOOKUP("csi_pclk", csi_p_clk.c, "msm_csid.0"),
+ CLK_LOOKUP("csi_pclk", csi_p_clk.c, "msm_csid.1"),
CLK_LOOKUP("dsi_m_pclk", dsi1_m_p_clk.c, NULL),
CLK_LOOKUP("dsi_s_pclk", dsi1_s_p_clk.c, NULL),
CLK_LOOKUP("dsi_m_pclk", dsi2_m_p_clk.c, NULL),
@@ -5472,9 +5527,9 @@
CLK_LOOKUP("tv_enc_pclk", tv_enc_p_clk.c, NULL),
CLK_LOOKUP("iface_clk", vcodec_p_clk.c, "msm_vidc.0"),
CLK_LOOKUP("iface_clk", vcodec_p_clk.c, "footswitch-8x60.7"),
- CLK_LOOKUP("vfe_pclk", vfe_p_clk.c, NULL),
+ CLK_LOOKUP("vfe_pclk", vfe_p_clk.c, "msm_vfe.0"),
CLK_LOOKUP("iface_clk", vfe_p_clk.c, "footswitch-8x60.8"),
- CLK_LOOKUP("vpe_pclk", vpe_p_clk.c, NULL),
+ CLK_LOOKUP("vpe_pclk", vpe_p_clk.c, "msm_vpe.0"),
CLK_LOOKUP("iface_clk", vpe_p_clk.c, "footswitch-8x60.9"),
CLK_LOOKUP("mi2s_bit_clk", mi2s_bit_clk.c, NULL),
CLK_LOOKUP("mi2s_osr_clk", mi2s_osr_clk.c, NULL),
@@ -5526,9 +5581,9 @@
CLK_LOOKUP("cam_clk", cam2_clk.c, NULL),
CLK_LOOKUP("csi_src_clk", csi2_src_clk.c, NULL),
CLK_LOOKUP("csi_clk", csi2_clk.c, NULL),
- CLK_LOOKUP("csi_pix1_clk", csi_pix1_clk.c, NULL),
- CLK_LOOKUP("csi_rdi1_clk", csi_rdi1_clk.c, NULL),
- CLK_LOOKUP("csi_rdi2_clk", csi_rdi2_clk.c, NULL),
+ CLK_LOOKUP("csi_pix1_clk", csi_pix1_clk.c, "msm_ispif.0"),
+ CLK_LOOKUP("csi_rdi1_clk", csi_rdi1_clk.c, "msm_ispif.0"),
+ CLK_LOOKUP("csi_rdi2_clk", csi_rdi2_clk.c, "msm_ispif.0"),
CLK_LOOKUP("csi_phy_clk", csi2_phy_clk.c, NULL),
CLK_LOOKUP("csi2phy_timer_clk", csi2phy_timer_clk.c, NULL),
CLK_LOOKUP("usb_hsic_xcvr_fs_clk", usb_hsic_xcvr_fs_clk.c, NULL),
@@ -5970,7 +6025,7 @@
if (WARN(IS_ERR(mmfpb_a_clk), "mmfpb_a_clk not found (%ld)\n",
PTR_ERR(mmfpb_a_clk)))
return PTR_ERR(mmfpb_a_clk);
- rc = clk_set_min_rate(mmfpb_a_clk, 76800000);
+ rc = clk_set_rate(mmfpb_a_clk, 76800000);
if (WARN(rc, "mmfpb_a_clk rate was not set (%d)\n", rc))
return rc;
rc = clk_enable(mmfpb_a_clk);
@@ -5981,7 +6036,7 @@
if (WARN(IS_ERR(cfpb_a_clk), "cfpb_a_clk not found (%ld)\n",
PTR_ERR(cfpb_a_clk)))
return PTR_ERR(cfpb_a_clk);
- rc = clk_set_min_rate(cfpb_a_clk, 64000000);
+ rc = clk_set_rate(cfpb_a_clk, 64000000);
if (WARN(rc, "cfpb_a_clk rate was not set (%d)\n", rc))
return rc;
rc = clk_enable(cfpb_a_clk);
diff --git a/arch/arm/mach-msm/clock-8x60.c b/arch/arm/mach-msm/clock-8x60.c
index 6707757..17052ae 100644
--- a/arch/arm/mach-msm/clock-8x60.c
+++ b/arch/arm/mach-msm/clock-8x60.c
@@ -55,6 +55,8 @@
#define CLK_TEST_REG REG(0x2FA0)
#define EBI2_2X_CLK_CTL_REG REG(0x2660)
#define EBI2_CLK_CTL_REG REG(0x2664)
+#define GPn_MD_REG(n) REG(0x2D00+(0x20*(n)))
+#define GPn_NS_REG(n) REG(0x2D24+(0x20*(n)))
#define GSBIn_HCLK_CTL_REG(n) REG(0x29C0+(0x20*((n)-1)))
#define GSBIn_QUP_APPS_MD_REG(n) REG(0x29C8+(0x20*((n)-1)))
#define GSBIn_QUP_APPS_NS_REG(n) REG(0x29CC+(0x20*((n)-1)))
@@ -207,7 +209,7 @@
/* MUX source input identifiers. */
#define pxo_to_bb_mux 0
#define mxo_to_bb_mux 1
-#define cxo_to_bb_mux pxo_to_bb_mux
+#define cxo_to_bb_mux 5
#define pll0_to_bb_mux 2
#define pll8_to_bb_mux 3
#define pll6_to_bb_mux 4
@@ -1050,6 +1052,49 @@
/*
* Peripheral Clocks
*/
+#define CLK_GP(i, n, h_r, h_b) \
+ struct rcg_clk i##_clk = { \
+ .b = { \
+ .ctl_reg = GPn_NS_REG(n), \
+ .en_mask = BIT(9), \
+ .halt_reg = h_r, \
+ .halt_bit = h_b, \
+ }, \
+ .ns_reg = GPn_NS_REG(n), \
+ .md_reg = GPn_MD_REG(n), \
+ .root_en_mask = BIT(11), \
+ .ns_mask = (BM(23, 16) | BM(6, 0)), \
+ .set_rate = set_rate_mnd, \
+ .freq_tbl = clk_tbl_gp, \
+ .current_freq = &rcg_dummy_freq, \
+ .c = { \
+ .dbg_name = #i "_clk", \
+ .ops = &clk_ops_rcg_8x60, \
+ VDD_DIG_FMAX_MAP1(LOW, 27000000), \
+ CLK_INIT(i##_clk.c), \
+ }, \
+ }
+#define F_GP(f, s, d, m, n) \
+ { \
+ .freq_hz = f, \
+ .src_clk = &s##_clk.c, \
+ .md_val = MD8(16, m, 0, n), \
+ .ns_val = NS(23, 16, n, m, 5, 4, 3, d, 2, 0, s##_to_bb_mux), \
+ .mnd_en_mask = BIT(8) * !!(n), \
+ }
+static struct clk_freq_tbl clk_tbl_gp[] = {
+ F_GP( 0, gnd, 1, 0, 0),
+ F_GP( 9600000, cxo, 2, 0, 0),
+ F_GP( 13500000, pxo, 2, 0, 0),
+ F_GP( 19200000, cxo, 1, 0, 0),
+ F_GP( 27000000, pxo, 1, 0, 0),
+ F_END
+};
+
+static CLK_GP(gp0, 0, CLK_HALT_SFPB_MISC_STATE_REG, 7);
+static CLK_GP(gp1, 1, CLK_HALT_SFPB_MISC_STATE_REG, 6);
+static CLK_GP(gp2, 2, CLK_HALT_SFPB_MISC_STATE_REG, 5);
+
#define CLK_GSBI_UART(i, n, h_r, h_b) \
struct rcg_clk i##_clk = { \
.b = { \
@@ -3215,6 +3260,9 @@
{ TEST_PER_LS(0x1B), &sdc5_clk.c },
{ TEST_PER_LS(0x1D), &ebi2_2x_clk.c },
{ TEST_PER_LS(0x1E), &ebi2_clk.c },
+ { TEST_PER_LS(0x1F), &gp0_clk.c },
+ { TEST_PER_LS(0x20), &gp1_clk.c },
+ { TEST_PER_LS(0x21), &gp2_clk.c },
{ TEST_PER_LS(0x25), &dfab_clk.c },
{ TEST_PER_LS(0x25), &dfab_a_clk.c },
{ TEST_PER_LS(0x26), &pmem_clk.c },
@@ -3567,6 +3615,9 @@
CLK_LOOKUP("smi_clk", smi_clk.c, NULL),
CLK_LOOKUP("smi_a_clk", smi_a_clk.c, NULL),
+ CLK_LOOKUP("core_clk", gp0_clk.c, NULL),
+ CLK_LOOKUP("core_clk", gp1_clk.c, NULL),
+ CLK_LOOKUP("core_clk", gp2_clk.c, NULL),
CLK_LOOKUP("core_clk", gsbi1_uart_clk.c, NULL),
CLK_LOOKUP("core_clk", gsbi2_uart_clk.c, NULL),
CLK_LOOKUP("core_clk", gsbi3_uart_clk.c, "msm_serial_hsl.2"),
@@ -3910,7 +3961,7 @@
if (WARN(IS_ERR(mmfpb_a_clk), "mmfpb_a_clk not found (%ld)\n",
PTR_ERR(mmfpb_a_clk)))
return PTR_ERR(mmfpb_a_clk);
- rc = clk_set_min_rate(mmfpb_a_clk, 64000000);
+ rc = clk_set_rate(mmfpb_a_clk, 64000000);
if (WARN(rc, "mmfpb_a_clk rate was not set (%d)\n", rc))
return rc;
rc = clk_enable(mmfpb_a_clk);
diff --git a/arch/arm/mach-msm/clock-9615.c b/arch/arm/mach-msm/clock-9615.c
index 8ff9725..7e163df 100644
--- a/arch/arm/mach-msm/clock-9615.c
+++ b/arch/arm/mach-msm/clock-9615.c
@@ -50,6 +50,8 @@
#define CLK_HALT_MSS_KPSS_MISC_STATE_REG REG(0x2FDC)
#define CLK_HALT_SFPB_MISC_STATE_REG REG(0x2FD8)
#define CLK_TEST_REG REG(0x2FA0)
+#define GPn_MD_REG(n) REG(0x2D00+(0x20*(n)))
+#define GPn_NS_REG(n) REG(0x2D24+(0x20*(n)))
#define GSBIn_HCLK_CTL_REG(n) REG(0x29C0+(0x20*((n)-1)))
#define GSBIn_QUP_APPS_MD_REG(n) REG(0x29C8+(0x20*((n)-1)))
#define GSBIn_QUP_APPS_NS_REG(n) REG(0x29CC+(0x20*((n)-1)))
@@ -346,6 +348,47 @@
/*
* Peripheral Clocks
*/
+#define CLK_GP(i, n, h_r, h_b) \
+ struct rcg_clk i##_clk = { \
+ .b = { \
+ .ctl_reg = GPn_NS_REG(n), \
+ .en_mask = BIT(9), \
+ .halt_reg = h_r, \
+ .halt_bit = h_b, \
+ }, \
+ .ns_reg = GPn_NS_REG(n), \
+ .md_reg = GPn_MD_REG(n), \
+ .root_en_mask = BIT(11), \
+ .ns_mask = (BM(23, 16) | BM(6, 0)), \
+ .set_rate = set_rate_mnd, \
+ .freq_tbl = clk_tbl_gp, \
+ .current_freq = &rcg_dummy_freq, \
+ .c = { \
+ .dbg_name = #i "_clk", \
+ .ops = &clk_ops_rcg_9615, \
+ VDD_DIG_FMAX_MAP1(LOW, 27000000), \
+ CLK_INIT(i##_clk.c), \
+ }, \
+ }
+#define F_GP(f, s, d, m, n) \
+ { \
+ .freq_hz = f, \
+ .src_clk = &s##_clk.c, \
+ .md_val = MD8(16, m, 0, n), \
+ .ns_val = NS(23, 16, n, m, 5, 4, 3, d, 2, 0, s##_to_bb_mux), \
+ .mnd_en_mask = BIT(8) * !!(n), \
+ }
+static struct clk_freq_tbl clk_tbl_gp[] = {
+ F_GP( 0, gnd, 1, 0, 0),
+ F_GP( 9600000, cxo, 2, 0, 0),
+ F_GP( 19200000, cxo, 1, 0, 0),
+ F_END
+};
+
+static CLK_GP(gp0, 0, CLK_HALT_SFPB_MISC_STATE_REG, 7);
+static CLK_GP(gp1, 1, CLK_HALT_SFPB_MISC_STATE_REG, 6);
+static CLK_GP(gp2, 2, CLK_HALT_SFPB_MISC_STATE_REG, 5);
+
#define CLK_GSBI_UART(i, n, h_r, h_b) \
struct rcg_clk i##_clk = { \
.b = { \
@@ -1277,6 +1320,7 @@
static DEFINE_CLK_VOTER(dfab_sdc1_clk, &dfab_clk.c);
static DEFINE_CLK_VOTER(dfab_sdc2_clk, &dfab_clk.c);
static DEFINE_CLK_VOTER(dfab_sps_clk, &dfab_clk.c);
+static DEFINE_CLK_VOTER(dfab_bam_dmux_clk, &dfab_clk.c);
static DEFINE_CLK_VOTER(ebi1_msmbus_clk, &ebi1_clk.c);
/*
@@ -1297,6 +1341,9 @@
{ TEST_PER_LS(0x13), &sdc1_clk.c },
{ TEST_PER_LS(0x14), &sdc2_p_clk.c },
{ TEST_PER_LS(0x15), &sdc2_clk.c },
+ { TEST_PER_LS(0x1F), &gp0_clk.c },
+ { TEST_PER_LS(0x20), &gp1_clk.c },
+ { TEST_PER_LS(0x21), &gp2_clk.c },
{ TEST_PER_LS(0x26), &pmem_clk.c },
{ TEST_PER_LS(0x25), &dfab_clk.c },
{ TEST_PER_LS(0x25), &dfab_a_clk.c },
@@ -1523,6 +1570,10 @@
CLK_LOOKUP("sfpb_clk", sfpb_clk.c, NULL),
CLK_LOOKUP("sfpb_a_clk", sfpb_a_clk.c, NULL),
+ CLK_LOOKUP("core_clk", gp0_clk.c, NULL),
+ CLK_LOOKUP("core_clk", gp1_clk.c, NULL),
+ CLK_LOOKUP("core_clk", gp2_clk.c, NULL),
+
CLK_LOOKUP("core_clk", gsbi1_uart_clk.c, NULL),
CLK_LOOKUP("core_clk", gsbi2_uart_clk.c, NULL),
CLK_LOOKUP("core_clk", gsbi3_uart_clk.c, NULL),
@@ -1585,7 +1636,7 @@
CLK_LOOKUP("bus_clk", dfab_sdc1_clk.c, "msm_sdcc.1"),
CLK_LOOKUP("bus_clk", dfab_sdc2_clk.c, "msm_sdcc.2"),
CLK_LOOKUP("dfab_clk", dfab_sps_clk.c, "msm_sps"),
-
+ CLK_LOOKUP("bus_clk", dfab_bam_dmux_clk.c, "BAM_RMNT"),
CLK_LOOKUP("ebi1_msmbus_clk", ebi1_msmbus_clk.c, NULL),
CLK_LOOKUP("mem_clk", ebi1_adm_clk.c, "msm_dmov"),
diff --git a/arch/arm/mach-msm/clock-debug.c b/arch/arm/mach-msm/clock-debug.c
index 78586a8..4990c81 100644
--- a/arch/arm/mach-msm/clock-debug.c
+++ b/arch/arm/mach-msm/clock-debug.c
@@ -33,13 +33,10 @@
* for debugging purposes so we don't check for error. */
if (clock->flags & CLKFLAG_MAX)
clk_set_max_rate(clock, val);
- if (clock->flags & CLKFLAG_MIN)
- ret = clk_set_min_rate(clock, val);
- else
- ret = clk_set_rate(clock, val);
- if (ret != 0)
- printk(KERN_ERR "clk_set%s_rate failed (%d)\n",
- (clock->flags & CLKFLAG_MIN) ? "_min" : "", ret);
+ ret = clk_set_rate(clock, val);
+ if (ret)
+ pr_err("clk_set_rate failed (%d)\n", ret);
+
return ret;
}
diff --git a/arch/arm/mach-msm/clock-voter.c b/arch/arm/mach-msm/clock-voter.c
index 56beca1..2624f6c 100644
--- a/arch/arm/mach-msm/clock-voter.c
+++ b/arch/arm/mach-msm/clock-voter.c
@@ -61,7 +61,7 @@
new_rate = max(other_rate, rate);
if (new_rate != cur_rate) {
- ret = clk_set_min_rate(parent, new_rate);
+ ret = clk_set_rate(parent, new_rate);
if (ret)
goto unlock;
}
@@ -90,7 +90,7 @@
*/
cur_rate = voter_clk_aggregate_rate(parent);
if (v->rate > cur_rate) {
- ret = clk_set_min_rate(parent, v->rate);
+ ret = clk_set_rate(parent, v->rate);
if (ret)
goto out;
}
@@ -119,7 +119,7 @@
cur_rate = max(new_rate, v->rate);
if (new_rate < cur_rate)
- clk_set_min_rate(parent, new_rate);
+ clk_set_rate(parent, new_rate);
spin_unlock_irqrestore(&voter_clk_lock, flags);
}
diff --git a/arch/arm/mach-msm/clock.c b/arch/arm/mach-msm/clock.c
index eff85f0..d4f3e45 100644
--- a/arch/arm/mach-msm/clock.c
+++ b/arch/arm/mach-msm/clock.c
@@ -277,7 +277,10 @@
int clk_set_rate(struct clk *clk, unsigned long rate)
{
- return _clk_set_rate(clk, rate, clk->ops->set_rate);
+ if (clk->flags & CLKFLAG_MIN)
+ return _clk_set_rate(clk, rate, clk->ops->set_min_rate);
+ else
+ return _clk_set_rate(clk, rate, clk->ops->set_rate);
}
EXPORT_SYMBOL(clk_set_rate);
diff --git a/arch/arm/mach-msm/devices-8960.c b/arch/arm/mach-msm/devices-8960.c
index 5d0a13c..2ea1f47 100644
--- a/arch/arm/mach-msm/devices-8960.c
+++ b/arch/arm/mach-msm/devices-8960.c
@@ -15,6 +15,7 @@
#include <linux/list.h>
#include <linux/platform_device.h>
#include <linux/msm_rotator.h>
+#include <linux/ion.h>
#include <linux/gpio.h>
#include <asm/clkdev.h>
#include <linux/msm_kgsl.h>
@@ -537,10 +538,11 @@
#ifdef CONFIG_MSM_BUS_SCALING
.vidc_bus_client_pdata = &vidc_bus_client_data,
#endif
- .memtype = MEMTYPE_EBI1,
#ifdef CONFIG_MSM_MULTIMEDIA_USE_ION
+ .memtype = ION_HEAP_EBI_ID,
.enable_ion = 1,
#else
+ .memtype = MEMTYPE_EBI1,
.enable_ion = 0,
#endif
};
@@ -983,94 +985,10 @@
#ifdef CONFIG_MSM_CAMERA
struct resource msm_camera_resources[] = {
{
- .name = "vfe",
- .start = 0x04500000,
- .end = 0x04500000 + SZ_1M - 1,
- .flags = IORESOURCE_MEM,
- },
- {
- .name = "vfe",
- .start = VFE_IRQ,
- .end = VFE_IRQ,
- .flags = IORESOURCE_IRQ,
- },
- {
- .name = "vpe",
- .start = 0x05300000,
- .end = 0x05300000 + SZ_1M - 1,
- .flags = IORESOURCE_MEM,
- },
- {
- .name = "vpe",
- .start = VPE_IRQ,
- .end = VPE_IRQ,
- .flags = IORESOURCE_IRQ,
- },
- {
.name = "vid_buf",
.flags = IORESOURCE_DMA,
},
{
- .name = "ispif",
- .start = 0x04800800,
- .end = 0x04800800 + SZ_1K - 1,
- .flags = IORESOURCE_MEM,
- },
- {
- .name = "ispif",
- .start = ISPIF_IRQ,
- .end = ISPIF_IRQ,
- .flags = IORESOURCE_IRQ,
- },
- {
- .name = "csid0",
- .start = 0x04800000,
- .end = 0x04800000 + SZ_1K - 1,
- .flags = IORESOURCE_MEM,
- },
- {
- .name = "csid0",
- .start = CSI_0_IRQ,
- .end = CSI_0_IRQ,
- .flags = IORESOURCE_IRQ,
- },
- {
- .name = "csiphy0",
- .start = 0x04800C00,
- .end = 0x04800C00 + SZ_1K - 1,
- .flags = IORESOURCE_MEM,
- },
- {
- .name = "csiphy0",
- .start = CSIPHY_4LN_IRQ,
- .end = CSIPHY_4LN_IRQ,
- .flags = IORESOURCE_IRQ,
- },
- {
- .name = "csid1",
- .start = 0x04800400,
- .end = 0x04800400 + SZ_1K - 1,
- .flags = IORESOURCE_MEM,
- },
- {
- .name = "csid1",
- .start = CSI_1_IRQ,
- .end = CSI_1_IRQ,
- .flags = IORESOURCE_IRQ,
- },
- {
- .name = "csiphy1",
- .start = 0x04801000,
- .end = 0x04801000 + SZ_1K - 1,
- .flags = IORESOURCE_MEM,
- },
- {
- .name = "csiphy1",
- .start = MSM8960_CSIPHY_2LN_IRQ,
- .end = MSM8960_CSIPHY_2LN_IRQ,
- .flags = IORESOURCE_IRQ,
- },
- {
.name = "s3d_rw",
.start = 0x008003E0,
.end = 0x008003E0 + SZ_16 - 1,
@@ -1082,7 +1000,6 @@
.end = 0x008020B8 + SZ_16 - 1,
.flags = IORESOURCE_MEM,
},
-
};
int __init msm_get_cam_resources(struct msm_camera_sensor_info *s_info)
@@ -1091,6 +1008,160 @@
s_info->num_resources = ARRAY_SIZE(msm_camera_resources);
return 0;
}
+
+static struct resource msm_csiphy0_resources[] = {
+ {
+ .name = "csiphy",
+ .start = 0x04800C00,
+ .end = 0x04800C00 + SZ_1K - 1,
+ .flags = IORESOURCE_MEM,
+ },
+ {
+ .name = "csiphy",
+ .start = CSIPHY_4LN_IRQ,
+ .end = CSIPHY_4LN_IRQ,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+static struct resource msm_csiphy1_resources[] = {
+ {
+ .name = "csiphy",
+ .start = 0x04801000,
+ .end = 0x04801000 + SZ_1K - 1,
+ .flags = IORESOURCE_MEM,
+ },
+ {
+ .name = "csiphy",
+ .start = MSM8960_CSIPHY_2LN_IRQ,
+ .end = MSM8960_CSIPHY_2LN_IRQ,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+struct platform_device msm8960_device_csiphy0 = {
+ .name = "msm_csiphy",
+ .id = 0,
+ .resource = msm_csiphy0_resources,
+ .num_resources = ARRAY_SIZE(msm_csiphy0_resources),
+};
+
+struct platform_device msm8960_device_csiphy1 = {
+ .name = "msm_csiphy",
+ .id = 1,
+ .resource = msm_csiphy1_resources,
+ .num_resources = ARRAY_SIZE(msm_csiphy1_resources),
+};
+
+static struct resource msm_csid0_resources[] = {
+ {
+ .name = "csid",
+ .start = 0x04800000,
+ .end = 0x04800000 + SZ_1K - 1,
+ .flags = IORESOURCE_MEM,
+ },
+ {
+ .name = "csid",
+ .start = CSI_0_IRQ,
+ .end = CSI_0_IRQ,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+static struct resource msm_csid1_resources[] = {
+ {
+ .name = "csid",
+ .start = 0x04800400,
+ .end = 0x04800400 + SZ_1K - 1,
+ .flags = IORESOURCE_MEM,
+ },
+ {
+ .name = "csid",
+ .start = CSI_1_IRQ,
+ .end = CSI_1_IRQ,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+struct platform_device msm8960_device_csid0 = {
+ .name = "msm_csid",
+ .id = 0,
+ .resource = msm_csid0_resources,
+ .num_resources = ARRAY_SIZE(msm_csid0_resources),
+};
+
+struct platform_device msm8960_device_csid1 = {
+ .name = "msm_csid",
+ .id = 1,
+ .resource = msm_csid1_resources,
+ .num_resources = ARRAY_SIZE(msm_csid1_resources),
+};
+
+struct resource msm_ispif_resources[] = {
+ {
+ .name = "ispif",
+ .start = 0x04800800,
+ .end = 0x04800800 + SZ_1K - 1,
+ .flags = IORESOURCE_MEM,
+ },
+ {
+ .name = "ispif",
+ .start = ISPIF_IRQ,
+ .end = ISPIF_IRQ,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+struct platform_device msm8960_device_ispif = {
+ .name = "msm_ispif",
+ .id = 0,
+ .resource = msm_ispif_resources,
+ .num_resources = ARRAY_SIZE(msm_ispif_resources),
+};
+
+static struct resource msm_vfe_resources[] = {
+ {
+ .name = "vfe32",
+ .start = 0x04500000,
+ .end = 0x04500000 + SZ_1M - 1,
+ .flags = IORESOURCE_MEM,
+ },
+ {
+ .name = "vfe32",
+ .start = VFE_IRQ,
+ .end = VFE_IRQ,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+struct platform_device msm8960_device_vfe = {
+ .name = "msm_vfe",
+ .id = 0,
+ .resource = msm_vfe_resources,
+ .num_resources = ARRAY_SIZE(msm_vfe_resources),
+};
+
+static struct resource msm_vpe_resources[] = {
+ {
+ .name = "vpe",
+ .start = 0x05300000,
+ .end = 0x05300000 + SZ_1M - 1,
+ .flags = IORESOURCE_MEM,
+ },
+ {
+ .name = "vpe",
+ .start = VPE_IRQ,
+ .end = VPE_IRQ,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+struct platform_device msm8960_device_vpe = {
+ .name = "msm_vpe",
+ .id = 0,
+ .resource = msm_vpe_resources,
+ .num_resources = ARRAY_SIZE(msm_vpe_resources),
+};
#endif
static struct resource resources_ssbi_pm8921[] = {
@@ -2345,6 +2416,7 @@
#define MSM_ETB_PHYS_BASE (MSM_QDSS_PHYS_BASE + 0x1000)
#define MSM_TPIU_PHYS_BASE (MSM_QDSS_PHYS_BASE + 0x3000)
#define MSM_FUNNEL_PHYS_BASE (MSM_QDSS_PHYS_BASE + 0x4000)
+#define MSM_DEBUG_PHYS_BASE (MSM_QDSS_PHYS_BASE + 0x10000)
#define MSM_PTM_PHYS_BASE (MSM_QDSS_PHYS_BASE + 0x1C000)
static struct resource msm_etb_resources[] = {
@@ -2392,6 +2464,26 @@
.resource = msm_funnel_resources,
};
+static struct resource msm_debug_resources[] = {
+ {
+ .start = MSM_DEBUG_PHYS_BASE,
+ .end = MSM_DEBUG_PHYS_BASE + SZ_4K - 1,
+ .flags = IORESOURCE_MEM,
+ },
+ {
+ .start = MSM_DEBUG_PHYS_BASE + (SZ_4K * 2),
+ .end = MSM_DEBUG_PHYS_BASE + (SZ_4K * 2) + SZ_4K - 1,
+ .flags = IORESOURCE_MEM,
+ },
+};
+
+struct platform_device msm_debug_device = {
+ .name = "msm_debug",
+ .id = 0,
+ .num_resources = ARRAY_SIZE(msm_debug_resources),
+ .resource = msm_debug_resources,
+};
+
static struct resource msm_ptm_resources[] = {
{
.start = MSM_PTM_PHYS_BASE,
diff --git a/arch/arm/mach-msm/devices-msm7x30.c b/arch/arm/mach-msm/devices-msm7x30.c
index 2a39e3c..017eed9 100644
--- a/arch/arm/mach-msm/devices-msm7x30.c
+++ b/arch/arm/mach-msm/devices-msm7x30.c
@@ -548,8 +548,8 @@
},
{
.name = "vbus_on",
- .start = PM8058_CHGVAL_IRQ(PMIC8058_IRQ_BASE),
- .end = PM8058_CHGVAL_IRQ(PMIC8058_IRQ_BASE),
+ .start = PMIC8058_IRQ_BASE + PM8058_CHGVAL_IRQ,
+ .end = PMIC8058_IRQ_BASE + PM8058_CHGVAL_IRQ,
.flags = IORESOURCE_IRQ,
},
};
diff --git a/arch/arm/mach-msm/devices-msm8x60.c b/arch/arm/mach-msm/devices-msm8x60.c
index 52c62fd..0ab9811 100644
--- a/arch/arm/mach-msm/devices-msm8x60.c
+++ b/arch/arm/mach-msm/devices-msm8x60.c
@@ -15,6 +15,7 @@
#include <linux/platform_device.h>
#include <linux/regulator/machine.h>
#include <linux/regulator/consumer.h>
+#include <linux/ion.h>
#include <mach/irqs.h>
#include <mach/dma.h>
#include <asm/mach/mmc.h>
@@ -2150,10 +2151,11 @@
#ifdef CONFIG_MSM_BUS_SCALING
.vidc_bus_client_pdata = &vidc_bus_client_data,
#endif
- .memtype = MEMTYPE_SMI_KERNEL,
#ifdef CONFIG_MSM_MULTIMEDIA_USE_ION
+ .memtype = ION_HEAP_SMI_ID,
.enable_ion = 1,
#else
+ .memtype = MEMTYPE_SMI_KERNEL,
.enable_ion = 0,
#endif
};
diff --git a/arch/arm/mach-msm/devices-msm8x60.h b/arch/arm/mach-msm/devices-msm8x60.h
index 6b7d141..1d5dee1 100644
--- a/arch/arm/mach-msm/devices-msm8x60.h
+++ b/arch/arm/mach-msm/devices-msm8x60.h
@@ -69,12 +69,6 @@
#ifdef CONFIG_MSM_DSPS
extern struct platform_device msm_dsps_device;
#endif
-#ifdef CONFIG_MSM_QDSS
-extern struct platform_device msm_etb_device;
-extern struct platform_device msm_tpiu_device;
-extern struct platform_device msm_funnel_device;
-extern struct platform_device msm_ptm_device;
-#endif
#if defined(CONFIG_MSM_RPM_STATS_LOG)
extern struct platform_device msm_rpm_stat_device;
diff --git a/arch/arm/mach-msm/devices.h b/arch/arm/mach-msm/devices.h
index 4af3e68..b5cadd3 100644
--- a/arch/arm/mach-msm/devices.h
+++ b/arch/arm/mach-msm/devices.h
@@ -58,6 +58,13 @@
extern struct platform_device msm8960_device_qup_i2c_gsbi12;
extern struct platform_device msm8960_device_qup_spi_gsbi1;
extern struct platform_device msm8960_gemini_device;
+extern struct platform_device msm8960_device_csiphy0;
+extern struct platform_device msm8960_device_csiphy1;
+extern struct platform_device msm8960_device_csid0;
+extern struct platform_device msm8960_device_csid1;
+extern struct platform_device msm8960_device_ispif;
+extern struct platform_device msm8960_device_vfe;
+extern struct platform_device msm8960_device_vpe;
extern struct platform_device apq8064_device_uart_gsbi1;
extern struct platform_device apq8064_device_uart_gsbi3;
@@ -207,4 +214,10 @@
extern struct platform_device msm8660_device_watchdog;
extern struct platform_device msm8064_device_watchdog;
extern struct platform_device msm9615_device_watchdog;
+
+extern struct platform_device msm_etb_device;
+extern struct platform_device msm_tpiu_device;
+extern struct platform_device msm_funnel_device;
+extern struct platform_device msm_debug_device;
+extern struct platform_device msm_ptm_device;
#endif
diff --git a/arch/arm/mach-msm/idle-v7.S b/arch/arm/mach-msm/idle-v7.S
index a6e8fdb..aab93f4 100644
--- a/arch/arm/mach-msm/idle-v7.S
+++ b/arch/arm/mach-msm/idle-v7.S
@@ -32,14 +32,11 @@
#endif
ENTRY(msm_arch_idle)
-#ifdef CONFIG_MSM_JTAG_V7
- stmfd sp!, {lr}
- bl msm_save_jtag_debug
-#endif
wfi
-#ifdef CONFIG_MSM_JTAG_V7
- bl msm_restore_jtag_debug
- ldmfd sp!, {lr}
+#ifdef CONFIG_ARCH_MSM8X60
+ mrc p14, 1, r1, c1, c5, 4 /* read ETM PDSR to clear sticky bit */
+ mrc p14, 0, r1, c1, c5, 4 /* read DBG PRSR to clear sticky bit */
+ isb
#endif
bx lr
@@ -85,7 +82,7 @@
stmia r0!, {r1-r3}
#endif
-#ifdef CONFIG_MSM_JTAG_V7
+#ifdef CONFIG_MSM_DEBUG_ACROSS_PC
bl msm_save_jtag_debug
#endif
#ifdef CONFIG_MSM_TRACE_ACROSS_PC
@@ -132,7 +129,7 @@
#ifdef CONFIG_MSM_TRACE_ACROSS_PC
bl etm_restore_reg_check
#endif
-#ifdef CONFIG_MSM_JTAG_V7
+#ifdef CONFIG_MSM_DEBUG_ACROSS_PC
bl msm_restore_jtag_debug
#endif
ldr r0, =saved_state /* restore registers */
@@ -220,7 +217,7 @@
#ifdef CONFIG_MSM_TRACE_ACROSS_PC
bl etm_restore_reg_check
#endif
-#ifdef CONFIG_MSM_JTAG_V7
+#ifdef CONFIG_MSM_DEBUG_ACROSS_PC
bl msm_restore_jtag_debug
#endif
ldmfd sp!, {lr}
diff --git a/arch/arm/mach-msm/include/mach/debug-macro.S b/arch/arm/mach-msm/include/mach/debug-macro.S
index 905a254..5112888 100644
--- a/arch/arm/mach-msm/include/mach/debug-macro.S
+++ b/arch/arm/mach-msm/include/mach/debug-macro.S
@@ -1,4 +1,4 @@
-/* arch/arm/mach-msm7200/include/mach/debug-macro.S
+/*
*
* Copyright (C) 2007 Google, Inc.
* Author: Brian Swetland <swetland@google.com>
@@ -19,7 +19,7 @@
#include <mach/hardware.h>
#include <mach/msm_iomap.h>
-#ifdef CONFIG_MSM_DEBUG_UART
+#ifdef MSM_DEBUG_UART_PHYS
.macro addruart, rp, rv
ldr \rp, =MSM_DEBUG_UART_PHYS
ldr \rv, =MSM_DEBUG_UART_BASE
diff --git a/arch/arm/mach-msm/include/mach/iommu.h b/arch/arm/mach-msm/include/mach/iommu.h
index 5cd7013..d5a2ed4 100644
--- a/arch/arm/mach-msm/include/mach/iommu.h
+++ b/arch/arm/mach-msm/include/mach/iommu.h
@@ -17,15 +17,7 @@
#include <linux/clk.h>
#include <mach/socinfo.h>
-/* Sharability attributes of MSM IOMMU mappings */
-#define MSM_IOMMU_ATTR_NON_SH 0x0
-#define MSM_IOMMU_ATTR_SH 0x4
-
-/* Cacheability attributes of MSM IOMMU mappings */
-#define MSM_IOMMU_ATTR_NONCACHED 0x0
-#define MSM_IOMMU_ATTR_CACHED_WB_WA 0x1
-#define MSM_IOMMU_ATTR_CACHED_WB_NWA 0x2
-#define MSM_IOMMU_ATTR_CACHED_WT 0x3
+extern pgprot_t pgprot_kernel;
/* Domain attributes */
#define MSM_IOMMU_DOMAIN_PT_CACHEABLE 0x1
diff --git a/arch/arm/mach-msm/include/mach/irqs-9615.h b/arch/arm/mach-msm/include/mach/irqs-9615.h
index 8b62632..74e5847 100644
--- a/arch/arm/mach-msm/include/mach/irqs-9615.h
+++ b/arch/arm/mach-msm/include/mach/irqs-9615.h
@@ -71,8 +71,8 @@
#define MSMC_SC_PRI_CE_IRQ (GIC_SPI_START + 32)
#define SLIMBUS0_CORE_EE1_IRQ (GIC_SPI_START + 33)
#define SLIMBUS0_BAM_EE1_IRQ (GIC_SPI_START + 34)
-#define Q6FW_WDOG_EXPIRED (GIC_SPI_START + 35)
-#define Q6SW_WDOG_EXPIRED (GIC_SPI_START + 36)
+#define Q6FW_WDOG_EXPIRED_IRQ (GIC_SPI_START + 35)
+#define Q6SW_WDOG_EXPIRED_IRQ (GIC_SPI_START + 36)
#define MSS_TO_APPS_IRQ_0 (GIC_SPI_START + 37)
#define MSS_TO_APPS_IRQ_1 (GIC_SPI_START + 38)
#define MSS_TO_APPS_IRQ_2 (GIC_SPI_START + 39)
diff --git a/arch/arm/mach-msm/include/mach/msm72k_otg.h b/arch/arm/mach-msm/include/mach/msm72k_otg.h
index 43f487a..4509dad 100644
--- a/arch/arm/mach-msm/include/mach/msm72k_otg.h
+++ b/arch/arm/mach-msm/include/mach/msm72k_otg.h
@@ -25,6 +25,7 @@
#define OTGSC_BSVIE (1 << 27)
#define OTGSC_IDIE (1 << 24)
+#define OTGSC_IDPU (1 << 5)
#define OTGSC_BSVIS (1 << 19)
#define OTGSC_ID (1 << 8)
#define OTGSC_IDIS (1 << 16)
@@ -148,7 +149,6 @@
struct wake_lock wlock;
unsigned long b_last_se0_sess; /* SRP initial condition check */
unsigned long inputs;
- int pmic_id_status;
unsigned long tmouts;
u8 active_tmout;
struct hrtimer timer;
diff --git a/arch/arm/mach-msm/include/mach/msm_hsusb.h b/arch/arm/mach-msm/include/mach/msm_hsusb.h
index 26f1cdd..3e8ab55 100644
--- a/arch/arm/mach-msm/include/mach/msm_hsusb.h
+++ b/arch/arm/mach-msm/include/mach/msm_hsusb.h
@@ -158,6 +158,7 @@
/* pmic notfications apis */
int (*pmic_vbus_notif_init) (void (*callback)(int online), int init);
int (*pmic_id_notif_init) (void (*callback)(int online), int init);
+ int (*phy_id_setup_init) (int init);
int (*pmic_register_vbus_sn) (void (*callback)(int online));
void (*pmic_unregister_vbus_sn) (void (*callback)(int online));
int (*pmic_enable_ldo) (int);
diff --git a/arch/arm/mach-msm/include/mach/msm_iomap-7x00.h b/arch/arm/mach-msm/include/mach/msm_iomap-7x00.h
index d1aef0a..333df32 100644
--- a/arch/arm/mach-msm/include/mach/msm_iomap-7x00.h
+++ b/arch/arm/mach-msm/include/mach/msm_iomap-7x00.h
@@ -83,18 +83,6 @@
#define MSM_UART3_PHYS 0xA9C00000
#define MSM_UART3_SIZE SZ_4K
-#ifdef CONFIG_MSM_DEBUG_UART
-#define MSM_DEBUG_UART_BASE 0xF9000000
-#if CONFIG_MSM_DEBUG_UART == 1
-#define MSM_DEBUG_UART_PHYS MSM_UART1_PHYS
-#elif CONFIG_MSM_DEBUG_UART == 2
-#define MSM_DEBUG_UART_PHYS MSM_UART2_PHYS
-#elif CONFIG_MSM_DEBUG_UART == 3
-#define MSM_DEBUG_UART_PHYS MSM_UART3_PHYS
-#endif
-#define MSM_DEBUG_UART_SIZE SZ_4K
-#endif
-
#define MSM_SDC1_PHYS 0xA0400000
#define MSM_SDC1_SIZE SZ_4K
diff --git a/arch/arm/mach-msm/include/mach/msm_iomap-7x30.h b/arch/arm/mach-msm/include/mach/msm_iomap-7x30.h
index e49e870..acd668b 100644
--- a/arch/arm/mach-msm/include/mach/msm_iomap-7x30.h
+++ b/arch/arm/mach-msm/include/mach/msm_iomap-7x30.h
@@ -91,18 +91,6 @@
#define MSM_UART3_PHYS 0xACC00000
#define MSM_UART3_SIZE SZ_4K
-#ifdef CONFIG_MSM_DEBUG_UART
-#define MSM_DEBUG_UART_BASE 0xFB000000
-#if CONFIG_MSM_DEBUG_UART == 1
-#define MSM_DEBUG_UART_PHYS MSM_UART1_PHYS
-#elif CONFIG_MSM_DEBUG_UART == 2
-#define MSM_DEBUG_UART_PHYS MSM_UART2_PHYS
-#elif CONFIG_MSM_DEBUG_UART == 3
-#define MSM_DEBUG_UART_PHYS MSM_UART3_PHYS
-#endif
-#define MSM_DEBUG_UART_SIZE SZ_4K
-#endif
-
#define MSM_MDC_BASE IOMEM(0xFA200000)
#define MSM_MDC_PHYS 0xAA500000
#define MSM_MDC_SIZE SZ_1M
diff --git a/arch/arm/mach-msm/include/mach/msm_iomap-7xxx.h b/arch/arm/mach-msm/include/mach/msm_iomap-7xxx.h
index d7dc4f4..d545a5f 100644
--- a/arch/arm/mach-msm/include/mach/msm_iomap-7xxx.h
+++ b/arch/arm/mach-msm/include/mach/msm_iomap-7xxx.h
@@ -79,18 +79,6 @@
#define MSM_UART3_PHYS 0xA9C00000
#define MSM_UART3_SIZE SZ_4K
-#ifdef CONFIG_MSM_DEBUG_UART
-#define MSM_DEBUG_UART_BASE 0xFB000000
-#if CONFIG_MSM_DEBUG_UART == 1
-#define MSM_DEBUG_UART_PHYS MSM_UART1_PHYS
-#elif CONFIG_MSM_DEBUG_UART == 2
-#define MSM_DEBUG_UART_PHYS MSM_UART2_PHYS
-#elif CONFIG_MSM_DEBUG_UART == 3
-#define MSM_DEBUG_UART_PHYS MSM_UART3_PHYS
-#endif
-#define MSM_DEBUG_UART_SIZE SZ_4K
-#endif
-
#define MSM_MDC_BASE IOMEM(0xFA200000)
#define MSM_MDC_PHYS 0xAA500000
#define MSM_MDC_SIZE SZ_1M
diff --git a/arch/arm/mach-msm/include/mach/msm_iomap-8930.h b/arch/arm/mach-msm/include/mach/msm_iomap-8930.h
index 8e50824..f3f8b8f 100644
--- a/arch/arm/mach-msm/include/mach/msm_iomap-8930.h
+++ b/arch/arm/mach-msm/include/mach/msm_iomap-8930.h
@@ -101,14 +101,10 @@
#define MSM8930_HDMI_PHYS 0x04A00000
#define MSM8930_HDMI_SIZE SZ_4K
-#ifdef CONFIG_MSM_DEBUG_UART
+#ifdef CONFIG_DEBUG_MSM8930_UART
#define MSM_DEBUG_UART_BASE IOMEM(0xFA740000)
-#define MSM_DEBUG_UART_SIZE SZ_4K
-
-#ifdef CONFIG_MSM_DEBUG_UART1
#define MSM_DEBUG_UART_PHYS 0x16440000
#endif
-#endif
#define MSM8930_QFPROM_PHYS 0x00700000
#define MSM8930_QFPROM_SIZE SZ_4K
diff --git a/arch/arm/mach-msm/include/mach/msm_iomap-8960.h b/arch/arm/mach-msm/include/mach/msm_iomap-8960.h
index 24505ae..b70cacc 100644
--- a/arch/arm/mach-msm/include/mach/msm_iomap-8960.h
+++ b/arch/arm/mach-msm/include/mach/msm_iomap-8960.h
@@ -98,14 +98,10 @@
#define MSM8960_HDMI_PHYS 0x04A00000
#define MSM8960_HDMI_SIZE SZ_4K
-#ifdef CONFIG_MSM_DEBUG_UART
+#ifdef CONFIG_DEBUG_MSM8960_UART
#define MSM_DEBUG_UART_BASE IOMEM(0xFA740000)
-#define MSM_DEBUG_UART_SIZE SZ_4K
-
-#ifdef CONFIG_MSM_DEBUG_UART1
#define MSM_DEBUG_UART_PHYS 0x16440000
#endif
-#endif
#define MSM8960_QFPROM_PHYS 0x00700000
#define MSM8960_QFPROM_SIZE SZ_4K
diff --git a/arch/arm/mach-msm/include/mach/msm_iomap-8x50.h b/arch/arm/mach-msm/include/mach/msm_iomap-8x50.h
index a073d6a..a1b32ec 100644
--- a/arch/arm/mach-msm/include/mach/msm_iomap-8x50.h
+++ b/arch/arm/mach-msm/include/mach/msm_iomap-8x50.h
@@ -83,18 +83,6 @@
#define MSM_UART3_PHYS 0xA9C00000
#define MSM_UART3_SIZE SZ_4K
-#ifdef CONFIG_MSM_DEBUG_UART
-#define MSM_DEBUG_UART_BASE 0xFB000000
-#if CONFIG_MSM_DEBUG_UART == 1
-#define MSM_DEBUG_UART_PHYS MSM_UART1_PHYS
-#elif CONFIG_MSM_DEBUG_UART == 2
-#define MSM_DEBUG_UART_PHYS MSM_UART2_PHYS
-#elif CONFIG_MSM_DEBUG_UART == 3
-#define MSM_DEBUG_UART_PHYS MSM_UART3_PHYS
-#endif
-#define MSM_DEBUG_UART_SIZE SZ_4K
-#endif
-
#define MSM_MDC_BASE IOMEM(0xFA200000)
#define MSM_MDC_PHYS 0xAA500000
#define MSM_MDC_SIZE SZ_1M
diff --git a/arch/arm/mach-msm/include/mach/msm_iomap-8x60.h b/arch/arm/mach-msm/include/mach/msm_iomap-8x60.h
index c1cf221..723f3d8 100644
--- a/arch/arm/mach-msm/include/mach/msm_iomap-8x60.h
+++ b/arch/arm/mach-msm/include/mach/msm_iomap-8x60.h
@@ -126,11 +126,9 @@
#define MSM_HDMI_PHYS 0x04A00000
#define MSM_HDMI_SIZE SZ_4K
-#ifdef CONFIG_MSM_DEBUG_UART
-
+#ifdef CONFIG_DEBUG_MSM8660_UART
#define MSM_DEBUG_UART_BASE 0xFBC40000
#define MSM_DEBUG_UART_PHYS 0x19C40000
-#define MSM_DEBUG_UART_SIZE SZ_4K
-
#endif
+
#endif
diff --git a/arch/arm/mach-msm/include/mach/msm_iomap-fsm9xxx.h b/arch/arm/mach-msm/include/mach/msm_iomap-fsm9xxx.h
index 57bfd58..c30c9e4 100644
--- a/arch/arm/mach-msm/include/mach/msm_iomap-fsm9xxx.h
+++ b/arch/arm/mach-msm/include/mach/msm_iomap-fsm9xxx.h
@@ -81,14 +81,4 @@
#define MSM_UART2_PHYS 0x94100000
#define MSM_UART2_SIZE SZ_4K
-#ifdef CONFIG_MSM_DEBUG_UART
-#define MSM_DEBUG_UART_BASE 0xFB000000
-#if CONFIG_MSM_DEBUG_UART == 1
-#define MSM_DEBUG_UART_PHYS MSM_UART1_PHYS
-#elif CONFIG_MSM_DEBUG_UART == 2
-#define MSM_DEBUG_UART_PHYS MSM_UART2_PHYS
-#endif
-#define MSM_DEBUG_UART_SIZE SZ_4K
-#endif
-
#endif
diff --git a/arch/arm/mach-msm/include/mach/msm_iomap.h b/arch/arm/mach-msm/include/mach/msm_iomap.h
index 256099b..dd01c62 100644
--- a/arch/arm/mach-msm/include/mach/msm_iomap.h
+++ b/arch/arm/mach-msm/include/mach/msm_iomap.h
@@ -43,6 +43,8 @@
#define IOMEM(x) ((void __force __iomem *)(x))
#endif
+#define MSM_DEBUG_UART_SIZE SZ_4K
+
#if defined(CONFIG_ARCH_MSM8960) || defined(CONFIG_ARCH_APQ8064) || \
defined(CONFIG_ARCH_MSM8930) || defined(CONFIG_ARCH_MSM9615) || \
defined(CONFIG_ARCH_MSMCOPPER)
@@ -103,6 +105,17 @@
#include "msm_iomap-7xxx.h"
#endif
+#if defined(CONFIG_DEBUG_MSM_UART1)
+#define MSM_DEBUG_UART_BASE 0xFB000000
+#define MSM_DEBUG_UART_PHYS MSM_UART1_PHYS
+#elif defined(CONFIG_DEBUG_MSM_UART2)
+#define MSM_DEBUG_UART_BASE 0xFB000000
+#define MSM_DEBUG_UART_PHYS MSM_UART2_PHYS
+#elif defined(CONFIG_DEBUG_MSM_UART3)
+#define MSM_DEBUG_UART_BASE 0xFB000000
+#define MSM_DEBUG_UART_PHYS MSM_UART3_PHYS
+#endif
+
#endif
#endif
diff --git a/arch/arm/mach-msm/include/mach/sps.h b/arch/arm/mach-msm/include/mach/sps.h
index 1514497..34729b3 100644
--- a/arch/arm/mach-msm/include/mach/sps.h
+++ b/arch/arm/mach-msm/include/mach/sps.h
@@ -1135,4 +1135,36 @@
struct sps_timer_ctrl *timer_ctrl,
struct sps_timer_result *timer_result);
+/**
+ * Find the handle of a BAM device based on the physical address
+ *
+ * This function finds a BAM device in the BAM registration list that
+ * matches the specified physical address, and returns its handle.
+ *
+ * @phys_addr - physical address of the BAM
+ *
+ * @h - device handle of the BAM
+ *
+ * @return 0 on success, negative value on error
+ *
+ */
+int sps_phy2h(u32 phys_addr, u32 *handle);
+
+/**
+ * Setup desc/data FIFO for bam-to-bam connection
+ *
+ * @mem_buffer - Pointer to struct for allocated memory properties.
+ *
+ * @addr - address of FIFO
+ *
+ * @size - FIFO size
+ *
+ * @use_offset - use address offset instead of absolute address
+ *
+ * @return 0 on success, negative value on error
+ *
+ */
+int sps_setup_bam2bam_fifo(struct sps_mem_buffer *mem_buffer,
+ u32 addr, u32 size, int use_offset);
+
#endif /* _SPS_H_ */
diff --git a/arch/arm/mach-msm/include/mach/uncompress.h b/arch/arm/mach-msm/include/mach/uncompress.h
index c8513b2..74cbda1 100644
--- a/arch/arm/mach-msm/include/mach/uncompress.h
+++ b/arch/arm/mach-msm/include/mach/uncompress.h
@@ -22,33 +22,30 @@
#include <mach/msm_iomap.h>
-bool msm_serial_hsl;
-
#ifndef CONFIG_DEBUG_ICEDCC
static void putc(int c)
{
#if defined(MSM_DEBUG_UART_PHYS)
unsigned long base = MSM_DEBUG_UART_PHYS;
- if (msm_serial_hsl) {
- /*
- * Wait for TX_READY to be set; but skip it if we have a
- * TX underrun.
- */
- if (__raw_readl(base + 0x08) & 0x08)
- while (!(__raw_readl(base + 0x14) & 0x80))
- cpu_relax();
-
- __raw_writel(0x300, base + 0x10);
- __raw_writel(0x1, base + 0x40);
- __raw_writel(c, base + 0x70);
-
- } else {
- /* Wait for TX_READY to be set */
- while (!(__raw_readl(base + 0x08) & 0x04))
+#ifdef CONFIG_SERIAL_MSM_HSL
+ /*
+ * Wait for TX_READY to be set; but skip it if we have a
+ * TX underrun.
+ */
+ if (__raw_readl(base + 0x08) & 0x08)
+ while (!(__raw_readl(base + 0x14) & 0x80))
cpu_relax();
- __raw_writel(c, base + 0x0c);
- }
+
+ __raw_writel(0x300, base + 0x10);
+ __raw_writel(0x1, base + 0x40);
+ __raw_writel(c, base + 0x70);
+#else
+ /* Wait for TX_READY to be set */
+ while (!(__raw_readl(base + 0x08) & 0x04))
+ cpu_relax();
+ __raw_writel(c, base + 0x0c);
+#endif
#endif
}
#endif
@@ -57,28 +54,8 @@
{
}
-#define DEBUG_LL_HS_ENTRY(machine) \
- if (machine_is_##machine()) { \
- msm_serial_hsl = true; \
- break; \
- }
-
static inline void arch_decomp_setup(void)
{
- do {
- DEBUG_LL_HS_ENTRY(msm8x60_fluid);
- DEBUG_LL_HS_ENTRY(msm8x60_surf);
- DEBUG_LL_HS_ENTRY(msm8x60_ffa);
- DEBUG_LL_HS_ENTRY(msm8x60_fusion);
- DEBUG_LL_HS_ENTRY(msm8x60_fusn_ffa);
- DEBUG_LL_HS_ENTRY(msm8x60_qrdc);
- DEBUG_LL_HS_ENTRY(msm8x60_qt);
- DEBUG_LL_HS_ENTRY(msm8960_cdp);
- DEBUG_LL_HS_ENTRY(msm8960_mtp);
- DEBUG_LL_HS_ENTRY(msm8960_fluid);
- DEBUG_LL_HS_ENTRY(msm8960_apq);
- DEBUG_LL_HS_ENTRY(msm8960_liquid);
- } while (0);
}
static inline void arch_decomp_wdog(void)
diff --git a/arch/arm/mach-msm/io.c b/arch/arm/mach-msm/io.c
index 65f5da0..8a79af7 100644
--- a/arch/arm/mach-msm/io.c
+++ b/arch/arm/mach-msm/io.c
@@ -66,7 +66,8 @@
MSM_DEVICE(CLK_CTL),
MSM_DEVICE(AD5),
MSM_DEVICE(MDC),
-#ifdef CONFIG_MSM_DEBUG_UART
+#if defined(CONFIG_DEBUG_MSM_UART1) || defined(CONFIG_DEBUG_MSM_UART2) || \
+ defined(CONFIG_DEBUG_MSM_UART3)
MSM_DEVICE(DEBUG_UART),
#endif
#ifdef CONFIG_CACHE_L2X0
@@ -113,7 +114,8 @@
MSM_DEVICE(AD5),
MSM_DEVICE(MDC),
MSM_DEVICE(TCSR),
-#ifdef CONFIG_MSM_DEBUG_UART
+#if defined(CONFIG_DEBUG_MSM_UART1) || defined(CONFIG_DEBUG_MSM_UART2) || \
+ defined(CONFIG_DEBUG_MSM_UART3)
MSM_DEVICE(DEBUG_UART),
#endif
{
@@ -151,7 +153,7 @@
MSM_DEVICE(TCSR),
MSM_DEVICE(IMEM),
MSM_DEVICE(HDMI),
-#ifdef CONFIG_MSM_DEBUG_UART
+#ifdef CONFIG_DEBUG_MSM8660_UART
MSM_DEVICE(DEBUG_UART),
#endif
MSM_DEVICE(SIC_NON_SECURE),
@@ -196,7 +198,7 @@
.length = MSM_SHARED_RAM_SIZE,
.type = MT_DEVICE,
},
-#ifdef CONFIG_MSM_DEBUG_UART
+#ifdef CONFIG_DEBUG_MSM8960_UART
MSM_DEVICE(DEBUG_UART),
#endif
MSM_CHIP_DEVICE(QFPROM, MSM8960),
@@ -235,7 +237,7 @@
.length = MSM_SHARED_RAM_SIZE,
.type = MT_DEVICE,
},
-#ifdef CONFIG_MSM_DEBUG_UART
+#ifdef CONFIG_DEBUG_MSM8930_UART
MSM_DEVICE(DEBUG_UART),
#endif
MSM_CHIP_DEVICE(QFPROM, MSM8930),
@@ -307,7 +309,8 @@
MSM_DEVICE(SAW),
MSM_DEVICE(GCC),
MSM_DEVICE(TCSR),
-#ifdef CONFIG_MSM_DEBUG_UART
+#if defined(CONFIG_DEBUG_MSM_UART1) || defined(CONFIG_DEBUG_MSM_UART2) || \
+ defined(CONFIG_DEBUG_MSM_UART3)
MSM_DEVICE(DEBUG_UART),
#endif
{
@@ -337,7 +340,8 @@
MSM_DEVICE(GRFC),
MSM_DEVICE(QFP_FUSE),
MSM_DEVICE(HH),
-#ifdef CONFIG_MSM_DEBUG_UART
+#if defined(CONFIG_DEBUG_MSM_UART1) || defined(CONFIG_DEBUG_MSM_UART2) || \
+ defined(CONFIG_DEBUG_MSM_UART3)
MSM_DEVICE(DEBUG_UART),
#endif
{
diff --git a/arch/arm/mach-msm/iommu.c b/arch/arm/mach-msm/iommu.c
index e874663..16c0790 100644
--- a/arch/arm/mach-msm/iommu.c
+++ b/arch/arm/mach-msm/iommu.c
@@ -38,6 +38,17 @@
#define RCP15_PRRR(reg) MRC(reg, p15, 0, c10, c2, 0)
#define RCP15_NMRR(reg) MRC(reg, p15, 0, c10, c2, 1)
+/* Sharability attributes of MSM IOMMU mappings */
+#define MSM_IOMMU_ATTR_NON_SH 0x0
+#define MSM_IOMMU_ATTR_SH 0x4
+
+/* Cacheability attributes of MSM IOMMU mappings */
+#define MSM_IOMMU_ATTR_NONCACHED 0x0
+#define MSM_IOMMU_ATTR_CACHED_WB_WA 0x1
+#define MSM_IOMMU_ATTR_CACHED_WB_NWA 0x2
+#define MSM_IOMMU_ATTR_CACHED_WT 0x3
+
+
static inline void clean_pte(unsigned long *start, unsigned long *end)
{
dmac_flush_range(start, end);
@@ -407,21 +418,23 @@
static int __get_pgprot(int prot, int len)
{
unsigned int pgprot;
- int tex, sh;
+ int tex;
- sh = (prot & MSM_IOMMU_ATTR_SH) ? 1 : 0;
- tex = msm_iommu_tex_class[prot & MSM_IOMMU_CP_MASK];
+ if (prot & IOMMU_CACHE)
+ tex = (pgprot_kernel >> 2) & 0x07;
+ else
+ tex = msm_iommu_tex_class[MSM_IOMMU_ATTR_NONCACHED];
if (tex < 0 || tex > NUM_TEX_CLASS - 1)
return 0;
if (len == SZ_16M || len == SZ_1M) {
- pgprot = sh ? FL_SHARED : 0;
+ pgprot = FL_SHARED;
pgprot |= tex & 0x01 ? FL_BUFFERABLE : 0;
pgprot |= tex & 0x02 ? FL_CACHEABLE : 0;
pgprot |= tex & 0x04 ? FL_TEX0 : 0;
} else {
- pgprot = sh ? SL_SHARED : 0;
+ pgprot = SL_SHARED;
pgprot |= tex & 0x01 ? SL_BUFFERABLE : 0;
pgprot |= tex & 0x02 ? SL_CACHEABLE : 0;
pgprot |= tex & 0x04 ? SL_TEX0 : 0;
diff --git a/arch/arm/mach-msm/iommu_dev.c b/arch/arm/mach-msm/iommu_dev.c
index d1dd3ed..1982082 100644
--- a/arch/arm/mach-msm/iommu_dev.c
+++ b/arch/arm/mach-msm/iommu_dev.c
@@ -24,7 +24,6 @@
#include <mach/iommu_hw-8xxx.h>
#include <mach/iommu.h>
-#include <mach/clk.h>
struct iommu_ctx_iter_data {
/* input */
@@ -164,8 +163,10 @@
iommu_clk = clk_get(&pdev->dev, "core_clk");
if (!IS_ERR(iommu_clk)) {
- if (clk_get_rate(iommu_clk) == 0)
- clk_set_min_rate(iommu_clk, 1);
+ if (clk_get_rate(iommu_clk) == 0) {
+ ret = clk_round_rate(iommu_clk, 1);
+ clk_set_rate(iommu_clk, ret);
+ }
ret = clk_enable(iommu_clk);
if (ret) {
diff --git a/arch/arm/mach-msm/lpass-8960.c b/arch/arm/mach-msm/lpass-8960.c
index 0f2559e..294e9c0 100644
--- a/arch/arm/mach-msm/lpass-8960.c
+++ b/arch/arm/mach-msm/lpass-8960.c
@@ -178,7 +178,7 @@
ret = -ENOMEM;
goto out;
}
- pr_info("%s: 8960 lpass SSR driver init'ed.\n", __func__);
+ pr_info("%s: lpass SSR driver init'ed.\n", __func__);
out:
return ret;
}
diff --git a/arch/arm/mach-msm/modem-8960.c b/arch/arm/mach-msm/modem-8960.c
index 7bcd844..f0aa13c 100644
--- a/arch/arm/mach-msm/modem-8960.c
+++ b/arch/arm/mach-msm/modem-8960.c
@@ -26,7 +26,6 @@
#include <mach/peripheral-loader.h>
#include <mach/subsystem_restart.h>
#include <mach/subsystem_notif.h>
-#include <mach/irqs-8960.h>
#include <mach/socinfo.h>
#include "smd_private.h"
@@ -227,7 +226,7 @@
{
int ret;
- if (!cpu_is_msm8960() && !cpu_is_msm8930())
+ if (!cpu_is_msm8960() && !cpu_is_msm8930() && !cpu_is_msm9615())
return -ENODEV;
ret = smsm_state_cb_register(SMSM_MODEM_STATE, SMSM_RESET,
@@ -266,7 +265,7 @@
ret = modem_debugfs_init();
- pr_info("%s: 8960 modem fatal driver init'ed.\n", __func__);
+ pr_info("%s: modem fatal driver init'ed.\n", __func__);
out:
return ret;
}
diff --git a/arch/arm/mach-msm/msm_bus/msm_bus_fabric.c b/arch/arm/mach-msm/msm_bus/msm_bus_fabric.c
index 1747425..fd82111 100644
--- a/arch/arm/mach-msm/msm_bus/msm_bus_fabric.c
+++ b/arch/arm/mach-msm/msm_bus/msm_bus_fabric.c
@@ -17,7 +17,6 @@
#include <linux/module.h>
#include <linux/clk.h>
#include <linux/radix-tree.h>
-#include <mach/clk.h>
#include <mach/board.h>
#include <mach/rpm.h>
#include "msm_bus_core.h"
@@ -344,7 +343,7 @@
int i, status = 0;
for (i = 0; i < NUM_CTX; i++)
if (info->nodeclk[i].dirty) {
- status = clk_set_min_rate(info->nodeclk[i].clk, info->
+ status = clk_set_rate(info->nodeclk[i].clk, info->
nodeclk[i].rate);
if (enable && !(info->nodeclk[i].enable)) {
clk_enable(info->nodeclk[i].clk);
@@ -359,7 +358,7 @@
}
if (info->memclk.dirty) {
- status = clk_set_min_rate(info->memclk.clk, info->memclk.rate);
+ status = clk_set_rate(info->memclk.clk, info->memclk.rate);
if (enable && !(info->memclk.enable)) {
clk_enable(info->memclk.clk);
info->memclk.dirty = false;
diff --git a/arch/arm/mach-msm/pm-8x60.c b/arch/arm/mach-msm/pm-8x60.c
index ad6da6a..cb5fcff 100644
--- a/arch/arm/mach-msm/pm-8x60.c
+++ b/arch/arm/mach-msm/pm-8x60.c
@@ -1111,6 +1111,7 @@
return 0;
}
etm_restore_reg_check();
+ msm_restore_jtag_debug();
#ifdef CONFIG_VFP
vfp_reinit();
#endif
diff --git a/arch/arm/mach-msm/qdsp5/adsp.c b/arch/arm/mach-msm/qdsp5/adsp.c
index d392cce..33c5a53 100644
--- a/arch/arm/mach-msm/qdsp5/adsp.c
+++ b/arch/arm/mach-msm/qdsp5/adsp.c
@@ -55,7 +55,6 @@
#include <linux/io.h>
#include <mach/msm_iomap.h>
-#include <mach/clk.h>
#include <mach/msm_adsp.h>
#include "adsp.h"
@@ -1018,7 +1017,7 @@
int adsp_set_clkrate(struct msm_adsp_module *module, unsigned long clk_rate)
{
if (module->clk && clk_rate)
- return clk_set_min_rate(module->clk, clk_rate);
+ return clk_set_rate(module->clk, clk_rate);
return -EINVAL;
}
@@ -1196,8 +1195,7 @@
else
mod->clk = NULL;
if (mod->clk && adsp_info.module[i].clk_rate)
- clk_set_min_rate(mod->clk,
- adsp_info.module[i].clk_rate);
+ clk_set_rate(mod->clk, adsp_info.module[i].clk_rate);
mod->verify_cmd = adsp_info.module[i].verify_cmd;
mod->patch_event = adsp_info.module[i].patch_event;
INIT_HLIST_HEAD(&mod->pmem_regions);
diff --git a/arch/arm/mach-msm/qdsp5v2/adsp.c b/arch/arm/mach-msm/qdsp5v2/adsp.c
index 6d4d074..b7b56c8 100644
--- a/arch/arm/mach-msm/qdsp5v2/adsp.c
+++ b/arch/arm/mach-msm/qdsp5v2/adsp.c
@@ -34,7 +34,6 @@
#include <linux/slab.h>
#include <linux/io.h>
#include <mach/msm_iomap.h>
-#include <mach/clk.h>
#include <mach/msm_adsp.h>
#include "adsp.h"
#include <mach/debug_mm.h>
@@ -851,7 +850,7 @@
int adsp_set_clkrate(struct msm_adsp_module *module, unsigned long clk_rate)
{
if (module->clk && clk_rate)
- return clk_set_min_rate(module->clk, clk_rate);
+ return clk_set_rate(module->clk, clk_rate);
return -EINVAL;
}
@@ -1015,8 +1014,7 @@
else
mod->clk = NULL;
if (mod->clk && adsp_info.module[i].clk_rate)
- clk_set_min_rate(mod->clk,
- adsp_info.module[i].clk_rate);
+ clk_set_rate(mod->clk, adsp_info.module[i].clk_rate);
mod->verify_cmd = adsp_info.module[i].verify_cmd;
mod->patch_event = adsp_info.module[i].patch_event;
INIT_HLIST_HEAD(&mod->pmem_regions);
diff --git a/arch/arm/mach-msm/qdsp6v2/apr.c b/arch/arm/mach-msm/qdsp6v2/apr.c
index 78f6519..13d92d1 100644
--- a/arch/arm/mach-msm/qdsp6v2/apr.c
+++ b/arch/arm/mach-msm/qdsp6v2/apr.c
@@ -266,23 +266,23 @@
if ((dest_id == APR_DEST_QDSP6) &&
(atomic_read(&dsp_state) == 0)) {
pr_info("%s: Wait for Lpass to bootup\n", __func__);
- rc = wait_event_interruptible(dsp_wait,
- (atomic_read(&dsp_state) == 1));
- if (rc < 0) {
+ rc = wait_event_interruptible_timeout(dsp_wait,
+ (atomic_read(&dsp_state) == 1), (1 * HZ));
+ if (rc == 0) {
pr_err("%s: DSP is not Up\n", __func__);
return NULL;
}
- pr_debug("%s: Lpass Up\n", __func__);
+ pr_info("%s: Lpass Up\n", __func__);
} else if ((dest_id == APR_DEST_MODEM) &&
(atomic_read(&modem_state) == 0)) {
pr_info("%s: Wait for modem to bootup\n", __func__);
- rc = wait_event_interruptible(modem_wait,
- (atomic_read(&modem_state) == 1));
- if (rc < 0) {
+ rc = wait_event_interruptible_timeout(modem_wait,
+ (atomic_read(&modem_state) == 1), (1 * HZ));
+ if (rc == 0) {
pr_err("%s: Modem is not Up\n", __func__);
return NULL;
}
- pr_debug("%s: modem Up\n", __func__);
+ pr_info("%s: modem Up\n", __func__);
}
if (!strcmp(svc_name, "AFE")) {
diff --git a/arch/arm/mach-msm/qdss-debug.c b/arch/arm/mach-msm/qdss-debug.c
new file mode 100644
index 0000000..b2d38b1
--- /dev/null
+++ b/arch/arm/mach-msm/qdss-debug.c
@@ -0,0 +1,285 @@
+/* Copyright (c) 2011, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/types.h>
+#include <linux/device.h>
+#include <linux/platform_device.h>
+#include <linux/io.h>
+#include <linux/err.h>
+#include <linux/slab.h>
+#include <linux/smp.h>
+
+#include "qdss.h"
+
+#define debug_writel(debug, cpu, val, off) \
+ __raw_writel((val), debug.base[cpu] + off)
+#define debug_readl(debug, cpu, off) \
+ __raw_readl(debug.base[cpu] + off)
+
+#define DBGDIDR (0x000)
+#define DBGWFAR (0x018)
+#define DBGVCR (0x01C)
+#define DBGECR (0x024)
+#define DBGDTRRX (0x080)
+#define DBGITR (0x084)
+#define DBGDSCR (0x088)
+#define DBGDTRTX (0x08C)
+#define DBGDRCR (0x090)
+#define DBGEACR (0x094)
+#define DBGPCSR (0x0A0)
+#define DBGCIDSR (0x0A4)
+#define DBGVIDSR (0x0A8)
+#define DBGBVRm(n) (0x100 + (n * 4))
+#define DBGBCRm(n) (0x140 + (n * 4))
+#define DBGWVRm(n) (0x180 + (n * 4))
+#define DBGWCRm(n) (0x1C0 + (n * 4))
+#define DBGBXVRm(n) (0x240 + (n * 4))
+#define DBGOSLAR (0x300)
+#define DBGOSLSR (0x304)
+#define DBGPRCR (0x310)
+#define DBGPRSR (0x314)
+
+
+#define DEBUG_LOCK(cpu) \
+do { \
+ mb(); \
+ debug_writel(debug, cpu, MAGIC2, CS_LAR); \
+} while (0)
+#define DEBUG_UNLOCK(cpu) \
+do { \
+ debug_writel(debug, cpu, MAGIC1, CS_LAR); \
+ mb(); \
+} while (0)
+
+#define DEBUG_OS_LOCK(cpu) \
+do { \
+ debug_writel(debug, cpu, MAGIC1, DBGOSLAR); \
+ mb(); \
+} while (0)
+#define DEBUG_OS_UNLOCK(cpu) \
+do { \
+ mb(); \
+ debug_writel(debug, cpu, MAGIC2, DBGOSLAR); \
+ mb(); \
+} while (0)
+
+#define MAX_DEBUG_REGS (90)
+#define MAX_STATE_SIZE (MAX_DEBUG_REGS * num_possible_cpus())
+#define DBGDSCR_MASK (0x6C30FC3C)
+
+struct debug_config {
+ /* read only config register */
+ uint32_t dbg_id;
+ /* derived values */
+ uint8_t nr_watch_pts;
+ uint8_t nr_brk_pts;
+ uint8_t nr_ctx_comp;
+};
+
+struct debug_ctx {
+ struct debug_config cfg;
+ void __iomem **base;
+ uint32_t *state;
+ struct device *dev;
+};
+
+static struct debug_ctx debug;
+
+static void debug_save_reg(int cpu)
+{
+ uint32_t i;
+ int j;
+
+ DEBUG_UNLOCK(cpu);
+ DEBUG_OS_LOCK(cpu);
+
+ i = cpu * MAX_DEBUG_REGS;
+
+ debug.state[i++] = debug_readl(debug, cpu, DBGWFAR);
+ for (j = 0; j < debug.cfg.nr_brk_pts; j++) {
+ debug.state[i++] = debug_readl(debug, cpu, DBGBCRm(j));
+ debug.state[i++] = debug_readl(debug, cpu, DBGBVRm(j));
+ }
+ for (j = 0; j < debug.cfg.nr_ctx_comp; j++)
+ debug.state[i++] = debug_readl(debug, cpu, DBGBXVRm(j));
+ for (j = 0; j < debug.cfg.nr_watch_pts; j++) {
+ debug.state[i++] = debug_readl(debug, cpu, DBGWVRm(j));
+ debug.state[i++] = debug_readl(debug, cpu, DBGWCRm(j));
+ }
+ debug.state[i++] = debug_readl(debug, cpu, DBGVCR);
+ debug.state[i++] = debug_readl(debug, cpu, CS_CLAIMSET);
+ debug.state[i++] = debug_readl(debug, cpu, CS_CLAIMCLR);
+ debug.state[i++] = debug_readl(debug, cpu, DBGDTRTX);
+ debug.state[i++] = debug_readl(debug, cpu, DBGDTRRX);
+ debug.state[i++] = debug_readl(debug, cpu, DBGDSCR);
+
+ DEBUG_LOCK(cpu);
+}
+
+static void debug_restore_reg(int cpu)
+{
+ uint32_t i;
+ int j;
+
+ DEBUG_UNLOCK(cpu);
+ DEBUG_OS_LOCK(cpu);
+
+ i = cpu * MAX_DEBUG_REGS;
+
+ debug_writel(debug, cpu, debug.state[i++], DBGWFAR);
+ for (j = 0; j < debug.cfg.nr_brk_pts; j++) {
+ debug_writel(debug, cpu, debug.state[i++], DBGBCRm(j));
+ debug_writel(debug, cpu, debug.state[i++], DBGBVRm(j));
+ }
+ for (j = 0; j < debug.cfg.nr_ctx_comp; j++)
+ debug_writel(debug, cpu, debug.state[i++], DBGBXVRm(j));
+ for (j = 0; j < debug.cfg.nr_watch_pts; j++) {
+ debug_writel(debug, cpu, debug.state[i++], DBGWVRm(j));
+ debug_writel(debug, cpu, debug.state[i++], DBGWCRm(j));
+ }
+ debug_writel(debug, cpu, debug.state[i++], DBGVCR);
+ debug_writel(debug, cpu, debug.state[i++], CS_CLAIMSET);
+ debug_writel(debug, cpu, debug.state[i++], CS_CLAIMCLR);
+ debug_writel(debug, cpu, debug.state[i++], DBGDTRTX);
+ debug_writel(debug, cpu, debug.state[i++], DBGDTRRX);
+ debug_writel(debug, cpu, debug.state[i++] & DBGDSCR_MASK, DBGDSCR);
+
+ DEBUG_OS_UNLOCK(cpu);
+ DEBUG_LOCK(cpu);
+}
+
+/* msm_save_jtag_debug and msm_restore_jtag_debug should be fast
+ *
+ * These functions will be called either from:
+ * 1. per_cpu idle thread context for idle power collapses.
+ * 2. per_cpu idle thread context for hotplug/suspend power collapse for
+ * nonboot cpus.
+ * 3. suspend thread context for core0.
+ *
+ * In all cases we are guaranteed to be running on the same cpu for the
+ * entire duration.
+ */
+void msm_save_jtag_debug(void)
+{
+ int cpu = smp_processor_id();
+ debug_save_reg(cpu);
+}
+
+void msm_restore_jtag_debug(void)
+{
+ int cpu = smp_processor_id();
+ debug_restore_reg(cpu);
+}
+
+static void debug_cfg_ro_init(void)
+{
+ /* use cpu 0 for setup */
+ int cpu = 0;
+
+ DEBUG_UNLOCK(cpu);
+
+ debug.cfg.dbg_id = debug_readl(debug, cpu, DBGDIDR);
+ debug.cfg.nr_ctx_comp = BMVAL(debug.cfg.dbg_id, 20, 23) + 1;
+ debug.cfg.nr_brk_pts = BMVAL(debug.cfg.dbg_id, 24, 27) + 1;
+ debug.cfg.nr_watch_pts = BMVAL(debug.cfg.dbg_id, 28, 31) + 1;
+
+ DEBUG_LOCK(cpu);
+}
+
+static int __devinit debug_probe(struct platform_device *pdev)
+{
+ int i, ret;
+ struct resource *res;
+
+ debug.base = kzalloc(pdev->num_resources * sizeof(void *), GFP_KERNEL);
+ if (!debug.base) {
+ ret = -ENOMEM;
+ goto err_base_kzalloc;
+ }
+
+ for (i = 0; i < pdev->num_resources; i++) {
+ res = platform_get_resource(pdev, IORESOURCE_MEM, i);
+ if (!res) {
+ ret = -EINVAL;
+ goto err_res;
+ }
+
+ debug.base[i] = ioremap_nocache(res->start, resource_size(res));
+ if (!debug.base[i]) {
+ ret = -EINVAL;
+ goto err_ioremap;
+ }
+ }
+
+ debug.dev = &pdev->dev;
+
+ debug.state = kzalloc(MAX_STATE_SIZE * sizeof(uint32_t), GFP_KERNEL);
+ if (!debug.state) {
+ ret = -ENOMEM;
+ goto err_state_kzalloc;
+ }
+
+ debug_cfg_ro_init();
+
+ dev_info(debug.dev, "Debug intialized.\n");
+
+ return 0;
+
+err_state_kzalloc:
+err_ioremap:
+err_res:
+ while (i) {
+ iounmap(debug.base[i-1]);
+ i--;
+ }
+ kfree(debug.base);
+err_base_kzalloc:
+ return ret;
+}
+
+static int __devexit debug_remove(struct platform_device *pdev)
+{
+ int i;
+
+ kfree(debug.state);
+ for (i = pdev->num_resources; i > 0; i--)
+ iounmap(debug.base[i-1]);
+ kfree(debug.base);
+
+ return 0;
+}
+
+static struct platform_driver debug_driver = {
+ .probe = debug_probe,
+ .remove = __devexit_p(debug_remove),
+ .driver = {
+ .name = "msm_debug",
+ },
+};
+
+static int __init debug_init(void)
+{
+ return platform_driver_register(&debug_driver);
+}
+module_init(debug_init);
+
+static void __exit debug_exit(void)
+{
+ platform_driver_unregister(&debug_driver);
+}
+module_exit(debug_exit);
+
+MODULE_LICENSE("GPL v2");
+MODULE_DESCRIPTION("Coresight Debug driver");
diff --git a/arch/arm/mach-msm/qdss-ptm.c b/arch/arm/mach-msm/qdss-ptm.c
index 4e8add7..0d971d7 100644
--- a/arch/arm/mach-msm/qdss-ptm.c
+++ b/arch/arm/mach-msm/qdss-ptm.c
@@ -119,6 +119,7 @@
} while (0)
#define PTM_OS_UNLOCK(cpu) \
do { \
+ mb(); \
ptm_writel(ptm, cpu, MAGIC2, ETMOSLAR); \
mb(); \
} while (0)
diff --git a/arch/arm/mach-msm/qdss.h b/arch/arm/mach-msm/qdss.h
index a41d7e2..8d346c4 100644
--- a/arch/arm/mach-msm/qdss.h
+++ b/arch/arm/mach-msm/qdss.h
@@ -56,6 +56,13 @@
void funnel_enable(uint8_t id, uint32_t port_mask);
void funnel_disable(uint8_t id, uint32_t port_mask);
+#ifdef CONFIG_MSM_DEBUG_ACROSS_PC
+extern void msm_save_jtag_debug(void);
+extern void msm_restore_jtag_debug(void);
+#else
+static inline void msm_save_jtag_debug(void) {}
+static inline void msm_restore_jtag_debug(void) {}
+#endif
#ifdef CONFIG_MSM_TRACE_ACROSS_PC
extern void etm_save_reg_check(void);
extern void etm_restore_reg_check(void);
diff --git a/arch/arm/mach-msm/ramdump.c b/arch/arm/mach-msm/ramdump.c
index 962371b..53128ad 100644
--- a/arch/arm/mach-msm/ramdump.c
+++ b/arch/arm/mach-msm/ramdump.c
@@ -198,8 +198,8 @@
return NULL;
}
- strncpy(rd_dev->name, "ramdump_", 256);
- strncat(rd_dev->name, dev_name, 256);
+ snprintf(rd_dev->name, ARRAY_SIZE(rd_dev->name), "ramdump_%s",
+ dev_name);
init_completion(&rd_dev->ramdump_complete);
diff --git a/arch/arm/mach-msm/restart.c b/arch/arm/mach-msm/restart.c
index 00be696..28bf064 100644
--- a/arch/arm/mach-msm/restart.c
+++ b/arch/arm/mach-msm/restart.c
@@ -120,11 +120,11 @@
#ifdef CONFIG_MSM_DLOAD_MODE
set_dload_mode(0);
#endif
- if (cpu_is_msm8x60()) {
- pm8058_reset_pwr_off(0);
- pm8901_reset_pwr_off(0);
- }
pm8xxx_reset_pwr_off(0);
+
+ if (cpu_is_msm8x60())
+ pm8901_reset_pwr_off(0);
+
if (lower_pshold) {
__raw_writel(0, PSHOLD_CTL_SU);
mdelay(10000);
@@ -202,8 +202,6 @@
printk(KERN_NOTICE "Going down for restart now\n");
- if (cpu_is_msm8x60())
- pm8058_reset_pwr_off(1);
pm8xxx_reset_pwr_off(1);
if (cmd != NULL) {
diff --git a/arch/arm/mach-msm/sdio_al.c b/arch/arm/mach-msm/sdio_al.c
index 891d655..356ce90 100644
--- a/arch/arm/mach-msm/sdio_al.c
+++ b/arch/arm/mach-msm/sdio_al.c
@@ -1223,7 +1223,7 @@
We need to keep reading mailbox to wait for the appropriate
write avail and cannot sleep. Ignore SMEM channel that has
only one direction. */
- if (strcmp(ch->name, "SDIO_SMEM"))
+ if (strncmp(ch->name, "SDIO_SMEM", CHANNEL_NAME_SIZE))
any_write_pending |=
(new_write_avail < ch->ch_config.max_tx_threshold);
}
@@ -2686,7 +2686,8 @@
if (sdio_al_dev->channel[i].state ==
SDIO_CHANNEL_STATE_INVALID)
continue;
- if (strcmp(sdio_al_dev->channel[i].name, name) == 0) {
+ if (strncmp(sdio_al_dev->channel[i].name, name,
+ CHANNEL_NAME_SIZE) == 0) {
ch = &sdio_al_dev->channel[i];
break;
}
diff --git a/arch/arm/mach-msm/subsystem_restart.c b/arch/arm/mach-msm/subsystem_restart.c
index 54607d0..37469f8 100644
--- a/arch/arm/mach-msm/subsystem_restart.c
+++ b/arch/arm/mach-msm/subsystem_restart.c
@@ -139,6 +139,11 @@
int ret;
int old_val = restart_level;
+ if (cpu_is_msm9615()) {
+ pr_err("Only Phase 1 subsystem restart is supported\n");
+ return -EINVAL;
+ }
+
ret = param_set_int(val, kp);
if (ret)
return ret;
@@ -571,7 +576,7 @@
n_restart_orders = ARRAY_SIZE(orders_8x60_all);
}
- if (cpu_is_msm8960() || cpu_is_msm8930()) {
+ if (cpu_is_msm8960() || cpu_is_msm8930() || cpu_is_msm9615()) {
restart_orders = restart_orders_8960;
n_restart_orders = ARRAY_SIZE(restart_orders_8960);
}
diff --git a/arch/arm/mach-msm/timer.c b/arch/arm/mach-msm/timer.c
index fd9049f..8f24d81 100644
--- a/arch/arm/mach-msm/timer.c
+++ b/arch/arm/mach-msm/timer.c
@@ -166,13 +166,6 @@
.regbase = MSM_TMR_BASE + 0x4,
.freq = 32768,
.index = MSM_CLOCK_GPT,
- .flags =
-#if defined(CONFIG_CPU_V6) || defined(CONFIG_ARCH_MSM7X27A)
- MSM_CLOCK_FLAGS_UNSTABLE_COUNT |
- MSM_CLOCK_FLAGS_ODD_MATCH_WRITE |
- MSM_CLOCK_FLAGS_DELAYED_WRITE_POST |
-#endif
- 0,
.write_delay = 9,
},
[MSM_CLOCK_DGT] = {
@@ -226,32 +219,32 @@
static uint32_t msm_read_timer_count(struct msm_clock *clock, int global)
{
- uint32_t t1, t2;
+ uint32_t t1, t2, t3;
int loop_count = 0;
-
- if (global)
- t1 = __raw_readl(clock->regbase + TIMER_COUNT_VAL +
- global_timer_offset);
- else
- t1 = __raw_readl(clock->regbase + TIMER_COUNT_VAL);
+ void __iomem *addr = clock->regbase + TIMER_COUNT_VAL +
+ global*global_timer_offset;
if (!(clock->flags & MSM_CLOCK_FLAGS_UNSTABLE_COUNT))
- return t1;
+ return __raw_readl(addr);
+
+ t1 = __raw_readl(addr);
+ t2 = __raw_readl(addr);
+ if ((t2-t1) <= 1)
+ return t2;
while (1) {
- if (global)
- t2 = __raw_readl(clock->regbase + TIMER_COUNT_VAL +
- global_timer_offset);
- else
- t2 = __raw_readl(clock->regbase + TIMER_COUNT_VAL);
- if (t1 == t2)
- return t1;
- if (loop_count++ > 10) {
- printk(KERN_ERR "msm_read_timer_count timer %s did not"
- "stabilize %u != %u\n", clock->clockevent.name,
- t2, t1);
+ t1 = __raw_readl(addr);
+ t2 = __raw_readl(addr);
+ t3 = __raw_readl(addr);
+ if ((t3-t2) <= 1)
+ return t3;
+ if ((t2-t1) <= 1)
return t2;
+ if (++loop_count == 10) {
+ pr_err("msm_read_timer_count timer %s did not "
+ "stabilize: %u -> %u -> %u\n",
+ clock->clockevent.name, t1, t2, t3);
+ return t3;
}
- t1 = t2;
}
}
@@ -994,6 +987,9 @@
dgt->clocksource.shift = 24 - MSM_DGT_SHIFT;
gpt->regbase = MSM_TMR_BASE;
dgt->regbase = MSM_TMR_BASE + 0x10;
+ gpt->flags |= MSM_CLOCK_FLAGS_UNSTABLE_COUNT
+ | MSM_CLOCK_FLAGS_ODD_MATCH_WRITE
+ | MSM_CLOCK_FLAGS_DELAYED_WRITE_POST;
} else if (cpu_is_qsd8x50()) {
dgt->freq = 4800000;
gpt->regbase = MSM_TMR_BASE;
@@ -1012,6 +1008,8 @@
gpt->freq = 32765;
gpt_hz = 32765;
sclk_hz = 32765;
+ gpt->flags |= MSM_CLOCK_FLAGS_UNSTABLE_COUNT;
+ dgt->flags |= MSM_CLOCK_FLAGS_UNSTABLE_COUNT;
} else if (cpu_is_msm8960() || cpu_is_apq8064() || cpu_is_msm8930()) {
global_timer_offset = MSM_TMR0_BASE - MSM_TMR_BASE;
dgt->freq = 6750000;
@@ -1019,6 +1017,8 @@
gpt->freq = 32765;
gpt_hz = 32765;
sclk_hz = 32765;
+ gpt->flags |= MSM_CLOCK_FLAGS_UNSTABLE_COUNT;
+ dgt->flags |= MSM_CLOCK_FLAGS_UNSTABLE_COUNT;
} else {
WARN_ON("Timer running on unknown hardware. Configure this! "
"Assuming default configuration.\n");
diff --git a/arch/arm/mm/proc-v7.S b/arch/arm/mm/proc-v7.S
index 5550d47..46729ee 100644
--- a/arch/arm/mm/proc-v7.S
+++ b/arch/arm/mm/proc-v7.S
@@ -294,11 +294,18 @@
*/
__v7_ca5mp_setup:
__v7_ca9mp_setup:
-#if defined(CONFIG_SMP)
- mrc p15, 0, r0, c1, c0, 1
+ mov r10, #(1 << 0) @ TLB ops broadcasting
+ b 1f
+__v7_ca15mp_setup:
+ mov r10, #0
+1:
+#ifdef CONFIG_SMP
+ ALT_SMP(mrc p15, 0, r0, c1, c0, 1)
+ ALT_UP(mov r0, #(1 << 6)) @ fake it for UP
tst r0, #(1 << 6) @ SMP/nAMP mode enabled?
- orreq r0, r0, #(1 << 6) | (1 << 0) @ Enable SMP/nAMP mode and
- mcreq p15, 0, r0, c1, c0, 1 @ TLB ops broadcasting
+ orreq r0, r0, #(1 << 6) @ Enable SMP/nAMP mode
+ orreq r0, r0, r10 @ Enable CPU-specific SMP bits
+ mcreq p15, 0, r0, c1, c0, 1
#endif
__v7_setup:
adr r12, __v7_setup_stack @ the local stack
@@ -526,6 +533,16 @@
__v7_proc __v7_ca9mp_setup
.size __v7_ca9mp_proc_info, . - __v7_ca9mp_proc_info
+ /*
+ * ARM Ltd. Cortex A15 processor.
+ */
+ .type __v7_ca15mp_proc_info, #object
+__v7_ca15mp_proc_info:
+ .long 0x410fc0f0
+ .long 0xff0ffff0
+ __v7_proc __v7_ca15mp_setup, hwcaps = HWCAP_IDIV
+ .size __v7_ca15mp_proc_info, . - __v7_ca15mp_proc_info
+
/*
* Match any ARMv7 processor core.
*/
diff --git a/arch/arm/vfp/vfpmodule.c b/arch/arm/vfp/vfpmodule.c
index 3554500..a8a8925 100644
--- a/arch/arm/vfp/vfpmodule.c
+++ b/arch/arm/vfp/vfpmodule.c
@@ -612,7 +612,6 @@
elf_hwcap |= HWCAP_VFPv3D16;
}
#endif
-#ifdef CONFIG_NEON
/*
* Check for the presence of the Advanced SIMD
* load/store instructions, integer and single
@@ -620,10 +619,13 @@
* for NEON if the hardware has the MVFR registers.
*/
if ((read_cpuid_id() & 0x000f0000) == 0x000f0000) {
+#ifdef CONFIG_NEON
if ((fmrx(MVFR1) & 0x000fff00) == 0x00011100)
elf_hwcap |= HWCAP_NEON;
- }
#endif
+ if ((fmrx(MVFR1) & 0xf0000000) == 0x10000000)
+ elf_hwcap |= HWCAP_VFPv4;
+ }
}
return 0;
}
diff --git a/drivers/gpio/pm8xxx-gpio.c b/drivers/gpio/pm8xxx-gpio.c
index 377510f..53305e3 100644
--- a/drivers/gpio/pm8xxx-gpio.c
+++ b/drivers/gpio/pm8xxx-gpio.c
@@ -432,7 +432,7 @@
return rc;
}
-EXPORT_SYMBOL_GPL(pm8xxx_gpio_config);
+EXPORT_SYMBOL(pm8xxx_gpio_config);
static struct platform_driver pm_gpio_driver = {
.probe = pm_gpio_probe,
diff --git a/drivers/gpu/ion/ion.c b/drivers/gpu/ion/ion.c
index 60bc276..50420ba 100644
--- a/drivers/gpu/ion/ion.c
+++ b/drivers/gpu/ion/ion.c
@@ -618,7 +618,6 @@
unsigned int cmd)
{
struct ion_buffer *buffer;
- unsigned long start, end;
int ret = -EINVAL;
mutex_lock(&client->lock);
@@ -643,14 +642,6 @@
goto out;
}
- start = (unsigned long) uaddr;
- end = (unsigned long) uaddr + len;
-
- if (check_vaddr_bounds(start, end)) {
- pr_err("%s: virtual address %p is out of bounds\n",
- __func__, uaddr);
- goto out;
- }
ret = buffer->heap->ops->cache_op(buffer->heap, buffer, uaddr,
offset, len, cmd);
@@ -1102,6 +1093,10 @@
return -EFAULT;
data.handle = ion_alloc(client, data.len, data.align,
data.flags);
+
+ if (IS_ERR_OR_NULL(data.handle))
+ return PTR_ERR(data.handle);
+
if (copy_to_user((void __user *)arg, &data, sizeof(data)))
return -EFAULT;
break;
@@ -1174,11 +1169,21 @@
case ION_IOC_CLEAN_INV_CACHES:
{
struct ion_flush_data data;
+ unsigned long start, end;
if (copy_from_user(&data, (void __user *)arg,
sizeof(struct ion_flush_data)))
return -EFAULT;
+ start = (unsigned long) data.vaddr;
+ end = (unsigned long) data.vaddr + data.length;
+
+ if (check_vaddr_bounds(start, end)) {
+ pr_err("%s: virtual address %p is out of bounds\n",
+ __func__, data.vaddr);
+ return -EINVAL;
+ }
+
return ion_do_cache_op(client, data.handle, data.vaddr,
data.offset, data.length, cmd);
diff --git a/drivers/gpu/msm/kgsl_iommu.c b/drivers/gpu/msm/kgsl_iommu.c
index 30365a3..e4e561c 100644
--- a/drivers/gpu/msm/kgsl_iommu.c
+++ b/drivers/gpu/msm/kgsl_iommu.c
@@ -262,12 +262,12 @@
iommu_virt_addr = memdesc->gpuaddr;
ret = iommu_map_range(domain, iommu_virt_addr, memdesc->sg,
- memdesc->size, MSM_IOMMU_ATTR_NONCACHED);
+ memdesc->size, 0);
if (ret) {
KGSL_CORE_ERR("iommu_map_range(%p, %x, %p, %d, %d) "
"failed with err: %d\n", domain,
iommu_virt_addr, memdesc->sg, memdesc->size,
- MSM_IOMMU_ATTR_NONCACHED, ret);
+ 0, ret);
return ret;
}
diff --git a/drivers/input/keyboard/Kconfig b/drivers/input/keyboard/Kconfig
index 0822866..6db0da1 100644
--- a/drivers/input/keyboard/Kconfig
+++ b/drivers/input/keyboard/Kconfig
@@ -401,17 +401,6 @@
Say Y here to enable the driver for the keypad matrix interface
on the Qualcomm PM8058 power management I/C device.
-config KEYBOARD_PMIC8XXX
- tristate "Qualcomm PMIC8XXX keypad support"
- depends on MFD_PM8XXX
- help
- Say Y here if you want to enable the driver for the PMIC8XXX
- keypad provided as a reference design from Qualcomm. This is intended
- to support upto 18x8 matrix based keypad design.
-
- To compile this driver as a module, choose M here: the module will
- be called pmic8xxx-keypad.
-
config KEYBOARD_PXA27x
tristate "PXA27x/PXA3xx keypad support"
depends on PXA27x || PXA3xx || ARCH_MMP
diff --git a/drivers/input/misc/pmic8058-othc.c b/drivers/input/misc/pmic8058-othc.c
index c6be119..a28e8e1 100644
--- a/drivers/input/misc/pmic8058-othc.c
+++ b/drivers/input/misc/pmic8058-othc.c
@@ -27,7 +27,7 @@
#include <linux/delay.h>
#include <linux/regulator/consumer.h>
-#include <linux/mfd/pmic8058.h>
+#include <linux/mfd/pm8xxx/core.h>
#include <linux/pmic8058-othc.h>
#include <linux/msm_adc.h>
@@ -68,6 +68,7 @@
void *adc_handle;
void *accessory_adc_handle;
spinlock_t lock;
+ struct device *dev;
struct regulator *othc_vreg;
struct input_dev *othc_ipd;
struct switch_dev othc_sdev;
@@ -75,7 +76,6 @@
struct othc_accessory_info *accessory_info;
struct hrtimer timer;
struct othc_n_switch_config *switch_config;
- struct pm8058_chip *pm_chip;
struct work_struct switch_work;
struct delayed_work detect_work;
struct delayed_work hs_work;
@@ -149,7 +149,7 @@
return -EINVAL;
}
- rc = pm8058_read(dd->pm_chip, dd->othc_base + 1, ®, 1);
+ rc = pm8xxx_readb(dd->dev->parent, dd->othc_base + 1, ®);
if (rc < 0) {
pr_err("PM8058 read failed\n");
return rc;
@@ -158,7 +158,7 @@
reg &= PM8058_OTHC_EN_SIG_MASK;
reg |= (enable << PM8058_OTHC_EN_SIG_SHIFT);
- rc = pm8058_write(dd->pm_chip, dd->othc_base + 1, ®, 1);
+ rc = pm8xxx_writeb(dd->dev->parent, dd->othc_base + 1, reg);
if (rc < 0) {
pr_err("PM8058 write failed\n");
return rc;
@@ -446,7 +446,7 @@
if (dd->ir_gpio < 0) {
/* Check the MIC_BIAS status */
- rc = pm8058_irq_get_rt_status(dd->pm_chip, dd->othc_irq_ir);
+ rc = pm8xxx_read_irq_stat(dd->dev->parent, dd->othc_irq_ir);
if (rc < 0) {
pr_err("Unable to read IR status from PMIC\n");
goto fail_ir_accessory;
@@ -462,7 +462,7 @@
}
/* Check the switch status */
- rc = pm8058_irq_get_rt_status(dd->pm_chip, dd->othc_irq_sw);
+ rc = pm8xxx_read_irq_stat(dd->dev->parent, dd->othc_irq_sw);
if (rc < 0) {
pr_err("Unable to read SWITCH status\n");
goto fail_ir_accessory;
@@ -576,7 +576,7 @@
}
spin_unlock_irqrestore(&dd->lock, flags);
- level = pm8058_irq_get_rt_status(dd->pm_chip, dd->othc_irq_sw);
+ level = pm8xxx_read_irq_stat(dd->dev->parent, dd->othc_irq_sw);
if (level < 0) {
pr_err("Unable to read IRQ status register\n");
return IRQ_HANDLED;
@@ -641,7 +641,7 @@
disable_irq_nosync(dd->othc_irq_ir);
/* Check the MIC_BIAS status, to check if inserted or removed */
- rc = pm8058_irq_get_rt_status(dd->pm_chip, dd->othc_irq_ir);
+ rc = pm8xxx_read_irq_stat(dd->dev->parent, dd->othc_irq_ir);
if (rc < 0) {
pr_err("Unable to read IR status\n");
goto fail_ir;
@@ -666,7 +666,7 @@
/* Intialize the OTHC module */
/* Control Register 1*/
- rc = pm8058_read(dd->pm_chip, base_addr, ®, 1);
+ rc = pm8xxx_readb(dd->dev->parent, base_addr, ®);
if (rc < 0) {
pr_err("PM8058 read failed\n");
return rc;
@@ -676,14 +676,14 @@
value = (hsed_config->othc_highcurr_thresh_uA / 100) - 2;
reg = (reg & PM8058_OTHC_HIGH_CURR_MASK) | value;
- rc = pm8058_write(dd->pm_chip, base_addr, ®, 1);
+ rc = pm8xxx_writeb(dd->dev->parent, base_addr, reg);
if (rc < 0) {
pr_err("PM8058 read failed\n");
return rc;
}
/* Control register 2*/
- rc = pm8058_read(dd->pm_chip, base_addr + 1, ®, 1);
+ rc = pm8xxx_readb(dd->dev->parent, base_addr + 1, ®);
if (rc < 0) {
pr_err("PM8058 read failed\n");
return rc;
@@ -718,14 +718,14 @@
}
reg = (reg & PM8058_OTHC_CLK_PREDIV_MASK) | (value - 1);
- rc = pm8058_write(dd->pm_chip, base_addr + 1, ®, 1);
+ rc = pm8xxx_writeb(dd->dev->parent, base_addr + 1, reg);
if (rc < 0) {
pr_err("PM8058 read failed\n");
return rc;
}
/* Control register 3 */
- rc = pm8058_read(dd->pm_chip, base_addr + 2 , ®, 1);
+ rc = pm8xxx_readb(dd->dev->parent, base_addr + 2 , ®);
if (rc < 0) {
pr_err("PM8058 read failed\n");
return rc;
@@ -748,7 +748,7 @@
}
reg = (reg & PM8058_OTHC_PERIOD_CLK_MASK) | value;
- rc = pm8058_write(dd->pm_chip, base_addr + 2, ®, 1);
+ rc = pm8xxx_writeb(dd->dev->parent, base_addr + 2, reg);
if (rc < 0) {
pr_err("PM8058 read failed\n");
return rc;
@@ -1006,7 +1006,7 @@
/* Check if the accessory is already inserted during boot up */
if (dd->ir_gpio < 0) {
- rc = pm8058_irq_get_rt_status(dd->pm_chip, dd->othc_irq_ir);
+ rc = pm8xxx_read_irq_stat(dd->dev->parent, dd->othc_irq_ir);
if (rc < 0) {
pr_err("Unable to get accessory status at boot\n");
goto fail_ir_status;
@@ -1061,22 +1061,9 @@
{
int rc;
struct pm8058_othc *dd;
- struct pm8058_chip *chip;
struct resource *res;
struct pmic8058_othc_config_pdata *pdata = pd->dev.platform_data;
- chip = dev_get_drvdata(pd->dev.parent);
- if (chip == NULL) {
- pr_err("Invalid driver information\n");
- return -EINVAL;
- }
-
- /* Check PMIC8058 version. A0 version is not supported */
- if (pm8058_rev(chip) == PM_8058_REV_1p0) {
- pr_err("PMIC8058 version not supported\n");
- return -ENODEV;
- }
-
if (pdata == NULL) {
pr_err("Platform data not present\n");
return -EINVAL;
@@ -1101,8 +1088,8 @@
goto fail_get_res;
}
+ dd->dev = &pd->dev;
dd->othc_pdata = pdata;
- dd->pm_chip = chip;
dd->othc_base = res->start;
if (pdata->micbias_regulator == NULL) {
pr_err("OTHC regulator not specified\n");
diff --git a/drivers/input/touchscreen/cy8c_ts.c b/drivers/input/touchscreen/cy8c_ts.c
index ac4138e..f708582 100644
--- a/drivers/input/touchscreen/cy8c_ts.c
+++ b/drivers/input/touchscreen/cy8c_ts.c
@@ -197,8 +197,7 @@
input_report_abs(ts->input, ABS_MT_TRACKING_ID, id);
input_report_abs(ts->input, ABS_MT_POSITION_X, x);
input_report_abs(ts->input, ABS_MT_POSITION_Y, y);
- input_report_abs(ts->input, ABS_MT_TOUCH_MAJOR, pressure);
- input_report_abs(ts->input, ABS_MT_WIDTH_MAJOR, ts->dd->finger_size);
+ input_report_abs(ts->input, ABS_MT_PRESSURE, pressure);
input_mt_sync(ts->input);
}
@@ -227,8 +226,7 @@
}
for (i = 0; i < ts->prev_touches - touches; i++) {
- input_report_abs(ts->input, ABS_MT_TOUCH_MAJOR, 0);
- input_report_abs(ts->input, ABS_MT_WIDTH_MAJOR, 0);
+ input_report_abs(ts->input, ABS_MT_PRESSURE, 0);
input_mt_sync(ts->input);
}
@@ -263,8 +261,7 @@
}
} else {
for (i = 0; i < ts->prev_touches; i++) {
- input_report_abs(ts->input, ABS_MT_TOUCH_MAJOR, 0);
- input_report_abs(ts->input, ABS_MT_WIDTH_MAJOR, 0);
+ input_report_abs(ts->input, ABS_MT_PRESSURE, 0);
input_mt_sync(ts->input);
}
}
@@ -402,10 +399,8 @@
ts->pdata->dis_min_x, ts->pdata->dis_max_x, 0, 0);
input_set_abs_params(input_device, ABS_MT_POSITION_Y,
ts->pdata->dis_min_y, ts->pdata->dis_max_y, 0, 0);
- input_set_abs_params(input_device, ABS_MT_TOUCH_MAJOR,
+ input_set_abs_params(input_device, ABS_MT_PRESSURE,
ts->pdata->min_touch, ts->pdata->max_touch, 0, 0);
- input_set_abs_params(input_device, ABS_MT_WIDTH_MAJOR,
- ts->pdata->min_width, ts->pdata->max_width, 0, 0);
input_set_abs_params(input_device, ABS_MT_TRACKING_ID,
ts->pdata->min_tid, ts->pdata->max_tid, 0, 0);
diff --git a/drivers/leds/leds-pmic8058.c b/drivers/leds/leds-pmic8058.c
index d1aed3f..3b3a24a 100644
--- a/drivers/leds/leds-pmic8058.c
+++ b/drivers/leds/leds-pmic8058.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2010, Code Aurora Forum. All rights reserved.
+/* Copyright (c) 2010, 2011, Code Aurora Forum. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -15,7 +15,7 @@
#include <linux/leds.h>
#include <linux/workqueue.h>
#include <linux/spinlock.h>
-#include <linux/mfd/pmic8058.h>
+#include <linux/mfd/pm8xxx/core.h>
#include <linux/leds-pmic8058.h>
#define SSBI_REG_ADDR_DRV_KEYPAD 0x48
@@ -41,11 +41,11 @@
#define PMIC8058_LED_OFFSET(id) ((id) - PMIC8058_ID_LED_0)
struct pmic8058_led_data {
+ struct device *dev;
struct led_classdev cdev;
int id;
enum led_brightness brightness;
u8 flags;
- struct pm8058_chip *pm_chip;
struct work_struct work;
struct mutex lock;
spinlock_t value_lock;
@@ -72,8 +72,8 @@
led->reg_kp |= level;
spin_unlock_irqrestore(&led->value_lock, flags);
- rc = pm8058_write(led->pm_chip, SSBI_REG_ADDR_DRV_KEYPAD,
- &led->reg_kp, 1);
+ rc = pm8xxx_writeb(led->dev->parent, SSBI_REG_ADDR_DRV_KEYPAD,
+ led->reg_kp);
if (rc)
pr_err("%s: can't set keypad backlight level\n", __func__);
}
@@ -105,8 +105,8 @@
tmp |= level;
spin_unlock_irqrestore(&led->value_lock, flags);
- rc = pm8058_write(led->pm_chip, SSBI_REG_ADDR_LED_CTRL(offset),
- &tmp, 1);
+ rc = pm8xxx_writeb(led->dev->parent, SSBI_REG_ADDR_LED_CTRL(offset),
+ tmp);
if (rc) {
dev_err(led->cdev.dev, "can't set (%d) led value\n",
led->id);
@@ -159,7 +159,7 @@
}
spin_unlock_irqrestore(&led->value_lock, flags);
- rc = pm8058_write(led->pm_chip, reg_addr, ®_flash_led, 1);
+ rc = pm8xxx_writeb(led->dev->parent, reg_addr, reg_flash_led);
if (rc)
pr_err("%s: can't set flash led%d level %d\n", __func__,
led->id, rc);
@@ -294,46 +294,38 @@
struct pmic8058_led_data *led_dat;
struct pmic8058_led *curr_led;
int rc, i = 0;
- struct pm8058_chip *pm_chip;
u8 reg_kp;
u8 reg_led_ctrl[3];
u8 reg_flash_led0;
u8 reg_flash_led1;
- pm_chip = dev_get_drvdata(pdev->dev.parent);
- if (pm_chip == NULL) {
- dev_err(&pdev->dev, "no parent data passed in\n");
- return -EFAULT;
- }
-
if (pdata == NULL) {
dev_err(&pdev->dev, "platform data not supplied\n");
return -EINVAL;
}
- rc = pm8058_read(pm_chip, SSBI_REG_ADDR_DRV_KEYPAD, ®_kp,
- 1);
+ rc = pm8xxx_readb(pdev->dev.parent, SSBI_REG_ADDR_DRV_KEYPAD, ®_kp);
if (rc) {
dev_err(&pdev->dev, "can't get keypad backlight level\n");
goto err_reg_read;
}
- rc = pm8058_read(pm_chip, SSBI_REG_ADDR_LED_CTRL_BASE,
- reg_led_ctrl, 3);
+ rc = pm8xxx_read_buf(pdev->dev.parent, SSBI_REG_ADDR_LED_CTRL_BASE,
+ reg_led_ctrl, 3);
if (rc) {
dev_err(&pdev->dev, "can't get led levels\n");
goto err_reg_read;
}
- rc = pm8058_read(pm_chip, SSBI_REG_ADDR_FLASH_DRV0,
- ®_flash_led0, 1);
+ rc = pm8xxx_readb(pdev->dev.parent, SSBI_REG_ADDR_FLASH_DRV0,
+ ®_flash_led0);
if (rc) {
dev_err(&pdev->dev, "can't read flash led0\n");
goto err_reg_read;
}
- rc = pm8058_read(pm_chip, SSBI_REG_ADDR_FLASH_DRV1,
- ®_flash_led1, 1);
+ rc = pm8xxx_readb(pdev->dev.parent, SSBI_REG_ADDR_FLASH_DRV1,
+ ®_flash_led1);
if (rc) {
dev_err(&pdev->dev, "can't get flash led1\n");
goto err_reg_read;
@@ -366,7 +358,7 @@
goto fail_id_check;
}
- led_dat->pm_chip = pm_chip;
+ led_dat->dev = &pdev->dev;
mutex_init(&led_dat->lock);
spin_lock_init(&led_dat->value_lock);
diff --git a/drivers/media/video/msm/Makefile b/drivers/media/video/msm/Makefile
index 59c4cab..a6b7f48 100644
--- a/drivers/media/video/msm/Makefile
+++ b/drivers/media/video/msm/Makefile
@@ -4,8 +4,9 @@
endif
ifeq ($(CONFIG_MSM_CAMERA_V4L2),y)
+ EXTRA_CFLAGS += -Idrivers/media/video/msm/csi
obj-$(CONFIG_MSM_CAMERA) += msm_isp.o msm.o msm_mem.o msm_mctl.o msm_mctl_buf.o msm_mctl_pp.o
- obj-$(CONFIG_MSM_CAMERA) += io/ sensors/ actuators/
+ obj-$(CONFIG_MSM_CAMERA) += io/ sensors/ actuators/ csi/
else
obj-$(CONFIG_MSM_CAMERA) += msm_camera.o
endif
@@ -16,7 +17,7 @@
obj-$(CONFIG_ARCH_MSM7X30) += msm_vfe31.o msm_io_vfe31.o msm_vpe1.o
obj-$(CONFIG_ARCH_QSD8X50) += msm_vfe8x.o msm_vfe8x_proc.o msm_io8x.o
obj-$(CONFIG_ARCH_MSM8X60) += msm_vfe31.o msm_io_8x60.o msm_vpe1.o
-obj-$(CONFIG_ARCH_MSM8960) += msm_io_8960.o msm_ispif.o msm_vfe32.o msm_vpe.o
+obj-$(CONFIG_ARCH_MSM8960) += msm_io_8960.o msm_vfe32.o msm_vpe.o
obj-$(CONFIG_MT9T013) += mt9t013.o mt9t013_reg.o
obj-$(CONFIG_SN12M0PZ) += sn12m0pz.o sn12m0pz_reg.o
obj-$(CONFIG_MT9P012) += mt9p012_reg.o
diff --git a/drivers/media/video/msm/csi/Makefile b/drivers/media/video/msm/csi/Makefile
new file mode 100644
index 0000000..3ce81af
--- /dev/null
+++ b/drivers/media/video/msm/csi/Makefile
@@ -0,0 +1,3 @@
+GCC_VERSION := $(shell $(CONFIG_SHELL) $(PWD)/scripts/gcc-version.sh $(CROSS_COMPILE)gcc)
+EXTRA_CFLAGS += -Idrivers/media/video/msm
+obj-$(CONFIG_ARCH_MSM8960) += msm_csiphy.o msm_csid.o msm_ispif.o
diff --git a/drivers/media/video/msm/csi/msm_csid.c b/drivers/media/video/msm/csi/msm_csid.c
new file mode 100644
index 0000000..fb809c9
--- /dev/null
+++ b/drivers/media/video/msm/csi/msm_csid.c
@@ -0,0 +1,306 @@
+/* Copyright (c) 2011, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/delay.h>
+#include <linux/clk.h>
+#include <linux/io.h>
+#include <mach/board.h>
+#include <mach/camera.h>
+#include <media/msm_isp.h>
+#include "msm_csid.h"
+#include "msm.h"
+
+#define V4L2_IDENT_CSID 50002
+
+/* MIPI CSID registers */
+#define CSID_HW_VERSION_ADDR 0x0
+#define CSID_CORE_CTRL_ADDR 0x4
+#define CSID_RST_CMD_ADDR 0x8
+#define CSID_CID_LUT_VC_0_ADDR 0xc
+#define CSID_CID_LUT_VC_1_ADDR 0x10
+#define CSID_CID_LUT_VC_2_ADDR 0x14
+#define CSID_CID_LUT_VC_3_ADDR 0x18
+#define CSID_CID_n_CFG_ADDR 0x1C
+#define CSID_IRQ_CLEAR_CMD_ADDR 0x5c
+#define CSID_IRQ_MASK_ADDR 0x60
+#define CSID_IRQ_STATUS_ADDR 0x64
+#define CSID_CAPTURED_UNMAPPED_LONG_PKT_HDR_ADDR 0x68
+#define CSID_CAPTURED_MMAPPED_LONG_PKT_HDR_ADDR 0x6c
+#define CSID_CAPTURED_SHORT_PKT_ADDR 0x70
+#define CSID_CAPTURED_LONG_PKT_HDR_ADDR 0x74
+#define CSID_CAPTURED_LONG_PKT_FTR_ADDR 0x78
+#define CSID_PIF_MISR_DL0_ADDR 0x7C
+#define CSID_PIF_MISR_DL1_ADDR 0x80
+#define CSID_PIF_MISR_DL2_ADDR 0x84
+#define CSID_PIF_MISR_DL3_ADDR 0x88
+#define CSID_STATS_TOTAL_PKTS_RCVD_ADDR 0x8C
+#define CSID_STATS_ECC_ADDR 0x90
+#define CSID_STATS_CRC_ADDR 0x94
+#define CSID_TG_CTRL_ADDR 0x9C
+#define CSID_TG_VC_CFG_ADDR 0xA0
+#define CSID_TG_DT_n_CFG_0_ADDR 0xA8
+#define CSID_TG_DT_n_CFG_1_ADDR 0xAC
+#define CSID_TG_DT_n_CFG_2_ADDR 0xB0
+#define CSID_TG_DT_n_CFG_3_ADDR 0xD8
+
+#define DBG_CSID 0
+
+static int msm_csid_cid_lut(
+ struct msm_camera_csid_lut_params *csid_lut_params,
+ void __iomem *csidbase)
+{
+ int rc = 0, i = 0;
+ uint32_t val = 0;
+
+ for (i = 0; i < csid_lut_params->num_cid && i < 4; i++) {
+ if (csid_lut_params->vc_cfg[i].dt < 0x12 ||
+ csid_lut_params->vc_cfg[i].dt > 0x37) {
+ CDBG("%s: unsupported data type 0x%x\n",
+ __func__, csid_lut_params->vc_cfg[i].dt);
+ return rc;
+ }
+ val = msm_io_r(csidbase + CSID_CID_LUT_VC_0_ADDR +
+ (csid_lut_params->vc_cfg[i].cid >> 2) * 4)
+ & ~(0xFF << csid_lut_params->vc_cfg[i].cid * 8);
+ val |= csid_lut_params->vc_cfg[i].dt <<
+ csid_lut_params->vc_cfg[i].cid * 8;
+ msm_io_w(val, csidbase + CSID_CID_LUT_VC_0_ADDR +
+ (csid_lut_params->vc_cfg[i].cid >> 2) * 4);
+ val = csid_lut_params->vc_cfg[i].decode_format << 4 | 0x3;
+ msm_io_w(val, csidbase + CSID_CID_n_CFG_ADDR +
+ (csid_lut_params->vc_cfg[i].cid * 4));
+ }
+ return rc;
+}
+
+static int msm_csid_config(struct csid_cfg_params *cfg_params)
+{
+ int rc = 0;
+ uint32_t val = 0;
+ struct csid_device *csid_dev;
+ struct msm_camera_csid_params *csid_params;
+ void __iomem *csidbase;
+ csid_dev = v4l2_get_subdevdata(cfg_params->subdev);
+ csidbase = csid_dev->base;
+ csid_params = cfg_params->parms;
+ val = csid_params->lane_cnt - 1;
+ val |= csid_params->lane_assign << 2;
+ val |= 0x1 << 10;
+ val |= 0x1 << 11;
+ val |= 0x1 << 12;
+ val |= 0x1 << 28;
+ msm_io_w(val, csidbase + CSID_CORE_CTRL_ADDR);
+
+ rc = msm_csid_cid_lut(&csid_params->lut_params, csidbase);
+ if (rc < 0)
+ return rc;
+
+ msm_io_w(0x7fF10800, csidbase + CSID_IRQ_MASK_ADDR);
+ msm_io_w(0x7fF10800, csidbase + CSID_IRQ_CLEAR_CMD_ADDR);
+
+ msleep(20);
+ return rc;
+}
+
+static irqreturn_t msm_csid_irq(int irq_num, void *data)
+{
+ uint32_t irq;
+ struct csid_device *csid_dev = data;
+ irq = msm_io_r(csid_dev->base + CSID_IRQ_STATUS_ADDR);
+ CDBG("%s CSID_IRQ_STATUS_ADDR = 0x%x\n", __func__, irq);
+ msm_io_w(irq, csid_dev->base + CSID_IRQ_CLEAR_CMD_ADDR);
+ return IRQ_HANDLED;
+}
+
+static int msm_csid_subdev_g_chip_ident(struct v4l2_subdev *sd,
+ struct v4l2_dbg_chip_ident *chip)
+{
+ BUG_ON(!chip);
+ chip->ident = V4L2_IDENT_CSID;
+ chip->revision = 0;
+ return 0;
+}
+
+static struct msm_cam_clk_info csid_clk_info[] = {
+ {"csi_src_clk", 177780000},
+ {"csi_clk", -1},
+ {"csi_phy_clk", -1},
+ {"csi_pclk", -1},
+};
+
+static int msm_csid_init(struct v4l2_subdev *sd, uint32_t *csid_version)
+{
+ int rc = 0;
+ struct csid_device *csid_dev;
+ csid_dev = v4l2_get_subdevdata(sd);
+ if (csid_dev == NULL) {
+ rc = -ENOMEM;
+ return rc;
+ }
+
+ csid_dev->base = ioremap(csid_dev->mem->start,
+ resource_size(csid_dev->mem));
+ if (!csid_dev->base) {
+ rc = -ENOMEM;
+ return rc;
+ }
+
+ rc = msm_cam_clk_enable(&csid_dev->pdev->dev, csid_clk_info,
+ csid_dev->csid_clk, ARRAY_SIZE(csid_clk_info), 1);
+ if (rc < 0) {
+ iounmap(csid_dev->base);
+ return rc;
+ }
+
+#if DBG_CSID
+ enable_irq(csid_dev->irq->start);
+#endif
+
+ *csid_version = csid_dev->hw_version;
+
+ return 0;
+}
+
+static int msm_csid_release(struct v4l2_subdev *sd)
+{
+ struct csid_device *csid_dev;
+ csid_dev = v4l2_get_subdevdata(sd);
+
+#if DBG_CSID
+ disable_irq(csid_dev->irq->start);
+#endif
+
+ msm_cam_clk_enable(&csid_dev->pdev->dev, csid_clk_info,
+ csid_dev->csid_clk, ARRAY_SIZE(csid_clk_info), 0);
+
+ iounmap(csid_dev->base);
+ return 0;
+}
+
+static long msm_csid_subdev_ioctl(struct v4l2_subdev *sd,
+ unsigned int cmd, void *arg)
+{
+ struct csid_cfg_params cfg_params;
+ switch (cmd) {
+ case VIDIOC_MSM_CSID_CFG:
+ cfg_params.subdev = sd;
+ cfg_params.parms = arg;
+ return msm_csid_config((struct csid_cfg_params *)&cfg_params);
+ case VIDIOC_MSM_CSID_INIT:
+ return msm_csid_init(sd, (uint32_t *)arg);
+ case VIDIOC_MSM_CSID_RELEASE:
+ return msm_csid_release(sd);
+ default:
+ return -ENOIOCTLCMD;
+ }
+}
+
+static struct v4l2_subdev_core_ops msm_csid_subdev_core_ops = {
+ .g_chip_ident = &msm_csid_subdev_g_chip_ident,
+ .ioctl = &msm_csid_subdev_ioctl,
+};
+
+static const struct v4l2_subdev_ops msm_csid_subdev_ops = {
+ .core = &msm_csid_subdev_core_ops,
+};
+
+static int __devinit csid_probe(struct platform_device *pdev)
+{
+ struct csid_device *new_csid_dev;
+ int rc = 0;
+ CDBG("%s: device id = %d\n", __func__, pdev->id);
+ new_csid_dev = kzalloc(sizeof(struct csid_device), GFP_KERNEL);
+ if (!new_csid_dev) {
+ pr_err("%s: no enough memory\n", __func__);
+ return -ENOMEM;
+ }
+
+ v4l2_subdev_init(&new_csid_dev->subdev, &msm_csid_subdev_ops);
+ v4l2_set_subdevdata(&new_csid_dev->subdev, new_csid_dev);
+ platform_set_drvdata(pdev, &new_csid_dev->subdev);
+ mutex_init(&new_csid_dev->mutex);
+
+ new_csid_dev->mem = platform_get_resource_byname(pdev,
+ IORESOURCE_MEM, "csid");
+ if (!new_csid_dev->mem) {
+ pr_err("%s: no mem resource?\n", __func__);
+ rc = -ENODEV;
+ goto csid_no_resource;
+ }
+ new_csid_dev->irq = platform_get_resource_byname(pdev,
+ IORESOURCE_IRQ, "csid");
+ if (!new_csid_dev->irq) {
+ pr_err("%s: no irq resource?\n", __func__);
+ rc = -ENODEV;
+ goto csid_no_resource;
+ }
+ new_csid_dev->io = request_mem_region(new_csid_dev->mem->start,
+ resource_size(new_csid_dev->mem), pdev->name);
+ if (!new_csid_dev->io) {
+ pr_err("%s: no valid mem region\n", __func__);
+ rc = -EBUSY;
+ goto csid_no_resource;
+ }
+
+ rc = request_irq(new_csid_dev->irq->start, msm_csid_irq,
+ IRQF_TRIGGER_RISING, "csid", new_csid_dev);
+ if (rc < 0) {
+ release_mem_region(new_csid_dev->mem->start,
+ resource_size(new_csid_dev->mem));
+ pr_err("%s: irq request fail\n", __func__);
+ rc = -EBUSY;
+ goto csid_no_resource;
+ }
+ disable_irq(new_csid_dev->irq->start);
+
+ new_csid_dev->base = ioremap(new_csid_dev->mem->start,
+ resource_size(new_csid_dev->mem));
+ if (!new_csid_dev->base) {
+ rc = -ENOMEM;
+ goto csid_no_resource;
+ }
+
+ new_csid_dev->hw_version =
+ msm_io_r(new_csid_dev->base + CSID_HW_VERSION_ADDR);
+ iounmap(new_csid_dev->base);
+
+ new_csid_dev->pdev = pdev;
+ return 0;
+
+csid_no_resource:
+ mutex_destroy(&new_csid_dev->mutex);
+ kfree(new_csid_dev);
+ return 0;
+}
+
+static struct platform_driver csid_driver = {
+ .probe = csid_probe,
+ .driver = {
+ .name = MSM_CSID_DRV_NAME,
+ .owner = THIS_MODULE,
+ },
+};
+
+static int __init msm_csid_init_module(void)
+{
+ return platform_driver_register(&csid_driver);
+}
+
+static void __exit msm_csid_exit_module(void)
+{
+ platform_driver_unregister(&csid_driver);
+}
+
+module_init(msm_csid_init_module);
+module_exit(msm_csid_exit_module);
+MODULE_DESCRIPTION("MSM CSID driver");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/media/video/msm/csi/msm_csid.h b/drivers/media/video/msm/csi/msm_csid.h
new file mode 100644
index 0000000..f90abf2
--- /dev/null
+++ b/drivers/media/video/msm/csi/msm_csid.h
@@ -0,0 +1,48 @@
+/* Copyright (c) 2011, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#ifndef MSM_CSID_H
+#define MSM_CSID_H
+
+#include <linux/clk.h>
+#include <linux/io.h>
+#include <media/v4l2-subdev.h>
+
+struct csid_device {
+ struct platform_device *pdev;
+ struct v4l2_subdev subdev;
+ struct resource *mem;
+ struct resource *irq;
+ struct resource *io;
+ void __iomem *base;
+ struct mutex mutex;
+ uint32_t hw_version;
+
+ struct clk *csid_clk[5];
+};
+
+struct csid_cfg_params {
+ struct v4l2_subdev *subdev;
+ void *parms;
+};
+
+#define VIDIOC_MSM_CSID_CFG \
+ _IOWR('V', BASE_VIDIOC_PRIVATE + 4, struct csid_cfg_params)
+
+#define VIDIOC_MSM_CSID_INIT \
+ _IOWR('V', BASE_VIDIOC_PRIVATE + 5, struct v4l2_subdev*)
+
+#define VIDIOC_MSM_CSID_RELEASE \
+ _IOWR('V', BASE_VIDIOC_PRIVATE + 6, struct v4l2_subdev*)
+
+#endif
+
diff --git a/drivers/media/video/msm/csi/msm_csiphy.c b/drivers/media/video/msm/csi/msm_csiphy.c
new file mode 100644
index 0000000..b62ec84
--- /dev/null
+++ b/drivers/media/video/msm/csi/msm_csiphy.c
@@ -0,0 +1,312 @@
+/* Copyright (c) 2011, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/delay.h>
+#include <linux/clk.h>
+#include <linux/io.h>
+#include <mach/board.h>
+#include <mach/camera.h>
+#include <mach/vreg.h>
+#include <media/msm_isp.h>
+#include "msm_csiphy.h"
+#include "msm.h"
+
+#define DBG_CSIPHY 0
+
+#define V4L2_IDENT_CSIPHY 50003
+
+/*MIPI CSI PHY registers*/
+#define MIPI_CSIPHY_LNn_CFG1_ADDR 0x0
+#define MIPI_CSIPHY_LNn_CFG2_ADDR 0x4
+#define MIPI_CSIPHY_LNn_CFG3_ADDR 0x8
+#define MIPI_CSIPHY_LNn_CFG4_ADDR 0xC
+#define MIPI_CSIPHY_LNn_CFG5_ADDR 0x10
+#define MIPI_CSIPHY_LNCK_CFG1_ADDR 0x100
+#define MIPI_CSIPHY_LNCK_CFG2_ADDR 0x104
+#define MIPI_CSIPHY_LNCK_CFG3_ADDR 0x108
+#define MIPI_CSIPHY_LNCK_CFG4_ADDR 0x10C
+#define MIPI_CSIPHY_LNCK_CFG5_ADDR 0x110
+#define MIPI_CSIPHY_LNCK_MISC1_ADDR 0x128
+#define MIPI_CSIPHY_GLBL_T_INIT_CFG0_ADDR 0x1E0
+#define MIPI_CSIPHY_T_WAKEUP_CFG0_ADDR 0x1E8
+#define MIPI_CSIPHY_GLBL_PWR_CFG_ADDR 0x0144
+#define MIPI_CSIPHY_INTERRUPT_STATUS0_ADDR 0x0180
+#define MIPI_CSIPHY_INTERRUPT_STATUS1_ADDR 0x0184
+#define MIPI_CSIPHY_INTERRUPT_STATUS2_ADDR 0x0188
+#define MIPI_CSIPHY_INTERRUPT_STATUS3_ADDR 0x018C
+#define MIPI_CSIPHY_INTERRUPT_STATUS4_ADDR 0x0190
+#define MIPI_CSIPHY_INTERRUPT_MASK0_ADDR 0x01A0
+#define MIPI_CSIPHY_INTERRUPT_MASK1_ADDR 0x01A4
+#define MIPI_CSIPHY_INTERRUPT_MASK2_ADDR 0x01A8
+#define MIPI_CSIPHY_INTERRUPT_MASK3_ADDR 0x01AC
+#define MIPI_CSIPHY_INTERRUPT_MASK4_ADDR 0x01B0
+#define MIPI_CSIPHY_INTERRUPT_CLEAR0_ADDR 0x01C0
+#define MIPI_CSIPHY_INTERRUPT_CLEAR1_ADDR 0x01C4
+#define MIPI_CSIPHY_INTERRUPT_CLEAR2_ADDR 0x01C8
+#define MIPI_CSIPHY_INTERRUPT_CLEAR3_ADDR 0x01CC
+#define MIPI_CSIPHY_INTERRUPT_CLEAR4_ADDR 0x01D0
+
+int msm_csiphy_config(struct csiphy_cfg_params *cfg_params)
+{
+ int rc = 0;
+ int i = 0;
+ uint32_t val = 0;
+ struct csiphy_device *csiphy_dev;
+ struct msm_camera_csiphy_params *csiphy_params;
+ void __iomem *csiphybase;
+ csiphy_dev = v4l2_get_subdevdata(cfg_params->subdev);
+ csiphybase = csiphy_dev->base;
+ csiphy_params = cfg_params->parms;
+ if (csiphy_params->lane_cnt < 1 || csiphy_params->lane_cnt > 4) {
+ CDBG("%s: unsupported lane cnt %d\n",
+ __func__, csiphy_params->lane_cnt);
+ return rc;
+ }
+
+ val = 0x3;
+ msm_io_w((((1 << csiphy_params->lane_cnt) - 1) << 2) | val,
+ csiphybase + MIPI_CSIPHY_GLBL_PWR_CFG_ADDR);
+ msm_io_w(0x1, csiphybase + MIPI_CSIPHY_GLBL_T_INIT_CFG0_ADDR);
+ msm_io_w(0x1, csiphybase + MIPI_CSIPHY_T_WAKEUP_CFG0_ADDR);
+
+ for (i = 0; i < csiphy_params->lane_cnt; i++) {
+ msm_io_w(0x10, csiphybase + MIPI_CSIPHY_LNn_CFG1_ADDR + 0x40*i);
+ msm_io_w(0x5F, csiphybase + MIPI_CSIPHY_LNn_CFG2_ADDR + 0x40*i);
+ msm_io_w(csiphy_params->settle_cnt,
+ csiphybase + MIPI_CSIPHY_LNn_CFG3_ADDR + 0x40*i);
+ msm_io_w(0x00000052,
+ csiphybase + MIPI_CSIPHY_LNn_CFG5_ADDR + 0x40*i);
+ }
+
+ msm_io_w(0x00000000, csiphybase + MIPI_CSIPHY_LNCK_CFG1_ADDR);
+ msm_io_w(0x5F, csiphybase + MIPI_CSIPHY_LNCK_CFG2_ADDR);
+ msm_io_w(csiphy_params->settle_cnt,
+ csiphybase + MIPI_CSIPHY_LNCK_CFG3_ADDR);
+ msm_io_w(0x5, csiphybase + MIPI_CSIPHY_LNCK_CFG4_ADDR);
+ msm_io_w(0x2, csiphybase + MIPI_CSIPHY_LNCK_CFG5_ADDR);
+ msm_io_w(0x0, csiphybase + 0x128);
+
+ msm_io_w(0x24,
+ csiphybase + MIPI_CSIPHY_INTERRUPT_MASK0_ADDR);
+ msm_io_w(0x24,
+ csiphybase + MIPI_CSIPHY_INTERRUPT_CLEAR0_ADDR);
+
+ for (i = 1; i <= csiphy_params->lane_cnt; i++) {
+ msm_io_w(0x6F,
+ csiphybase + MIPI_CSIPHY_INTERRUPT_MASK0_ADDR + 0x4*i);
+ msm_io_w(0x6F,
+ csiphybase + MIPI_CSIPHY_INTERRUPT_CLEAR0_ADDR + 0x4*i);
+ }
+ return rc;
+}
+
+static irqreturn_t msm_csiphy_irq(int irq_num, void *data)
+{
+ uint32_t irq;
+ struct csiphy_device *csiphy_dev = data;
+ irq = msm_io_r(csiphy_dev->base + MIPI_CSIPHY_INTERRUPT_STATUS0_ADDR);
+ msm_io_w(irq, csiphy_dev->base + MIPI_CSIPHY_INTERRUPT_CLEAR0_ADDR);
+ CDBG("%s MIPI_CSIPHY_INTERRUPT_STATUS0 = 0x%x\n", __func__, irq);
+ irq = msm_io_r(csiphy_dev->base + MIPI_CSIPHY_INTERRUPT_STATUS1_ADDR);
+ msm_io_w(irq, csiphy_dev->base + MIPI_CSIPHY_INTERRUPT_CLEAR1_ADDR);
+ CDBG("%s MIPI_CSIPHY_INTERRUPT_STATUS1 = 0x%x\n", __func__, irq);
+ irq = msm_io_r(csiphy_dev->base + MIPI_CSIPHY_INTERRUPT_STATUS2_ADDR);
+ msm_io_w(irq, csiphy_dev->base + MIPI_CSIPHY_INTERRUPT_CLEAR2_ADDR);
+ CDBG("%s MIPI_CSIPHY_INTERRUPT_STATUS2 = 0x%x\n", __func__, irq);
+ irq = msm_io_r(csiphy_dev->base + MIPI_CSIPHY_INTERRUPT_STATUS3_ADDR);
+ msm_io_w(irq, csiphy_dev->base + MIPI_CSIPHY_INTERRUPT_CLEAR3_ADDR);
+ CDBG("%s MIPI_CSIPHY_INTERRUPT_STATUS3 = 0x%x\n", __func__, irq);
+ irq = msm_io_r(csiphy_dev->base + MIPI_CSIPHY_INTERRUPT_STATUS4_ADDR);
+ msm_io_w(irq, csiphy_dev->base + MIPI_CSIPHY_INTERRUPT_CLEAR4_ADDR);
+ CDBG("%s MIPI_CSIPHY_INTERRUPT_STATUS4 = 0x%x\n", __func__, irq);
+ msm_io_w(0x1, csiphy_dev->base + 0x164);
+ msm_io_w(0x0, csiphy_dev->base + 0x164);
+ return IRQ_HANDLED;
+}
+
+static int msm_csiphy_subdev_g_chip_ident(struct v4l2_subdev *sd,
+ struct v4l2_dbg_chip_ident *chip)
+{
+ BUG_ON(!chip);
+ chip->ident = V4L2_IDENT_CSIPHY;
+ chip->revision = 0;
+ return 0;
+}
+
+static struct msm_cam_clk_info csiphy_clk_info[] = {
+ {"csiphy_timer_src_clk", 177780000},
+ {"csiphy_timer_clk", -1},
+};
+
+static int msm_csiphy_init(struct v4l2_subdev *sd)
+{
+ int rc = 0;
+ struct csiphy_device *csiphy_dev;
+ csiphy_dev = v4l2_get_subdevdata(sd);
+ if (csiphy_dev == NULL) {
+ rc = -ENOMEM;
+ return rc;
+ }
+
+ csiphy_dev->base = ioremap(csiphy_dev->mem->start,
+ resource_size(csiphy_dev->mem));
+ if (!csiphy_dev->base) {
+ rc = -ENOMEM;
+ return rc;
+ }
+
+ rc = msm_cam_clk_enable(&csiphy_dev->pdev->dev, csiphy_clk_info,
+ csiphy_dev->csiphy_clk, ARRAY_SIZE(csiphy_clk_info), 1);
+
+ if (rc < 0) {
+ iounmap(csiphy_dev->base);
+ return rc;
+ }
+
+#if DBG_CSIPHY
+ enable_irq(csiphy_dev->irq->start);
+#endif
+
+ return 0;
+}
+
+static int msm_csiphy_release(struct v4l2_subdev *sd)
+{
+ struct csiphy_device *csiphy_dev;
+ int i;
+ csiphy_dev = v4l2_get_subdevdata(sd);
+ for (i = 0; i < 4; i++)
+ msm_io_w(0x0, csiphy_dev->base +
+ MIPI_CSIPHY_LNn_CFG2_ADDR + 0x40*i);
+
+ msm_io_w(0x0, csiphy_dev->base + MIPI_CSIPHY_LNCK_CFG2_ADDR);
+ msm_io_w(0x0, csiphy_dev->base + MIPI_CSIPHY_GLBL_PWR_CFG_ADDR);
+
+ msm_cam_clk_enable(&csiphy_dev->pdev->dev, csiphy_clk_info,
+ csiphy_dev->csiphy_clk, ARRAY_SIZE(csiphy_clk_info), 0);
+
+#if DBG_CSIPHY
+ disable_irq(csiphy_dev->irq->start);
+#endif
+ iounmap(csiphy_dev->base);
+ return 0;
+}
+
+static long msm_csiphy_subdev_ioctl(struct v4l2_subdev *sd,
+ unsigned int cmd, void *arg)
+{
+ struct csiphy_cfg_params cfg_params;
+ switch (cmd) {
+ case VIDIOC_MSM_CSIPHY_CFG:
+ cfg_params.subdev = sd;
+ cfg_params.parms = arg;
+ return msm_csiphy_config(
+ (struct csiphy_cfg_params *)&cfg_params);
+ case VIDIOC_MSM_CSIPHY_INIT:
+ return msm_csiphy_init(sd);
+ case VIDIOC_MSM_CSIPHY_RELEASE:
+ return msm_csiphy_release(sd);
+ default:
+ return -ENOIOCTLCMD;
+ }
+}
+
+static struct v4l2_subdev_core_ops msm_csiphy_subdev_core_ops = {
+ .g_chip_ident = &msm_csiphy_subdev_g_chip_ident,
+ .ioctl = &msm_csiphy_subdev_ioctl,
+};
+
+static const struct v4l2_subdev_ops msm_csiphy_subdev_ops = {
+ .core = &msm_csiphy_subdev_core_ops,
+};
+
+static int __devinit csiphy_probe(struct platform_device *pdev)
+{
+ struct csiphy_device *new_csiphy_dev;
+ int rc = 0;
+ CDBG("%s: device id = %d\n", __func__, pdev->id);
+ new_csiphy_dev = kzalloc(sizeof(struct csiphy_device), GFP_KERNEL);
+ if (!new_csiphy_dev) {
+ pr_err("%s: no enough memory\n", __func__);
+ return -ENOMEM;
+ }
+
+ v4l2_subdev_init(&new_csiphy_dev->subdev, &msm_csiphy_subdev_ops);
+ v4l2_set_subdevdata(&new_csiphy_dev->subdev, new_csiphy_dev);
+ platform_set_drvdata(pdev, &new_csiphy_dev->subdev);
+
+ mutex_init(&new_csiphy_dev->mutex);
+
+ new_csiphy_dev->mem = platform_get_resource_byname(pdev,
+ IORESOURCE_MEM, "csiphy");
+ if (!new_csiphy_dev->mem) {
+ pr_err("%s: no mem resource?\n", __func__);
+ rc = -ENODEV;
+ goto csiphy_no_resource;
+ }
+ new_csiphy_dev->irq = platform_get_resource_byname(pdev,
+ IORESOURCE_IRQ, "csiphy");
+ if (!new_csiphy_dev->irq) {
+ pr_err("%s: no irq resource?\n", __func__);
+ rc = -ENODEV;
+ goto csiphy_no_resource;
+ }
+ new_csiphy_dev->io = request_mem_region(new_csiphy_dev->mem->start,
+ resource_size(new_csiphy_dev->mem), pdev->name);
+ if (!new_csiphy_dev->io) {
+ pr_err("%s: no valid mem region\n", __func__);
+ rc = -EBUSY;
+ goto csiphy_no_resource;
+ }
+
+ rc = request_irq(new_csiphy_dev->irq->start, msm_csiphy_irq,
+ IRQF_TRIGGER_RISING, "csiphy", new_csiphy_dev);
+ if (rc < 0) {
+ release_mem_region(new_csiphy_dev->mem->start,
+ resource_size(new_csiphy_dev->mem));
+ pr_err("%s: irq request fail\n", __func__);
+ rc = -EBUSY;
+ goto csiphy_no_resource;
+ }
+ disable_irq(new_csiphy_dev->irq->start);
+
+ new_csiphy_dev->pdev = pdev;
+ return 0;
+
+csiphy_no_resource:
+ mutex_destroy(&new_csiphy_dev->mutex);
+ kfree(new_csiphy_dev);
+ return 0;
+}
+
+static struct platform_driver csiphy_driver = {
+ .probe = csiphy_probe,
+ .driver = {
+ .name = MSM_CSIPHY_DRV_NAME,
+ .owner = THIS_MODULE,
+ },
+};
+
+static int __init msm_csiphy_init_module(void)
+{
+ return platform_driver_register(&csiphy_driver);
+}
+
+static void __exit msm_csiphy_exit_module(void)
+{
+ platform_driver_unregister(&csiphy_driver);
+}
+
+module_init(msm_csiphy_init_module);
+module_exit(msm_csiphy_exit_module);
+MODULE_DESCRIPTION("MSM CSIPHY driver");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/media/video/msm/csi/msm_csiphy.h b/drivers/media/video/msm/csi/msm_csiphy.h
new file mode 100644
index 0000000..522a1c1
--- /dev/null
+++ b/drivers/media/video/msm/csi/msm_csiphy.h
@@ -0,0 +1,46 @@
+/* Copyright (c) 2011, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#ifndef MSM_CSIPHY_H
+#define MSM_CSIPHY_H
+
+#include <linux/clk.h>
+#include <linux/io.h>
+#include <media/v4l2-subdev.h>
+
+struct csiphy_device {
+ struct platform_device *pdev;
+ struct v4l2_subdev subdev;
+ struct resource *mem;
+ struct resource *irq;
+ struct resource *io;
+ void __iomem *base;
+ struct mutex mutex;
+
+ struct clk *csiphy_clk[2];
+};
+
+struct csiphy_cfg_params {
+ struct v4l2_subdev *subdev;
+ void *parms;
+};
+
+#define VIDIOC_MSM_CSIPHY_CFG \
+ _IOWR('V', BASE_VIDIOC_PRIVATE + 7, struct csiphy_cfg_params)
+
+#define VIDIOC_MSM_CSIPHY_INIT \
+ _IOWR('V', BASE_VIDIOC_PRIVATE + 8, struct v4l2_subdev*)
+
+#define VIDIOC_MSM_CSIPHY_RELEASE \
+ _IOWR('V', BASE_VIDIOC_PRIVATE + 9, struct v4l2_subdev*)
+
+#endif
diff --git a/drivers/media/video/msm/msm_ispif.c b/drivers/media/video/msm/csi/msm_ispif.c
similarity index 86%
rename from drivers/media/video/msm/msm_ispif.c
rename to drivers/media/video/msm/csi/msm_ispif.c
index 8797d38..af61bd2 100644
--- a/drivers/media/video/msm/msm_ispif.c
+++ b/drivers/media/video/msm/csi/msm_ispif.c
@@ -13,20 +13,13 @@
#include <linux/delay.h>
#include <linux/clk.h>
#include <linux/io.h>
-#include <linux/regulator/consumer.h>
#include <mach/gpio.h>
-#include <mach/board.h>
#include <mach/camera.h>
-#include <mach/vreg.h>
-#include <mach/camera.h>
-#include <mach/clk.h>
-#include <mach/msm_bus.h>
-#include <mach/msm_bus_board.h>
-#include <media/msm_isp.h>
#include "msm_ispif.h"
#include "msm.h"
#define V4L2_IDENT_ISPIF 50001
+#define CSID_VERSION_V2 0x2000011
/* ISPIF registers */
@@ -147,7 +140,17 @@
static void msm_ispif_sel_csid_core(uint8_t intftype, uint8_t csid)
{
+ int rc = 0;
uint32_t data;
+ if (ispif->ispif_clk[intftype] == NULL) {
+ pr_err("%s: ispif NULL clk\n", __func__);
+ return;
+ }
+
+ rc = clk_set_rate(ispif->ispif_clk[intftype], csid);
+ if (rc < 0)
+ pr_err("%s: clk_set_rate failed %d\n", __func__, rc);
+
data = msm_io_r(ispif->base + ISPIF_INPUT_SEL_ADDR);
data |= csid<<(intftype*4);
msm_io_w(data, ispif->base + ISPIF_INPUT_SEL_ADDR);
@@ -215,18 +218,6 @@
return rc;
}
-static long msm_ispif_subdev_ioctl(struct v4l2_subdev *sd, unsigned int cmd,
- void *arg)
-{
- switch (cmd) {
- case VIDIOC_MSM_ISPSF_CFG:
- return msm_ispif_config((struct msm_ispif_params_list *)arg);
- default:
- return -ENOIOCTLCMD;
- }
-}
-
-
static uint32_t msm_ispif_get_cid_mask(uint8_t intftype)
{
uint32_t mask = 0;
@@ -373,20 +364,6 @@
return rc;
}
-static struct v4l2_subdev_core_ops msm_ispif_subdev_core_ops = {
- .g_chip_ident = &msm_ispif_subdev_g_chip_ident,
- .ioctl = &msm_ispif_subdev_ioctl,
-};
-
-static struct v4l2_subdev_video_ops msm_ispif_subdev_video_ops = {
- .s_stream = &msm_ispif_subdev_video_s_stream,
-};
-
-static const struct v4l2_subdev_ops msm_ispif_subdev_ops = {
- .core = &msm_ispif_subdev_core_ops,
- .video = &msm_ispif_subdev_video_ops,
-};
-
static inline void msm_ispif_read_irq_status(struct ispif_irq_status *out)
{
out->ispifIrqStatus0 = msm_io_r(ispif->base +
@@ -426,84 +403,54 @@
return IRQ_HANDLED;
}
-int msm_ispif_init(struct v4l2_subdev **sd, struct platform_device *pdev)
+static struct msm_cam_clk_info ispif_clk_info[] = {
+ {"csi_pix_clk", 0},
+ {"csi_rdi_clk", 0},
+ {"csi_pix1_clk", 0},
+ {"csi_rdi1_clk", 0},
+ {"csi_rdi2_clk", 0},
+};
+
+static int msm_ispif_init(const uint32_t *csid_version)
{
int rc = 0;
-
- ispif = kzalloc(sizeof(struct ispif_device), GFP_KERNEL);
- if (!ispif) {
- pr_err("%s: no enough memory\n", __func__);
- return -ENOMEM;
- }
-
- v4l2_subdev_init(&ispif->subdev, &msm_ispif_subdev_ops);
- v4l2_set_subdevdata(&ispif->subdev, ispif);
- snprintf(ispif->subdev.name, sizeof(ispif->subdev.name),
- "ispif");
- mutex_init(&ispif->mutex);
-
- ispif->mem = platform_get_resource_byname(pdev,
- IORESOURCE_MEM, "ispif");
- if (!ispif->mem) {
- pr_err("%s: no mem resource?\n", __func__);
- rc = -ENODEV;
- goto ispif_no_resource;
- }
- ispif->irq = platform_get_resource_byname(pdev,
- IORESOURCE_IRQ, "ispif");
- if (!ispif->irq) {
- pr_err("%s: no irq resource?\n", __func__);
- rc = -ENODEV;
- goto ispif_no_resource;
- }
- ispif->io = request_mem_region(ispif->mem->start,
- resource_size(ispif->mem), pdev->name);
- if (!ispif->io) {
- pr_err("%s: no valid mem region\n", __func__);
- rc = -EBUSY;
- goto ispif_no_resource;
- }
- ispif->base = ioremap(ispif->mem->start,
- resource_size(ispif->mem));
- if (!ispif->base) {
- rc = -ENOMEM;
- goto ispif_no_mem;
- }
-
rc = request_irq(ispif->irq->start, msm_io_ispif_irq,
IRQF_TRIGGER_RISING, "ispif", 0);
- if (rc < 0)
- goto ispif_irq_fail;
global_intf_cmd_mask = 0xFFFFFFFF;
init_completion(&ispif->reset_complete);
- rc = msm_ispif_reset();
- *sd = &(ispif->subdev);
- return rc;
+ ispif->csid_version = *csid_version;
+ if (ispif->csid_version == CSID_VERSION_V2) {
+ rc = msm_cam_clk_enable(&ispif->pdev->dev, ispif_clk_info,
+ ispif->ispif_clk, ARRAY_SIZE(ispif_clk_info), 1);
+ if (rc < 0)
+ return rc;
+ } else {
+ rc = msm_cam_clk_enable(&ispif->pdev->dev, ispif_clk_info,
+ ispif->ispif_clk, 2, 1);
+ if (rc < 0)
+ return rc;
+ }
-ispif_irq_fail:
- iounmap(ispif->base);
-ispif_no_mem:
- release_mem_region(ispif->mem->start,
- resource_size(ispif->mem));
-ispif_no_resource:
- mutex_destroy(&ispif->mutex);
- kfree(ispif);
+ rc = msm_ispif_reset();
return rc;
}
-void msm_ispif_release(struct v4l2_subdev *sd)
+static void msm_ispif_release(struct v4l2_subdev *sd)
{
struct ispif_device *ispif =
(struct ispif_device *)v4l2_get_subdevdata(sd);
+ if (ispif->csid_version == CSID_VERSION_V2)
+ msm_cam_clk_enable(&ispif->pdev->dev, ispif_clk_info,
+ ispif->ispif_clk, ARRAY_SIZE(ispif_clk_info), 0);
+ else
+ msm_cam_clk_enable(&ispif->pdev->dev, ispif_clk_info,
+ ispif->ispif_clk, 2, 0);
+
CDBG("%s, free_irq\n", __func__);
free_irq(ispif->irq->start, 0);
- iounmap(ispif->base);
- release_mem_region(ispif->mem->start,
- resource_size(ispif->mem));
- kfree(ispif);
}
void msm_ispif_vfe_get_cid(uint8_t intftype, char *cids, int *num)
@@ -537,3 +484,112 @@
data >>= 1;
}
}
+
+static long msm_ispif_subdev_ioctl(struct v4l2_subdev *sd, unsigned int cmd,
+ void *arg)
+{
+ switch (cmd) {
+ case VIDIOC_MSM_ISPIF_CFG:
+ return msm_ispif_config((struct msm_ispif_params_list *)arg);
+ case VIDIOC_MSM_ISPIF_INIT:
+ return msm_ispif_init((uint32_t *)arg);
+ case VIDIOC_MSM_ISPIF_RELEASE:
+ msm_ispif_release(sd);
+ default:
+ return -ENOIOCTLCMD;
+ }
+}
+
+static struct v4l2_subdev_core_ops msm_ispif_subdev_core_ops = {
+ .g_chip_ident = &msm_ispif_subdev_g_chip_ident,
+ .ioctl = &msm_ispif_subdev_ioctl,
+};
+
+static struct v4l2_subdev_video_ops msm_ispif_subdev_video_ops = {
+ .s_stream = &msm_ispif_subdev_video_s_stream,
+};
+
+static const struct v4l2_subdev_ops msm_ispif_subdev_ops = {
+ .core = &msm_ispif_subdev_core_ops,
+ .video = &msm_ispif_subdev_video_ops,
+};
+
+static int __devinit ispif_probe(struct platform_device *pdev)
+{
+ int rc = 0;
+ CDBG("%s\n", __func__);
+ ispif = kzalloc(sizeof(struct ispif_device), GFP_KERNEL);
+ if (!ispif) {
+ pr_err("%s: no enough memory\n", __func__);
+ return -ENOMEM;
+ }
+
+ v4l2_subdev_init(&ispif->subdev, &msm_ispif_subdev_ops);
+ v4l2_set_subdevdata(&ispif->subdev, ispif);
+ platform_set_drvdata(pdev, &ispif->subdev);
+ snprintf(ispif->subdev.name, sizeof(ispif->subdev.name),
+ "ispif");
+ mutex_init(&ispif->mutex);
+
+ ispif->mem = platform_get_resource_byname(pdev,
+ IORESOURCE_MEM, "ispif");
+ if (!ispif->mem) {
+ pr_err("%s: no mem resource?\n", __func__);
+ rc = -ENODEV;
+ goto ispif_no_resource;
+ }
+ ispif->irq = platform_get_resource_byname(pdev,
+ IORESOURCE_IRQ, "ispif");
+ if (!ispif->irq) {
+ pr_err("%s: no irq resource?\n", __func__);
+ rc = -ENODEV;
+ goto ispif_no_resource;
+ }
+ ispif->io = request_mem_region(ispif->mem->start,
+ resource_size(ispif->mem), pdev->name);
+ if (!ispif->io) {
+ pr_err("%s: no valid mem region\n", __func__);
+ rc = -EBUSY;
+ goto ispif_no_resource;
+ }
+ ispif->base = ioremap(ispif->mem->start,
+ resource_size(ispif->mem));
+ if (!ispif->base) {
+ rc = -ENOMEM;
+ goto ispif_no_mem;
+ }
+
+ ispif->pdev = pdev;
+ return 0;
+
+ispif_no_mem:
+ release_mem_region(ispif->mem->start,
+ resource_size(ispif->mem));
+ispif_no_resource:
+ mutex_destroy(&ispif->mutex);
+ kfree(ispif);
+ return rc;
+}
+
+static struct platform_driver ispif_driver = {
+ .probe = ispif_probe,
+ .driver = {
+ .name = MSM_ISPIF_DRV_NAME,
+ .owner = THIS_MODULE,
+ },
+};
+
+static int __init msm_ispif_init_module(void)
+{
+ return platform_driver_register(&ispif_driver);
+}
+
+static void __exit msm_ispif_exit_module(void)
+{
+ platform_driver_unregister(&ispif_driver);
+}
+
+module_init(msm_ispif_init_module);
+module_exit(msm_ispif_exit_module);
+MODULE_DESCRIPTION("MSM ISP Interface driver");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/media/video/msm/msm_ispif.h b/drivers/media/video/msm/csi/msm_ispif.h
similarity index 76%
rename from drivers/media/video/msm/msm_ispif.h
rename to drivers/media/video/msm/csi/msm_ispif.h
index 3b923ea..deadc28 100644
--- a/drivers/media/video/msm/msm_ispif.h
+++ b/drivers/media/video/msm/csi/msm_ispif.h
@@ -13,27 +13,17 @@
#ifndef MSM_ISPIF_H
#define MSM_ISPIF_H
-#include <linux/delay.h>
#include <linux/clk.h>
#include <linux/io.h>
-#include <linux/regulator/consumer.h>
-#include <mach/gpio.h>
-#include <mach/board.h>
-#include <mach/camera.h>
-#include <mach/vreg.h>
-#include <mach/camera.h>
-#include <mach/clk.h>
-#include <mach/msm_bus.h>
-#include <mach/msm_bus_board.h>
#include <media/v4l2-subdev.h>
-
struct ispif_irq_status {
uint32_t ispifIrqStatus0;
uint32_t ispifIrqStatus1;
};
struct ispif_device {
+ struct platform_device *pdev;
struct v4l2_subdev subdev;
struct resource *mem;
struct resource *irq;
@@ -42,19 +32,25 @@
struct mutex mutex;
uint8_t start_ack_pending;
struct completion reset_complete;
+ uint32_t csid_version;
+ struct clk *ispif_clk[5];
};
-#define VIDIOC_MSM_ISPSF_CFG \
+#define VIDIOC_MSM_ISPIF_CFG \
_IOWR('V', BASE_VIDIOC_PRIVATE + 1, struct msm_ispif_params)
+#define VIDIOC_MSM_ISPIF_INIT \
+ _IO('V', BASE_VIDIOC_PRIVATE + 2)
+
+#define VIDIOC_MSM_ISPIF_RELEASE \
+ _IOWR('V', BASE_VIDIOC_PRIVATE + 3, struct v4l2_subdev*)
+
#define ISPIF_STREAM(intf, action) (((intf)<<ISPIF_S_STREAM_SHIFT)+(action))
#define ISPIF_ON_FRAME_BOUNDARY (0x01 << 0)
#define ISPIF_OFF_FRAME_BOUNDARY (0x01 << 1)
#define ISPIF_OFF_IMMEDIATELY (0x01 << 2)
#define ISPIF_S_STREAM_SHIFT 4
-int msm_ispif_init(struct v4l2_subdev **sd, struct platform_device *pdev);
-void msm_ispif_release(struct v4l2_subdev *sd);
void msm_ispif_vfe_get_cid(uint8_t intftype, char *cids, int *num);
#endif
diff --git a/drivers/media/video/msm/msm.c b/drivers/media/video/msm/msm.c
index 8ef0de9..f7a1fa8 100644
--- a/drivers/media/video/msm/msm.c
+++ b/drivers/media/video/msm/msm.c
@@ -1473,7 +1473,7 @@
/* Register isp subdev */
rc = v4l2_device_register_subdev(&pcam->v4l2_dev,
- &pcam->mctl.isp_sdev->sd);
+ pcam->mctl.isp_sdev->sd);
if (rc < 0) {
mutex_unlock(&pcam->vid_lock);
pr_err("%s: v4l2_device_register_subdev failed rc = %d\n",
@@ -1481,7 +1481,7 @@
return rc;
}
rc = v4l2_device_register_subdev(&pcam->v4l2_dev,
- &pcam->mctl.isp_sdev->sd_vpe);
+ pcam->mctl.isp_sdev->sd_vpe);
if (rc < 0) {
mutex_unlock(&pcam->vid_lock);
pr_err("%s: vpe v4l2_device_register_subdev failed rc = %d\n",
@@ -1613,8 +1613,8 @@
f->private_data = NULL;
if (pcam->use_count == 0) {
- v4l2_device_unregister_subdev(&pcam->mctl.isp_sdev->sd);
- v4l2_device_unregister_subdev(&pcam->mctl.isp_sdev->sd_vpe);
+ v4l2_device_unregister_subdev(pcam->mctl.isp_sdev->sd);
+ v4l2_device_unregister_subdev(pcam->mctl.isp_sdev->sd_vpe);
rc = msm_cam_server_close_session(&g_server_dev, pcam);
if (rc < 0)
pr_err("msm_cam_server_close_session fails %d\n", rc);
diff --git a/drivers/media/video/msm/msm.h b/drivers/media/video/msm/msm.h
index f9cf5de..f11e43f 100644
--- a/drivers/media/video/msm/msm.h
+++ b/drivers/media/video/msm/msm.h
@@ -41,6 +41,12 @@
#define ERR_COPY_FROM_USER() ERR_USER_COPY(0)
#define ERR_COPY_TO_USER() ERR_USER_COPY(1)
+#define MSM_CSIPHY_DRV_NAME "msm_csiphy"
+#define MSM_CSID_DRV_NAME "msm_csid"
+#define MSM_ISPIF_DRV_NAME "msm_ispif"
+#define MSM_VFE_DRV_NAME "msm_vfe"
+#define MSM_VPE_DRV_NAME "msm_vpe"
+
/* msm queue management APIs*/
#define msm_dequeue(queue, member) ({ \
@@ -113,6 +119,8 @@
NOTIFY_ISPIF_STREAM, /* arg = enable parameter for s_stream */
NOTIFY_VPE_MSG_EVT,
NOTIFY_PCLK_CHANGE, /* arg = pclk */
+ NOTIFY_CSIPHY_CFG, /* arg = msm_camera_csiphy_params */
+ NOTIFY_CSID_CFG, /* arg = msm_camera_csid_params */
NOTIFY_INVALID
};
@@ -215,6 +223,8 @@
struct v4l2_subdev *vpe_sdev; /* vpe sub device : VPE */
struct v4l2_subdev *flash_sdev; /* vpe sub device : VPE */
struct msm_cam_config_dev *config_device;
+ struct v4l2_subdev *csiphy_sdev; /*csiphy sub device*/
+ struct v4l2_subdev *csid_sdev; /*csid sub device*/
struct v4l2_subdev *ispif_sdev; /* ispif sub device */
struct v4l2_subdev *act_sdev; /* actuator sub device */
@@ -239,8 +249,8 @@
struct msm_mctl_pp_cmd, void *data);
/* vfe subdevice */
- struct v4l2_subdev sd;
- struct v4l2_subdev sd_vpe;
+ struct v4l2_subdev *sd;
+ struct v4l2_subdev *sd_vpe;
};
struct msm_isp_buf_info {
diff --git a/drivers/media/video/msm/msm_camera.c b/drivers/media/video/msm/msm_camera.c
index 565c724..7f43136 100644
--- a/drivers/media/video/msm/msm_camera.c
+++ b/drivers/media/video/msm/msm_camera.c
@@ -34,6 +34,7 @@
#include <mach/camera.h>
#include <linux/syscalls.h>
#include <linux/hrtimer.h>
+#include <linux/ion.h>
DEFINE_MUTEX(ctrl_cmd_lock);
#define CAMERA_STOP_VIDEO 58
@@ -56,6 +57,8 @@
static enum msm_camera_type camera_type[MSM_MAX_CAMERA_SENSORS];
static uint32_t sensor_mount_angle[MSM_MAX_CAMERA_SENSORS];
+struct ion_client *client_for_ion;
+
static const char *vfe_config_cmd[] = {
"CMD_GENERAL", /* 0 */
"CMD_AXI_CFG_OUT1",
@@ -293,29 +296,41 @@
struct msm_pmem_info *info, spinlock_t* pmem_spinlock,
struct msm_sync *sync)
{
- struct file *file;
unsigned long paddr;
+#ifndef CONFIG_MSM_MULTIMEDIA_USE_ION
+ struct file *file;
unsigned long kvstart;
+#endif
unsigned long len;
- int rc;
+ int rc = -ENOMEM;
struct msm_pmem_region *region;
unsigned long flags;
-
+ region = kmalloc(sizeof(struct msm_pmem_region), GFP_KERNEL);
+ if (!region)
+ goto out;
+#ifdef CONFIG_MSM_MULTIMEDIA_USE_ION
+ region->handle = ion_import_fd(client_for_ion, info->fd);
+ if (IS_ERR_OR_NULL(region->handle))
+ goto out1;
+ ion_phys(client_for_ion, region->handle,
+ &paddr, (size_t *)&len);
+#else
rc = get_pmem_file(info->fd, &paddr, &kvstart, &len, &file);
if (rc < 0) {
pr_err("%s: get_pmem_file fd %d error %d\n",
__func__,
info->fd, rc);
- return rc;
+ goto out1;
}
-
+ region->file = file;
+#endif
if (!info->len)
info->len = len;
rc = check_pmem_info(info, len);
if (rc < 0)
- return rc;
+ goto out2;
paddr += info->offset;
len = info->len;
@@ -323,29 +338,33 @@
spin_lock_irqsave(pmem_spinlock, flags);
if (check_overlap(ptype, paddr, len) < 0) {
spin_unlock_irqrestore(pmem_spinlock, flags);
- return -EINVAL;
+ rc = -EINVAL;
+ goto out2;
}
spin_unlock_irqrestore(pmem_spinlock, flags);
-
- region = kmalloc(sizeof(struct msm_pmem_region), GFP_KERNEL);
- if (!region)
- return -ENOMEM;
-
spin_lock_irqsave(pmem_spinlock, flags);
INIT_HLIST_NODE(®ion->list);
region->paddr = paddr;
region->len = len;
- region->file = file;
memcpy(®ion->info, info, sizeof(region->info));
hlist_add_head(&(region->list), ptype);
spin_unlock_irqrestore(pmem_spinlock, flags);
CDBG("%s: type %d, paddr 0x%lx, vaddr 0x%lx\n",
__func__, info->type, paddr, (unsigned long)info->vaddr);
-
return 0;
+out2:
+#ifdef CONFIG_MSM_MULTIMEDIA_USE_ION
+ ion_free(client_for_ion, region->handle);
+#else
+ put_pmem_file(region->file);
+#endif
+out1:
+ kfree(region);
+out:
+ return rc;
}
/* return of 0 means failure */
@@ -616,7 +635,11 @@
pinfo->vaddr == region->info.vaddr &&
pinfo->fd == region->info.fd) {
hlist_del(node);
+#ifdef CONFIG_MSM_MULTIMEDIA_USE_ION
+ ion_free(client_for_ion, region->handle);
+#else
put_pmem_file(region->file);
+#endif
kfree(region);
CDBG("%s: type %d, vaddr 0x%p\n",
__func__, pinfo->type, pinfo->vaddr);
@@ -636,7 +659,11 @@
pinfo->vaddr == region->info.vaddr &&
pinfo->fd == region->info.fd) {
hlist_del(node);
+#ifdef CONFIG_MSM_MULTIMEDIA_USE_ION
+ ion_free(client_for_ion, region->handle);
+#else
put_pmem_file(region->file);
+#endif
kfree(region);
CDBG("%s: type %d, vaddr 0x%p\n",
__func__, pinfo->type, pinfo->vaddr);
@@ -655,7 +682,11 @@
pinfo->vaddr == region->info.vaddr &&
pinfo->fd == region->info.fd) {
hlist_del(node);
+#ifdef CONFIG_MSM_MULTIMEDIA_USE_ION
+ ion_free(client_for_ion, region->handle);
+#else
put_pmem_file(region->file);
+#endif
kfree(region);
CDBG("%s: type %d, vaddr 0x%p\n",
__func__, pinfo->type, pinfo->vaddr);
@@ -3013,14 +3044,22 @@
hlist_for_each_entry_safe(region, hnode, n,
&sync->pmem_frames, list) {
hlist_del(hnode);
+#ifdef CONFIG_MSM_MULTIMEDIA_USE_ION
+ ion_free(client_for_ion, region->handle);
+#else
put_pmem_file(region->file);
+#endif
kfree(region);
}
CDBG("%s, free stats pmem region\n", __func__);
hlist_for_each_entry_safe(region, hnode, n,
&sync->pmem_stats, list) {
hlist_del(hnode);
+#ifdef CONFIG_MSM_MULTIMEDIA_USE_ION
+ ion_free(client_for_ion, region->handle);
+#else
put_pmem_file(region->file);
+#endif
kfree(region);
}
msm_queue_drain(&sync->pict_q, list_pict);
@@ -3031,6 +3070,7 @@
sync->core_powered_on = 0;
}
mutex_unlock(&sync->lock);
+ ion_client_destroy(client_for_ion);
return 0;
}
@@ -3733,6 +3773,7 @@
sync->core_powered_on = 1;
}
sync->opencnt++;
+ client_for_ion = msm_ion_client_create(-1, "camera");
msm_open_done:
mutex_unlock(&sync->lock);
diff --git a/drivers/media/video/msm/msm_io_8960.c b/drivers/media/video/msm/msm_io_8960.c
index 0e4429e..1293c7b 100644
--- a/drivers/media/video/msm/msm_io_8960.c
+++ b/drivers/media/video/msm/msm_io_8960.c
@@ -25,74 +25,8 @@
#include <mach/msm_bus.h>
#include <mach/msm_bus_board.h>
-#define DBG_CSID 0
-#define DBG_CSIPHY 0
#define BUFF_SIZE_128 128
-/* MIPI CSI PHY registers */
-#define MIPI_CSIPHY_LNn_CFG1_ADDR 0x0
-#define MIPI_CSIPHY_LNn_CFG2_ADDR 0x4
-#define MIPI_CSIPHY_LNn_CFG3_ADDR 0x8
-#define MIPI_CSIPHY_LNn_CFG4_ADDR 0xC
-#define MIPI_CSIPHY_LNn_CFG5_ADDR 0x10
-#define MIPI_CSIPHY_LNCK_CFG1_ADDR 0x100
-#define MIPI_CSIPHY_LNCK_CFG2_ADDR 0x104
-#define MIPI_CSIPHY_LNCK_CFG3_ADDR 0x108
-#define MIPI_CSIPHY_LNCK_CFG4_ADDR 0x10C
-#define MIPI_CSIPHY_LNCK_CFG5_ADDR 0x110
-#define MIPI_CSIPHY_LNCK_MISC1_ADDR 0x128
-#define MIPI_CSIPHY_GLBL_T_INIT_CFG0_ADDR 0x1E0
-#define MIPI_CSIPHY_T_WAKEUP_CFG0_ADDR 0x1E8
-#define MIPI_CSIPHY_GLBL_PWR_CFG_ADDR 0x0144
-#define MIPI_CSIPHY_INTERRUPT_STATUS0_ADDR 0x0180
-#define MIPI_CSIPHY_INTERRUPT_STATUS1_ADDR 0x0184
-#define MIPI_CSIPHY_INTERRUPT_STATUS2_ADDR 0x0188
-#define MIPI_CSIPHY_INTERRUPT_STATUS3_ADDR 0x018C
-#define MIPI_CSIPHY_INTERRUPT_STATUS4_ADDR 0x0190
-#define MIPI_CSIPHY_INTERRUPT_MASK0_ADDR 0x01A0
-#define MIPI_CSIPHY_INTERRUPT_MASK1_ADDR 0x01A4
-#define MIPI_CSIPHY_INTERRUPT_MASK2_ADDR 0x01A8
-#define MIPI_CSIPHY_INTERRUPT_MASK3_ADDR 0x01AC
-#define MIPI_CSIPHY_INTERRUPT_MASK4_ADDR 0x01B0
-#define MIPI_CSIPHY_INTERRUPT_CLEAR0_ADDR 0x01C0
-#define MIPI_CSIPHY_INTERRUPT_CLEAR1_ADDR 0x01C4
-#define MIPI_CSIPHY_INTERRUPT_CLEAR2_ADDR 0x01C8
-#define MIPI_CSIPHY_INTERRUPT_CLEAR3_ADDR 0x01CC
-#define MIPI_CSIPHY_INTERRUPT_CLEAR4_ADDR 0x01D0
-
-/* MIPI CSID registers */
-#define CSID_HW_VERSION_ADDR 0x0
-#define CSID_CORE_CTRL_ADDR 0x4
-#define CSID_RST_CMD_ADDR 0x8
-#define CSID_CID_LUT_VC_0_ADDR 0xc
-#define CSID_CID_LUT_VC_1_ADDR 0x10
-#define CSID_CID_LUT_VC_2_ADDR 0x14
-#define CSID_CID_LUT_VC_3_ADDR 0x18
-#define CSID_CID_n_CFG_ADDR 0x1C
-#define CSID_IRQ_CLEAR_CMD_ADDR 0x5c
-#define CSID_IRQ_MASK_ADDR 0x60
-#define CSID_IRQ_STATUS_ADDR 0x64
-#define CSID_CAPTURED_UNMAPPED_LONG_PKT_HDR_ADDR 0x68
-#define CSID_CAPTURED_MMAPPED_LONG_PKT_HDR_ADDR 0x6c
-#define CSID_CAPTURED_SHORT_PKT_ADDR 0x70
-#define CSID_CAPTURED_LONG_PKT_HDR_ADDR 0x74
-#define CSID_CAPTURED_LONG_PKT_FTR_ADDR 0x78
-#define CSID_PIF_MISR_DL0_ADDR 0x7C
-#define CSID_PIF_MISR_DL1_ADDR 0x80
-#define CSID_PIF_MISR_DL2_ADDR 0x84
-#define CSID_PIF_MISR_DL3_ADDR 0x88
-#define CSID_STATS_TOTAL_PKTS_RCVD_ADDR 0x8C
-#define CSID_STATS_ECC_ADDR 0x90
-#define CSID_STATS_CRC_ADDR 0x94
-#define CSID_TG_CTRL_ADDR 0x9C
-#define CSID_TG_VC_CFG_ADDR 0xA0
-#define CSID_TG_DT_n_CFG_0_ADDR 0xA8
-#define CSID_TG_DT_n_CFG_1_ADDR 0xAC
-#define CSID_TG_DT_n_CFG_2_ADDR 0xB0
-#define CSID_TG_DT_n_CFG_3_ADDR 0xD8
-
-/* Regulator Voltage and Current */
-
#define CAM_VAF_MINUV 2800000
#define CAM_VAF_MAXUV 2800000
#define CAM_VDIG_MINUV 1200000
@@ -107,35 +41,11 @@
#define CAM_VANA_LOAD_UA 85600
#define CAM_CSI_LOAD_UA 20000
-#define CSID_VERSION_V2 0x2000011
-
-static uint32_t csid_hw_version;
static struct clk *camio_cam_clk;
-static struct clk *camio_vfe_clk;
-static struct clk *camio_csi_src_clk;
-static struct clk *camio_csi1_src_clk;
-static struct clk *camio_csi0_vfe_clk;
-static struct clk *camio_csi0_clk;
-static struct clk *camio_csi0_pclk;
-static struct clk *camio_csi_pix_clk;
-static struct clk *camio_csi_pix1_clk;
-static struct clk *camio_csi_rdi_clk;
-static struct clk *camio_csi_rdi1_clk;
-static struct clk *camio_csi_rdi2_clk;
-static struct clk *camio_csiphy0_timer_clk;
-static struct clk *camio_csiphy1_timer_clk;
-static struct clk *camio_vfe_pclk;
-static struct clk *camio_csi0_phy_clk;
-static struct clk *camio_csiphy_timer_src_clk;
-/*static struct clk *camio_vfe_pclk;*/
static struct clk *camio_jpeg_clk;
static struct clk *camio_jpeg_pclk;
-static struct clk *camio_vpe_clk;
-static struct clk *camio_vpe_pclk;
-static struct regulator *fs_vfe;
static struct regulator *fs_ijpeg;
-static struct regulator *fs_vpe;
static struct regulator *cam_vana;
static struct regulator *cam_vio;
static struct regulator *cam_vdig;
@@ -144,10 +54,9 @@
static struct msm_camera_io_clk camio_clk;
static struct platform_device *camio_dev;
-static struct resource *csidio, *csiphyio, *s3drw_io, *s3dctl_io;
-static struct resource *csid_mem, *csiphy_mem, *s3drw_mem, *s3dctl_mem;
-static struct resource *csid_irq, *csiphy_irq;
-void __iomem *csidbase, *csiphybase, *s3d_rw, *s3d_ctl;
+static struct resource *s3drw_io, *s3dctl_io;
+static struct resource *s3drw_mem, *s3dctl_mem;
+void __iomem *s3d_rw, *s3d_ctl;
struct msm_bus_scale_pdata *cam_bus_scale_table;
@@ -338,18 +247,6 @@
goto cam_vaf_disable;
}
}
- if (fs_vfe == NULL) {
- fs_vfe = regulator_get(&pdev->dev, "fs_vfe");
- if (IS_ERR(fs_vfe)) {
- pr_err("%s: Regulator FS_VFE get failed %ld\n",
- __func__, PTR_ERR(fs_vfe));
- fs_vfe = NULL;
- } else if (regulator_enable(fs_vfe)) {
- pr_err("%s: Regulator FS_VFE enable failed\n",
- __func__);
- regulator_put(fs_vfe);
- }
- }
return 0;
cam_vaf_disable:
@@ -432,21 +329,12 @@
regulator_put(cam_vaf);
cam_vaf = NULL;
}
-
- if (fs_vfe) {
- regulator_disable(fs_vfe);
- regulator_put(fs_vfe);
- fs_vfe = NULL;
- }
}
int msm_camio_clk_enable(enum msm_camio_clk_type clktype)
{
int rc = 0;
struct clk *clk = NULL;
- struct msm_camera_sensor_info *sinfo = camio_dev->dev.platform_data;
- struct msm_camera_device_platform_data *camdev = sinfo->pdata;
- uint8_t csid_core = camdev->csid_core;
switch (clktype) {
case CAMIO_CAM_MCLK_CLK:
@@ -455,105 +343,6 @@
msm_camio_clk_rate_set_2(clk, camio_clk.mclk_clk_rate);
break;
- case CAMIO_VFE_CLK:
- camio_vfe_clk =
- clk = clk_get(NULL, "vfe_clk");
- msm_camio_clk_rate_set_2(clk, camio_clk.vfe_clk_rate);
- break;
-
- case CAMIO_VFE_PCLK:
- camio_vfe_pclk =
- clk = clk_get(NULL, "vfe_pclk");
- break;
-
- case CAMIO_CSI0_VFE_CLK:
- camio_csi0_vfe_clk =
- clk = clk_get(NULL, "csi_vfe_clk");
- break;
-/*
- case CAMIO_CSI1_VFE_CLK:
- camio_csi1_vfe_clk =
- clk = clk_get(&camio_dev->dev, "csi_vfe_clk");
- break;
-*/
- case CAMIO_CSI_SRC_CLK:
- camio_csi_src_clk =
- clk = clk_get(NULL, "csi_src_clk");
- msm_camio_clk_rate_set_2(clk, 177780000);
- break;
-
- case CAMIO_CSI1_SRC_CLK:
- camio_csi1_src_clk =
- clk = clk_get(&camio_dev->dev, "csi_src_clk");
- msm_camio_clk_rate_set_2(clk, 177780000);
- break;
-
- case CAMIO_CSI0_CLK:
- camio_csi0_clk =
- clk = clk_get(&camio_dev->dev, "csi_clk");
- break;
-
- case CAMIO_CSI0_PHY_CLK:
- camio_csi0_phy_clk =
- clk = clk_get(&camio_dev->dev, "csi_phy_clk");
- break;
-
- case CAMIO_CSI_PIX_CLK:
- camio_csi_pix_clk =
- clk = clk_get(NULL, "csi_pix_clk");
- /* mux to select between csid0 and csid1 */
- msm_camio_clk_rate_set_2(clk, csid_core);
- break;
-
- case CAMIO_CSI_PIX1_CLK:
- camio_csi_pix1_clk =
- clk = clk_get(NULL, "csi_pix1_clk");
- /* mux to select between csid0 and csid1 */
- msm_camio_clk_rate_set_2(clk, csid_core);
- break;
-
- case CAMIO_CSI_RDI_CLK:
- camio_csi_rdi_clk =
- clk = clk_get(NULL, "csi_rdi_clk");
- /* mux to select between csid0 and csid1 */
- msm_camio_clk_rate_set_2(clk, csid_core);
- break;
-
- case CAMIO_CSI_RDI1_CLK:
- camio_csi_rdi1_clk =
- clk = clk_get(NULL, "csi_rdi1_clk");
- /* mux to select between csid0 and csid1 */
- msm_camio_clk_rate_set_2(clk, csid_core);
- break;
-
- case CAMIO_CSI_RDI2_CLK:
- camio_csi_rdi2_clk =
- clk = clk_get(NULL, "csi_rdi2_clk");
- /* mux to select between csid0 and csid1 */
- msm_camio_clk_rate_set_2(clk, csid_core);
- break;
-
- case CAMIO_CSIPHY0_TIMER_CLK:
- camio_csiphy0_timer_clk =
- clk = clk_get(NULL, "csi0phy_timer_clk");
- break;
-
- case CAMIO_CSIPHY1_TIMER_CLK:
- camio_csiphy1_timer_clk =
- clk = clk_get(NULL, "csi1phy_timer_clk");
- break;
-
- case CAMIO_CSIPHY_TIMER_SRC_CLK:
- camio_csiphy_timer_src_clk =
- clk = clk_get(NULL, "csiphy_timer_src_clk");
- msm_camio_clk_rate_set_2(clk, 177780000);
- break;
-
- case CAMIO_CSI0_PCLK:
- camio_csi0_pclk =
- clk = clk_get(NULL, "csi_pclk");
- break;
-
case CAMIO_JPEG_CLK:
camio_jpeg_clk =
clk = clk_get(NULL, "ijpeg_clk");
@@ -565,17 +354,6 @@
clk = clk_get(NULL, "ijpeg_pclk");
break;
- case CAMIO_VPE_CLK:
- camio_vpe_clk =
- clk = clk_get(NULL, "vpe_clk");
- msm_camio_clk_set_min_rate(clk, 150000000);
- break;
-
- case CAMIO_VPE_PCLK:
- camio_vpe_pclk =
- clk = clk_get(NULL, "vpe_pclk");
- break;
-
default:
break;
}
@@ -601,62 +379,6 @@
clk = camio_cam_clk;
break;
- case CAMIO_VFE_CLK:
- clk = camio_vfe_clk;
- break;
-
- case CAMIO_VFE_PCLK:
- clk = camio_vfe_pclk;
- break;
-
- case CAMIO_CSI0_VFE_CLK:
- clk = camio_csi0_vfe_clk;
- break;
-
- case CAMIO_CSI_SRC_CLK:
- clk = camio_csi_src_clk;
- break;
-
- case CAMIO_CSI0_CLK:
- clk = camio_csi0_clk;
- break;
-
- case CAMIO_CSI0_PHY_CLK:
- clk = camio_csi0_phy_clk;
- break;
-
- case CAMIO_CSI_PIX1_CLK:
- clk = camio_csi_pix1_clk;
- break;
-
- case CAMIO_CSI_PIX_CLK:
- clk = camio_csi_pix_clk;
- break;
-
- case CAMIO_CSI_RDI1_CLK:
- clk = camio_csi_rdi1_clk;
- break;
-
- case CAMIO_CSI_RDI2_CLK:
- clk = camio_csi_rdi2_clk;
- break;
-
- case CAMIO_CSI_RDI_CLK:
- clk = camio_csi_rdi_clk;
- break;
-
- case CAMIO_CSIPHY0_TIMER_CLK:
- clk = camio_csiphy0_timer_clk;
- break;
-
- case CAMIO_CSIPHY_TIMER_SRC_CLK:
- clk = camio_csiphy_timer_src_clk;
- break;
-
- case CAMIO_CSI0_PCLK:
- clk = camio_csi0_pclk;
- break;
-
case CAMIO_JPEG_CLK:
clk = camio_jpeg_clk;
break;
@@ -665,14 +387,6 @@
clk = camio_jpeg_pclk;
break;
- case CAMIO_VPE_CLK:
- clk = camio_vpe_clk;
- break;
-
- case CAMIO_VPE_PCLK:
- clk = camio_vpe_pclk;
- break;
-
default:
break;
}
@@ -689,26 +403,6 @@
return rc;
}
-int msm_camio_vfe_clk_rate_set(int rate)
-{
- int rc = 0;
- int round_rate;
- struct clk *clk = camio_vfe_clk;
- round_rate = clk_round_rate(clk, rate);
- if (rc < 0) {
- pr_err("%s: clk_round_rate failed %d\n",
- __func__, rc);
- return rc;
- }
-
- rc = clk_set_rate(clk, round_rate);
- if (rc < 0)
- pr_err("%s: clk_set_rate failed %d\n",
- __func__, rc);
-
- return rc;
-}
-
void msm_camio_clk_rate_set(int rate)
{
struct clk *clk = camio_cam_clk;
@@ -725,210 +419,6 @@
clk_set_min_rate(clk, rate);
}
-#if DBG_CSID
-static irqreturn_t msm_io_csi_irq(int irq_num, void *data)
-{
- uint32_t irq;
- irq = msm_io_r(csidbase + CSID_IRQ_STATUS_ADDR);
- CDBG("%s CSID_IRQ_STATUS_ADDR = 0x%x\n", __func__, irq);
- msm_io_w(irq, csidbase + CSID_IRQ_CLEAR_CMD_ADDR);
- return IRQ_HANDLED;
-}
-#endif
-/*
-void msm_io_read_interrupt(void)
-{
- uint32_t irq;
- irq = msm_io_r(csiphybase + MIPI_CSIPHY_INTERRUPT_STATUS0_ADDR);
- CDBG("%s MIPI_CSIPHY_INTERRUPT_STATUS0 = 0x%x\n", __func__, irq);
- irq = msm_io_r(csiphybase + MIPI_CSIPHY_INTERRUPT_STATUS0_ADDR);
- CDBG("%s MIPI_CSIPHY_INTERRUPT_STATUS0 = 0x%x\n", __func__, irq);
- irq = msm_io_r(csiphybase + MIPI_CSIPHY_INTERRUPT_STATUS1_ADDR);
- CDBG("%s MIPI_CSIPHY_INTERRUPT_STATUS1 = 0x%x\n", __func__, irq);
- irq = msm_io_r(csiphybase + MIPI_CSIPHY_INTERRUPT_STATUS2_ADDR);
- CDBG("%s MIPI_CSIPHY_INTERRUPT_STATUS2 = 0x%x\n", __func__, irq);
- irq = msm_io_r(csiphybase + MIPI_CSIPHY_INTERRUPT_STATUS3_ADDR);
- CDBG("%s MIPI_CSIPHY_INTERRUPT_STATUS3 = 0x%x\n", __func__, irq);
- irq = msm_io_r(csiphybase + MIPI_CSIPHY_INTERRUPT_STATUS4_ADDR);
- CDBG("%s MIPI_CSIPHY_INTERRUPT_STATUS4 = 0x%x\n", __func__, irq);
- msm_io_w(irq, csiphybase + MIPI_CSIPHY_INTERRUPT_CLEAR0_ADDR);
- msm_io_w(irq, csiphybase + MIPI_CSIPHY_INTERRUPT_CLEAR1_ADDR);
- msm_io_w(irq, csiphybase + MIPI_CSIPHY_INTERRUPT_CLEAR2_ADDR);
- msm_io_w(irq, csiphybase + MIPI_CSIPHY_INTERRUPT_CLEAR3_ADDR);
- msm_io_w(irq, csiphybase + MIPI_CSIPHY_INTERRUPT_CLEAR4_ADDR);
- msm_io_w(0x1, csiphybase + 0x164);
- msm_io_w(0x0, csiphybase + 0x164);
- return;
-}
-*/
-#if DBG_CSIPHY
-static irqreturn_t msm_io_csiphy_irq(int irq_num, void *data)
-{
- uint32_t irq;
- irq = msm_io_r(csiphybase + MIPI_CSIPHY_INTERRUPT_STATUS0_ADDR);
- msm_io_w(irq, csiphybase + MIPI_CSIPHY_INTERRUPT_CLEAR0_ADDR);
- CDBG("%s MIPI_CSIPHY_INTERRUPT_STATUS0 = 0x%x\n", __func__, irq);
- irq = msm_io_r(csiphybase + MIPI_CSIPHY_INTERRUPT_STATUS1_ADDR);
- msm_io_w(irq, csiphybase + MIPI_CSIPHY_INTERRUPT_CLEAR1_ADDR);
- CDBG("%s MIPI_CSIPHY_INTERRUPT_STATUS1 = 0x%x\n", __func__, irq);
- irq = msm_io_r(csiphybase + MIPI_CSIPHY_INTERRUPT_STATUS2_ADDR);
- msm_io_w(irq, csiphybase + MIPI_CSIPHY_INTERRUPT_CLEAR2_ADDR);
- CDBG("%s MIPI_CSIPHY_INTERRUPT_STATUS2 = 0x%x\n", __func__, irq);
- irq = msm_io_r(csiphybase + MIPI_CSIPHY_INTERRUPT_STATUS3_ADDR);
- msm_io_w(irq, csiphybase + MIPI_CSIPHY_INTERRUPT_CLEAR3_ADDR);
- CDBG("%s MIPI_CSIPHY_INTERRUPT_STATUS3 = 0x%x\n", __func__, irq);
- irq = msm_io_r(csiphybase + MIPI_CSIPHY_INTERRUPT_STATUS4_ADDR);
- msm_io_w(irq, csiphybase + MIPI_CSIPHY_INTERRUPT_CLEAR4_ADDR);
- CDBG("%s MIPI_CSIPHY_INTERRUPT_STATUS4 = 0x%x\n", __func__, irq);
- msm_io_w(0x1, csiphybase + 0x164);
- msm_io_w(0x0, csiphybase + 0x164);
- return IRQ_HANDLED;
-}
-#endif
-
-static int msm_camio_enable_v2_clks(void)
-{
- int rc = 0;
- csid_hw_version = msm_io_r(csidbase +
- CSID_HW_VERSION_ADDR);
- CDBG("%s csid_hw_version %d\n",
- __func__,
- csid_hw_version);
-
- if (csid_hw_version == CSID_VERSION_V2) {
- rc = msm_camio_clk_enable(CAMIO_CSI_PIX1_CLK);
- if (rc < 0)
- goto csi_pix1_fail;
-
- rc = msm_camio_clk_enable(CAMIO_CSI_RDI1_CLK);
- if (rc < 0)
- goto csi_rdi1_fail;
-
- rc = msm_camio_clk_enable(CAMIO_CSI_RDI2_CLK);
- if (rc < 0)
- goto csi_rdi2_fail;
- }
-
- return rc;
-
-csi_rdi2_fail:
- msm_camio_clk_disable(CAMIO_CSI_RDI1_CLK);
-csi_rdi1_fail:
- msm_camio_clk_disable(CAMIO_CSI_PIX1_CLK);
-csi_pix1_fail:
- return rc;
-}
-
-static int msm_camio_enable_all_clks(uint8_t csid_core)
-{
- int rc = 0;
-
- rc = msm_camio_clk_enable(CAMIO_CSI_SRC_CLK);
- if (rc < 0)
- goto csi_src_fail;
- if (csid_core == 1) {
- rc = msm_camio_clk_enable(CAMIO_CSI1_SRC_CLK);
- if (rc < 0)
- goto csi1_src_fail;
- }
- rc = msm_camio_clk_enable(CAMIO_CSI0_CLK);
- if (rc < 0)
- goto csi0_fail;
- rc = msm_camio_clk_enable(CAMIO_CSI0_PHY_CLK);
- if (rc < 0)
- goto csi0_phy_fail;
- rc = msm_camio_clk_enable(CAMIO_CSIPHY_TIMER_SRC_CLK);
- if (rc < 0)
- goto csiphy_timer_src_fail;
- if (csid_core == 0) {
- rc = msm_camio_clk_enable(CAMIO_CSIPHY0_TIMER_CLK);
- if (rc < 0)
- goto csiphy0_timer_fail;
- } else if (csid_core == 1) {
- rc = msm_camio_clk_enable(CAMIO_CSIPHY1_TIMER_CLK);
- if (rc < 0)
- goto csiphy1_timer_fail;
- }
- rc = msm_camio_clk_enable(CAMIO_CSI0_PCLK);
- if (rc < 0)
- goto csi0p_fail;
-
- rc = msm_camio_clk_enable(CAMIO_VFE_CLK);
- if (rc < 0)
- goto vfe_fail;
- rc = msm_camio_clk_enable(CAMIO_VFE_PCLK);
- if (rc < 0)
- goto vfep_fail;
-
- rc = msm_camio_clk_enable(CAMIO_CSI0_VFE_CLK);
- if (rc < 0)
- goto csi0_vfe_fail;
- rc = msm_camio_clk_enable(CAMIO_CSI_PIX_CLK);
- if (rc < 0)
- goto csi_pix_fail;
- rc = msm_camio_clk_enable(CAMIO_CSI_RDI_CLK);
- if (rc < 0)
- goto csi_rdi_fail;
- return rc;
-
-csi_rdi_fail:
- msm_camio_clk_disable(CAMIO_CSI_PIX_CLK);
-csi_pix_fail:
- msm_camio_clk_disable(CAMIO_CSI0_VFE_CLK);
-csi0_vfe_fail:
- msm_camio_clk_disable(CAMIO_VFE_PCLK);
-vfep_fail:
- msm_camio_clk_disable(CAMIO_VFE_CLK);
-vfe_fail:
- msm_camio_clk_disable(CAMIO_CSI0_PCLK);
-csi0p_fail:
- msm_camio_clk_disable(CAMIO_CSIPHY0_TIMER_CLK);
-csiphy1_timer_fail:
- msm_camio_clk_disable(CAMIO_CSIPHY1_TIMER_CLK);
-csiphy0_timer_fail:
- msm_camio_clk_disable(CAMIO_CSIPHY_TIMER_SRC_CLK);
-csiphy_timer_src_fail:
- msm_camio_clk_disable(CAMIO_CSI0_PHY_CLK);
-csi0_phy_fail:
- msm_camio_clk_disable(CAMIO_CSI0_CLK);
-csi0_fail:
- msm_camio_clk_disable(CAMIO_CSI1_SRC_CLK);
-csi1_src_fail:
- msm_camio_clk_disable(CAMIO_CSI_SRC_CLK);
-csi_src_fail:
- return rc;
-}
-
-static void msm_camio_disable_v2_clks(void)
-{
- if (csid_hw_version == CSID_VERSION_V2) {
- msm_camio_clk_disable(CAMIO_CSI_RDI2_CLK);
- msm_camio_clk_disable(CAMIO_CSI_RDI1_CLK);
- msm_camio_clk_disable(CAMIO_CSI_PIX1_CLK);
- }
-}
-
-static void msm_camio_disable_all_clks(uint8_t csid_core)
-{
- msm_camio_disable_v2_clks();
- msm_camio_clk_disable(CAMIO_CSI_RDI_CLK);
- msm_camio_clk_disable(CAMIO_CSI_PIX_CLK);
- msm_camio_clk_disable(CAMIO_CSI0_VFE_CLK);
- msm_camio_clk_disable(CAMIO_VFE_PCLK);
- msm_camio_clk_disable(CAMIO_VFE_CLK);
- msm_camio_clk_disable(CAMIO_CSI0_PCLK);
- if (csid_core == 0)
- msm_camio_clk_disable(CAMIO_CSIPHY0_TIMER_CLK);
- else if (csid_core == 1)
- msm_camio_clk_disable(CAMIO_CSIPHY1_TIMER_CLK);
- msm_camio_clk_disable(CAMIO_CSIPHY_TIMER_SRC_CLK);
- msm_camio_clk_disable(CAMIO_CSI0_PHY_CLK);
- msm_camio_clk_disable(CAMIO_CSI0_CLK);
- if (csid_core == 1)
- msm_camio_clk_disable(CAMIO_CSI1_SRC_CLK);
- msm_camio_clk_disable(CAMIO_CSI_SRC_CLK);
-}
-
int msm_camio_jpeg_clk_disable(void)
{
int rc = 0;
@@ -971,42 +461,6 @@
return rc;
}
-int msm_camio_vpe_clk_disable(void)
-{
- int rc = 0;
- if (fs_vpe) {
- regulator_disable(fs_vpe);
- regulator_put(fs_vpe);
- }
-
- rc = msm_camio_clk_disable(CAMIO_VPE_CLK);
- if (rc < 0)
- return rc;
- rc = msm_camio_clk_disable(CAMIO_VPE_PCLK);
- return rc;
-}
-
-int msm_camio_vpe_clk_enable(uint32_t clk_rate)
-{
- int rc = 0;
- (void)clk_rate;
- fs_vpe = regulator_get(NULL, "fs_vpe");
- if (IS_ERR(fs_vpe)) {
- pr_err("%s: Regulator FS_VPE get failed %ld\n", __func__,
- PTR_ERR(fs_vpe));
- fs_vpe = NULL;
- } else if (regulator_enable(fs_vpe)) {
- pr_err("%s: Regulator FS_VPE enable failed\n", __func__);
- regulator_put(fs_vpe);
- }
-
- rc = msm_camio_clk_enable(CAMIO_VPE_CLK);
- if (rc < 0)
- return rc;
- rc = msm_camio_clk_enable(CAMIO_VPE_PCLK);
- return rc;
-}
-
static int config_gpio_table(int gpio_en)
{
struct msm_camera_sensor_info *sinfo = camio_dev->dev.platform_data;
@@ -1040,125 +494,6 @@
return rc;
}
-int msm_camio_enable(struct platform_device *pdev)
-{
- int rc = 0;
- struct msm_camera_sensor_info *sinfo = pdev->dev.platform_data;
- struct msm_camera_device_platform_data *camdev = sinfo->pdata;
- uint8_t csid_core = camdev->csid_core;
- char csid[] = "csid0";
- char csiphy[] = "csiphy0";
- if (csid_core < 0 || csid_core > 2)
- return -ENODEV;
-
- csid[4] = '0' + csid_core;
- csiphy[6] = '0' + csid_core;
-
- camio_dev = pdev;
- camio_clk = camdev->ioclk;
- cam_bus_scale_table = camdev->cam_bus_scale_table;
-
- rc = msm_camio_enable_all_clks(csid_core);
- if (rc < 0)
- return rc;
-
- csid_mem = platform_get_resource_byname(pdev, IORESOURCE_MEM, csid);
- if (!csid_mem) {
- pr_err("%s: no mem resource?\n", __func__);
- return -ENODEV;
- }
- csid_irq = platform_get_resource_byname(pdev, IORESOURCE_IRQ, csid);
- if (!csid_irq) {
- pr_err("%s: no irq resource?\n", __func__);
- return -ENODEV;
- }
- csiphy_mem = platform_get_resource_byname(pdev, IORESOURCE_MEM, csiphy);
- if (!csiphy_mem) {
- pr_err("%s: no mem resource?\n", __func__);
- return -ENODEV;
- }
- csiphy_irq = platform_get_resource_byname(pdev, IORESOURCE_IRQ, csiphy);
- if (!csiphy_irq) {
- pr_err("%s: no irq resource?\n", __func__);
- return -ENODEV;
- }
-
- csidio = request_mem_region(csid_mem->start,
- resource_size(csid_mem), pdev->name);
- if (!csidio) {
- rc = -EBUSY;
- goto common_fail;
- }
- csidbase = ioremap(csid_mem->start,
- resource_size(csid_mem));
- if (!csidbase) {
- rc = -ENOMEM;
- goto csi_busy;
- }
-#if DBG_CSID
- rc = request_irq(csid_irq->start, msm_io_csi_irq,
- IRQF_TRIGGER_RISING, "csid", 0);
- if (rc < 0)
- goto csi_irq_fail;
-#endif
- csiphyio = request_mem_region(csiphy_mem->start,
- resource_size(csiphy_mem), pdev->name);
- if (!csidio) {
- rc = -EBUSY;
- goto csi_irq_fail;
- }
- csiphybase = ioremap(csiphy_mem->start,
- resource_size(csiphy_mem));
- if (!csiphybase) {
- rc = -ENOMEM;
- goto csiphy_busy;
- }
-#if DBG_CSIPHY
- rc = request_irq(csiphy_irq->start, msm_io_csiphy_irq,
- IRQF_TRIGGER_RISING, "csiphy", 0);
- if (rc < 0)
- goto csiphy_irq_fail;
-#endif
- msm_camio_enable_v2_clks();
- CDBG("camio enable done\n");
- return 0;
-#if DBG_CSIPHY
-csiphy_irq_fail:
- iounmap(csiphybase);
-#endif
-csiphy_busy:
- release_mem_region(csiphy_mem->start, resource_size(csiphy_mem));
-csi_irq_fail:
- iounmap(csidbase);
-csi_busy:
- release_mem_region(csid_mem->start, resource_size(csid_mem));
-common_fail:
- msm_camio_disable_all_clks(csid_core);
- msm_camera_vreg_disable();
- config_gpio_table(0);
- return rc;
-}
-
-void msm_camio_disable(struct platform_device *pdev)
-{
- struct msm_camera_sensor_info *sinfo = pdev->dev.platform_data;
- struct msm_camera_device_platform_data *camdev = sinfo->pdata;
- uint8_t csid_core = camdev->csid_core;
-#if DBG_CSIPHY
- free_irq(csiphy_irq->start, 0);
-#endif
- iounmap(csiphybase);
- release_mem_region(csiphy_mem->start, resource_size(csiphy_mem));
-
-#if DBG_CSID
- free_irq(csid_irq->start, 0);
-#endif
- iounmap(csidbase);
- release_mem_region(csid_mem->start, resource_size(csid_mem));
-
- msm_camio_disable_all_clks(csid_core);
-}
-
int32_t msm_camio_3d_enable(const struct msm_camera_sensor_info *s_info)
{
int32_t val = 0, rc = 0;
@@ -1306,103 +641,6 @@
return msm_camio_clk_disable(CAMIO_CAM_MCLK_CLK);
}
-int msm_camio_csid_cid_lut(struct msm_camera_csid_lut_params *csid_lut_params)
-{
- int rc = 0, i = 0;
- uint32_t val = 0;
-
- for (i = 0; i < csid_lut_params->num_cid && i < 4; i++) {
- if (csid_lut_params->vc_cfg[i].dt < 0x12 ||
- csid_lut_params->vc_cfg[i].dt > 0x37) {
- CDBG("%s: unsupported data type 0x%x\n",
- __func__, csid_lut_params->vc_cfg[i].dt);
- return rc;
- }
- val = msm_io_r(csidbase + CSID_CID_LUT_VC_0_ADDR +
- (csid_lut_params->vc_cfg[i].cid >> 2) * 4)
- & ~(0xFF << csid_lut_params->vc_cfg[i].cid * 8);
- val |= csid_lut_params->vc_cfg[i].dt <<
- csid_lut_params->vc_cfg[i].cid * 8;
- msm_io_w(val, csidbase + CSID_CID_LUT_VC_0_ADDR +
- (csid_lut_params->vc_cfg[i].cid >> 2) * 4);
- val = csid_lut_params->vc_cfg[i].decode_format << 4 | 0x3;
- msm_io_w(val, csidbase + CSID_CID_n_CFG_ADDR +
- (csid_lut_params->vc_cfg[i].cid * 4));
- }
- return rc;
-}
-
-int msm_camio_csid_config(struct msm_camera_csid_params *csid_params)
-{
- int rc = 0;
- uint32_t val = 0;
- val = csid_params->lane_cnt - 1;
- val |= csid_params->lane_assign << 2;
- val |= 0x1 << 10;
- val |= 0x1 << 11;
- val |= 0x1 << 12;
- val |= 0x1 << 28;
- msm_io_w(val, csidbase + CSID_CORE_CTRL_ADDR);
-
- rc = msm_camio_csid_cid_lut(&csid_params->lut_params);
- if (rc < 0)
- return rc;
-
- msm_io_w(0x7fF10800, csidbase + CSID_IRQ_MASK_ADDR);
- msm_io_w(0x7fF10800, csidbase + CSID_IRQ_CLEAR_CMD_ADDR);
-
- msleep(20);
- return rc;
-}
-
-int msm_camio_csiphy_config(struct msm_camera_csiphy_params *csiphy_params)
-{
- int rc = 0;
- int i = 0;
- uint32_t val = 0;
- if (csiphy_params->lane_cnt < 1 || csiphy_params->lane_cnt > 4) {
- CDBG("%s: unsupported lane cnt %d\n",
- __func__, csiphy_params->lane_cnt);
- return rc;
- }
-
- val = 0x3;
- msm_io_w((((1 << csiphy_params->lane_cnt) - 1) << 2) | val,
- csiphybase + MIPI_CSIPHY_GLBL_PWR_CFG_ADDR);
- msm_io_w(0x1, csiphybase + MIPI_CSIPHY_GLBL_T_INIT_CFG0_ADDR);
- msm_io_w(0x1, csiphybase + MIPI_CSIPHY_T_WAKEUP_CFG0_ADDR);
-
- for (i = 0; i < csiphy_params->lane_cnt; i++) {
- msm_io_w(0x10, csiphybase + MIPI_CSIPHY_LNn_CFG1_ADDR + 0x40*i);
- msm_io_w(0x5F, csiphybase + MIPI_CSIPHY_LNn_CFG2_ADDR + 0x40*i);
- msm_io_w(csiphy_params->settle_cnt,
- csiphybase + MIPI_CSIPHY_LNn_CFG3_ADDR + 0x40*i);
- msm_io_w(0x00000052,
- csiphybase + MIPI_CSIPHY_LNn_CFG5_ADDR + 0x40*i);
- }
-
- msm_io_w(0x00000000, csiphybase + MIPI_CSIPHY_LNCK_CFG1_ADDR);
- msm_io_w(0x5F, csiphybase + MIPI_CSIPHY_LNCK_CFG2_ADDR);
- msm_io_w(csiphy_params->settle_cnt,
- csiphybase + MIPI_CSIPHY_LNCK_CFG3_ADDR);
- msm_io_w(0x5, csiphybase + MIPI_CSIPHY_LNCK_CFG4_ADDR);
- msm_io_w(0x2, csiphybase + MIPI_CSIPHY_LNCK_CFG5_ADDR);
- msm_io_w(0x0, csiphybase + 0x128);
-
- msm_io_w(0x24,
- csiphybase + MIPI_CSIPHY_INTERRUPT_MASK0_ADDR);
- msm_io_w(0x24,
- csiphybase + MIPI_CSIPHY_INTERRUPT_CLEAR0_ADDR);
-
- for (i = 1; i <= csiphy_params->lane_cnt; i++) {
- msm_io_w(0x6F,
- csiphybase + MIPI_CSIPHY_INTERRUPT_MASK0_ADDR + 0x4*i);
- msm_io_w(0x6F,
- csiphybase + MIPI_CSIPHY_INTERRUPT_CLEAR0_ADDR + 0x4*i);
- }
- return rc;
-}
-
void msm_camio_mode_config(enum msm_cam_mode mode)
{
uint32_t val;
@@ -1423,9 +661,13 @@
void msm_camio_set_perf_lvl(enum msm_bus_perf_setting perf_setting)
{
static uint32_t bus_perf_client;
+ struct msm_camera_sensor_info *sinfo = camio_dev->dev.platform_data;
+ struct msm_camera_device_platform_data *camdev = sinfo->pdata;
+
int rc = 0;
switch (perf_setting) {
case S_INIT:
+ cam_bus_scale_table = camdev->cam_bus_scale_table;
bus_perf_client =
msm_bus_scale_register_client(cam_bus_scale_table);
if (!bus_perf_client) {
diff --git a/drivers/media/video/msm/msm_isp.c b/drivers/media/video/msm/msm_isp.c
index e12d6b1..e4d4f27 100644
--- a/drivers/media/video/msm/msm_isp.c
+++ b/drivers/media/video/msm/msm_isp.c
@@ -638,7 +638,7 @@
int rc = -EINVAL;
void __user *argp = (void __user *)arg;
- struct v4l2_subdev *sd = &pmctl->isp_sdev->sd;
+ struct v4l2_subdev *sd = pmctl->isp_sdev->sd;
D("%s: cmd %d\n", __func__, _IOC_NR(cmd));
switch (cmd) {
diff --git a/drivers/media/video/msm/msm_mctl.c b/drivers/media/video/msm/msm_mctl.c
index a7fe8a2..a3cf004 100644
--- a/drivers/media/video/msm/msm_mctl.c
+++ b/drivers/media/video/msm/msm_mctl.c
@@ -28,6 +28,8 @@
#include <linux/android_pmem.h>
#include "msm.h"
+#include "msm_csid.h"
+#include "msm_csiphy.h"
#include "msm_ispif.h"
#ifdef CONFIG_MSM_CAMERA_DEBUG
@@ -188,7 +190,7 @@
ispif_params.params[0].csid = csid_core;
rc = v4l2_subdev_call(p_mctl->ispif_sdev, core, ioctl,
- VIDIOC_MSM_ISPSF_CFG, &ispif_params);
+ VIDIOC_MSM_ISPIF_CFG, &ispif_params);
if (rc < 0)
return rc;
}
@@ -207,17 +209,26 @@
case NOTIFY_VFE_BUF_EVT:
if (p_mctl->isp_sdev && p_mctl->isp_sdev->isp_notify) {
rc = p_mctl->isp_sdev->isp_notify(
- &p_mctl->isp_sdev->sd, notification, arg);
+ p_mctl->isp_sdev->sd, notification, arg);
}
break;
case NOTIFY_VPE_MSG_EVT:
if (p_mctl->isp_sdev && p_mctl->isp_sdev->isp_notify) {
rc = p_mctl->isp_sdev->isp_notify(
- &p_mctl->isp_sdev->sd_vpe, notification, arg);
+ p_mctl->isp_sdev->sd_vpe, notification, arg);
}
break;
case NOTIFY_PCLK_CHANGE:
- rc = msm_camio_vfe_clk_rate_set(*(uint32_t *)arg);
+ rc = v4l2_subdev_call(p_mctl->isp_sdev->sd, video,
+ s_crystal_freq, *(uint32_t *)arg, 0);
+ break;
+ case NOTIFY_CSIPHY_CFG:
+ rc = v4l2_subdev_call(p_mctl->csiphy_sdev,
+ core, ioctl, VIDIOC_MSM_CSIPHY_CFG, arg);
+ break;
+ case NOTIFY_CSID_CFG:
+ rc = v4l2_subdev_call(p_mctl->csid_sdev,
+ core, ioctl, VIDIOC_MSM_CSID_CFG, arg);
break;
default:
break;
@@ -313,11 +324,105 @@
return rc;
}
+static int msm_mctl_subdev_match_core(struct device *dev, void *data)
+{
+ int core_index = (int)data;
+ struct platform_device *pdev = to_platform_device(dev);
+
+ if (pdev->id == core_index)
+ return 1;
+ else
+ return 0;
+}
+
+static int msm_mctl_register_subdevs(struct msm_cam_media_controller *p_mctl,
+ int core_index)
+{
+ struct device_driver *driver;
+ struct device *dev;
+ int rc = -ENODEV;
+
+ /* register csiphy subdev */
+ driver = driver_find(MSM_CSIPHY_DRV_NAME, &platform_bus_type);
+ if (!driver)
+ goto out;
+
+ dev = driver_find_device(driver, NULL, (void *)core_index,
+ msm_mctl_subdev_match_core);
+ if (!dev)
+ goto out_put_driver;
+
+ p_mctl->csiphy_sdev = dev_get_drvdata(dev);
+ put_driver(driver);
+
+ /* register csid subdev */
+ driver = driver_find(MSM_CSID_DRV_NAME, &platform_bus_type);
+ if (!driver)
+ goto out;
+
+ dev = driver_find_device(driver, NULL, (void *)core_index,
+ msm_mctl_subdev_match_core);
+ if (!dev)
+ goto out_put_driver;
+
+ p_mctl->csid_sdev = dev_get_drvdata(dev);
+ put_driver(driver);
+
+ /* register ispif subdev */
+ driver = driver_find(MSM_ISPIF_DRV_NAME, &platform_bus_type);
+ if (!driver)
+ goto out;
+
+ dev = driver_find_device(driver, NULL, 0,
+ msm_mctl_subdev_match_core);
+ if (!dev)
+ goto out_put_driver;
+
+ p_mctl->ispif_sdev = dev_get_drvdata(dev);
+ put_driver(driver);
+
+ /* register vfe subdev */
+ driver = driver_find(MSM_VFE_DRV_NAME, &platform_bus_type);
+ if (!driver)
+ goto out;
+
+ dev = driver_find_device(driver, NULL, 0,
+ msm_mctl_subdev_match_core);
+ if (!dev)
+ goto out_put_driver;
+
+ p_mctl->isp_sdev->sd = dev_get_drvdata(dev);
+ put_driver(driver);
+
+ /* register vfe subdev */
+ driver = driver_find(MSM_VPE_DRV_NAME, &platform_bus_type);
+ if (!driver)
+ goto out;
+
+ dev = driver_find_device(driver, NULL, 0,
+ msm_mctl_subdev_match_core);
+ if (!dev)
+ goto out_put_driver;
+
+ p_mctl->isp_sdev->sd_vpe = dev_get_drvdata(dev);
+ put_driver(driver);
+
+ rc = 0;
+ return rc;
+out_put_driver:
+ put_driver(driver);
+out:
+ return rc;
+}
+
static int msm_mctl_open(struct msm_cam_media_controller *p_mctl,
const char *const apps_id)
{
int rc = 0;
struct msm_sync *sync = NULL;
+ struct msm_camera_sensor_info *sinfo;
+ struct msm_camera_device_platform_data *camdev;
+ uint8_t csid_core;
D("%s\n", __func__);
if (!p_mctl) {
pr_err("%s: param is NULL", __func__);
@@ -330,8 +435,21 @@
mutex_lock(&sync->lock);
/* open sub devices - once only*/
if (!sync->opencnt) {
+ uint32_t csid_version;
wake_lock(&sync->wake_lock);
+ sinfo = sync->pdev->dev.platform_data;
+ sync->pdev->resource = sinfo->resource;
+ sync->pdev->num_resources = sinfo->num_resources;
+ camdev = sinfo->pdata;
+ csid_core = camdev->csid_core;
+ rc = msm_mctl_register_subdevs(p_mctl, csid_core);
+ if (rc < 0) {
+ pr_err("%s: msm_mctl_register_subdevs failed:%d\n",
+ __func__, rc);
+ goto msm_open_done;
+ }
+
/* turn on clock */
rc = msm_camio_sensor_clk_on(sync->pdev);
if (rc < 0) {
@@ -340,19 +458,34 @@
goto msm_open_done;
}
+ rc = v4l2_subdev_call(p_mctl->csiphy_sdev, core, ioctl,
+ VIDIOC_MSM_CSIPHY_INIT, NULL);
+ if (rc < 0) {
+ pr_err("%s: csiphy initialization failed %d\n",
+ __func__, rc);
+ goto msm_open_done;
+ }
+
+ rc = v4l2_subdev_call(p_mctl->csid_sdev, core, ioctl,
+ VIDIOC_MSM_CSID_INIT, &csid_version);
+ if (rc < 0) {
+ pr_err("%s: csid initialization failed %d\n",
+ __func__, rc);
+ goto msm_open_done;
+ }
+
/* ISP first*/
if (p_mctl->isp_sdev && p_mctl->isp_sdev->isp_open)
rc = p_mctl->isp_sdev->isp_open(
- &p_mctl->isp_sdev->sd,
- &p_mctl->isp_sdev->sd_vpe, sync);
+ p_mctl->isp_sdev->sd,
+ p_mctl->isp_sdev->sd_vpe, sync);
if (rc < 0) {
pr_err("%s: isp init failed: %d\n", __func__, rc);
goto msm_open_done;
}
- /*This has to be after isp_open, because isp_open initialize
- *platform resource. This dependency needs to be removed. */
- rc = msm_ispif_init(&p_mctl->ispif_sdev, sync->pdev);
+ rc = v4l2_subdev_call(p_mctl->ispif_sdev, core, ioctl,
+ VIDIOC_MSM_ISPIF_INIT, &csid_version);
if (rc < 0) {
pr_err("%s: ispif initialization failed %d\n",
__func__, rc);
@@ -385,16 +518,21 @@
static int msm_mctl_release(struct msm_cam_media_controller *p_mctl)
{
- struct msm_sync *sync = NULL;
int rc = 0;
+ struct msm_sync *sync = &(p_mctl->sync);
- sync = &(p_mctl->sync);
-
- msm_ispif_release(p_mctl->ispif_sdev);
+ v4l2_subdev_call(p_mctl->ispif_sdev, core, ioctl,
+ VIDIOC_MSM_ISPIF_RELEASE, NULL);
if (p_mctl->isp_sdev && p_mctl->isp_sdev->isp_release)
p_mctl->isp_sdev->isp_release(&p_mctl->sync);
+ v4l2_subdev_call(p_mctl->csid_sdev, core, ioctl,
+ VIDIOC_MSM_CSID_RELEASE, NULL);
+
+ v4l2_subdev_call(p_mctl->csiphy_sdev, core, ioctl,
+ VIDIOC_MSM_CSIPHY_RELEASE, NULL);
+
if (p_mctl->sync.actctrl.a_power_down)
p_mctl->sync.actctrl.a_power_down();
diff --git a/drivers/media/video/msm/msm_mctl_pp.c b/drivers/media/video/msm/msm_mctl_pp.c
index 2bf95a0..8236dae 100644
--- a/drivers/media/video/msm/msm_mctl_pp.c
+++ b/drivers/media/video/msm/msm_mctl_pp.c
@@ -300,12 +300,12 @@
case VPE_CMD_INIT:
case VPE_CMD_DEINIT:
rc = msm_isp_subdev_ioctl_vpe(
- &p_mctl->isp_sdev->sd_vpe, pp_cmd, NULL);
+ p_mctl->isp_sdev->sd_vpe, pp_cmd, NULL);
break;
case VPE_CMD_DISABLE:
case VPE_CMD_RESET:
rc = msm_isp_subdev_ioctl_vpe(
- &p_mctl->isp_sdev->sd_vpe, pp_cmd, NULL);
+ p_mctl->isp_sdev->sd_vpe, pp_cmd, NULL);
break;
case VPE_CMD_ENABLE: {
struct msm_vpe_clock_rate clk_rate;
@@ -325,7 +325,7 @@
}
pp_cmd->value = (void *)&clk_rate;
rc = msm_isp_subdev_ioctl_vpe(
- &p_mctl->isp_sdev->sd_vpe, pp_cmd, NULL);
+ p_mctl->isp_sdev->sd_vpe, pp_cmd, NULL);
pp_cmd->value = argp;
break;
}
@@ -344,7 +344,7 @@
return -EFAULT;
pp_cmd->value = (void *)&flush_buf;
rc = msm_isp_subdev_ioctl_vpe(
- &p_mctl->isp_sdev->sd_vpe, pp_cmd, NULL);
+ p_mctl->isp_sdev->sd_vpe, pp_cmd, NULL);
if (rc == 0) {
if (copy_to_user((void *)argp,
&flush_buf,
@@ -372,7 +372,7 @@
return -EFAULT;
pp_cmd->value = (void *)&op_mode_cfg;
rc = msm_isp_subdev_ioctl_vpe(
- &p_mctl->isp_sdev->sd_vpe, pp_cmd, NULL);
+ p_mctl->isp_sdev->sd_vpe, pp_cmd, NULL);
break;
}
case VPE_CMD_INPUT_PLANE_CFG: {
@@ -390,7 +390,7 @@
return -EFAULT;
pp_cmd->value = (void *)&input_cfg;
rc = msm_isp_subdev_ioctl_vpe(
- &p_mctl->isp_sdev->sd_vpe, pp_cmd, NULL);
+ p_mctl->isp_sdev->sd_vpe, pp_cmd, NULL);
break;
}
case VPE_CMD_OUTPUT_PLANE_CFG: {
@@ -411,7 +411,7 @@
}
pp_cmd->value = (void *)&output_cfg;
rc = msm_isp_subdev_ioctl_vpe(
- &p_mctl->isp_sdev->sd_vpe, pp_cmd, NULL);
+ p_mctl->isp_sdev->sd_vpe, pp_cmd, NULL);
break;
}
case VPE_CMD_INPUT_PLANE_UPDATE: {
@@ -429,7 +429,7 @@
return -EFAULT;
pp_cmd->value = (void *)&input_update_cfg;
rc = msm_isp_subdev_ioctl_vpe(
- &p_mctl->isp_sdev->sd_vpe, pp_cmd, NULL);
+ p_mctl->isp_sdev->sd_vpe, pp_cmd, NULL);
break;
}
case VPE_CMD_SCALE_CFG_TYPE: {
@@ -447,7 +447,7 @@
return -EFAULT;
pp_cmd->value = (void *)&scaler_cfg;
rc = msm_isp_subdev_ioctl_vpe(
- &p_mctl->isp_sdev->sd_vpe, pp_cmd, NULL);
+ p_mctl->isp_sdev->sd_vpe, pp_cmd, NULL);
break;
}
case VPE_CMD_ZOOM: {
@@ -512,7 +512,7 @@
break;
}
rc = msm_isp_subdev_ioctl_vpe(
- &p_mctl->isp_sdev->sd_vpe, pp_cmd, (void *)zoom);
+ p_mctl->isp_sdev->sd_vpe, pp_cmd, (void *)zoom);
if (rc) {
kfree(zoom);
break;
diff --git a/drivers/media/video/msm/msm_vfe32.c b/drivers/media/video/msm/msm_vfe32.c
index 4a3e49f..c5cc55c 100644
--- a/drivers/media/video/msm/msm_vfe32.c
+++ b/drivers/media/video/msm/msm_vfe32.c
@@ -15,6 +15,8 @@
#include <linux/slab.h>
#include <linux/io.h>
#include <linux/atomic.h>
+#include <linux/regulator/consumer.h>
+#include <linux/clk.h>
#include <mach/irqs.h>
#include <mach/camera.h>
#include <media/v4l2-device.h>
@@ -23,7 +25,6 @@
#include "msm.h"
#include "msm_vfe32.h"
-#include "msm_ispif.h"
atomic_t irq_cnt;
@@ -54,8 +55,8 @@
vfe32_put_ch_ping_addr((chn), (addr)))
static struct vfe32_ctrl_type *vfe32_ctrl;
-static struct msm_camera_io_clk camio_clk;
static void *vfe_syncdata;
+static uint32_t vfe_clk_rate;
struct vfe32_isr_queue_cmd {
struct list_head list;
@@ -437,7 +438,7 @@
rp->evt_msg.type = MSM_CAMERA_MSG;
rp->evt_msg.msg_id = path;
rp->type = id;
- v4l2_subdev_notify(vfe32_ctrl->subdev, NOTIFY_VFE_BUF_EVT, rp);
+ v4l2_subdev_notify(&vfe32_ctrl->subdev, NOTIFY_VFE_BUF_EVT, rp);
spin_unlock_irqrestore(&vfe32_ctrl->sd_notify_lock, flags);
}
@@ -1019,7 +1020,7 @@
8 + ((vfe32_ctrl->sync_timer_number) * 12));
/* Sync Timer Pixel Duration */
value = *tbl++;
- val = camio_clk.vfe_clk_rate / 10000;
+ val = vfe_clk_rate / 10000;
val = 10000000 / val;
val = value * 10000 / val;
CDBG("%s: Pixel Clk Cycles!!! %d\n", __func__, val);
@@ -1205,7 +1206,7 @@
isp_msg_evt.msg_id = isp_msg_id;
isp_msg_evt.sof_count = vfe32_ctrl->vfeFrameId;
- v4l2_subdev_notify(vctrl->subdev,
+ v4l2_subdev_notify(&vctrl->subdev,
NOTIFY_ISP_MSG_EVT,
(void *)&isp_msg_evt);
}
@@ -2091,6 +2092,9 @@
}
msm_io_memcpy(vfe32_ctrl->vfebase + vfe32_cmd[cmd->id].offset,
cmdp, (vfe32_cmd[cmd->id].length));
+ cmdp_local = cmdp + V32_ASF_LEN/4;
+ msm_io_memcpy(vfe32_ctrl->vfebase + V32_ASF_SPECIAL_EFX_CFG_OFF,
+ cmdp_local, V32_ASF_SPECIAL_EFX_CFG_LEN);
break;
case VFE_CMD_PCA_ROLL_OFF_CFG:
@@ -2637,7 +2641,7 @@
msg.buf.ch_paddr[2] = ch2_paddr;
msg.frameCounter = vfe32_ctrl->vfeFrameId;
- v4l2_subdev_notify(vfe32_ctrl->subdev,
+ v4l2_subdev_notify(&vfe32_ctrl->subdev,
NOTIFY_VFE_MSG_OUT,
&msg);
return;
@@ -2703,13 +2707,13 @@
VFE_MODE_OF_OPERATION_SNAPSHOT) {
/* will add message for multi-shot. */
vfe32_ctrl->outpath.out0.capture_cnt--;
- vfe_send_outmsg(vfe32_ctrl->subdev,
+ vfe_send_outmsg(&vfe32_ctrl->subdev,
MSG_ID_OUTPUT_T, ch0_paddr,
ch1_paddr, ch2_paddr);
} else {
/* always send message for continous mode. */
/* if continuous mode, for display. (preview) */
- vfe_send_outmsg(vfe32_ctrl->subdev,
+ vfe_send_outmsg(&vfe32_ctrl->subdev,
MSG_ID_OUTPUT_P, ch0_paddr,
ch1_paddr, ch2_paddr);
}
@@ -2749,7 +2753,7 @@
vfe32_put_ch_addr(ping_pong,
vfe32_ctrl->outpath.out1.ch2,
free_buf->ch_paddr[2]);
- vfe_send_outmsg(vfe32_ctrl->subdev,
+ vfe_send_outmsg(&vfe32_ctrl->subdev,
MSG_ID_OUTPUT_T, ch0_paddr,
ch1_paddr, ch2_paddr);
}
@@ -2775,7 +2779,7 @@
vfe32_put_ch_addr(ping_pong,
vfe32_ctrl->outpath.out2.ch1,
free_buf->ch_paddr[1]);
- vfe_send_outmsg(vfe32_ctrl->subdev,
+ vfe_send_outmsg(&vfe32_ctrl->subdev,
MSG_ID_OUTPUT_S, ch0_paddr,
ch1_paddr, ch2_paddr);
}
@@ -2844,7 +2848,7 @@
vfe32_ctrl->operation_mode ==
VFE_MODE_OF_OPERATION_RAW_SNAPSHOT) {
vfe32_ctrl->outpath.out1.capture_cnt--;
- vfe_send_outmsg(vfe32_ctrl->subdev,
+ vfe_send_outmsg(&vfe32_ctrl->subdev,
MSG_ID_OUTPUT_S, ch0_paddr,
ch1_paddr, ch2_paddr);
}
@@ -2907,7 +2911,7 @@
vfe32_ctrl->outpath.out2.ch2,
free_buf->ch_paddr[2]);
- vfe_send_outmsg(vfe32_ctrl->subdev,
+ vfe_send_outmsg(&vfe32_ctrl->subdev,
MSG_ID_OUTPUT_V, ch0_paddr,
ch1_paddr, ch2_paddr);
@@ -2999,7 +3003,7 @@
goto stats_done;
}
- v4l2_subdev_notify(vfe32_ctrl->subdev,
+ v4l2_subdev_notify(&vfe32_ctrl->subdev,
NOTIFY_VFE_MSG_STATS,
&msgStats);
stats_done:
@@ -3295,91 +3299,6 @@
return IRQ_HANDLED;
}
-static int vfe32_resource_init(struct platform_device *pdev, void *sdata)
-{
- struct resource *vfemem, *vfeirq, *vfeio;
- int rc;
- struct msm_camera_sensor_info *s_info;
- s_info = pdev->dev.platform_data;
-
- pdev->resource = s_info->resource;
- pdev->num_resources = s_info->num_resources;
-
- vfemem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
- if (!vfemem) {
- pr_err("%s: no mem resource?\n", __func__);
- return -ENODEV;
- }
-
- vfeirq = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
- if (!vfeirq) {
- pr_err("%s: no irq resource?\n", __func__);
- return -ENODEV;
- }
-
- vfeio = request_mem_region(vfemem->start,
- resource_size(vfemem), pdev->name);
- if (!vfeio) {
- pr_err("%s: VFE region already claimed\n", __func__);
- return -EBUSY;
- }
-
- vfe32_ctrl = kzalloc(sizeof(struct vfe32_ctrl_type), GFP_KERNEL);
- if (!vfe32_ctrl) {
- rc = -ENOMEM;
- goto cmd_init_failed1;
- }
-
- vfe32_ctrl->vfeirq = vfeirq->start;
-
- vfe32_ctrl->vfebase =
- ioremap(vfemem->start, (vfemem->end - vfemem->start) + 1);
- if (!vfe32_ctrl->vfebase) {
- rc = -ENOMEM;
- pr_err("%s: vfe ioremap failed\n", __func__);
- goto cmd_init_failed2;
- }
-
- vfe32_ctrl->extdata =
- kmalloc(sizeof(struct vfe32_frame_extra), GFP_KERNEL);
- if (!vfe32_ctrl->extdata) {
- rc = -ENOMEM;
- goto cmd_init_failed3;
- }
-
- vfe32_ctrl->extlen = sizeof(struct vfe32_frame_extra);
-
- spin_lock_init(&vfe32_ctrl->stop_flag_lock);
- spin_lock_init(&vfe32_ctrl->state_lock);
- spin_lock_init(&vfe32_ctrl->io_lock);
- spin_lock_init(&vfe32_ctrl->update_ack_lock);
- spin_lock_init(&vfe32_ctrl->tasklet_lock);
-
- spin_lock_init(&vfe32_ctrl->aec_ack_lock);
- spin_lock_init(&vfe32_ctrl->awb_ack_lock);
- spin_lock_init(&vfe32_ctrl->af_ack_lock);
- spin_lock_init(&vfe32_ctrl->sd_notify_lock);
- INIT_LIST_HEAD(&vfe32_ctrl->tasklet_q);
-
- vfe32_ctrl->syncdata = sdata;
- vfe32_ctrl->vfemem = vfemem;
- vfe32_ctrl->vfeio = vfeio;
- vfe32_ctrl->update_linear = false;
- vfe32_ctrl->update_rolloff = false;
- vfe32_ctrl->update_la = false;
- vfe32_ctrl->update_gamma = false;
- return 0;
-
-cmd_init_failed3:
- free_irq(vfe32_ctrl->vfeirq, 0);
- iounmap(vfe32_ctrl->vfebase);
-cmd_init_failed2:
- kfree(vfe32_ctrl);
-cmd_init_failed1:
- release_mem_region(vfemem->start, (vfemem->end - vfemem->start) + 1);
- return rc;
-}
-
static long msm_vfe_subdev_ioctl(struct v4l2_subdev *sd,
unsigned int subdev_cmd, void *arg)
{
@@ -3678,36 +3597,103 @@
return rc;
}
+static struct msm_cam_clk_info vfe32_clk_info[] = {
+ {"vfe_clk", 228570000},
+ {"vfe_pclk", -1},
+ {"csi_vfe_clk", -1},
+};
+
+static int msm_vfe_subdev_s_crystal_freq(struct v4l2_subdev *sd,
+ u32 freq, u32 flags)
+{
+ int rc = 0;
+ int round_rate;
+
+ round_rate = clk_round_rate(vfe32_ctrl->vfe_clk[0], freq);
+ if (rc < 0) {
+ pr_err("%s: clk_round_rate failed %d\n",
+ __func__, rc);
+ return rc;
+ }
+
+ vfe_clk_rate = round_rate;
+ rc = clk_set_rate(vfe32_ctrl->vfe_clk[0], round_rate);
+ if (rc < 0)
+ pr_err("%s: clk_set_rate failed %d\n",
+ __func__, rc);
+
+ return rc;
+}
+
+static const struct v4l2_subdev_video_ops msm_vfe_subdev_video_ops = {
+ .s_crystal_freq = msm_vfe_subdev_s_crystal_freq,
+};
+
static const struct v4l2_subdev_core_ops msm_vfe_subdev_core_ops = {
.ioctl = msm_vfe_subdev_ioctl,
};
static const struct v4l2_subdev_ops msm_vfe_subdev_ops = {
.core = &msm_vfe_subdev_core_ops,
+ .video = &msm_vfe_subdev_video_ops,
};
int msm_vfe_subdev_init(struct v4l2_subdev *sd, void *data,
struct platform_device *pdev)
{
int rc = 0;
- struct msm_camera_sensor_info *sinfo = pdev->dev.platform_data;
- struct msm_camera_device_platform_data *camdev = sinfo->pdata;
-
- v4l2_subdev_init(sd, &msm_vfe_subdev_ops);
v4l2_set_subdev_hostdata(sd, data);
- snprintf(sd->name, sizeof(sd->name), "vfe3.2");
-
vfe_syncdata = data;
- camio_clk = camdev->ioclk;
+ spin_lock_init(&vfe32_ctrl->stop_flag_lock);
+ spin_lock_init(&vfe32_ctrl->state_lock);
+ spin_lock_init(&vfe32_ctrl->io_lock);
+ spin_lock_init(&vfe32_ctrl->update_ack_lock);
+ spin_lock_init(&vfe32_ctrl->tasklet_lock);
- rc = vfe32_resource_init(pdev, vfe_syncdata);
+ spin_lock_init(&vfe32_ctrl->aec_ack_lock);
+ spin_lock_init(&vfe32_ctrl->awb_ack_lock);
+ spin_lock_init(&vfe32_ctrl->af_ack_lock);
+ spin_lock_init(&vfe32_ctrl->sd_notify_lock);
+ INIT_LIST_HEAD(&vfe32_ctrl->tasklet_q);
+
+ vfe32_ctrl->update_linear = false;
+ vfe32_ctrl->update_rolloff = false;
+ vfe32_ctrl->update_la = false;
+ vfe32_ctrl->update_gamma = false;
+
+ enable_irq(vfe32_ctrl->vfeirq->start);
+
+ vfe32_ctrl->vfebase = ioremap(vfe32_ctrl->vfemem->start,
+ resource_size(vfe32_ctrl->vfemem));
+ if (!vfe32_ctrl->vfebase) {
+ rc = -ENOMEM;
+ pr_err("%s: vfe ioremap failed\n", __func__);
+ goto vfe_remap_failed;
+ }
+
+ if (vfe32_ctrl->fs_vfe == NULL) {
+ vfe32_ctrl->fs_vfe =
+ regulator_get(&vfe32_ctrl->pdev->dev, "fs_vfe");
+ if (IS_ERR(vfe32_ctrl->fs_vfe)) {
+ pr_err("%s: Regulator FS_VFE get failed %ld\n",
+ __func__, PTR_ERR(vfe32_ctrl->fs_vfe));
+ vfe32_ctrl->fs_vfe = NULL;
+ goto vfe_fs_failed;
+ } else if (regulator_enable(vfe32_ctrl->fs_vfe)) {
+ pr_err("%s: Regulator FS_VFE enable failed\n",
+ __func__);
+ regulator_put(vfe32_ctrl->fs_vfe);
+ vfe32_ctrl->fs_vfe = NULL;
+ goto vfe_fs_failed;
+ }
+ }
+
+ rc = msm_cam_clk_enable(&vfe32_ctrl->pdev->dev, vfe32_clk_info,
+ vfe32_ctrl->vfe_clk, ARRAY_SIZE(vfe32_clk_info), 1);
if (rc < 0)
- return rc;
+ goto vfe_clk_enable_failed;
- vfe32_ctrl->subdev = sd;
- /* Bring up all the required GPIOs and Clocks */
- rc = msm_camio_enable(pdev);
msm_camio_set_perf_lvl(S_INIT);
msm_camio_set_perf_lvl(S_PREVIEW);
@@ -3717,38 +3703,118 @@
else
vfe32_ctrl->register_total = VFE33_REGISTER_TOTAL;
- /* TO DO: Need to release the VFE resources */
- rc = request_irq(vfe32_ctrl->vfeirq, vfe32_parse_irq,
- IRQF_TRIGGER_RISING, "vfe", 0);
+ return rc;
+vfe_clk_enable_failed:
+ regulator_disable(vfe32_ctrl->fs_vfe);
+ regulator_put(vfe32_ctrl->fs_vfe);
+ vfe32_ctrl->fs_vfe = NULL;
+vfe_fs_failed:
+ iounmap(vfe32_ctrl->vfebase);
+vfe_remap_failed:
+ disable_irq(vfe32_ctrl->vfeirq->start);
return rc;
}
void msm_vfe_subdev_release(struct platform_device *pdev)
{
- struct resource *vfemem, *vfeio;
-
+ msm_cam_clk_enable(&vfe32_ctrl->pdev->dev, vfe32_clk_info,
+ vfe32_ctrl->vfe_clk, ARRAY_SIZE(vfe32_clk_info), 0);
+ if (vfe32_ctrl->fs_vfe) {
+ regulator_disable(vfe32_ctrl->fs_vfe);
+ regulator_put(vfe32_ctrl->fs_vfe);
+ vfe32_ctrl->fs_vfe = NULL;
+ }
CDBG("%s, free_irq\n", __func__);
- free_irq(vfe32_ctrl->vfeirq, 0);
+ disable_irq(vfe32_ctrl->vfeirq->start);
tasklet_kill(&vfe32_tasklet);
+ iounmap(vfe32_ctrl->vfebase);
if (atomic_read(&irq_cnt))
pr_warning("%s, Warning IRQ Count not ZERO\n", __func__);
- vfemem = vfe32_ctrl->vfemem;
- vfeio = vfe32_ctrl->vfeio;
-
- kfree(vfe32_ctrl->extdata);
- iounmap(vfe32_ctrl->vfebase);
- kfree(vfe32_ctrl);
- vfe32_ctrl = NULL;
- release_mem_region(vfemem->start, (vfemem->end - vfemem->start) + 1);
-
- CDBG("%s, msm_camio_disable\n", __func__);
- msm_camio_disable(pdev);
msm_camio_set_perf_lvl(S_EXIT);
-
vfe_syncdata = NULL;
}
+static int __devinit vfe32_probe(struct platform_device *pdev)
+{
+ int rc = 0;
+ CDBG("%s: device id = %d\n", __func__, pdev->id);
+ vfe32_ctrl = kzalloc(sizeof(struct vfe32_ctrl_type), GFP_KERNEL);
+ if (!vfe32_ctrl) {
+ pr_err("%s: no enough memory\n", __func__);
+ return -ENOMEM;
+ }
+ v4l2_subdev_init(&vfe32_ctrl->subdev, &msm_vfe_subdev_ops);
+ snprintf(vfe32_ctrl->subdev.name,
+ sizeof(vfe32_ctrl->subdev.name), "vfe3.2");
+ v4l2_set_subdevdata(&vfe32_ctrl->subdev, vfe32_ctrl);
+ platform_set_drvdata(pdev, &vfe32_ctrl->subdev);
+
+ vfe32_ctrl->vfemem = platform_get_resource_byname(pdev,
+ IORESOURCE_MEM, "vfe32");
+ if (!vfe32_ctrl->vfemem) {
+ pr_err("%s: no mem resource?\n", __func__);
+ rc = -ENODEV;
+ goto vfe32_no_resource;
+ }
+ vfe32_ctrl->vfeirq = platform_get_resource_byname(pdev,
+ IORESOURCE_IRQ, "vfe32");
+ if (!vfe32_ctrl->vfeirq) {
+ pr_err("%s: no irq resource?\n", __func__);
+ rc = -ENODEV;
+ goto vfe32_no_resource;
+ }
+
+ vfe32_ctrl->vfeio = request_mem_region(vfe32_ctrl->vfemem->start,
+ resource_size(vfe32_ctrl->vfemem), pdev->name);
+ if (!vfe32_ctrl->vfeio) {
+ pr_err("%s: no valid mem region\n", __func__);
+ rc = -EBUSY;
+ goto vfe32_no_resource;
+ }
+
+ rc = request_irq(vfe32_ctrl->vfeirq->start, vfe32_parse_irq,
+ IRQF_TRIGGER_RISING, "vfe", 0);
+ if (rc < 0) {
+ release_mem_region(vfe32_ctrl->vfemem->start,
+ resource_size(vfe32_ctrl->vfemem));
+ pr_err("%s: irq request fail\n", __func__);
+ rc = -EBUSY;
+ goto vfe32_no_resource;
+ }
+
+ disable_irq(vfe32_ctrl->vfeirq->start);
+
+ vfe32_ctrl->pdev = pdev;
+ return 0;
+
+vfe32_no_resource:
+ kfree(vfe32_ctrl);
+ return 0;
+}
+
+static struct platform_driver vfe32_driver = {
+ .probe = vfe32_probe,
+ .driver = {
+ .name = MSM_VFE_DRV_NAME,
+ .owner = THIS_MODULE,
+ },
+};
+
+static int __init msm_vfe32_init_module(void)
+{
+ return platform_driver_register(&vfe32_driver);
+}
+
+static void __exit msm_vfe32_exit_module(void)
+{
+ platform_driver_unregister(&vfe32_driver);
+}
+
+module_init(msm_vfe32_init_module);
+module_exit(msm_vfe32_exit_module);
+MODULE_DESCRIPTION("VFE 3.2 driver");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/media/video/msm/msm_vfe32.h b/drivers/media/video/msm/msm_vfe32.h
index a01d910..ecb8608 100644
--- a/drivers/media/video/msm/msm_vfe32.h
+++ b/drivers/media/video/msm/msm_vfe32.h
@@ -349,6 +349,9 @@
#define V32_MODULE_CFG_OFF 0x00000010
#define V32_MODULE_CFG_LEN 4
+#define V32_ASF_SPECIAL_EFX_CFG_OFF 0x000005FC
+#define V32_ASF_SPECIAL_EFX_CFG_LEN 4
+
#define V32_CLF_CFG_OFF 0x000006B0
#define V32_CLF_CFG_LEN 72
@@ -915,13 +918,14 @@
spinlock_t tasklet_lock;
struct list_head tasklet_q;
- int vfeirq;
void __iomem *vfebase;
void *syncdata;
uint32_t register_total;
struct resource *vfemem;
struct resource *vfeio;
+ struct resource *vfeirq;
+ struct regulator *fs_vfe;
uint32_t stats_comp;
atomic_t vstate;
@@ -945,7 +949,9 @@
struct vfe_stats_control csStatsControl;
/* v4l2 subdev */
- struct v4l2_subdev *subdev;
+ struct v4l2_subdev subdev;
+ struct platform_device *pdev;
+ struct clk *vfe_clk[3];
spinlock_t sd_notify_lock;
};
diff --git a/drivers/media/video/msm/msm_vpe.c b/drivers/media/video/msm/msm_vpe.c
index c59918d..658f911 100644
--- a/drivers/media/video/msm/msm_vpe.c
+++ b/drivers/media/video/msm/msm_vpe.c
@@ -17,6 +17,7 @@
#include <linux/io.h>
#include <linux/slab.h>
#include <linux/pm_qos_params.h>
+#include <linux/regulator/consumer.h>
#include <linux/clk.h>
#include <mach/clk.h>
#include <asm/div64.h>
@@ -32,9 +33,7 @@
static int vpe_enable(uint32_t);
static int vpe_disable(void);
static int vpe_update_scaler(struct msm_pp_crop *pcrop);
-static struct vpe_device_type *vpe_device;
struct vpe_ctrl_type *vpe_ctrl;
-static void *vpe_syncdata;
static atomic_t vpe_init_done = ATOMIC_INIT(0);
static int msm_vpe_do_pp(struct msm_mctl_pp_cmd *cmd,
@@ -49,14 +48,14 @@
static int vpe_start(void)
{
/* enable the frame irq, bit 0 = Display list 0 ROI done */
- msm_io_w_mb(1, vpe_device->vpebase + VPE_INTR_ENABLE_OFFSET);
- msm_io_dump(vpe_device->vpebase, 0x120);
- msm_io_dump(vpe_device->vpebase + 0x10000, 0x250);
- msm_io_dump(vpe_device->vpebase + 0x30000, 0x20);
- msm_io_dump(vpe_device->vpebase + 0x50000, 0x30);
- msm_io_dump(vpe_device->vpebase + 0x50400, 0x10);
+ msm_io_w_mb(1, vpe_ctrl->vpebase + VPE_INTR_ENABLE_OFFSET);
+ msm_io_dump(vpe_ctrl->vpebase, 0x120);
+ msm_io_dump(vpe_ctrl->vpebase + 0x10000, 0x250);
+ msm_io_dump(vpe_ctrl->vpebase + 0x30000, 0x20);
+ msm_io_dump(vpe_ctrl->vpebase + 0x50000, 0x30);
+ msm_io_dump(vpe_ctrl->vpebase + 0x50400, 0x10);
/* this triggers the operation. */
- msm_io_w(1, vpe_device->vpebase + VPE_DL0_START_OFFSET);
+ msm_io_w(1, vpe_ctrl->vpebase + VPE_DL0_START_OFFSET);
wmb();
return 0;
}
@@ -70,16 +69,16 @@
static void vpe_config_axi_default(void)
{
- msm_io_w(0x25, vpe_device->vpebase + VPE_AXI_ARB_2_OFFSET);
+ msm_io_w(0x25, vpe_ctrl->vpebase + VPE_AXI_ARB_2_OFFSET);
CDBG("%s: yaddr %ld cbcraddr %ld", __func__,
vpe_ctrl->out_y_addr, vpe_ctrl->out_cbcr_addr);
if (!vpe_ctrl->out_y_addr || !vpe_ctrl->out_cbcr_addr)
return;
msm_io_w(vpe_ctrl->out_y_addr,
- vpe_device->vpebase + VPE_OUTP0_ADDR_OFFSET);
+ vpe_ctrl->vpebase + VPE_OUTP0_ADDR_OFFSET);
/* for video CbCr address */
msm_io_w(vpe_ctrl->out_cbcr_addr,
- vpe_device->vpebase + VPE_OUTP1_ADDR_OFFSET);
+ vpe_ctrl->vpebase + VPE_OUTP1_ADDR_OFFSET);
}
@@ -89,33 +88,33 @@
uint32_t rc = 0;
vpe_reset_state_variables();
- vpe_version = msm_io_r(vpe_device->vpebase + VPE_HW_VERSION_OFFSET);
+ vpe_version = msm_io_r(vpe_ctrl->vpebase + VPE_HW_VERSION_OFFSET);
CDBG("vpe_version = 0x%x\n", vpe_version);
/* disable all interrupts.*/
- msm_io_w(0, vpe_device->vpebase + VPE_INTR_ENABLE_OFFSET);
+ msm_io_w(0, vpe_ctrl->vpebase + VPE_INTR_ENABLE_OFFSET);
/* clear all pending interrupts*/
- msm_io_w(0x1fffff, vpe_device->vpebase + VPE_INTR_CLEAR_OFFSET);
+ msm_io_w(0x1fffff, vpe_ctrl->vpebase + VPE_INTR_CLEAR_OFFSET);
/* write sw_reset to reset the core. */
- msm_io_w(0x10, vpe_device->vpebase + VPE_SW_RESET_OFFSET);
+ msm_io_w(0x10, vpe_ctrl->vpebase + VPE_SW_RESET_OFFSET);
/* then poll the reset bit, it should be self-cleared. */
while (1) {
rc =
- msm_io_r(vpe_device->vpebase + VPE_SW_RESET_OFFSET) & 0x10;
+ msm_io_r(vpe_ctrl->vpebase + VPE_SW_RESET_OFFSET) & 0x10;
if (rc == 0)
break;
}
/* at this point, hardware is reset. Then pogram to default
values. */
msm_io_w(VPE_AXI_RD_ARB_CONFIG_VALUE,
- vpe_device->vpebase + VPE_AXI_RD_ARB_CONFIG_OFFSET);
+ vpe_ctrl->vpebase + VPE_AXI_RD_ARB_CONFIG_OFFSET);
msm_io_w(VPE_CGC_ENABLE_VALUE,
- vpe_device->vpebase + VPE_CGC_EN_OFFSET);
- msm_io_w(1, vpe_device->vpebase + VPE_CMD_MODE_OFFSET);
+ vpe_ctrl->vpebase + VPE_CGC_EN_OFFSET);
+ msm_io_w(1, vpe_ctrl->vpebase + VPE_CMD_MODE_OFFSET);
msm_io_w(VPE_DEFAULT_OP_MODE_VALUE,
- vpe_device->vpebase + VPE_OP_MODE_OFFSET);
+ vpe_ctrl->vpebase + VPE_OP_MODE_OFFSET);
msm_io_w(VPE_DEFAULT_SCALE_CONFIG,
- vpe_device->vpebase + VPE_SCALE_CONFIG_OFFSET);
+ vpe_ctrl->vpebase + VPE_SCALE_CONFIG_OFFSET);
vpe_config_axi_default();
return rc;
}
@@ -125,7 +124,7 @@
uint32_t rot_flag, rc = 0;
struct msm_pp_crop *pcrop = (struct msm_pp_crop *)pinfo;
- rot_flag = msm_io_r(vpe_device->vpebase +
+ rot_flag = msm_io_r(vpe_ctrl->vpebase +
VPE_OP_MODE_OFFSET) & 0xE00;
if (pinfo != NULL) {
pr_err("%s: Crop info in2_w = %d, in2_h = %d "
@@ -145,39 +144,39 @@
uint32_t i, offset;
offset = *p;
for (i = offset; i < (VPE_SCALE_COEFF_NUM + offset); i++) {
- msm_io_w(*(++p), vpe_device->vpebase + VPE_SCALE_COEFF_LSBn(i));
- msm_io_w(*(++p), vpe_device->vpebase + VPE_SCALE_COEFF_MSBn(i));
+ msm_io_w(*(++p), vpe_ctrl->vpebase + VPE_SCALE_COEFF_LSBn(i));
+ msm_io_w(*(++p), vpe_ctrl->vpebase + VPE_SCALE_COEFF_MSBn(i));
}
}
void vpe_input_plane_config(uint32_t *p)
{
- msm_io_w(*p, vpe_device->vpebase + VPE_SRC_FORMAT_OFFSET);
- msm_io_w(*(++p), vpe_device->vpebase + VPE_SRC_UNPACK_PATTERN1_OFFSET);
- msm_io_w(*(++p), vpe_device->vpebase + VPE_SRC_IMAGE_SIZE_OFFSET);
- msm_io_w(*(++p), vpe_device->vpebase + VPE_SRC_YSTRIDE1_OFFSET);
- msm_io_w(*(++p), vpe_device->vpebase + VPE_SRC_SIZE_OFFSET);
+ msm_io_w(*p, vpe_ctrl->vpebase + VPE_SRC_FORMAT_OFFSET);
+ msm_io_w(*(++p), vpe_ctrl->vpebase + VPE_SRC_UNPACK_PATTERN1_OFFSET);
+ msm_io_w(*(++p), vpe_ctrl->vpebase + VPE_SRC_IMAGE_SIZE_OFFSET);
+ msm_io_w(*(++p), vpe_ctrl->vpebase + VPE_SRC_YSTRIDE1_OFFSET);
+ msm_io_w(*(++p), vpe_ctrl->vpebase + VPE_SRC_SIZE_OFFSET);
vpe_ctrl->in_h_w = *p;
- msm_io_w(*(++p), vpe_device->vpebase + VPE_SRC_XY_OFFSET);
+ msm_io_w(*(++p), vpe_ctrl->vpebase + VPE_SRC_XY_OFFSET);
CDBG("%s: in_h_w=0x%x", __func__, vpe_ctrl->in_h_w);
}
void vpe_output_plane_config(uint32_t *p)
{
- msm_io_w(*p, vpe_device->vpebase + VPE_OUT_FORMAT_OFFSET);
- msm_io_w(*(++p), vpe_device->vpebase + VPE_OUT_PACK_PATTERN1_OFFSET);
- msm_io_w(*(++p), vpe_device->vpebase + VPE_OUT_YSTRIDE1_OFFSET);
- msm_io_w(*(++p), vpe_device->vpebase + VPE_OUT_SIZE_OFFSET);
- msm_io_w(*(++p), vpe_device->vpebase + VPE_OUT_XY_OFFSET);
+ msm_io_w(*p, vpe_ctrl->vpebase + VPE_OUT_FORMAT_OFFSET);
+ msm_io_w(*(++p), vpe_ctrl->vpebase + VPE_OUT_PACK_PATTERN1_OFFSET);
+ msm_io_w(*(++p), vpe_ctrl->vpebase + VPE_OUT_YSTRIDE1_OFFSET);
+ msm_io_w(*(++p), vpe_ctrl->vpebase + VPE_OUT_SIZE_OFFSET);
+ msm_io_w(*(++p), vpe_ctrl->vpebase + VPE_OUT_XY_OFFSET);
vpe_ctrl->pcbcr_dis_offset = *(++p);
}
static int vpe_operation_config(uint32_t *p)
{
uint32_t w, h, temp;
- msm_io_w(*p, vpe_device->vpebase + VPE_OP_MODE_OFFSET);
+ msm_io_w(*p, vpe_ctrl->vpebase + VPE_OP_MODE_OFFSET);
- temp = msm_io_r(vpe_device->vpebase + VPE_OUT_SIZE_OFFSET);
+ temp = msm_io_r(vpe_ctrl->vpebase + VPE_OUT_SIZE_OFFSET);
w = temp & 0xFFF;
h = (temp & 0xFFF0000) >> 16;
if (*p++ & 0xE00) {
@@ -221,15 +220,15 @@
(pcrop->src_h >= pcrop->dst_h)) {
CDBG(" =======VPE no zoom needed.\n");
- temp = msm_io_r(vpe_device->vpebase + VPE_OP_MODE_OFFSET)
+ temp = msm_io_r(vpe_ctrl->vpebase + VPE_OP_MODE_OFFSET)
& 0xfffffffc;
- msm_io_w(temp, vpe_device->vpebase + VPE_OP_MODE_OFFSET);
+ msm_io_w(temp, vpe_ctrl->vpebase + VPE_OP_MODE_OFFSET);
- msm_io_w(0, vpe_device->vpebase + VPE_SRC_XY_OFFSET);
+ msm_io_w(0, vpe_ctrl->vpebase + VPE_SRC_XY_OFFSET);
CDBG("vpe_ctrl->in_h_w = %d\n", vpe_ctrl->in_h_w);
- msm_io_w(vpe_ctrl->in_h_w , vpe_device->vpebase +
+ msm_io_w(vpe_ctrl->in_h_w , vpe_ctrl->vpebase +
VPE_SRC_SIZE_OFFSET);
return rc;
@@ -240,8 +239,8 @@
/* assumption is both direction need zoom. this can be
improved. */
temp =
- msm_io_r(vpe_device->vpebase + VPE_OP_MODE_OFFSET) | 0x3;
- msm_io_w(temp, vpe_device->vpebase + VPE_OP_MODE_OFFSET);
+ msm_io_r(vpe_ctrl->vpebase + VPE_OP_MODE_OFFSET) | 0x3;
+ msm_io_w(temp, vpe_ctrl->vpebase + VPE_OP_MODE_OFFSET);
src_ROI_width = pcrop->src_w;
src_ROI_height = pcrop->src_h;
@@ -253,7 +252,7 @@
out_ROI_height);
src_roi = (src_ROI_height << 16) + src_ROI_width;
- msm_io_w(src_roi, vpe_device->vpebase + VPE_SRC_SIZE_OFFSET);
+ msm_io_w(src_roi, vpe_ctrl->vpebase + VPE_SRC_SIZE_OFFSET);
src_x = pcrop->src_x;
src_y = pcrop->src_y;
@@ -261,7 +260,7 @@
CDBG("src_x = %d, src_y=%d.\n", src_x, src_y);
src_xy = src_y*(1<<16) + src_x;
- msm_io_w(src_xy, vpe_device->vpebase +
+ msm_io_w(src_xy, vpe_ctrl->vpebase +
VPE_SRC_XY_OFFSET);
CDBG("src_xy = %d, src_roi=%d.\n", src_xy, src_roi);
@@ -401,15 +400,15 @@
CDBG("phase init x = %d, init y = %d.\n",
phase_init_x, phase_init_y);
- msm_io_w(phase_step_x, vpe_device->vpebase +
+ msm_io_w(phase_step_x, vpe_ctrl->vpebase +
VPE_SCALE_PHASEX_STEP_OFFSET);
- msm_io_w(phase_step_y, vpe_device->vpebase +
+ msm_io_w(phase_step_y, vpe_ctrl->vpebase +
VPE_SCALE_PHASEY_STEP_OFFSET);
- msm_io_w(phase_init_x, vpe_device->vpebase +
+ msm_io_w(phase_init_x, vpe_ctrl->vpebase +
VPE_SCALE_PHASEX_INIT_OFFSET);
- msm_io_w(phase_init_y, vpe_device->vpebase +
+ msm_io_w(phase_init_y, vpe_ctrl->vpebase +
VPE_SCALE_PHASEY_INIT_OFFSET);
return 1;
@@ -445,16 +444,16 @@
spin_lock_irqsave(&vpe_ctrl->lock, flags);
msm_io_w((vpe_ctrl->pp_frame_info->src_frame.sp.phy_addr +
vpe_ctrl->pp_frame_info->src_frame.sp.y_off),
- vpe_device->vpebase + VPE_SRCP0_ADDR_OFFSET);
+ vpe_ctrl->vpebase + VPE_SRCP0_ADDR_OFFSET);
msm_io_w((vpe_ctrl->pp_frame_info->src_frame.sp.phy_addr +
vpe_ctrl->pp_frame_info->src_frame.sp.cbcr_off),
- vpe_device->vpebase + VPE_SRCP1_ADDR_OFFSET);
+ vpe_ctrl->vpebase + VPE_SRCP1_ADDR_OFFSET);
msm_io_w((vpe_ctrl->pp_frame_info->dest_frame.sp.phy_addr +
vpe_ctrl->pp_frame_info->dest_frame.sp.y_off),
- vpe_device->vpebase + VPE_OUTP0_ADDR_OFFSET);
+ vpe_ctrl->vpebase + VPE_OUTP0_ADDR_OFFSET);
msm_io_w((vpe_ctrl->pp_frame_info->dest_frame.sp.phy_addr +
vpe_ctrl->pp_frame_info->dest_frame.sp.cbcr_off),
- vpe_device->vpebase + VPE_OUTP1_ADDR_OFFSET);
+ vpe_ctrl->vpebase + VPE_OUTP1_ADDR_OFFSET);
vpe_ctrl->state = VPE_STATE_ACTIVE;
spin_unlock_irqrestore(&vpe_ctrl->lock, flags);
vpe_start();
@@ -473,7 +472,7 @@
vpe_ctrl->state = VPE_STATE_INIT; /* put it back to idle. */
vpe_ctrl->pp_frame_info = NULL;
spin_unlock_irqrestore(&vpe_ctrl->lock, flags);
- v4l2_subdev_notify(vpe_ctrl->subdev,
+ v4l2_subdev_notify(&vpe_ctrl->subdev,
NOTIFY_VPE_MSG_EVT, (void *)&rp);
}
@@ -489,22 +488,20 @@
static irqreturn_t vpe_parse_irq(int irq_num, void *data)
{
- vpe_ctrl->irq_status = msm_io_r_mb(vpe_device->vpebase +
+ vpe_ctrl->irq_status = msm_io_r_mb(vpe_ctrl->vpebase +
VPE_INTR_STATUS_OFFSET);
- msm_io_w_mb(vpe_ctrl->irq_status, vpe_device->vpebase +
+ msm_io_w_mb(vpe_ctrl->irq_status, vpe_ctrl->vpebase +
VPE_INTR_CLEAR_OFFSET);
- msm_io_w(0, vpe_device->vpebase + VPE_INTR_ENABLE_OFFSET);
+ msm_io_w(0, vpe_ctrl->vpebase + VPE_INTR_ENABLE_OFFSET);
CDBG("%s: vpe_parse_irq =0x%x.\n", __func__, vpe_ctrl->irq_status);
tasklet_schedule(&vpe_tasklet);
return IRQ_HANDLED;
}
-static int vpe_enable_irq(void)
-{
- uint32_t rc = 0;
- enable_irq(vpe_device->vpeirq);
- return rc;
-}
+static struct msm_cam_clk_info vpe_clk_info[] = {
+ {"vpe_clk", 160000000},
+ {"vpe_pclk", -1},
+};
int vpe_enable(uint32_t clk_rate)
{
@@ -520,13 +517,32 @@
}
vpe_ctrl->state = VPE_STATE_INIT;
spin_unlock_irqrestore(&vpe_ctrl->lock, flags);
- rc = msm_camio_vpe_clk_enable(clk_rate);
- if (rc < 0) {
- pr_err("%s: msm_camio_vpe_clk_enable failed", __func__);
- vpe_ctrl->state = VPE_STATE_IDLE;
- return rc;
+ enable_irq(vpe_ctrl->vpeirq->start);
+ vpe_ctrl->fs_vpe = regulator_get(NULL, "fs_vpe");
+ if (IS_ERR(vpe_ctrl->fs_vpe)) {
+ pr_err("%s: Regulator FS_VPE get failed %ld\n", __func__,
+ PTR_ERR(vpe_ctrl->fs_vpe));
+ vpe_ctrl->fs_vpe = NULL;
+ goto vpe_fs_failed;
+ } else if (regulator_enable(vpe_ctrl->fs_vpe)) {
+ pr_err("%s: Regulator FS_VPE enable failed\n", __func__);
+ regulator_put(vpe_ctrl->fs_vpe);
+ goto vpe_fs_failed;
}
- vpe_enable_irq();
+
+ rc = msm_cam_clk_enable(&vpe_ctrl->pdev->dev, vpe_clk_info,
+ vpe_ctrl->vpe_clk, ARRAY_SIZE(vpe_clk_info), 1);
+ if (rc < 0)
+ goto vpe_clk_failed;
+
+ return rc;
+
+vpe_clk_failed:
+ regulator_disable(vpe_ctrl->fs_vpe);
+ regulator_put(vpe_ctrl->fs_vpe);
+ vpe_ctrl->fs_vpe = NULL;
+vpe_fs_failed:
+ disable_irq(vpe_ctrl->vpeirq->start);
return rc;
}
@@ -543,9 +559,15 @@
}
vpe_ctrl->state = VPE_STATE_IDLE;
spin_unlock_irqrestore(&vpe_ctrl->lock, flags);
- disable_irq(vpe_device->vpeirq);
+
+ msm_cam_clk_enable(&vpe_ctrl->pdev->dev, vpe_clk_info,
+ vpe_ctrl->vpe_clk, ARRAY_SIZE(vpe_clk_info), 0);
+
+ regulator_disable(vpe_ctrl->fs_vpe);
+ regulator_put(vpe_ctrl->fs_vpe);
+ vpe_ctrl->fs_vpe = NULL;
+ disable_irq(vpe_ctrl->vpeirq->start);
tasklet_kill(&vpe_tasklet);
- rc = msm_camio_vpe_clk_disable();
return rc;
}
@@ -628,7 +650,7 @@
.core = &msm_vpe_subdev_core_ops,
};
-static int msm_vpe_resource_init(struct platform_device *pdev, void *sdata);
+static int msm_vpe_resource_init(struct platform_device *pdev);
int msm_vpe_subdev_init(struct v4l2_subdev *sd, void *data,
struct platform_device *pdev)
@@ -640,108 +662,122 @@
return -EBUSY;
}
atomic_set(&vpe_init_done, 1);
- vpe_syncdata = data;
- rc = msm_vpe_resource_init(pdev, vpe_syncdata);
+
+ rc = msm_vpe_resource_init(pdev);
if (rc < 0) {
atomic_set(&vpe_init_done, 0);
return rc;
}
- vpe_ctrl->subdev = sd;
- v4l2_subdev_init(sd, &msm_vpe_subdev_ops);
- v4l2_set_subdev_hostdata(sd, data);
- snprintf(sd->name, sizeof(sd->name), "vpe");
spin_lock_init(&vpe_ctrl->lock);
CDBG("%s:end", __func__);
return rc;
}
EXPORT_SYMBOL(msm_vpe_subdev_init);
-static int msm_vpe_resource_init(struct platform_device *pdev,
- void *sdata)
+static int msm_vpe_resource_init(struct platform_device *pdev)
{
int rc = 0;
- struct resource *vpemem, *vpeirq, *vpeio;
- void __iomem *vpebase;
- /* first allocate */
- vpe_ctrl = kzalloc(sizeof(struct vpe_ctrl_type), GFP_KERNEL);
- if (!vpe_ctrl) {
+
+ vpe_ctrl->vpebase = ioremap(vpe_ctrl->vpemem->start,
+ resource_size(vpe_ctrl->vpemem));
+
+ if (!vpe_ctrl->vpebase) {
rc = -ENOMEM;
- goto vpe_free_device;
- }
- vpe_device = &vpe_ctrl->device_data;
- /* does the device exist? */
- vpeirq = platform_get_resource(pdev, IORESOURCE_IRQ, 1);
- if (!vpeirq) {
- pr_err("%s: no vpe irq resource.\n", __func__);
- rc = -ENODEV;
- goto vpe_free_device;
- }
- vpemem = platform_get_resource(pdev, IORESOURCE_MEM, 1);
- if (!vpemem) {
- pr_err("%s: no vpe mem resource!\n", __func__);
- rc = -ENODEV;
- goto vpe_free_device;
- }
- vpeio = request_mem_region(vpemem->start,
- resource_size(vpemem), pdev->name);
- if (!vpeio) {
- pr_err("%s: VPE region already claimed.\n", __func__);
- rc = -EBUSY;
- goto vpe_release_mem_region;
- }
- vpebase =
- ioremap(vpemem->start,
- (vpemem->end - vpemem->start) + 1);
- if (!vpebase) {
- pr_err("%s: vpe ioremap failed.\n", __func__);
- rc = -ENOMEM;
- goto vpe_release_mem_region;
+ pr_err("%s: vpe ioremap failed\n", __func__);
+ goto vpe_unmap_mem_region;
}
- /* Fall through, _probe is successful. */
- vpe_device->vpeirq = vpeirq->start;
- vpe_device->vpemem = vpemem;
- vpe_device->vpeio = vpeio;
- vpe_device->vpebase = vpebase;
- rc = request_irq(vpe_device->vpeirq,
- vpe_parse_irq,
- IRQF_TRIGGER_HIGH, "vpe", 0);
- disable_irq(vpe_device->vpeirq);
- CDBG("%s:end: vpebase=0x%p", __func__, vpebase);
- return rc; /* this rc should be zero.*/
-
- iounmap(vpe_device->vpebase); /* this path should never occur */
-
+ return rc;
/* from this part it is error handling. */
-vpe_release_mem_region:
- release_mem_region(vpemem->start, (vpemem->end - vpemem->start) + 1);
-vpe_free_device:
- kfree(vpe_ctrl);
+vpe_unmap_mem_region:
+ iounmap(vpe_ctrl->vpebase);
return rc; /* this rc should have error code. */
}
void msm_vpe_subdev_release(struct platform_device *pdev)
{
- struct resource *vpemem, *vpeio;
if (!atomic_read(&vpe_init_done)) {
/* no VPE object created */
pr_err("%s: no VPE object to release", __func__);
return;
}
- CDBG("%s, free_irq\n", __func__);
- free_irq(vpe_ctrl->device_data.vpeirq, 0);
- vpemem = vpe_ctrl->device_data.vpemem;
- vpeio = vpe_ctrl->device_data.vpeio;
-
- kfree(vpe_ctrl->extdata);
- iounmap(vpe_ctrl->device_data.vpebase);
- kfree(vpe_ctrl);
- vpe_ctrl = NULL;
- release_mem_region(vpemem->start, (vpemem->end - vpemem->start) + 1);
- CDBG("%s, end\n", __func__);
- vpe_syncdata = NULL;
+ iounmap(vpe_ctrl->vpebase);
atomic_set(&vpe_init_done, 0);
}
EXPORT_SYMBOL(msm_vpe_subdev_release);
+static int __devinit vpe_probe(struct platform_device *pdev)
+{
+ int rc = 0;
+ CDBG("%s: device id = %d\n", __func__, pdev->id);
+ vpe_ctrl = kzalloc(sizeof(struct vpe_ctrl_type), GFP_KERNEL);
+ if (!vpe_ctrl) {
+ pr_err("%s: no enough memory\n", __func__);
+ return -ENOMEM;
+ }
+
+ v4l2_subdev_init(&vpe_ctrl->subdev, &msm_vpe_subdev_ops);
+ v4l2_set_subdevdata(&vpe_ctrl->subdev, vpe_ctrl);
+ snprintf(vpe_ctrl->subdev.name, sizeof(vpe_ctrl->subdev.name), "vpe");
+ platform_set_drvdata(pdev, &vpe_ctrl->subdev);
+
+ vpe_ctrl->vpemem = platform_get_resource_byname(pdev,
+ IORESOURCE_MEM, "vpe");
+ if (!vpe_ctrl->vpemem) {
+ pr_err("%s: no mem resource?\n", __func__);
+ rc = -ENODEV;
+ goto vpe_no_resource;
+ }
+ vpe_ctrl->vpeirq = platform_get_resource_byname(pdev,
+ IORESOURCE_IRQ, "vpe");
+ if (!vpe_ctrl->vpeirq) {
+ pr_err("%s: no irq resource?\n", __func__);
+ rc = -ENODEV;
+ goto vpe_no_resource;
+ }
+
+ vpe_ctrl->vpeio = request_mem_region(vpe_ctrl->vpemem->start,
+ resource_size(vpe_ctrl->vpemem), pdev->name);
+ if (!vpe_ctrl->vpeio) {
+ pr_err("%s: no valid mem region\n", __func__);
+ rc = -EBUSY;
+ goto vpe_no_resource;
+ }
+
+ rc = request_irq(vpe_ctrl->vpeirq->start, vpe_parse_irq,
+ IRQF_TRIGGER_RISING, "vfe", 0);
+ if (rc < 0) {
+ release_mem_region(vpe_ctrl->vpemem->start,
+ resource_size(vpe_ctrl->vpemem));
+ pr_err("%s: irq request fail\n", __func__);
+ rc = -EBUSY;
+ goto vpe_no_resource;
+ }
+
+ disable_irq(vpe_ctrl->vpeirq->start);
+
+ vpe_ctrl->pdev = pdev;
+ return 0;
+
+vpe_no_resource:
+ kfree(vpe_ctrl);
+ return 0;
+}
+
+struct platform_driver vpe_driver = {
+ .probe = vpe_probe,
+ .driver = {
+ .name = MSM_VPE_DRV_NAME,
+ .owner = THIS_MODULE,
+ },
+};
+
+static int __init msm_vpe_init_module(void)
+{
+ return platform_driver_register(&vpe_driver);
+}
+
+module_init(msm_vpe_init_module);
+MODULE_DESCRIPTION("VPE driver");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/media/video/msm/msm_vpe.h b/drivers/media/video/msm/msm_vpe.h
index 40df0b0..6d84f4e 100644
--- a/drivers/media/video/msm/msm_vpe.h
+++ b/drivers/media/video/msm/msm_vpe.h
@@ -91,15 +91,6 @@
VPE_STATE_ACTIVE,
};
-struct vpe_device_type {
- /* device related. */
- int vpeirq;
- void __iomem *vpebase;
- struct resource *vpemem;
- struct resource *vpeio;
- void *device_extdata;
-};
-
struct dis_offset_type {
int32_t dis_offset_x;
int32_t dis_offset_y;
@@ -128,8 +119,15 @@
enum vpe_state state;
unsigned long out_y_addr;
unsigned long out_cbcr_addr;
- struct v4l2_subdev *subdev;
- struct vpe_device_type device_data;
+ struct v4l2_subdev subdev;
+ struct platform_device *pdev;
+ struct resource *vpeirq;
+ void __iomem *vpebase;
+ struct resource *vpemem;
+ struct resource *vpeio;
+ void *device_extdata;
+ struct regulator *fs_vpe;
+ struct clk *vpe_clk[2];
struct msm_mctl_pp_frame_info *pp_frame_info;
};
diff --git a/drivers/media/video/msm/sensors/Makefile b/drivers/media/video/msm/sensors/Makefile
index 6d697df..3e42126 100644
--- a/drivers/media/video/msm/sensors/Makefile
+++ b/drivers/media/video/msm/sensors/Makefile
@@ -1,6 +1,7 @@
GCC_VERSION := $(shell $(CONFIG_SHELL) $(PWD)/scripts/gcc-version.sh $(CROSS_COMPILE)gcc)
EXTRA_CFLAGS += -Idrivers/media/video/msm
EXTRA_CFLAGS += -Idrivers/media/video/msm/io
+EXTRA_CFLAGS += -Idrivers/media/video/msm/csi
obj-$(CONFIG_MSM_CAMERA_SENSOR) += msm_sensor.o
obj-$(CONFIG_IMX074) += imx074_v4l2.o
obj-$(CONFIG_OV2720) += ov2720.o
diff --git a/drivers/media/video/msm/sensors/msm_sensor.c b/drivers/media/video/msm/sensors/msm_sensor.c
index 19cf8c7..76ade6c 100644
--- a/drivers/media/video/msm/sensors/msm_sensor.c
+++ b/drivers/media/video/msm/sensors/msm_sensor.c
@@ -238,12 +238,14 @@
msm_sensor_write_res_settings(s_ctrl, res);
if (s_ctrl->curr_csi_params != s_ctrl->csi_params[res]) {
s_ctrl->curr_csi_params = s_ctrl->csi_params[res];
- rc = msm_camio_csid_config(
+ v4l2_subdev_notify(s_ctrl->sensor_v4l2_subdev,
+ NOTIFY_CSID_CFG,
&s_ctrl->curr_csi_params->csid_params);
v4l2_subdev_notify(s_ctrl->sensor_v4l2_subdev,
NOTIFY_CID_CHANGE, NULL);
mb();
- rc = msm_camio_csiphy_config(
+ v4l2_subdev_notify(s_ctrl->sensor_v4l2_subdev,
+ NOTIFY_CSIPHY_CFG,
&s_ctrl->curr_csi_params->csiphy_params);
mb();
msleep(20);
diff --git a/drivers/mfd/Kconfig b/drivers/mfd/Kconfig
index a4feb838..c27fea6 100644
--- a/drivers/mfd/Kconfig
+++ b/drivers/mfd/Kconfig
@@ -157,6 +157,7 @@
tristate "PMIC8058 Power Management chip"
depends on MSM_SSBI
select MFD_CORE
+ select MFD_PM8XXX
select MSM_SHOW_RESUME_IRQ
help
Say yes here for Qualcomm PM8058 chip.
diff --git a/drivers/mfd/pm8xxx-misc.c b/drivers/mfd/pm8xxx-misc.c
index 439cefe..a73a695 100644
--- a/drivers/mfd/pm8xxx-misc.c
+++ b/drivers/mfd/pm8xxx-misc.c
@@ -16,14 +16,13 @@
#include <linux/kernel.h>
#include <linux/slab.h>
#include <linux/spinlock.h>
+#include <linux/interrupt.h>
#include <linux/platform_device.h>
#include <linux/mfd/pm8xxx/core.h>
#include <linux/mfd/pm8xxx/misc.h>
/* PON CTRL 1 register */
-#define REG_PM8058_PON_CTRL_1 0x01C
-#define REG_PM8921_PON_CTRL_1 0x01C
-#define REG_PM8018_PON_CTRL_1 0x01C
+#define REG_PM8XXX_PON_CTRL_1 0x01C
#define PON_CTRL_1_PULL_UP_MASK 0xE0
#define PON_CTRL_1_USB_PWR_EN 0x10
@@ -32,6 +31,23 @@
#define PON_CTRL_1_WD_EN_RESET 0x08
#define PON_CTRL_1_WD_EN_PWR_OFF 0x00
+/* PON CNTL registers */
+#define REG_PM8058_PON_CNTL_4 0x098
+#define REG_PM8901_PON_CNTL_4 0x099
+#define REG_PM8018_PON_CNTL_4 0x01E
+#define REG_PM8921_PON_CNTL_4 0x01E
+#define REG_PM8058_PON_CNTL_5 0x07B
+#define REG_PM8901_PON_CNTL_5 0x09A
+#define REG_PM8018_PON_CNTL_5 0x01F
+#define REG_PM8921_PON_CNTL_5 0x01F
+
+#define PON_CTRL_4_RESET_EN_MASK 0x01
+#define PON_CTRL_4_SHUTDOWN_ON_RESET 0x0
+#define PON_CTRL_4_RESTART_ON_RESET 0x1
+#define PON_CTRL_5_HARD_RESET_EN_MASK 0x08
+#define PON_CTRL_5_HARD_RESET_EN 0x08
+#define PON_CTRL_5_HARD_RESET_DIS 0x00
+
/* Regulator master enable addresses */
#define REG_PM8058_VREG_EN_MSM 0x018
#define REG_PM8058_VREG_EN_GRP_5_4 0x1C8
@@ -83,6 +99,10 @@
#define SLEEP_CTRL_SMPL_EN_RESET 0x04
#define SLEEP_CTRL_SMPL_EN_PWR_OFF 0x00
+#define SLEEP_CTRL_SMPL_SEL_MASK 0x03
+#define SLEEP_CTRL_SMPL_SEL_MIN 0
+#define SLEEP_CTRL_SMPL_SEL_MAX 3
+
/* FTS regulator PMR registers */
#define REG_PM8901_REGULATOR_S1_PMR 0xA7
#define REG_PM8901_REGULATOR_S2_PMR 0xA8
@@ -92,6 +112,19 @@
#define PM8901_REGULATOR_PMR_STATE_MASK 0x60
#define PM8901_REGULATOR_PMR_STATE_OFF 0x20
+/* COINCELL CHG registers */
+#define REG_PM8058_COIN_CHG 0x02F
+#define REG_PM8921_COIN_CHG 0x09C
+#define REG_PM8018_COIN_CHG 0x09C
+
+#define COINCELL_RESISTOR_SHIFT 0x2
+
+/* GP TEST register */
+#define REG_PM8XXX_GP_TEST_1 0x07A
+
+/* Stay on configuration */
+#define PM8XXX_STAY_ON_CFG 0x92
+
/* GPIO UART MUX CTRL registers */
#define REG_PM8XXX_GPIO_MUX_CTRL 0x1CC
@@ -103,6 +136,7 @@
struct pm8xxx_misc_platform_data pdata;
struct device *dev;
enum pm8xxx_version version;
+ u64 osc_halt_count;
};
static LIST_HEAD(pm8xxx_misc_chips);
@@ -294,7 +328,7 @@
* Also ensure that KPD, CBL0, and CBL1 pull ups are enabled and that
* USB charging is enabled.
*/
- rc = pm8xxx_misc_masked_write(chip, REG_PM8018_PON_CTRL_1,
+ rc = pm8xxx_misc_masked_write(chip, REG_PM8XXX_PON_CTRL_1,
PON_CTRL_1_PULL_UP_MASK | PON_CTRL_1_USB_PWR_EN
| PON_CTRL_1_WD_EN_MASK,
PON_CTRL_1_PULL_UP_MASK | PON_CTRL_1_USB_PWR_EN
@@ -351,7 +385,7 @@
* Also ensure that KPD, CBL0, and CBL1 pull ups are enabled and that
* USB charging is enabled.
*/
- rc = pm8xxx_misc_masked_write(chip, REG_PM8058_PON_CTRL_1,
+ rc = pm8xxx_misc_masked_write(chip, REG_PM8XXX_PON_CTRL_1,
PON_CTRL_1_PULL_UP_MASK | PON_CTRL_1_USB_PWR_EN
| PON_CTRL_1_WD_EN_MASK,
PON_CTRL_1_PULL_UP_MASK | PON_CTRL_1_USB_PWR_EN
@@ -411,7 +445,7 @@
* Also ensure that KPD, CBL0, and CBL1 pull ups are enabled and that
* USB charging is enabled.
*/
- rc = pm8xxx_misc_masked_write(chip, REG_PM8921_PON_CTRL_1,
+ rc = pm8xxx_misc_masked_write(chip, REG_PM8XXX_PON_CTRL_1,
PON_CTRL_1_PULL_UP_MASK | PON_CTRL_1_USB_PWR_EN
| PON_CTRL_1_WD_EN_MASK,
PON_CTRL_1_PULL_UP_MASK | PON_CTRL_1_USB_PWR_EN
@@ -472,6 +506,397 @@
EXPORT_SYMBOL_GPL(pm8xxx_reset_pwr_off);
/**
+ * pm8xxx_smpl_control - enables/disables SMPL detection
+ * @enable: 0 = shutdown PMIC on power loss, 1 = reset PMIC on power loss
+ *
+ * This function enables or disables the Sudden Momentary Power Loss detection
+ * module. If SMPL detection is enabled, then when a sufficiently long power
+ * loss event occurs, the PMIC will automatically reset itself. If SMPL
+ * detection is disabled, then the PMIC will shutdown when power loss occurs.
+ *
+ * RETURNS: an appropriate -ERRNO error value on error, or zero for success.
+ */
+int pm8xxx_smpl_control(int enable)
+{
+ struct pm8xxx_misc_chip *chip;
+ unsigned long flags;
+ int rc = 0;
+
+ spin_lock_irqsave(&pm8xxx_misc_chips_lock, flags);
+
+ /* Loop over all attached PMICs and call specific functions for them. */
+ list_for_each_entry(chip, &pm8xxx_misc_chips, link) {
+ switch (chip->version) {
+ case PM8XXX_VERSION_8018:
+ rc = pm8xxx_misc_masked_write(chip,
+ REG_PM8018_SLEEP_CTRL, SLEEP_CTRL_SMPL_EN_MASK,
+ (enable ? SLEEP_CTRL_SMPL_EN_PWR_OFF
+ : SLEEP_CTRL_SMPL_EN_PWR_OFF));
+ break;
+ case PM8XXX_VERSION_8058:
+ rc = pm8xxx_misc_masked_write(chip,
+ REG_PM8058_SLEEP_CTRL, SLEEP_CTRL_SMPL_EN_MASK,
+ (enable ? SLEEP_CTRL_SMPL_EN_RESET
+ : SLEEP_CTRL_SMPL_EN_PWR_OFF));
+ break;
+ case PM8XXX_VERSION_8921:
+ rc = pm8xxx_misc_masked_write(chip,
+ REG_PM8921_SLEEP_CTRL, SLEEP_CTRL_SMPL_EN_MASK,
+ (enable ? SLEEP_CTRL_SMPL_EN_PWR_OFF
+ : SLEEP_CTRL_SMPL_EN_PWR_OFF));
+ break;
+ default:
+ /* PMIC doesn't have reset_pwr_off; do nothing. */
+ break;
+ }
+ if (rc) {
+ pr_err("setting smpl control failed, rc=%d\n", rc);
+ break;
+ }
+ }
+
+ spin_unlock_irqrestore(&pm8xxx_misc_chips_lock, flags);
+
+ return rc;
+}
+EXPORT_SYMBOL(pm8xxx_smpl_control);
+
+
+/**
+ * pm8xxx_smpl_set_delay - sets the SMPL detection time delay
+ * @delay: enum value corresponding to delay time
+ *
+ * This function sets the time delay of the SMPL detection module. If power
+ * is reapplied within this interval, then the PMIC reset automatically. The
+ * SMPL detection module must be enabled for this delay time to take effect.
+ *
+ * RETURNS: an appropriate -ERRNO error value on error, or zero for success.
+ */
+int pm8xxx_smpl_set_delay(enum pm8xxx_smpl_delay delay)
+{
+ struct pm8xxx_misc_chip *chip;
+ unsigned long flags;
+ int rc = 0;
+
+ if (delay < SLEEP_CTRL_SMPL_SEL_MIN
+ || delay > SLEEP_CTRL_SMPL_SEL_MAX) {
+ pr_err("%s: invalid delay specified: %d\n", __func__, delay);
+ return -EINVAL;
+ }
+
+ spin_lock_irqsave(&pm8xxx_misc_chips_lock, flags);
+
+ /* Loop over all attached PMICs and call specific functions for them. */
+ list_for_each_entry(chip, &pm8xxx_misc_chips, link) {
+ switch (chip->version) {
+ case PM8XXX_VERSION_8018:
+ rc = pm8xxx_misc_masked_write(chip,
+ REG_PM8018_SLEEP_CTRL, SLEEP_CTRL_SMPL_SEL_MASK,
+ delay);
+ break;
+ case PM8XXX_VERSION_8058:
+ rc = pm8xxx_misc_masked_write(chip,
+ REG_PM8058_SLEEP_CTRL, SLEEP_CTRL_SMPL_SEL_MASK,
+ delay);
+ break;
+ case PM8XXX_VERSION_8921:
+ rc = pm8xxx_misc_masked_write(chip,
+ REG_PM8921_SLEEP_CTRL, SLEEP_CTRL_SMPL_SEL_MASK,
+ delay);
+ break;
+ default:
+ /* PMIC doesn't have reset_pwr_off; do nothing. */
+ break;
+ }
+ if (rc) {
+ pr_err("setting smpl delay failed, rc=%d\n", rc);
+ break;
+ }
+ }
+
+ spin_unlock_irqrestore(&pm8xxx_misc_chips_lock, flags);
+
+ return rc;
+}
+EXPORT_SYMBOL(pm8xxx_smpl_set_delay);
+
+/**
+ * pm8xxx_coincell_chg_config - Disables or enables the coincell charger, and
+ * configures its voltage and resistor settings.
+ * @chg_config: Holds both voltage and resistor values, and a
+ * switch to change the state of charger.
+ * If state is to disable the charger then
+ * both voltage and resistor are disregarded.
+ *
+ * RETURNS: an appropriate -ERRNO error value on error, or zero for success.
+ */
+int pm8xxx_coincell_chg_config(struct pm8xxx_coincell_chg *chg_config)
+{
+ struct pm8xxx_misc_chip *chip;
+ unsigned long flags;
+ u8 reg = 0, voltage, resistor;
+ int rc = 0;
+
+ if (chg_config == NULL) {
+ pr_err("chg_config is NULL\n");
+ return -EINVAL;
+ }
+
+ voltage = chg_config->voltage;
+ resistor = chg_config->resistor;
+
+ if (resistor < PM8XXX_COINCELL_RESISTOR_2100_OHMS ||
+ resistor > PM8XXX_COINCELL_RESISTOR_800_OHMS) {
+ pr_err("Invalid resistor value provided\n");
+ return -EINVAL;
+ }
+
+ if (voltage < PM8XXX_COINCELL_VOLTAGE_3p2V ||
+ (voltage > PM8XXX_COINCELL_VOLTAGE_3p0V &&
+ voltage != PM8XXX_COINCELL_VOLTAGE_2p5V)) {
+ pr_err("Invalid voltage value provided\n");
+ return -EINVAL;
+ }
+
+ if (chg_config->state == PM8XXX_COINCELL_CHG_DISABLE) {
+ reg = 0;
+ } else {
+ reg |= voltage;
+ reg |= (resistor << COINCELL_RESISTOR_SHIFT);
+ }
+
+ spin_lock_irqsave(&pm8xxx_misc_chips_lock, flags);
+
+ /* Loop over all attached PMICs and call specific functions for them. */
+ list_for_each_entry(chip, &pm8xxx_misc_chips, link) {
+ switch (chip->version) {
+ case PM8XXX_VERSION_8018:
+ rc = pm8xxx_writeb(chip->dev->parent,
+ REG_PM8018_COIN_CHG, reg);
+ break;
+ case PM8XXX_VERSION_8058:
+ rc = pm8xxx_writeb(chip->dev->parent,
+ REG_PM8058_COIN_CHG, reg);
+ break;
+ case PM8XXX_VERSION_8921:
+ rc = pm8xxx_writeb(chip->dev->parent,
+ REG_PM8921_COIN_CHG, reg);
+ break;
+ default:
+ /* PMIC doesn't have reset_pwr_off; do nothing. */
+ break;
+ }
+ if (rc) {
+ pr_err("coincell chg. config failed, rc=%d\n", rc);
+ break;
+ }
+ }
+
+ spin_unlock_irqrestore(&pm8xxx_misc_chips_lock, flags);
+
+ return rc;
+}
+EXPORT_SYMBOL(pm8xxx_coincell_chg_config);
+
+/**
+ * pm8xxx_watchdog_reset_control - enables/disables watchdog reset detection
+ * @enable: 0 = shutdown when PS_HOLD goes low, 1 = reset when PS_HOLD goes low
+ *
+ * This function enables or disables the PMIC watchdog reset detection feature.
+ * If watchdog reset detection is enabled, then the PMIC will reset itself
+ * when PS_HOLD goes low. If it is not enabled, then the PMIC will shutdown
+ * when PS_HOLD goes low.
+ *
+ * RETURNS: an appropriate -ERRNO error value on error, or zero for success.
+ */
+int pm8xxx_watchdog_reset_control(int enable)
+{
+ struct pm8xxx_misc_chip *chip;
+ unsigned long flags;
+ int rc = 0;
+
+ spin_lock_irqsave(&pm8xxx_misc_chips_lock, flags);
+
+ /* Loop over all attached PMICs and call specific functions for them. */
+ list_for_each_entry(chip, &pm8xxx_misc_chips, link) {
+ switch (chip->version) {
+ case PM8XXX_VERSION_8018:
+ case PM8XXX_VERSION_8058:
+ case PM8XXX_VERSION_8921:
+ rc = pm8xxx_misc_masked_write(chip,
+ REG_PM8XXX_PON_CTRL_1, PON_CTRL_1_WD_EN_MASK,
+ (enable ? PON_CTRL_1_WD_EN_RESET
+ : PON_CTRL_1_WD_EN_PWR_OFF));
+ break;
+ default:
+ /* WD reset control not supported */
+ break;
+ }
+ if (rc) {
+ pr_err("setting WD reset control failed, rc=%d\n", rc);
+ break;
+ }
+ }
+
+ spin_unlock_irqrestore(&pm8xxx_misc_chips_lock, flags);
+
+ return rc;
+}
+EXPORT_SYMBOL(pm8xxx_watchdog_reset_control);
+
+/**
+ * pm8xxx_stay_on - enables stay_on feature
+ *
+ * PMIC stay-on feature allows PMIC to ignore MSM PS_HOLD=low
+ * signal so that some special functions like debugging could be
+ * performed.
+ *
+ * This feature should not be used in any product release.
+ *
+ * RETURNS: an appropriate -ERRNO error value on error, or zero for success.
+ */
+int pm8xxx_stay_on(void)
+{
+ struct pm8xxx_misc_chip *chip;
+ unsigned long flags;
+ int rc = 0;
+
+ spin_lock_irqsave(&pm8xxx_misc_chips_lock, flags);
+
+ /* Loop over all attached PMICs and call specific functions for them. */
+ list_for_each_entry(chip, &pm8xxx_misc_chips, link) {
+ switch (chip->version) {
+ case PM8XXX_VERSION_8018:
+ case PM8XXX_VERSION_8058:
+ case PM8XXX_VERSION_8921:
+ rc = pm8xxx_writeb(chip->dev->parent,
+ REG_PM8XXX_GP_TEST_1, PM8XXX_STAY_ON_CFG);
+ break;
+ default:
+ /* stay on not supported */
+ break;
+ }
+ if (rc) {
+ pr_err("stay_on failed failed, rc=%d\n", rc);
+ break;
+ }
+ }
+
+ spin_unlock_irqrestore(&pm8xxx_misc_chips_lock, flags);
+
+ return rc;
+}
+EXPORT_SYMBOL(pm8xxx_stay_on);
+
+static int
+__pm8xxx_hard_reset_config(struct pm8xxx_misc_chip *chip,
+ enum pm8xxx_pon_config config, u16 pon4_addr, u16 pon5_addr)
+{
+ int rc = 0;
+
+ switch (config) {
+ case PM8XXX_DISABLE_HARD_RESET:
+ rc = pm8xxx_misc_masked_write(chip, pon5_addr,
+ PON_CTRL_5_HARD_RESET_EN_MASK,
+ PON_CTRL_5_HARD_RESET_DIS);
+ break;
+ case PM8XXX_SHUTDOWN_ON_HARD_RESET:
+ rc = pm8xxx_misc_masked_write(chip, pon5_addr,
+ PON_CTRL_5_HARD_RESET_EN_MASK,
+ PON_CTRL_5_HARD_RESET_EN);
+ if (!rc) {
+ rc = pm8xxx_misc_masked_write(chip, pon4_addr,
+ PON_CTRL_4_RESET_EN_MASK,
+ PON_CTRL_4_SHUTDOWN_ON_RESET);
+ }
+ break;
+ case PM8XXX_RESTART_ON_HARD_RESET:
+ rc = pm8xxx_misc_masked_write(chip, pon5_addr,
+ PON_CTRL_5_HARD_RESET_EN_MASK,
+ PON_CTRL_5_HARD_RESET_EN);
+ if (!rc) {
+ rc = pm8xxx_misc_masked_write(chip, pon4_addr,
+ PON_CTRL_4_RESET_EN_MASK,
+ PON_CTRL_4_RESTART_ON_RESET);
+ }
+ break;
+ default:
+ rc = -EINVAL;
+ break;
+ }
+ return rc;
+}
+
+/**
+ * pm8xxx_hard_reset_config - Allows different reset configurations
+ *
+ * config = PM8XXX_DISABLE_HARD_RESET to disable hard reset
+ * = PM8XXX_SHUTDOWN_ON_HARD_RESET to turn off the system on hard reset
+ * = PM8XXX_RESTART_ON_HARD_RESET to restart the system on hard reset
+ *
+ * RETURNS: an appropriate -ERRNO error value on error, or zero for success.
+ */
+int pm8xxx_hard_reset_config(enum pm8xxx_pon_config config)
+{
+ struct pm8xxx_misc_chip *chip;
+ unsigned long flags;
+ int rc = 0;
+
+ spin_lock_irqsave(&pm8xxx_misc_chips_lock, flags);
+
+ /* Loop over all attached PMICs and call specific functions for them. */
+ list_for_each_entry(chip, &pm8xxx_misc_chips, link) {
+ switch (chip->version) {
+ case PM8XXX_VERSION_8018:
+ __pm8xxx_hard_reset_config(chip, config,
+ REG_PM8018_PON_CNTL_4, REG_PM8018_PON_CNTL_5);
+ break;
+ case PM8XXX_VERSION_8058:
+ __pm8xxx_hard_reset_config(chip, config,
+ REG_PM8058_PON_CNTL_4, REG_PM8058_PON_CNTL_5);
+ break;
+ case PM8XXX_VERSION_8901:
+ __pm8xxx_hard_reset_config(chip, config,
+ REG_PM8901_PON_CNTL_4, REG_PM8901_PON_CNTL_5);
+ break;
+ case PM8XXX_VERSION_8921:
+ __pm8xxx_hard_reset_config(chip, config,
+ REG_PM8921_PON_CNTL_4, REG_PM8921_PON_CNTL_5);
+ break;
+ default:
+ /* hard reset config. no supported */
+ break;
+ }
+ if (rc) {
+ pr_err("hard reset config. failed, rc=%d\n", rc);
+ break;
+ }
+ }
+
+ spin_unlock_irqrestore(&pm8xxx_misc_chips_lock, flags);
+
+ return rc;
+}
+EXPORT_SYMBOL(pm8xxx_hard_reset_config);
+
+/* Handle the OSC_HALT interrupt: 32 kHz XTAL oscillator has stopped. */
+static irqreturn_t pm8xxx_osc_halt_isr(int irq, void *data)
+{
+ struct pm8xxx_misc_chip *chip = data;
+ u64 count = 0;
+
+ if (chip) {
+ chip->osc_halt_count++;
+ count = chip->osc_halt_count;
+ }
+
+ pr_crit("%s: OSC_HALT interrupt has triggered, 32 kHz XTAL oscillator"
+ " has halted (%llu)!\n", __func__, count);
+
+ return IRQ_HANDLED;
+}
+
+/**
* pm8xxx_uart_gpio_mux_ctrl - Mux configuration to select the UART
*
* @uart_path_sel: Input argument to select either UART1/2/3
@@ -519,7 +944,7 @@
struct pm8xxx_misc_chip *sibling;
struct list_head *prev;
unsigned long flags;
- int rc = 0;
+ int rc = 0, irq;
if (!pdata) {
pr_err("missing platform data\n");
@@ -537,6 +962,18 @@
chip->version = pm8xxx_get_version(chip->dev->parent);
memcpy(&(chip->pdata), pdata, sizeof(struct pm8xxx_misc_platform_data));
+ irq = platform_get_irq_byname(pdev, "pm8xxx_osc_halt_irq");
+ if (irq > 0) {
+ rc = request_any_context_irq(irq, pm8xxx_osc_halt_isr,
+ IRQF_TRIGGER_RISING | IRQF_DISABLED,
+ "pm8xxx_osc_halt_irq", chip);
+ if (rc < 0) {
+ pr_err("%s: request_any_context_irq(%d) FAIL: %d\n",
+ __func__, irq, rc);
+ goto fail_irq;
+ }
+ }
+
/* Insert PMICs in priority order (lowest value first). */
spin_lock_irqsave(&pm8xxx_misc_chips_lock, flags);
prev = &pm8xxx_misc_chips;
@@ -552,12 +989,20 @@
platform_set_drvdata(pdev, chip);
return rc;
+
+fail_irq:
+ platform_set_drvdata(pdev, NULL);
+ kfree(chip);
+ return rc;
}
static int __devexit pm8xxx_misc_remove(struct platform_device *pdev)
{
struct pm8xxx_misc_chip *chip = platform_get_drvdata(pdev);
unsigned long flags;
+ int irq = platform_get_irq_byname(pdev, "pm8xxx_osc_halt_irq");
+ if (irq > 0)
+ free_irq(irq, chip);
spin_lock_irqsave(&pm8xxx_misc_chips_lock, flags);
list_del(&chip->link);
diff --git a/drivers/mfd/pmic8058.c b/drivers/mfd/pmic8058.c
index 85c8a9d..77e393e 100644
--- a/drivers/mfd/pmic8058.c
+++ b/drivers/mfd/pmic8058.c
@@ -14,55 +14,32 @@
* Qualcomm PMIC8058 driver
*
*/
-#include <linux/interrupt.h>
-#include <linux/i2c.h>
-#include <linux/bitops.h>
+#include <linux/kernel.h>
+#include <linux/platform_device.h>
#include <linux/slab.h>
-#include <linux/ratelimit.h>
-#include <linux/kthread.h>
+#include <linux/irq.h>
#include <linux/msm_ssbi.h>
#include <linux/mfd/core.h>
#include <linux/mfd/pmic8058.h>
-#include <linux/platform_device.h>
-#include <linux/ratelimit.h>
-#include <linux/slab.h>
-#include <linux/debugfs.h>
-#include <linux/irq.h>
-#include <linux/syscore_ops.h>
-#include <linux/gpio.h>
+#include <linux/mfd/pm8xxx/core.h>
+#include <linux/msm_adc.h>
+
+#define REG_MPP_BASE 0x50
/* PMIC8058 Revision */
-#define SSBI_REG_REV 0x002 /* PMIC4 revision */
+#define PM8058_REG_REV 0x002 /* PMIC4 revision */
+#define PM8058_VERSION_MASK 0xF0
+#define PM8058_REVISION_MASK 0x0F
+#define PM8058_VERSION_VALUE 0xE0
-/* PMIC8058 IRQ */
-#define SSBI_REG_ADDR_IRQ_BASE 0x1BB
+/* PMIC 8058 Battery Alarm SSBI registers */
+#define REG_BATT_ALARM_THRESH 0x023
+#define REG_BATT_ALARM_CTRL1 0x024
+#define REG_BATT_ALARM_CTRL2 0x0AA
+#define REG_BATT_ALARM_PWM_CTRL 0x0A3
-#define SSBI_REG_ADDR_IRQ_ROOT (SSBI_REG_ADDR_IRQ_BASE + 0)
-#define SSBI_REG_ADDR_IRQ_M_STATUS1 (SSBI_REG_ADDR_IRQ_BASE + 1)
-#define SSBI_REG_ADDR_IRQ_M_STATUS2 (SSBI_REG_ADDR_IRQ_BASE + 2)
-#define SSBI_REG_ADDR_IRQ_M_STATUS3 (SSBI_REG_ADDR_IRQ_BASE + 3)
-#define SSBI_REG_ADDR_IRQ_M_STATUS4 (SSBI_REG_ADDR_IRQ_BASE + 4)
-#define SSBI_REG_ADDR_IRQ_BLK_SEL (SSBI_REG_ADDR_IRQ_BASE + 5)
-#define SSBI_REG_ADDR_IRQ_IT_STATUS (SSBI_REG_ADDR_IRQ_BASE + 6)
-#define SSBI_REG_ADDR_IRQ_CONFIG (SSBI_REG_ADDR_IRQ_BASE + 7)
-#define SSBI_REG_ADDR_IRQ_RT_STATUS (SSBI_REG_ADDR_IRQ_BASE + 8)
-
-#define PM8058_IRQF_LVL_SEL 0x01 /* level select */
-#define PM8058_IRQF_MASK_FE 0x02 /* mask falling edge */
-#define PM8058_IRQF_MASK_RE 0x04 /* mask rising edge */
-#define PM8058_IRQF_CLR 0x08 /* clear interrupt */
-#define PM8058_IRQF_BITS_MASK 0x70
-#define PM8058_IRQF_BITS_SHIFT 4
-#define PM8058_IRQF_WRITE 0x80
-
-#define PM8058_IRQF_MASK_ALL (PM8058_IRQF_MASK_FE | \
- PM8058_IRQF_MASK_RE)
-#define PM8058_IRQF_W_C_M (PM8058_IRQF_WRITE | \
- PM8058_IRQF_CLR | \
- PM8058_IRQF_MASK_ALL)
-
-/* MISC register */
-#define SSBI_REG_ADDR_MISC 0x1CC
+#define REG_TEMP_ALRM_CTRL 0x1B
+#define REG_TEMP_ALRM_PWM 0x9B
/* PON CNTL 1 register */
#define SSBI_REG_ADDR_PON_CNTL_1 0x01C
@@ -138,53 +115,32 @@
/* GP_TEST1 register */
#define SSBI_REG_ADDR_GP_TEST_1 0x07A
-/* IRQ */
-#define MAX_PM_IRQ 256
-#define MAX_PM_BLOCKS (MAX_PM_IRQ / 8 + 1)
-#define MAX_PM_MASTERS (MAX_PM_BLOCKS / 8 + 1)
+#define PM8058_RTC_BASE 0x1E8
+#define PM8058_OTHC_CNTR_BASE0 0xA0
+#define PM8058_OTHC_CNTR_BASE1 0x134
+#define PM8058_OTHC_CNTR_BASE2 0x137
+
+#define SINGLE_IRQ_RESOURCE(_name, _irq) \
+{ \
+ .name = _name, \
+ .start = _irq, \
+ .end = _irq, \
+ .flags = IORESOURCE_IRQ, \
+}
struct pm8058_chip {
struct pm8058_platform_data pdata;
struct device *dev;
+ struct pm_irq_chip *irq_chip;
+ struct mfd_cell *mfd_regulators, *mfd_xo_buffers;
- u8 irqs_allowed[MAX_PM_BLOCKS];
- u8 blocks_allowed[MAX_PM_MASTERS];
- u8 masters_allowed;
- int pm_max_irq;
- int pm_max_blocks;
- int pm_max_masters;
-
- u8 config[MAX_PM_IRQ];
- u8 bus_unlock_config[MAX_PM_IRQ];
- u8 wake_enable[MAX_PM_IRQ];
- u16 count_wakeable;
-
- u8 revision;
+ u8 revision;
struct mutex pm_lock;
};
-#if defined(CONFIG_DEBUG_FS)
-struct pm8058_dbg_device {
- struct mutex dbg_mutex;
- struct pm8058_chip *pm_chip;
- struct dentry *dent;
- int addr;
-};
-
-static struct pm8058_dbg_device *pmic_dbg_device;
-#endif
-
static struct pm8058_chip *pmic_chip;
-/* Helper Functions */
-DEFINE_RATELIMIT_STATE(pm8058_msg_ratelimit, 60 * HZ, 10);
-
-static inline int pm8058_can_print(void)
-{
- return __ratelimit(&pm8058_msg_ratelimit);
-}
-
static inline int
ssbi_read(struct device *dev, u16 addr, u8 *buf, size_t len)
{
@@ -223,111 +179,6 @@
return rc;
}
-/* External APIs */
-int pm8058_rev(struct pm8058_chip *chip)
-{
- if (chip == NULL)
- return -EINVAL;
-
- return chip->revision;
-}
-EXPORT_SYMBOL(pm8058_rev);
-
-int pm8058_irq_get_rt_status(struct pm8058_chip *chip, int irq)
-{
- int rc;
- u8 block, bits, bit;
-
- if (chip == NULL || irq < chip->pdata.irq_base ||
- irq >= chip->pdata.irq_base + MAX_PM_IRQ)
- return -EINVAL;
-
- irq -= chip->pdata.irq_base;
-
- block = irq / 8;
- bit = irq % 8;
-
- mutex_lock(&chip->pm_lock);
-
- rc = ssbi_write(chip->dev, SSBI_REG_ADDR_IRQ_BLK_SEL, &block, 1);
- if (rc) {
- pr_err("%s: FAIL ssbi_write(): rc=%d (Select Block)\n",
- __func__, rc);
- goto bail_out;
- }
-
- rc = ssbi_read(chip->dev, SSBI_REG_ADDR_IRQ_RT_STATUS, &bits, 1);
- if (rc) {
- pr_err("%s: FAIL ssbi_read(): rc=%d (Read RT Status)\n",
- __func__, rc);
- goto bail_out;
- }
-
- rc = (bits & (1 << bit)) ? 1 : 0;
-
-bail_out:
- mutex_unlock(&chip->pm_lock);
-
- return rc;
-}
-EXPORT_SYMBOL(pm8058_irq_get_rt_status);
-
-int pm8058_read(struct pm8058_chip *chip, u16 addr, u8 *values,
- unsigned int len)
-{
- if (chip == NULL)
- return -EINVAL;
-
- return ssbi_read(chip->dev, addr, values, len);
-}
-EXPORT_SYMBOL(pm8058_read);
-
-int pm8058_write(struct pm8058_chip *chip, u16 addr, u8 *values,
- unsigned int len)
-{
- if (chip == NULL)
- return -EINVAL;
-
- return ssbi_write(chip->dev, addr, values, len);
-}
-EXPORT_SYMBOL(pm8058_write);
-
-int pm8058_misc_control(struct pm8058_chip *chip, int mask, int flag)
-{
- int rc;
- u8 misc;
-
- if (chip == NULL)
- chip = pmic_chip; /* for calls from non child */
- if (chip == NULL)
- return -ENODEV;
-
- mutex_lock(&chip->pm_lock);
-
- rc = ssbi_read(chip->dev, SSBI_REG_ADDR_MISC, &misc, 1);
- if (rc) {
- pr_err("%s: FAIL ssbi_read(0x%x): rc=%d\n",
- __func__, SSBI_REG_ADDR_MISC, rc);
- goto get_out;
- }
-
- misc &= ~mask;
- misc |= flag;
-
- rc = ssbi_write(chip->dev, SSBI_REG_ADDR_MISC, &misc, 1);
- if (rc) {
- pr_err("%s: FAIL ssbi_write(0x%x)=0x%x: rc=%d\n",
- __func__, SSBI_REG_ADDR_MISC, misc, rc);
- goto get_out;
- }
-
-get_out:
- mutex_unlock(&chip->pm_lock);
-
- return rc;
-}
-EXPORT_SYMBOL(pm8058_misc_control);
-
/**
* pm8058_smpl_control - enables/disables SMPL detection
* @enable: 0 = shutdown PMIC on power loss, 1 = reset PMIC on power loss
@@ -713,765 +564,694 @@
}
EXPORT_SYMBOL(pm8058_hard_reset_config);
-/* Internal functions */
-static inline int
-pm8058_config_irq(struct pm8058_chip *chip, u8 *bp, u8 *cp)
+static int pm8058_readb(const struct device *dev, u16 addr, u8 *val)
{
- int rc;
+ const struct pm8xxx_drvdata *pm8058_drvdata = dev_get_drvdata(dev);
+ const struct pm8058_chip *pmic = pm8058_drvdata->pm_chip_data;
- rc = ssbi_write(chip->dev, SSBI_REG_ADDR_IRQ_BLK_SEL, bp, 1);
- if (rc) {
- pr_err("%s: ssbi_write: rc=%d (Select block)\n",
- __func__, rc);
- goto bail_out;
- }
-
- rc = ssbi_write(chip->dev, SSBI_REG_ADDR_IRQ_CONFIG, cp, 1);
- if (rc)
- pr_err("%s: ssbi_write: rc=%d (Configure IRQ)\n",
- __func__, rc);
-
-bail_out:
- return rc;
+ return msm_ssbi_read(pmic->dev->parent, addr, val, 1);
}
-static void pm8058_irq_mask(struct irq_data *data)
+static int pm8058_writeb(const struct device *dev, u16 addr, u8 val)
{
- int master, irq_bit;
- struct pm8058_chip *chip = irq_data_get_irq_chip_data(data);
- u8 block, config;
- unsigned int irq = data->irq;
+ const struct pm8xxx_drvdata *pm8058_drvdata = dev_get_drvdata(dev);
+ const struct pm8058_chip *pmic = pm8058_drvdata->pm_chip_data;
- irq -= chip->pdata.irq_base;
- block = irq / 8;
- master = block / 8;
- irq_bit = irq % 8;
-
- chip->irqs_allowed[block] &= ~(1 << irq_bit);
- if (!chip->irqs_allowed[block]) {
- chip->blocks_allowed[master] &= ~(1 << (block % 8));
-
- if (!chip->blocks_allowed[master])
- chip->masters_allowed &= ~(1 << master);
- }
-
- config = PM8058_IRQF_WRITE | chip->config[irq] |
- PM8058_IRQF_MASK_FE | PM8058_IRQF_MASK_RE;
- chip->bus_unlock_config[irq] = config;
+ return msm_ssbi_write(pmic->dev->parent, addr, &val, 1);
}
-static void pm8058_irq_unmask(struct irq_data *data)
+static int pm8058_read_buf(const struct device *dev, u16 addr, u8 *buf,
+ int cnt)
{
- int master, irq_bit;
- struct pm8058_chip *chip = irq_data_get_irq_chip_data(data);
- u8 block, config, old_irqs_allowed, old_blocks_allowed;
- unsigned int irq = data->irq;
+ const struct pm8xxx_drvdata *pm8058_drvdata = dev_get_drvdata(dev);
+ const struct pm8058_chip *pmic = pm8058_drvdata->pm_chip_data;
- irq -= chip->pdata.irq_base;
- block = irq / 8;
- master = block / 8;
- irq_bit = irq % 8;
-
- old_irqs_allowed = chip->irqs_allowed[block];
- if (old_irqs_allowed & (1 << irq_bit)) {
- pr_debug("%s: no need to enable an already enabled irq=%d\n",
- __func__, irq + chip->pdata.irq_base);
- return;
- }
-
- chip->irqs_allowed[block] |= 1 << irq_bit;
- if (!old_irqs_allowed) {
- master = block / 8;
-
- old_blocks_allowed = chip->blocks_allowed[master];
- chip->blocks_allowed[master] |= 1 << (block % 8);
-
- if (!old_blocks_allowed)
- chip->masters_allowed |= 1 << master;
- }
-
- config = PM8058_IRQF_WRITE | chip->config[irq];
- chip->bus_unlock_config[irq] = config;
+ return msm_ssbi_read(pmic->dev->parent, addr, buf, cnt);
}
-static void pm8058_irq_ack(struct irq_data *data)
+static int pm8058_write_buf(const struct device *dev, u16 addr, u8 *buf,
+ int cnt)
{
- struct pm8058_chip *chip = irq_data_get_irq_chip_data(data);
- u8 block, config;
- unsigned int irq = data->irq;
+ const struct pm8xxx_drvdata *pm8058_drvdata = dev_get_drvdata(dev);
+ const struct pm8058_chip *pmic = pm8058_drvdata->pm_chip_data;
- irq -= chip->pdata.irq_base;
- block = irq / 8;
-
- config = PM8058_IRQF_WRITE | chip->config[irq] | PM8058_IRQF_CLR;
- /* Keep the mask */
- if (!(chip->irqs_allowed[block] & (1 << (irq % 8))))
- config |= PM8058_IRQF_MASK_FE | PM8058_IRQF_MASK_RE;
- chip->bus_unlock_config[irq] = config;
+ return msm_ssbi_write(pmic->dev->parent, addr, buf, cnt);
}
-static int pm8058_irq_set_type(struct irq_data *data, unsigned int flow_type)
+static int pm8058_read_irq_stat(const struct device *dev, int irq)
{
- int master, irq_bit;
- struct pm8058_chip *chip = irq_data_get_irq_chip_data(data);
- u8 block, config;
- unsigned int irq = data->irq;
+ const struct pm8xxx_drvdata *pm8058_drvdata = dev_get_drvdata(dev);
+ const struct pm8058_chip *pmic = pm8058_drvdata->pm_chip_data;
- irq -= chip->pdata.irq_base;
- if (irq > chip->pm_max_irq) {
- chip->pm_max_irq = irq;
- chip->pm_max_blocks =
- chip->pm_max_irq / 8 + 1;
- chip->pm_max_masters =
- chip->pm_max_blocks / 8 + 1;
- }
- block = irq / 8;
- master = block / 8;
- irq_bit = irq % 8;
-
- chip->config[irq] = (irq_bit << PM8058_IRQF_BITS_SHIFT) |
- PM8058_IRQF_MASK_RE | PM8058_IRQF_MASK_FE;
- if (flow_type & (IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING)) {
- if (flow_type & IRQF_TRIGGER_RISING)
- chip->config[irq] &= ~PM8058_IRQF_MASK_RE;
- if (flow_type & IRQF_TRIGGER_FALLING)
- chip->config[irq] &= ~PM8058_IRQF_MASK_FE;
- } else {
- chip->config[irq] |= PM8058_IRQF_LVL_SEL;
-
- if (flow_type & IRQF_TRIGGER_HIGH)
- chip->config[irq] &= ~PM8058_IRQF_MASK_RE;
- else
- chip->config[irq] &= ~PM8058_IRQF_MASK_FE;
- }
-
- config = PM8058_IRQF_WRITE | chip->config[irq] | PM8058_IRQF_CLR;
- chip->bus_unlock_config[irq] = config;
- return 0;
-}
-
-static int pm8058_irq_set_wake(struct irq_data *data, unsigned int on)
-{
- struct pm8058_chip *chip = irq_data_get_irq_chip_data(data);
- unsigned int irq = data->irq;
-
- irq -= chip->pdata.irq_base;
- if (on) {
- if (!chip->wake_enable[irq]) {
- chip->wake_enable[irq] = 1;
- chip->count_wakeable++;
- }
- } else {
- if (chip->wake_enable[irq]) {
- chip->wake_enable[irq] = 0;
- chip->count_wakeable--;
- }
- }
+ return pm8xxx_get_irq_stat(pmic->irq_chip, irq);
return 0;
}
-static void pm8058_irq_bus_lock(struct irq_data *data)
+static enum pm8xxx_version pm8058_get_version(const struct device *dev)
{
- u8 block;
- struct pm8058_chip *chip = irq_data_get_irq_chip_data(data);
- unsigned int irq = data->irq;
+ const struct pm8xxx_drvdata *pm8058_drvdata = dev_get_drvdata(dev);
+ const struct pm8058_chip *pmic = pm8058_drvdata->pm_chip_data;
+ enum pm8xxx_version version = -ENODEV;
- irq -= chip->pdata.irq_base;
- block = irq / 8;
- chip->bus_unlock_config[irq] = 0;
+ if ((pmic->revision & PM8058_VERSION_MASK) == PM8058_VERSION_VALUE)
+ version = PM8XXX_VERSION_8058;
- mutex_lock(&chip->pm_lock);
+ return version;
}
-static void pm8058_irq_bus_sync_unlock(struct irq_data *data)
+static int pm8058_get_revision(const struct device *dev)
{
- u8 block, config;
- struct pm8058_chip *chip = irq_data_get_irq_chip_data(data);
- unsigned int irq = data->irq;
+ const struct pm8xxx_drvdata *pm8058_drvdata = dev_get_drvdata(dev);
+ const struct pm8058_chip *pmic = pm8058_drvdata->pm_chip_data;
- irq -= chip->pdata.irq_base;
- block = irq / 8;
- config = chip->bus_unlock_config[irq];
- /* dont waste cpu cycles if we dont have data to write */
- if (config)
- pm8058_config_irq(chip, &block, &config);
- mutex_unlock(&chip->pm_lock);
+ return pmic->revision & PM8058_REVISION_MASK;
}
-static inline int
-pm8058_read_root(struct pm8058_chip *chip, u8 *rp)
-{
- int rc;
-
- rc = ssbi_read(chip->dev, SSBI_REG_ADDR_IRQ_ROOT, rp, 1);
- if (rc) {
- pr_err("%s: FAIL ssbi_read(): rc=%d (Read Root)\n",
- __func__, rc);
- *rp = 0;
- }
-
- return rc;
-}
-
-static inline int
-pm8058_read_master(struct pm8058_chip *chip, u8 m, u8 *bp)
-{
- int rc;
-
- rc = ssbi_read(chip->dev, SSBI_REG_ADDR_IRQ_M_STATUS1 + m, bp, 1);
- if (rc) {
- pr_err("%s: FAIL ssbi_read(): rc=%d (Read Master)\n",
- __func__, rc);
- *bp = 0;
- }
-
- return rc;
-}
-
-static inline int
-pm8058_read_block(struct pm8058_chip *chip, u8 *bp, u8 *ip)
-{
- int rc;
-
- rc = ssbi_write(chip->dev, SSBI_REG_ADDR_IRQ_BLK_SEL, bp, 1);
- if (rc) {
- pr_err("%s: FAIL ssbi_write(): rc=%d (Select Block)\n",
- __func__, rc);
- *bp = 0;
- goto bail_out;
- }
-
- rc = ssbi_read(chip->dev, SSBI_REG_ADDR_IRQ_IT_STATUS, ip, 1);
- if (rc)
- pr_err("%s: FAIL ssbi_read(): rc=%d (Read Status)\n",
- __func__, rc);
-
-bail_out:
- return rc;
-}
-
-static irqreturn_t pm8058_isr_thread(int irq_requested, void *data)
-{
- struct pm8058_chip *chip = data;
- int i, j, k;
- u8 root, block, config, bits;
- u8 blocks[MAX_PM_MASTERS];
- int masters = 0, irq, handled = 0, spurious = 0;
- u16 irqs_to_handle[MAX_PM_IRQ];
-
- mutex_lock(&chip->pm_lock);
-
- /* Read root for masters */
- if (pm8058_read_root(chip, &root))
- goto bail_out;
-
- masters = root >> 1;
-
- if (!(masters & chip->masters_allowed) ||
- (masters & ~chip->masters_allowed)) {
- spurious = 1000000;
- }
-
- /* Read allowed masters for blocks. */
- for (i = 0; i < chip->pm_max_masters; i++) {
- if (masters & (1 << i)) {
- if (pm8058_read_master(chip, i, &blocks[i]))
- goto bail_out;
-
- if (!blocks[i]) {
- if (pm8058_can_print())
- pr_err("%s: Spurious master: %d "
- "(blocks=0)", __func__, i);
- spurious += 10000;
- }
- } else
- blocks[i] = 0;
- }
-
- /* Select block, read status and call isr */
- for (i = 0; i < chip->pm_max_masters; i++) {
- if (!blocks[i])
- continue;
-
- for (j = 0; j < 8; j++) {
- if (!(blocks[i] & (1 << j)))
- continue;
-
- block = i * 8 + j; /* block # */
- if (pm8058_read_block(chip, &block, &bits))
- goto bail_out;
-
- if (!bits) {
- if (pm8058_can_print())
- pr_err("%s: Spurious block: "
- "[master, block]=[%d, %d] "
- "(bits=0)\n", __func__, i, j);
- spurious += 100;
- continue;
- }
-
- /* Check IRQ bits */
- for (k = 0; k < 8; k++) {
- if (!(bits & (1 << k)))
- continue;
-
- /* Check spurious interrupts */
- if (((1 << i) & chip->masters_allowed) &&
- (blocks[i] & chip->blocks_allowed[i]) &&
- (bits & chip->irqs_allowed[block])) {
-
- /* Found one */
- irq = block * 8 + k;
- irqs_to_handle[handled] = irq +
- chip->pdata.irq_base;
- handled++;
- } else {
- /* Clear and mask wrong one */
- config = PM8058_IRQF_W_C_M |
- (k << PM8058_IRQF_BITS_SHIFT);
-
- pm8058_config_irq(chip,
- &block, &config);
-
- if (pm8058_can_print())
- pr_err("%s: Spurious IRQ: "
- "[master, block, bit]="
- "[%d, %d (%d), %d]\n",
- __func__,
- i, j, block, k);
- spurious++;
- }
- }
- }
-
- }
-
-bail_out:
-
- mutex_unlock(&chip->pm_lock);
-
- for (i = 0; i < handled; i++) {
- int pmic_irq = irqs_to_handle[i] - chip->pdata.irq_base;
-
- /* ack the interrupt first */
- block = pmic_irq / 8 ;
- config = PM8058_IRQF_WRITE | chip->config[pmic_irq]
- | PM8058_IRQF_CLR;
- pm8058_config_irq(chip, &block, &config);
-
- /* calle the action handler */
- handle_nested_irq(irqs_to_handle[i]);
- }
-
- if (spurious) {
- if (!pm8058_can_print())
- return IRQ_HANDLED;
-
- pr_err("%s: spurious = %d (handled = %d)\n",
- __func__, spurious, handled);
- pr_err(" root = 0x%x (masters_allowed<<1 = 0x%x)\n",
- root, chip->masters_allowed << 1);
- for (i = 0; i < chip->pm_max_masters; i++) {
- if (masters & (1 << i))
- pr_err(" blocks[%d]=0x%x, "
- "allowed[%d]=0x%x\n",
- i, blocks[i],
- i, chip->blocks_allowed[i]);
- }
- }
-
- return IRQ_HANDLED;
-}
-
-#if defined(CONFIG_DEBUG_FS)
-
-static int check_addr(int addr, const char *func_name)
-{
- if (addr < 0 || addr > 0x3FF) {
- pr_err("%s: PMIC 8058 register address is invalid: %d\n",
- func_name, addr);
- return -EINVAL;
- }
- return 0;
-}
-
-static int data_set(void *data, u64 val)
-{
- struct pm8058_dbg_device *dbgdev = data;
- u8 reg = val;
- int rc;
-
- mutex_lock(&dbgdev->dbg_mutex);
-
- rc = check_addr(dbgdev->addr, __func__);
- if (rc)
- goto done;
-
- rc = pm8058_write(dbgdev->pm_chip, dbgdev->addr, ®, 1);
-
- if (rc)
- pr_err("%s: FAIL pm8058_write(0x%03X)=0x%02X: rc=%d\n",
- __func__, dbgdev->addr, reg, rc);
-done:
- mutex_unlock(&dbgdev->dbg_mutex);
- return rc;
-}
-
-static int data_get(void *data, u64 *val)
-{
- struct pm8058_dbg_device *dbgdev = data;
- int rc;
- u8 reg;
-
- mutex_lock(&dbgdev->dbg_mutex);
-
- rc = check_addr(dbgdev->addr, __func__);
- if (rc)
- goto done;
-
- rc = pm8058_read(dbgdev->pm_chip, dbgdev->addr, ®, 1);
-
- if (rc) {
- pr_err("%s: FAIL pm8058_read(0x%03X)=0x%02X: rc=%d\n",
- __func__, dbgdev->addr, reg, rc);
- goto done;
- }
-
- *val = reg;
-done:
- mutex_unlock(&dbgdev->dbg_mutex);
- return rc;
-}
-
-DEFINE_SIMPLE_ATTRIBUTE(dbg_data_fops, data_get, data_set, "0x%02llX\n");
-
-static int addr_set(void *data, u64 val)
-{
- struct pm8058_dbg_device *dbgdev = data;
- int rc;
-
- rc = check_addr(val, __func__);
- if (rc)
- return rc;
-
- mutex_lock(&dbgdev->dbg_mutex);
- dbgdev->addr = val;
- mutex_unlock(&dbgdev->dbg_mutex);
-
- return 0;
-}
-
-static int addr_get(void *data, u64 *val)
-{
- struct pm8058_dbg_device *dbgdev = data;
- int rc;
-
- mutex_lock(&dbgdev->dbg_mutex);
-
- rc = check_addr(dbgdev->addr, __func__);
- if (rc) {
- mutex_unlock(&dbgdev->dbg_mutex);
- return rc;
- }
- *val = dbgdev->addr;
-
- mutex_unlock(&dbgdev->dbg_mutex);
-
- return 0;
-}
-
-DEFINE_SIMPLE_ATTRIBUTE(dbg_addr_fops, addr_get, addr_set, "0x%03llX\n");
-
-static int __devinit pmic8058_dbg_probe(struct pm8058_chip *chip)
-{
- struct pm8058_dbg_device *dbgdev;
- struct dentry *dent;
- struct dentry *temp;
- int rc;
-
- if (chip == NULL) {
- pr_err("%s: no parent data passed in.\n", __func__);
- return -EINVAL;
- }
-
- dbgdev = kzalloc(sizeof *dbgdev, GFP_KERNEL);
- if (dbgdev == NULL) {
- pr_err("%s: kzalloc() failed.\n", __func__);
- return -ENOMEM;
- }
-
- dbgdev->pm_chip = chip;
- dbgdev->addr = -1;
-
- dent = debugfs_create_dir("pm8058-dbg", NULL);
- if (dent == NULL || IS_ERR(dent)) {
- pr_err("%s: ERR debugfs_create_dir: dent=0x%X\n",
- __func__, (unsigned)dent);
- rc = PTR_ERR(dent);
- goto dir_error;
- }
-
- temp = debugfs_create_file("addr", S_IRUSR | S_IWUSR, dent,
- dbgdev, &dbg_addr_fops);
- if (temp == NULL || IS_ERR(temp)) {
- pr_err("%s: ERR debugfs_create_file: dent=0x%X\n",
- __func__, (unsigned)temp);
- rc = PTR_ERR(temp);
- goto debug_error;
- }
-
- temp = debugfs_create_file("data", S_IRUSR | S_IWUSR, dent,
- dbgdev, &dbg_data_fops);
- if (temp == NULL || IS_ERR(temp)) {
- pr_err("%s: ERR debugfs_create_file: dent=0x%X\n",
- __func__, (unsigned)temp);
- rc = PTR_ERR(temp);
- goto debug_error;
- }
-
- mutex_init(&dbgdev->dbg_mutex);
-
- dbgdev->dent = dent;
-
- pmic_dbg_device = dbgdev;
-
- return 0;
-
-debug_error:
- debugfs_remove_recursive(dent);
-dir_error:
- kfree(dbgdev);
-
- return rc;
-}
-
-static int __devexit pmic8058_dbg_remove(void)
-{
- if (pmic_dbg_device) {
- debugfs_remove_recursive(pmic_dbg_device->dent);
- mutex_destroy(&pmic_dbg_device->dbg_mutex);
- kfree(pmic_dbg_device);
- }
- return 0;
-}
-
-#else
-
-static int __devinit pmic8058_dbg_probe(struct pm8058_chip *chip)
-{
- return 0;
-}
-
-static int __devexit pmic8058_dbg_remove(void)
-{
- return 0;
-}
-
-#endif
-
-static struct irq_chip pm8058_irq_chip = {
- .name = "pm8058",
- .irq_ack = pm8058_irq_ack,
- .irq_mask = pm8058_irq_mask,
- .irq_unmask = pm8058_irq_unmask,
- .irq_set_type = pm8058_irq_set_type,
- .irq_set_wake = pm8058_irq_set_wake,
- .irq_bus_lock = pm8058_irq_bus_lock,
- .irq_bus_sync_unlock = pm8058_irq_bus_sync_unlock,
+static struct pm8xxx_drvdata pm8058_drvdata = {
+ .pmic_readb = pm8058_readb,
+ .pmic_writeb = pm8058_writeb,
+ .pmic_read_buf = pm8058_read_buf,
+ .pmic_write_buf = pm8058_write_buf,
+ .pmic_read_irq_stat = pm8058_read_irq_stat,
+ .pmic_get_version = pm8058_get_version,
+ .pmic_get_revision = pm8058_get_revision,
};
-static int pm8058_suspend(void)
-{
- struct pm8058_chip *chip = pmic_chip;
- struct irq_data *data;
- int i;
-
- for (i = 0; i < MAX_PM_IRQ; i++) {
- if (chip->config[i] && !chip->wake_enable[i]) {
- if (!((chip->config[i] & PM8058_IRQF_MASK_ALL)
- == PM8058_IRQF_MASK_ALL)) {
- data = irq_get_irq_data(i +
- chip->pdata.irq_base);
- pm8058_irq_bus_lock(data);
- pm8058_irq_mask(data);
- pm8058_irq_bus_sync_unlock(data);
- }
- }
- }
-
- if (!chip->count_wakeable)
- disable_irq(chip->pdata.irq);
-
- return 0;
-}
-
-extern int msm_show_resume_irq_mask;
-
-static void pm8058_show_resume_irq(void)
-{
- u8 block, bits;
- int i;
- struct pm8058_chip *chip = pmic_chip;
-
- if (!msm_show_resume_irq_mask)
- return;
-
- for (i = 0; i < MAX_PM_IRQ; i++) {
- if (chip->wake_enable[i]) {
- block = i / 8;
- if (!pm8058_read_block(chip, &block, &bits)) {
- if (bits & (1 << (i & 0x7)))
- pr_warning("%s:%d triggered\n",
- __func__, i + chip->pdata.irq_base);
- }
- }
- }
-}
-
-static void pm8058_resume(void)
-{
- struct pm8058_chip *chip = pmic_chip;
- struct irq_data *data;
- int i;
-
- pm8058_show_resume_irq();
-
- for (i = 0; i < MAX_PM_IRQ; i++) {
- if (chip->config[i] && !chip->wake_enable[i]) {
- if (!((chip->config[i] & PM8058_IRQF_MASK_ALL)
- == PM8058_IRQF_MASK_ALL)) {
- data = irq_get_irq_data(i +
- chip->pdata.irq_base);
- pm8058_irq_bus_lock(data);
- pm8058_irq_unmask(data);
- pm8058_irq_bus_sync_unlock(data);
- }
- }
- }
-
- if (!chip->count_wakeable)
- enable_irq(chip->pdata.irq);
-}
-
-static struct syscore_ops pm8058_pm = {
- .suspend = pm8058_suspend,
- .resume = pm8058_resume,
+static const struct resource pm8058_charger_resources[] __devinitconst = {
+ SINGLE_IRQ_RESOURCE("CHGVAL", PM8058_CHGVAL_IRQ),
+ SINGLE_IRQ_RESOURCE("CHGINVAL", PM8058_CHGINVAL_IRQ),
+ SINGLE_IRQ_RESOURCE("CHGILIM", PM8058_CHGILIM_IRQ),
+ SINGLE_IRQ_RESOURCE("VCP", PM8058_VCP_IRQ),
+ SINGLE_IRQ_RESOURCE("ATC_DONE", PM8058_ATC_DONE_IRQ),
+ SINGLE_IRQ_RESOURCE("ATCFAIL", PM8058_ATCFAIL_IRQ),
+ SINGLE_IRQ_RESOURCE("AUTO_CHGDONE", PM8058_AUTO_CHGDONE_IRQ),
+ SINGLE_IRQ_RESOURCE("AUTO_CHGFAIL", PM8058_AUTO_CHGFAIL_IRQ),
+ SINGLE_IRQ_RESOURCE("CHGSTATE", PM8058_CHGSTATE_IRQ),
+ SINGLE_IRQ_RESOURCE("FASTCHG", PM8058_FASTCHG_IRQ),
+ SINGLE_IRQ_RESOURCE("CHG_END", PM8058_CHG_END_IRQ),
+ SINGLE_IRQ_RESOURCE("BATTTEMP", PM8058_BATTTEMP_IRQ),
+ SINGLE_IRQ_RESOURCE("CHGHOT", PM8058_CHGHOT_IRQ),
+ SINGLE_IRQ_RESOURCE("CHGTLIMIT", PM8058_CHGTLIMIT_IRQ),
+ SINGLE_IRQ_RESOURCE("CHG_GONE", PM8058_CHG_GONE_IRQ),
+ SINGLE_IRQ_RESOURCE("VCPMAJOR", PM8058_VCPMAJOR_IRQ),
+ SINGLE_IRQ_RESOURCE("VBATDET", PM8058_VBATDET_IRQ),
+ SINGLE_IRQ_RESOURCE("BATFET", PM8058_BATFET_IRQ),
+ SINGLE_IRQ_RESOURCE("BATT_REPLACE", PM8058_BATT_REPLACE_IRQ),
+ SINGLE_IRQ_RESOURCE("BATTCONNECT", PM8058_BATTCONNECT_IRQ),
+ SINGLE_IRQ_RESOURCE("VBATDET_LOW", PM8058_VBATDET_LOW_IRQ),
};
+static struct mfd_cell pm8058_charger_cell __devinitdata = {
+ .name = "pm8058-charger",
+ .id = -1,
+ .resources = pm8058_charger_resources,
+ .num_resources = ARRAY_SIZE(pm8058_charger_resources),
+};
+
+static const struct resource misc_cell_resources[] __devinitconst = {
+ SINGLE_IRQ_RESOURCE("pm8xxx_osc_halt_irq", PM8058_OSCHALT_IRQ),
+};
+
+static struct mfd_cell misc_cell __devinitdata = {
+ .name = PM8XXX_MISC_DEV_NAME,
+ .id = -1,
+ .resources = misc_cell_resources,
+ .num_resources = ARRAY_SIZE(misc_cell_resources),
+};
+
+static struct mfd_cell pm8058_pwm_cell __devinitdata = {
+ .name = "pm8058-pwm",
+ .id = -1,
+};
+
+static struct resource xoadc_resources[] = {
+ SINGLE_IRQ_RESOURCE(NULL, PM8058_ADC_IRQ),
+};
+
+static struct mfd_cell xoadc_cell __devinitdata = {
+ .name = "pm8058-xoadc",
+ .id = -1,
+ .resources = xoadc_resources,
+ .num_resources = ARRAY_SIZE(xoadc_resources),
+};
+
+static const struct resource thermal_alarm_cell_resources[] __devinitconst = {
+ SINGLE_IRQ_RESOURCE("pm8058_tempstat_irq", PM8058_TEMPSTAT_IRQ),
+ SINGLE_IRQ_RESOURCE("pm8058_overtemp_irq", PM8058_OVERTEMP_IRQ),
+};
+
+static struct pm8xxx_tm_core_data thermal_alarm_cdata = {
+ .adc_channel = CHANNEL_ADC_DIE_TEMP,
+ .adc_type = PM8XXX_TM_ADC_PM8058_ADC,
+ .reg_addr_temp_alarm_ctrl = REG_TEMP_ALRM_CTRL,
+ .reg_addr_temp_alarm_pwm = REG_TEMP_ALRM_PWM,
+ .tm_name = "pm8058_tz",
+ .irq_name_temp_stat = "pm8058_tempstat_irq",
+ .irq_name_over_temp = "pm8058_overtemp_irq",
+};
+
+static struct mfd_cell thermal_alarm_cell __devinitdata = {
+ .name = PM8XXX_TM_DEV_NAME,
+ .id = -1,
+ .resources = thermal_alarm_cell_resources,
+ .num_resources = ARRAY_SIZE(thermal_alarm_cell_resources),
+ .platform_data = &thermal_alarm_cdata,
+ .pdata_size = sizeof(struct pm8xxx_tm_core_data),
+};
+
+static struct mfd_cell debugfs_cell __devinitdata = {
+ .name = "pm8xxx-debug",
+ .id = -1,
+ .platform_data = "pm8058-dbg",
+ .pdata_size = sizeof("pm8058-dbg"),
+};
+
+static const struct resource othc0_cell_resources[] __devinitconst = {
+ {
+ .name = "othc_base",
+ .start = PM8058_OTHC_CNTR_BASE0,
+ .end = PM8058_OTHC_CNTR_BASE0,
+ .flags = IORESOURCE_IO,
+ },
+};
+
+static const struct resource othc1_cell_resources[] __devinitconst = {
+ SINGLE_IRQ_RESOURCE(NULL, PM8058_SW_1_IRQ),
+ SINGLE_IRQ_RESOURCE(NULL, PM8058_IR_1_IRQ),
+ {
+ .name = "othc_base",
+ .start = PM8058_OTHC_CNTR_BASE1,
+ .end = PM8058_OTHC_CNTR_BASE1,
+ .flags = IORESOURCE_IO,
+ },
+};
+
+static const struct resource othc2_cell_resources[] __devinitconst = {
+ {
+ .name = "othc_base",
+ .start = PM8058_OTHC_CNTR_BASE2,
+ .end = PM8058_OTHC_CNTR_BASE2,
+ .flags = IORESOURCE_IO,
+ },
+};
+
+static const struct resource batt_alarm_cell_resources[] __devinitconst = {
+ SINGLE_IRQ_RESOURCE("pm8058_batt_alarm_irq", PM8058_BATT_ALARM_IRQ),
+};
+
+static struct mfd_cell leds_cell __devinitdata = {
+ .name = "pm8058-led",
+ .id = -1,
+};
+
+static struct mfd_cell othc0_cell __devinitdata = {
+ .name = "pm8058-othc",
+ .id = 0,
+ .resources = othc0_cell_resources,
+ .num_resources = ARRAY_SIZE(othc0_cell_resources),
+};
+
+static struct mfd_cell othc1_cell __devinitdata = {
+ .name = "pm8058-othc",
+ .id = 1,
+ .resources = othc1_cell_resources,
+ .num_resources = ARRAY_SIZE(othc1_cell_resources),
+};
+
+static struct mfd_cell othc2_cell __devinitdata = {
+ .name = "pm8058-othc",
+ .id = 2,
+ .resources = othc2_cell_resources,
+ .num_resources = ARRAY_SIZE(othc2_cell_resources),
+};
+
+static struct pm8xxx_batt_alarm_core_data batt_alarm_cdata = {
+ .irq_name = "pm8058_batt_alarm_irq",
+ .reg_addr_threshold = REG_BATT_ALARM_THRESH,
+ .reg_addr_ctrl1 = REG_BATT_ALARM_CTRL1,
+ .reg_addr_ctrl2 = REG_BATT_ALARM_CTRL2,
+ .reg_addr_pwm_ctrl = REG_BATT_ALARM_PWM_CTRL,
+};
+
+static struct mfd_cell batt_alarm_cell __devinitdata = {
+ .name = PM8XXX_BATT_ALARM_DEV_NAME,
+ .id = -1,
+ .resources = batt_alarm_cell_resources,
+ .num_resources = ARRAY_SIZE(batt_alarm_cell_resources),
+ .platform_data = &batt_alarm_cdata,
+ .pdata_size = sizeof(struct pm8xxx_batt_alarm_core_data),
+};
+
+static struct mfd_cell upl_cell __devinitdata = {
+ .name = PM8XXX_UPL_DEV_NAME,
+ .id = -1,
+};
+
+static struct mfd_cell nfc_cell __devinitdata = {
+ .name = PM8XXX_NFC_DEV_NAME,
+ .id = -1,
+};
+
+static const struct resource rtc_cell_resources[] __devinitconst = {
+ [0] = SINGLE_IRQ_RESOURCE(NULL, PM8058_RTC_ALARM_IRQ),
+ [1] = {
+ .name = "pmic_rtc_base",
+ .start = PM8058_RTC_BASE,
+ .end = PM8058_RTC_BASE,
+ .flags = IORESOURCE_IO,
+ },
+};
+
+static struct mfd_cell rtc_cell __devinitdata = {
+ .name = PM8XXX_RTC_DEV_NAME,
+ .id = -1,
+ .resources = rtc_cell_resources,
+ .num_resources = ARRAY_SIZE(rtc_cell_resources),
+};
+
+static const struct resource resources_pwrkey[] __devinitconst = {
+ SINGLE_IRQ_RESOURCE(NULL, PM8058_PWRKEY_REL_IRQ),
+ SINGLE_IRQ_RESOURCE(NULL, PM8058_PWRKEY_PRESS_IRQ),
+};
+
+static struct mfd_cell vibrator_cell __devinitdata = {
+ .name = PM8XXX_VIBRATOR_DEV_NAME,
+ .id = -1,
+};
+
+static struct mfd_cell pwrkey_cell __devinitdata = {
+ .name = PM8XXX_PWRKEY_DEV_NAME,
+ .id = -1,
+ .num_resources = ARRAY_SIZE(resources_pwrkey),
+ .resources = resources_pwrkey,
+};
+
+static const struct resource resources_keypad[] = {
+ SINGLE_IRQ_RESOURCE(NULL, PM8058_KEYPAD_IRQ),
+ SINGLE_IRQ_RESOURCE(NULL, PM8058_KEYSTUCK_IRQ),
+};
+
+static struct mfd_cell keypad_cell __devinitdata = {
+ .name = PM8XXX_KEYPAD_DEV_NAME,
+ .id = -1,
+ .num_resources = ARRAY_SIZE(resources_keypad),
+ .resources = resources_keypad,
+};
+
+static const struct resource mpp_cell_resources[] __devinitconst = {
+ {
+ .start = PM8058_IRQ_BLOCK_BIT(PM8058_MPP_BLOCK_START, 0),
+ .end = PM8058_IRQ_BLOCK_BIT(PM8058_MPP_BLOCK_START, 0)
+ + PM8058_MPPS - 1,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+static struct mfd_cell mpp_cell __devinitdata = {
+ .name = PM8XXX_MPP_DEV_NAME,
+ .id = 0,
+ .resources = mpp_cell_resources,
+ .num_resources = ARRAY_SIZE(mpp_cell_resources),
+};
+
+static const struct resource gpio_cell_resources[] __devinitconst = {
+ [0] = {
+ .start = PM8058_IRQ_BLOCK_BIT(PM8058_GPIO_BLOCK_START, 0),
+ .end = PM8058_IRQ_BLOCK_BIT(PM8058_GPIO_BLOCK_START, 0)
+ + PM8058_GPIOS - 1,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+static struct mfd_cell gpio_cell __devinitdata = {
+ .name = PM8XXX_GPIO_DEV_NAME,
+ .id = -1,
+ .resources = gpio_cell_resources,
+ .num_resources = ARRAY_SIZE(gpio_cell_resources),
+};
+
+static int __devinit
+pm8058_add_subdevices(const struct pm8058_platform_data *pdata,
+ struct pm8058_chip *pmic)
+{
+ int rc = 0, irq_base = 0, i;
+ struct pm_irq_chip *irq_chip;
+ static struct mfd_cell *mfd_regulators, *mfd_xo_buffers;
+
+ if (pdata->irq_pdata) {
+ pdata->irq_pdata->irq_cdata.nirqs = PM8058_NR_IRQS;
+ irq_base = pdata->irq_pdata->irq_base;
+ irq_chip = pm8xxx_irq_init(pmic->dev, pdata->irq_pdata);
+
+ if (IS_ERR(irq_chip)) {
+ pr_err("Failed to init interrupts ret=%ld\n",
+ PTR_ERR(irq_chip));
+ return PTR_ERR(irq_chip);
+ }
+ pmic->irq_chip = irq_chip;
+ }
+
+ if (pdata->gpio_pdata) {
+ pdata->gpio_pdata->gpio_cdata.ngpios = PM8058_GPIOS;
+ gpio_cell.platform_data = pdata->gpio_pdata;
+ gpio_cell.pdata_size = sizeof(struct pm8xxx_gpio_platform_data);
+ rc = mfd_add_devices(pmic->dev, 0, &gpio_cell, 1,
+ NULL, irq_base);
+ if (rc) {
+ pr_err("Failed to add gpio subdevice ret=%d\n", rc);
+ goto bail;
+ }
+ }
+
+ if (pdata->mpp_pdata) {
+ pdata->mpp_pdata->core_data.nmpps = PM8058_MPPS;
+ pdata->mpp_pdata->core_data.base_addr = REG_MPP_BASE;
+ mpp_cell.platform_data = pdata->mpp_pdata;
+ mpp_cell.pdata_size = sizeof(struct pm8xxx_mpp_platform_data);
+ rc = mfd_add_devices(pmic->dev, 0, &mpp_cell, 1, NULL,
+ irq_base);
+ if (rc) {
+ pr_err("Failed to add mpp subdevice ret=%d\n", rc);
+ goto bail;
+ }
+ }
+
+ if (pdata->num_regulators > 0 && pdata->regulator_pdatas) {
+ mfd_regulators = kzalloc(sizeof(struct mfd_cell)
+ * (pdata->num_regulators), GFP_KERNEL);
+ if (!mfd_regulators) {
+ pr_err("Cannot allocate %d bytes for pm8058 regulator "
+ "mfd cells\n", sizeof(struct mfd_cell)
+ * (pdata->num_regulators));
+ rc = -ENOMEM;
+ goto bail;
+ }
+ for (i = 0; i < pdata->num_regulators; i++) {
+ mfd_regulators[i].name = "pm8058-regulator";
+ mfd_regulators[i].id = pdata->regulator_pdatas[i].id;
+ mfd_regulators[i].platform_data =
+ &(pdata->regulator_pdatas[i]);
+ mfd_regulators[i].pdata_size =
+ sizeof(struct pm8058_vreg_pdata);
+ }
+ rc = mfd_add_devices(pmic->dev, 0, mfd_regulators,
+ pdata->num_regulators, NULL, irq_base);
+ if (rc) {
+ pr_err("Failed to add regulator subdevices ret=%d\n",
+ rc);
+ kfree(mfd_regulators);
+ goto bail;
+ }
+ pmic->mfd_regulators = mfd_regulators;
+ }
+
+ if (pdata->num_xo_buffers > 0 && pdata->xo_buffer_pdata) {
+ mfd_xo_buffers = kzalloc(sizeof(struct mfd_cell)
+ * (pdata->num_xo_buffers), GFP_KERNEL);
+ if (!mfd_xo_buffers) {
+ pr_err("Cannot allocate %d bytes for pm8058 XO buffer "
+ "mfd cells\n", sizeof(struct mfd_cell)
+ * (pdata->num_xo_buffers));
+ rc = -ENOMEM;
+ goto bail;
+ }
+ for (i = 0; i < pdata->num_xo_buffers; i++) {
+ mfd_xo_buffers[i].name = PM8058_XO_BUFFER_DEV_NAME;
+ mfd_xo_buffers[i].id = pdata->xo_buffer_pdata[i].id;
+ mfd_xo_buffers[i].platform_data =
+ &(pdata->xo_buffer_pdata[i]);
+ mfd_xo_buffers[i].pdata_size =
+ sizeof(struct pm8058_xo_pdata);
+ }
+ rc = mfd_add_devices(pmic->dev, 0, mfd_xo_buffers,
+ pdata->num_xo_buffers, NULL, irq_base);
+ if (rc) {
+ pr_err("Failed to add XO buffer subdevices ret=%d\n",
+ rc);
+ kfree(mfd_xo_buffers);
+ goto bail;
+ }
+ pmic->mfd_xo_buffers = mfd_xo_buffers;
+ }
+
+ if (pdata->keypad_pdata) {
+ keypad_cell.platform_data = pdata->keypad_pdata;
+ keypad_cell.pdata_size =
+ sizeof(struct pm8xxx_keypad_platform_data);
+ rc = mfd_add_devices(pmic->dev, 0, &keypad_cell, 1, NULL,
+ irq_base);
+ if (rc) {
+ pr_err("Failed to add keypad subdevice ret=%d\n", rc);
+ goto bail;
+ }
+ }
+
+ if (pdata->rtc_pdata) {
+ rtc_cell.platform_data = pdata->rtc_pdata;
+ rtc_cell.pdata_size = sizeof(struct pm8xxx_rtc_platform_data);
+ rc = mfd_add_devices(pmic->dev, 0, &rtc_cell, 1, NULL,
+ irq_base);
+ if (rc) {
+ pr_err("Failed to add rtc subdevice ret=%d\n", rc);
+ goto bail;
+ }
+ }
+
+ if (pdata->pwrkey_pdata) {
+ pwrkey_cell.platform_data = pdata->pwrkey_pdata;
+ pwrkey_cell.pdata_size =
+ sizeof(struct pm8xxx_pwrkey_platform_data);
+ rc = mfd_add_devices(pmic->dev, 0, &pwrkey_cell, 1, NULL,
+ irq_base);
+ if (rc) {
+ pr_err("Failed to add pwrkey subdevice ret=%d\n", rc);
+ goto bail;
+ }
+ }
+
+ if (pdata->vibrator_pdata) {
+ vibrator_cell.platform_data = pdata->vibrator_pdata;
+ vibrator_cell.pdata_size =
+ sizeof(struct pm8xxx_vibrator_platform_data);
+ rc = mfd_add_devices(pmic->dev, 0, &vibrator_cell, 1, NULL,
+ irq_base);
+ if (rc) {
+ pr_err("Failed to add vibrator subdevice ret=%d\n",
+ rc);
+ goto bail;
+ }
+ }
+
+ if (pdata->leds_pdata) {
+ leds_cell.platform_data = pdata->leds_pdata;
+ leds_cell.pdata_size =
+ sizeof(struct pmic8058_leds_platform_data);
+ rc = mfd_add_devices(pmic->dev, 0, &leds_cell, 1, NULL,
+ irq_base);
+ if (rc) {
+ pr_err("Failed to add leds subdevice ret=%d\n", rc);
+ goto bail;
+ }
+ }
+
+ if (pdata->xoadc_pdata) {
+ xoadc_cell.platform_data = pdata->xoadc_pdata;
+ xoadc_cell.pdata_size =
+ sizeof(struct xoadc_platform_data);
+ rc = mfd_add_devices(pmic->dev, 0, &xoadc_cell, 1, NULL,
+ irq_base);
+ if (rc) {
+ pr_err("Failed to add leds subdevice ret=%d\n", rc);
+ goto bail;
+ }
+ }
+
+ if (pdata->othc0_pdata) {
+ othc0_cell.platform_data = pdata->othc0_pdata;
+ othc0_cell.pdata_size =
+ sizeof(struct pmic8058_othc_config_pdata);
+ rc = mfd_add_devices(pmic->dev, 0, &othc0_cell, 1, NULL, 0);
+ if (rc) {
+ pr_err("Failed to add othc0 subdevice ret=%d\n", rc);
+ goto bail;
+ }
+ }
+
+ if (pdata->othc1_pdata) {
+ othc1_cell.platform_data = pdata->othc1_pdata;
+ othc1_cell.pdata_size =
+ sizeof(struct pmic8058_othc_config_pdata);
+ rc = mfd_add_devices(pmic->dev, 0, &othc1_cell, 1, NULL,
+ irq_base);
+ if (rc) {
+ pr_err("Failed to add othc1 subdevice ret=%d\n", rc);
+ goto bail;
+ }
+ }
+
+ if (pdata->othc2_pdata) {
+ othc2_cell.platform_data = pdata->othc2_pdata;
+ othc2_cell.pdata_size =
+ sizeof(struct pmic8058_othc_config_pdata);
+ rc = mfd_add_devices(pmic->dev, 0, &othc2_cell, 1, NULL, 0);
+ if (rc) {
+ pr_err("Failed to add othc2 subdevice ret=%d\n", rc);
+ goto bail;
+ }
+ }
+
+ if (pdata->pwm_pdata) {
+ pm8058_pwm_cell.platform_data = pdata->pwm_pdata;
+ pm8058_pwm_cell.pdata_size = sizeof(struct pm8058_pwm_pdata);
+ rc = mfd_add_devices(pmic->dev, 0, &pm8058_pwm_cell, 1, NULL,
+ irq_base);
+ if (rc) {
+ pr_err("Failed to add pwm subdevice ret=%d\n", rc);
+ goto bail;
+ }
+ }
+
+ if (pdata->misc_pdata) {
+ misc_cell.platform_data = pdata->misc_pdata;
+ misc_cell.pdata_size = sizeof(struct pm8xxx_misc_platform_data);
+ rc = mfd_add_devices(pmic->dev, 0, &misc_cell, 1, NULL,
+ irq_base);
+ if (rc) {
+ pr_err("Failed to add misc subdevice ret=%d\n", rc);
+ goto bail;
+ }
+ }
+
+ rc = mfd_add_devices(pmic->dev, 0, &thermal_alarm_cell, 1, NULL,
+ irq_base);
+ if (rc) {
+ pr_err("Failed to add thermal alarm subdevice ret=%d\n",
+ rc);
+ goto bail;
+ }
+
+ rc = mfd_add_devices(pmic->dev, 0, &batt_alarm_cell, 1, NULL,
+ irq_base);
+ if (rc) {
+ pr_err("Failed to add battery alarm subdevice ret=%d\n",
+ rc);
+ goto bail;
+ }
+
+ rc = mfd_add_devices(pmic->dev, 0, &upl_cell, 1, NULL, 0);
+ if (rc) {
+ pr_err("Failed to add upl subdevice ret=%d\n", rc);
+ goto bail;
+ }
+
+ rc = mfd_add_devices(pmic->dev, 0, &nfc_cell, 1, NULL, 0);
+ if (rc) {
+ pr_err("Failed to add upl subdevice ret=%d\n", rc);
+ goto bail;
+ }
+
+ if (pdata->charger_pdata) {
+ pm8058_charger_cell.platform_data = pdata->charger_pdata;
+ pm8058_charger_cell.pdata_size = sizeof(struct
+ pmic8058_charger_data);
+ rc = mfd_add_devices(pmic->dev, 0, &pm8058_charger_cell,
+ 1, NULL, irq_base);
+ if (rc) {
+ pr_err("Failed to add charger subdevice ret=%d\n", rc);
+ goto bail;
+ }
+ }
+
+ rc = mfd_add_devices(pmic->dev, 0, &debugfs_cell, 1, NULL, irq_base);
+ if (rc) {
+ pr_err("Failed to add debugfs subdevice ret=%d\n", rc);
+ goto bail;
+ }
+
+ return rc;
+bail:
+ if (pmic->irq_chip) {
+ pm8xxx_irq_exit(pmic->irq_chip);
+ pmic->irq_chip = NULL;
+ }
+ return rc;
+}
+
static int __devinit pm8058_probe(struct platform_device *pdev)
{
- int i, rc;
- struct pm8058_platform_data *pdata = pdev->dev.platform_data;
- struct pm8058_chip *chip;
+ int rc;
+ struct pm8058_platform_data *pdata = pdev->dev.platform_data;
+ struct pm8058_chip *pmic;
- if (pdata == NULL || !gpio_is_valid(pdata->irq)) {
+ if (pdata == NULL) {
pr_err("%s: No platform_data or IRQ.\n", __func__);
return -ENODEV;
}
- if (pdata->num_subdevs == 0) {
- pr_err("%s: No sub devices to support.\n", __func__);
- return -ENODEV;
- }
-
- chip = kzalloc(sizeof *chip, GFP_KERNEL);
- if (chip == NULL) {
+ pmic = kzalloc(sizeof *pmic, GFP_KERNEL);
+ if (pmic == NULL) {
pr_err("%s: kzalloc() failed.\n", __func__);
return -ENOMEM;
}
- chip->dev = &pdev->dev;
+ pmic->dev = &pdev->dev;
+
+ pm8058_drvdata.pm_chip_data = pmic;
+ platform_set_drvdata(pdev, &pm8058_drvdata);
+
+ mutex_init(&pmic->pm_lock);
+ pmic_chip = pmic;
/* Read PMIC chip revision */
- rc = ssbi_read(chip->dev, SSBI_REG_REV, &chip->revision, 1);
+ rc = pm8058_readb(pmic->dev, PM8058_REG_REV, &pmic->revision);
if (rc)
- pr_err("%s: Failed on ssbi_read for revision: rc=%d.\n",
+ pr_err("%s: Failed on pm8058_readb for revision: rc=%d.\n",
__func__, rc);
- pr_info("%s: PMIC revision: %X\n", __func__, chip->revision);
- (void) memcpy((void *)&chip->pdata, (const void *)pdata,
- sizeof(chip->pdata));
+ pr_info("%s: PMIC revision: %X\n", __func__, pmic->revision);
- mutex_init(&chip->pm_lock);
- irq_set_handler_data(pdata->irq, (void *)chip);
- irq_set_irq_wake(pdata->irq, 1);
+ (void) memcpy((void *)&pmic->pdata, (const void *)pdata,
+ sizeof(pmic->pdata));
- chip->pm_max_irq = 0;
- chip->pm_max_blocks = 0;
- chip->pm_max_masters = 0;
-
- platform_set_drvdata(pdev, chip);
-
- pmic_chip = chip;
-
- /* Register for all reserved IRQs */
- for (i = pdata->irq_base; i < (pdata->irq_base + MAX_PM_IRQ); i++) {
- irq_set_chip(i, &pm8058_irq_chip);
- irq_set_chip_data(i, (void *)chip);
- irq_set_handler(i, handle_edge_irq);
- set_irq_flags(i, IRQF_VALID);
- irq_set_nested_thread(i, 1);
+ rc = pm8058_add_subdevices(pdata, pmic);
+ if (rc) {
+ pr_err("Cannot add subdevices rc=%d\n", rc);
+ goto err;
}
- rc = mfd_add_devices(chip->dev, 0, pdata->sub_devices,
- pdata->num_subdevs, NULL, 0);
-
- /* Add charger sub device with the chip parameter as driver data */
- if (pdata->charger_sub_device) {
- rc = mfd_add_devices(chip->dev, 0,
- pdata->charger_sub_device,
- 1, NULL, 0);
- }
-
- if (pdata->init) {
- rc = pdata->init(chip);
- if (rc != 0) {
- pr_err("%s: board init failed\n", __func__);
- chip->dev = NULL;
- kfree(chip);
- return -ENODEV;
- }
- }
-
- rc = request_threaded_irq(pdata->irq, NULL, pm8058_isr_thread,
- IRQF_ONESHOT | IRQF_DISABLED | pdata->irq_trigger_flags,
- "pm8058-irq", chip);
- if (rc < 0)
- pr_err("%s: could not request irq %d: %d\n", __func__,
- pdata->irq, rc);
-
- rc = pmic8058_dbg_probe(chip);
- if (rc < 0)
- pr_err("%s: could not set up debugfs: %d\n", __func__, rc);
-
rc = pm8058_hard_reset_config(SHUTDOWN_ON_HARD_RESET);
if (rc < 0)
pr_err("%s: failed to config shutdown on hard reset: %d\n",
__func__, rc);
- register_syscore_ops(&pm8058_pm);
-
return 0;
+
+err:
+ mfd_remove_devices(pmic->dev);
+ platform_set_drvdata(pdev, NULL);
+ kfree(pmic);
+ return rc;
}
static int __devexit pm8058_remove(struct platform_device *pdev)
{
- struct pm8058_chip *chip;
+ struct pm8xxx_drvdata *drvdata;
+ struct pm8058_chip *pmic = NULL;
- chip = platform_get_drvdata(pdev);
- if (chip) {
- if (chip->pm_max_irq) {
- irq_set_irq_wake(chip->pdata.irq, 0);
- free_irq(chip->pdata.irq, chip);
- }
- mutex_destroy(&chip->pm_lock);
- chip->dev = NULL;
-
- kfree(chip);
+ drvdata = platform_get_drvdata(pdev);
+ if (drvdata)
+ pmic = drvdata->pm_chip_data;
+ if (pmic) {
+ if (pmic->dev)
+ mfd_remove_devices(pmic->dev);
+ if (pmic->irq_chip)
+ pm8xxx_irq_exit(pmic->irq_chip);
+ mutex_destroy(&pmic->pm_lock);
+ kfree(pmic->mfd_regulators);
+ kfree(pmic);
}
-
- pmic8058_dbg_remove();
+ platform_set_drvdata(pdev, NULL);
return 0;
}
@@ -1489,7 +1269,7 @@
{
return platform_driver_register(&pm8058_driver);
}
-arch_initcall(pm8058_init);
+postcore_initcall(pm8058_init);
static void __exit pm8058_exit(void)
{
diff --git a/drivers/misc/Kconfig b/drivers/misc/Kconfig
index dfbf345..3d7738e 100644
--- a/drivers/misc/Kconfig
+++ b/drivers/misc/Kconfig
@@ -601,21 +601,19 @@
on the PM8XXX chips. The vibrator is controlled using the
timed output class.
-config PMIC8058_NFC
- tristate "Qualcomm PM8058 support for Near Field Communication"
- depends on PMIC8058
- default y
+config PMIC8XXX_NFC
+ tristate "Qualcomm PM8XXX support for Near Field Communication"
+ depends on MFD_PM8XXX
help
- Qualcomm PM8058 chip has a module to support NFC (Near Field
+ Qualcomm PM8XXX chips have a module to support NFC (Near Field
Communication). This option enables the driver to support it.
-config PMIC8058_UPL
- tristate "Qualcomm PM8058 support for User Programmable Logic"
- depends on PMIC8058
- default n
+config PMIC8XXX_UPL
+ tristate "Qualcomm PM8XXX support for User Programmable Logic"
+ depends on MFD_PM8XXX
help
This option enables device driver support for User Programmable Logic
- on Qualcomm PM8058 chip. The UPL module provides a means to implement
+ on Qualcomm PM8XXX chips. The UPL module provides a means to implement
simple truth table based logic via a set of control registers. I/O may
be routed in and out of the UPL module via GPIO or DTEST pins.
diff --git a/drivers/misc/Makefile b/drivers/misc/Makefile
index a38ccfd..b7f23c8 100644
--- a/drivers/misc/Makefile
+++ b/drivers/misc/Makefile
@@ -59,8 +59,8 @@
obj-$(CONFIG_PMIC8058_PWM) += pmic8058-pwm.o
obj-$(CONFIG_PMIC8058_VIBRATOR) += pmic8058-vibrator.o
obj-$(CONFIG_PMIC8XXX_VIBRATOR) += pm8xxx-vibrator.o
-obj-$(CONFIG_PMIC8058_NFC) += pmic8058-nfc.o
-obj-$(CONFIG_PMIC8058_UPL) += pmic8058-upl.o
+obj-$(CONFIG_PMIC8XXX_NFC) += pm8xxx-nfc.o
+obj-$(CONFIG_PMIC8XXX_UPL) += pm8xxx-upl.o
obj-$(CONFIG_MSM_MEMORY_LOW_POWER_MODE_SUSPEND_DEEP_POWER_DOWN) \
+= msm_migrate_pages.o
obj-$(CONFIG_PMIC8058_XOADC) += pmic8058-xoadc.o
diff --git a/drivers/misc/pm8xxx-nfc.c b/drivers/misc/pm8xxx-nfc.c
new file mode 100644
index 0000000..1aaa3e3
--- /dev/null
+++ b/drivers/misc/pm8xxx-nfc.c
@@ -0,0 +1,311 @@
+/* Copyright (c) 2010,2011 Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ */
+/*
+ * Qualcomm PMIC8XXX NFC driver
+ *
+ */
+
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/err.h>
+#include <linux/debugfs.h>
+#include <linux/slab.h>
+#include <linux/mfd/pm8xxx/core.h>
+#include <linux/mfd/pm8xxx/nfc.h>
+
+/* PM8XXX NFC */
+#define SSBI_REG_NFC_CTRL 0x14D
+#define SSBI_REG_NFC_TEST 0x14E
+
+/* NFC_CTRL */
+#define PM8XXX_NFC_SUPPORT_EN 0x80
+#define PM8XXX_NFC_LDO_EN 0x40
+#define PM8XXX_NFC_EN 0x20
+#define PM8XXX_NFC_EXT_VDDLDO_EN 0x10
+#define PM8XXX_NFC_VPH_PWR_EN 0x08
+#define PM8XXX_NFC_RESERVED 0x04
+#define PM8XXX_NFC_VDDLDO_LEVEL 0x03
+
+/* NFC_TEST */
+#define PM8XXX_NFC_VDDLDO_MON_EN 0x80
+#define PM8XXX_NFC_ATEST_EN 0x40
+#define PM8XXX_NFC_DTEST1_EN 0x20
+#define PM8XXX_NFC_RESERVED2 0x18
+#define PM8XXX_NFC_VDDLDO_OK_S 0x04
+#define PM8XXX_NFC_MBG_EN_S 0x02
+#define PM8XXX_NFC_EXT_EN_S 0x01
+
+struct pm8xxx_nfc_device {
+ struct device *dev;
+ struct mutex nfc_mutex;
+#if defined(CONFIG_DEBUG_FS)
+ struct dentry *dent;
+#endif
+};
+static struct pm8xxx_nfc_device *nfc_dev;
+
+/* APIs */
+/*
+ * pm8xxx_nfc_request - request a handle to access NFC device
+ */
+struct pm8xxx_nfc_device *pm8xxx_nfc_request(void)
+{
+ return nfc_dev;
+}
+EXPORT_SYMBOL(pm8xxx_nfc_request);
+
+/*
+ * pm8xxx_nfc_config - configure NFC signals
+ *
+ * @nfcdev: the NFC device
+ * @mask: signal mask to configure
+ * @flags: control flags
+ */
+int pm8xxx_nfc_config(struct pm8xxx_nfc_device *nfcdev, u32 mask, u32 flags)
+{
+ u8 nfc_ctrl, nfc_test, m, f;
+ int rc;
+
+ if (nfcdev == NULL || IS_ERR(nfcdev) || !mask)
+ return -EINVAL;
+
+ mutex_lock(&nfcdev->nfc_mutex);
+
+ if (!(mask & PM_NFC_CTRL_REQ))
+ goto config_test;
+
+ rc = pm8xxx_readb(nfcdev->dev->parent, SSBI_REG_NFC_CTRL, &nfc_ctrl);
+ if (rc) {
+ pr_err("%s: FAIL pm8xxx_readb(): rc=%d (nfc_ctrl=0x%x)\n",
+ __func__, rc, nfc_ctrl);
+ goto config_done;
+ }
+
+ m = mask & 0x00ff;
+ f = flags & 0x00ff;
+ nfc_ctrl &= ~m;
+ nfc_ctrl |= m & f;
+
+ rc = pm8xxx_writeb(nfcdev->dev->parent, SSBI_REG_NFC_CTRL, nfc_ctrl);
+ if (rc) {
+ pr_err("%s: FAIL pm8xxx_writeb(): rc=%d (nfc_ctrl=0x%x)\n",
+ __func__, rc, nfc_ctrl);
+ goto config_done;
+ }
+
+config_test:
+ if (!(mask & PM_NFC_TEST_REQ))
+ goto config_done;
+
+ rc = pm8xxx_readb(nfcdev->dev->parent, SSBI_REG_NFC_TEST, &nfc_test);
+ if (rc) {
+ pr_err("%s: FAIL pm8xxx_readb(): rc=%d (nfc_test=0x%x)\n",
+ __func__, rc, nfc_test);
+ goto config_done;
+ }
+
+ m = (mask >> 8) & 0x00ff;
+ f = (flags >> 8) & 0x00ff;
+ nfc_test &= ~m;
+ nfc_test |= m & f;
+
+ rc = pm8xxx_writeb(nfcdev->dev->parent, SSBI_REG_NFC_TEST, nfc_test);
+ if (rc) {
+ pr_err("%s: FAIL pm8xxx_writeb(): rc=%d (nfc_test=0x%x)\n",
+ __func__, rc, nfc_test);
+ goto config_done;
+ }
+
+config_done:
+ mutex_unlock(&nfcdev->nfc_mutex);
+ return 0;
+}
+EXPORT_SYMBOL(pm8xxx_nfc_config);
+
+/*
+ * pm8xxx_nfc_get_status - get NFC status
+ *
+ * @nfcdev: the NFC device
+ * @mask: of status mask to read
+ * @status: pointer to the status variable
+ */
+int pm8xxx_nfc_get_status(struct pm8xxx_nfc_device *nfcdev,
+ u32 mask, u32 *status)
+{
+ u8 nfc_ctrl, nfc_test;
+ u32 st;
+ int rc;
+
+ if (nfcdev == NULL || IS_ERR(nfcdev) || status == NULL)
+ return -EINVAL;
+
+ st = 0;
+ mutex_lock(&nfcdev->nfc_mutex);
+
+ if (!(mask & PM_NFC_CTRL_REQ))
+ goto read_test;
+
+ rc = pm8xxx_readb(nfcdev->dev->parent, SSBI_REG_NFC_CTRL, &nfc_ctrl);
+ if (rc) {
+ pr_err("%s: FAIL pm8xxx_readb(): rc=%d (nfc_ctrl=0x%x)\n",
+ __func__, rc, nfc_ctrl);
+ goto get_status_done;
+ }
+
+read_test:
+ if (!(mask & (PM_NFC_TEST_REQ | PM_NFC_TEST_STATUS)))
+ goto get_status_done;
+
+ rc = pm8xxx_readb(nfcdev->dev->parent, SSBI_REG_NFC_TEST, &nfc_test);
+ if (rc)
+ pr_err("%s: FAIL pm8xxx_readb(): rc=%d (nfc_test=0x%x)\n",
+ __func__, rc, nfc_test);
+
+get_status_done:
+ st = nfc_ctrl;
+ st |= nfc_test << 8;
+ *status = st;
+
+ mutex_unlock(&nfcdev->nfc_mutex);
+ return 0;
+}
+EXPORT_SYMBOL(pm8xxx_nfc_get_status);
+
+/*
+ * pm8xxx_nfc_free - free the NFC device
+ */
+void pm8xxx_nfc_free(struct pm8xxx_nfc_device *nfcdev)
+{
+ /* Disable all signals */
+ pm8xxx_nfc_config(nfcdev, PM_NFC_CTRL_REQ, 0);
+}
+EXPORT_SYMBOL(pm8xxx_nfc_free);
+
+#if defined(CONFIG_DEBUG_FS)
+static int pm8xxx_nfc_debug_set(void *data, u64 val)
+{
+ struct pm8xxx_nfc_device *nfcdev;
+ u32 mask, control;
+ int rc;
+
+ nfcdev = (struct pm8xxx_nfc_device *)data;
+ control = (u32)val & 0xffff;
+ mask = ((u32)val >> 16) & 0xffff;
+ rc = pm8xxx_nfc_config(nfcdev, mask, control);
+ if (rc)
+ pr_err("%s: ERR pm8xxx_nfc_config: rc=%d, "
+ "[mask, control]=[0x%x, 0x%x]\n",
+ __func__, rc, mask, control);
+
+ return 0;
+}
+
+static int pm8xxx_nfc_debug_get(void *data, u64 *val)
+{
+ struct pm8xxx_nfc_device *nfcdev;
+ u32 status;
+ int rc;
+
+ nfcdev = (struct pm8xxx_nfc_device *)data;
+ rc = pm8xxx_nfc_get_status(nfcdev, (u32)-1, &status);
+ if (rc)
+ pr_err("%s: ERR pm8xxx_nfc_get_status: rc=%d, status=0x%x\n",
+ __func__, rc, status);
+
+ if (val)
+ *val = (u64)status;
+ return 0;
+}
+
+DEFINE_SIMPLE_ATTRIBUTE(pm8xxx_nfc_fops, pm8xxx_nfc_debug_get,
+ pm8xxx_nfc_debug_set, "%llu\n");
+
+static int pm8xxx_nfc_debug_init(struct pm8xxx_nfc_device *nfcdev)
+{
+ struct dentry *dent;
+
+ dent = debugfs_create_file("pm8xxx-nfc", 0644, NULL,
+ (void *)nfcdev, &pm8xxx_nfc_fops);
+
+ if (dent == NULL || IS_ERR(dent))
+ pr_err("%s: ERR debugfs_create_file: dent=0x%x\n",
+ __func__, (unsigned)dent);
+
+ nfcdev->dent = dent;
+ return 0;
+}
+#endif
+
+static int __devinit pm8xxx_nfc_probe(struct platform_device *pdev)
+{
+ struct pm8xxx_nfc_device *nfcdev;
+
+ nfcdev = kzalloc(sizeof *nfcdev, GFP_KERNEL);
+ if (nfcdev == NULL) {
+ pr_err("%s: kzalloc() failed.\n", __func__);
+ return -ENOMEM;
+ }
+
+ mutex_init(&nfcdev->nfc_mutex);
+
+ nfcdev->dev = &pdev->dev;
+ nfc_dev = nfcdev;
+ platform_set_drvdata(pdev, nfcdev);
+
+#if defined(CONFIG_DEBUG_FS)
+ pm8xxx_nfc_debug_init(nfc_dev);
+#endif
+
+ pr_notice("%s: OK\n", __func__);
+ return 0;
+}
+
+static int __devexit pm8xxx_nfc_remove(struct platform_device *pdev)
+{
+ struct pm8xxx_nfc_device *nfcdev = platform_get_drvdata(pdev);
+
+#if defined(CONFIG_DEBUG_FS)
+ debugfs_remove(nfcdev->dent);
+#endif
+
+ platform_set_drvdata(pdev, NULL);
+ kfree(nfcdev);
+ return 0;
+}
+
+static struct platform_driver pm8xxx_nfc_driver = {
+ .probe = pm8xxx_nfc_probe,
+ .remove = __devexit_p(pm8xxx_nfc_remove),
+ .driver = {
+ .name = PM8XXX_NFC_DEV_NAME,
+ .owner = THIS_MODULE,
+ },
+};
+
+static int __init pm8xxx_nfc_init(void)
+{
+ return platform_driver_register(&pm8xxx_nfc_driver);
+}
+
+static void __exit pm8xxx_nfc_exit(void)
+{
+ platform_driver_unregister(&pm8xxx_nfc_driver);
+}
+
+module_init(pm8xxx_nfc_init);
+module_exit(pm8xxx_nfc_exit);
+
+MODULE_LICENSE("GPL v2");
+MODULE_DESCRIPTION("PM8XXX NFC driver");
+MODULE_VERSION("1.0");
+MODULE_ALIAS("platform:" PM8XXX_NFC_DEV_NAME);
diff --git a/drivers/misc/pm8xxx-upl.c b/drivers/misc/pm8xxx-upl.c
new file mode 100644
index 0000000..d3d9746f
--- /dev/null
+++ b/drivers/misc/pm8xxx-upl.c
@@ -0,0 +1,350 @@
+/* Copyright (c) 2010,2011 Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ */
+/*
+ * Qualcomm PM8XXX UPL driver
+ *
+ */
+
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/err.h>
+#include <linux/debugfs.h>
+#include <linux/slab.h>
+#include <linux/mfd/pm8xxx/core.h>
+#include <linux/mfd/pm8xxx/upl.h>
+
+/* PMIC8XXX UPL registers */
+#define SSBI_REG_UPL_CTRL 0x17B
+#define SSBI_REG_UPL_TRUTHTABLE1 0x17C
+#define SSBI_REG_UPL_TRUTHTABLE2 0x17D
+
+struct pm8xxx_upl_device {
+ struct device *dev;
+ struct mutex upl_mutex;
+#if defined(CONFIG_DEBUG_FS)
+ struct dentry *dent;
+#endif
+};
+static struct pm8xxx_upl_device *upl_dev;
+
+/* APIs */
+
+/*
+ * pm8xxx_upl_request - request a handle to access UPL device
+ */
+struct pm8xxx_upl_device *pm8xxx_upl_request(void)
+{
+ return upl_dev;
+}
+EXPORT_SYMBOL(pm8xxx_upl_request);
+
+/*
+ * pm8xxx_upl_read_truthtable - read value currently stored in UPL truth table
+ *
+ * @upldev: the UPL device
+ * @truthtable: value read from UPL truth table
+ */
+int pm8xxx_upl_read_truthtable(struct pm8xxx_upl_device *upldev,
+ u16 *truthtable)
+{
+ int rc = 0;
+ u8 table[2];
+
+ if (upldev == NULL || IS_ERR(upldev))
+ return -EINVAL;
+
+ mutex_lock(&upldev->upl_mutex);
+
+ rc = pm8xxx_readb(upldev->dev->parent, SSBI_REG_UPL_TRUTHTABLE1,
+ &(table[0]));
+ if (rc) {
+ pr_err("%s: FAIL pm8xxx_readb(0x%X)=0x%02X: rc=%d\n",
+ __func__, SSBI_REG_UPL_TRUTHTABLE1, table[0], rc);
+ goto upl_read_done;
+ }
+
+ rc = pm8xxx_readb(upldev->dev->parent, SSBI_REG_UPL_TRUTHTABLE2,
+ &(table[1]));
+ if (rc)
+ pr_err("%s: FAIL pm8xxx_readb(0x%X)=0x%02X: rc=%d\n",
+ __func__, SSBI_REG_UPL_TRUTHTABLE2, table[1], rc);
+upl_read_done:
+ mutex_unlock(&upldev->upl_mutex);
+ *truthtable = (((u16)table[1]) << 8) | table[0];
+ return rc;
+}
+EXPORT_SYMBOL(pm8xxx_upl_read_truthtable);
+
+/*
+ * pm8xxx_upl_writes_truthtable - write value into UPL truth table
+ *
+ * @upldev: the UPL device
+ * @truthtable: value written to UPL truth table
+ *
+ * Each bit in parameter "truthtable" corresponds to the UPL output for a given
+ * set of input pin values. For example, if the input pins have the following
+ * values: A=1, B=1, C=1, D=0, then the UPL would output the value of bit 14
+ * (0b1110) in parameter "truthtable".
+ */
+int pm8xxx_upl_write_truthtable(struct pm8xxx_upl_device *upldev,
+ u16 truthtable)
+{
+ int rc = 0;
+ u8 table[2];
+
+ if (upldev == NULL || IS_ERR(upldev))
+ return -EINVAL;
+
+ table[0] = truthtable & 0xFF;
+ table[1] = (truthtable >> 8) & 0xFF;
+
+ mutex_lock(&upldev->upl_mutex);
+
+ rc = pm8xxx_writeb(upldev->dev->parent, SSBI_REG_UPL_TRUTHTABLE1,
+ table[0]);
+ if (rc) {
+ pr_err("%s: FAIL pm8xxx_writeb(0x%X)=0x%04X: rc=%d\n",
+ __func__, SSBI_REG_UPL_TRUTHTABLE1, table[0], rc);
+ goto upl_write_done;
+ }
+
+ rc = pm8xxx_writeb(upldev->dev->parent, SSBI_REG_UPL_TRUTHTABLE2,
+ table[1]);
+ if (rc)
+ pr_err("%s: FAIL pm8xxx_writeb(0x%X)=0x%04X: rc=%d\n",
+ __func__, SSBI_REG_UPL_TRUTHTABLE2, table[1], rc);
+upl_write_done:
+ mutex_unlock(&upldev->upl_mutex);
+ return rc;
+}
+EXPORT_SYMBOL(pm8xxx_upl_write_truthtable);
+
+/*
+ * pm8xxx_upl_config - configure UPL I/O settings and UPL enable/disable
+ *
+ * @upldev: the UPL device
+ * @mask: setting mask to configure
+ * @flags: setting flags
+ */
+int pm8xxx_upl_config(struct pm8xxx_upl_device *upldev, u32 mask, u32 flags)
+{
+ int rc;
+ u8 upl_ctrl, m, f;
+
+ if (upldev == NULL || IS_ERR(upldev))
+ return -EINVAL;
+
+ mutex_lock(&upldev->upl_mutex);
+
+ rc = pm8xxx_readb(upldev->dev->parent, SSBI_REG_UPL_CTRL, &upl_ctrl);
+ if (rc) {
+ pr_err("%s: FAIL pm8xxx_readb(0x%X)=0x%02X: rc=%d\n",
+ __func__, SSBI_REG_UPL_CTRL, upl_ctrl, rc);
+ goto upl_config_done;
+ }
+
+ m = mask & 0x00ff;
+ f = flags & 0x00ff;
+ upl_ctrl &= ~m;
+ upl_ctrl |= m & f;
+
+ rc = pm8xxx_writeb(upldev->dev->parent, SSBI_REG_UPL_CTRL, upl_ctrl);
+ if (rc)
+ pr_err("%s: FAIL pm8xxx_writeb(0x%X)=0x%02X: rc=%d\n",
+ __func__, SSBI_REG_UPL_CTRL, upl_ctrl, rc);
+upl_config_done:
+ mutex_unlock(&upldev->upl_mutex);
+ return rc;
+}
+EXPORT_SYMBOL(pm8xxx_upl_config);
+
+#if defined(CONFIG_DEBUG_FS)
+
+static int truthtable_set(void *data, u64 val)
+{
+ int rc;
+
+ rc = pm8xxx_upl_write_truthtable(data, val);
+ if (rc)
+ pr_err("%s: pm8xxx_upl_write_truthtable: rc=%d, "
+ "truthtable=0x%llX\n", __func__, rc, val);
+ return rc;
+}
+
+static int truthtable_get(void *data, u64 *val)
+{
+ int rc;
+ u16 truthtable;
+
+ rc = pm8xxx_upl_read_truthtable(data, &truthtable);
+ if (rc)
+ pr_err("%s: pm8xxx_upl_read_truthtable: rc=%d, "
+ "truthtable=0x%X\n", __func__, rc, truthtable);
+ if (val)
+ *val = truthtable;
+
+ return rc;
+}
+
+DEFINE_SIMPLE_ATTRIBUTE(upl_truthtable_fops, truthtable_get,
+ truthtable_set, "0x%04llX\n");
+
+/* enter values as 0xMMMMFFFF where MMMM is the mask and FFFF is the flags */
+static int control_set(void *data, u64 val)
+{
+ u8 mask, flags;
+ int rc;
+
+ flags = val & 0xFFFF;
+ mask = (val >> 16) & 0xFFFF;
+
+ rc = pm8xxx_upl_config(data, mask, flags);
+ if (rc)
+ pr_err("%s: pm8xxx_upl_config: rc=%d, mask = 0x%X, "
+ "flags = 0x%X\n", __func__, rc, mask, flags);
+ return rc;
+}
+
+static int control_get(void *data, u64 *val)
+{
+ struct pm8xxx_upl_device *upldev;
+ int rc = 0;
+ u8 ctrl;
+
+ upldev = data;
+
+ mutex_lock(&upldev->upl_mutex);
+
+ rc = pm8xxx_readb(upldev->dev->parent, SSBI_REG_UPL_CTRL, &ctrl);
+ if (rc)
+ pr_err("%s: FAIL pm8xxx_readb(): rc=%d (ctrl=0x%02X)\n",
+ __func__, rc, ctrl);
+
+ mutex_unlock(&upldev->upl_mutex);
+
+ *val = ctrl;
+
+ return rc;
+}
+
+DEFINE_SIMPLE_ATTRIBUTE(upl_control_fops, control_get,
+ control_set, "0x%02llX\n");
+
+static int pm8xxx_upl_debug_init(struct pm8xxx_upl_device *upldev)
+{
+ struct dentry *dent;
+ struct dentry *temp;
+
+ dent = debugfs_create_dir("pm8xxx-upl", NULL);
+ if (dent == NULL || IS_ERR(dent)) {
+ pr_err("%s: ERR debugfs_create_dir: dent=0x%X\n",
+ __func__, (unsigned)dent);
+ return -ENOMEM;
+ }
+
+ temp = debugfs_create_file("truthtable", S_IRUSR | S_IWUSR, dent,
+ upldev, &upl_truthtable_fops);
+ if (temp == NULL || IS_ERR(temp)) {
+ pr_err("%s: ERR debugfs_create_file: dent=0x%X\n",
+ __func__, (unsigned)dent);
+ goto debug_error;
+ }
+
+ temp = debugfs_create_file("control", S_IRUSR | S_IWUSR, dent,
+ upldev, &upl_control_fops);
+ if (temp == NULL || IS_ERR(temp)) {
+ pr_err("%s: ERR debugfs_create_file: dent=0x%X\n",
+ __func__, (unsigned)dent);
+ goto debug_error;
+ }
+
+ upldev->dent = dent;
+ return 0;
+
+debug_error:
+ debugfs_remove_recursive(dent);
+ return -ENOMEM;
+}
+
+static int __devexit pm8xxx_upl_debug_remove(struct pm8xxx_upl_device *upldev)
+{
+ debugfs_remove_recursive(upldev->dent);
+ return 0;
+}
+
+#endif /* CONFIG_DEBUG_FS */
+
+static int __devinit pm8xxx_upl_probe(struct platform_device *pdev)
+{
+ struct pm8xxx_upl_device *upldev;
+
+ upldev = kzalloc(sizeof *upldev, GFP_KERNEL);
+ if (upldev == NULL) {
+ pr_err("%s: kzalloc() failed.\n", __func__);
+ return -ENOMEM;
+ }
+
+ mutex_init(&upldev->upl_mutex);
+
+ upl_dev = upldev;
+ upldev->dev = &pdev->dev;
+ platform_set_drvdata(pdev, upldev);
+
+#if defined(CONFIG_DEBUG_FS)
+ pm8xxx_upl_debug_init(upl_dev);
+#endif
+ pr_notice("%s: OK\n", __func__);
+ return 0;
+}
+
+static int __devexit pm8xxx_upl_remove(struct platform_device *pdev)
+{
+ struct pm8xxx_upl_device *upldev = platform_get_drvdata(pdev);
+
+#if defined(CONFIG_DEBUG_FS)
+ pm8xxx_upl_debug_remove(upldev);
+#endif
+
+ platform_set_drvdata(pdev, NULL);
+ kfree(upldev);
+ pr_notice("%s: OK\n", __func__);
+
+ return 0;
+}
+
+static struct platform_driver pm8xxx_upl_driver = {
+ .probe = pm8xxx_upl_probe,
+ .remove = __devexit_p(pm8xxx_upl_remove),
+ .driver = {
+ .name = PM8XXX_UPL_DEV_NAME,
+ .owner = THIS_MODULE,
+ },
+};
+
+static int __init pm8xxx_upl_init(void)
+{
+ return platform_driver_register(&pm8xxx_upl_driver);
+}
+
+static void __exit pm8xxx_upl_exit(void)
+{
+ platform_driver_unregister(&pm8xxx_upl_driver);
+}
+
+module_init(pm8xxx_upl_init);
+module_exit(pm8xxx_upl_exit);
+
+MODULE_LICENSE("GPL v2");
+MODULE_DESCRIPTION("PM8XXX UPL driver");
+MODULE_VERSION("1.0");
+MODULE_ALIAS("platform:" PM8XXX_UPL_DEV_NAME);
diff --git a/drivers/misc/pm8xxx-vibrator.c b/drivers/misc/pm8xxx-vibrator.c
index 8aa7f72..4f22efe 100644
--- a/drivers/misc/pm8xxx-vibrator.c
+++ b/drivers/misc/pm8xxx-vibrator.c
@@ -27,6 +27,7 @@
#define VIB_DRV_SEL_MASK 0xf8
#define VIB_DRV_SEL_SHIFT 0x03
#define VIB_DRV_EN_MANUAL_MASK 0xfc
+#define VIB_DRV_LOGIC_SHIFT 0x2
#define VIB_MAX_LEVEL_mV 3100
#define VIB_MIN_LEVEL_mV 1200
@@ -43,6 +44,40 @@
u8 reg_vib_drv;
};
+static struct pm8xxx_vib *vib_dev;
+
+int pm8xxx_vibrator_config(struct pm8xxx_vib_config *vib_config)
+{
+ u8 reg = 0;
+ int rc;
+
+ if (vib_dev == NULL) {
+ pr_err("%s: vib_dev is NULL\n", __func__);
+ return -EINVAL;
+ }
+
+ if (vib_config->drive_mV) {
+ if ((vib_config->drive_mV < VIB_MIN_LEVEL_mV) ||
+ (vib_config->drive_mV > VIB_MAX_LEVEL_mV)) {
+ pr_err("Invalid vibrator drive strength\n");
+ return -EINVAL;
+ }
+ }
+
+ reg = (vib_config->drive_mV / 100) << VIB_DRV_SEL_SHIFT;
+
+ reg |= (!!vib_config->active_low) << VIB_DRV_LOGIC_SHIFT;
+
+ reg |= vib_config->enable_mode;
+
+ rc = pm8xxx_writeb(vib_dev->dev->parent, VIB_DRV, reg);
+ if (rc)
+ pr_err("%s: pm8xxx write failed: rc=%d\n", __func__, rc);
+
+ return rc;
+}
+EXPORT_SYMBOL(pm8xxx_vibrator_config);
+
/* REVISIT: just for debugging, will be removed in final working version */
static void __dump_vib_regs(struct pm8xxx_vib *vib, char *msg)
{
@@ -240,6 +275,8 @@
platform_set_drvdata(pdev, vib);
+ vib_dev = vib;
+
return 0;
err_read_vib:
diff --git a/drivers/misc/pmic8058-nfc.c b/drivers/misc/pmic8058-nfc.c
deleted file mode 100644
index 76a19f4..0000000
--- a/drivers/misc/pmic8058-nfc.c
+++ /dev/null
@@ -1,322 +0,0 @@
-/* Copyright (c) 2010, Code Aurora Forum. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 and
- * only version 2 as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- */
-/*
- * Qualcomm PMIC8058 NFC driver
- *
- */
-
-#include <linux/module.h>
-#include <linux/platform_device.h>
-#include <linux/err.h>
-#include <linux/mfd/pmic8058.h>
-#include <linux/pmic8058-nfc.h>
-#include <linux/debugfs.h>
-#include <linux/slab.h>
-
-/* PMIC8058 NFC */
-#define SSBI_REG_NFC_CTRL 0x14D
-#define SSBI_REG_NFC_TEST 0x14E
-
-/* NFC_CTRL */
-#define PM8058_NFC_SUPPORT_EN 0x80
-#define PM8058_NFC_LDO_EN 0x40
-#define PM8058_NFC_EN 0x20
-#define PM8058_NFC_EXT_VDDLDO_EN 0x10
-#define PM8058_NFC_VPH_PWR_EN 0x08
-#define PM8058_NFC_RESERVED 0x04
-#define PM8058_NFC_VDDLDO_LEVEL 0x03
-
-/* NFC_TEST */
-#define PM8058_NFC_VDDLDO_MON_EN 0x80
-#define PM8058_NFC_ATEST_EN 0x40
-#define PM8058_NFC_DTEST1_EN 0x20
-#define PM8058_NFC_RESERVED2 0x18
-#define PM8058_NFC_VDDLDO_OK_S 0x04
-#define PM8058_NFC_MBG_EN_S 0x02
-#define PM8058_NFC_EXT_EN_S 0x01
-
-struct pm8058_nfc_device {
- struct mutex nfc_mutex;
- struct pm8058_chip *pm_chip;
-#if defined(CONFIG_DEBUG_FS)
- struct dentry *dent;
-#endif
-};
-static struct pm8058_nfc_device *nfc_dev;
-
-/* APIs */
-/*
- * pm8058_nfc_request - request a handle to access NFC device
- */
-struct pm8058_nfc_device *pm8058_nfc_request(void)
-{
- return nfc_dev;
-}
-EXPORT_SYMBOL(pm8058_nfc_request);
-
-/*
- * pm8058_nfc_config - configure NFC signals
- *
- * @nfcdev: the NFC device
- * @mask: signal mask to configure
- * @flags: control flags
- */
-int pm8058_nfc_config(struct pm8058_nfc_device *nfcdev, u32 mask, u32 flags)
-{
- u8 nfc_ctrl, nfc_test, m, f;
- int rc;
-
- if (nfcdev == NULL || IS_ERR(nfcdev) || !mask)
- return -EINVAL;
- if (nfcdev->pm_chip == NULL)
- return -ENODEV;
-
- mutex_lock(&nfcdev->nfc_mutex);
-
- if (!(mask & PM_NFC_CTRL_REQ))
- goto config_test;
-
- rc = pm8058_read(nfcdev->pm_chip, SSBI_REG_NFC_CTRL, &nfc_ctrl, 1);
- if (rc) {
- pr_err("%s: FAIL pm8058_read(): rc=%d (nfc_ctrl=0x%x)\n",
- __func__, rc, nfc_ctrl);
- goto config_done;
- }
-
- m = mask & 0x00ff;
- f = flags & 0x00ff;
- nfc_ctrl &= ~m;
- nfc_ctrl |= m & f;
-
- rc = pm8058_write(nfcdev->pm_chip, SSBI_REG_NFC_CTRL, &nfc_ctrl, 1);
- if (rc) {
- pr_err("%s: FAIL pm8058_write(): rc=%d (nfc_ctrl=0x%x)\n",
- __func__, rc, nfc_ctrl);
- goto config_done;
- }
-
-config_test:
- if (!(mask & PM_NFC_TEST_REQ))
- goto config_done;
-
- rc = pm8058_read(nfcdev->pm_chip, SSBI_REG_NFC_TEST, &nfc_test, 1);
- if (rc) {
- pr_err("%s: FAIL pm8058_read(): rc=%d (nfc_test=0x%x)\n",
- __func__, rc, nfc_test);
- goto config_done;
- }
-
- m = (mask >> 8) & 0x00ff;
- f = (flags >> 8) & 0x00ff;
- nfc_test &= ~m;
- nfc_test |= m & f;
-
- rc = pm8058_write(nfcdev->pm_chip, SSBI_REG_NFC_TEST, &nfc_test, 1);
- if (rc) {
- pr_err("%s: FAIL pm8058_write(): rc=%d (nfc_test=0x%x)\n",
- __func__, rc, nfc_test);
- goto config_done;
- }
-
-config_done:
- mutex_unlock(&nfcdev->nfc_mutex);
- return 0;
-}
-EXPORT_SYMBOL(pm8058_nfc_config);
-
-/*
- * pm8058_nfc_get_status - get NFC status
- *
- * @nfcdev: the NFC device
- * @mask: of status mask to read
- * @status: pointer to the status variable
- */
-int pm8058_nfc_get_status(struct pm8058_nfc_device *nfcdev,
- u32 mask, u32 *status)
-{
- u8 nfc_ctrl, nfc_test;
- u32 st;
- int rc;
-
- if (nfcdev == NULL || IS_ERR(nfcdev) || status == NULL)
- return -EINVAL;
- if (nfcdev->pm_chip == NULL)
- return -ENODEV;
-
- st = 0;
- mutex_lock(&nfcdev->nfc_mutex);
-
- if (!(mask & PM_NFC_CTRL_REQ))
- goto read_test;
-
- rc = pm8058_read(nfcdev->pm_chip, SSBI_REG_NFC_CTRL, &nfc_ctrl, 1);
- if (rc) {
- pr_err("%s: FAIL pm8058_read(): rc=%d (nfc_ctrl=0x%x)\n",
- __func__, rc, nfc_ctrl);
- goto get_status_done;
- }
-
-read_test:
- if (!(mask & (PM_NFC_TEST_REQ | PM_NFC_TEST_STATUS)))
- goto get_status_done;
-
- rc = pm8058_read(nfcdev->pm_chip, SSBI_REG_NFC_TEST, &nfc_test, 1);
- if (rc)
- pr_err("%s: FAIL pm8058_read(): rc=%d (nfc_test=0x%x)\n",
- __func__, rc, nfc_test);
-
-get_status_done:
- st = nfc_ctrl;
- st |= nfc_test << 8;
- *status = st;
-
- mutex_unlock(&nfcdev->nfc_mutex);
- return 0;
-}
-EXPORT_SYMBOL(pm8058_nfc_get_status);
-
-/*
- * pm8058_nfc_free - free the NFC device
- */
-void pm8058_nfc_free(struct pm8058_nfc_device *nfcdev)
-{
- /* Disable all signals */
- pm8058_nfc_config(nfcdev, PM_NFC_CTRL_REQ, 0);
-}
-EXPORT_SYMBOL(pm8058_nfc_free);
-
-#if defined(CONFIG_DEBUG_FS)
-static int pm8058_nfc_debug_set(void *data, u64 val)
-{
- struct pm8058_nfc_device *nfcdev;
- u32 mask, control;
- int rc;
-
- nfcdev = (struct pm8058_nfc_device *)data;
- control = (u32)val & 0xffff;
- mask = ((u32)val >> 16) & 0xffff;
- rc = pm8058_nfc_config(nfcdev, mask, control);
- if (rc)
- pr_err("%s: ERR pm8058_nfc_config: rc=%d, "
- "[mask, control]=[0x%x, 0x%x]\n",
- __func__, rc, mask, control);
-
- return 0;
-}
-
-static int pm8058_nfc_debug_get(void *data, u64 *val)
-{
- struct pm8058_nfc_device *nfcdev;
- u32 status;
- int rc;
-
- nfcdev = (struct pm8058_nfc_device *)data;
- rc = pm8058_nfc_get_status(nfcdev, (u32)-1, &status);
- if (rc)
- pr_err("%s: ERR pm8058_nfc_get_status: rc=%d, status=0x%x\n",
- __func__, rc, status);
-
- if (val)
- *val = (u64)status;
- return 0;
-}
-
-DEFINE_SIMPLE_ATTRIBUTE(pm8058_nfc_fops, pm8058_nfc_debug_get,
- pm8058_nfc_debug_set, "%llu\n");
-
-static int pm8058_nfc_debug_init(struct pm8058_nfc_device *nfcdev)
-{
- struct dentry *dent;
-
- dent = debugfs_create_file("pm8058-nfc", 0644, NULL,
- (void *)nfcdev, &pm8058_nfc_fops);
-
- if (dent == NULL || IS_ERR(dent))
- pr_err("%s: ERR debugfs_create_file: dent=0x%x\n",
- __func__, (unsigned)dent);
-
- nfcdev->dent = dent;
- return 0;
-}
-#endif
-
-static int __devinit pmic8058_nfc_probe(struct platform_device *pdev)
-{
- struct pm8058_chip *pm_chip;
- struct pm8058_nfc_device *nfcdev;
-
- pm_chip = dev_get_drvdata(pdev->dev.parent);
- if (pm_chip == NULL) {
- pr_err("%s: no parent data passed in.\n", __func__);
- return -EFAULT;
- }
-
- nfcdev = kzalloc(sizeof *nfcdev, GFP_KERNEL);
- if (nfcdev == NULL) {
- pr_err("%s: kzalloc() failed.\n", __func__);
- return -ENOMEM;
- }
-
- mutex_init(&nfcdev->nfc_mutex);
-
- nfcdev->pm_chip = pm_chip;
- nfc_dev = nfcdev;
- platform_set_drvdata(pdev, nfcdev);
-
-#if defined(CONFIG_DEBUG_FS)
- pm8058_nfc_debug_init(nfc_dev);
-#endif
-
- pr_notice("%s: OK\n", __func__);
- return 0;
-}
-
-static int __devexit pmic8058_nfc_remove(struct platform_device *pdev)
-{
- struct pm8058_nfc_device *nfcdev = platform_get_drvdata(pdev);
-
-#if defined(CONFIG_DEBUG_FS)
- debugfs_remove(nfcdev->dent);
-#endif
-
- platform_set_drvdata(pdev, nfcdev->pm_chip);
- kfree(nfcdev);
- return 0;
-}
-
-static struct platform_driver pmic8058_nfc_driver = {
- .probe = pmic8058_nfc_probe,
- .remove = __devexit_p(pmic8058_nfc_remove),
- .driver = {
- .name = "pm8058-nfc",
- .owner = THIS_MODULE,
- },
-};
-
-static int __init pm8058_nfc_init(void)
-{
- return platform_driver_register(&pmic8058_nfc_driver);
-}
-
-static void __exit pm8058_nfc_exit(void)
-{
- platform_driver_unregister(&pmic8058_nfc_driver);
-}
-
-module_init(pm8058_nfc_init);
-module_exit(pm8058_nfc_exit);
-
-MODULE_LICENSE("GPL v2");
-MODULE_DESCRIPTION("PMIC8058 NFC driver");
-MODULE_VERSION("1.0");
-MODULE_ALIAS("platform:pmic8058-nfc");
diff --git a/drivers/misc/pmic8058-pwm.c b/drivers/misc/pmic8058-pwm.c
index ad03b88..33407b7 100644
--- a/drivers/misc/pmic8058-pwm.c
+++ b/drivers/misc/pmic8058-pwm.c
@@ -19,11 +19,11 @@
#include <linux/module.h>
#include <linux/platform_device.h>
+#include <linux/slab.h>
#include <linux/err.h>
#include <linux/pwm.h>
-#include <linux/mfd/pmic8058.h>
+#include <linux/mfd/pm8xxx/core.h>
#include <linux/pmic8058-pwm.h>
-#include <linux/slab.h>
#define PM8058_LPG_BANKS 8
#define PM8058_PWM_CHANNELS PM8058_LPG_BANKS /* MAX=8 */
@@ -179,6 +179,7 @@
struct pm8058_pwm_chip;
struct pwm_device {
+ struct device *dev;
int pwm_id; /* = bank/channel id */
int in_use;
const char *label;
@@ -188,14 +189,13 @@
int use_lut; /* Use LUT to output PWM */
u8 pwm_ctl[PM8058_LPG_CTL_REGS];
int irq;
- struct pm8058_pwm_chip *chip;
+ struct pm8058_pwm_chip *chip;
};
struct pm8058_pwm_chip {
struct pwm_device pwm_dev[PM8058_PWM_CHANNELS];
u8 bank_mask;
struct mutex pwm_mutex;
- struct pm8058_chip *pm_chip;
struct pm8058_pwm_pdata *pdata;
};
@@ -244,9 +244,10 @@
else
reg = chip->bank_mask & ~(1 << pwm->pwm_id);
- rc = pm8058_write(chip->pm_chip, SSBI_REG_ADDR_LPG_BANK_EN, ®, 1);
+ rc = pm8xxx_writeb(pwm->dev->parent,
+ SSBI_REG_ADDR_LPG_BANK_EN, reg);
if (rc) {
- pr_err("pm8058_write(): rc=%d (Enable LPG Bank)\n", rc);
+ pr_err("pm8xxx_write(): rc=%d (Enable LPG Bank)\n", rc);
goto bail_out;
}
chip->bank_mask = reg;
@@ -261,10 +262,10 @@
u8 reg;
reg = pwm->pwm_id;
- rc = pm8058_write(pwm->chip->pm_chip, SSBI_REG_ADDR_LPG_BANK_SEL,
- ®, 1);
+ rc = pm8xxx_writeb(pwm->dev->parent,
+ SSBI_REG_ADDR_LPG_BANK_SEL, reg);
if (rc)
- pr_err("pm8058_write(): rc=%d (Select PWM Bank)\n", rc);
+ pr_err("pm8xxx_write(): rc=%d (Select PWM Bank)\n", rc);
return rc;
}
@@ -284,10 +285,10 @@
reg &= ~PM8058_PWM_RAMP_GEN_START;
}
- rc = pm8058_write(pwm->chip->pm_chip, SSBI_REG_ADDR_LPG_CTL(0),
- ®, 1);
+ rc = pm8xxx_writeb(pwm->dev->parent, SSBI_REG_ADDR_LPG_CTL(0),
+ reg);
if (rc)
- pr_err("pm8058_write(): rc=%d (Enable PWM Ctl 0)\n", rc);
+ pr_err("pm8xxx_write(): rc=%d (Enable PWM Ctl 0)\n", rc);
else
pwm->pwm_ctl[0] = reg;
return rc;
@@ -415,15 +416,13 @@
cfg1 = (pwm_value >> 1) & 0x80;
cfg1 |= start_idx + i;
- rc = pm8058_write(pwm->chip->pm_chip,
- SSBI_REG_ADDR_LPG_LUT_CFG0,
- &cfg0, 1);
+ rc = pm8xxx_writeb(pwm->dev->parent,
+ SSBI_REG_ADDR_LPG_LUT_CFG0, cfg0);
if (rc)
break;
- rc = pm8058_write(pwm->chip->pm_chip,
- SSBI_REG_ADDR_LPG_LUT_CFG1,
- &cfg1, 1);
+ rc = pm8xxx_writeb(pwm->dev->parent,
+ SSBI_REG_ADDR_LPG_LUT_CFG1, cfg1);
if (rc)
break;
}
@@ -539,11 +538,11 @@
/* Write in reverse way so 0 would be the last */
for (i = end - 1; i >= start; i--) {
- rc = pm8058_write(pwm->chip->pm_chip,
+ rc = pm8xxx_writeb(pwm->dev->parent,
SSBI_REG_ADDR_LPG_CTL(i),
- &pwm->pwm_ctl[i], 1);
+ pwm->pwm_ctl[i]);
if (rc) {
- pr_err("pm8058_write(): rc=%d (PWM Ctl[%d])\n", rc, i);
+ pr_err("pm8xxx_write(): rc=%d (PWM Ctl[%d])\n", rc, i);
return rc;
}
}
@@ -957,8 +956,8 @@
case PM_PWM_LED_2:
conf = mode & PM8058_LED_MODE_MASK;
conf |= (max_current / 2) << PM8058_LED_CURRENT_SHIFT;
- rc = pm8058_write(pwm->chip->pm_chip,
- SSBI_REG_ADDR_LED(id), &conf, 1);
+ rc = pm8xxx_writeb(pwm->dev->parent,
+ SSBI_REG_ADDR_LED(id), conf);
break;
case PM_PWM_LED_KPD:
@@ -982,8 +981,8 @@
}
conf |= (max_current / 20) << PM8058_FLASH_CURRENT_SHIFT;
id -= PM_PWM_LED_KPD;
- rc = pm8058_write(pwm->chip->pm_chip,
- SSBI_REG_ADDR_FLASH(id), &conf, 1);
+ rc = pm8xxx_writeb(pwm->dev->parent,
+ SSBI_REG_ADDR_FLASH(id), conf);
break;
default:
rc = -EINVAL;
@@ -1012,10 +1011,10 @@
/* Only Test 1 available */
reg |= (1 << PM8058_PWM_DTEST_SHIFT) &
PM8058_PWM_DTEST_MASK;
- rc = pm8058_write(pwm->chip->pm_chip, SSBI_REG_ADDR_LPG_TEST,
- ®, 1);
+ rc = pm8xxx_writeb(pwm->dev->parent,
+ SSBI_REG_ADDR_LPG_TEST, reg);
if (rc)
- pr_err("pm8058_write(DTEST=0x%x): rc=%d\n", reg, rc);
+ pr_err("pm8xxx_write(DTEST=0x%x): rc=%d\n", reg, rc);
}
return rc;
@@ -1024,16 +1023,9 @@
static int __devinit pmic8058_pwm_probe(struct platform_device *pdev)
{
- struct pm8058_chip *pm_chip;
struct pm8058_pwm_chip *chip;
int i;
- pm_chip = dev_get_drvdata(pdev->dev.parent);
- if (pm_chip == NULL) {
- pr_err("no parent data passed in.\n");
- return -EFAULT;
- }
-
chip = kzalloc(sizeof *chip, GFP_KERNEL);
if (chip == NULL) {
pr_err("kzalloc() failed.\n");
@@ -1043,12 +1035,12 @@
for (i = 0; i < PM8058_PWM_CHANNELS; i++) {
chip->pwm_dev[i].pwm_id = i;
chip->pwm_dev[i].chip = chip;
+ chip->pwm_dev[i].dev = &pdev->dev;
}
mutex_init(&chip->pwm_mutex);
chip->pdata = pdev->dev.platform_data;
- chip->pm_chip = pm_chip;
pwm_chip = chip;
platform_set_drvdata(pdev, chip);
diff --git a/drivers/misc/pmic8058-upl.c b/drivers/misc/pmic8058-upl.c
deleted file mode 100644
index ae0abd8..0000000
--- a/drivers/misc/pmic8058-upl.c
+++ /dev/null
@@ -1,363 +0,0 @@
-/* Copyright (c) 2010, Code Aurora Forum. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 and
- * only version 2 as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- */
-/*
- * Qualcomm PMIC8058 UPL driver
- *
- */
-
-#include <linux/module.h>
-#include <linux/platform_device.h>
-#include <linux/err.h>
-#include <linux/mfd/pmic8058.h>
-#include <linux/pmic8058-upl.h>
-#include <linux/debugfs.h>
-#include <linux/slab.h>
-
-/* PMIC8058 UPL registers */
-#define SSBI_REG_UPL_CTRL 0x17B
-#define SSBI_REG_UPL_TRUTHTABLE1 0x17C
-#define SSBI_REG_UPL_TRUTHTABLE2 0x17D
-
-struct pm8058_upl_device {
- struct mutex upl_mutex;
- struct pm8058_chip *pm_chip;
-#if defined(CONFIG_DEBUG_FS)
- struct dentry *dent;
-#endif
-};
-static struct pm8058_upl_device *upl_dev;
-
-/* APIs */
-
-/*
- * pm8058_upl_request - request a handle to access UPL device
- */
-struct pm8058_upl_device *pm8058_upl_request(void)
-{
- return upl_dev;
-}
-EXPORT_SYMBOL(pm8058_upl_request);
-
-/*
- * pm8058_upl_read_truthtable - read value currently stored in UPL truth table
- *
- * @upldev: the UPL device
- * @truthtable: value read from UPL truth table
- */
-int pm8058_upl_read_truthtable(struct pm8058_upl_device *upldev,
- u16 *truthtable)
-{
- int rc = 0;
- u8 table[2];
-
- if (upldev == NULL || IS_ERR(upldev))
- return -EINVAL;
- if (upldev->pm_chip == NULL)
- return -ENODEV;
-
- mutex_lock(&upldev->upl_mutex);
-
- rc = pm8058_read(upldev->pm_chip, SSBI_REG_UPL_TRUTHTABLE1,
- &(table[0]), 1);
- if (rc) {
- pr_err("%s: FAIL pm8058_read(0x%X)=0x%02X: rc=%d\n",
- __func__, SSBI_REG_UPL_TRUTHTABLE1, table[0], rc);
- goto upl_read_done;
- }
-
- rc = pm8058_read(upldev->pm_chip, SSBI_REG_UPL_TRUTHTABLE2,
- &(table[1]), 1);
- if (rc)
- pr_err("%s: FAIL pm8058_read(0x%X)=0x%02X: rc=%d\n",
- __func__, SSBI_REG_UPL_TRUTHTABLE2, table[1], rc);
-upl_read_done:
- mutex_unlock(&upldev->upl_mutex);
- *truthtable = (((u16)table[1]) << 8) | table[0];
- return rc;
-}
-EXPORT_SYMBOL(pm8058_upl_read_truthtable);
-
-/*
- * pm8058_upl_writes_truthtable - write value into UPL truth table
- *
- * @upldev: the UPL device
- * @truthtable: value written to UPL truth table
- *
- * Each bit in parameter "truthtable" corresponds to the UPL output for a given
- * set of input pin values. For example, if the input pins have the following
- * values: A=1, B=1, C=1, D=0, then the UPL would output the value of bit 14
- * (0b1110) in parameter "truthtable".
- */
-int pm8058_upl_write_truthtable(struct pm8058_upl_device *upldev,
- u16 truthtable)
-{
- int rc = 0;
- u8 table[2];
-
- if (upldev == NULL || IS_ERR(upldev))
- return -EINVAL;
- if (upldev->pm_chip == NULL)
- return -ENODEV;
-
- table[0] = truthtable & 0xFF;
- table[1] = (truthtable >> 8) & 0xFF;
-
- mutex_lock(&upldev->upl_mutex);
-
- rc = pm8058_write(upldev->pm_chip, SSBI_REG_UPL_TRUTHTABLE1,
- &(table[0]), 1);
- if (rc) {
- pr_err("%s: FAIL pm8058_write(0x%X)=0x%04X: rc=%d\n",
- __func__, SSBI_REG_UPL_TRUTHTABLE1, table[0], rc);
- goto upl_write_done;
- }
-
- rc = pm8058_write(upldev->pm_chip, SSBI_REG_UPL_TRUTHTABLE2,
- &(table[1]), 1);
- if (rc)
- pr_err("%s: FAIL pm8058_write(0x%X)=0x%04X: rc=%d\n",
- __func__, SSBI_REG_UPL_TRUTHTABLE2, table[1], rc);
-upl_write_done:
- mutex_unlock(&upldev->upl_mutex);
- return rc;
-}
-EXPORT_SYMBOL(pm8058_upl_write_truthtable);
-
-/*
- * pm8058_upl_config - configure UPL I/O settings and UPL enable/disable
- *
- * @upldev: the UPL device
- * @mask: setting mask to configure
- * @flags: setting flags
- */
-int pm8058_upl_config(struct pm8058_upl_device *upldev, u32 mask, u32 flags)
-{
- int rc;
- u8 upl_ctrl, m, f;
-
- if (upldev == NULL || IS_ERR(upldev))
- return -EINVAL;
- if (upldev->pm_chip == NULL)
- return -ENODEV;
-
- mutex_lock(&upldev->upl_mutex);
-
- rc = pm8058_read(upldev->pm_chip, SSBI_REG_UPL_CTRL, &upl_ctrl, 1);
- if (rc) {
- pr_err("%s: FAIL pm8058_read(0x%X)=0x%02X: rc=%d\n",
- __func__, SSBI_REG_UPL_CTRL, upl_ctrl, rc);
- goto upl_config_done;
- }
-
- m = mask & 0x00ff;
- f = flags & 0x00ff;
- upl_ctrl &= ~m;
- upl_ctrl |= m & f;
-
- rc = pm8058_write(upldev->pm_chip, SSBI_REG_UPL_CTRL, &upl_ctrl, 1);
- if (rc)
- pr_err("%s: FAIL pm8058_write(0x%X)=0x%02X: rc=%d\n",
- __func__, SSBI_REG_UPL_CTRL, upl_ctrl, rc);
-upl_config_done:
- mutex_unlock(&upldev->upl_mutex);
- return rc;
-}
-EXPORT_SYMBOL(pm8058_upl_config);
-
-#if defined(CONFIG_DEBUG_FS)
-
-static int truthtable_set(void *data, u64 val)
-{
- int rc;
-
- rc = pm8058_upl_write_truthtable(data, val);
- if (rc)
- pr_err("%s: pm8058_upl_write_truthtable: rc=%d, "
- "truthtable=0x%llX\n", __func__, rc, val);
- return rc;
-}
-
-static int truthtable_get(void *data, u64 *val)
-{
- int rc;
- u16 truthtable;
-
- rc = pm8058_upl_read_truthtable(data, &truthtable);
- if (rc)
- pr_err("%s: pm8058_upl_read_truthtable: rc=%d, "
- "truthtable=0x%X\n", __func__, rc, truthtable);
- if (val)
- *val = truthtable;
-
- return rc;
-}
-
-DEFINE_SIMPLE_ATTRIBUTE(upl_truthtable_fops, truthtable_get,
- truthtable_set, "0x%04llX\n");
-
-/* enter values as 0xMMMMFFFF where MMMM is the mask and FFFF is the flags */
-static int control_set(void *data, u64 val)
-{
- u8 mask, flags;
- int rc;
-
- flags = val & 0xFFFF;
- mask = (val >> 16) & 0xFFFF;
-
- rc = pm8058_upl_config(data, mask, flags);
- if (rc)
- pr_err("%s: pm8058_upl_config: rc=%d, mask = 0x%X, "
- "flags = 0x%X\n", __func__, rc, mask, flags);
- return rc;
-}
-
-static int control_get(void *data, u64 *val)
-{
- struct pm8058_upl_device *upldev;
- int rc = 0;
- u8 ctrl;
-
- upldev = data;
-
- mutex_lock(&upldev->upl_mutex);
-
- rc = pm8058_read(upldev->pm_chip, SSBI_REG_UPL_CTRL, &ctrl, 1);
- if (rc)
- pr_err("%s: FAIL pm8058_read(): rc=%d (ctrl=0x%02X)\n",
- __func__, rc, ctrl);
-
- mutex_unlock(&upldev->upl_mutex);
-
- *val = ctrl;
-
- return rc;
-}
-
-DEFINE_SIMPLE_ATTRIBUTE(upl_control_fops, control_get,
- control_set, "0x%02llX\n");
-
-static int pm8058_upl_debug_init(struct pm8058_upl_device *upldev)
-{
- struct dentry *dent;
- struct dentry *temp;
-
- dent = debugfs_create_dir("pm8058-upl", NULL);
- if (dent == NULL || IS_ERR(dent)) {
- pr_err("%s: ERR debugfs_create_dir: dent=0x%X\n",
- __func__, (unsigned)dent);
- return -ENOMEM;
- }
-
- temp = debugfs_create_file("truthtable", S_IRUSR | S_IWUSR, dent,
- upldev, &upl_truthtable_fops);
- if (temp == NULL || IS_ERR(temp)) {
- pr_err("%s: ERR debugfs_create_file: dent=0x%X\n",
- __func__, (unsigned)dent);
- goto debug_error;
- }
-
- temp = debugfs_create_file("control", S_IRUSR | S_IWUSR, dent,
- upldev, &upl_control_fops);
- if (temp == NULL || IS_ERR(temp)) {
- pr_err("%s: ERR debugfs_create_file: dent=0x%X\n",
- __func__, (unsigned)dent);
- goto debug_error;
- }
-
- upldev->dent = dent;
- return 0;
-
-debug_error:
- debugfs_remove_recursive(dent);
- return -ENOMEM;
-}
-
-static int __devexit pm8058_upl_debug_remove(struct pm8058_upl_device *upldev)
-{
- debugfs_remove_recursive(upldev->dent);
- return 0;
-}
-
-#endif /* CONFIG_DEBUG_FS */
-
-static int __devinit pmic8058_upl_probe(struct platform_device *pdev)
-{
- struct pm8058_chip *pm_chip;
- struct pm8058_upl_device *upldev;
-
- pm_chip = dev_get_drvdata(pdev->dev.parent);
- if (pm_chip == NULL) {
- pr_err("%s: no parent data passed in.\n", __func__);
- return -EFAULT;
- }
-
- upldev = kzalloc(sizeof *upldev, GFP_KERNEL);
- if (upldev == NULL) {
- pr_err("%s: kzalloc() failed.\n", __func__);
- return -ENOMEM;
- }
-
- mutex_init(&upldev->upl_mutex);
-
- upldev->pm_chip = pm_chip;
- upl_dev = upldev;
- platform_set_drvdata(pdev, upldev);
-
-#if defined(CONFIG_DEBUG_FS)
- pm8058_upl_debug_init(upl_dev);
-#endif
- pr_notice("%s: OK\n", __func__);
- return 0;
-}
-
-static int __devexit pmic8058_upl_remove(struct platform_device *pdev)
-{
- struct pm8058_upl_device *upldev = platform_get_drvdata(pdev);
-
-#if defined(CONFIG_DEBUG_FS)
- pm8058_upl_debug_remove(upldev);
-#endif
-
- platform_set_drvdata(pdev, upldev->pm_chip);
- kfree(upldev);
- pr_notice("%s: OK\n", __func__);
-
- return 0;
-}
-
-static struct platform_driver pmic8058_upl_driver = {
- .probe = pmic8058_upl_probe,
- .remove = __devexit_p(pmic8058_upl_remove),
- .driver = {
- .name = "pm8058-upl",
- .owner = THIS_MODULE,
- },
-};
-
-static int __init pm8058_upl_init(void)
-{
- return platform_driver_register(&pmic8058_upl_driver);
-}
-
-static void __exit pm8058_upl_exit(void)
-{
- platform_driver_unregister(&pmic8058_upl_driver);
-}
-
-module_init(pm8058_upl_init);
-module_exit(pm8058_upl_exit);
-
-MODULE_LICENSE("GPL v2");
-MODULE_DESCRIPTION("PMIC8058 UPL driver");
-MODULE_VERSION("1.0");
-MODULE_ALIAS("platform:pmic8058-upl");
diff --git a/drivers/misc/pmic8058-xoadc.c b/drivers/misc/pmic8058-xoadc.c
index b63800c..14b790f 100644
--- a/drivers/misc/pmic8058-xoadc.c
+++ b/drivers/misc/pmic8058-xoadc.c
@@ -17,7 +17,7 @@
#include <linux/platform_device.h>
#include <linux/err.h>
#include <linux/msm_adc.h>
-#include <linux/pmic8058-xoadc.h>
+#include <linux/mfd/pm8xxx/core.h>
#include <linux/mfd/pmic8058.h>
#include <linux/interrupt.h>
#include <linux/slab.h>
@@ -54,8 +54,8 @@
#define ADC_ARB_USRP_DATA1 0x19C
struct pmic8058_adc {
+ struct device *dev;
struct xoadc_platform_data *pdata;
- struct pm8058_chip *pm_chip;
struct adc_properties *adc_prop;
struct xoadc_conv_state conv[2];
int xoadc_queue_count;
@@ -144,8 +144,8 @@
/* Write twice to the CNTRL register for the arbiter settings
to take into effect */
for (i = 0; i < 2; i++) {
- rc = pm8058_write(adc_pmic->pm_chip, ADC_ARB_USRP_CNTRL,
- &data_arb_cntrl, 1);
+ rc = pm8xxx_writeb(adc_pmic->dev->parent, ADC_ARB_USRP_CNTRL,
+ data_arb_cntrl);
if (rc < 0) {
pr_debug("%s: PM8058 write failed\n", __func__);
return rc;
@@ -165,8 +165,8 @@
{
struct pmic8058_adc *adc_pmic = pmic_adc[adc_instance];
- u8 data_arb_cntrl, data_amux_chan, data_arb_rsv, data_ana_param;
- u8 data_dig_param, data_ana_param2;
+ u8 data_arb_cntrl = 0, data_amux_chan = 0, data_arb_rsv = 0;
+ u8 data_dig_param = 0, data_ana_param2 = 0, data_ana_param = 0;
int rc;
rc = pm8058_xoadc_arb_cntrl(1, adc_instance, slot->chan_path);
@@ -307,15 +307,15 @@
break;
}
- rc = pm8058_write(adc_pmic->pm_chip,
- ADC_ARB_USRP_AMUX_CNTRL, &data_amux_chan, 1);
+ rc = pm8xxx_writeb(adc_pmic->dev->parent,
+ ADC_ARB_USRP_AMUX_CNTRL, data_amux_chan);
if (rc < 0) {
pr_debug("%s: PM8058 write failed\n", __func__);
return rc;
}
- rc = pm8058_write(adc_pmic->pm_chip,
- ADC_ARB_USRP_RSV, &data_arb_rsv, 1);
+ rc = pm8xxx_writeb(adc_pmic->dev->parent,
+ ADC_ARB_USRP_RSV, data_arb_rsv);
if (rc < 0) {
pr_debug("%s: PM8058 write failed\n", __func__);
return rc;
@@ -341,22 +341,22 @@
break;
}
- rc = pm8058_write(adc_pmic->pm_chip,
- ADC_ARB_USRP_ANA_PARAM, &data_ana_param, 1);
+ rc = pm8xxx_writeb(adc_pmic->dev->parent,
+ ADC_ARB_USRP_ANA_PARAM, data_ana_param);
if (rc < 0) {
pr_debug("%s: PM8058 write failed\n", __func__);
return rc;
}
- rc = pm8058_write(adc_pmic->pm_chip,
- ADC_ARB_USRP_DIG_PARAM, &data_dig_param, 1);
+ rc = pm8xxx_writeb(adc_pmic->dev->parent,
+ ADC_ARB_USRP_DIG_PARAM, data_dig_param);
if (rc < 0) {
pr_debug("%s: PM8058 write failed\n", __func__);
return rc;
}
- rc = pm8058_write(adc_pmic->pm_chip,
- ADC_ARB_USRP_ANA_PARAM, &data_ana_param2, 1);
+ rc = pm8xxx_writeb(adc_pmic->dev->parent,
+ ADC_ARB_USRP_ANA_PARAM, data_ana_param2);
if (rc < 0) {
pr_debug("%s: PM8058 write failed\n", __func__);
return rc;
@@ -364,8 +364,8 @@
enable_irq(adc_pmic->adc_irq);
- rc = pm8058_write(adc_pmic->pm_chip,
- ADC_ARB_USRP_CNTRL, &data_arb_cntrl, 1);
+ rc = pm8xxx_writeb(adc_pmic->dev->parent,
+ ADC_ARB_USRP_CNTRL, data_arb_cntrl);
if (rc < 0) {
pr_debug("%s: PM8058 write failed\n", __func__);
return rc;
@@ -434,13 +434,15 @@
if (!xoadc_initialized)
return -ENODEV;
- rc = pm8058_read(adc_pmic->pm_chip, ADC_ARB_USRP_DATA0, &rslt_lsb, 1);
+ rc = pm8xxx_readb(adc_pmic->dev->parent, ADC_ARB_USRP_DATA0,
+ &rslt_lsb);
if (rc < 0) {
pr_debug("%s: PM8058 read failed\n", __func__);
return rc;
}
- rc = pm8058_read(adc_pmic->pm_chip, ADC_ARB_USRP_DATA1, &rslt_msb, 1);
+ rc = pm8xxx_readb(adc_pmic->dev->parent, ADC_ARB_USRP_DATA1,
+ &rslt_msb);
if (rc < 0) {
pr_debug("%s: PM8058 read failed\n", __func__);
return rc;
@@ -657,7 +659,7 @@
wake_lock_destroy(&adc_pmic->adc_wakelock);
msm_xo_put(adc_pmic->adc_voter);
- platform_set_drvdata(pdev, adc_pmic->pm_chip);
+ platform_set_drvdata(pdev, NULL);
device_init_wakeup(&pdev->dev, 0);
kfree(adc_pmic);
xoadc_initialized = false;
@@ -668,16 +670,9 @@
static int __devinit pm8058_xoadc_probe(struct platform_device *pdev)
{
struct xoadc_platform_data *pdata = pdev->dev.platform_data;
- struct pm8058_chip *pm_chip;
struct pmic8058_adc *adc_pmic;
int i, rc = 0;
- pm_chip = dev_get_drvdata(pdev->dev.parent);
- if (pm_chip == NULL) {
- dev_err(&pdev->dev, "no parent data passed in\n");
- return -EFAULT;
- }
-
if (!pdata) {
dev_err(&pdev->dev, "no platform data?\n");
return -EINVAL;
@@ -689,7 +684,7 @@
return -ENOMEM;
}
- adc_pmic->pm_chip = pm_chip;
+ adc_pmic->dev = &pdev->dev;
adc_pmic->adc_prop = pdata->xoadc_prop;
adc_pmic->xoadc_num = pdata->xoadc_num;
adc_pmic->xoadc_queue_count = 0;
diff --git a/drivers/mmc/host/msm_sdcc.c b/drivers/mmc/host/msm_sdcc.c
index e639815..1ce089d 100644
--- a/drivers/mmc/host/msm_sdcc.c
+++ b/drivers/mmc/host/msm_sdcc.c
@@ -244,7 +244,7 @@
static void msmsdcc_reset_and_restore(struct msmsdcc_host *host)
{
- if (host->plat->sdcc_v4_sup) {
+ if (host->sdcc_version) {
if (host->is_sps_mode) {
/* Reset DML first */
msmsdcc_dml_reset(host);
@@ -345,7 +345,7 @@
mb();
udelay(host->reg_write_delay);
- if (host->plat->sdcc_v4_sup &&
+ if (host->sdcc_version &&
(readl_relaxed(host->base + MCI_STATUS2) &
MCI_MCLK_REG_WR_ACTIVE)) {
start = ktime_get();
@@ -1631,7 +1631,7 @@
if (mrq->data && (mrq->data->flags & MMC_DATA_WRITE)) {
if (mrq->cmd->opcode == SD_IO_RW_EXTENDED ||
mrq->cmd->opcode == 54) {
- if (!host->plat->sdcc_v4_sup)
+ if (!host->sdcc_version)
host->dummy_52_needed = 1;
else
/*
@@ -1716,7 +1716,12 @@
rc = PTR_ERR(vreg->reg);
pr_err("%s: regulator_get(%s) failed. rc=%d\n",
__func__, vreg->name, rc);
+ goto out;
}
+
+ if (regulator_count_voltages(vreg->reg) > 0)
+ vreg->set_voltage_sup = 1;
+
out:
return rc;
}
@@ -3696,6 +3701,14 @@
host->clk_rate = clk_get_rate(host->clk);
if (!host->clk_rate)
dev_err(&pdev->dev, "Failed to read MCLK\n");
+
+ /*
+ * Lookup the Controller Version, to identify the supported features
+ * Version number read as 0 would indicate SDCC3 or earlier versions
+ */
+ host->sdcc_version = readl_relaxed(host->base + MCI_VERSION);
+ pr_info("%s: mci-version: %x\n", mmc_hostname(host->mmc),
+ host->sdcc_version);
/*
* Set the register write delay according to min. clock frequency
* supported and update later when the host->clk_rate changes.
@@ -3747,7 +3760,7 @@
* status is to use the AUTO_PROG_DONE status provided by SDCC4
* controller. So let's enable the CMD23 for SDCC4 only.
*/
- if (!plat->disable_cmd23 && host->plat->sdcc_v4_sup)
+ if (!plat->disable_cmd23 && host->sdcc_version)
mmc->caps |= MMC_CAP_CMD23;
mmc->caps |= plat->uhs_caps;
diff --git a/drivers/mmc/host/msm_sdcc.h b/drivers/mmc/host/msm_sdcc.h
index 12aa54b..2019913 100644
--- a/drivers/mmc/host/msm_sdcc.h
+++ b/drivers/mmc/host/msm_sdcc.h
@@ -168,6 +168,7 @@
#define MMCIMASK1 0x040
#define MMCIFIFOCNT 0x044
+#define MCI_VERSION 0x050
#define MCICCSTIMER 0x058
#define MCI_DLL_CONFIG 0x060
#define MCI_DLL_EN (1 << 16)
@@ -316,6 +317,7 @@
u32 pwr;
struct mmc_platform_data *plat;
+ u32 sdcc_version;
unsigned int oldstat;
diff --git a/drivers/net/msm_rmnet_bam.c b/drivers/net/msm_rmnet_bam.c
index e617aa5..3b3758e 100644
--- a/drivers/net/msm_rmnet_bam.c
+++ b/drivers/net/msm_rmnet_bam.c
@@ -374,8 +374,11 @@
if (!p->device_up) {
r = msm_bam_dmux_open(p->ch_id, dev, bam_notify);
- if (r < 0)
+ if (r < 0) {
+ DBG0("%s: ch=%d failed with rc %d\n",
+ __func__, p->ch_id, r);
return -ENODEV;
+ }
}
p->device_up = DEVICE_ACTIVE;
@@ -688,8 +691,10 @@
dev = alloc_netdev(sizeof(struct rmnet_private),
"rmnet%d", rmnet_setup);
- if (!dev)
+ if (!dev) {
+ pr_err("%s: no memory for netdev %d\n", __func__, n);
return -ENOMEM;
+ }
netdevs[n] = dev;
d = &(dev->dev);
@@ -707,6 +712,8 @@
ret = register_netdev(dev);
if (ret) {
+ pr_err("%s: unable to register netdev"
+ " %d rc=%d\n", __func__, n, ret);
free_netdev(dev);
return ret;
}
diff --git a/drivers/platform/msm/sps/sps.c b/drivers/platform/msm/sps/sps.c
index cb453e0..e43166e 100644
--- a/drivers/platform/msm/sps/sps.c
+++ b/drivers/platform/msm/sps/sps.c
@@ -425,6 +425,85 @@
}
/**
+ * Find the handle of a BAM device based on the physical address
+ *
+ * This function finds a BAM device in the BAM registration list that
+ * matches the specified physical address, and returns its handle.
+ *
+ * @phys_addr - physical address of the BAM
+ *
+ * @h - device handle of the BAM
+ *
+ * @return 0 on success, negative value on error
+ *
+ */
+int sps_phy2h(u32 phys_addr, u32 *handle)
+{
+ struct sps_bam *bam;
+
+ list_for_each_entry(bam, &sps->bams_q, list) {
+ if (bam->props.phys_addr == phys_addr) {
+ *handle = (u32) bam;
+ return 0;
+ }
+ }
+
+ SPS_INFO("sps: BAM device 0x%x is not registered yet.\n", phys_addr);
+
+ return -ENODEV;
+}
+EXPORT_SYMBOL(sps_phy2h);
+
+/**
+ * Setup desc/data FIFO for bam-to-bam connection
+ *
+ * @mem_buffer - Pointer to struct for allocated memory properties.
+ *
+ * @addr - address of FIFO
+ *
+ * @size - FIFO size
+ *
+ * @use_offset - use address offset instead of absolute address
+ *
+ * @return 0 on success, negative value on error
+ *
+ */
+int sps_setup_bam2bam_fifo(struct sps_mem_buffer *mem_buffer,
+ u32 addr, u32 size, int use_offset)
+{
+ if ((mem_buffer == NULL) || (size == 0))
+ return SPS_ERROR;
+
+ if (use_offset) {
+ if ((addr + size) <= sps->pipemem_size)
+ mem_buffer->phys_base = sps->pipemem_phys_base + addr;
+ else {
+ SPS_ERR("sps: requested mem is out of "
+ "pipe mem range.\n");
+ return SPS_ERROR;
+ }
+ } else {
+ if (addr >= sps->pipemem_phys_base &&
+ (addr + size) <= (sps->pipemem_phys_base
+ + sps->pipemem_size))
+ mem_buffer->phys_base = addr;
+ else {
+ SPS_ERR("sps: requested mem is out of "
+ "pipe mem range.\n");
+ return SPS_ERROR;
+ }
+ }
+
+ mem_buffer->base = spsi_get_mem_ptr(mem_buffer->phys_base);
+ mem_buffer->size = size;
+
+ memset(mem_buffer->base, 0, mem_buffer->size);
+
+ return 0;
+}
+EXPORT_SYMBOL(sps_setup_bam2bam_fifo);
+
+/**
* Find the BAM device from the handle
*
* This function finds a BAM device in the BAM registration list that
diff --git a/drivers/power/Kconfig b/drivers/power/Kconfig
index cca1035..3590e6d 100644
--- a/drivers/power/Kconfig
+++ b/drivers/power/Kconfig
@@ -244,7 +244,7 @@
config BATTERY_MSM8X60
tristate "MSM8X60 battery"
- select PMIC8058_BATTALARM
+ select PMIC8XXX_BATTALARM
help
Some MSM boards have dual charging paths to charge the battery.
Say Y to enable support for the battery charging in
diff --git a/drivers/power/pm8921-bms.c b/drivers/power/pm8921-bms.c
index 2d0f7cd..d7cf3a8 100644
--- a/drivers/power/pm8921-bms.c
+++ b/drivers/power/pm8921-bms.c
@@ -89,6 +89,12 @@
DECLARE_BITMAP(enabled_irqs, PM_BMS_MAX_INTS);
spinlock_t bms_output_lock;
struct single_row_lut *adjusted_fcc_temp_lut;
+ unsigned int charging_began;
+ unsigned int start_percent;
+ unsigned int end_percent;
+
+ uint16_t ocv_reading_at_100;
+ int cc_reading_at_100;
};
static struct pm8921_bms_chip *the_chip;
@@ -484,6 +490,9 @@
}
*result = msw << 16 | lsw;
pr_debug("msw = %04x lsw = %04x cc = %d\n", msw, lsw, *result);
+ *result = *result - chip->cc_reading_at_100;
+ pr_debug("cc = %d after subtracting %d\n",
+ *result, chip->cc_reading_at_100);
return 0;
}
@@ -497,12 +506,29 @@
pr_err("fail to read LAST_GOOD_OCV_VALUE rc = %d\n", rc);
return rc;
}
- *result = xoadc_reading_to_microvolt(reading);
- pr_debug("raw = %04x ocv_uV = %u\n", reading, *result);
- *result = adjust_xo_vbatt_reading(chip, *result);
- pr_debug("after adj ocv_uV = %u\n", *result);
- if (*result != 0)
- last_ocv_uv = *result;
+
+ if (chip->ocv_reading_at_100 != reading) {
+ chip->ocv_reading_at_100 = 0;
+ chip->cc_reading_at_100 = 0;
+ *result = xoadc_reading_to_microvolt(reading);
+ pr_debug("raw = %04x ocv_uV = %u\n", reading, *result);
+ *result = adjust_xo_vbatt_reading(chip, *result);
+ pr_debug("after adj ocv_uV = %u\n", *result);
+ if (*result != 0)
+ last_ocv_uv = *result;
+ } else {
+ /*
+ * force 100% ocv by selecting the highest profiled ocv
+ * This is the first row last column entry in the ocv
+ * lookup table
+ */
+ int cols = chip->pc_temp_ocv_lut->cols;
+
+ pr_debug("Forcing max voltage %d\n",
+ 1000 * chip->pc_temp_ocv_lut->ocv[0][cols-1]);
+ *result = 1000 * chip->pc_temp_ocv_lut->ocv[0][cols-1];
+ }
+
return 0;
}
@@ -628,18 +654,33 @@
static int interpolate_scalingfactor_fcc(struct pm8921_bms_chip *chip,
int cycles)
{
- return interpolate_single_lut(chip->fcc_sf_lut, cycles);
+ /*
+ * sf table could be null when no battery aging data is available, in
+ * that case return 100%
+ */
+ if (chip->fcc_sf_lut)
+ return interpolate_single_lut(chip->fcc_sf_lut, cycles);
+ else
+ return 100;
}
static int interpolate_scalingfactor_pc(struct pm8921_bms_chip *chip,
int cycles, int pc)
{
int i, scalefactorrow1, scalefactorrow2, scalefactor;
+ int rows, cols;
int row1 = 0;
int row2 = 0;
- int rows = chip->pc_sf_lut->rows;
- int cols = chip->pc_sf_lut->cols;
+ /*
+ * sf table could be null when no battery aging data is available, in
+ * that case return 100%
+ */
+ if (!chip->pc_sf_lut)
+ return 100;
+
+ rows = chip->pc_sf_lut->rows;
+ cols = chip->pc_sf_lut->cols;
if (pc > chip->pc_sf_lut->percent[0]) {
pr_debug("pc %d greater than known pc ranges for sfd\n", pc);
row1 = 0;
@@ -1016,10 +1057,10 @@
/* calculate cc milli_volt_hour */
calculate_cc_mah(chip, cc_mah, &coulumb_counter);
+ pr_debug("cc_mah = %lldmAh cc = %d\n", *cc_mah, coulumb_counter);
pm_bms_unlock_output_data(chip);
spin_unlock_irqrestore(&chip->bms_output_lock, flags);
- pr_debug("cc_mah = %lldmAh cc = %d\n", *cc_mah, coulumb_counter);
}
static int calculate_real_fcc(struct pm8921_bms_chip *chip,
@@ -1037,7 +1078,8 @@
&cc_mah);
real_fcc = remaining_charge - cc_mah;
-
+ pr_debug("real_fcc = %d, RC = %d CC = %lld\n",
+ real_fcc, remaining_charge, cc_mah);
return real_fcc;
}
/*
@@ -1102,9 +1144,23 @@
update_userspace = 0;
}
- if (update_userspace) {
- last_soc = soc;
+ if (last_soc == -EINVAL || soc <= last_soc) {
+ last_soc = update_userspace ? soc : last_soc;
+ return soc;
}
+
+ /*
+ * soc > last_soc
+ * the device must be charging for reporting a higher soc, if not ignore
+ * this soc and continue reporting the last_soc
+ */
+ if (the_chip->start_percent != 0) {
+ last_soc = soc;
+ } else {
+ pr_debug("soc = %d reporting last_soc = %d\n", soc, last_soc);
+ soc = last_soc;
+ }
+
return soc;
}
@@ -1645,19 +1701,18 @@
}
EXPORT_SYMBOL_GPL(pm8921_bms_get_fcc);
-static int start_percent;
-static int end_percent;
void pm8921_bms_charging_began(void)
{
- start_percent = pm8921_bms_get_percent_charge();
- pr_debug("start_percent = %u%%\n", start_percent);
+ the_chip->start_percent = pm8921_bms_get_percent_charge();
+ pr_debug("start_percent = %u%%\n", the_chip->start_percent);
}
EXPORT_SYMBOL_GPL(pm8921_bms_charging_began);
void pm8921_bms_charging_end(int is_battery_full)
{
if (is_battery_full && the_chip != NULL) {
- int batt_temp, rc;
+ unsigned long flags;
+ int batt_temp, rc, cc_reading;
struct pm8921_adc_chan_result result;
rc = pm8921_adc_read(the_chip->batt_temp_channel, &result);
@@ -1673,12 +1728,25 @@
batt_temp, last_chargecycles);
last_real_fcc_batt_temp = batt_temp;
readjust_fcc_table();
+
+ spin_lock_irqsave(&the_chip->bms_output_lock, flags);
+ pm_bms_lock_output_data(the_chip);
+ pm_bms_read_output_data(the_chip, LAST_GOOD_OCV_VALUE,
+ &the_chip->ocv_reading_at_100);
+ read_cc(the_chip, &cc_reading);
+ pm_bms_unlock_output_data(the_chip);
+ spin_unlock_irqrestore(&the_chip->bms_output_lock, flags);
+ the_chip->cc_reading_at_100 = cc_reading;
+ pr_debug("EOC ocv_reading = 0x%x cc_reading = %d\n",
+ the_chip->ocv_reading_at_100,
+ the_chip->cc_reading_at_100);
}
charge_cycle_calculation:
- end_percent = pm8921_bms_get_percent_charge();
- if (end_percent > start_percent) {
- last_charge_increase = end_percent - start_percent;
+ the_chip->end_percent = pm8921_bms_get_percent_charge();
+ if (the_chip->end_percent > the_chip->start_percent) {
+ last_charge_increase =
+ the_chip->end_percent - the_chip->start_percent;
if (last_charge_increase > 100) {
last_chargecycles++;
last_charge_increase = last_charge_increase % 100;
@@ -1686,9 +1754,11 @@
}
pr_debug("end_percent = %u%% last_charge_increase = %d"
"last_chargecycles = %d\n",
- end_percent,
+ the_chip->end_percent,
last_charge_increase,
last_chargecycles);
+ the_chip->start_percent = 0;
+ the_chip->end_percent = 0;
}
EXPORT_SYMBOL_GPL(pm8921_bms_charging_end);
diff --git a/drivers/power/pm8921-charger.c b/drivers/power/pm8921-charger.c
index dde6194..cccb317 100644
--- a/drivers/power/pm8921-charger.c
+++ b/drivers/power/pm8921-charger.c
@@ -556,7 +556,7 @@
return pm_chg_masked_write(chip, CHG_TWDOG, PM8921_CHG_WD_MASK, 0);
}
-#define PM8921_CHG_TCHG_MASK 0x3F
+#define PM8921_CHG_TCHG_MASK 0x7F
#define PM8921_CHG_TCHG_MIN 4
#define PM8921_CHG_TCHG_MAX 512
#define PM8921_CHG_TCHG_STEP 4
diff --git a/drivers/power/pmic8058-charger.c b/drivers/power/pmic8058-charger.c
index a3ce54d..70b5d59 100644
--- a/drivers/power/pmic8058-charger.c
+++ b/drivers/power/pmic8058-charger.c
@@ -15,7 +15,6 @@
#include <linux/moduleparam.h>
#include <linux/platform_device.h>
#include <linux/errno.h>
-#include <linux/mfd/pmic8058.h>
#include <linux/interrupt.h>
#include <linux/delay.h>
#include <linux/bitops.h>
@@ -25,8 +24,10 @@
#include <linux/slab.h>
#include <linux/msm_adc.h>
#include <linux/notifier.h>
-#include <linux/pmic8058-batt-alarm.h>
+#include <linux/mfd/pm8xxx/core.h>
+#include <linux/mfd/pmic8058.h>
#include <linux/pmic8058-charger.h>
+#include <linux/mfd/pm8xxx/batt-alarm.h>
#include <mach/msm_xo.h>
#include <mach/msm_hsusb.h>
@@ -177,7 +178,6 @@
struct pm8058_charger {
struct pmic_charger_pdata *pdata;
- struct pm8058_chip *pm_chip;
struct device *dev;
int pmic_chg_irq[PMIC_CHG_MAX_INTS];
@@ -228,7 +228,11 @@
if (rc)
goto out;
- rc = pm8058_batt_alarm_threshold_set(resume_mv, 4300);
+ rc = pm8xxx_batt_alarm_threshold_set(
+ PM8XXX_BATT_ALARM_LOWER_COMPARATOR, resume_mv);
+ if (!rc)
+ rc = pm8xxx_batt_alarm_threshold_set(
+ PM8XXX_BATT_ALARM_UPPER_COMPARATOR, 4300);
out:
mutex_unlock(&batt_alarm_lock);
@@ -255,15 +259,9 @@
static int pm_chg_get_rt_status(int irq)
{
- int count = 3;
int ret;
- while ((ret =
- pm8058_irq_get_rt_status(pm8058_chg.pm_chip, irq)) == -EAGAIN
- && count--) {
- dev_info(pm8058_chg.dev, "%s trycount=%d\n", __func__, count);
- cpu_relax();
- }
+ ret = pm8xxx_read_irq_stat(pm8058_chg.dev->parent, irq);
if (ret == -EAGAIN)
return 0;
else
@@ -281,53 +279,53 @@
u8 temp;
int temp2;
- pm8058_read(pm8058_chg.pm_chip, PM8058_CHG_CNTRL, &temp, 1);
+ pm8xxx_readb(pm8058_chg.dev->parent, PM8058_CHG_CNTRL, &temp);
dev_dbg(pm8058_chg.dev, "PM8058_CHG_CNTRL = 0x%x\n", temp);
- pm8058_read(pm8058_chg.pm_chip, PM8058_CHG_CNTRL_2, &temp, 1);
+ pm8xxx_readb(pm8058_chg.dev->parent, PM8058_CHG_CNTRL_2, &temp);
dev_dbg(pm8058_chg.dev, "PM8058_CHG_CNTRL_2 = 0x%x\n", temp);
- pm8058_read(pm8058_chg.pm_chip, PM8058_CHG_VMAX_SEL, &temp, 1);
+ pm8xxx_readb(pm8058_chg.dev->parent, PM8058_CHG_VMAX_SEL, &temp);
dev_dbg(pm8058_chg.dev, "PM8058_CHG_VMAX_SEL = 0x%x\n", temp);
- pm8058_read(pm8058_chg.pm_chip, PM8058_CHG_VBAT_DET, &temp, 1);
+ pm8xxx_readb(pm8058_chg.dev->parent, PM8058_CHG_VBAT_DET, &temp);
dev_dbg(pm8058_chg.dev, "PM8058_CHG_VBAT_DET = 0x%x\n", temp);
- pm8058_read(pm8058_chg.pm_chip, PM8058_CHG_IMAX, &temp, 1);
+ pm8xxx_readb(pm8058_chg.dev->parent, PM8058_CHG_IMAX, &temp);
dev_dbg(pm8058_chg.dev, "PM8058_CHG_IMAX = 0x%x\n", temp);
- pm8058_read(pm8058_chg.pm_chip, PM8058_CHG_TRICKLE, &temp, 1);
+ pm8xxx_readb(pm8058_chg.dev->parent, PM8058_CHG_TRICKLE, &temp);
dev_dbg(pm8058_chg.dev, "PM8058_CHG_TRICKLE = 0x%x\n", temp);
- pm8058_read(pm8058_chg.pm_chip, PM8058_CHG_ITERM, &temp, 1);
+ pm8xxx_readb(pm8058_chg.dev->parent, PM8058_CHG_ITERM, &temp);
dev_dbg(pm8058_chg.dev, "PM8058_CHG_ITERM = 0x%x\n", temp);
- pm8058_read(pm8058_chg.pm_chip, PM8058_CHG_TTRKL_MAX, &temp, 1);
+ pm8xxx_readb(pm8058_chg.dev->parent, PM8058_CHG_TTRKL_MAX, &temp);
dev_dbg(pm8058_chg.dev, "PM8058_CHG_TTRKL_MAX = 0x%x\n", temp);
- pm8058_read(pm8058_chg.pm_chip, PM8058_CHG_TCHG_MAX, &temp, 1);
+ pm8xxx_readb(pm8058_chg.dev->parent, PM8058_CHG_TCHG_MAX, &temp);
dev_dbg(pm8058_chg.dev, "PM8058_CHG_TCHG_MAX = 0x%x\n", temp);
- pm8058_read(pm8058_chg.pm_chip, PM8058_CHG_TEMP_THRESH, &temp, 1);
+ pm8xxx_readb(pm8058_chg.dev->parent, PM8058_CHG_TEMP_THRESH, &temp);
dev_dbg(pm8058_chg.dev, "PM8058_CHG_TEMP_THRESH = 0x%x\n", temp);
- pm8058_read(pm8058_chg.pm_chip, PM8058_CHG_TEMP_REG, &temp, 1);
+ pm8xxx_readb(pm8058_chg.dev->parent, PM8058_CHG_TEMP_REG, &temp);
dev_dbg(pm8058_chg.dev, "PM8058_CHG_TEMP_REG = 0x%x\n", temp);
- pm8058_read(pm8058_chg.pm_chip, PM8058_CHG_PULSE, &temp, 1);
+ pm8xxx_readb(pm8058_chg.dev->parent, PM8058_CHG_PULSE, &temp);
dev_dbg(pm8058_chg.dev, "PM8058_CHG_PULSE = 0x%x\n", temp);
- pm8058_read(pm8058_chg.pm_chip, PM8058_CHG_STATUS_CLEAR_IRQ_1,
- &temp, 1);
+ pm8xxx_readb(pm8058_chg.dev->parent, PM8058_CHG_STATUS_CLEAR_IRQ_1,
+ &temp);
dev_dbg(pm8058_chg.dev, "PM8058_CHG_STATUS_CLEAR_IRQ_1 = 0x%x\n", temp);
- pm8058_read(pm8058_chg.pm_chip, PM8058_CHG_STATUS_CLEAR_IRQ_3,
- &temp, 1);
+ pm8xxx_readb(pm8058_chg.dev->parent, PM8058_CHG_STATUS_CLEAR_IRQ_3,
+ &temp);
dev_dbg(pm8058_chg.dev, "PM8058_CHG_STATUS_CLEAR_IRQ_3 = 0x%x\n", temp);
- pm8058_read(pm8058_chg.pm_chip, PM8058_CHG_STATUS_CLEAR_IRQ_10,
- &temp, 1);
+ pm8xxx_readb(pm8058_chg.dev->parent, PM8058_CHG_STATUS_CLEAR_IRQ_10,
+ &temp);
dev_dbg(pm8058_chg.dev, "PM8058_CHG_STATUS_CLEAR_IRQ_10 = 0x%x\n",
temp);
- pm8058_read(pm8058_chg.pm_chip, PM8058_CHG_STATUS_CLEAR_IRQ_11,
- &temp, 1);
+ pm8xxx_readb(pm8058_chg.dev->parent, PM8058_CHG_STATUS_CLEAR_IRQ_11,
+ &temp);
dev_dbg(pm8058_chg.dev, "PM8058_CHG_STATUS_CLEAR_IRQ_11 = 0x%x\n",
temp);
- pm8058_read(pm8058_chg.pm_chip, PM8058_CHG_MASK_IRQ_1, &temp, 1);
+ pm8xxx_readb(pm8058_chg.dev->parent, PM8058_CHG_MASK_IRQ_1, &temp);
dev_dbg(pm8058_chg.dev, "PM8058_CHG_MASK_IRQ_1 = 0x%x\n", temp);
- pm8058_read(pm8058_chg.pm_chip, PM8058_CHG_MASK_IRQ_3, &temp, 1);
+ pm8xxx_readb(pm8058_chg.dev->parent, PM8058_CHG_MASK_IRQ_3, &temp);
dev_dbg(pm8058_chg.dev, "PM8058_CHG_MASK_IRQ_3 = 0x%x\n", temp);
- pm8058_read(pm8058_chg.pm_chip, PM8058_CHG_MASK_IRQ_10, &temp, 1);
+ pm8xxx_readb(pm8058_chg.dev->parent, PM8058_CHG_MASK_IRQ_10, &temp);
dev_dbg(pm8058_chg.dev, "PM8058_CHG_MASK_IRQ_10 = 0x%x\n", temp);
- pm8058_read(pm8058_chg.pm_chip, PM8058_CHG_MASK_IRQ_11, &temp, 1);
+ pm8xxx_readb(pm8058_chg.dev->parent, PM8058_CHG_MASK_IRQ_11, &temp);
dev_dbg(pm8058_chg.dev, "PM8058_CHG_MASK_IRQ_11 = 0x%x\n", temp);
temp2 = pm_chg_get_rt_status(pm8058_chg.pmic_chg_irq[CHGVAL_IRQ]);
@@ -405,7 +403,7 @@
u8 temp;
int ret;
- ret = pm8058_read(pm8058_chg.pm_chip, PM8058_CHG_CNTRL, &temp, 1);
+ ret = pm8xxx_readb(pm8058_chg.dev->parent, PM8058_CHG_CNTRL, &temp);
if (ret)
return ret;
if (value)
@@ -413,7 +411,7 @@
else
temp &= ~BIT(CHG_USB_SUSPEND);
- return pm8058_write(pm8058_chg.pm_chip, PM8058_CHG_CNTRL, &temp, 1);
+ return pm8xxx_writeb(pm8058_chg.dev->parent, PM8058_CHG_CNTRL, temp);
}
static int pm_chg_auto_disable(int value)
@@ -421,7 +419,7 @@
u8 temp;
int ret;
- ret = pm8058_read(pm8058_chg.pm_chip, PM8058_CHG_CNTRL_2, &temp, 1);
+ ret = pm8xxx_readb(pm8058_chg.dev->parent, PM8058_CHG_CNTRL_2, &temp);
if (ret)
return ret;
if (value)
@@ -429,7 +427,7 @@
else
temp &= ~BIT(CHARGE_AUTO_DIS);
- return pm8058_write(pm8058_chg.pm_chip, PM8058_CHG_CNTRL_2, &temp, 1);
+ return pm8xxx_writeb(pm8058_chg.dev->parent, PM8058_CHG_CNTRL_2, temp);
}
static int pm_chg_batt_temp_disable(int value)
@@ -437,7 +435,7 @@
u8 temp;
int ret;
- ret = pm8058_read(pm8058_chg.pm_chip, PM8058_CHG_CNTRL_2, &temp, 1);
+ ret = pm8xxx_readb(pm8058_chg.dev->parent, PM8058_CHG_CNTRL_2, &temp);
if (ret)
return ret;
if (value)
@@ -445,7 +443,7 @@
else
temp &= ~BIT(CHG_BATT_TEMP_DIS);
- return pm8058_write(pm8058_chg.pm_chip, PM8058_CHG_CNTRL_2, &temp, 1);
+ return pm8xxx_writeb(pm8058_chg.dev->parent, PM8058_CHG_CNTRL_2, temp);
}
static int pm_chg_vbatdet_set(int voltage)
@@ -463,7 +461,7 @@
temp = diff / PM8058_CHG_V_STEP_MV;
dev_dbg(pm8058_chg.dev, "%s voltage=%d setting %02x\n", __func__,
voltage, temp);
- return pm8058_write(pm8058_chg.pm_chip, PM8058_CHG_VBAT_DET, &temp, 1);
+ return pm8xxx_writeb(pm8058_chg.dev->parent, PM8058_CHG_VBAT_DET, temp);
}
static int pm_chg_imaxsel_set(int chg_current)
@@ -484,7 +482,7 @@
__func__, chg_current);
temp = 31;
}
- return pm8058_write(pm8058_chg.pm_chip, PM8058_CHG_IMAX, &temp, 1);
+ return pm8xxx_writeb(pm8058_chg.dev->parent, PM8058_CHG_IMAX, temp);
}
#define PM8058_CHG_VMAX_MIN 3300
@@ -501,7 +499,7 @@
temp = (voltage - PM8058_CHG_V_MIN_MV) / PM8058_CHG_V_STEP_MV;
dev_dbg(pm8058_chg.dev, "%s mV=%d setting %02x\n", __func__, voltage,
temp);
- return pm8058_write(pm8058_chg.pm_chip, PM8058_CHG_VMAX_SEL, &temp, 1);
+ return pm8xxx_writeb(pm8058_chg.dev->parent, PM8058_CHG_VMAX_SEL, temp);
}
static int pm_chg_failed_clear(int value)
@@ -509,14 +507,14 @@
u8 temp;
int ret;
- ret = pm8058_read(pm8058_chg.pm_chip, PM8058_CHG_CNTRL_2, &temp, 1);
+ ret = pm8xxx_readb(pm8058_chg.dev->parent, PM8058_CHG_CNTRL_2, &temp);
if (ret)
return ret;
if (value)
temp |= BIT(CHG_FAILED_CLEAR);
else
temp &= ~BIT(CHG_FAILED_CLEAR);
- return pm8058_write(pm8058_chg.pm_chip, PM8058_CHG_CNTRL_2, &temp, 1);
+ return pm8xxx_writeb(pm8058_chg.dev->parent, PM8058_CHG_CNTRL_2, temp);
}
static int pm_chg_iterm_set(int chg_current)
@@ -524,7 +522,7 @@
u8 temp;
temp = (chg_current / PM8058_CHG_I_TERM_STEP_MA) - 1;
- return pm8058_write(pm8058_chg.pm_chip, PM8058_CHG_ITERM, &temp, 1);
+ return pm8xxx_writeb(pm8058_chg.dev->parent, PM8058_CHG_ITERM, temp);
}
static int pm_chg_tchg_set(int minutes)
@@ -532,7 +530,7 @@
u8 temp;
temp = (minutes >> PM8058_CHG_T_TCHG_SHIFT) - 1;
- return pm8058_write(pm8058_chg.pm_chip, PM8058_CHG_TCHG_MAX, &temp, 1);
+ return pm8xxx_writeb(pm8058_chg.dev->parent, PM8058_CHG_TCHG_MAX, temp);
}
static int pm_chg_ttrkl_set(int minutes)
@@ -540,7 +538,8 @@
u8 temp;
temp = minutes - 1;
- return pm8058_write(pm8058_chg.pm_chip, PM8058_CHG_TTRKL_MAX, &temp, 1);
+ return pm8xxx_writeb(pm8058_chg.dev->parent, PM8058_CHG_TTRKL_MAX,
+ temp);
}
static int pm_chg_enum_done_enable(int value)
@@ -548,7 +547,7 @@
u8 temp;
int ret;
- ret = pm8058_read(pm8058_chg.pm_chip, PM8058_CHG_CNTRL_2, &temp, 1);
+ ret = pm8xxx_readb(pm8058_chg.dev->parent, PM8058_CHG_CNTRL_2, &temp);
if (ret)
return ret;
if (value)
@@ -556,7 +555,7 @@
else
temp &= ~BIT(ENUM_DONE);
- return pm8058_write(pm8058_chg.pm_chip, PM8058_CHG_CNTRL_2, &temp, 1);
+ return pm8xxx_writeb(pm8058_chg.dev->parent, PM8058_CHG_CNTRL_2, temp);
}
static uint32_t get_fsm_state(void)
@@ -564,8 +563,8 @@
u8 temp;
temp = 0x00;
- pm8058_write(pm8058_chg.pm_chip, PM8058_CHG_TEST_3, &temp, 1);
- pm8058_read(pm8058_chg.pm_chip, PM8058_CHG_TEST_3, &temp, 1);
+ pm8xxx_writeb(pm8058_chg.dev->parent, PM8058_CHG_TEST_3, temp);
+ pm8xxx_readb(pm8058_chg.dev->parent, PM8058_CHG_TEST_3, &temp);
return (uint32_t)temp;
}
@@ -590,7 +589,7 @@
u8 temp;
int ret;
- ret = pm8058_read(pm8058_chg.pm_chip, PM8058_CHG_CNTRL, &temp, 1);
+ ret = pm8xxx_readb(pm8058_chg.dev->parent, PM8058_CHG_CNTRL, &temp);
if (ret)
return ret;
if (value)
@@ -598,7 +597,7 @@
else
temp &= ~BIT(CHG_CHARGE_DIS);
- return pm8058_write(pm8058_chg.pm_chip, PM8058_CHG_CNTRL, &temp, 1);
+ return pm8xxx_writeb(pm8058_chg.dev->parent, PM8058_CHG_CNTRL, temp);
}
static void pm8058_start_system_current(struct msm_hardware_charger *hw_chg,
@@ -734,7 +733,11 @@
case PMIC8058_CHG_STATE_ATC:
case PMIC8058_CHG_STATE_FAST_CHG:
case PMIC8058_CHG_STATE_TRKL_CHG:
- rc = pm8058_batt_alarm_state_set(0, 0);
+ rc = pm8xxx_batt_alarm_disable(
+ PM8XXX_BATT_ALARM_UPPER_COMPARATOR);
+ if (!rc)
+ rc = pm8xxx_batt_alarm_disable(
+ PM8XXX_BATT_ALARM_LOWER_COMPARATOR);
if (rc)
dev_err(pm8058_chg.dev,
"%s: unable to set alarm state\n", __func__);
@@ -863,25 +866,25 @@
}
} else {
if (pm8058_chg.present) {
- ret = pm8058_read(pm8058_chg.pm_chip,
+ ret = pm8xxx_readb(pm8058_chg.dev->parent,
PM8058_OVP_TEST_REG,
- &old, 1);
+ &old);
temp = old | BIT(FORCE_OVP_OFF);
- ret = pm8058_write(pm8058_chg.pm_chip,
+ ret = pm8xxx_writeb(pm8058_chg.dev->parent,
PM8058_OVP_TEST_REG,
- &temp, 1);
+ temp);
temp = 0xFC;
- ret = pm8058_write(pm8058_chg.pm_chip, PM8058_CHG_TEST,
- &temp, 1);
+ ret = pm8xxx_writeb(pm8058_chg.dev->parent,
+ PM8058_CHG_TEST, temp);
/* 10 ms sleep is for the VCHG to discharge */
msleep(10);
temp = 0xF0;
- ret = pm8058_write(pm8058_chg.pm_chip,
+ ret = pm8xxx_writeb(pm8058_chg.dev->parent,
PM8058_CHG_TEST,
- &temp, 1);
- ret = pm8058_write(pm8058_chg.pm_chip,
+ temp);
+ ret = pm8xxx_writeb(pm8058_chg.dev->parent,
PM8058_OVP_TEST_REG,
- &old, 1);
+ old);
pm_chg_enum_done_enable(0);
pm_chg_auto_disable(1);
@@ -904,21 +907,21 @@
pm_chg_enum_done_enable(0);
pm_chg_auto_disable(1);
- ret = pm8058_read(pm8058_chg.pm_chip,
- PM8058_OVP_TEST_REG, &old, 1);
+ ret = pm8xxx_readb(pm8058_chg.dev->parent,
+ PM8058_OVP_TEST_REG, &old);
temp = old | BIT(FORCE_OVP_OFF);
- ret = pm8058_write(pm8058_chg.pm_chip,
- PM8058_OVP_TEST_REG, &temp, 1);
+ ret = pm8xxx_writeb(pm8058_chg.dev->parent,
+ PM8058_OVP_TEST_REG, temp);
temp = 0xFC;
- ret = pm8058_write(pm8058_chg.pm_chip,
- PM8058_CHG_TEST, &temp, 1);
+ ret = pm8xxx_writeb(pm8058_chg.dev->parent,
+ PM8058_CHG_TEST, temp);
/* 10 ms sleep is for the VCHG to discharge */
msleep(10);
temp = 0xF0;
- ret = pm8058_write(pm8058_chg.pm_chip,
- PM8058_CHG_TEST, &temp, 1);
- ret = pm8058_write(pm8058_chg.pm_chip,
- PM8058_OVP_TEST_REG, &old, 1);
+ ret = pm8xxx_writeb(pm8058_chg.dev->parent,
+ PM8058_CHG_TEST, temp);
+ ret = pm8xxx_writeb(pm8058_chg.dev->parent,
+ PM8058_OVP_TEST_REG, old);
if (!is_chg_plugged_in()) {
msm_charger_notify_event(&usb_hw_chg,
@@ -983,8 +986,8 @@
u8 temp;
temp = 0x00;
- if (!pm8058_write(pm8058_chg.pm_chip, PM8058_CHG_TEST_3, &temp, 1)) {
- pm8058_read(pm8058_chg.pm_chip, PM8058_CHG_TEST_3, &temp, 1);
+ if (!pm8xxx_writeb(pm8058_chg.dev->parent, PM8058_CHG_TEST_3, temp)) {
+ pm8xxx_readb(pm8058_chg.dev->parent, PM8058_CHG_TEST_3, &temp);
dev_dbg(pm8058_chg.dev, "%s state=%d\n", __func__, temp);
}
return IRQ_HANDLED;
@@ -1187,7 +1190,7 @@
"%s:couldnt find resource AUTO_CHGDONE\n", __func__);
goto err_out;
} else {
- ret = request_threaded_irq(res->start, NULL,
+ ret = request_irq(res->start,
pm8058_chg_auto_chgdone_handler,
IRQF_TRIGGER_RISING,
res->name, NULL);
@@ -1208,7 +1211,7 @@
"%s:couldnt find resource AUTO_CHGFAIL\n", __func__);
goto err_out;
} else {
- ret = request_threaded_irq(res->start, NULL,
+ ret = request_irq(res->start,
pm8058_chg_auto_chgfail_handler,
IRQF_TRIGGER_RISING, res->name, NULL);
if (ret < 0) {
@@ -1227,7 +1230,7 @@
"%s:couldnt find resource CHGSTATE\n", __func__);
goto err_out;
} else {
- ret = request_threaded_irq(res->start, NULL,
+ ret = request_irq(res->start,
pm8058_chg_chgstate_handler,
IRQF_TRIGGER_RISING, res->name, NULL);
if (ret < 0) {
@@ -1246,7 +1249,7 @@
"%s:couldnt find resource FASTCHG\n", __func__);
goto err_out;
} else {
- ret = request_threaded_irq(res->start, NULL,
+ ret = request_irq(res->start,
pm8058_chg_fastchg_handler,
IRQF_TRIGGER_RISING, res->name, NULL);
if (ret < 0) {
@@ -1265,7 +1268,7 @@
"%s:couldnt find resource CHG_END\n", __func__);
goto err_out;
} else {
- ret = request_threaded_irq(res->start, NULL,
+ ret = request_irq(res->start,
pm8058_chg_batttemp_handler,
IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING,
res->name, NULL);
@@ -1286,7 +1289,7 @@
"%s:couldnt find resource BATT_REPLACE\n", __func__);
goto err_out;
} else {
- ret = request_threaded_irq(res->start, NULL,
+ ret = request_irq(res->start,
pm8058_chg_batt_replace_handler,
IRQF_TRIGGER_RISING, res->name, NULL);
if (ret < 0) {
@@ -1305,7 +1308,7 @@
"%s:couldnt find resource BATTCONNECT\n", __func__);
goto err_out;
} else {
- ret = request_threaded_irq(res->start, NULL,
+ ret = request_irq(res->start,
pm8058_chg_battconnect_handler,
IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING,
res->name, NULL);
@@ -1351,7 +1354,7 @@
u8 temp;
int rc;
- rc = pm8058_read(pm8058_chg.pm_chip, PM8058_CHG_CNTRL, &temp, 1);
+ rc = pm8xxx_readb(pm8058_chg.dev->parent, PM8058_CHG_CNTRL, &temp);
if (rc)
return rc;
@@ -1367,7 +1370,7 @@
u8 temp;
int rc;
- rc = pm8058_read(pm8058_chg.pm_chip, PM8058_CHG_CNTRL, &temp, 1);
+ rc = pm8xxx_readb(pm8058_chg.dev->parent, PM8058_CHG_CNTRL, &temp);
if (rc)
return rc;
if (on)
@@ -1375,7 +1378,7 @@
else
temp &= ~BIT(CHG_CHARGE_BAT);
- return pm8058_write(pm8058_chg.pm_chip, PM8058_CHG_CNTRL, &temp, 1);
+ return pm8xxx_writeb(pm8058_chg.dev->parent, PM8058_CHG_CNTRL, temp);
}
EXPORT_SYMBOL(pm8058_set_charge_batt);
@@ -1496,12 +1499,12 @@
u8 temp;
temp = 0xA3;
- pm8058_write(pm8058_chg.pm_chip, PM8058_CHG_TEST_2, &temp, 1);
+ pm8xxx_writeb(pm8058_chg.dev->parent, PM8058_CHG_TEST_2, temp);
temp = 0x84;
- pm8058_write(pm8058_chg.pm_chip, PM8058_CHG_TEST_2, &temp, 1);
+ pm8xxx_writeb(pm8058_chg.dev->parent, PM8058_CHG_TEST_2, temp);
msleep(2);
temp = 0x80;
- pm8058_write(pm8058_chg.pm_chip, PM8058_CHG_TEST_2, &temp, 1);
+ pm8xxx_writeb(pm8058_chg.dev->parent, PM8058_CHG_TEST_2, temp);
return 0;
}
@@ -1511,7 +1514,7 @@
int ret;
u8 temp;
- ret = pm8058_read(pm8058_chg.pm_chip, i, &temp, 1);
+ ret = pm8xxx_readb(pm8058_chg.dev->parent, i, &temp);
if (ret)
return -EAGAIN;
*val = temp;
@@ -1525,7 +1528,7 @@
u8 temp;
temp = (u8) val;
- ret = pm8058_write(pm8058_chg.pm_chip, i, &temp, 1);
+ ret = pm8xxx_writeb(pm8058_chg.dev->parent, i, temp);
mb();
if (ret)
return -EAGAIN;
@@ -1821,7 +1824,11 @@
break;
/* expected case - trip of low threshold */
case 1:
- rc = pm8058_batt_alarm_state_set(0, 0);
+ rc = pm8xxx_batt_alarm_disable(
+ PM8XXX_BATT_ALARM_UPPER_COMPARATOR);
+ if (!rc)
+ rc = pm8xxx_batt_alarm_disable(
+ PM8XXX_BATT_ALARM_LOWER_COMPARATOR);
if (rc)
dev_err(pm8058_chg.dev,
"%s: unable to set alarm state\n", __func__);
@@ -1841,8 +1848,15 @@
static int pm8058_monitor_for_recharging(void)
{
+ int rc;
/* enable low comparator */
- return pm8058_batt_alarm_state_set(1, 0);
+ rc = pm8xxx_batt_alarm_disable(PM8XXX_BATT_ALARM_UPPER_COMPARATOR);
+ if (!rc)
+ return pm8xxx_batt_alarm_enable(
+ PM8XXX_BATT_ALARM_LOWER_COMPARATOR);
+
+ return rc;
+
}
static struct msm_battery_gauge pm8058_batt_gauge = {
@@ -1860,33 +1874,30 @@
int ret = 0;
temp = 0x10;
- ret |= pm8058_write(pm8058_chg.pm_chip, PM8058_CHG_TEST, &temp, 1);
- ret |= pm8058_read(pm8058_chg.pm_chip, PM8058_CHG_TEST, &old, 1);
+ ret |= pm8xxx_writeb(pm8058_chg.dev->parent, PM8058_CHG_TEST, temp);
+ ret |= pm8xxx_readb(pm8058_chg.dev->parent, PM8058_CHG_TEST, &old);
old = old & ~BIT(IGNORE_LL);
temp = 0x90 | (0xF & old);
- ret |= pm8058_write(pm8058_chg.pm_chip, PM8058_CHG_TEST, &temp, 1);
+ ret |= pm8xxx_writeb(pm8058_chg.dev->parent, PM8058_CHG_TEST, temp);
return ret;
}
static int __devinit pm8058_charger_probe(struct platform_device *pdev)
{
- struct pm8058_chip *pm_chip;
struct pmic8058_charger_data *pdata;
int rc = 0;
- pm_chip = dev_get_drvdata(pdev->dev.parent);
- if (pm_chip == NULL) {
- pr_err("%s:no parent data passed in.\n", __func__);
- return -EFAULT;
- }
-
- pm8058_chg.pm_chip = pm_chip;
pm8058_chg.pdata = pdev->dev.platform_data;
pm8058_chg.dev = &pdev->dev;
pdata = (struct pmic8058_charger_data *) pm8058_chg.pdata;
- if (pdata) {
+ if (pdata == NULL) {
+ pr_err("%s: pdata not present\n", __func__);
+ return -EINVAL;
+ }
+
+ if (pdata->charger_data_valid) {
usb_hw_chg.type = pdata->charger_type;
chg_data.charger_type = pdata->charger_type;
chg_data.max_source_current = pdata->max_source_current;
@@ -1928,7 +1939,10 @@
pm8058_chg_enable_irq(BATTTEMP_IRQ);
pm8058_chg_enable_irq(BATTCONNECT_IRQ);
- rc = pm8058_batt_alarm_state_set(0, 0);
+ rc = pm8xxx_batt_alarm_disable(PM8XXX_BATT_ALARM_UPPER_COMPARATOR);
+ if (!rc)
+ rc = pm8xxx_batt_alarm_disable(
+ PM8XXX_BATT_ALARM_LOWER_COMPARATOR);
if (rc) {
pr_err("%s: unable to set batt alarm state\n", __func__);
goto free_irq;
@@ -1938,26 +1952,31 @@
* The batt-alarm driver requires sane values for both min / max,
* regardless of whether they're both activated.
*/
- rc = pm8058_batt_alarm_threshold_set(resume_mv, 4300);
+ rc = pm8xxx_batt_alarm_threshold_set(
+ PM8XXX_BATT_ALARM_LOWER_COMPARATOR, resume_mv);
+ if (!rc)
+ rc = pm8xxx_batt_alarm_threshold_set(
+ PM8XXX_BATT_ALARM_UPPER_COMPARATOR, 4300);
if (rc) {
pr_err("%s: unable to set batt alarm threshold\n", __func__);
goto free_irq;
}
- rc = pm8058_batt_alarm_hold_time_set(PM8058_BATT_ALARM_HOLD_TIME_16_MS);
+ rc = pm8xxx_batt_alarm_hold_time_set(
+ PM8XXX_BATT_ALARM_HOLD_TIME_16_MS);
if (rc) {
pr_err("%s: unable to set batt alarm hold time\n", __func__);
goto free_irq;
}
/* PWM enabled at 2Hz */
- rc = pm8058_batt_alarm_pwm_rate_set(1, 7, 4);
+ rc = pm8xxx_batt_alarm_pwm_rate_set(1, 7, 4);
if (rc) {
pr_err("%s: unable to set batt alarm pwm rate\n", __func__);
goto free_irq;
}
- rc = pm8058_batt_alarm_register_notifier(&alarm_notifier);
+ rc = pm8xxx_batt_alarm_register_notifier(&alarm_notifier);
if (rc) {
pr_err("%s: unable to register alarm notifier\n", __func__);
goto free_irq;
@@ -1987,11 +2006,14 @@
remove_debugfs_entries();
kfree(chip);
- rc = pm8058_batt_alarm_state_set(0, 0);
+ rc = pm8xxx_batt_alarm_disable(PM8XXX_BATT_ALARM_UPPER_COMPARATOR);
+ if (!rc)
+ rc = pm8xxx_batt_alarm_disable(
+ PM8XXX_BATT_ALARM_LOWER_COMPARATOR);
if (rc)
pr_err("%s: unable to set batt alarm state\n", __func__);
- rc |= pm8058_batt_alarm_unregister_notifier(&alarm_notifier);
+ rc |= pm8xxx_batt_alarm_unregister_notifier(&alarm_notifier);
if (rc)
pr_err("%s: unable to register alarm notifier\n", __func__);
return rc;
diff --git a/drivers/regulator/pm8058-xo.c b/drivers/regulator/pm8058-xo.c
index 581e228..b778660 100644
--- a/drivers/regulator/pm8058-xo.c
+++ b/drivers/regulator/pm8058-xo.c
@@ -19,6 +19,7 @@
#include <linux/bitops.h>
#include <linux/mfd/pmic8058.h>
#include <linux/regulator/driver.h>
+#include <linux/mfd/pm8xxx/core.h>
#include <linux/regulator/pm8058-xo.h>
/* XO buffer masks and values */
@@ -39,6 +40,7 @@
#define XO_DISABLE (XO_MODE_MANUAL | XO_BUFFER_DISABLE)
struct pm8058_xo_buffer {
+ struct device *dev;
struct pm8058_xo_pdata *pdata;
struct regulator_dev *rdev;
u16 ctrl_addr;
@@ -55,7 +57,7 @@
XO_BUFFER(A1, 0x186),
};
-static int pm8058_xo_buffer_write(struct pm8058_chip *chip,
+static int pm8058_xo_buffer_write(struct pm8058_xo_buffer *xo,
u16 addr, u8 val, u8 mask, u8 *reg_save)
{
u8 reg;
@@ -63,10 +65,10 @@
reg = (*reg_save & ~mask) | (val & mask);
if (reg != *reg_save)
- rc = pm8058_write(chip, addr, ®, 1);
+ rc = pm8xxx_writeb(xo->dev->parent, addr, reg);
if (rc)
- pr_err("FAIL: pm8058_write: rc=%d\n", rc);
+ pr_err("FAIL: pm8xxx_write: rc=%d\n", rc);
else
*reg_save = reg;
return rc;
@@ -75,10 +77,9 @@
static int pm8058_xo_buffer_enable(struct regulator_dev *dev)
{
struct pm8058_xo_buffer *xo = rdev_get_drvdata(dev);
- struct pm8058_chip *chip = dev_get_drvdata(dev->dev.parent);
int rc;
- rc = pm8058_xo_buffer_write(chip, xo->ctrl_addr, XO_ENABLE,
+ rc = pm8058_xo_buffer_write(xo, xo->ctrl_addr, XO_ENABLE,
XO_ENABLE_MASK, &xo->ctrl_reg);
if (rc)
pr_err("FAIL: pm8058_xo_buffer_write: rc=%d\n", rc);
@@ -99,10 +100,9 @@
static int pm8058_xo_buffer_disable(struct regulator_dev *dev)
{
struct pm8058_xo_buffer *xo = rdev_get_drvdata(dev);
- struct pm8058_chip *chip = dev_get_drvdata(dev->dev.parent);
int rc;
- rc = pm8058_xo_buffer_write(chip, xo->ctrl_addr, XO_DISABLE,
+ rc = pm8058_xo_buffer_write(xo, xo->ctrl_addr, XO_DISABLE,
XO_ENABLE_MASK, &xo->ctrl_reg);
if (rc)
pr_err("FAIL: pm8058_xo_buffer_write: rc=%d\n", rc);
@@ -130,23 +130,21 @@
VREG_DESCRIP(PM8058_XO_ID_A1, "8058_xo_a1", &pm8058_xo_ops),
};
-static int pm8058_init_xo_buffer(struct pm8058_chip *chip,
- struct pm8058_xo_buffer *xo)
+static int pm8058_init_xo_buffer(struct pm8058_xo_buffer *xo)
{
int rc;
/* Save the current control register state */
- rc = pm8058_read(chip, xo->ctrl_addr, &xo->ctrl_reg, 1);
+ rc = pm8xxx_readb(xo->dev->parent, xo->ctrl_addr, &xo->ctrl_reg);
if (rc)
- pr_err("FAIL: pm8058_read: rc=%d\n", rc);
+ pr_err("FAIL: pm8xxx_read: rc=%d\n", rc);
return rc;
}
static int __devinit pm8058_xo_buffer_probe(struct platform_device *pdev)
{
struct regulator_desc *rdesc;
- struct pm8058_chip *chip;
struct pm8058_xo_buffer *xo;
int rc = 0;
@@ -154,16 +152,15 @@
return -EINVAL;
if (pdev->id >= 0 && pdev->id < PM8058_XO_ID_MAX) {
- chip = dev_get_drvdata(pdev->dev.parent);
rdesc = &pm8058_xo_buffer_desc[pdev->id];
xo = &pm8058_xo_buffer[pdev->id];
xo->pdata = pdev->dev.platform_data;
+ xo->dev = &pdev->dev;
- rc = pm8058_init_xo_buffer(chip, xo);
+ rc = pm8058_init_xo_buffer(xo);
if (rc)
goto bail;
- platform_set_drvdata(pdev, chip);
xo->rdev = regulator_register(rdesc, &pdev->dev,
&xo->pdata->init_data, xo);
if (IS_ERR(xo->rdev)) {
diff --git a/drivers/regulator/pmic8058-regulator.c b/drivers/regulator/pmic8058-regulator.c
index c11f32b..e137b0f 100644
--- a/drivers/regulator/pmic8058-regulator.c
+++ b/drivers/regulator/pmic8058-regulator.c
@@ -18,6 +18,7 @@
#include <linux/mfd/pmic8058.h>
#include <linux/regulator/driver.h>
#include <linux/regulator/machine.h>
+#include <linux/mfd/pm8xxx/core.h>
#include <linux/regulator/pmic8058-regulator.h>
/* Regulator types */
@@ -205,6 +206,7 @@
};
struct pm8058_vreg {
+ struct device *dev;
struct pm8058_vreg_pdata *pdata;
struct regulator_dev *rdev;
struct pm8058_enable *global_enable[GLOBAL_ENABLE_MAX];
@@ -375,11 +377,9 @@
NCP(NCP, 0x090, 0x0EC),
};
-static int pm8058_smps_set_voltage_advanced(struct pm8058_vreg *vreg,
- struct pm8058_chip *chip, int uV,
+static int pm8058_smps_set_voltage_advanced(struct pm8058_vreg *vreg, int uV,
int force_on);
-static int pm8058_smps_set_voltage_legacy(struct pm8058_vreg *vreg,
- struct pm8058_chip *chip, int uV);
+static int pm8058_smps_set_voltage_legacy(struct pm8058_vreg *vreg, int uV);
static int _pm8058_vreg_is_enabled(struct pm8058_vreg *vreg);
static unsigned int pm8058_vreg_get_mode(struct regulator_dev *dev);
@@ -387,7 +387,7 @@
static void print_write_error(struct pm8058_vreg *vreg, int rc,
const char *func);
-static int pm8058_vreg_write(struct pm8058_chip *chip,
+static int pm8058_vreg_write(struct pm8058_vreg *vreg,
u16 addr, u8 val, u8 mask, u8 *reg_save)
{
int rc = 0;
@@ -395,9 +395,9 @@
reg = (*reg_save & ~mask) | (val & mask);
if (reg != *reg_save)
- rc = pm8058_write(chip, addr, ®, 1);
+ rc = pm8xxx_writeb(vreg->dev->parent, addr, reg);
if (rc)
- pr_err("%s: pm8058_write failed, rc=%d\n", __func__, rc);
+ pr_err("%s: pm8xxx_write failed, rc=%d\n", __func__, rc);
else
*reg_save = reg;
return rc;
@@ -416,14 +416,13 @@
}
-static int pm8058_vreg_set_global_enable(struct pm8058_vreg *vreg,
- struct pm8058_chip *chip, int on)
+static int pm8058_vreg_set_global_enable(struct pm8058_vreg *vreg, int on)
{
int rc = 0, i;
for (i = 0;
(i < GLOBAL_ENABLE_MAX) && !rc && vreg->global_enable[i]; i++)
- rc = pm8058_vreg_write(chip, vreg->global_enable[i]->addr,
+ rc = pm8058_vreg_write(vreg, vreg->global_enable[i]->addr,
(on ? vreg->global_enable_mask[i] : 0),
vreg->global_enable_mask[i],
&vreg->global_enable[i]->reg);
@@ -452,8 +451,7 @@
return ret;
}
-static int pm8058_vreg_set_pin_ctrl(struct pm8058_vreg *vreg,
- struct pm8058_chip *chip, int on)
+static int pm8058_vreg_set_pin_ctrl(struct pm8058_vreg *vreg, int on)
{
int rc = 0, bank;
u8 val = 0, mask;
@@ -473,7 +471,7 @@
val |= LDO_TEST_PIN_CTRL_EN3;
bank = (pf == PM8058_VREG_PIN_FN_ENABLE ? 5 : 6);
- rc = pm8058_vreg_write(chip, vreg->test_addr,
+ rc = pm8058_vreg_write(vreg, vreg->test_addr,
val | REGULATOR_BANK_SEL(bank)
| REGULATOR_BANK_WRITE,
LDO_TEST_PIN_CTRL_MASK | REGULATOR_BANK_MASK,
@@ -484,26 +482,25 @@
val = LDO_TEST_LPM_SEL_CTRL | REGULATOR_BANK_WRITE
| REGULATOR_BANK_SEL(0);
mask = LDO_TEST_LPM_MASK | REGULATOR_BANK_MASK;
- rc = pm8058_vreg_write(chip, vreg->test_addr, val, mask,
+ rc = pm8058_vreg_write(vreg, vreg->test_addr, val, mask,
&vreg->test_reg[0]);
if (rc)
goto bail;
if (pf == PM8058_VREG_PIN_FN_ENABLE) {
/* Pin control ON/OFF */
- rc = pm8058_vreg_write(chip, vreg->ctrl_addr,
+ rc = pm8058_vreg_write(vreg, vreg->ctrl_addr,
LDO_CTRL_PM_HPM,
LDO_ENABLE_MASK | LDO_CTRL_PM_MASK,
&vreg->ctrl_reg);
if (rc)
goto bail;
- rc = pm8058_vreg_set_global_enable(vreg, chip,
- 0);
+ rc = pm8058_vreg_set_global_enable(vreg, 0);
if (rc)
goto bail;
} else {
/* Pin control LPM/HPM */
- rc = pm8058_vreg_write(chip, vreg->ctrl_addr,
+ rc = pm8058_vreg_write(vreg, vreg->ctrl_addr,
LDO_ENABLE | LDO_CTRL_PM_LPM,
LDO_ENABLE_MASK | LDO_CTRL_PM_MASK,
&vreg->ctrl_reg);
@@ -512,14 +509,14 @@
}
} else {
/* Pin control off */
- rc = pm8058_vreg_write(chip, vreg->test_addr,
+ rc = pm8058_vreg_write(vreg, vreg->test_addr,
REGULATOR_BANK_SEL(5) | REGULATOR_BANK_WRITE,
LDO_TEST_PIN_CTRL_MASK | REGULATOR_BANK_MASK,
&vreg->test_reg[5]);
if (rc)
goto bail;
- rc = pm8058_vreg_write(chip, vreg->test_addr,
+ rc = pm8058_vreg_write(vreg, vreg->test_addr,
REGULATOR_BANK_SEL(6) | REGULATOR_BANK_WRITE,
LDO_TEST_PIN_CTRL_MASK | REGULATOR_BANK_MASK,
&vreg->test_reg[6]);
@@ -551,29 +548,29 @@
if (pc & PM8058_VREG_PIN_CTRL_A1)
val |= SMPS_PIN_CTRL_LPM_A1;
}
- rc = pm8058_vreg_set_global_enable(vreg, chip, 0);
+ rc = pm8058_vreg_set_global_enable(vreg, 0);
if (rc)
goto bail;
- rc = pm8058_smps_set_voltage_legacy(vreg, chip,
+ rc = pm8058_smps_set_voltage_legacy(vreg,
vreg->save_uV);
if (rc)
goto bail;
- rc = pm8058_vreg_write(chip, vreg->sleep_ctrl_addr, val,
+ rc = pm8058_vreg_write(vreg, vreg->sleep_ctrl_addr, val,
SMPS_PIN_CTRL_MASK | SMPS_PIN_CTRL_LPM_MASK,
&vreg->sleep_ctrl_reg);
if (rc)
goto bail;
- rc = pm8058_vreg_write(chip, vreg->ctrl_addr,
+ rc = pm8058_vreg_write(vreg, vreg->ctrl_addr,
(pf == PM8058_VREG_PIN_FN_ENABLE
? 0 : SMPS_LEGACY_ENABLE),
SMPS_LEGACY_ENABLE, &vreg->ctrl_reg);
if (rc)
goto bail;
- rc = pm8058_vreg_write(chip, vreg->clk_ctrl_addr,
+ rc = pm8058_vreg_write(vreg, vreg->clk_ctrl_addr,
(pf == PM8058_VREG_PIN_FN_ENABLE
? SMPS_CLK_CTRL_PWM : SMPS_CLK_CTRL_PFM),
SMPS_CLK_CTRL_MASK, &vreg->clk_ctrl_reg);
@@ -584,20 +581,20 @@
if (!SMPS_IN_ADVANCED_MODE(vreg)) {
if (_pm8058_vreg_is_enabled(vreg))
val = SMPS_LEGACY_ENABLE;
- rc = pm8058_vreg_write(chip, vreg->ctrl_addr,
+ rc = pm8058_vreg_write(vreg, vreg->ctrl_addr,
val, SMPS_LEGACY_ENABLE,
&vreg->ctrl_reg);
if (rc)
goto bail;
}
- rc = pm8058_vreg_write(chip, vreg->sleep_ctrl_addr, 0,
+ rc = pm8058_vreg_write(vreg, vreg->sleep_ctrl_addr, 0,
SMPS_PIN_CTRL_MASK | SMPS_PIN_CTRL_LPM_MASK,
&vreg->sleep_ctrl_reg);
if (rc)
goto bail;
- rc = pm8058_smps_set_voltage_advanced(vreg, chip,
+ rc = pm8058_smps_set_voltage_advanced(vreg,
vreg->save_uV, 0);
if (rc)
goto bail;
@@ -615,13 +612,13 @@
if (pc & PM8058_VREG_PIN_CTRL_A1)
val |= LVS_PIN_CTRL_EN3;
- rc = pm8058_vreg_write(chip, vreg->ctrl_addr, val,
+ rc = pm8058_vreg_write(vreg, vreg->ctrl_addr, val,
LVS_PIN_CTRL_MASK | LVS_ENABLE_MASK,
&vreg->ctrl_reg);
if (rc)
goto bail;
- rc = pm8058_vreg_set_global_enable(vreg, chip, 0);
+ rc = pm8058_vreg_set_global_enable(vreg, 0);
if (rc)
goto bail;
} else {
@@ -629,7 +626,7 @@
if (_pm8058_vreg_is_enabled(vreg))
val = LVS_ENABLE;
- rc = pm8058_vreg_write(chip, vreg->ctrl_addr, val,
+ rc = pm8058_vreg_write(vreg, vreg->ctrl_addr, val,
LVS_ENABLE_MASK | LVS_PIN_CTRL_MASK,
&vreg->ctrl_reg);
if (rc)
@@ -649,7 +646,6 @@
static int pm8058_vreg_enable(struct regulator_dev *dev)
{
struct pm8058_vreg *vreg = rdev_get_drvdata(dev);
- struct pm8058_chip *chip = dev_get_drvdata(dev->dev.parent);
int mode;
int rc = 0;
@@ -657,16 +653,15 @@
if (mode == REGULATOR_MODE_IDLE) {
/* Turn on pin control. */
- rc = pm8058_vreg_set_pin_ctrl(vreg, chip, 1);
+ rc = pm8058_vreg_set_pin_ctrl(vreg, 1);
if (rc)
goto bail;
return rc;
}
if (vreg->type == REGULATOR_TYPE_SMPS && SMPS_IN_ADVANCED_MODE(vreg))
- rc = pm8058_smps_set_voltage_advanced(vreg, chip,
- vreg->save_uV, 1);
+ rc = pm8058_smps_set_voltage_advanced(vreg, vreg->save_uV, 1);
else
- rc = pm8058_vreg_write(chip, vreg->ctrl_addr, REGULATOR_EN_MASK,
+ rc = pm8058_vreg_write(vreg, vreg->ctrl_addr, REGULATOR_EN_MASK,
REGULATOR_EN_MASK, &vreg->ctrl_reg);
bail:
if (rc)
@@ -706,26 +701,25 @@
static int pm8058_vreg_disable(struct regulator_dev *dev)
{
struct pm8058_vreg *vreg = rdev_get_drvdata(dev);
- struct pm8058_chip *chip = dev_get_drvdata(dev->dev.parent);
int rc = 0;
/* Disable in global control register. */
- rc = pm8058_vreg_set_global_enable(vreg, chip, 0);
+ rc = pm8058_vreg_set_global_enable(vreg, 0);
if (rc)
goto bail;
/* Turn off pin control. */
- rc = pm8058_vreg_set_pin_ctrl(vreg, chip, 0);
+ rc = pm8058_vreg_set_pin_ctrl(vreg, 0);
if (rc)
goto bail;
/* Disable in local control register. */
if (vreg->type == REGULATOR_TYPE_SMPS && SMPS_IN_ADVANCED_MODE(vreg))
- rc = pm8058_vreg_write(chip, vreg->ctrl_addr,
+ rc = pm8058_vreg_write(vreg, vreg->ctrl_addr,
SMPS_ADVANCED_BAND_OFF, SMPS_ADVANCED_BAND_MASK,
&vreg->ctrl_reg);
else
- rc = pm8058_vreg_write(chip, vreg->ctrl_addr, 0,
+ rc = pm8058_vreg_write(vreg, vreg->ctrl_addr, 0,
REGULATOR_EN_MASK, &vreg->ctrl_reg);
bail:
@@ -735,8 +729,7 @@
return rc;
}
-static int pm8058_pldo_set_voltage(struct pm8058_chip *chip,
- struct pm8058_vreg *vreg, int uV)
+static int pm8058_pldo_set_voltage(struct pm8058_vreg *vreg, int uV)
{
int vmin, rc = 0;
unsigned vprog, fine_step;
@@ -775,7 +768,7 @@
|| ((range_sel ^ vreg->test_reg[2]) & LDO_TEST_RANGE_SEL_MASK)
|| ((fine_step_reg ^ vreg->test_reg[2])
& LDO_TEST_FINE_STEP_MASK))) {
- rc = pm8058_vreg_write(chip, vreg->test_addr,
+ rc = pm8058_vreg_write(vreg, vreg->test_addr,
REGULATOR_BANK_SEL(2) | REGULATOR_BANK_WRITE,
REGULATOR_BANK_MASK | LDO_TEST_VPROG_UPDATE_MASK,
&vreg->test_reg[2]);
@@ -784,13 +777,13 @@
}
/* Write new voltage. */
- rc = pm8058_vreg_write(chip, vreg->ctrl_addr, vprog,
+ rc = pm8058_vreg_write(vreg, vreg->ctrl_addr, vprog,
LDO_CTRL_VPROG_MASK, &vreg->ctrl_reg);
if (rc)
goto bail;
/* Write range extension. */
- rc = pm8058_vreg_write(chip, vreg->test_addr,
+ rc = pm8058_vreg_write(vreg, vreg->test_addr,
range_ext | REGULATOR_BANK_SEL(4)
| REGULATOR_BANK_WRITE,
LDO_TEST_RANGE_EXT_MASK | REGULATOR_BANK_MASK,
@@ -799,7 +792,7 @@
goto bail;
/* Write fine step, range select and program voltage update. */
- rc = pm8058_vreg_write(chip, vreg->test_addr,
+ rc = pm8058_vreg_write(vreg, vreg->test_addr,
fine_step_reg | range_sel | REGULATOR_BANK_SEL(2)
| REGULATOR_BANK_WRITE | LDO_TEST_VPROG_UPDATE_MASK,
LDO_TEST_FINE_STEP_MASK | LDO_TEST_RANGE_SEL_MASK
@@ -812,8 +805,7 @@
return rc;
}
-static int pm8058_nldo_set_voltage(struct pm8058_chip *chip,
- struct pm8058_vreg *vreg, int uV)
+static int pm8058_nldo_set_voltage(struct pm8058_vreg *vreg, int uV)
{
unsigned vprog, fine_step_reg;
int rc;
@@ -826,13 +818,13 @@
vprog >>= 1;
/* Write new voltage. */
- rc = pm8058_vreg_write(chip, vreg->ctrl_addr, vprog,
+ rc = pm8058_vreg_write(vreg, vreg->ctrl_addr, vprog,
LDO_CTRL_VPROG_MASK, &vreg->ctrl_reg);
if (rc)
goto bail;
/* Write fine step. */
- rc = pm8058_vreg_write(chip, vreg->test_addr,
+ rc = pm8058_vreg_write(vreg, vreg->test_addr,
fine_step_reg | REGULATOR_BANK_SEL(2)
| REGULATOR_BANK_WRITE | LDO_TEST_VPROG_UPDATE_MASK,
LDO_TEST_FINE_STEP_MASK | REGULATOR_BANK_MASK
@@ -849,12 +841,11 @@
int min_uV, int max_uV, unsigned *selector)
{
struct pm8058_vreg *vreg = rdev_get_drvdata(dev);
- struct pm8058_chip *chip = dev_get_drvdata(dev->dev.parent);
if (vreg->is_nmos)
- return pm8058_nldo_set_voltage(chip, vreg, min_uV);
+ return pm8058_nldo_set_voltage(vreg, min_uV);
else
- return pm8058_pldo_set_voltage(chip, vreg, min_uV);
+ return pm8058_pldo_set_voltage(vreg, min_uV);
}
static int pm8058_pldo_get_voltage(struct pm8058_vreg *vreg)
@@ -967,8 +958,7 @@
}
static int pm8058_smps_set_voltage_advanced(struct pm8058_vreg *vreg,
- struct pm8058_chip *chip, int uV,
- int force_on)
+ int uV, int force_on)
{
u8 vprog, band;
int rc, new_uV;
@@ -992,7 +982,7 @@
band = SMPS_ADVANCED_BAND_OFF;
/* Set advanced mode bit to 1. */
- rc = pm8058_vreg_write(chip, vreg->test_addr, SMPS_ADVANCED_MODE
+ rc = pm8058_vreg_write(vreg, vreg->test_addr, SMPS_ADVANCED_MODE
| REGULATOR_BANK_WRITE | REGULATOR_BANK_SEL(7),
SMPS_ADVANCED_MODE_MASK | REGULATOR_BANK_MASK,
&vreg->test_reg[7]);
@@ -1000,7 +990,7 @@
goto bail;
/* Set voltage and voltage band. */
- rc = pm8058_vreg_write(chip, vreg->ctrl_addr, band | vprog,
+ rc = pm8058_vreg_write(vreg, vreg->ctrl_addr, band | vprog,
SMPS_ADVANCED_BAND_MASK | SMPS_ADVANCED_VPROG_MASK,
&vreg->ctrl_reg);
if (rc)
@@ -1012,8 +1002,7 @@
return rc;
}
-static int pm8058_smps_set_voltage_legacy(struct pm8058_vreg *vreg,
- struct pm8058_chip *chip, int uV)
+static int pm8058_smps_set_voltage_legacy(struct pm8058_vreg *vreg, int uV)
{
u8 vlow, vref, vprog, pd, en;
int rc;
@@ -1033,7 +1022,7 @@
}
/* set vlow bit for ultra low voltage mode */
- rc = pm8058_vreg_write(chip, vreg->test_addr,
+ rc = pm8058_vreg_write(vreg, vreg->test_addr,
vlow | REGULATOR_BANK_WRITE | REGULATOR_BANK_SEL(1),
REGULATOR_BANK_MASK | SMPS_LEGACY_VLOW_SEL_MASK,
&vreg->test_reg[1]);
@@ -1041,7 +1030,7 @@
goto bail;
/* Set advanced mode bit to 0. */
- rc = pm8058_vreg_write(chip, vreg->test_addr, SMPS_LEGACY_MODE
+ rc = pm8058_vreg_write(vreg, vreg->test_addr, SMPS_LEGACY_MODE
| REGULATOR_BANK_WRITE | REGULATOR_BANK_SEL(7),
SMPS_ADVANCED_MODE_MASK | REGULATOR_BANK_MASK,
&vreg->test_reg[7]);
@@ -1052,7 +1041,7 @@
pd = (vreg->pdata->pull_down_enable ? SMPS_LEGACY_PULL_DOWN_ENABLE : 0);
/* Set voltage (and the rest of the control register). */
- rc = pm8058_vreg_write(chip, vreg->ctrl_addr, en | pd | vref | vprog,
+ rc = pm8058_vreg_write(vreg, vreg->ctrl_addr, en | pd | vref | vprog,
SMPS_LEGACY_ENABLE | SMPS_LEGACY_PULL_DOWN_ENABLE
| SMPS_LEGACY_VREF_SEL_MASK | SMPS_LEGACY_VPROG_MASK,
&vreg->ctrl_reg);
@@ -1067,16 +1056,15 @@
int min_uV, int max_uV, unsigned *selector)
{
struct pm8058_vreg *vreg = rdev_get_drvdata(dev);
- struct pm8058_chip *chip = dev_get_drvdata(dev->dev.parent);
int rc = 0;
if (min_uV < SMPS_UV_MIN || min_uV > SMPS_UV_MAX)
return -EINVAL;
if (SMPS_IN_ADVANCED_MODE(vreg))
- rc = pm8058_smps_set_voltage_advanced(vreg, chip, min_uV, 0);
+ rc = pm8058_smps_set_voltage_advanced(vreg, min_uV, 0);
else
- rc = pm8058_smps_set_voltage_legacy(vreg, chip, min_uV);
+ rc = pm8058_smps_set_voltage_legacy(vreg, min_uV);
if (rc)
print_write_error(vreg, rc, __func__);
@@ -1088,7 +1076,6 @@
int min_uV, int max_uV, unsigned *selector)
{
struct pm8058_vreg *vreg = rdev_get_drvdata(dev);
- struct pm8058_chip *chip = dev_get_drvdata(dev->dev.parent);
int rc;
u8 val;
@@ -1098,7 +1085,7 @@
val = (min_uV - NCP_UV_MIN) / NCP_UV_STEP;
/* voltage setting */
- rc = pm8058_vreg_write(chip, vreg->ctrl_addr, val, NCP_VPROG_MASK,
+ rc = pm8058_vreg_write(vreg, vreg->ctrl_addr, val, NCP_VPROG_MASK,
&vreg->ctrl_reg);
if (rc)
print_write_error(vreg, rc, __func__);
@@ -1113,8 +1100,7 @@
return NCP_UV_MIN + vprog * NCP_UV_STEP;
}
-static int pm8058_ldo_set_mode(struct pm8058_vreg *vreg,
- struct pm8058_chip *chip, unsigned int mode)
+static int pm8058_ldo_set_mode(struct pm8058_vreg *vreg, unsigned int mode)
{
int rc = 0;
u8 mask, val;
@@ -1125,13 +1111,13 @@
val = (_pm8058_vreg_is_enabled(vreg) ? LDO_ENABLE : 0)
| LDO_CTRL_PM_HPM;
mask = LDO_ENABLE_MASK | LDO_CTRL_PM_MASK;
- rc = pm8058_vreg_write(chip, vreg->ctrl_addr, val, mask,
+ rc = pm8058_vreg_write(vreg, vreg->ctrl_addr, val, mask,
&vreg->ctrl_reg);
if (rc)
goto bail;
if (pm8058_vreg_using_pin_ctrl(vreg))
- rc = pm8058_vreg_set_pin_ctrl(vreg, chip, 0);
+ rc = pm8058_vreg_set_pin_ctrl(vreg, 0);
if (rc)
goto bail;
break;
@@ -1141,7 +1127,7 @@
val = (_pm8058_vreg_is_enabled(vreg) ? LDO_ENABLE : 0)
| LDO_CTRL_PM_LPM;
mask = LDO_ENABLE_MASK | LDO_CTRL_PM_MASK;
- rc = pm8058_vreg_write(chip, vreg->ctrl_addr, val, mask,
+ rc = pm8058_vreg_write(vreg, vreg->ctrl_addr, val, mask,
&vreg->ctrl_reg);
if (rc)
goto bail;
@@ -1149,13 +1135,13 @@
val = LDO_TEST_LPM_SEL_CTRL | REGULATOR_BANK_WRITE
| REGULATOR_BANK_SEL(0);
mask = LDO_TEST_LPM_MASK | REGULATOR_BANK_MASK;
- rc = pm8058_vreg_write(chip, vreg->test_addr, val, mask,
+ rc = pm8058_vreg_write(vreg, vreg->test_addr, val, mask,
&vreg->test_reg[0]);
if (rc)
goto bail;
if (pm8058_vreg_using_pin_ctrl(vreg))
- rc = pm8058_vreg_set_pin_ctrl(vreg, chip, 0);
+ rc = pm8058_vreg_set_pin_ctrl(vreg, 0);
if (rc)
goto bail;
break;
@@ -1163,7 +1149,7 @@
case REGULATOR_MODE_IDLE:
/* Pin Control */
if (_pm8058_vreg_is_enabled(vreg))
- rc = pm8058_vreg_set_pin_ctrl(vreg, chip, 1);
+ rc = pm8058_vreg_set_pin_ctrl(vreg, 1);
if (rc)
goto bail;
break;
@@ -1180,8 +1166,7 @@
return rc;
}
-static int pm8058_smps_set_mode(struct pm8058_vreg *vreg,
- struct pm8058_chip *chip, unsigned int mode)
+static int pm8058_smps_set_mode(struct pm8058_vreg *vreg, unsigned int mode)
{
int rc = 0;
u8 mask, val;
@@ -1191,13 +1176,13 @@
/* HPM */
val = SMPS_CLK_CTRL_PWM;
mask = SMPS_CLK_CTRL_MASK;
- rc = pm8058_vreg_write(chip, vreg->clk_ctrl_addr, val, mask,
+ rc = pm8058_vreg_write(vreg, vreg->clk_ctrl_addr, val, mask,
&vreg->clk_ctrl_reg);
if (rc)
goto bail;
if (pm8058_vreg_using_pin_ctrl(vreg))
- rc = pm8058_vreg_set_pin_ctrl(vreg, chip, 0);
+ rc = pm8058_vreg_set_pin_ctrl(vreg, 0);
if (rc)
goto bail;
break;
@@ -1206,13 +1191,13 @@
/* LPM */
val = SMPS_CLK_CTRL_PFM;
mask = SMPS_CLK_CTRL_MASK;
- rc = pm8058_vreg_write(chip, vreg->clk_ctrl_addr, val, mask,
+ rc = pm8058_vreg_write(vreg, vreg->clk_ctrl_addr, val, mask,
&vreg->clk_ctrl_reg);
if (rc)
goto bail;
if (pm8058_vreg_using_pin_ctrl(vreg))
- rc = pm8058_vreg_set_pin_ctrl(vreg, chip, 0);
+ rc = pm8058_vreg_set_pin_ctrl(vreg, 0);
if (rc)
goto bail;
break;
@@ -1220,7 +1205,7 @@
case REGULATOR_MODE_IDLE:
/* Pin Control */
if (_pm8058_vreg_is_enabled(vreg))
- rc = pm8058_vreg_set_pin_ctrl(vreg, chip, 1);
+ rc = pm8058_vreg_set_pin_ctrl(vreg, 1);
if (rc)
goto bail;
break;
@@ -1237,18 +1222,17 @@
return rc;
}
-static int pm8058_lvs_set_mode(struct pm8058_vreg *vreg,
- struct pm8058_chip *chip, unsigned int mode)
+static int pm8058_lvs_set_mode(struct pm8058_vreg *vreg, unsigned int mode)
{
int rc = 0;
if (mode == REGULATOR_MODE_IDLE) {
/* Use pin control. */
if (_pm8058_vreg_is_enabled(vreg))
- rc = pm8058_vreg_set_pin_ctrl(vreg, chip, 1);
+ rc = pm8058_vreg_set_pin_ctrl(vreg, 1);
} else {
/* Turn off pin control. */
- rc = pm8058_vreg_set_pin_ctrl(vreg, chip, 0);
+ rc = pm8058_vreg_set_pin_ctrl(vreg, 0);
}
return rc;
@@ -1268,7 +1252,6 @@
static int pm8058_vreg_set_mode(struct regulator_dev *dev, unsigned int mode)
{
struct pm8058_vreg *vreg = rdev_get_drvdata(dev);
- struct pm8058_chip *chip = dev_get_drvdata(dev->dev.parent);
unsigned prev_optimum = vreg->optimum;
unsigned prev_pc_vote = vreg->pc_vote;
unsigned prev_mode_initialized = vreg->mode_initialized;
@@ -1320,13 +1303,13 @@
switch (vreg->type) {
case REGULATOR_TYPE_LDO:
- rc = pm8058_ldo_set_mode(vreg, chip, new_mode);
+ rc = pm8058_ldo_set_mode(vreg, new_mode);
break;
case REGULATOR_TYPE_SMPS:
- rc = pm8058_smps_set_mode(vreg, chip, new_mode);
+ rc = pm8058_smps_set_mode(vreg, new_mode);
break;
case REGULATOR_TYPE_LVS:
- rc = pm8058_lvs_set_mode(vreg, chip, new_mode);
+ rc = pm8058_lvs_set_mode(vreg, new_mode);
break;
}
@@ -1499,24 +1482,25 @@
VREG_DESCRIP(PM8058_VREG_ID_NCP, "8058_ncp", &pm8058_ncp_ops),
};
-static int pm8058_master_enable_init(struct pm8058_chip *chip)
+static int pm8058_master_enable_init(struct pm8058_vreg *vreg)
{
int rc = 0, i;
for (i = 0; i < MASTER_ENABLE_COUNT; i++) {
- rc = pm8058_read(chip, m_en[i].addr, &(m_en[i].reg), 1);
+ rc = pm8xxx_readb(vreg->dev->parent, m_en[i].addr,
+ &(m_en[i].reg));
if (rc)
goto bail;
}
bail:
if (rc)
- pr_err("%s: pm8058_read failed, rc=%d\n", __func__, rc);
+ pr_err("%s: pm8xxx_read failed, rc=%d\n", __func__, rc);
return rc;
}
-static int pm8058_init_ldo(struct pm8058_chip *chip, struct pm8058_vreg *vreg)
+static int pm8058_init_ldo(struct pm8058_vreg *vreg)
{
int rc = 0, i;
u8 bank;
@@ -1524,11 +1508,12 @@
/* Save the current test register state. */
for (i = 0; i < LDO_TEST_BANKS; i++) {
bank = REGULATOR_BANK_SEL(i);
- rc = pm8058_write(chip, vreg->test_addr, &bank, 1);
+ rc = pm8xxx_writeb(vreg->dev->parent, vreg->test_addr, bank);
if (rc)
goto bail;
- rc = pm8058_read(chip, vreg->test_addr, &vreg->test_reg[i], 1);
+ rc = pm8xxx_readb(vreg->dev->parent, vreg->test_addr,
+ &vreg->test_reg[i]);
if (rc)
goto bail;
vreg->test_reg[i] |= REGULATOR_BANK_WRITE;
@@ -1540,14 +1525,14 @@
vreg->optimum = REGULATOR_MODE_FAST;
/* Set pull down enable based on platform data. */
- rc = pm8058_vreg_write(chip, vreg->ctrl_addr,
+ rc = pm8058_vreg_write(vreg, vreg->ctrl_addr,
(vreg->pdata->pull_down_enable ? LDO_PULL_DOWN_ENABLE : 0),
LDO_PULL_DOWN_ENABLE_MASK, &vreg->ctrl_reg);
bail:
return rc;
}
-static int pm8058_init_smps(struct pm8058_chip *chip, struct pm8058_vreg *vreg)
+static int pm8058_init_smps(struct pm8058_vreg *vreg)
{
int rc = 0, i;
u8 bank;
@@ -1555,24 +1540,26 @@
/* Save the current test2 register state. */
for (i = 0; i < SMPS_TEST_BANKS; i++) {
bank = REGULATOR_BANK_SEL(i);
- rc = pm8058_write(chip, vreg->test_addr, &bank, 1);
+ rc = pm8xxx_writeb(vreg->dev->parent, vreg->test_addr, bank);
if (rc)
goto bail;
- rc = pm8058_read(chip, vreg->test_addr, &vreg->test_reg[i],
- 1);
+ rc = pm8xxx_readb(vreg->dev->parent, vreg->test_addr,
+ &vreg->test_reg[i]);
if (rc)
goto bail;
vreg->test_reg[i] |= REGULATOR_BANK_WRITE;
}
/* Save the current clock control register state. */
- rc = pm8058_read(chip, vreg->clk_ctrl_addr, &vreg->clk_ctrl_reg, 1);
+ rc = pm8xxx_readb(vreg->dev->parent, vreg->clk_ctrl_addr,
+ &vreg->clk_ctrl_reg);
if (rc)
goto bail;
/* Save the current sleep control register state. */
- rc = pm8058_read(chip, vreg->sleep_ctrl_addr, &vreg->sleep_ctrl_reg, 1);
+ rc = pm8xxx_readb(vreg->dev->parent, vreg->sleep_ctrl_addr,
+ &vreg->sleep_ctrl_reg);
if (rc)
goto bail;
@@ -1585,7 +1572,7 @@
vreg->optimum = REGULATOR_MODE_FAST;
/* Set advanced mode pull down enable based on platform data. */
- rc = pm8058_vreg_write(chip, vreg->test_addr,
+ rc = pm8058_vreg_write(vreg, vreg->test_addr,
(vreg->pdata->pull_down_enable
? SMPS_ADVANCED_PULL_DOWN_ENABLE : 0)
| REGULATOR_BANK_SEL(6) | REGULATOR_BANK_WRITE,
@@ -1596,7 +1583,7 @@
if (!SMPS_IN_ADVANCED_MODE(vreg)) {
/* Set legacy mode pull down enable based on platform data. */
- rc = pm8058_vreg_write(chip, vreg->ctrl_addr,
+ rc = pm8058_vreg_write(vreg, vreg->ctrl_addr,
(vreg->pdata->pull_down_enable
? SMPS_LEGACY_PULL_DOWN_ENABLE : 0),
SMPS_LEGACY_PULL_DOWN_ENABLE, &vreg->ctrl_reg);
@@ -1608,26 +1595,27 @@
return rc;
}
-static int pm8058_init_lvs(struct pm8058_chip *chip, struct pm8058_vreg *vreg)
+static int pm8058_init_lvs(struct pm8058_vreg *vreg)
{
int rc = 0;
vreg->optimum = REGULATOR_MODE_FAST;
/* Set pull down enable based on platform data. */
- rc = pm8058_vreg_write(chip, vreg->ctrl_addr,
+ rc = pm8058_vreg_write(vreg, vreg->ctrl_addr,
(vreg->pdata->pull_down_enable
? LVS_PULL_DOWN_ENABLE : LVS_PULL_DOWN_DISABLE),
LVS_PULL_DOWN_ENABLE_MASK, &vreg->ctrl_reg);
return rc;
}
-static int pm8058_init_ncp(struct pm8058_chip *chip, struct pm8058_vreg *vreg)
+static int pm8058_init_ncp(struct pm8058_vreg *vreg)
{
int rc = 0;
/* Save the current test1 register state. */
- rc = pm8058_read(chip, vreg->test_addr, &vreg->test_reg[0], 1);
+ rc = pm8xxx_readb(vreg->dev->parent, vreg->test_addr,
+ &vreg->test_reg[0]);
if (rc)
goto bail;
@@ -1637,8 +1625,7 @@
return rc;
}
-static int pm8058_init_regulator(struct pm8058_chip *chip,
- struct pm8058_vreg *vreg)
+static int pm8058_init_regulator(struct pm8058_vreg *vreg)
{
static int master_enable_inited;
int rc = 0;
@@ -1646,28 +1633,28 @@
vreg->mode_initialized = 0;
if (!master_enable_inited) {
- rc = pm8058_master_enable_init(chip);
+ rc = pm8058_master_enable_init(vreg);
if (!rc)
master_enable_inited = 1;
}
/* save the current control register state */
- rc = pm8058_read(chip, vreg->ctrl_addr, &vreg->ctrl_reg, 1);
+ rc = pm8xxx_readb(vreg->dev->parent, vreg->ctrl_addr, &vreg->ctrl_reg);
if (rc)
goto bail;
switch (vreg->type) {
case REGULATOR_TYPE_LDO:
- rc = pm8058_init_ldo(chip, vreg);
+ rc = pm8058_init_ldo(vreg);
break;
case REGULATOR_TYPE_SMPS:
- rc = pm8058_init_smps(chip, vreg);
+ rc = pm8058_init_smps(vreg);
break;
case REGULATOR_TYPE_LVS:
- rc = pm8058_init_lvs(chip, vreg);
+ rc = pm8058_init_lvs(vreg);
break;
case REGULATOR_TYPE_NCP:
- rc = pm8058_init_ncp(chip, vreg);
+ rc = pm8058_init_ncp(vreg);
break;
}
@@ -1681,7 +1668,6 @@
static int __devinit pm8058_vreg_probe(struct platform_device *pdev)
{
struct regulator_desc *rdesc;
- struct pm8058_chip *chip;
struct pm8058_vreg *vreg;
const char *reg_name = NULL;
int rc = 0;
@@ -1690,13 +1676,13 @@
return -EINVAL;
if (pdev->id >= 0 && pdev->id < PM8058_VREG_MAX) {
- chip = dev_get_drvdata(pdev->dev.parent);
rdesc = &pm8058_vreg_descrip[pdev->id];
vreg = &pm8058_vreg[pdev->id];
vreg->pdata = pdev->dev.platform_data;
reg_name = pm8058_vreg_descrip[pdev->id].name;
+ vreg->dev = &pdev->dev;
- rc = pm8058_init_regulator(chip, vreg);
+ rc = pm8058_init_regulator(vreg);
if (rc)
goto bail;
@@ -1705,7 +1691,6 @@
vreg->pdata->init_data.constraints.valid_modes_mask
&= ~(REGULATOR_MODE_NORMAL | REGULATOR_MODE_IDLE);
- platform_set_drvdata(pdev, chip);
vreg->rdev = regulator_register(rdesc, &pdev->dev,
&vreg->pdata->init_data, vreg);
if (IS_ERR(vreg->rdev)) {
diff --git a/drivers/slimbus/slim-msm-ctrl.c b/drivers/slimbus/slim-msm-ctrl.c
index 1e4302b..6aa111c 100644
--- a/drivers/slimbus/slim-msm-ctrl.c
+++ b/drivers/slimbus/slim-msm-ctrl.c
@@ -21,6 +21,7 @@
#include <linux/delay.h>
#include <linux/kthread.h>
#include <linux/clk.h>
+#include <linux/pm_runtime.h>
#include <mach/sps.h>
/* Per spec.max 40 bytes per received message */
@@ -44,6 +45,7 @@
#define MSM_SLIM_PERF_SUMM_THRESHOLD 0x8000
#define MSM_SLIM_NCHANS 32
#define MSM_SLIM_NPORTS 24
+#define MSM_SLIM_AUTOSUSPEND MSEC_PER_SEC
/*
* Need enough descriptors to receive present messages from slaves
@@ -80,6 +82,7 @@
#define QC_DEVID_SAT1 0x3
#define QC_DEVID_SAT2 0x4
#define QC_DEVID_PGD 0x5
+#define QC_MSM_DEVS 5
/* Component registers */
enum comp_reg {
@@ -184,6 +187,12 @@
REF_CLK_GEAR = 15,
};
+enum msm_ctrl_state {
+ MSM_CTRL_AWAKE,
+ MSM_CTRL_SLEEPING,
+ MSM_CTRL_ASLEEP,
+};
+
struct msm_slim_sps_bam {
u32 hdl;
void __iomem *base;
@@ -226,10 +235,11 @@
struct mutex tx_lock;
u8 pgdla;
bool use_rx_msgqs;
- int suspended;
int pipe_b;
struct completion reconf;
bool reconf_busy;
+ bool chan_active;
+ enum msm_ctrl_state state;
};
struct msm_slim_sat {
@@ -241,6 +251,8 @@
u16 *satch;
u8 nsatch;
bool sent_capability;
+ bool pending_reconf;
+ bool pending_capability;
int shead;
int stail;
spinlock_t lock;
@@ -322,6 +334,16 @@
return false;
}
+static void msm_slim_get_ctrl(struct msm_slim_ctrl *dev)
+{
+ pm_runtime_get_sync(dev->dev);
+}
+static void msm_slim_put_ctrl(struct msm_slim_ctrl *dev)
+{
+ pm_runtime_mark_last_busy(dev->dev);
+ pm_runtime_put(dev->dev);
+}
+
static irqreturn_t msm_slim_interrupt(int irq, void *d)
{
struct msm_slim_ctrl *dev = d;
@@ -450,6 +472,10 @@
* before exiting ISR
*/
mb();
+ if (dev->ctrl.sched.usedslots == 0 && dev->chan_active) {
+ dev->chan_active = false;
+ msm_slim_put_ctrl(dev);
+ }
complete(&dev->reconf);
}
pstat = readl_relaxed(dev->base + PGD_PORT_INT_ST_EEn + (16 * dev->ee));
@@ -649,17 +675,37 @@
u8 *puc;
int timeout;
u8 la = txn->la;
+ u8 mc = (u8)(txn->mc & 0xFF);
+ /*
+ * Voting for runtime PM: Slimbus has 2 possible use cases:
+ * 1. messaging
+ * 2. Data channels
+ * Messaging case goes through messaging slots and data channels
+ * use their own slots
+ * This "get" votes for messaging bandwidth
+ */
+ if (!(txn->mc & SLIM_MSG_CLK_PAUSE_SEQ_FLG))
+ msm_slim_get_ctrl(dev);
mutex_lock(&dev->tx_lock);
+ if (dev->state == MSM_CTRL_ASLEEP) {
+ dev_err(dev->dev, "runtime or system PM suspended state");
+ mutex_unlock(&dev->tx_lock);
+ if (!(txn->mc & SLIM_MSG_CLK_PAUSE_SEQ_FLG))
+ msm_slim_put_ctrl(dev);
+ return -EBUSY;
+ }
if (txn->mt == SLIM_MSG_MT_CORE &&
- txn->mc == SLIM_MSG_MC_BEGIN_RECONFIGURATION &&
- dev->reconf_busy) {
+ mc == SLIM_MSG_MC_BEGIN_RECONFIGURATION) {
+ if (dev->reconf_busy) {
wait_for_completion(&dev->reconf);
dev->reconf_busy = false;
- }
- if (dev->suspended) {
- dev_err(dev->dev, "No transaction in suspended state");
- mutex_unlock(&dev->tx_lock);
- return -EBUSY;
+ }
+ /* This "get" votes for data channels */
+ if (dev->ctrl.sched.usedslots != 0 &&
+ !dev->chan_active) {
+ dev->chan_active = true;
+ msm_slim_get_ctrl(dev);
+ }
}
txn->rl--;
pbuf = msm_get_msg_buf(ctrl, txn->rl);
@@ -668,19 +714,19 @@
if (txn->dt == SLIM_MSG_DEST_ENUMADDR) {
mutex_unlock(&dev->tx_lock);
+ if (!(txn->mc & SLIM_MSG_CLK_PAUSE_SEQ_FLG))
+ msm_slim_put_ctrl(dev);
return -EPROTONOSUPPORT;
}
if (txn->mt == SLIM_MSG_MT_CORE && txn->la == 0xFF &&
- (txn->mc == SLIM_MSG_MC_CONNECT_SOURCE ||
- txn->mc == SLIM_MSG_MC_CONNECT_SINK ||
- txn->mc == SLIM_MSG_MC_DISCONNECT_PORT))
+ (mc == SLIM_MSG_MC_CONNECT_SOURCE ||
+ mc == SLIM_MSG_MC_CONNECT_SINK ||
+ mc == SLIM_MSG_MC_DISCONNECT_PORT))
la = dev->pgdla;
if (txn->dt == SLIM_MSG_DEST_LOGICALADDR)
- *pbuf = SLIM_MSG_ASM_FIRST_WORD(txn->rl, txn->mt, txn->mc,
- 0, la);
+ *pbuf = SLIM_MSG_ASM_FIRST_WORD(txn->rl, txn->mt, mc, 0, la);
else
- *pbuf = SLIM_MSG_ASM_FIRST_WORD(txn->rl, txn->mt, txn->mc,
- 1, la);
+ *pbuf = SLIM_MSG_ASM_FIRST_WORD(txn->rl, txn->mt, mc, 1, la);
if (txn->dt == SLIM_MSG_DEST_LOGICALADDR)
puc = ((u8 *)pbuf) + 3;
else
@@ -688,20 +734,20 @@
if (txn->rbuf)
*(puc++) = txn->tid;
if ((txn->mt == SLIM_MSG_MT_CORE) &&
- ((txn->mc >= SLIM_MSG_MC_REQUEST_INFORMATION &&
- txn->mc <= SLIM_MSG_MC_REPORT_INFORMATION) ||
- (txn->mc >= SLIM_MSG_MC_REQUEST_VALUE &&
- txn->mc <= SLIM_MSG_MC_CHANGE_VALUE))) {
+ ((mc >= SLIM_MSG_MC_REQUEST_INFORMATION &&
+ mc <= SLIM_MSG_MC_REPORT_INFORMATION) ||
+ (mc >= SLIM_MSG_MC_REQUEST_VALUE &&
+ mc <= SLIM_MSG_MC_CHANGE_VALUE))) {
*(puc++) = (txn->ec & 0xFF);
*(puc++) = (txn->ec >> 8)&0xFF;
}
if (txn->wbuf)
memcpy(puc, txn->wbuf, txn->len);
if (txn->mt == SLIM_MSG_MT_CORE && txn->la == 0xFF &&
- (txn->mc == SLIM_MSG_MC_CONNECT_SOURCE ||
- txn->mc == SLIM_MSG_MC_CONNECT_SINK ||
- txn->mc == SLIM_MSG_MC_DISCONNECT_PORT)) {
- if (txn->mc != SLIM_MSG_MC_DISCONNECT_PORT)
+ (mc == SLIM_MSG_MC_CONNECT_SOURCE ||
+ mc == SLIM_MSG_MC_CONNECT_SINK ||
+ mc == SLIM_MSG_MC_DISCONNECT_PORT)) {
+ if (mc != SLIM_MSG_MC_DISCONNECT_PORT)
dev->err = msm_slim_connect_pipe_port(dev, *puc);
else {
struct msm_slim_endp *endpoint = &dev->pipes[*puc];
@@ -715,25 +761,49 @@
*/
dev->pipes[*puc].connected = false;
mutex_unlock(&dev->tx_lock);
+ msm_slim_put_ctrl(dev);
return 0;
}
if (dev->err) {
dev_err(dev->dev, "pipe-port connect err:%d", dev->err);
mutex_unlock(&dev->tx_lock);
+ msm_slim_put_ctrl(dev);
return dev->err;
}
*(puc) = *(puc) + dev->pipe_b;
}
if (txn->mt == SLIM_MSG_MT_CORE &&
- txn->mc == SLIM_MSG_MC_BEGIN_RECONFIGURATION)
+ mc == SLIM_MSG_MC_BEGIN_RECONFIGURATION)
dev->reconf_busy = true;
dev->wr_comp = &done;
msm_send_msg_buf(ctrl, pbuf, txn->rl);
timeout = wait_for_completion_timeout(&done, HZ);
+
+ if ((txn->mc == (SLIM_MSG_MC_RECONFIGURE_NOW |
+ SLIM_MSG_CLK_PAUSE_SEQ_FLG)) && timeout) {
+ timeout = wait_for_completion_timeout(&dev->reconf, HZ);
+ dev->reconf_busy = false;
+ if (timeout) {
+ clk_disable(dev->rclk);
+ disable_irq(dev->irq);
+ }
+ }
+ if ((txn->mc == (SLIM_MSG_MC_RECONFIGURE_NOW |
+ SLIM_MSG_CLK_PAUSE_SEQ_FLG)) && !timeout) {
+ dev->reconf_busy = false;
+ dev_err(dev->dev, "clock pause failed");
+ mutex_unlock(&dev->tx_lock);
+ return -ETIMEDOUT;
+ }
+
+ mutex_unlock(&dev->tx_lock);
+ if (!txn->rbuf && !(txn->mc & SLIM_MSG_CLK_PAUSE_SEQ_FLG))
+ msm_slim_put_ctrl(dev);
+
if (!timeout)
dev_err(dev->dev, "TX timed out:MC:0x%x,mt:0x%x", txn->mc,
txn->mt);
- mutex_unlock(&dev->tx_lock);
+
return timeout ? dev->err : -ETIMEDOUT;
}
@@ -763,6 +833,7 @@
static int msm_clk_pause_wakeup(struct slim_controller *ctrl)
{
struct msm_slim_ctrl *dev = slim_get_ctrldata(ctrl);
+ enable_irq(dev->irq);
clk_enable(dev->rclk);
writel_relaxed(1, dev->base + FRM_WAKEUP);
/* Make sure framer wakeup write goes through before exiting function */
@@ -921,6 +992,9 @@
e_addr[1] == QC_DEVID_PGD &&
e_addr[2] != QC_CHIPID_SL)
dev->pgdla = laddr;
+ if (!ret && !pm_runtime_enabled(dev->dev) &&
+ laddr == (QC_MSM_DEVS - 1))
+ pm_runtime_enable(dev->dev);
} else if (mc == SLIM_MSG_MC_REPLY_INFORMATION ||
mc == SLIM_MSG_MC_REPLY_VALUE) {
@@ -928,6 +1002,7 @@
dev_dbg(dev->dev, "tid:%d, len:%d\n", tid, len - 4);
slim_msg_response(&dev->ctrl, &buf[4], tid,
len - 4);
+ msm_slim_put_ctrl(dev);
} else if (mc == SLIM_MSG_MC_REPORT_INFORMATION) {
u8 l_addr = buf[2];
u16 ele = (u16)buf[4] << 4;
@@ -980,11 +1055,26 @@
for (i = 0; i < 6; i++)
e_addr[i] = buf[7-i];
+ if (pm_runtime_enabled(dev->dev)) {
+ msm_slim_get_ctrl(dev);
+ sat->pending_capability = true;
+ }
slim_assign_laddr(&dev->ctrl, e_addr, 6, &laddr);
sat->satcl.laddr = laddr;
- }
+ } else if (mt != SLIM_MSG_MT_CORE &&
+ mc != SLIM_MSG_MC_REPORT_PRESENT)
+ msm_slim_get_ctrl(dev);
switch (mc) {
case SLIM_MSG_MC_REPORT_PRESENT:
+ /* Remove runtime_pm vote once satellite acks */
+ if (mt != SLIM_MSG_MT_CORE) {
+ if (pm_runtime_enabled(dev->dev) &&
+ sat->pending_capability) {
+ msm_slim_put_ctrl(dev);
+ sat->pending_capability = false;
+ }
+ continue;
+ }
/* send a Manager capability msg */
if (sat->sent_capability)
continue;
@@ -1040,11 +1130,19 @@
"SAT define_ch returned:%d",
ret);
}
+ if (!sat->pending_reconf) {
+ msm_slim_get_ctrl(dev);
+ sat->pending_reconf = true;
+ }
break;
case SLIM_USR_MC_RECONFIG_NOW:
tid = buf[3];
gen_ack = true;
ret = slim_reconfigure_now(&sat->satcl);
+ if (sat->pending_reconf) {
+ msm_slim_put_ctrl(dev);
+ sat->pending_reconf = false;
+ }
break;
case SLIM_USR_MC_REQ_BW:
/* what we get is in SLOTS */
@@ -1085,8 +1183,12 @@
default:
break;
}
- if (!gen_ack)
+ if (!gen_ack) {
+ if (mc != SLIM_MSG_MC_REPORT_PRESENT)
+ msm_slim_put_ctrl(dev);
continue;
+ }
+
wbuf[0] = tid;
if (!ret)
wbuf[1] = MSM_SAT_SUCCSS;
@@ -1099,6 +1201,7 @@
txn.wbuf = wbuf;
txn.mt = SLIM_MSG_MT_SRC_REFERRED_USER;
msm_xfer_msg(&dev->ctrl, &txn);
+ msm_slim_put_ctrl(dev);
}
}
@@ -1606,11 +1709,7 @@
dev->framer.rootfreq / SLIM_CL_PER_SUPERFRAME_DIV8;
dev->ctrl.a_framer = &dev->framer;
dev->ctrl.clkgear = SLIM_MAX_CLK_GEAR;
- ret = slim_add_numbered_controller(&dev->ctrl);
- if (ret) {
- dev_err(dev->dev, "error adding controller\n");
- goto err_ctrl_failed;
- }
+ dev->ctrl.dev.parent = &pdev->dev;
ret = request_irq(dev->irq, msm_slim_interrupt, IRQF_TRIGGER_HIGH,
"msm_slim_irq", dev);
@@ -1702,14 +1801,24 @@
* function
*/
mb();
+ pm_runtime_use_autosuspend(&pdev->dev);
+ pm_runtime_set_autosuspend_delay(&pdev->dev, MSM_SLIM_AUTOSUSPEND);
+ pm_runtime_set_active(&pdev->dev);
+
+ ret = slim_add_numbered_controller(&dev->ctrl);
+ if (ret) {
+ dev_err(dev->dev, "error adding controller\n");
+ goto err_ctrl_failed;
+ }
dev_dbg(dev->dev, "MSM SB controller is up!\n");
return 0;
+err_ctrl_failed:
+ writel_relaxed(0, dev->base + COMP_CFG);
+ kfree(dev->satd);
err_sat_failed:
free_irq(dev->irq, dev);
err_request_irq_failed:
- slim_del_controller(&dev->ctrl);
-err_ctrl_failed:
clk_disable(dev->rclk);
clk_put(dev->rclk);
err_clk_get_failed:
@@ -1735,12 +1844,13 @@
struct resource *slew_mem = dev->slew_mem;
struct msm_slim_sat *sat = dev->satd;
slim_remove_device(&sat->satcl);
+ pm_runtime_disable(&pdev->dev);
+ pm_runtime_set_suspended(&pdev->dev);
kfree(sat->satch);
destroy_workqueue(sat->wq);
kfree(sat);
free_irq(dev->irq, dev);
slim_del_controller(&dev->ctrl);
- clk_disable(dev->rclk);
clk_put(dev->rclk);
msm_slim_sps_exit(dev);
kthread_stop(dev->rx_msgq_thread);
@@ -1760,79 +1870,89 @@
return 0;
}
-#ifdef CONFIG_PM
-static int msm_slim_suspend(struct device *device)
+#ifdef CONFIG_PM_RUNTIME
+static int msm_slim_runtime_idle(struct device *device)
+{
+ dev_dbg(device, "pm_runtime: idle...\n");
+ pm_request_autosuspend(device);
+ return -EAGAIN;
+}
+#endif
+
+/*
+ * If PM_RUNTIME is not defined, these 2 functions become helper
+ * functions to be called from system suspend/resume. So they are not
+ * inside ifdef CONFIG_PM_RUNTIME
+ */
+static int msm_slim_runtime_suspend(struct device *device)
{
struct platform_device *pdev = to_platform_device(device);
struct msm_slim_ctrl *dev = platform_get_drvdata(pdev);
- int ret = slim_ctrl_clk_pause(&dev->ctrl, false, SLIM_CLK_UNSPECIFIED);
- /* Make sure clock pause goes through */
- mutex_lock(&dev->tx_lock);
- if (!ret && dev->reconf_busy) {
- wait_for_completion(&dev->reconf);
- dev->reconf_busy = false;
+ int ret;
+ dev_dbg(device, "pm_runtime: suspending...\n");
+ dev->state = MSM_CTRL_SLEEPING;
+ ret = slim_ctrl_clk_pause(&dev->ctrl, false, SLIM_CLK_UNSPECIFIED);
+ if (ret)
+ dev->state = MSM_CTRL_AWAKE;
+ else
+ dev->state = MSM_CTRL_ASLEEP;
+ return ret;
+}
+
+static int msm_slim_runtime_resume(struct device *device)
+{
+ struct platform_device *pdev = to_platform_device(device);
+ struct msm_slim_ctrl *dev = platform_get_drvdata(pdev);
+ int ret = 0;
+ dev_dbg(device, "pm_runtime: resuming...\n");
+ if (dev->state == MSM_CTRL_ASLEEP)
+ ret = slim_ctrl_clk_pause(&dev->ctrl, true, 0);
+ if (ret)
+ dev->state = MSM_CTRL_ASLEEP;
+ else
+ dev->state = MSM_CTRL_AWAKE;
+ return ret;
+}
+
+#ifdef CONFIG_PM_SLEEP
+static int msm_slim_suspend(struct device *dev)
+{
+ int ret = 0;
+ if (!pm_runtime_enabled(dev) || !pm_runtime_suspended(dev)) {
+ dev_dbg(dev, "system suspend");
+ ret = msm_slim_runtime_suspend(dev);
}
- mutex_unlock(&dev->tx_lock);
- if (!ret) {
- clk_disable(dev->rclk);
- disable_irq(dev->irq);
- dev->suspended = 1;
- } else if (ret == -EBUSY) {
+ if (ret == -EBUSY) {
/*
- * If the clock pause failed due to active channels, there is
- * a possibility that some audio stream is active during suspend
- * We dont want to return suspend failure in that case so that
- * display and relevant components can still go to suspend.
- * If there is some other error, then it should be passed-on
- * to system level suspend
- */
+ * If the clock pause failed due to active channels, there is
+ * a possibility that some audio stream is active during suspend
+ * We dont want to return suspend failure in that case so that
+ * display and relevant components can still go to suspend.
+ * If there is some other error, then it should be passed-on
+ * to system level suspend
+ */
ret = 0;
}
return ret;
}
-static int msm_slim_resume(struct device *device)
+static int msm_slim_resume(struct device *dev)
{
- struct platform_device *pdev = to_platform_device(device);
- struct msm_slim_ctrl *dev = platform_get_drvdata(pdev);
- mutex_lock(&dev->tx_lock);
- if (dev->suspended) {
- dev->suspended = 0;
- mutex_unlock(&dev->tx_lock);
- enable_irq(dev->irq);
- return slim_ctrl_clk_pause(&dev->ctrl, true, 0);
+ /* If runtime_pm is enabled, this resume shouldn't do anything */
+ if (!pm_runtime_enabled(dev) || !pm_runtime_suspended(dev)) {
+ int ret;
+ dev_dbg(dev, "system resume");
+ ret = msm_slim_runtime_resume(dev);
+ if (!ret) {
+ pm_runtime_mark_last_busy(dev);
+ pm_request_autosuspend(dev);
+ }
+ return ret;
+
}
- mutex_unlock(&dev->tx_lock);
return 0;
}
-#else
-#define msm_slim_suspend NULL
-#define msm_slim_resume NULL
-#endif /* CONFIG_PM */
-
-#ifdef CONFIG_PM_RUNTIME
-static int msm_slim_runtime_idle(struct device *dev)
-{
- dev_dbg(dev, "pm_runtime: idle...\n");
- return 0;
-}
-
-static int msm_slim_runtime_suspend(struct device *dev)
-{
- dev_dbg(dev, "pm_runtime: suspending...\n");
- return 0;
-}
-
-static int msm_slim_runtime_resume(struct device *dev)
-{
- dev_dbg(dev, "pm_runtime: resuming...\n");
- return 0;
-}
-#else
-#define msm_slim_runtime_idle NULL
-#define msm_slim_runtime_suspend NULL
-#define msm_slim_runtime_resume NULL
-#endif
+#endif /* CONFIG_PM_SLEEP */
static const struct dev_pm_ops msm_slim_dev_pm_ops = {
SET_SYSTEM_SLEEP_PM_OPS(
diff --git a/drivers/slimbus/slimbus.c b/drivers/slimbus/slimbus.c
index 3b79129..d8003bf 100644
--- a/drivers/slimbus/slimbus.c
+++ b/drivers/slimbus/slimbus.c
@@ -377,7 +377,6 @@
dev_set_name(&ctrl->dev, "sb-%d", ctrl->nr);
ctrl->dev.bus = &slimbus_type;
ctrl->dev.type = &slim_ctrl_type;
- ctrl->dev.parent = &slimbus_dev;
ctrl->num_dev = 0;
if (!ctrl->min_cg)
ctrl->min_cg = SLIM_MIN_CLK_GEAR;
@@ -581,7 +580,7 @@
}
EXPORT_SYMBOL_GPL(slim_msg_response);
-static int slim_processtxn(struct slim_controller *ctrl, u8 dt, u8 mc, u16 ec,
+static int slim_processtxn(struct slim_controller *ctrl, u8 dt, u16 mc, u16 ec,
u8 mt, u8 *rbuf, const u8 *wbuf, u8 len, u8 mlen,
struct completion *comp, u8 la, u8 *tid)
{
@@ -870,7 +869,7 @@
* All controllers may not support broadcast
*/
int slim_xfer_msg(struct slim_controller *ctrl, struct slim_device *sbdev,
- struct slim_ele_access *msg, u8 mc, u8 *rbuf,
+ struct slim_ele_access *msg, u16 mc, u8 *rbuf,
const u8 *wbuf, u8 len)
{
DECLARE_COMPLETION_ONSTACK(complete);
@@ -892,10 +891,6 @@
cur = slim_slicecodefromsize(sl);
ec = ((sl | (1 << 3)) | ((msg->start_offset & 0xFFF) << 4));
- ret = slim_ctrl_clk_pause(ctrl, true, 0);
- if (ret)
- return ret;
-
if (wbuf)
mlen += len;
if (rbuf) {
@@ -1069,7 +1064,7 @@
enum slim_port_flow flow)
{
int ret;
- u8 mc;
+ u16 mc;
u8 buf[2];
u32 la = SLIM_HDL_TO_LA(ph);
u8 pn = (u8)SLIM_HDL_TO_PORT(ph);
@@ -1093,7 +1088,7 @@
static int disconnect_port_ch(struct slim_controller *ctrl, u32 ph)
{
int ret;
- u8 mc;
+ u16 mc;
u32 la = SLIM_HDL_TO_LA(ph);
u8 pn = (u8)SLIM_HDL_TO_PORT(ph);
@@ -1127,10 +1122,6 @@
u8 chan = (u8)(chanh & 0xFF);
struct slim_ich *slc = &ctrl->chans[chan];
- ret = slim_ctrl_clk_pause(ctrl, true, 0);
- if (ret)
- return ret;
-
mutex_lock(&ctrl->m_ctrl);
/* Make sure the channel is not already pending reconf. or active */
if (slc->state >= SLIM_CH_PENDING_ACTIVE) {
@@ -1193,11 +1184,8 @@
int slim_disconnect_ports(struct slim_device *sb, u32 *ph, int nph)
{
struct slim_controller *ctrl = sb->ctrl;
- int i, ret;
+ int i;
- ret = slim_ctrl_clk_pause(ctrl, true, 0);
- if (ret)
- return ret;
mutex_lock(&ctrl->m_ctrl);
for (i = 0; i < nph; i++)
@@ -2389,10 +2377,6 @@
u32 segdist;
struct slim_pending_ch *pch;
- ret = slim_ctrl_clk_pause(ctrl, true, 0);
- if (ret)
- return ret;
-
mutex_lock(&ctrl->sched.m_reconf);
mutex_lock(&ctrl->m_ctrl);
ctrl->sched.pending_msgsl += sb->pending_msgsl - sb->cur_msgsl;
@@ -2785,20 +2769,20 @@
}
ret = slim_processtxn(ctrl, SLIM_MSG_DEST_BROADCAST,
- SLIM_MSG_MC_BEGIN_RECONFIGURATION, 0, SLIM_MSG_MT_CORE,
- NULL, NULL, 0, 3, NULL, 0, NULL);
- if (ret)
- goto clk_pause_ret;
-
- ret = slim_processtxn(ctrl, SLIM_MSG_DEST_BROADCAST,
- SLIM_MSG_MC_NEXT_PAUSE_CLOCK, 0, SLIM_MSG_MT_CORE,
- NULL, &restart, 1, 4, NULL, 0, NULL);
+ SLIM_MSG_CLK_PAUSE_SEQ_FLG | SLIM_MSG_MC_BEGIN_RECONFIGURATION,
+ 0, SLIM_MSG_MT_CORE, NULL, NULL, 0, 3, NULL, 0, NULL);
if (ret)
goto clk_pause_ret;
ret = slim_processtxn(ctrl, SLIM_MSG_DEST_BROADCAST,
- SLIM_MSG_MC_RECONFIGURE_NOW, 0, SLIM_MSG_MT_CORE,
- NULL, NULL, 0, 3, NULL, 0, NULL);
+ SLIM_MSG_CLK_PAUSE_SEQ_FLG | SLIM_MSG_MC_NEXT_PAUSE_CLOCK, 0,
+ SLIM_MSG_MT_CORE, NULL, &restart, 1, 4, NULL, 0, NULL);
+ if (ret)
+ goto clk_pause_ret;
+
+ ret = slim_processtxn(ctrl, SLIM_MSG_DEST_BROADCAST,
+ SLIM_MSG_CLK_PAUSE_SEQ_FLG | SLIM_MSG_MC_RECONFIGURE_NOW, 0,
+ SLIM_MSG_MT_CORE, NULL, NULL, 0, 3, NULL, 0, NULL);
if (ret)
goto clk_pause_ret;
diff --git a/drivers/thermal/pm8xxx-tm.c b/drivers/thermal/pm8xxx-tm.c
index d9f9c9e..1d518e3 100644
--- a/drivers/thermal/pm8xxx-tm.c
+++ b/drivers/thermal/pm8xxx-tm.c
@@ -30,6 +30,7 @@
#include <linux/mfd/pm8xxx/tm.h>
#include <linux/completion.h>
#include <linux/mfd/pm8xxx/pm8921-adc.h>
+#include <linux/msm_adc.h>
/* Register TEMP_ALARM_CTRL bits */
#define TEMP_ALARM_CTRL_ST3_SD 0x80
@@ -226,6 +227,43 @@
return 0;
}
+static int pm8xxx_tz_get_temp_pm8058_adc(struct thermal_zone_device *thermal,
+ unsigned long *temp)
+{
+ struct pm8xxx_tm_chip *chip = thermal->devdata;
+ DECLARE_COMPLETION_ONSTACK(wait);
+ struct adc_chan_result adc_result = {
+ .physical = 0lu,
+ };
+ int rc;
+
+ if (!chip || !temp)
+ return -EINVAL;
+
+ *temp = chip->temp;
+
+ rc = adc_channel_request_conv(chip->adc_handle, &wait);
+ if (rc < 0) {
+ pr_err("%s: adc_channel_request_conv() failed, rc = %d\n",
+ __func__, rc);
+ return rc;
+ }
+
+ wait_for_completion(&wait);
+
+ rc = adc_channel_read_result(chip->adc_handle, &adc_result);
+ if (rc < 0) {
+ pr_err("%s: adc_channel_read_result() failed, rc = %d\n",
+ __func__, rc);
+ return rc;
+ }
+
+ *temp = adc_result.physical;
+ chip->temp = adc_result.physical;
+
+ return 0;
+}
+
static int pm8xxx_tz_get_temp_pm8921_adc(struct thermal_zone_device *thermal,
unsigned long *temp)
{
@@ -372,6 +410,15 @@
.get_crit_temp = pm8xxx_tz_get_crit_temp,
};
+static struct thermal_zone_device_ops pm8xxx_thermal_zone_ops_pm8058_adc = {
+ .get_temp = pm8xxx_tz_get_temp_pm8058_adc,
+ .get_mode = pm8xxx_tz_get_mode,
+ .set_mode = pm8xxx_tz_set_mode,
+ .get_trip_type = pm8xxx_tz_get_trip_type,
+ .get_trip_temp = pm8xxx_tz_get_trip_temp,
+ .get_crit_temp = pm8xxx_tz_get_crit_temp,
+};
+
static void pm8xxx_tm_work(struct work_struct *work)
{
struct pm8xxx_tm_chip *chip
@@ -465,6 +512,24 @@
return rc;
}
+static int pm8xxx_init_adc(struct pm8xxx_tm_chip *chip, bool enable)
+{
+ int rc = 0;
+
+ if (chip->cdata.adc_type == PM8XXX_TM_ADC_PM8058_ADC) {
+ if (enable) {
+ rc = adc_channel_open(chip->cdata.adc_channel,
+ &(chip->adc_handle));
+ if (rc < 0)
+ pr_err("adc_channel_open() failed.\n");
+ } else {
+ adc_channel_close(chip->adc_handle);
+ }
+ }
+
+ return rc;
+}
+
static int __devinit pm8xxx_tm_probe(struct platform_device *pdev)
{
const struct pm8xxx_tm_core_data *cdata = pdev->dev.platform_data;
@@ -505,18 +570,27 @@
goto err_free_chip;
}
+ rc = pm8xxx_init_adc(chip, true);
+ if (rc < 0) {
+ pr_err("Unable to initialize adc\n");
+ goto err_free_chip;
+ }
+
/* Select proper thermal zone ops functions based on ADC type. */
if (chip->cdata.adc_type == PM8XXX_TM_ADC_PM8921_ADC)
tz_ops = &pm8xxx_thermal_zone_ops_pm8921_adc;
+ else if (chip->cdata.adc_type == PM8XXX_TM_ADC_PM8058_ADC)
+ tz_ops = &pm8xxx_thermal_zone_ops_pm8058_adc;
else
tz_ops = &pm8xxx_thermal_zone_ops_no_adc;
chip->tz_dev = thermal_zone_device_register(chip->cdata.tm_name,
TRIP_NUM, chip, tz_ops, 0, 0, 0, 0);
+
if (chip->tz_dev == NULL) {
pr_err("thermal_zone_device_register() failed.\n");
rc = -ENODEV;
- goto err_free_chip;
+ goto err_fail_adc;
}
rc = pm8xxx_tm_init_reg(chip);
@@ -564,6 +638,8 @@
cancel_work_sync(&chip->irq_work);
err_free_tz:
thermal_zone_device_unregister(chip->tz_dev);
+err_fail_adc:
+ pm8xxx_init_adc(chip, false);
err_free_chip:
kfree(chip);
return rc;
@@ -579,6 +655,7 @@
free_irq(chip->overtemp_irq, chip);
free_irq(chip->tempstat_irq, chip);
pm8xxx_tm_shutdown_override(chip, SOFTWARE_OVERRIDE_DISABLED);
+ pm8xxx_init_adc(chip, false);
thermal_zone_device_unregister(chip->tz_dev);
kfree(chip);
}
diff --git a/drivers/usb/gadget/f_diag.c b/drivers/usb/gadget/f_diag.c
index e276be6..ccfd2e3 100644
--- a/drivers/usb/gadget/f_diag.c
+++ b/drivers/usb/gadget/f_diag.c
@@ -512,7 +512,6 @@
struct diag_context *dev = func_to_diag(f);
struct usb_composite_dev *cdev = f->config->cdev;
unsigned long flags;
- struct usb_diag_ch *ch;
int rc = 0;
dev->in_desc = ep_choose(cdev->gadget,
@@ -536,14 +535,9 @@
}
schedule_work(&dev->config_work);
- list_for_each_entry(ch, &usb_diag_ch_list, list) {
- struct diag_context *ctxt;
-
- ctxt = ch->priv_usb;
- ctxt->dpkts_tolaptop = 0;
- ctxt->dpkts_tomodem = 0;
- ctxt->dpkts_tolaptop_pending = 0;
- }
+ dev->dpkts_tolaptop = 0;
+ dev->dpkts_tomodem = 0;
+ dev->dpkts_tolaptop_pending = 0;
spin_lock_irqsave(&dev->lock, flags);
dev->configured = 1;
diff --git a/drivers/usb/gadget/f_rmnet.c b/drivers/usb/gadget/f_rmnet.c
index 6f0fb07..7686bf2 100644
--- a/drivers/usb/gadget/f_rmnet.c
+++ b/drivers/usb/gadget/f_rmnet.c
@@ -487,7 +487,7 @@
}
spin_lock_irqsave(&dev->lock, flags);
- list_add(&cpkt->list, &dev->cpkt_resp_q);
+ list_add_tail(&cpkt->list, &dev->cpkt_resp_q);
spin_unlock_irqrestore(&dev->lock, flags);
frmnet_ctrl_response_available(dev);
diff --git a/drivers/usb/host/ehci-msm-hsic.c b/drivers/usb/host/ehci-msm-hsic.c
index 350f286..ec303b9 100644
--- a/drivers/usb/host/ehci-msm-hsic.c
+++ b/drivers/usb/host/ehci-msm-hsic.c
@@ -400,8 +400,6 @@
dev_err(mehci->dev, "Unable to suspend PHY\n");
msm_hsic_config_gpios(mehci, 0);
msm_hsic_reset(mehci);
- enable_irq(hcd->irq);
- return -ETIMEDOUT;
}
/*
diff --git a/drivers/usb/host/ehci-msm.c b/drivers/usb/host/ehci-msm.c
index 411fa97..f45f257 100644
--- a/drivers/usb/host/ehci-msm.c
+++ b/drivers/usb/host/ehci-msm.c
@@ -177,11 +177,6 @@
}
device_init_wakeup(&pdev->dev, 1);
- /*
- * OTG device parent of HCD takes care of putting
- * hardware into low power mode.
- */
- pm_runtime_no_callbacks(&pdev->dev);
pm_runtime_enable(&pdev->dev);
return 0;
@@ -212,7 +207,31 @@
return 0;
}
-#ifdef CONFIG_PM
+#ifdef CONFIG_PM_RUNTIME
+static int ehci_msm_runtime_idle(struct device *dev)
+{
+ dev_dbg(dev, "ehci runtime idle\n");
+ return 0;
+}
+
+static int ehci_msm_runtime_suspend(struct device *dev)
+{
+ dev_dbg(dev, "ehci runtime suspend\n");
+ /*
+ * Notify OTG about suspend. It takes care of
+ * putting the hardware in LPM.
+ */
+ return otg_set_suspend(otg, 1);
+}
+
+static int ehci_msm_runtime_resume(struct device *dev)
+{
+ dev_dbg(dev, "ehci runtime resume\n");
+ return otg_set_suspend(otg, 0);
+}
+#endif
+
+#ifdef CONFIG_PM_SLEEP
static int ehci_msm_pm_suspend(struct device *dev)
{
struct usb_hcd *hcd = dev_get_drvdata(dev);
@@ -236,7 +255,7 @@
wakeup);
}
- return 0;
+ return otg_set_suspend(otg, 1);
}
static int ehci_msm_pm_resume(struct device *dev)
@@ -250,16 +269,14 @@
ehci_prepare_ports_for_controller_resume(hcd_to_ehci(hcd));
- return 0;
+ return otg_set_suspend(otg, 0);
}
-#else
-#define ehci_msm_pm_suspend NULL
-#define ehci_msm_pm_resume NULL
#endif
static const struct dev_pm_ops ehci_msm_dev_pm_ops = {
- .suspend = ehci_msm_pm_suspend,
- .resume = ehci_msm_pm_resume,
+ SET_SYSTEM_SLEEP_PM_OPS(ehci_msm_pm_suspend, ehci_msm_pm_resume)
+ SET_RUNTIME_PM_OPS(ehci_msm_runtime_suspend, ehci_msm_runtime_resume,
+ ehci_msm_runtime_idle)
};
static struct platform_driver ehci_msm_driver = {
diff --git a/drivers/usb/otg/Kconfig b/drivers/usb/otg/Kconfig
index 71f36f2..8864f32 100644
--- a/drivers/usb/otg/Kconfig
+++ b/drivers/usb/otg/Kconfig
@@ -161,7 +161,7 @@
config USB_MSM_STANDARD_ACA
bool "Support for Standard ACA"
depends on USB_MSM_ACA
- default y
+ default USB_MSM_OTG_72K
help
A Standard ACA has a Standard-A receptacle on the Accessory Port,
and can only be attached to a B-device. RID_A and RID_GND states
diff --git a/drivers/usb/otg/msm72k_otg.c b/drivers/usb/otg/msm72k_otg.c
index fccd357..714099a 100644
--- a/drivers/usb/otg/msm72k_otg.c
+++ b/drivers/usb/otg/msm72k_otg.c
@@ -37,7 +37,13 @@
#define DRIVER_NAME "msm_otg"
static void otg_reset(struct otg_transceiver *xceiv, int phy_reset);
static void msm_otg_set_vbus_state(int online);
-static void msm_otg_set_id_state(int online);
+#ifdef CONFIG_USB_EHCI_MSM_72K
+static void msm_otg_set_id_state(int id);
+#else
+static void msm_otg_set_id_state(int id)
+{
+}
+#endif
struct msm_otg *the_msm_otg;
@@ -45,9 +51,7 @@
{
struct msm_otg *dev = the_msm_otg;
- if (dev->pmic_id_notif_supp)
- return dev->pmic_id_status ? 0 : 1;
- else if (dev->pdata->otg_mode == OTG_ID)
+ if (dev->pdata->otg_mode == OTG_ID)
return (OTGSC_ID & readl(USB_OTGSC)) ? 0 : 1;
else
return !test_bit(ID, &dev->inputs);
@@ -135,24 +139,38 @@
#ifdef CONFIG_USB_EHCI_MSM_72K
static void enable_idgnd(struct msm_otg *dev)
{
+ unsigned temp;
+
/* Do nothing if instead of ID pin, USER controls mode switch */
if (dev->pdata->otg_mode == OTG_USER_CONTROL)
return;
ulpi_write(dev, (1<<4), 0x0E);
ulpi_write(dev, (1<<4), 0x11);
- writel_relaxed(readl_relaxed(USB_OTGSC) | OTGSC_IDIE, USB_OTGSC);
+ ulpi_write(dev, (1<<0), 0x0B);
+ temp = OTGSC_IDIE | OTGSC_IDPU;
+ writel_relaxed(readl_relaxed(USB_OTGSC) | temp, USB_OTGSC);
}
static void disable_idgnd(struct msm_otg *dev)
{
+ unsigned temp;
+
/* Do nothing if instead of ID pin, USER controls mode switch */
if (dev->pdata->otg_mode == OTG_USER_CONTROL)
return;
-
+ temp = OTGSC_IDIE | OTGSC_IDPU;
+ writel_relaxed(readl_relaxed(USB_OTGSC) & ~temp, USB_OTGSC);
ulpi_write(dev, (1<<4), 0x0F);
ulpi_write(dev, (1<<4), 0x12);
- writel_relaxed(readl_relaxed(USB_OTGSC) & ~OTGSC_IDIE, USB_OTGSC);
+ ulpi_write(dev, (1<<0), 0x0C);
+}
+#else
+static void enable_idgnd(struct msm_otg *dev)
+{
+}
+static void disable_idgnd(struct msm_otg *dev)
+{
}
#endif
@@ -224,6 +242,9 @@
#define get_aca_bmaxpower(dev) (dev->b_max_power)
#define set_aca_bmaxpower(dev, power) (dev->b_max_power = power)
#else
+static void set_aca_id_inputs(struct msm_otg *dev)
+{
+}
#define get_aca_bmaxpower(dev) 0
#define set_aca_bmaxpower(dev, power)
#endif
@@ -692,6 +713,31 @@
* 4. peripheral is supported, but, vbus is not routed to pmic
*/
host_bus_suspend = dev->otg.host && is_host();
+
+ /*
+ * Configure the PMIC ID only in case of cable disconnect.
+ * PMIC doesn't generate interrupt for ID_GND to ID_A
+ * transistion. hence use the PHY ID cricuit.
+ */
+ if (dev->pdata->pmic_id_notif_init && !host_bus_suspend &&
+ !test_bit(ID_A, &dev->inputs)) {
+ disable_idgnd(dev);
+ ret = dev->pdata->pmic_id_notif_init(
+ &msm_otg_set_id_state, 1);
+ if (!ret) {
+ dev->pmic_id_notif_supp = 1;
+ if (dev->pdata->pmic_id_irq)
+ dev->id_irq = dev->pdata->pmic_id_irq;
+ } else if (ret == -ENOTSUPP) {
+ pr_debug("%s:USB ID is not routed to pmic",
+ __func__);
+ enable_idgnd(dev);
+ } else {
+ pr_err("%s: pmic_id_ notif_init failed err:%d",
+ __func__, ret);
+ }
+ }
+
if ((dev->otg.gadget && chg_type == USB_CHG_TYPE__WALLCHARGER) ||
host_bus_suspend ||
(dev->otg.host && !dev->pmic_id_notif_supp) ||
@@ -760,7 +806,8 @@
* that there is no harm with this. Till hw folks confirms this
* put regulators in lpm.
*/
- if (!host_bus_suspend && dev->pmic_vbus_notif_supp) {
+ if (!host_bus_suspend && dev->pmic_vbus_notif_supp &&
+ !test_bit(ID_A, &dev->inputs)) {
pr_debug("phy can power collapse: (%d)\n",
can_phy_power_collapse(dev));
if (can_phy_power_collapse(dev) && dev->pdata->ldo_enable) {
@@ -881,9 +928,35 @@
}
phy_resumed:
+ /*
+ * It is observed that BSVIS may get set immediatly
+ * after PHY becomes active upon micro-B cable connect.
+ * But BSVIS might get cleared by below enable_idgnd
+ * function which causes hw to not generate the BSV interrupt.
+ * Hence check for BSV interrupt explictly and schedule the
+ * work.
+ */
+ if (readl_relaxed(USB_OTGSC) & OTGSC_BSVIS) {
+ set_bit(B_SESS_VLD, &dev->inputs);
+ queue_work(dev->wq, &dev->sm_work);
+ }
+ if (dev->pmic_id_notif_supp) {
+ dev->pdata->pmic_id_notif_init(&msm_otg_set_id_state, 0);
+ dev->pmic_id_notif_supp = 0;
+ enable_idgnd(dev);
+ }
+
/* Enable Idabc interrupts as these were disabled before entering LPM */
enable_idabc(dev);
+ /*
+ * There is corner case where host won't be resumed
+ * while transitioning from ID_GND to ID_A. In that
+ * IDGND might have cleared and ID_A might not have updated
+ * yet. Hence update the ACA states explicitly.
+ */
+ set_aca_id_inputs(dev);
+
/* If resume signalling finishes before lpm exit, PCD is not set in
* USBSTS register. Drive resume signal to the downstream device now
* so that host driver can process the upcoming port change interrupt.*/
@@ -996,6 +1069,12 @@
}
udelay(10);
}
+ if (dev->pmic_id_notif_supp) {
+ dev->pdata->pmic_id_notif_init(
+ &msm_otg_set_id_state, 0);
+ dev->pmic_id_notif_supp = 0;
+ enable_idgnd(dev);
+ }
out:
enable_idabc(dev);
enable_irq(dev->irq);
@@ -1119,23 +1198,20 @@
#endif
return 0;
}
-#endif
-void msm_otg_set_id_state(int id)
+static void msm_otg_set_id_state(int id)
{
struct msm_otg *dev = the_msm_otg;
unsigned long flags;
- if (id == dev->pmic_id_status)
+ if (!atomic_read(&dev->in_lpm))
return;
if (id) {
set_bit(ID, &dev->inputs);
- dev->pmic_id_status = 1;
} else {
clear_bit(ID, &dev->inputs);
set_bit(A_BUS_REQ, &dev->inputs);
- dev->pmic_id_status = 0;
}
spin_lock_irqsave(&dev->lock, flags);
if (dev->otg.state != OTG_STATE_UNDEFINED) {
@@ -1144,6 +1220,7 @@
}
spin_unlock_irqrestore(&dev->lock, flags);
}
+#endif
void msm_otg_set_vbus_state(int online)
{
@@ -1973,6 +2050,7 @@
} else if (test_bit(ID_A, &dev->inputs)) {
dev->pdata->vbus_power(USB_PHY_INTEGRATED, 0);
} else if (!test_bit(ID, &dev->inputs)) {
+ msm_otg_set_power(&dev->otg, 0);
dev->pdata->vbus_power(USB_PHY_INTEGRATED, 1);
}
break;
@@ -2687,12 +2765,10 @@
}
}
- if (dev->pdata->pmic_id_notif_init) {
- ret = dev->pdata->pmic_id_notif_init(&msm_otg_set_id_state, 1);
- if (!ret) {
- dev->pmic_id_notif_supp = 1;
- } else if (ret != -ENOTSUPP) {
- pr_err("%s: pmic_id_ notif_init failed err:%d",
+ if (dev->pdata->phy_id_setup_init) {
+ ret = dev->pdata->phy_id_setup_init(1);
+ if (ret) {
+ pr_err("%s: phy_id_setup_init failed err:%d",
__func__, ret);
goto free_pmic_vbus_notif;
}
@@ -2700,8 +2776,6 @@
if (dev->pdata->pmic_vbus_irq)
dev->vbus_on_irq = dev->pdata->pmic_vbus_irq;
- if (dev->pdata->pmic_id_irq)
- dev->id_irq = dev->pdata->pmic_id_irq;
/* vote for vddcx, as PHY cannot tolerate vddcx below 1.0V */
if (dev->pdata->init_vddcx) {
@@ -2709,7 +2783,7 @@
if (ret) {
pr_err("%s: unable to enable vddcx digital core:%d\n",
__func__, ret);
- goto free_pmic_id_notif;
+ goto free_phy_id_setup;
}
}
@@ -2819,9 +2893,9 @@
free_config_vddcx:
if (dev->pdata->init_vddcx)
dev->pdata->init_vddcx(0);
-free_pmic_id_notif:
- if (dev->pdata->pmic_id_notif_init && dev->pmic_id_notif_supp)
- dev->pdata->pmic_id_notif_init(&msm_otg_set_id_state, 0);
+free_phy_id_setup:
+ if (dev->pdata->phy_id_setup_init)
+ dev->pdata->phy_id_setup_init(0);
free_pmic_vbus_notif:
if (dev->pdata->pmic_vbus_notif_init && dev->pmic_vbus_notif_supp)
dev->pdata->pmic_vbus_notif_init(&msm_otg_set_vbus_state, 0);
@@ -2890,6 +2964,9 @@
if (dev->pmic_vbus_notif_supp)
dev->pdata->pmic_vbus_notif_init(&msm_otg_set_vbus_state, 0);
+ if (dev->pdata->phy_id_setup_init)
+ dev->pdata->phy_id_setup_init(0);
+
if (dev->pmic_id_notif_supp)
dev->pdata->pmic_id_notif_init(&msm_otg_set_id_state, 0);
diff --git a/drivers/usb/otg/msm_otg.c b/drivers/usb/otg/msm_otg.c
index d16fcda..4622725 100644
--- a/drivers/usb/otg/msm_otg.c
+++ b/drivers/usb/otg/msm_otg.c
@@ -25,6 +25,8 @@
#include <linux/debugfs.h>
#include <linux/seq_file.h>
#include <linux/pm_runtime.h>
+#include <linux/of.h>
+#include <linux/dma-mapping.h>
#include <linux/usb.h>
#include <linux/usb/otg.h>
@@ -41,27 +43,7 @@
#define MSM_USB_BASE (motg->regs)
#define DRIVER_NAME "msm_otg"
-#ifdef CONFIG_USB_MSM_ACA
-static void msm_chg_enable_aca_det(struct msm_otg *motg);
-static void msm_chg_enable_aca_intr(struct msm_otg *motg);
-#else
-static inline bool msm_chg_aca_detect(struct msm_otg *motg)
-{
- return false;
-}
-
-static inline void msm_chg_enable_aca_det(struct msm_otg *motg)
-{
-}
-static inline void msm_chg_enable_aca_intr(struct msm_otg *motg)
-{
-}
-static inline bool msm_chg_check_aca_intr(struct msm_otg *motg)
-{
- return false;
-}
-#endif
-
+#define ID_TIMER_FREQ (jiffies + msecs_to_jiffies(2000))
#define ULPI_IO_TIMEOUT_USEC (10 * 1000)
#define USB_PHY_3P3_VOL_MIN 3050000 /* uV */
@@ -78,11 +60,21 @@
#define USB_PHY_VDD_DIG_VOL_MAX 1320000 /* uV */
static struct msm_otg *the_msm_otg;
+static bool debug_aca_enabled;
static struct regulator *hsusb_3p3;
static struct regulator *hsusb_1p8;
static struct regulator *hsusb_vddcx;
+static inline bool aca_enabled(void)
+{
+#ifdef CONFIG_USB_MSM_ACA
+ return true;
+#else
+ return debug_aca_enabled;
+#endif
+}
+
static int msm_hsusb_init_vddcx(struct msm_otg *motg, int init)
{
int ret = 0;
@@ -477,11 +469,32 @@
}
#define LINK_RESET_TIMEOUT_USEC (250 * 1000)
+static int msm_otg_link_reset(struct msm_otg *motg)
+{
+ int cnt = 0;
+
+ writel_relaxed(USBCMD_RESET, USB_USBCMD);
+ while (cnt < LINK_RESET_TIMEOUT_USEC) {
+ if (!(readl_relaxed(USB_USBCMD) & USBCMD_RESET))
+ break;
+ udelay(1);
+ cnt++;
+ }
+ if (cnt >= LINK_RESET_TIMEOUT_USEC)
+ return -ETIMEDOUT;
+
+ /* select ULPI phy */
+ writel_relaxed(0x80000000, USB_PORTSC);
+ writel_relaxed(0x0, USB_AHBBURST);
+ writel_relaxed(0x00, USB_AHBMODE);
+
+ return 0;
+}
+
static int msm_otg_reset(struct otg_transceiver *otg)
{
struct msm_otg *motg = container_of(otg, struct msm_otg, otg);
struct msm_otg_platform_data *pdata = motg->pdata;
- int cnt = 0;
int ret;
u32 val = 0;
u32 ulpi_val = 0;
@@ -495,26 +508,15 @@
ulpi_init(motg);
- writel(USBCMD_RESET, USB_USBCMD);
- while (cnt < LINK_RESET_TIMEOUT_USEC) {
- if (!(readl(USB_USBCMD) & USBCMD_RESET))
- break;
- udelay(1);
- cnt++;
+ ret = msm_otg_link_reset(motg);
+ if (ret) {
+ dev_err(otg->dev, "link reset failed\n");
+ return ret;
}
- if (cnt >= LINK_RESET_TIMEOUT_USEC)
- return -ETIMEDOUT;
-
- /* select ULPI phy */
- writel(0x80000000, USB_PORTSC);
-
msleep(100);
-
- writel(0x0, USB_AHBBURST);
- writel(0x00, USB_AHBMODE);
-
/* Ensure that RESET operation is completed before turning off clock */
mb();
+
clk_disable(motg->clk);
val = readl_relaxed(USB_OTGSC);
@@ -529,8 +531,27 @@
ulpi_write(otg, ulpi_val, ULPI_USB_INT_EN_RISE);
ulpi_write(otg, ulpi_val, ULPI_USB_INT_EN_FALL);
- msm_chg_enable_aca_det(motg);
- msm_chg_enable_aca_intr(motg);
+ return 0;
+}
+
+static int msm_otg_set_suspend(struct otg_transceiver *otg, int suspend)
+{
+ struct msm_otg *motg = container_of(otg, struct msm_otg, otg);
+
+ /*
+ * Allow bus suspend only for host mode. Device mode bus suspend
+ * is not implemented yet.
+ */
+ if (!test_bit(ID, &motg->inputs) || test_bit(ID_A, &motg->inputs)) {
+ /*
+ * ID_GND --> ID_A transition can not be detected in LPM.
+ * Disallow host bus suspend when ACA is enabled.
+ */
+ if (suspend && !aca_enabled())
+ pm_runtime_put(otg->dev);
+ else
+ pm_runtime_resume(otg->dev);
+ }
return 0;
}
@@ -743,9 +764,13 @@
atomic_set(&motg->in_lpm, 0);
+ if (aca_enabled() && !irq_read_line(motg->pdata->pmic_id_irq)) {
+ clear_bit(ID, &motg->inputs);
+ schedule_work(&motg->sm_work);
+ }
+
if (motg->async_int) {
motg->async_int = 0;
- pm_runtime_put(otg->dev);
enable_irq(motg->irq);
}
@@ -757,6 +782,13 @@
static void msm_otg_notify_charger(struct msm_otg *motg, unsigned mA)
{
+ if ((motg->chg_type == USB_ACA_DOCK_CHARGER ||
+ motg->chg_type == USB_ACA_A_CHARGER ||
+ motg->chg_type == USB_ACA_B_CHARGER ||
+ motg->chg_type == USB_ACA_C_CHARGER) &&
+ mA > IDEV_ACA_CHG_LIMIT)
+ mA = IDEV_ACA_CHG_LIMIT;
+
if (motg->cur_power == mA)
return;
@@ -808,6 +840,9 @@
dev_dbg(otg->dev, "host off\n");
usb_remove_hcd(hcd);
+ /* HCD core reset all bits of PORTSC. select ULPI phy */
+ writel_relaxed(0x80000000, USB_PORTSC);
+
if (pdata->setup_gpio)
pdata->setup_gpio(OTG_STATE_UNDEFINED);
}
@@ -817,32 +852,45 @@
unsigned long action, void *priv)
{
struct msm_otg *motg = container_of(self, struct msm_otg, usbdev_nb);
- struct usb_device *udev;
+ struct usb_device *udev = priv;
+
+ if (!aca_enabled())
+ goto out;
+
+ if (action == USB_BUS_ADD || action == USB_BUS_REMOVE)
+ goto out;
+
+ if (udev->bus != motg->otg.host)
+ goto out;
+ /*
+ * Interested in devices connected directly to the root hub.
+ * ACA dock can supply IDEV_CHG irrespective devices connected
+ * on the accessory port.
+ */
+ if (!udev->parent || udev->parent->parent ||
+ motg->chg_type == USB_ACA_DOCK_CHARGER)
+ goto out;
switch (action) {
case USB_DEVICE_ADD:
+ usb_disable_autosuspend(udev);
+ /* fall through */
case USB_DEVICE_CONFIG:
- udev = priv;
- /*
- * Interested in devices connected directly to the root hub.
- * ACA dock can supply IDEV_CHG irrespective devices connected
- * on the accessory port.
- */
- if (!udev->parent || udev->parent->parent ||
- motg->chg_type == USB_ACA_DOCK_CHARGER)
- break;
if (udev->actconfig)
motg->mA_port = udev->actconfig->desc.bMaxPower * 2;
else
motg->mA_port = IUNIT;
-
- if (test_bit(ID_A, &motg->inputs))
- msm_otg_notify_charger(motg, IDEV_CHG_MIN -
- motg->mA_port);
+ break;
+ case USB_DEVICE_REMOVE:
+ motg->mA_port = IUNIT;
break;
default:
break;
}
+ if (test_bit(ID_A, &motg->inputs))
+ msm_otg_notify_charger(motg, IDEV_ACA_CHG_MAX -
+ motg->mA_port);
+out:
return NOTIFY_OK;
}
@@ -966,13 +1014,15 @@
return 0;
}
-#ifdef CONFIG_USB_MSM_ACA
static bool msm_chg_aca_detect(struct msm_otg *motg)
{
struct otg_transceiver *otg = &motg->otg;
u32 int_sts;
bool ret = false;
+ if (!aca_enabled())
+ goto out;
+
if (motg->pdata->phy_type == CI_45NM_INTEGRATED_PHY)
goto out;
@@ -985,6 +1035,7 @@
motg->chg_state = USB_CHG_STATE_DETECTED;
clear_bit(ID_B, &motg->inputs);
clear_bit(ID_C, &motg->inputs);
+ set_bit(ID, &motg->inputs);
ret = true;
}
break;
@@ -995,6 +1046,7 @@
motg->chg_state = USB_CHG_STATE_DETECTED;
clear_bit(ID_A, &motg->inputs);
clear_bit(ID_C, &motg->inputs);
+ set_bit(ID, &motg->inputs);
ret = true;
}
break;
@@ -1005,15 +1057,28 @@
motg->chg_state = USB_CHG_STATE_DETECTED;
clear_bit(ID_A, &motg->inputs);
clear_bit(ID_B, &motg->inputs);
+ set_bit(ID, &motg->inputs);
+ ret = true;
+ }
+ break;
+ case 0x04:
+ if (test_and_clear_bit(ID, &motg->inputs)) {
+ dev_dbg(otg->dev, "ID_GND\n");
+ motg->chg_type = USB_INVALID_CHARGER;
+ motg->chg_state = USB_CHG_STATE_UNDEFINED;
+ clear_bit(ID_A, &motg->inputs);
+ clear_bit(ID_B, &motg->inputs);
+ clear_bit(ID_C, &motg->inputs);
ret = true;
}
break;
default:
ret = test_and_clear_bit(ID_A, &motg->inputs) |
test_and_clear_bit(ID_B, &motg->inputs) |
- test_and_clear_bit(ID_C, &motg->inputs);
+ test_and_clear_bit(ID_C, &motg->inputs) |
+ !test_and_set_bit(ID, &motg->inputs);
if (ret) {
- dev_dbg(otg->dev, "ID A/B/C is no more\n");
+ dev_dbg(otg->dev, "ID A/B/C/GND is no more\n");
motg->chg_type = USB_INVALID_CHARGER;
motg->chg_state = USB_CHG_STATE_UNDEFINED;
}
@@ -1026,9 +1091,18 @@
{
struct otg_transceiver *otg = &motg->otg;
+ if (!aca_enabled())
+ return;
+
switch (motg->pdata->phy_type) {
case SNPS_28NM_INTEGRATED_PHY:
- /* ACA ID pin resistance detection enable */
+ /* Disable ID_GND in link and PHY */
+ writel_relaxed(readl_relaxed(USB_OTGSC) & ~(OTGSC_IDPU |
+ OTGSC_IDIE), USB_OTGSC);
+ ulpi_write(otg, 0x01, 0x0C);
+ ulpi_write(otg, 0x10, 0x0F);
+ ulpi_write(otg, 0x10, 0x12);
+ /* Enable ACA ID detection */
ulpi_write(otg, 0x20, 0x85);
break;
default:
@@ -1040,10 +1114,29 @@
{
struct otg_transceiver *otg = &motg->otg;
+ if (!aca_enabled())
+ return;
+
switch (motg->pdata->phy_type) {
case SNPS_28NM_INTEGRATED_PHY:
- /* Enables ACA Detection interrupt (on any RID change) */
- ulpi_write(otg, 0x20, 0x94);
+ /* Enable ACA Detection interrupt (on any RID change) */
+ ulpi_write(otg, 0x01, 0x94);
+ break;
+ default:
+ break;
+ }
+}
+
+static void msm_chg_disable_aca_intr(struct msm_otg *motg)
+{
+ struct otg_transceiver *otg = &motg->otg;
+
+ if (!aca_enabled())
+ return;
+
+ switch (motg->pdata->phy_type) {
+ case SNPS_28NM_INTEGRATED_PHY:
+ ulpi_write(otg, 0x01, 0x95);
break;
default:
break;
@@ -1055,6 +1148,9 @@
struct otg_transceiver *otg = &motg->otg;
bool ret = false;
+ if (!aca_enabled())
+ return ret;
+
switch (motg->pdata->phy_type) {
case SNPS_28NM_INTEGRATED_PHY:
if (ulpi_read(otg, 0x91) & 1) {
@@ -1067,7 +1163,28 @@
}
return ret;
}
-#endif
+
+static void msm_otg_id_timer_func(unsigned long data)
+{
+ struct msm_otg *motg = (struct msm_otg *) data;
+
+ if (!aca_enabled())
+ return;
+
+ if (atomic_read(&motg->in_lpm)) {
+ dev_dbg(motg->otg.dev, "timer: in lpm\n");
+ return;
+ }
+
+ if (msm_chg_check_aca_intr(motg)) {
+ dev_dbg(motg->otg.dev, "timer: aca work\n");
+ schedule_work(&motg->sm_work);
+ }
+
+ if (!test_bit(ID, &motg->inputs) || test_bit(ID_A, &motg->inputs))
+ mod_timer(&motg->id_timer, ID_TIMER_FREQ);
+}
+
static bool msm_chg_check_secondary_det(struct msm_otg *motg)
{
struct otg_transceiver *otg = &motg->otg;
@@ -1260,7 +1377,7 @@
break;
case SNPS_28NM_INTEGRATED_PHY:
/* Clear charger detecting control bits */
- ulpi_write(otg, 0x3F, 0x86);
+ ulpi_write(otg, 0x1F, 0x86);
/* Clear alt interrupt latch and enable bits */
ulpi_write(otg, 0x1F, 0x92);
ulpi_write(otg, 0x1F, 0x95);
@@ -1329,7 +1446,6 @@
dev_dbg(otg->dev, "chg detection work\n");
switch (motg->chg_state) {
case USB_CHG_STATE_UNDEFINED:
- pm_runtime_get_sync(otg->dev);
msm_chg_block_on(motg);
msm_chg_enable_dcd(motg);
msm_chg_enable_aca_det(motg);
@@ -1364,18 +1480,23 @@
break;
case USB_CHG_STATE_DCD_DONE:
vout = msm_chg_check_primary_det(motg);
- is_aca = msm_chg_aca_detect(motg);
- if (is_aca) {
- if (vout && test_bit(ID_A, &motg->inputs))
- motg->chg_type = USB_ACA_DOCK_CHARGER;
- delay = 0;
- break;
- }
if (vout) {
+ if (test_bit(ID_A, &motg->inputs)) {
+ motg->chg_type = USB_ACA_DOCK_CHARGER;
+ motg->chg_state = USB_CHG_STATE_DETECTED;
+ delay = 0;
+ break;
+ }
msm_chg_enable_secondary_det(motg);
delay = MSM_CHG_SECONDARY_DET_TIME;
motg->chg_state = USB_CHG_STATE_PRIMARY_DONE;
} else {
+ if (test_bit(ID_A, &motg->inputs)) {
+ motg->chg_type = USB_ACA_A_CHARGER;
+ motg->chg_state = USB_CHG_STATE_DETECTED;
+ delay = 0;
+ break;
+ }
motg->chg_type = USB_SDP_CHARGER;
motg->chg_state = USB_CHG_STATE_DETECTED;
delay = 0;
@@ -1431,10 +1552,18 @@
clear_bit(B_SESS_VLD, &motg->inputs);
}
} else {
- if (otgsc & OTGSC_ID)
- set_bit(ID, &motg->inputs);
- else
- clear_bit(ID, &motg->inputs);
+ if (aca_enabled()) {
+ if (irq_read_line(motg->pdata->pmic_id_irq))
+ set_bit(ID, &motg->inputs);
+ else
+ clear_bit(ID, &motg->inputs);
+
+ } else {
+ if (otgsc & OTGSC_ID)
+ set_bit(ID, &motg->inputs);
+ else
+ clear_bit(ID, &motg->inputs);
+ }
if (otgsc & OTGSC_BSV)
set_bit(B_SESS_VLD, &motg->inputs);
@@ -1462,6 +1591,7 @@
struct msm_otg *motg = container_of(w, struct msm_otg, sm_work);
struct otg_transceiver *otg = &motg->otg;
+ pm_runtime_resume(otg->dev);
switch (otg->state) {
case OTG_STATE_UNDEFINED:
dev_dbg(otg->dev, "OTG_STATE_UNDEFINED state\n");
@@ -1473,15 +1603,26 @@
dev_dbg(otg->dev, "OTG_STATE_B_IDLE state\n");
if ((!test_bit(ID, &motg->inputs) ||
test_bit(ID_A, &motg->inputs)) && otg->host) {
- /* disable BSV bit */
- writel(readl(USB_OTGSC) & ~OTGSC_BSVIE, USB_OTGSC);
if (motg->chg_type == USB_ACA_DOCK_CHARGER)
msm_otg_notify_charger(motg,
- IDEV_CHG_MAX);
- else if (!test_bit(ID_A, &motg->inputs) &&
- motg->pdata->vbus_power)
+ IDEV_ACA_CHG_MAX);
+ else if (test_bit(ID_A, &motg->inputs))
+ msm_otg_notify_charger(motg,
+ IDEV_ACA_CHG_MAX - IUNIT);
+ else if (motg->pdata->vbus_power)
motg->pdata->vbus_power(1);
msm_otg_start_host(otg, 1);
+ /*
+ * Link can not generate PHY_ALT interrupt
+ * in host mode when no device is attached
+ * to the port. It is also observed PHY_ALT
+ * interrupt missing upon Micro-A cable disconnect.
+ * Hence disable PHY_ALT interrupt and perform
+ * polling to detect RID change.
+ */
+ msm_chg_enable_aca_det(motg);
+ msm_chg_disable_aca_intr(motg);
+ mod_timer(&motg->id_timer, ID_TIMER_FREQ);
otg->state = OTG_STATE_A_HOST;
} else if (test_bit(B_SESS_VLD, &motg->inputs)) {
switch (motg->chg_state) {
@@ -1491,17 +1632,31 @@
case USB_CHG_STATE_DETECTED:
switch (motg->chg_type) {
case USB_DCP_CHARGER:
+ msm_otg_notify_charger(motg,
+ IDEV_CHG_MAX);
+ pm_runtime_put_noidle(otg->dev);
+ pm_runtime_suspend(otg->dev);
+ break;
case USB_ACA_B_CHARGER:
msm_otg_notify_charger(motg,
- IDEV_CHG_MAX);
+ IDEV_ACA_CHG_MAX);
+ /*
+ * (ID_B --> ID_C) PHY_ALT interrupt can
+ * not be detected in LPM.
+ */
break;
case USB_CDP_CHARGER:
- case USB_ACA_C_CHARGER:
msm_otg_notify_charger(motg,
IDEV_CHG_MAX);
msm_otg_start_peripheral(otg, 1);
otg->state = OTG_STATE_B_PERIPHERAL;
break;
+ case USB_ACA_C_CHARGER:
+ msm_otg_notify_charger(motg,
+ IDEV_ACA_CHG_MAX);
+ msm_otg_start_peripheral(otg, 1);
+ otg->state = OTG_STATE_B_PERIPHERAL;
+ break;
case USB_SDP_CHARGER:
msm_otg_notify_charger(motg, IUNIT);
msm_otg_start_peripheral(otg, 1);
@@ -1515,39 +1670,25 @@
break;
}
} else {
- /*
- * If charger detection work is pending, decrement
- * the pm usage counter to balance with the one that
- * is incremented in charger detection work.
- */
- if (cancel_delayed_work_sync(&motg->chg_work)) {
- pm_runtime_put_sync(otg->dev);
- msm_otg_reset(otg);
- }
+ cancel_delayed_work_sync(&motg->chg_work);
msm_otg_notify_charger(motg, 0);
motg->chg_state = USB_CHG_STATE_UNDEFINED;
motg->chg_type = USB_INVALID_CHARGER;
+ msm_otg_reset(otg);
+ pm_runtime_put_noidle(otg->dev);
+ pm_runtime_suspend(otg->dev);
}
- pm_runtime_put_sync(otg->dev);
break;
case OTG_STATE_B_PERIPHERAL:
dev_dbg(otg->dev, "OTG_STATE_B_PERIPHERAL state\n");
if (!test_bit(B_SESS_VLD, &motg->inputs) ||
!test_bit(ID, &motg->inputs) ||
!test_bit(ID_C, &motg->inputs)) {
- msm_otg_notify_charger(motg, 0);
msm_otg_start_peripheral(otg, 0);
- if (!test_bit(ID_B, &motg->inputs) &&
- !test_bit(ID_A, &motg->inputs)) {
- motg->chg_state = USB_CHG_STATE_UNDEFINED;
- motg->chg_type = USB_INVALID_CHARGER;
- }
otg->state = OTG_STATE_B_IDLE;
- msm_otg_reset(otg);
schedule_work(w);
} else if (test_bit(ID_C, &motg->inputs)) {
- msm_otg_notify_charger(motg, IDEV_CHG_MAX);
- pm_runtime_put_sync(otg->dev);
+ msm_otg_notify_charger(motg, IDEV_ACA_CHG_MAX);
}
break;
case OTG_STATE_A_HOST:
@@ -1555,29 +1696,39 @@
if (test_bit(ID, &motg->inputs) &&
!test_bit(ID_A, &motg->inputs)) {
msm_otg_start_host(otg, 0);
- writel(readl(USB_OTGSC) & ~OTGSC_BSVIE, USB_OTGSC);
- if (motg->pdata->vbus_power)
+ if (motg->pdata->vbus_power) {
motg->pdata->vbus_power(0);
- motg->chg_state = USB_CHG_STATE_UNDEFINED;
- motg->chg_type = USB_INVALID_CHARGER;
+ msleep(100); /* TA_WAIT_VFALL */
+ }
+ /*
+ * Exit point of host mode.
+ *
+ * 1. Micro-A cable disconnect: Just schedule
+ * the work. PHY is reset in B_IDLE and LPM
+ * is allowed.
+ * 2. ID_GND --> ID_B: No need to reset the PHY.
+ * HCD core clears all PORTSC bits and initializes
+ * the controller to host mode in remove_hcd.
+ * Restore PORTSC transceiver select bits (ULPI)
+ * and reset the controller to change MODE bits.
+ * PHY_ALT interrupt can not occur in host mode.
+ */
+ del_timer_sync(&motg->id_timer);
+ if (motg->chg_state != USB_CHG_STATE_UNDEFINED) {
+ msm_otg_link_reset(motg);
+ msm_chg_enable_aca_intr(motg);
+ }
otg->state = OTG_STATE_B_IDLE;
- msm_otg_reset(otg);
schedule_work(w);
} else if (test_bit(ID_A, &motg->inputs)) {
- writel(readl(USB_OTGSC) & ~OTGSC_BSVIE, USB_OTGSC);
if (motg->pdata->vbus_power)
motg->pdata->vbus_power(0);
msm_otg_notify_charger(motg,
- IDEV_CHG_MIN - motg->mA_port);
- pm_runtime_put_sync(otg->dev);
+ IDEV_ACA_CHG_MAX - motg->mA_port);
} else if (!test_bit(ID, &motg->inputs)) {
- motg->chg_state = USB_CHG_STATE_UNDEFINED;
- motg->chg_type = USB_INVALID_CHARGER;
msm_otg_notify_charger(motg, 0);
- writel(readl(USB_OTGSC) & ~OTGSC_BSVIE, USB_OTGSC);
if (motg->pdata->vbus_power)
motg->pdata->vbus_power(1);
- pm_runtime_put_sync(otg->dev);
}
break;
default:
@@ -1594,15 +1745,16 @@
if (atomic_read(&motg->in_lpm)) {
disable_irq_nosync(irq);
motg->async_int = 1;
- pm_runtime_get(otg->dev);
+ pm_request_resume(otg->dev);
return IRQ_HANDLED;
}
usbsts = readl(USB_USBSTS);
if ((usbsts & PHY_ALT_INT)) {
+ dev_dbg(otg->dev, "PHY_ALT interrupt\n");
writel(PHY_ALT_INT, USB_USBSTS);
if (msm_chg_check_aca_intr(motg)) {
- pm_runtime_get_noresume(otg->dev);
+ dev_dbg(otg->dev, "ACA work from IRQ\n");
schedule_work(&motg->sm_work);
}
return IRQ_HANDLED;
@@ -1613,21 +1765,25 @@
return IRQ_NONE;
if ((otgsc & OTGSC_IDIS) && (otgsc & OTGSC_IDIE)) {
- if (otgsc & OTGSC_ID)
+ if (otgsc & OTGSC_ID) {
+ dev_dbg(otg->dev, "ID set\n");
set_bit(ID, &motg->inputs);
- else
+ } else {
+ dev_dbg(otg->dev, "ID clear\n");
clear_bit(ID, &motg->inputs);
- dev_dbg(otg->dev, "ID set/clear\n");
+ msm_chg_enable_aca_det(motg);
+ }
schedule_work(&motg->sm_work);
- pm_runtime_get_noresume(otg->dev);
} else if ((otgsc & OTGSC_BSVIS) && (otgsc & OTGSC_BSVIE)) {
- if (otgsc & OTGSC_BSV)
+ if (otgsc & OTGSC_BSV) {
+ dev_dbg(otg->dev, "BSV set\n");
set_bit(B_SESS_VLD, &motg->inputs);
- else
+ } else {
+ dev_dbg(otg->dev, "BSV clear\n");
clear_bit(B_SESS_VLD, &motg->inputs);
- dev_dbg(otg->dev, "BSV set/clear\n");
+ msm_chg_check_aca_intr(motg);
+ }
schedule_work(&motg->sm_work);
- pm_runtime_get_noresume(otg->dev);
}
writel(otgsc, USB_OTGSC);
@@ -1749,7 +1905,7 @@
goto out;
}
- pm_runtime_get_sync(otg->dev);
+ pm_runtime_resume(otg->dev);
schedule_work(&motg->sm_work);
out:
return status;
@@ -1783,9 +1939,51 @@
.release = single_release,
};
+static int msm_otg_aca_show(struct seq_file *s, void *unused)
+{
+ if (debug_aca_enabled)
+ seq_printf(s, "enabled\n");
+ else
+ seq_printf(s, "disabled\n");
+
+ return 0;
+}
+
+static int msm_otg_aca_open(struct inode *inode, struct file *file)
+{
+ return single_open(file, msm_otg_aca_show, inode->i_private);
+}
+
+static ssize_t msm_otg_aca_write(struct file *file, const char __user *ubuf,
+ size_t count, loff_t *ppos)
+{
+ char buf[8];
+
+ memset(buf, 0x00, sizeof(buf));
+
+ if (copy_from_user(&buf, ubuf, min_t(size_t, sizeof(buf) - 1, count)))
+ return -EFAULT;
+
+ if (!strncmp(buf, "enable", 6))
+ debug_aca_enabled = true;
+ else
+ debug_aca_enabled = false;
+
+ return count;
+}
+
+const struct file_operations msm_otg_aca_fops = {
+ .open = msm_otg_aca_open,
+ .read = seq_read,
+ .write = msm_otg_aca_write,
+ .llseek = seq_lseek,
+ .release = single_release,
+};
+
static struct dentry *msm_otg_dbg_root;
static struct dentry *msm_otg_dbg_mode;
static struct dentry *msm_otg_chg_type;
+static struct dentry *msm_otg_dbg_aca;
static int msm_otg_debugfs_init(struct msm_otg *motg)
{
@@ -1814,10 +2012,16 @@
&msm_otg_chg_fops);
if (!msm_otg_chg_type) {
- debugfs_remove(msm_otg_dbg_mode);
- debugfs_remove(msm_otg_dbg_root);
- msm_otg_dbg_root = NULL;
- msm_otg_dbg_mode = NULL;
+ debugfs_remove_recursive(msm_otg_dbg_root);
+ return -ENODEV;
+ }
+
+ msm_otg_dbg_aca = debugfs_create_file("aca", S_IRUGO | S_IWUSR,
+ msm_otg_dbg_root, motg,
+ &msm_otg_aca_fops);
+
+ if (!msm_otg_dbg_aca) {
+ debugfs_remove_recursive(msm_otg_dbg_root);
return -ENODEV;
}
@@ -1829,17 +2033,147 @@
debugfs_remove_recursive(msm_otg_dbg_root);
}
+static u64 msm_otg_dma_mask = DMA_BIT_MASK(64);
+static struct platform_device *msm_otg_add_pdev(
+ struct platform_device *ofdev, const char *name)
+{
+ struct platform_device *pdev;
+ const struct resource *res = ofdev->resource;
+ unsigned int num = ofdev->num_resources;
+ int retval;
+
+ pdev = platform_device_alloc(name, -1);
+ if (!pdev) {
+ retval = -ENOMEM;
+ goto error;
+ }
+
+ pdev->dev.coherent_dma_mask = DMA_BIT_MASK(32);
+ pdev->dev.dma_mask = &msm_otg_dma_mask;
+
+ if (num) {
+ retval = platform_device_add_resources(pdev, res, num);
+ if (retval)
+ goto error;
+ }
+
+ retval = platform_device_add(pdev);
+ if (retval)
+ goto error;
+
+ return pdev;
+
+error:
+ platform_device_put(pdev);
+ return ERR_PTR(retval);
+}
+
+static int msm_otg_setup_devices(struct platform_device *ofdev,
+ enum usb_mode_type mode, bool init)
+{
+ const char *gadget_name = "msm_hsusb";
+ const char *host_name = "msm_hsusb_host";
+ static struct platform_device *gadget_pdev;
+ static struct platform_device *host_pdev;
+ int retval = 0;
+
+ if (!init) {
+ if (gadget_pdev)
+ platform_device_unregister(gadget_pdev);
+ if (host_pdev)
+ platform_device_unregister(host_pdev);
+ return 0;
+ }
+
+ switch (mode) {
+ case USB_OTG:
+ /* fall through */
+ case USB_PERIPHERAL:
+ gadget_pdev = msm_otg_add_pdev(ofdev, gadget_name);
+ if (IS_ERR(gadget_pdev)) {
+ retval = PTR_ERR(gadget_pdev);
+ break;
+ }
+ if (mode == USB_PERIPHERAL)
+ break;
+ /* fall through */
+ case USB_HOST:
+ host_pdev = msm_otg_add_pdev(ofdev, host_name);
+ if (IS_ERR(host_pdev)) {
+ retval = PTR_ERR(host_pdev);
+ if (mode == USB_OTG)
+ platform_device_unregister(gadget_pdev);
+ }
+ break;
+ default:
+ break;
+ }
+
+ return retval;
+}
+
+struct msm_otg_platform_data *msm_otg_dt_to_pdata(struct platform_device *pdev)
+{
+ struct device_node *node = pdev->dev.of_node;
+ struct msm_otg_platform_data *pdata;
+ int len = 0;
+
+ pdata = devm_kzalloc(&pdev->dev, sizeof(*pdata), GFP_KERNEL);
+ if (!pdata) {
+ pr_err("unable to allocate platform data\n");
+ return NULL;
+ }
+ of_get_property(node, "qcom,hsusb-otg-phy-init-seq", &len);
+ if (len) {
+ pdata->phy_init_seq = devm_kzalloc(&pdev->dev, len, GFP_KERNEL);
+ if (!pdata->phy_init_seq)
+ return NULL;
+ of_property_read_u32_array(node, "qcom,hsusb-otg-phy-init-seq",
+ pdata->phy_init_seq,
+ len/sizeof(*pdata->phy_init_seq));
+ }
+ of_property_read_u32(node, "qcom,hsusb-otg-power-budget",
+ &pdata->power_budget);
+ of_property_read_u32(node, "qcom,hsusb-otg-mode",
+ &pdata->mode);
+ of_property_read_u32(node, "qcom,hsusb-otg-otg-control",
+ &pdata->otg_control);
+ of_property_read_u32(node, "qcom,hsusb-otg-default-mode",
+ &pdata->default_mode);
+ of_property_read_u32(node, "qcom,hsusb-otg-phy-type",
+ &pdata->phy_type);
+ of_property_read_u32(node, "qcom,hsusb-otg-pmic-id-irq",
+ &pdata->pmic_id_irq);
+ of_property_read_string(node, "qcom,hsusb-otg-pclk-src-name",
+ &pdata->pclk_src_name);
+ return pdata;
+}
+
static int __init msm_otg_probe(struct platform_device *pdev)
{
int ret = 0;
struct resource *res;
struct msm_otg *motg;
struct otg_transceiver *otg;
+ struct msm_otg_platform_data *pdata;
dev_info(&pdev->dev, "msm_otg probe\n");
- if (!pdev->dev.platform_data) {
+
+ if (pdev->dev.of_node) {
+ dev_dbg(&pdev->dev, "device tree enabled\n");
+ pdata = msm_otg_dt_to_pdata(pdev);
+ if (!pdata)
+ return -ENOMEM;
+ ret = msm_otg_setup_devices(pdev, pdata->mode, true);
+ if (ret) {
+ dev_err(&pdev->dev, "devices setup failed\n");
+ return ret;
+ }
+ } else if (!pdev->dev.platform_data) {
dev_err(&pdev->dev, "No platform data given. Bailing out\n");
return -ENODEV;
+ } else {
+ pdata = pdev->dev.platform_data;
}
motg = kzalloc(sizeof(struct msm_otg), GFP_KERNEL);
@@ -1849,10 +2183,21 @@
}
the_msm_otg = motg;
- motg->pdata = pdev->dev.platform_data;
+ motg->pdata = pdata;
otg = &motg->otg;
otg->dev = &pdev->dev;
+ /*
+ * ACA ID_GND threshold range is overlapped with OTG ID_FLOAT. Hence
+ * PHY treat ACA ID_GND as float and no interrupt is generated. But
+ * PMIC can detect ACA ID_GND and generate an interrupt.
+ */
+ if (aca_enabled() && motg->pdata->otg_control != OTG_PMIC_CONTROL) {
+ dev_err(&pdev->dev, "ACA can not be enabled without PMIC\n");
+ ret = -EINVAL;
+ goto free_motg;
+ }
+
/* Some targets don't support PHY clock. */
motg->phy_reset_clk = clk_get(&pdev->dev, "usb_phy_clk");
if (IS_ERR(motg->phy_reset_clk))
@@ -1962,6 +2307,8 @@
wake_lock_init(&motg->wlock, WAKE_LOCK_SUSPEND, "msm_otg");
INIT_WORK(&motg->sm_work, msm_otg_sm_work);
INIT_DELAYED_WORK(&motg->chg_work, msm_chg_detect_work);
+ setup_timer(&motg->id_timer, msm_otg_id_timer_func,
+ (unsigned long) motg);
ret = request_irq(motg->irq, msm_otg_irq, IRQF_SHARED,
"msm_otg", motg);
if (ret) {
@@ -1973,6 +2320,7 @@
otg->set_host = msm_otg_set_host;
otg->set_peripheral = msm_otg_set_peripheral;
otg->set_power = msm_otg_set_power;
+ otg->set_suspend = msm_otg_set_suspend;
otg->io_ops = &msm_otg_io_ops;
@@ -2059,7 +2407,7 @@
put_phy_reset_clk:
if (!IS_ERR(motg->phy_reset_clk))
clk_put(motg->phy_reset_clk);
-
+free_motg:
kfree(motg);
return ret;
}
@@ -2073,6 +2421,8 @@
if (otg->host || otg->gadget)
return -EBUSY;
+ if (pdev->dev.of_node)
+ msm_otg_setup_devices(pdev, motg->pdata->mode, false);
if (motg->pdata->otg_control == OTG_PMIC_CONTROL)
pm8921_charger_unregister_vbus_sn(0);
msm_otg_debugfs_cleanup();
@@ -2145,16 +2495,10 @@
dev_dbg(dev, "OTG runtime idle\n");
- /*
- * It is observed some times that a spurious interrupt
- * comes when PHY is put into LPM immediately after PHY reset.
- * This 1 sec delay also prevents entering into LPM immediately
- * after asynchronous interrupt.
- */
- if (otg->state != OTG_STATE_UNDEFINED)
- pm_schedule_suspend(dev, 1000);
-
- return -EAGAIN;
+ if (otg->state == OTG_STATE_UNDEFINED)
+ return -EAGAIN;
+ else
+ return 0;
}
static int msm_otg_runtime_suspend(struct device *dev)
@@ -2170,6 +2514,7 @@
struct msm_otg *motg = dev_get_drvdata(dev);
dev_dbg(dev, "OTG runtime resume\n");
+ pm_runtime_get_noresume(dev);
return msm_otg_resume(motg);
}
#endif
@@ -2177,10 +2522,18 @@
#ifdef CONFIG_PM_SLEEP
static int msm_otg_pm_suspend(struct device *dev)
{
- struct msm_otg *motg = dev_get_drvdata(dev);
+ int ret;
dev_dbg(dev, "OTG PM suspend\n");
- return msm_otg_suspend(motg);
+
+#ifdef CONFIG_PM_RUNTIME
+ ret = pm_runtime_suspend(dev);
+ if (ret > 0)
+ ret = 0;
+#else
+ ret = msm_otg_suspend(dev_get_drvdata(dev));
+#endif
+ return ret;
}
static int msm_otg_pm_resume(struct device *dev)
@@ -2209,6 +2562,12 @@
};
#endif
+static struct of_device_id msm_otg_dt_match[] = {
+ { .compatible = "qcom,hsusb-otg",
+ },
+ {}
+};
+
static struct platform_driver msm_otg_driver = {
.remove = __devexit_p(msm_otg_remove),
.driver = {
@@ -2217,6 +2576,7 @@
#ifdef CONFIG_PM
.pm = &msm_otg_dev_pm_ops,
#endif
+ .of_match_table = msm_otg_dt_match,
},
};
diff --git a/drivers/video/msm/Makefile b/drivers/video/msm/Makefile
index f5a7c9e..dc02da4 100644
--- a/drivers/video/msm/Makefile
+++ b/drivers/video/msm/Makefile
@@ -10,6 +10,7 @@
ifeq ($(CONFIG_FB_MSM_MDP40),y)
obj-y += mdp4_util.o
+obj-y += mdp4_hsic.o
else
obj-y += mdp_hw_init.o
obj-y += mdp_ppp.o
diff --git a/drivers/video/msm/mdp.h b/drivers/video/msm/mdp.h
index c12a250..8817213 100644
--- a/drivers/video/msm/mdp.h
+++ b/drivers/video/msm/mdp.h
@@ -737,6 +737,10 @@
{
/* empty */
}
+static inline int mdp4_overlay_dsi_state_get(void)
+{
+ return 0;
+}
#endif
#endif /* MDP_H */
diff --git a/drivers/video/msm/mdp4.h b/drivers/video/msm/mdp4.h
index d757b5d..65b64f6 100644
--- a/drivers/video/msm/mdp4.h
+++ b/drivers/video/msm/mdp4.h
@@ -222,6 +222,15 @@
#define MDP4_MAX_PLANE 4
+struct mdp4_hsic_regs {
+ int32_t params[NUM_HSIC_PARAM];
+ int32_t conv_matrix[3][3];
+ int32_t pre_limit[6];
+ int32_t post_limit[6];
+ int32_t pre_bias[3];
+ int32_t post_bias[3];
+ int32_t dirty;
+};
struct mdp4_overlay_pipe {
uint32 pipe_used;
@@ -298,6 +307,7 @@
uint32 dmap_cnt;
uint32 blt_end;
uint32 luma_align_size;
+ struct mdp4_hsic_regs hsic_regs;
struct completion dmas_comp;
struct mdp_overlay req_data;
};
@@ -410,6 +420,7 @@
void mdp4_overlay0_done_dsi_cmd(struct mdp_dma_data *dma);
void mdp4_dsi_cmd_overlay(struct msm_fb_data_type *mfd);
void mdp4_overlay_dsi_state_set(int state);
+int mdp4_overlay_dsi_state_get(void);
void mdp4_overlay_rgb_setup(struct mdp4_overlay_pipe *pipe);
void mdp4_overlay_reg_flush(struct mdp4_overlay_pipe *pipe, int all);
void mdp4_mixer_blend_setup(struct mdp4_overlay_pipe *pipe);
@@ -636,4 +647,6 @@
int mdp4_writeback_init(struct fb_info *info);
int mdp4_writeback_terminate(struct fb_info *info);
+void mdp4_hsic_set(struct mdp4_overlay_pipe *pipe, struct dpp_ctrl *ctrl);
+void mdp4_hsic_update(struct mdp4_overlay_pipe *pipe);
#endif /* MDP_H */
diff --git a/drivers/video/msm/mdp4_hsic.c b/drivers/video/msm/mdp4_hsic.c
new file mode 100644
index 0000000..5735f45
--- /dev/null
+++ b/drivers/video/msm/mdp4_hsic.c
@@ -0,0 +1,534 @@
+/* Copyright (c) 2009-2011, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#include <linux/module.h>
+#include <linux/types.h>
+#include <linux/msm_mdp.h>
+#include "mdp.h"
+#include "mdp4.h"
+
+/* Definitions */
+#define MDP4_CSC_MV_OFF 0x4400
+#define MDP4_CSC_PRE_BV_OFF 0x4500
+#define MDP4_CSC_POST_BV_OFF 0x4580
+#define MDP4_CSC_PRE_LV_OFF 0x4600
+#define MDP4_CSC_POST_LV_OFF 0x4680
+#define MDP_VG1_BASE (MDP_BASE + MDP4_VIDEO_BASE)
+
+#define MDP_VG1_CSC_MVn(n) (MDP_VG1_BASE + MDP4_CSC_MV_OFF + 4 * (n))
+#define MDP_VG1_CSC_PRE_LVn(n) (MDP_VG1_BASE + MDP4_CSC_PRE_LV_OFF + 4 * (n))
+#define MDP_VG1_CSC_POST_LVn(n) (MDP_VG1_BASE + MDP4_CSC_POST_LV_OFF + 4 * (n))
+#define MDP_VG1_CSC_PRE_BVn(n) (MDP_VG1_BASE + MDP4_CSC_PRE_BV_OFF + 4 * (n))
+#define MDP_VG1_CSC_POST_BVn(n) (MDP_VG1_BASE + MDP4_CSC_POST_BV_OFF + 4 * (n))
+
+#define Q16 (16)
+#define Q16_ONE (1 << Q16)
+
+#define Q16_VALUE(x) ((int32_t)((uint32_t)x << Q16))
+#define Q16_PERCENT_VALUE(x, n) ((int32_t)( \
+ div_s64(((int64_t)x * (int64_t)Q16_ONE), n)))
+
+#define Q16_WHOLE(x) ((int32_t)(x >> 16))
+#define Q16_FRAC(x) ((int32_t)(x & 0xFFFF))
+#define Q16_S1Q16_MUL(x, y) (((x >> 1) * (y >> 1)) >> 14)
+
+#define Q16_MUL(x, y) ((int32_t)((((int64_t)x) * ((int64_t)y)) >> Q16))
+#define Q16_NEGATE(x) (0 - (x))
+
+/*
+ * HSIC Control min/max values
+ * These settings are based on the maximum/minimum allowed modifications to
+ * HSIC controls for layer and display color. Allowing too much variation in
+ * the CSC block will result in color clipping resulting in unwanted color
+ * shifts.
+ */
+#define TRIG_MAX Q16_VALUE(128)
+#define CON_SAT_MAX Q16_VALUE(128)
+#define INTENSITY_MAX (Q16_VALUE(2047) >> 12)
+
+#define HUE_MAX Q16_VALUE(100)
+#define HUE_MIN Q16_VALUE(-100)
+#define HUE_DEF Q16_VALUE(0)
+
+#define SAT_MAX Q16_VALUE(100)
+#define SAT_MIN Q16_VALUE(-100)
+#define SAT_DEF CON_SAT_MAX
+
+#define CON_MAX Q16_VALUE(100)
+#define CON_MIN Q16_VALUE(-100)
+#define CON_DEF CON_SAT_MAX
+
+#define INTEN_MAX Q16_VALUE(100)
+#define INTEN_MIN Q16_VALUE(-100)
+#define INTEN_DEF Q16_VALUE(0)
+
+enum {
+ DIRTY,
+ GENERATED,
+ CLEAN
+};
+
+/* local vars*/
+static int32_t csc_matrix_tab[3][3] = {
+ {0x00012a00, 0x00000000, 0x00019880},
+ {0x00012a00, 0xffff9b80, 0xffff3000},
+ {0x00012a00, 0x00020480, 0x00000000}
+};
+
+static int32_t csc_yuv2rgb_conv_tab[3][3] = {
+ {0x00010000, 0x00000000, 0x000123cb},
+ {0x00010000, 0xffff9af9, 0xffff6b5e},
+ {0x00010000, 0x00020838, 0x00000000}
+};
+
+static int32_t csc_rgb2yuv_conv_tab[3][3] = {
+ {0x00004c8b, 0x00009645, 0x00001d2f},
+ {0xffffda56, 0xffffb60e, 0x00006f9d},
+ {0x00009d70, 0xffff7c2a, 0xffffe666}
+};
+
+static uint32_t csc_pre_bv_tab[3] = {0xfffff800, 0xffffc000, 0xffffc000};
+static uint32_t csc_post_bv_tab[3] = {0x00000000, 0x00000000, 0x00000000};
+
+static uint32_t csc_pre_lv_tab[6] = {0x00000000, 0x00007f80, 0x00000000,
+ 0x00007f80, 0x00000000, 0x00007f80};
+static uint32_t csc_post_lv_tab[6] = {0x00000000, 0x00007f80, 0x00000000,
+ 0x00007f80, 0x00000000, 0x00007f80};
+
+/* Lookup table for Sin/Cos lookup - Q16*/
+static const int32_t trig_lut[65] = {
+ 0x00000000, /* sin((2*M_PI/256) * 0x00);*/
+ 0x00000648, /* sin((2*M_PI/256) * 0x01);*/
+ 0x00000C90, /* sin((2*M_PI/256) * 0x02);*/
+ 0x000012D5,
+ 0x00001918,
+ 0x00001F56,
+ 0x00002590,
+ 0x00002BC4,
+ 0x000031F1,
+ 0x00003817,
+ 0x00003E34,
+ 0x00004447,
+ 0x00004A50,
+ 0x0000504D,
+ 0x0000563E,
+ 0x00005C22,
+ 0x000061F8,
+ 0x000067BE,
+ 0x00006D74,
+ 0x0000731A,
+ 0x000078AD,
+ 0x00007E2F,
+ 0x0000839C,
+ 0x000088F6,
+ 0x00008E3A,
+ 0x00009368,
+ 0x00009880,
+ 0x00009D80,
+ 0x0000A268,
+ 0x0000A736,
+ 0x0000ABEB,
+ 0x0000B086,
+ 0x0000B505,
+ 0x0000B968,
+ 0x0000BDAF,
+ 0x0000C1D8,
+ 0x0000C5E4,
+ 0x0000C9D1,
+ 0x0000CD9F,
+ 0x0000D14D,
+ 0x0000D4DB,
+ 0x0000D848,
+ 0x0000DB94,
+ 0x0000DEBE,
+ 0x0000E1C6,
+ 0x0000E4AA,
+ 0x0000E768,
+ 0x0000EA0A,
+ 0x0000EC83,
+ 0x0000EED9,
+ 0x0000F109,
+ 0x0000F314,
+ 0x0000F4FA,
+ 0x0000F6BA,
+ 0x0000F854,
+ 0x0000F9C8,
+ 0x0000FB15,
+ 0x0000FC3B,
+ 0x0000FD3B,
+ 0x0000FE13,
+ 0x0000FEC4,
+ 0x0000FF4E,
+ 0x0000FFB1,
+ 0x0000FFEC,
+ 0x00010000, /* sin((2*M_PI/256) * 0x40);*/
+};
+
+void trig_values_q16(int32_t deg, int32_t *cos, int32_t *sin)
+{
+ int32_t angle;
+ int32_t quad, anglei, anglef;
+ int32_t v0 = 0, v1 = 0;
+ int32_t t1, t2;
+
+ /*
+ * Scale the angle so that 256 is one complete revolution and mask it
+ * to this domain
+ * NOTE: 0xB60B == 256/360
+ */
+ angle = Q16_MUL(deg, 0xB60B) & 0x00FFFFFF;
+
+ /* Obtain a quadrant number, integer, and fractional part */
+ quad = angle >> 22;
+ anglei = (angle >> 16) & 0x3F;
+ anglef = angle & 0xFFFF;
+
+ /*
+ * Using the integer part, obtain the lookup table entry and its
+ * complement. Using the quadrant, swap and negate these as
+ * necessary.
+ * (The values and all derivatives of sine and cosine functions
+ * can be derived from these values)
+ */
+ switch (quad) {
+ case 0x0:
+ v0 += trig_lut[anglei];
+ v1 += trig_lut[0x40-anglei];
+ break;
+
+ case 0x1:
+ v0 += trig_lut[0x40-anglei];
+ v1 -= trig_lut[anglei];
+ break;
+
+ case 0x2:
+ v0 -= trig_lut[anglei];
+ v1 -= trig_lut[0x40-anglei];
+ break;
+
+ case 0x3:
+ v0 -= trig_lut[0x40-anglei];
+ v1 += trig_lut[anglei];
+ break;
+ }
+
+ /*
+ * Multiply the fractional part by 2*PI/256 to move it from lookup
+ * table units to radians, giving us the coefficient for first
+ * derivatives.
+ */
+ t1 = Q16_S1Q16_MUL(anglef, 0x0648);
+
+ /*
+ * Square this and divide by 2 to get the coefficient for second
+ * derivatives
+ */
+ t2 = Q16_S1Q16_MUL(t1, t1) >> 1;
+
+ *sin = v0 + Q16_S1Q16_MUL(v1, t1) - Q16_S1Q16_MUL(v0, t2);
+
+ *cos = v1 - Q16_S1Q16_MUL(v0, t1) - Q16_S1Q16_MUL(v1, t2);
+}
+
+/* Convert input Q16 value to s4.9 */
+int16_t convert_q16_s49(int32_t q16Value)
+{ /* Top half is the whole number, Bottom half is fractional portion*/
+ int16_t whole = Q16_WHOLE(q16Value);
+ int32_t fraction = Q16_FRAC(q16Value);
+
+ /* Clamp whole to 3 bits */
+ if (whole > 7)
+ whole = 7;
+ else if (whole < -7)
+ whole = -7;
+
+ /* Reduce fraction to 9 bits. */
+ fraction = (fraction<<9)>>Q16;
+
+ return (int16_t) ((int16_t)whole<<9) | ((int16_t)fraction);
+}
+
+/* Convert input Q16 value to uint16 */
+int16_t convert_q16_int16(int32_t val)
+{
+ int32_t rounded;
+
+ if (val >= 0) {
+ /* Add 0.5 */
+ rounded = val + (Q16_ONE>>1);
+ } else {
+ /* Subtract 0.5 */
+ rounded = val - (Q16_ONE>>1);
+ }
+
+ /* Truncate rounded value */
+ return (int16_t)(rounded>>Q16);
+}
+
+/*
+ * norm_q16
+ * Return a Q16 value represeting a normalized value
+ *
+ * value -100% 0% +100%
+ * |-----------------|----------------|
+ * ^ ^ ^
+ * q16MinValue q16DefaultValue q16MaxValue
+ *
+ */
+int32_t norm_q16(int32_t value, int32_t min, int32_t default_val, int32_t max,
+ int32_t range)
+{
+ int32_t diff, perc, mul, result;
+
+ if (0 == value) {
+ result = default_val;
+ } else if (value > 0) {
+ /* value is between 0% and +100% represent 1.0 -> QRange Max */
+ diff = range;
+ perc = Q16_PERCENT_VALUE(value, max);
+ mul = Q16_MUL(perc, diff);
+ result = default_val + mul;
+ } else {
+ /* if (value <= 0) */
+ diff = -range;
+ perc = Q16_PERCENT_VALUE(-value, -min);
+ mul = Q16_MUL(perc, diff);
+ result = default_val + mul;
+ }
+ return result;
+}
+
+void matrix_mul_3x3(int32_t dest[][3], int32_t a[][3], int32_t b[][3])
+{
+ int32_t i, j, k;
+ int32_t tmp[3][3];
+
+ for (i = 0; i < 3; i++) {
+ for (j = 0; j < 3; j++) {
+ tmp[i][j] = 0;
+ for (k = 0; k < 3; k++)
+ tmp[i][j] += Q16_MUL(a[i][k], b[k][j]);
+ }
+ }
+
+ /* in case dest = a or b*/
+ for (i = 0; i < 3; i++) {
+ for (j = 0; j < 3; j++)
+ dest[i][j] = tmp[i][j];
+ }
+}
+
+#define CONVERT(x) (x)/*convert_q16_s49((x))*/
+void pr_params(struct mdp4_hsic_regs *regs)
+{
+ int i;
+ if (regs) {
+ for (i = 0; i < NUM_HSIC_PARAM; i++) {
+ pr_info("\t: hsic->params[%d] = 0x%08x [raw = 0x%08x]\n",
+ i, CONVERT(regs->params[i]), regs->params[i]);
+ }
+ }
+}
+
+void pr_3x3_matrix(int32_t in[][3])
+{
+ pr_info("\t[0x%08x\t0x%08x\t0x%08x]\n", CONVERT(in[0][0]),
+ CONVERT(in[0][1]), CONVERT(in[0][2]));
+ pr_info("\t[0x%08x\t0x%08x\t0x%08x]\n", CONVERT(in[1][0]),
+ CONVERT(in[1][1]), CONVERT(in[1][2]));
+ pr_info("\t[0x%08x\t0x%08x\t0x%08x]\n", CONVERT(in[2][0]),
+ CONVERT(in[2][1]), CONVERT(in[2][2]));
+}
+
+void _hsic_get(struct mdp4_hsic_regs *regs, int32_t type, int8_t *val)
+{
+ if (type < 0 || type >= NUM_HSIC_PARAM)
+ BUG_ON(-EINVAL);
+ *val = regs->params[type];
+ pr_info("%s: getting params[%d] = %d\n", __func__, type, *val);
+}
+
+void _hsic_set(struct mdp4_hsic_regs *regs, int32_t type, int8_t val)
+{
+ if (type < 0 || type >= NUM_HSIC_PARAM)
+ BUG_ON(-EINVAL);
+
+ if (regs->params[type] != Q16_VALUE(val)) {
+ regs->params[type] = Q16_VALUE(val);
+ regs->dirty = DIRTY;
+ }
+}
+
+void _hsic_generate_csc_matrix(struct mdp4_overlay_pipe *pipe)
+{
+ int i, j;
+ int32_t sin, cos;
+
+ int32_t hue_matrix[3][3];
+ int32_t con_sat_matrix[3][3];
+ struct mdp4_hsic_regs *regs = &(pipe->hsic_regs);
+
+ memset(con_sat_matrix, 0x0, sizeof(con_sat_matrix));
+ memset(hue_matrix, 0x0, sizeof(hue_matrix));
+
+ /*
+ * HSIC control require matrix multiplication of these two tables
+ * [T 0 0][1 0 0] T = Contrast C=Cos(Hue)
+ * [0 S 0][0 C -N] S = Saturation N=Sin(Hue)
+ * [0 0 S][0 N C]
+ */
+
+ con_sat_matrix[0][0] = norm_q16(regs->params[HSIC_CON], CON_MIN,
+ CON_DEF, CON_MAX, CON_SAT_MAX);
+ con_sat_matrix[1][1] = norm_q16(regs->params[HSIC_SAT], SAT_MIN,
+ SAT_DEF, SAT_MAX, CON_SAT_MAX);
+ con_sat_matrix[2][2] = con_sat_matrix[1][1];
+
+ hue_matrix[0][0] = TRIG_MAX;
+
+ trig_values_q16(norm_q16(regs->params[HSIC_HUE], HUE_MIN, HUE_DEF,
+ HUE_MAX, TRIG_MAX), &cos, &sin);
+
+ cos = Q16_MUL(cos, TRIG_MAX);
+ sin = Q16_MUL(sin, TRIG_MAX);
+
+ hue_matrix[1][1] = cos;
+ hue_matrix[2][2] = cos;
+ hue_matrix[2][1] = sin;
+ hue_matrix[1][2] = Q16_NEGATE(sin);
+
+ /* Generate YUV CSC matrix */
+ matrix_mul_3x3(regs->conv_matrix, con_sat_matrix, hue_matrix);
+
+ if (!(pipe->op_mode & MDP4_OP_SRC_DATA_YCBCR)) {
+ /* Convert input RGB to YUV then apply CSC matrix */
+ pr_info("Pipe %d, has RGB input\n", pipe->pipe_num);
+ matrix_mul_3x3(regs->conv_matrix, regs->conv_matrix,
+ csc_rgb2yuv_conv_tab);
+ }
+
+ /* Normalize the matrix */
+ for (i = 0; i < 3; i++) {
+ for (j = 0; j < 3; j++)
+ regs->conv_matrix[i][j] = (regs->conv_matrix[i][j]>>14);
+ }
+
+ /* Multiply above result by current csc table */
+ matrix_mul_3x3(regs->conv_matrix, regs->conv_matrix, csc_matrix_tab);
+
+ if (!(pipe->op_mode & MDP4_OP_SRC_DATA_YCBCR)) {
+ /*HACK:only "works"for src side*/
+ /* Convert back to RGB */
+ pr_info("Pipe %d, has RGB output\n", pipe->pipe_num);
+ matrix_mul_3x3(regs->conv_matrix, csc_yuv2rgb_conv_tab,
+ regs->conv_matrix);
+ }
+
+ /* Update clamps pre and post. */
+ /* TODO: different tables for different color formats? */
+ for (i = 0; i < 6; i++) {
+ regs->pre_limit[i] = csc_pre_lv_tab[i];
+ regs->post_limit[i] = csc_post_lv_tab[i];
+ }
+
+ /* update bias values, pre and post */
+ for (i = 0; i < 3; i++) {
+ regs->pre_bias[i] = csc_pre_bv_tab[i];
+ regs->post_bias[i] = csc_post_bv_tab[i] +
+ norm_q16(regs->params[HSIC_INT],
+ INTEN_MIN, INTEN_DEF, INTEN_MAX, INTENSITY_MAX);
+ }
+
+ regs->dirty = GENERATED;
+}
+
+void _hsic_update_mdp(struct mdp4_overlay_pipe *pipe)
+{
+ struct mdp4_hsic_regs *regs = &(pipe->hsic_regs);
+ int i, j, k;
+
+ uint32_t *csc_mv;
+ uint32_t *pre_lv;
+ uint32_t *post_lv;
+ uint32_t *pre_bv;
+ uint32_t *post_bv;
+
+ switch (pipe->pipe_num) {
+ case OVERLAY_PIPE_VG2:
+ csc_mv = (uint32_t *) (MDP_VG1_CSC_MVn(0) +
+ MDP4_VIDEO_OFF);
+ pre_lv = (uint32_t *) (MDP_VG1_CSC_PRE_LVn(0) +
+ MDP4_VIDEO_OFF);
+ post_lv = (uint32_t *) (MDP_VG1_CSC_POST_LVn(0) +
+ MDP4_VIDEO_OFF);
+ pre_bv = (uint32_t *) (MDP_VG1_CSC_PRE_BVn(0) +
+ MDP4_VIDEO_OFF);
+ post_bv = (uint32_t *) (MDP_VG1_CSC_POST_BVn(0) +
+ MDP4_VIDEO_OFF);
+ break;
+ case OVERLAY_PIPE_VG1:
+ default:
+ csc_mv = (uint32_t *) MDP_VG1_CSC_MVn(0);
+ pre_lv = (uint32_t *) MDP_VG1_CSC_PRE_LVn(0);
+ post_lv = (uint32_t *) MDP_VG1_CSC_POST_LVn(0);
+ pre_bv = (uint32_t *) MDP_VG1_CSC_PRE_BVn(0);
+ post_bv = (uint32_t *) MDP_VG1_CSC_POST_BVn(0);
+ break;
+ }
+
+ mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_ON, FALSE);
+
+ for (i = 0; i < 3; i++) {
+ for (j = 0; j < 3; j++) {
+ k = (3*i) + j;
+ MDP_OUTP(csc_mv + k, convert_q16_s49(
+ regs->conv_matrix[i][j]));
+ }
+ }
+
+ for (i = 0; i < 6; i++) {
+ MDP_OUTP(pre_lv + i, convert_q16_s49(regs->pre_limit[i]));
+ MDP_OUTP(post_lv + i, convert_q16_s49(regs->post_limit[i]));
+ }
+
+ for (i = 0; i < 3; i++) {
+ MDP_OUTP(pre_bv + i, convert_q16_s49(regs->pre_bias[i]));
+ MDP_OUTP(post_bv + i, convert_q16_s49(regs->post_bias[i]));
+ }
+ mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_OFF, FALSE);
+
+ regs->dirty = CLEAN;
+}
+
+void mdp4_hsic_get(struct mdp4_overlay_pipe *pipe, struct dpp_ctrl *ctrl)
+{
+ int i;
+ for (i = 0; i < NUM_HSIC_PARAM; i++)
+ _hsic_get(&(pipe->hsic_regs), i, &(ctrl->hsic_params[i]));
+}
+
+void mdp4_hsic_set(struct mdp4_overlay_pipe *pipe, struct dpp_ctrl *ctrl)
+{
+ int i;
+ for (i = 0; i < NUM_HSIC_PARAM; i++)
+ _hsic_set(&(pipe->hsic_regs), i, ctrl->hsic_params[i]);
+
+ if (pipe->hsic_regs.dirty == DIRTY)
+ _hsic_generate_csc_matrix(pipe);
+}
+
+void mdp4_hsic_update(struct mdp4_overlay_pipe *pipe)
+{
+ if (pipe->hsic_regs.dirty == GENERATED)
+ _hsic_update_mdp(pipe);
+}
diff --git a/drivers/video/msm/mdp4_overlay.c b/drivers/video/msm/mdp4_overlay.c
index dbed160..90b68ca 100644
--- a/drivers/video/msm/mdp4_overlay.c
+++ b/drivers/video/msm/mdp4_overlay.c
@@ -2114,6 +2114,10 @@
}
}
+ /* precompute HSIC matrices */
+ if (req->flags & MDP_DPP_HSIC)
+ mdp4_hsic_set(pipe, &(req->dpp));
+
mdp4_stat.overlay_set[pipe->mixer_num]++;
if (ctrl->panel_mode & MDP4_PANEL_MDDI) {
@@ -2163,6 +2167,8 @@
struct msm_fb_data_type *mfd = (struct msm_fb_data_type *)info->par;
struct mdp4_overlay_pipe *pipe;
uint32 flags;
+ struct dpp_ctrl dpp;
+ int i;
if (mfd == NULL)
return -ENODEV;
@@ -2247,6 +2253,15 @@
}
#endif
+ /* Reset any HSIC settings to default */
+ if (pipe->flags & MDP_DPP_HSIC) {
+ for (i = 0; i < NUM_HSIC_PARAM; i++)
+ dpp.hsic_params[i] = 0;
+
+ mdp4_hsic_set(pipe, &dpp);
+ mdp4_hsic_update(pipe);
+ }
+
mdp4_stat.overlay_unset[pipe->mixer_num]++;
mdp4_overlay_pipe_free(pipe);
@@ -2533,6 +2548,10 @@
}
}
+ /* write out DPP HSIC registers */
+ if (pipe->flags & MDP_DPP_HSIC)
+ mdp4_hsic_update(pipe);
+
mdp4_stat.overlay_play[pipe->mixer_num]++;
mutex_unlock(&mfd->dma->ov_mutex);
end:
diff --git a/drivers/video/msm/mdp4_overlay_dsi_cmd.c b/drivers/video/msm/mdp4_overlay_dsi_cmd.c
index 0020fd5..07322dc 100644
--- a/drivers/video/msm/mdp4_overlay_dsi_cmd.c
+++ b/drivers/video/msm/mdp4_overlay_dsi_cmd.c
@@ -56,6 +56,11 @@
spin_unlock_irqrestore(&mdp_spin_lock, flag);
}
+int mdp4_overlay_dsi_state_get(void)
+{
+ return dsi_state;
+}
+
static void dsi_clock_tout(unsigned long data)
{
if (mipi_dsi_clk_on) {
@@ -530,6 +535,7 @@
/* mutex holded by caller */
if (dsi_mfd && dsi_pipe) {
mdp4_dsi_cmd_dma_busy_wait(dsi_mfd);
+ mipi_dsi_mdp_busy_wait(dsi_mfd);
mdp4_overlay_update_dsi_cmd(dsi_mfd);
if (dsi_pipe->blt_addr)
diff --git a/drivers/video/msm/mipi_dsi.c b/drivers/video/msm/mipi_dsi.c
index 00256e6..aa210f1 100644
--- a/drivers/video/msm/mipi_dsi.c
+++ b/drivers/video/msm/mipi_dsi.c
@@ -137,7 +137,7 @@
else
up(&mfd->dma->mutex);
- pr_debug("%s:\n", __func__);
+ pr_debug("%s-:\n", __func__);
return ret;
}
@@ -171,11 +171,6 @@
clk_rate = mfd->fbi->var.pixclock;
clk_rate = min(clk_rate, mfd->panel_info.clk_max);
-
-#ifndef CONFIG_FB_MSM_MDP303
- mdp4_overlay_dsi_state_set(ST_DSI_RESUME);
-#endif
-
MIPI_OUTP(MIPI_DSI_BASE + 0x114, 1);
MIPI_OUTP(MIPI_DSI_BASE + 0x114, 0);
@@ -266,6 +261,11 @@
wmb();
}
+ if (mdp_rev >= MDP_REV_41)
+ mutex_lock(&mfd->dma->ov_mutex);
+ else
+ down(&mfd->dma->mutex);
+
ret = panel_next_on(pdev);
mipi_dsi_op_mode_config(mipi->mode);
@@ -320,6 +320,16 @@
#ifdef CONFIG_MSM_BUS_SCALING
mdp_bus_scale_update_request(2);
#endif
+
+ mdp4_overlay_dsi_state_set(ST_DSI_RESUME);
+
+ if (mdp_rev >= MDP_REV_41)
+ mutex_unlock(&mfd->dma->ov_mutex);
+ else
+ up(&mfd->dma->mutex);
+
+ pr_debug("%s-:\n", __func__);
+
return ret;
}
diff --git a/drivers/video/msm/mipi_novatek.c b/drivers/video/msm/mipi_novatek.c
index cb4bd1b..5e2e515 100644
--- a/drivers/video/msm/mipi_novatek.c
+++ b/drivers/video/msm/mipi_novatek.c
@@ -439,6 +439,10 @@
return;
mutex_lock(&mfd->dma->ov_mutex);
+ if (mdp4_overlay_dsi_state_get() <= ST_DSI_SUSPEND) {
+ mutex_unlock(&mfd->dma->ov_mutex);
+ return;
+ }
/* mdp4_dsi_cmd_busy_wait: will turn on dsi clock also */
mdp4_dsi_cmd_dma_busy_wait(mfd);
mdp4_dsi_blt_dmap_busy_wait(mfd);
diff --git a/drivers/video/msm/vidc/1080p/ddl/vcd_ddl_utils.c b/drivers/video/msm/vidc/1080p/ddl/vcd_ddl_utils.c
index a0637aa..df65d26 100644
--- a/drivers/video/msm/vidc/1080p/ddl/vcd_ddl_utils.c
+++ b/drivers/video/msm/vidc/1080p/ddl/vcd_ddl_utils.c
@@ -64,7 +64,7 @@
}
addr->alloc_handle = ion_alloc(
ddl_context->video_ion_client, alloc_size, SZ_4K,
- (1<<ION_HEAP_EBI_ID));
+ (1<<res_trk_get_mem_type()));
if (!addr->alloc_handle) {
DDL_MSG_ERROR("%s() :DDL ION alloc failed\n",
__func__);
diff --git a/drivers/video/msm/vidc/720p/ddl/vcd_ddl.h b/drivers/video/msm/vidc/720p/ddl/vcd_ddl.h
index c388407..e5a5a84 100644
--- a/drivers/video/msm/vidc/720p/ddl/vcd_ddl.h
+++ b/drivers/video/msm/vidc/720p/ddl/vcd_ddl.h
@@ -195,6 +195,7 @@
struct vcd_buffer_requirement actual_output_buf_req;
struct vcd_buffer_requirement min_output_buf_req;
struct vcd_buffer_requirement client_output_buf_req;
+ u32 idr_only_decoding;
};
union ddl_codec_data {
diff --git a/drivers/video/msm/vidc/720p/ddl/vcd_ddl_errors.c b/drivers/video/msm/vidc/720p/ddl/vcd_ddl_errors.c
index ad2fd37..e17107e 100644
--- a/drivers/video/msm/vidc/720p/ddl/vcd_ddl_errors.c
+++ b/drivers/video/msm/vidc/720p/ddl/vcd_ddl_errors.c
@@ -356,6 +356,11 @@
case ACTIVE_SPS_NOT_PRESENT:
case ACTIVE_PPS_NOT_PRESENT:
{
+ if (ddl->codec_data.decoder.idr_only_decoding) {
+ DBG("Consider warnings as errors in idr mode");
+ ddl_client_fatal_cb(ddl_context);
+ return true;
+ }
vcd_status = VCD_ERR_BITSTREAM_ERR;
break;
}
diff --git a/drivers/video/msm/vidc/720p/ddl/vcd_ddl_hal.c b/drivers/video/msm/vidc/720p/ddl/vcd_ddl_hal.c
index 6343202..f09bd71 100644
--- a/drivers/video/msm/vidc/720p/ddl/vcd_ddl_hal.c
+++ b/drivers/video/msm/vidc/720p/ddl/vcd_ddl_hal.c
@@ -807,8 +807,13 @@
}
case VCD_CODEC_H264:
{
- comv_buf_no =
- decoder->client_output_buf_req.actual_count;
+ if (decoder->idr_only_decoding)
+ comv_buf_no = decoder->min_dpb_num;
+ else
+ comv_buf_no =
+ decoder->
+ client_output_buf_req.
+ actual_count;
break;
}
}
diff --git a/drivers/video/msm/vidc/720p/ddl/vcd_ddl_helper.c b/drivers/video/msm/vidc/720p/ddl/vcd_ddl_helper.c
index 2899df6..2ec8419 100644
--- a/drivers/video/msm/vidc/720p/ddl/vcd_ddl_helper.c
+++ b/drivers/video/msm/vidc/720p/ddl/vcd_ddl_helper.c
@@ -124,6 +124,7 @@
u32 loopc;
struct ddl_frame_data_tag *found_frame = NULL;
struct ddl_mask *dpb_mask = &decoder->dpb_mask;
+ u32 temp_mask;
switch (operation) {
case DDL_DPB_OP_MARK_BUSY:
@@ -145,13 +146,17 @@
if (found_frame) {
if (operation == DDL_DPB_OP_MARK_BUSY) {
- dpb_mask->hw_mask &=
- (~(0x1 << loopc));
+ temp_mask = (~(0x1 << loopc));
+ if (decoder->idr_only_decoding)
+ temp_mask = ~(0xffffffff);
+ dpb_mask->hw_mask &= temp_mask;
*in_out_frame = *found_frame;
} else if (operation ==
DDL_DPB_OP_MARK_FREE) {
- dpb_mask->client_mask |=
- (0x1 << loopc);
+ temp_mask = (0x1 << loopc);
+ if (decoder->idr_only_decoding)
+ temp_mask = 0xffffffff;
+ dpb_mask->client_mask |= temp_mask;
*found_frame = *in_out_frame;
}
} else {
@@ -172,29 +177,35 @@
}
case DDL_DPB_OP_INIT:
{
- u32 dpb_size;
+ u32 dpb_size, index, num_dpb;
dpb_size = (!decoder->meta_data_offset) ?
decoder->dp_buf.dec_pic_buffers[0].vcd_frm.
alloc_len : decoder->meta_data_offset;
- vidc_720p_decode_set_dpb_details(decoder->dp_buf.
- no_of_dec_pic_buf,
+ if (decoder->idr_only_decoding)
+ num_dpb = decoder->min_dpb_num;
+ else
+ num_dpb = decoder->dp_buf.no_of_dec_pic_buf;
+ vidc_720p_decode_set_dpb_details(
+ num_dpb,
dpb_size,
decoder->ref_buffer.
align_physical_addr);
- for (loopc = 0;
- loopc < decoder->dp_buf.no_of_dec_pic_buf;
- ++loopc) {
+ for (loopc = 0; loopc < num_dpb; ++loopc) {
+ if (decoder->idr_only_decoding)
+ index = 0;
+ else
+ index = loopc;
vidc_720p_decode_set_dpb_buffers(loopc,
(u32 *)
decoder->
dp_buf.
dec_pic_buffers
- [loopc].
+ [index].
vcd_frm.
physical);
- VIDC_LOG1("DEC_DPB_BUFn_SIZE",
+ VIDC_LOG1("DEC_DPB_BUFn_SIZE=%d",
decoder->dp_buf.
- dec_pic_buffers[loopc].vcd_frm.
+ dec_pic_buffers[index].vcd_frm.
alloc_len);
}
break;
diff --git a/drivers/video/msm/vidc/720p/ddl/vcd_ddl_properties.c b/drivers/video/msm/vidc/720p/ddl/vcd_ddl_properties.c
index 17c2028..d1b1952 100644
--- a/drivers/video/msm/vidc/720p/ddl/vcd_ddl_properties.c
+++ b/drivers/video/msm/vidc/720p/ddl/vcd_ddl_properties.c
@@ -365,6 +365,18 @@
}
break;
}
+ case VCD_I_DEC_PICTYPE:
+ {
+ if ((sizeof(u32) == property_hdr->sz) &&
+ DDLCLIENT_STATE_IS(ddl, DDL_CLIENT_OPEN)) {
+ decoder->idr_only_decoding =
+ *(u32 *)property_value;
+ ddl_set_default_decoder_buffer_req(
+ decoder, true);
+ vcd_status = VCD_S_SUCCESS;
+ }
+ }
+ break;
case VCD_I_FRAME_RATE:
{
vcd_status = VCD_S_SUCCESS;
@@ -1462,6 +1474,7 @@
decoder->client_frame_size.stride = 176;
decoder->client_frame_size.scan_lines = 144;
decoder->progressive_only = 1;
+ decoder->idr_only_decoding = 0;
decoder->profile.profile = VCD_PROFILE_UNKNOWN;
decoder->level.level = VCD_LEVEL_UNKNOWN;
decoder->output_order = VCD_DEC_ORDER_DISPLAY;
@@ -1689,18 +1702,24 @@
min_dpb = decoder->min_dpb_num;
}
+ if (decoder->idr_only_decoding)
+ min_dpb = 1;
+
memset(output_buf_req, 0, sizeof(struct vcd_buffer_requirement));
output_buf_req->min_count = min_dpb;
num_mb = DDL_NO_OF_MB(frame_size->width, frame_size->height);
- if (num_mb >= DDL_WVGA_MBS) {
- output_buf_req->actual_count = min_dpb + 2;
- if (output_buf_req->actual_count < 10)
- output_buf_req->actual_count = 10;
- } else
- output_buf_req->actual_count = min_dpb + 5;
-
+ if (decoder->idr_only_decoding) {
+ output_buf_req->actual_count = output_buf_req->min_count;
+ } else {
+ if (num_mb >= DDL_WVGA_MBS) {
+ output_buf_req->actual_count = min_dpb + 2;
+ if (output_buf_req->actual_count < 10)
+ output_buf_req->actual_count = 10;
+ } else
+ output_buf_req->actual_count = min_dpb + 5;
+ }
output_buf_req->max_count = DDL_MAX_BUFFER_COUNT;
output_buf_req->sz = y_cb_cr_size;
if (decoder->buf_format.buffer_format != VCD_BUFFER_FORMAT_NV12)
diff --git a/drivers/video/msm/vidc/common/init/vidc_init.c b/drivers/video/msm/vidc/common/init/vidc_init.c
index 8da4ba5..1217f1f 100644
--- a/drivers/video/msm/vidc/common/init/vidc_init.c
+++ b/drivers/video/msm/vidc/common/init/vidc_init.c
@@ -526,7 +526,8 @@
}
phys_addr += buffer_addr_offset;
(*kernel_vaddr) += buffer_addr_offset;
- flags = MSM_SUBSYSTEM_MAP_IOVA;
+ flags = (buffer == BUFFER_TYPE_INPUT) ? MSM_SUBSYSTEM_MAP_IOVA :
+ MSM_SUBSYSTEM_MAP_IOVA|MSM_SUBSYSTEM_ALIGN_IOVA_8K;
mapped_buffer = msm_subsystem_map_buffer(phys_addr, length,
flags, vidc_mmu_subsystem,
sizeof(vidc_mmu_subsystem)/sizeof(unsigned int));
diff --git a/drivers/video/msm/vidc/common/vcd/vcd_device_sm.c b/drivers/video/msm/vidc/common/vcd/vcd_device_sm.c
index f8fb0fa..4c477cb 100644
--- a/drivers/video/msm/vidc/common/vcd/vcd_device_sm.c
+++ b/drivers/video/msm/vidc/common/vcd/vcd_device_sm.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2010, Code Aurora Forum. All rights reserved.
+/* Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -523,8 +523,8 @@
config->map_dev_base_addr
|| dev_ctxt->config.un_map_dev_base_addr !=
config->un_map_dev_base_addr) {
- VCD_MSG_ERROR("Device config mismatch");
- VCD_MSG_HIGH("VCD will be using config from 1st vcd_init");
+ VCD_MSG_HIGH("Device config mismatch. "
+ "VCD will be using config from 1st vcd_init");
}
*driver_handle = 0;
diff --git a/drivers/video/msm/vidc/common/vcd/vcd_sub.c b/drivers/video/msm/vidc/common/vcd/vcd_sub.c
index 35ee946..3924088 100644
--- a/drivers/video/msm/vidc/common/vcd/vcd_sub.c
+++ b/drivers/video/msm/vidc/common/vcd/vcd_sub.c
@@ -57,8 +57,8 @@
pr_err("%s() map table is full", __func__);
goto bailout;
}
+ memtype = res_trk_get_mem_type();
if (!cctxt->vcd_enable_ion) {
- memtype = res_trk_get_mem_type();
map_buffer->phy_addr = (phys_addr_t)
allocate_contiguous_memory_nomap(sz, memtype, SZ_4K);
if (!map_buffer->phy_addr) {
@@ -68,7 +68,7 @@
} else {
map_buffer->alloc_handle = ion_alloc(
cctxt->vcd_ion_client, sz, SZ_4K,
- (1<<ION_HEAP_EBI_ID));
+ (1<<memtype));
if (!map_buffer->alloc_handle) {
pr_err("%s() ION alloc failed", __func__);
goto bailout;
diff --git a/include/linux/mfd/pm8xxx/gpio.h b/include/linux/mfd/pm8xxx/gpio.h
index 0a9c95d..f2e4a21 100644
--- a/include/linux/mfd/pm8xxx/gpio.h
+++ b/include/linux/mfd/pm8xxx/gpio.h
@@ -59,6 +59,16 @@
#define PM_GPIO_VIN_L3 5
#define PM_GPIO_VIN_L17 6
+/* vin_sel: Voltage Input select on PM8058 */
+#define PM8058_GPIO_VIN_VPH 0
+#define PM8058_GPIO_VIN_BB 1
+#define PM8058_GPIO_VIN_S3 2
+#define PM8058_GPIO_VIN_L3 3
+#define PM8058_GPIO_VIN_L7 4
+#define PM8058_GPIO_VIN_L6 5
+#define PM8058_GPIO_VIN_L5 6
+#define PM8058_GPIO_VIN_L2 7
+
/* out_strength */
#define PM_GPIO_STRENGTH_NO 0
#define PM_GPIO_STRENGTH_HIGH 1
diff --git a/include/linux/mfd/pm8xxx/misc.h b/include/linux/mfd/pm8xxx/misc.h
index 2374d11..32189b2 100644
--- a/include/linux/mfd/pm8xxx/misc.h
+++ b/include/linux/mfd/pm8xxx/misc.h
@@ -35,6 +35,44 @@
UART_TX3_RX3,
};
+enum pm8xxx_coincell_chg_voltage {
+ PM8XXX_COINCELL_VOLTAGE_3p2V = 1,
+ PM8XXX_COINCELL_VOLTAGE_3p1V,
+ PM8XXX_COINCELL_VOLTAGE_3p0V,
+ PM8XXX_COINCELL_VOLTAGE_2p5V = 16
+};
+
+enum pm8xxx_coincell_chg_resistor {
+ PM8XXX_COINCELL_RESISTOR_2100_OHMS,
+ PM8XXX_COINCELL_RESISTOR_1700_OHMS,
+ PM8XXX_COINCELL_RESISTOR_1200_OHMS,
+ PM8XXX_COINCELL_RESISTOR_800_OHMS
+};
+
+enum pm8xxx_coincell_chg_state {
+ PM8XXX_COINCELL_CHG_DISABLE,
+ PM8XXX_COINCELL_CHG_ENABLE
+};
+
+struct pm8xxx_coincell_chg {
+ enum pm8xxx_coincell_chg_state state;
+ enum pm8xxx_coincell_chg_voltage voltage;
+ enum pm8xxx_coincell_chg_resistor resistor;
+};
+
+enum pm8xxx_smpl_delay {
+ PM8XXX_SMPL_DELAY_0p5,
+ PM8XXX_SMPL_DELAY_1p0,
+ PM8XXX_SMPL_DELAY_1p5,
+ PM8XXX_SMPL_DELAY_2p0,
+};
+
+enum pm8xxx_pon_config {
+ PM8XXX_DISABLE_HARD_RESET = 0,
+ PM8XXX_SHUTDOWN_ON_HARD_RESET,
+ PM8XXX_RESTART_ON_HARD_RESET,
+};
+
#if defined(CONFIG_MFD_PM8XXX_MISC) || defined(CONFIG_MFD_PM8XXX_MISC_MODULE)
/**
@@ -48,19 +86,116 @@
int pm8xxx_uart_gpio_mux_ctrl(enum pm8xxx_uart_path_sel uart_path_sel);
+/**
+ * pm8xxx_coincell_chg_config - Disables or enables the coincell charger, and
+ * configures its voltage and resistor settings.
+ * @chg_config: Holds both voltage and resistor values, and a
+ * switch to change the state of charger.
+ * If state is to disable the charger then
+ * both voltage and resistor are disregarded.
+ *
+ * RETURNS: an appropriate -ERRNO error value on error, or zero for success.
+ */
+int pm8xxx_coincell_chg_config(struct pm8xxx_coincell_chg *chg_config);
+
+/**
+ * pm8xxx_smpl_control - enables/disables SMPL detection
+ * @enable: 0 = shutdown PMIC on power loss, 1 = reset PMIC on power loss
+ *
+ * This function enables or disables the Sudden Momentary Power Loss detection
+ * module. If SMPL detection is enabled, then when a sufficiently long power
+ * loss event occurs, the PMIC will automatically reset itself. If SMPL
+ * detection is disabled, then the PMIC will shutdown when power loss occurs.
+ *
+ * RETURNS: an appropriate -ERRNO error value on error, or zero for success.
+ */
+int pm8xxx_smpl_control(int enable);
+
+/**
+ * pm8xxx_smpl_set_delay - sets the SMPL detection time delay
+ * @delay: enum value corresponding to delay time
+ *
+ * This function sets the time delay of the SMPL detection module. If power
+ * is reapplied within this interval, then the PMIC reset automatically. The
+ * SMPL detection module must be enabled for this delay time to take effect.
+ *
+ * RETURNS: an appropriate -ERRNO error value on error, or zero for success.
+ */
+int pm8xxx_smpl_set_delay(enum pm8xxx_smpl_delay delay);
+
+/**
+ * pm8xxx_watchdog_reset_control - enables/disables watchdog reset detection
+ * @enable: 0 = shutdown when PS_HOLD goes low, 1 = reset when PS_HOLD goes low
+ *
+ * This function enables or disables the PMIC watchdog reset detection feature.
+ * If watchdog reset detection is enabled, then the PMIC will reset itself
+ * when PS_HOLD goes low. If it is not enabled, then the PMIC will shutdown
+ * when PS_HOLD goes low.
+ *
+ * RETURNS: an appropriate -ERRNO error value on error, or zero for success.
+ */
+int pm8xxx_watchdog_reset_control(int enable);
+
+/**
+ * pm8xxx_hard_reset_config - Allows different reset configurations
+ *
+ * config = DISABLE_HARD_RESET to disable hard reset
+ * = SHUTDOWN_ON_HARD_RESET to turn off the system on hard reset
+ * = RESTART_ON_HARD_RESET to restart the system on hard reset
+ *
+ * RETURNS: an appropriate -ERRNO error value on error, or zero for success.
+ */
+int pm8xxx_hard_reset_config(enum pm8xxx_pon_config config);
+
+/**
+ * pm8xxx_stay_on - enables stay_on feature
+ *
+ * PMIC stay-on feature allows PMIC to ignore MSM PS_HOLD=low
+ * signal so that some special functions like debugging could be
+ * performed.
+ *
+ * This feature should not be used in any product release.
+ *
+ * RETURNS: an appropriate -ERRNO error value on error, or zero for success.
+ */
+int pm8xxx_stay_on(void);
+
#else
static inline int pm8xxx_reset_pwr_off(int reset)
{
return -ENODEV;
}
-
static inline int
pm8xxx_uart_gpio_mux_ctrl(enum pm8xxx_uart_path_sel uart_path_sel)
{
return -ENODEV;
}
-
+static inline int
+pm8xxx_coincell_chg_config(struct pm8xxx_coincell_chg *chg_config)
+{
+ return -ENODEV;
+}
+static inline int pm8xxx_smpl_set_delay(enum pm8xxx_smpl_delay delay)
+{
+ return -ENODEV;
+}
+static inline int pm8xxx_smpl_control(int enable)
+{
+ return -ENODEV;
+}
+static inline int pm8xxx_watchdog_reset_control(int enable)
+{
+ return -ENODEV;
+}
+static inline int pm8xxx_hard_reset_config(enum pm8xxx_pon_config config)
+{
+ return -ENODEV;
+}
+static inline int pm8xxx_stay_on(void)
+{
+ return -ENODEV;
+}
#endif
#endif
diff --git a/include/linux/pmic8058-nfc.h b/include/linux/mfd/pm8xxx/nfc.h
similarity index 70%
rename from include/linux/pmic8058-nfc.h
rename to include/linux/mfd/pm8xxx/nfc.h
index 5b2d6cf..e58e0a9 100644
--- a/include/linux/pmic8058-nfc.h
+++ b/include/linux/mfd/pm8xxx/nfc.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2010, Code Aurora Forum. All rights reserved.
+/* Copyright (c) 2010,2011 Code Aurora Forum. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -10,10 +10,12 @@
* GNU General Public License for more details.
*
*/
-#ifndef __PMIC8058_NFC_H__
-#define __PMIC8058_NFC_H__
+#ifndef __PM8XXX_NFC_H__
+#define __PM8XXX_NFC_H__
-struct pm8058_nfc_device;
+struct pm8xxx_nfc_device;
+
+#define PM8XXX_NFC_DEV_NAME "pm8xxx-nfc"
/* masks, flags and status */
#define PM_NFC_VDDLDO_MON_LEVEL 0x0003
@@ -46,32 +48,32 @@
PM_NFC_VDDLDO_OK_HIGH)
/*
- * pm8058_nfc_request - request a handle to access NFC device
+ * pm8xxx_nfc_request - request a handle to access NFC device
*/
-struct pm8058_nfc_device *pm8058_nfc_request(void);
+struct pm8xxx_nfc_device *pm8xxx_nfc_request(void);
/*
- * pm8058_nfc_config - configure NFC signals
+ * pm8xxx_nfc_config - configure NFC signals
*
* @nfcdev: the NFC device
* @mask: signal mask to configure
* @flags: control flags
*/
-int pm8058_nfc_config(struct pm8058_nfc_device *nfcdev, u32 mask, u32 flags);
+int pm8xxx_nfc_config(struct pm8xxx_nfc_device *nfcdev, u32 mask, u32 flags);
/*
- * pm8058_nfc_get_status - get NFC status
+ * pm8xxx_nfc_get_status - get NFC status
*
* @nfcdev: the NFC device
* @mask: of status mask to read
* @status: pointer to the status variable
*/
-int pm8058_nfc_get_status(struct pm8058_nfc_device *nfcdev,
+int pm8xxx_nfc_get_status(struct pm8xxx_nfc_device *nfcdev,
u32 mask, u32 *status);
/*
- * pm8058_nfc_free - free the NFC device
+ * pm8xxx_nfc_free - free the NFC device
*/
-void pm8058_nfc_free(struct pm8058_nfc_device *nfcdev);
+void pm8xxx_nfc_free(struct pm8xxx_nfc_device *nfcdev);
-#endif /* __PMIC8058_NFC_H__ */
+#endif /* __PM8XXX_NFC_H__ */
diff --git a/include/linux/mfd/pm8xxx/tm.h b/include/linux/mfd/pm8xxx/tm.h
index 01edb97..5eeefd9 100644
--- a/include/linux/mfd/pm8xxx/tm.h
+++ b/include/linux/mfd/pm8xxx/tm.h
@@ -24,6 +24,7 @@
enum pm8xxx_tm_adc_type {
PM8XXX_TM_ADC_NONE, /* Estimates temp based on overload level. */
+ PM8XXX_TM_ADC_PM8058_ADC,
PM8XXX_TM_ADC_PM8921_ADC,
};
diff --git a/include/linux/mfd/pm8xxx/upl.h b/include/linux/mfd/pm8xxx/upl.h
new file mode 100644
index 0000000..b0e94a9
--- /dev/null
+++ b/include/linux/mfd/pm8xxx/upl.h
@@ -0,0 +1,65 @@
+/* Copyright (c) 2010,2011 Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ */
+#ifndef __PM8XXX_UPL_H__
+#define __PM8XXX_UPL_H__
+
+struct pm8xxx_upl_device;
+
+#define PM8XXX_UPL_DEV_NAME "pm8xxx-upl"
+
+/* control masks and flags */
+#define PM8XXX_UPL_MOD_ENABLE_MASK (0x10)
+#define PM8XXX_UPL_MOD_ENABLE (0x10)
+#define PM8XXX_UPL_MOD_DISABLE (0x00)
+
+#define PM8XXX_UPL_OUT_DTEST_MASK (0xE0)
+#define PM8XXX_UPL_OUT_GPIO_ONLY (0x00)
+#define PM8XXX_UPL_OUT_DTEST_1 (0x80)
+#define PM8XXX_UPL_OUT_DTEST_2 (0xA0)
+#define PM8XXX_UPL_OUT_DTEST_3 (0xC0)
+#define PM8XXX_UPL_OUT_DTEST_4 (0xE0)
+
+#define PM8XXX_UPL_IN_A_MASK (0x01)
+#define PM8XXX_UPL_IN_A_GPIO (0x00)
+#define PM8XXX_UPL_IN_A_DTEST (0x01)
+#define PM8XXX_UPL_IN_B_MASK (0x02)
+#define PM8XXX_UPL_IN_B_GPIO (0x00)
+#define PM8XXX_UPL_IN_B_DTEST (0x02)
+#define PM8XXX_UPL_IN_C_MASK (0x04)
+#define PM8XXX_UPL_IN_C_GPIO (0x00)
+#define PM8XXX_UPL_IN_C_DTEST (0x04)
+#define PM8XXX_UPL_IN_D_MASK (0x08)
+#define PM8XXX_UPL_IN_D_GPIO (0x00)
+#define PM8XXX_UPL_IN_D_DTEST (0x08)
+
+/*
+ * pm8xxx_upl_request - request a handle to access UPL device
+ */
+struct pm8xxx_upl_device *pm8xxx_upl_request(void);
+
+int pm8xxx_upl_read_truthtable(struct pm8xxx_upl_device *upldev,
+ u16 *truthtable);
+
+int pm8xxx_upl_write_truthtable(struct pm8xxx_upl_device *upldev,
+ u16 truthtable);
+
+/*
+ * pm8xxx_upl_config - configure UPL I/O settings and UPL enable/disable
+ *
+ * @upldev: the UPL device
+ * @mask: setting mask to configure
+ * @flags: setting flags
+ */
+int pm8xxx_upl_config(struct pm8xxx_upl_device *upldev, u32 mask, u32 flags);
+
+#endif /* __PM8XXX_UPL_H__ */
diff --git a/include/linux/mfd/pm8xxx/vibrator.h b/include/linux/mfd/pm8xxx/vibrator.h
index 3a269a0..cfea1c9 100644
--- a/include/linux/mfd/pm8xxx/vibrator.h
+++ b/include/linux/mfd/pm8xxx/vibrator.h
@@ -15,10 +15,25 @@
#define PM8XXX_VIBRATOR_DEV_NAME "pm8xxx-vib"
+enum pm8xxx_vib_en_mode {
+ PM8XXX_VIB_MANUAL,
+ PM8XXX_VIB_DTEST1,
+ PM8XXX_VIB_DTEST2,
+ PM8XXX_VIB_DTEST3
+};
+
+struct pm8xxx_vib_config {
+ u16 drive_mV;
+ u8 active_low;
+ enum pm8xxx_vib_en_mode enable_mode;
+};
+
struct pm8xxx_vibrator_platform_data {
int initial_vibrate_ms;
int max_timeout_ms;
int level_mV;
};
+int pm8xxx_vibrator_config(struct pm8xxx_vib_config *vib_config);
+
#endif /* __PMIC8XXX_VIBRATOR_H__ */
diff --git a/include/linux/mfd/pmic8058.h b/include/linux/mfd/pmic8058.h
index 4d9f257..cf753b5d 100644
--- a/include/linux/mfd/pmic8058.h
+++ b/include/linux/mfd/pmic8058.h
@@ -15,12 +15,39 @@
*
*/
+#ifndef __MFD_PMIC8058_H__
+#define __MFD_PMIC8058_H__
+
#include <linux/irq.h>
#include <linux/mfd/core.h>
+#include <linux/mfd/pm8xxx/irq.h>
+#include <linux/mfd/pm8xxx/gpio.h>
+#include <linux/mfd/pm8xxx/mpp.h>
+#include <linux/mfd/pm8xxx/rtc.h>
+#include <linux/input/pmic8xxx-pwrkey.h>
+#include <linux/input/pmic8xxx-keypad.h>
+#include <linux/mfd/pm8xxx/vibrator.h>
+#include <linux/mfd/pm8xxx/nfc.h>
+#include <linux/mfd/pm8xxx/upl.h>
+#include <linux/mfd/pm8xxx/misc.h>
+#include <linux/mfd/pm8xxx/batt-alarm.h>
+#include <linux/leds-pmic8058.h>
+#include <linux/pmic8058-othc.h>
+#include <linux/mfd/pm8xxx/tm.h>
+#include <linux/pmic8058-xoadc.h>
+#include <linux/regulator/pmic8058-regulator.h>
+#include <linux/regulator/pm8058-xo.h>
+#include <linux/pwm.h>
+#include <linux/pmic8058-pwm.h>
#define PM8058_GPIOS 40
#define PM8058_MPPS 12
+#define PM8058_GPIO_BLOCK_START 24
+#define PM8058_MPP_BLOCK_START 16
+
+#define PM8058_NR_IRQS 256
+
#define PM8058_IRQ_BLOCK_BIT(block, bit) ((block) * 8 + (bit))
/* MPPs and GPIOs [0,N) */
@@ -29,146 +56,58 @@
#define PM8058_GPIO_IRQ(base, gpio) ((base) + \
PM8058_IRQ_BLOCK_BIT(24, (gpio)))
-#define PM8058_KEYPAD_IRQ(base) ((base) + PM8058_IRQ_BLOCK_BIT(9, 2))
-#define PM8058_KEYSTUCK_IRQ(base) ((base) + PM8058_IRQ_BLOCK_BIT(9, 3))
+/* PM8058 IRQ's */
+#define PM8058_VCP_IRQ PM8058_IRQ_BLOCK_BIT(1, 0)
+#define PM8058_CHGILIM_IRQ PM8058_IRQ_BLOCK_BIT(1, 3)
+#define PM8058_VBATDET_LOW_IRQ PM8058_IRQ_BLOCK_BIT(1, 4)
+#define PM8058_BATT_REPLACE_IRQ PM8058_IRQ_BLOCK_BIT(1, 5)
+#define PM8058_CHGINVAL_IRQ PM8058_IRQ_BLOCK_BIT(1, 6)
+#define PM8058_CHGVAL_IRQ PM8058_IRQ_BLOCK_BIT(1, 7)
+#define PM8058_CHG_END_IRQ PM8058_IRQ_BLOCK_BIT(2, 0)
+#define PM8058_FASTCHG_IRQ PM8058_IRQ_BLOCK_BIT(2, 1)
+#define PM8058_CHGSTATE_IRQ PM8058_IRQ_BLOCK_BIT(2, 3)
+#define PM8058_AUTO_CHGFAIL_IRQ PM8058_IRQ_BLOCK_BIT(2, 4)
+#define PM8058_AUTO_CHGDONE_IRQ PM8058_IRQ_BLOCK_BIT(2, 5)
+#define PM8058_ATCFAIL_IRQ PM8058_IRQ_BLOCK_BIT(2, 6)
+#define PM8058_ATC_DONE_IRQ PM8058_IRQ_BLOCK_BIT(2, 7)
+#define PM8058_OVP_OK_IRQ PM8058_IRQ_BLOCK_BIT(3, 0)
+#define PM8058_COARSE_DET_OVP_IRQ PM8058_IRQ_BLOCK_BIT(3, 1)
+#define PM8058_VCPMAJOR_IRQ PM8058_IRQ_BLOCK_BIT(3, 2)
+#define PM8058_CHG_GONE_IRQ PM8058_IRQ_BLOCK_BIT(3, 3)
+#define PM8058_CHGTLIMIT_IRQ PM8058_IRQ_BLOCK_BIT(3, 4)
+#define PM8058_CHGHOT_IRQ PM8058_IRQ_BLOCK_BIT(3, 5)
+#define PM8058_BATTTEMP_IRQ PM8058_IRQ_BLOCK_BIT(3, 6)
+#define PM8058_BATTCONNECT_IRQ PM8058_IRQ_BLOCK_BIT(3, 7)
+#define PM8058_BATFET_IRQ PM8058_IRQ_BLOCK_BIT(5, 4)
+#define PM8058_VBATDET_IRQ PM8058_IRQ_BLOCK_BIT(5, 5)
+#define PM8058_VBAT_IRQ PM8058_IRQ_BLOCK_BIT(5, 6)
-#define PM8058_VCP_IRQ(base) ((base) + PM8058_IRQ_BLOCK_BIT(1, 0))
-#define PM8058_CHGILIM_IRQ(base) ((base) + PM8058_IRQ_BLOCK_BIT(1, 3))
-#define PM8058_VBATDET_LOW_IRQ(base) ((base) + PM8058_IRQ_BLOCK_BIT(1, 4))
-#define PM8058_BATT_REPLACE_IRQ(base) ((base) + PM8058_IRQ_BLOCK_BIT(1, 5))
-#define PM8058_CHGINVAL_IRQ(base) ((base) + PM8058_IRQ_BLOCK_BIT(1, 6))
-#define PM8058_CHGVAL_IRQ(base) ((base) + PM8058_IRQ_BLOCK_BIT(1, 7))
-#define PM8058_CHG_END_IRQ(base) ((base) + PM8058_IRQ_BLOCK_BIT(2, 0))
-#define PM8058_FASTCHG_IRQ(base) ((base) + PM8058_IRQ_BLOCK_BIT(2, 1))
-#define PM8058_CHGSTATE_IRQ(base) ((base) + PM8058_IRQ_BLOCK_BIT(2, 3))
-#define PM8058_AUTO_CHGFAIL_IRQ(base) ((base) + PM8058_IRQ_BLOCK_BIT(2, 4))
-#define PM8058_AUTO_CHGDONE_IRQ(base) ((base) + PM8058_IRQ_BLOCK_BIT(2, 5))
-#define PM8058_ATCFAIL_IRQ(base) ((base) + PM8058_IRQ_BLOCK_BIT(2, 6))
-#define PM8058_ATC_DONE_IRQ(base) ((base) + PM8058_IRQ_BLOCK_BIT(2, 7))
-#define PM8058_OVP_OK_IRQ(base) ((base) + PM8058_IRQ_BLOCK_BIT(3, 0))
-#define PM8058_COARSE_DET_OVP_IRQ(base) ((base) + PM8058_IRQ_BLOCK_BIT(3, 1))
-#define PM8058_VCPMAJOR_IRQ(base) ((base) + PM8058_IRQ_BLOCK_BIT(3, 2))
-#define PM8058_CHG_GONE_IRQ(base) ((base) + PM8058_IRQ_BLOCK_BIT(3, 3))
-#define PM8058_CHGTLIMIT_IRQ(base) ((base) + PM8058_IRQ_BLOCK_BIT(3, 4))
-#define PM8058_CHGHOT_IRQ(base) ((base) + PM8058_IRQ_BLOCK_BIT(3, 5))
-#define PM8058_BATTTEMP_IRQ(base) ((base) + PM8058_IRQ_BLOCK_BIT(3, 6))
-#define PM8058_BATTCONNECT_IRQ(base) ((base) + PM8058_IRQ_BLOCK_BIT(3, 7))
-#define PM8058_BATFET_IRQ(base) ((base) + PM8058_IRQ_BLOCK_BIT(5, 4))
-#define PM8058_VBATDET_IRQ(base) ((base) + PM8058_IRQ_BLOCK_BIT(5, 5))
-#define PM8058_VBAT_IRQ(base) ((base) + PM8058_IRQ_BLOCK_BIT(5, 6))
-
-#define PM8058_CBLPWR_IRQ(base) ((base) + PM8058_IRQ_BLOCK_BIT(4, 3))
-
-#define PM8058_PWRKEY_REL_IRQ(base) ((base) + PM8058_IRQ_BLOCK_BIT(6, 2))
-#define PM8058_PWRKEY_PRESS_IRQ(base) ((base) + PM8058_IRQ_BLOCK_BIT(6, 3))
-#define PM8058_SW_0_IRQ(base) ((base) + PM8058_IRQ_BLOCK_BIT(7, 1))
-#define PM8058_IR_0_IRQ(base) ((base) + PM8058_IRQ_BLOCK_BIT(7, 0))
-#define PM8058_SW_1_IRQ(base) ((base) + PM8058_IRQ_BLOCK_BIT(7, 3))
-#define PM8058_IR_1_IRQ(base) ((base) + PM8058_IRQ_BLOCK_BIT(7, 2))
-#define PM8058_SW_2_IRQ(base) ((base) + PM8058_IRQ_BLOCK_BIT(7, 5))
-#define PM8058_IR_2_IRQ(base) ((base) + PM8058_IRQ_BLOCK_BIT(7, 4))
-#define PM8058_RTC_IRQ(base) ((base) + PM8058_IRQ_BLOCK_BIT(6, 5))
-#define PM8058_RTC_ALARM_IRQ(base) ((base) + PM8058_IRQ_BLOCK_BIT(4, 7))
-#define PM8058_ADC_IRQ(base) ((base) + PM8058_IRQ_BLOCK_BIT(9, 4))
-#define PM8058_TEMP_ALARM_IRQ(base) ((base) + PM8058_IRQ_BLOCK_BIT(6, 7))
-#define PM8058_OSCHALT_IRQ(base) ((base) + PM8058_IRQ_BLOCK_BIT(4, 6))
-#define PM8058_BATT_ALARM_IRQ(base) ((base) + PM8058_IRQ_BLOCK_BIT(5, 6))
-#define PM8058_RESOUT_IRQ(base) ((base) + PM8058_IRQ_BLOCK_BIT(6, 4))
-
-struct pm8058_chip;
-
-struct pm8058_platform_data {
- /* This table is only needed for misc interrupts. */
- int irq_base;
- int irq;
- int (*init)(struct pm8058_chip *pm_chip);
-
- int num_subdevs;
- struct mfd_cell *sub_devices;
- int irq_trigger_flags;
- struct mfd_cell *charger_sub_device;
-};
-
-struct pm8058_gpio_platform_data {
- int gpio_base;
- int irq_base;
- int (*init)(void);
-};
-
-/* GPIO parameters */
-/* direction */
-#define PM_GPIO_DIR_OUT 0x01
-#define PM_GPIO_DIR_IN 0x02
-#define PM_GPIO_DIR_BOTH (PM_GPIO_DIR_OUT | PM_GPIO_DIR_IN)
-
-/* output_buffer */
-#define PM_GPIO_OUT_BUF_OPEN_DRAIN 1
-#define PM_GPIO_OUT_BUF_CMOS 0
-
-/* pull */
-#define PM_GPIO_PULL_UP_30 0
-#define PM_GPIO_PULL_UP_1P5 1
-#define PM_GPIO_PULL_UP_31P5 2
-#define PM_GPIO_PULL_UP_1P5_30 3
-#define PM_GPIO_PULL_DN 4
-#define PM_GPIO_PULL_NO 5
-
-/* vin_sel: Voltage Input Select */
-#define PM_GPIO_VIN_VPH 0
-#define PM_GPIO_VIN_BB 1
-#define PM_GPIO_VIN_S3 2
-#define PM_GPIO_VIN_L3 3
-#define PM_GPIO_VIN_L7 4
-#define PM_GPIO_VIN_L6 5
-#define PM_GPIO_VIN_L5 6
-#define PM_GPIO_VIN_L2 7
-
-/* out_strength */
-#define PM_GPIO_STRENGTH_NO 0
-#define PM_GPIO_STRENGTH_HIGH 1
-#define PM_GPIO_STRENGTH_MED 2
-#define PM_GPIO_STRENGTH_LOW 3
-
-/* function */
-#define PM_GPIO_FUNC_NORMAL 0
-#define PM_GPIO_FUNC_PAIRED 1
-#define PM_GPIO_FUNC_1 2
-#define PM_GPIO_FUNC_2 3
-#define PM_GPIO_DTEST1 4
-#define PM_GPIO_DTEST2 5
-#define PM_GPIO_DTEST3 6
-#define PM_GPIO_DTEST4 7
-
-struct pm8058_gpio {
- int direction;
- int output_buffer;
- int output_value;
- int pull;
- int vin_sel; /* 0..7 */
- int out_strength;
- int function;
- int inv_int_pol; /* invert interrupt polarity */
- int disable_pin; /* disable pin and tri-state its pad */
-};
+#define PM8058_RTC_IRQ PM8058_IRQ_BLOCK_BIT(6, 5)
+#define PM8058_RTC_ALARM_IRQ PM8058_IRQ_BLOCK_BIT(4, 7)
+#define PM8058_PWRKEY_REL_IRQ PM8058_IRQ_BLOCK_BIT(6, 2)
+#define PM8058_PWRKEY_PRESS_IRQ PM8058_IRQ_BLOCK_BIT(6, 3)
+#define PM8058_KEYPAD_IRQ PM8058_IRQ_BLOCK_BIT(9, 2)
+#define PM8058_KEYSTUCK_IRQ PM8058_IRQ_BLOCK_BIT(9, 3)
+#define PM8058_BATT_ALARM_IRQ PM8058_IRQ_BLOCK_BIT(5, 6)
+#define PM8058_SW_0_IRQ PM8058_IRQ_BLOCK_BIT(7, 1)
+#define PM8058_IR_0_IRQ PM8058_IRQ_BLOCK_BIT(7, 0)
+#define PM8058_SW_1_IRQ PM8058_IRQ_BLOCK_BIT(7, 3)
+#define PM8058_IR_1_IRQ PM8058_IRQ_BLOCK_BIT(7, 2)
+#define PM8058_SW_2_IRQ PM8058_IRQ_BLOCK_BIT(7, 5)
+#define PM8058_IR_2_IRQ PM8058_IRQ_BLOCK_BIT(7, 4)
+#define PM8058_TEMPSTAT_IRQ PM8058_IRQ_BLOCK_BIT(6, 7)
+#define PM8058_OVERTEMP_IRQ PM8058_IRQ_BLOCK_BIT(4, 2)
+#define PM8058_ADC_IRQ PM8058_IRQ_BLOCK_BIT(9, 4)
+#define PM8058_OSCHALT_IRQ PM8058_IRQ_BLOCK_BIT(4, 6)
+#define PM8058_CBLPWR_IRQ PM8058_IRQ_BLOCK_BIT(4, 3)
+#define PM8058_RESOUT_IRQ PM8058_IRQ_BLOCK_BIT(6, 4)
struct pmic8058_charger_data {
unsigned int max_source_current;
int charger_type;
+ bool charger_data_valid;
};
-/* chip revision */
-#define PM_8058_REV_1p0 0xE1
-#define PM_8058_REV_2p0 0xE2
-#define PM_8058_REV_2p1 0xE3
-
-/* misc: control mask and flag */
-#define PM8058_UART_MUX_MASK 0x60
-
-#define PM8058_UART_MUX_NO 0x0
-#define PM8058_UART_MUX_1 0x20
-#define PM8058_UART_MUX_2 0x40
-#define PM8058_UART_MUX_3 0x60
-
enum pon_config{
DISABLE_HARD_RESET = 0,
SHUTDOWN_ON_HARD_RESET,
@@ -183,19 +122,27 @@
PM8058_SMPL_DELAY_2p0,
};
-/* Note -do not call pm8058_read and pm8058_write in an atomic context */
-int pm8058_read(struct pm8058_chip *pm_chip, u16 addr, u8 *values,
- unsigned int len);
-int pm8058_write(struct pm8058_chip *pm_chip, u16 addr, u8 *values,
- unsigned int len);
-
-int pm8058_gpio_config(int gpio, struct pm8058_gpio *param);
-
-int pm8058_rev(struct pm8058_chip *pm_chip);
-
-int pm8058_irq_get_rt_status(struct pm8058_chip *pm_chip, int irq);
-
-int pm8058_misc_control(struct pm8058_chip *pm_chip, int mask, int flag);
+struct pm8058_platform_data {
+ struct pm8xxx_mpp_platform_data *mpp_pdata;
+ struct pm8xxx_keypad_platform_data *keypad_pdata;
+ struct pm8xxx_gpio_platform_data *gpio_pdata;
+ struct pm8xxx_irq_platform_data *irq_pdata;
+ struct pm8xxx_rtc_platform_data *rtc_pdata;
+ struct pm8xxx_pwrkey_platform_data *pwrkey_pdata;
+ struct pm8xxx_vibrator_platform_data *vibrator_pdata;
+ struct pm8xxx_misc_platform_data *misc_pdata;
+ struct pmic8058_leds_platform_data *leds_pdata;
+ struct pmic8058_othc_config_pdata *othc0_pdata;
+ struct pmic8058_othc_config_pdata *othc1_pdata;
+ struct pmic8058_othc_config_pdata *othc2_pdata;
+ struct xoadc_platform_data *xoadc_pdata;
+ struct pm8058_pwm_pdata *pwm_pdata;
+ struct pm8058_vreg_pdata *regulator_pdatas;
+ int num_regulators;
+ struct pm8058_xo_pdata *xo_buffer_pdata;
+ int num_xo_buffers;
+ struct pmic8058_charger_data *charger_pdata;
+};
#ifdef CONFIG_PMIC8058
int pm8058_reset_pwr_off(int reset);
@@ -256,3 +203,5 @@
* RETURNS: an appropriate -ERRNO error value on error, or zero for success.
*/
int pm8058_stay_on(void);
+
+#endif /* __MFD_PMIC8058_H__ */
diff --git a/include/linux/msm_adc.h b/include/linux/msm_adc.h
index 5d5fb1b..51371a6 100644
--- a/include/linux/msm_adc.h
+++ b/include/linux/msm_adc.h
@@ -344,22 +344,24 @@
int32_t adc_channel_request_conv(void *h, struct completion *conv_complete_evt);
int32_t adc_channel_read_result(void *h, struct adc_chan_result *chan_result);
#else
-int32_t adc_channel_open(uint32_t channel, void **h)
+static int32_t adc_channel_open(uint32_t channel, void **h)
{
pr_err("%s.not supported.\n", __func__);
return -ENODEV;
}
-int32_t adc_channel_close(void *h)
+static int32_t adc_channel_close(void *h)
{
pr_err("%s.not supported.\n", __func__);
return -ENODEV;
}
-int32_t adc_channel_request_conv(void *h, struct completion *conv_complete_evt)
+static int32_t
+adc_channel_request_conv(void *h, struct completion *conv_complete_evt)
{
pr_err("%s.not supported.\n", __func__);
return -ENODEV;
}
-int32_t adc_channel_read_result(void *h, struct adc_chan_result *chan_result)
+static int32_t
+adc_channel_read_result(void *h, struct adc_chan_result *chan_result)
{
pr_err("%s.not supported.\n", __func__);
return -ENODEV;
diff --git a/include/linux/msm_mdp.h b/include/linux/msm_mdp.h
index 5011229..5c67471 100644
--- a/include/linux/msm_mdp.h
+++ b/include/linux/msm_mdp.h
@@ -106,6 +106,14 @@
FB_IMG,
};
+enum {
+ HSIC_HUE = 0,
+ HSIC_SAT,
+ HSIC_INT,
+ HSIC_CON,
+ NUM_HSIC_PARAM,
+};
+
/* mdp_blit_req flag values */
#define MDP_ROT_NOP 0
#define MDP_FLIP_LR 0x1
@@ -132,6 +140,7 @@
#define MDP_OV_PLAY_NOWAIT 0x00200000
#define MDP_SOURCE_ROTATED_90 0x00100000
#define MDP_MEMORY_ID_TYPE_FB 0x00001000
+#define MDP_DPP_HSIC 0x00080000
#define MDP_TRANSP_NOP 0xffffffff
#define MDP_ALPHA_NOP 0xff
@@ -250,6 +259,7 @@
* smoothed picture.
*/
int8_t sharp_strength;
+ int8_t hsic_params[NUM_HSIC_PARAM];
};
struct mdp_overlay {
diff --git a/include/linux/pmic8058-upl.h b/include/linux/pmic8058-upl.h
deleted file mode 100644
index a8979f4..0000000
--- a/include/linux/pmic8058-upl.h
+++ /dev/null
@@ -1,63 +0,0 @@
-/* Copyright (c) 2010, Code Aurora Forum. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 and
- * only version 2 as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- */
-#ifndef __PMIC8058_UPL_H__
-#define __PMIC8058_UPL_H__
-
-struct pm8058_upl_device;
-
-/* control masks and flags */
-#define PM8058_UPL_MOD_ENABLE_MASK (0x10)
-#define PM8058_UPL_MOD_ENABLE (0x10)
-#define PM8058_UPL_MOD_DISABLE (0x00)
-
-#define PM8058_UPL_OUT_DTEST_MASK (0xE0)
-#define PM8058_UPL_OUT_GPIO_ONLY (0x00)
-#define PM8058_UPL_OUT_DTEST_1 (0x80)
-#define PM8058_UPL_OUT_DTEST_2 (0xA0)
-#define PM8058_UPL_OUT_DTEST_3 (0xC0)
-#define PM8058_UPL_OUT_DTEST_4 (0xE0)
-
-#define PM8058_UPL_IN_A_MASK (0x01)
-#define PM8058_UPL_IN_A_GPIO (0x00)
-#define PM8058_UPL_IN_A_DTEST (0x01)
-#define PM8058_UPL_IN_B_MASK (0x02)
-#define PM8058_UPL_IN_B_GPIO (0x00)
-#define PM8058_UPL_IN_B_DTEST (0x02)
-#define PM8058_UPL_IN_C_MASK (0x04)
-#define PM8058_UPL_IN_C_GPIO (0x00)
-#define PM8058_UPL_IN_C_DTEST (0x04)
-#define PM8058_UPL_IN_D_MASK (0x08)
-#define PM8058_UPL_IN_D_GPIO (0x00)
-#define PM8058_UPL_IN_D_DTEST (0x08)
-
-/*
- * pm8058_upl_request - request a handle to access UPL device
- */
-struct pm8058_upl_device *pm8058_upl_request(void);
-
-int pm8058_upl_read_truthtable(struct pm8058_upl_device *upldev,
- u16 *truthtable);
-
-int pm8058_upl_write_truthtable(struct pm8058_upl_device *upldev,
- u16 truthtable);
-
-/*
- * pm8058_upl_config - configure UPL I/O settings and UPL enable/disable
- *
- * @upldev: the UPL device
- * @mask: setting mask to configure
- * @flags: setting flags
- */
-int pm8058_upl_config(struct pm8058_upl_device *upldev, u32 mask, u32 flags);
-
-#endif /* __PMIC8058_UPL_H__ */
diff --git a/include/linux/regulator/pm8058-xo.h b/include/linux/regulator/pm8058-xo.h
index 9b363c4..a2b8aeb 100644
--- a/include/linux/regulator/pm8058-xo.h
+++ b/include/linux/regulator/pm8058-xo.h
@@ -25,6 +25,7 @@
struct pm8058_xo_pdata {
struct regulator_init_data init_data;
+ int id;
};
#endif
diff --git a/include/linux/regulator/pmic8058-regulator.h b/include/linux/regulator/pmic8058-regulator.h
index 83d4412..3eeaa61 100644
--- a/include/linux/regulator/pmic8058-regulator.h
+++ b/include/linux/regulator/pmic8058-regulator.h
@@ -80,6 +80,7 @@
struct pm8058_vreg_pdata {
struct regulator_init_data init_data;
+ int id;
unsigned pull_down_enable;
unsigned pin_ctrl;
enum pm8058_vreg_pin_fn pin_fn;
diff --git a/include/linux/slimbus/slimbus.h b/include/linux/slimbus/slimbus.h
index 26ca79a..2b5adb3 100644
--- a/include/linux/slimbus/slimbus.h
+++ b/include/linux/slimbus/slimbus.h
@@ -83,6 +83,12 @@
#define SLIM_MSG_MC_NEXT_REMOVE_CHANNEL 0x58
#define SLIM_MSG_MC_RECONFIGURE_NOW 0x5F
+/*
+ * Clock pause flag to indicate that the reconfig message
+ * corresponds to clock pause sequence
+ */
+#define SLIM_MSG_CLK_PAUSE_SEQ_FLG (1U << 8)
+
/* Value management messages */
#define SLIM_MSG_MC_REQUEST_VALUE 0x60
#define SLIM_MSG_MC_REQUEST_CHANGE_VALUE 0x61
@@ -150,7 +156,9 @@
* For the header information, refer to Table 34-36.
* @rl: Header field. remaining length.
* @mt: Header field. Message type.
- * @mc: Header field. Message code for type mt.
+ * @mc: Header field. LSB is message code for type mt. Framework will set MSB to
+ * SLIM_MSG_CLK_PAUSE_SEQ_FLG in case "mc" in the reconfiguration sequence
+ * is for pausing the clock.
* @dt: Header field. Destination type.
* @ec: Element size. Used for elemental access APIs.
* @len: Length of payload. (excludes ec)
@@ -166,7 +174,7 @@
struct slim_msg_txn {
u8 rl;
u8 mt;
- u8 mc;
+ u16 mc;
u8 dt;
u16 ec;
u8 len;
@@ -670,7 +678,7 @@
*/
extern int slim_xfer_msg(struct slim_controller *ctrl,
struct slim_device *sbdev, struct slim_ele_access *msg,
- u8 mc, u8 *rbuf, const u8 *wbuf, u8 len);
+ u16 mc, u8 *rbuf, const u8 *wbuf, u8 len);
/* end of message apis */
/* Port management for manager device APIs */
diff --git a/include/linux/usb/msm_hsusb.h b/include/linux/usb/msm_hsusb.h
index 955d229..4c01f5b 100644
--- a/include/linux/usb/msm_hsusb.h
+++ b/include/linux/usb/msm_hsusb.h
@@ -72,6 +72,9 @@
#define IDEV_CHG_MIN 500
#define IUNIT 100
+#define IDEV_ACA_CHG_MAX 1500
+#define IDEV_ACA_CHG_LIMIT 500
+
/**
* Different states involved in USB charger detection.
*
@@ -152,7 +155,7 @@
enum usb_mode_type default_mode;
enum msm_usb_phy_type phy_type;
void (*setup_gpio)(enum usb_otg_state state);
- char *pclk_src_name;
+ const char *pclk_src_name;
int pmic_id_irq;
bool mhl_enable;
};
@@ -185,6 +188,7 @@
* connected. Useful only when ACA_A charger is
* connected.
* @mA_port: The amount of current drawn by the attached B-device.
+ * @id_timer: The timer used for polling ID line to detect ACA states.
*/
struct msm_otg {
struct otg_transceiver otg;
@@ -214,6 +218,7 @@
struct wake_lock wlock;
struct notifier_block usbdev_nb;
unsigned mA_port;
+ struct timer_list id_timer;
unsigned long caps;
/*
* Allowing PHY power collpase turns off the HSUSB 3.3v and 1.8v
diff --git a/include/linux/usb/msm_hsusb_hw.h b/include/linux/usb/msm_hsusb_hw.h
index 79b0415..9cb8356 100644
--- a/include/linux/usb/msm_hsusb_hw.h
+++ b/include/linux/usb/msm_hsusb_hw.h
@@ -54,6 +54,7 @@
/* OTG definitions */
#define OTGSC_INTSTS_MASK (0x7f << 16)
+#define OTGSC_IDPU (1 << 5)
#define OTGSC_ID (1 << 8)
#define OTGSC_BSV (1 << 11)
#define OTGSC_IDIS (1 << 16)
diff --git a/include/media/msm_camera.h b/include/media/msm_camera.h
index 384c3ca..65ca534 100644
--- a/include/media/msm_camera.h
+++ b/include/media/msm_camera.h
@@ -13,6 +13,9 @@
#include <linux/time.h>
#endif
+#ifdef __KERNEL__
+#include <linux/ion.h>
+#endif
#define MSM_CAM_IOCTL_MAGIC 'm'
#define MSM_CAM_IOCTL_GET_SENSOR_INFO \
@@ -522,6 +525,9 @@
uint32_t frame_id;
int stcam_quality_ind;
uint32_t stcam_conv_value;
+
+ struct ion_allocation_data ion_alloc;
+ struct ion_fd_data fd_data;
};
enum msm_st_frame_packing {
diff --git a/net/bluetooth/mgmt.c b/net/bluetooth/mgmt.c
index 094bfdb..0e7ff51 100644
--- a/net/bluetooth/mgmt.c
+++ b/net/bluetooth/mgmt.c
@@ -2608,7 +2608,10 @@
loc_mitm = conn->auth_type & 0x01;
rem_mitm = conn->remote_auth & 0x01;
- if (loc_cap == 0x01 && (rem_cap == 0x00 || rem_cap == 0x03))
+ if ((conn->auth_type & HCI_AT_DEDICATED_BONDING) &&
+ conn->auth_initiator && rem_cap == 0x03)
+ ev.auto_confirm = 1;
+ else if (loc_cap == 0x01 && (rem_cap == 0x00 || rem_cap == 0x03))
goto no_auto_confirm;
diff --git a/sound/soc/msm/msm-pcm-afe.c b/sound/soc/msm/msm-pcm-afe.c
index a34b774..01b8463 100644
--- a/sound/soc/msm/msm-pcm-afe.c
+++ b/sound/soc/msm/msm-pcm-afe.c
@@ -149,8 +149,6 @@
}
case AFE_EVENT_RTPORT_STOP:
pr_debug("%s: event!=0\n", __func__);
- prtd->start = 0;
- snd_pcm_stop(substream, SNDRV_PCM_STATE_SETUP);
break;
case AFE_EVENT_RTPORT_LOW_WM:
pr_debug("%s: Underrun\n", __func__);
@@ -215,8 +213,6 @@
}
case AFE_EVENT_RTPORT_STOP:
pr_debug("%s: event!=0\n", __func__);
- prtd->start = 0;
- snd_pcm_stop(substream, SNDRV_PCM_STATE_SETUP);
break;
case AFE_EVENT_RTPORT_LOW_WM:
pr_debug("%s: Underrun\n", __func__);
diff --git a/sound/soc/msm/msm-pcm-routing.c b/sound/soc/msm/msm-pcm-routing.c
index dbd02e8..97d0760 100644
--- a/sound/soc/msm/msm-pcm-routing.c
+++ b/sound/soc/msm/msm-pcm-routing.c
@@ -761,6 +761,15 @@
msm_routing_put_voice_mixer),
};
+static const struct snd_kcontrol_new hdmi_rx_voice_mixer_controls[] = {
+ SOC_SINGLE_EXT("CSVoice", MSM_BACKEND_DAI_HDMI_RX,
+ MSM_FRONTEND_DAI_CS_VOICE, 1, 0, msm_routing_get_voice_mixer,
+ msm_routing_put_voice_mixer),
+ SOC_SINGLE_EXT("Voip", MSM_BACKEND_DAI_HDMI_RX,
+ MSM_FRONTEND_DAI_VOIP, 1, 0, msm_routing_get_voice_mixer,
+ msm_routing_put_voice_mixer),
+};
+
static const struct snd_kcontrol_new tx_voice_mixer_controls[] = {
SOC_SINGLE_EXT("PRI_TX_Voice", MSM_BACKEND_DAI_PRI_I2S_TX,
MSM_FRONTEND_DAI_CS_VOICE, 1, 0, msm_routing_get_voice_mixer,
@@ -1077,6 +1086,10 @@
SND_SOC_NOPM, 0, 0,
aux_pcm_rx_voice_mixer_controls,
ARRAY_SIZE(aux_pcm_rx_voice_mixer_controls)),
+ SND_SOC_DAPM_MIXER("HDMI_RX_Voice Mixer",
+ SND_SOC_NOPM, 0, 0,
+ hdmi_rx_voice_mixer_controls,
+ ARRAY_SIZE(hdmi_rx_voice_mixer_controls)),
SND_SOC_DAPM_MIXER("Voice_Tx Mixer",
SND_SOC_NOPM, 0, 0, tx_voice_mixer_controls,
ARRAY_SIZE(tx_voice_mixer_controls)),
@@ -1162,6 +1175,10 @@
{"AUX_PCM_RX_Voice Mixer", "Voip", "VOIP_DL"},
{"AUX_PCM_RX", NULL, "AUX_PCM_RX_Voice Mixer"},
+ {"HDMI_RX_Voice Mixer", "CSVoice", "CS-VOICE_DL1"},
+ {"HDMI_RX_Voice Mixer", "Voip", "VOIP_DL"},
+ {"HDMI", NULL, "HDMI_RX_Voice Mixer"},
+
{"Voice_Tx Mixer", "PRI_TX_Voice", "PRI_I2S_TX"},
{"Voice_Tx Mixer", "SLIM_0_TX_Voice", "SLIMBUS_0_TX"},
{"Voice_Tx Mixer", "INTERNAL_BT_SCO_TX_Voice", "INT_BT_SCO_TX"},