Merge "power: pm8921-bms: detect power supply" into msm-3.0
diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig
index e070f1c..b2dbee3 100644
--- a/arch/arm/Kconfig
+++ b/arch/arm/Kconfig
@@ -1359,7 +1359,7 @@
ARCH_EXYNOS4 || ARCH_TEGRA || ARCH_U8500 || ARCH_VEXPRESS_CA9X4 || \
MSM_SMP || ARCH_SHMOBILE
select USE_GENERIC_SMP_HELPERS
- select HAVE_ARM_SCU if !MSM_SMP
+ select HAVE_ARM_SCU
help
This enables support for systems with more than one CPU. If you have
a system with only one CPU, like most personal computers, say N. If
diff --git a/arch/arm/boot/compressed/Makefile b/arch/arm/boot/compressed/Makefile
index 414f8da..2cd81c8 100644
--- a/arch/arm/boot/compressed/Makefile
+++ b/arch/arm/boot/compressed/Makefile
@@ -120,7 +120,8 @@
asflags-y := -Wa,-march=all
# Supply kernel BSS size to the decompressor via a linker symbol.
-KBSS_SZ = $(shell size $(obj)/../../../../vmlinux | awk 'END{print $$3}')
+SIZEBIN := $(if $(shell which $(CROSS_COMPILE)size),$(CROSS_COMPILE)size,size)
+KBSS_SZ = $(shell $(SIZEBIN) $(obj)/../../../../vmlinux | awk 'END{print $$3}')
LDFLAGS_vmlinux = --defsym _kernel_bss_size=$(KBSS_SZ)
# Supply ZRELADDR to the decompressor via a linker symbol.
ifneq ($(CONFIG_AUTO_ZRELADDR),y)
diff --git a/arch/arm/configs/msm7630-perf_defconfig b/arch/arm/configs/msm7630-perf_defconfig
index 9f31996..143fe2b 100644
--- a/arch/arm/configs/msm7630-perf_defconfig
+++ b/arch/arm/configs/msm7630-perf_defconfig
@@ -171,6 +171,7 @@
CONFIG_BT_HCIUART=y
CONFIG_BT_HCIUART_H4=y
CONFIG_BT_HCIUART_IBS=y
+CONFIG_MSM_BT_POWER=y
# CONFIG_WIRELESS_EXT_SYSFS is not set
CONFIG_RFKILL=y
# CONFIG_RFKILL_PM is not set
diff --git a/arch/arm/configs/msm7630_defconfig b/arch/arm/configs/msm7630_defconfig
index b7a7b34..ad49cdd 100644
--- a/arch/arm/configs/msm7630_defconfig
+++ b/arch/arm/configs/msm7630_defconfig
@@ -170,6 +170,7 @@
CONFIG_BT_HCIUART=y
CONFIG_BT_HCIUART_H4=y
CONFIG_BT_HCIUART_IBS=y
+CONFIG_MSM_BT_POWER=y
# CONFIG_WIRELESS_EXT_SYSFS is not set
CONFIG_RFKILL=y
# CONFIG_RFKILL_PM is not set
diff --git a/arch/arm/configs/msm8660-perf_defconfig b/arch/arm/configs/msm8660-perf_defconfig
index 5577fd8..0f03453 100644
--- a/arch/arm/configs/msm8660-perf_defconfig
+++ b/arch/arm/configs/msm8660-perf_defconfig
@@ -210,6 +210,7 @@
CONFIG_BT_HCIUART=y
CONFIG_BT_HCIUART_H4=y
CONFIG_BT_HCIUART_IBS=y
+CONFIG_MSM_BT_POWER=y
# CONFIG_WIRELESS_EXT_SYSFS is not set
CONFIG_RFKILL=y
CONFIG_BLK_DEV_LOOP=y
diff --git a/arch/arm/configs/msm8660_defconfig b/arch/arm/configs/msm8660_defconfig
index 2dc6b36..4b2b909 100644
--- a/arch/arm/configs/msm8660_defconfig
+++ b/arch/arm/configs/msm8660_defconfig
@@ -201,6 +201,7 @@
CONFIG_BT_HCIUART=y
CONFIG_BT_HCIUART_H4=y
CONFIG_BT_HCIUART_IBS=y
+CONFIG_MSM_BT_POWER=y
# CONFIG_WIRELESS_EXT_SYSFS is not set
CONFIG_RFKILL=y
CONFIG_BLK_DEV_LOOP=y
diff --git a/arch/arm/configs/msm8960_defconfig b/arch/arm/configs/msm8960_defconfig
index 8ccb48a..ddbe87c 100755
--- a/arch/arm/configs/msm8960_defconfig
+++ b/arch/arm/configs/msm8960_defconfig
@@ -285,6 +285,7 @@
CONFIG_FB_VIRTUAL=y
CONFIG_FB_MSM=y
# CONFIG_FB_MSM_BACKLIGHT is not set
+CONFIG_FB_MSM_TRIPLE_BUFFER=y
CONFIG_FB_MSM_MDP40=y
CONFIG_FB_MSM_OVERLAY=y
CONFIG_FB_MSM_OVERLAY_WRITEBACK=y
diff --git a/arch/arm/configs/msm9615_defconfig b/arch/arm/configs/msm9615_defconfig
index 9e7df07..52a4d20 100644
--- a/arch/arm/configs/msm9615_defconfig
+++ b/arch/arm/configs/msm9615_defconfig
@@ -100,6 +100,39 @@
CONFIG_REGULATOR=y
# CONFIG_HID_SUPPORT is not set
# CONFIG_USB_SUPPORT is not set
+CONFIG_MMC=y
+# CONFIG_MMC_DEBUG is not set
+CONFIG_MMC_PERF_PROFILING=y
+CONFIG_MMC_UNSAFE_RESUME=y
+# CONFIG_MMC_CLKGATE is not set
+CONFIG_MMC_EMBEDDED_SDIO=y
+CONFIG_MMC_PARANOID_SD_INIT=y
+
+#
+# MMC/SD/SDIO Card Drivers
+#
+CONFIG_MMC_BLOCK=y
+CONFIG_MMC_BLOCK_MINORS=32
+# CONFIG_MMC_BLOCK_BOUNCE is not set
+# CONFIG_MMC_BLOCK_DEFERRED_RESUME is not set
+# CONFIG_SDIO_UART is not set
+# CONFIG_MMC_TEST is not set
+
+#
+# MMC/SD/SDIO Host Controller Drivers
+#
+# CONFIG_MMC_SDHCI is not set
+CONFIG_MMC_MSM=y
+CONFIG_MMC_MSM_SDIO_SUPPORT=y
+# CONFIG_MMC_MSM_CARD_HW_DETECTION is not set
+CONFIG_MMC_MSM_SDC1_SUPPORT=y
+# CONFIG_MMC_MSM_SDC1_8_BIT_SUPPORT is not set
+CONFIG_MMC_MSM_SDC2_SUPPORT=y
+# CONFIG_MMC_MSM_SDC2_8_BIT_SUPPORT is not set
+# CONFIG_MMC_MSM_SDC3_SUPPORT is not set
+# CONFIG_MMC_MSM_SDC4_SUPPORT is not set
+# CONFIG_MMC_MSM_SDC5_SUPPORT is not set
+# CONFIG_MMC_MSM_SPS_SUPPORT is not set
CONFIG_MSM_SSBI=y
CONFIG_SPS=y
CONFIG_SPS_SUPPORT_BAMDMA=y
diff --git a/arch/arm/include/asm/hardirq.h b/arch/arm/include/asm/hardirq.h
index 89ad180..2635c8b 100644
--- a/arch/arm/include/asm/hardirq.h
+++ b/arch/arm/include/asm/hardirq.h
@@ -5,7 +5,7 @@
#include <linux/threads.h>
#include <asm/irq.h>
-#define NR_IPI 5
+#define NR_IPI 6
typedef struct {
unsigned int __softirq_pending;
diff --git a/arch/arm/kernel/smp.c b/arch/arm/kernel/smp.c
index a9d1a5c..5478f55 100644
--- a/arch/arm/kernel/smp.c
+++ b/arch/arm/kernel/smp.c
@@ -48,6 +48,7 @@
struct secondary_data secondary_data;
enum ipi_msg_type {
+ IPI_CPU_START = 1,
IPI_TIMER = 2,
IPI_RESCHEDULE,
IPI_CALL_FUNC,
@@ -399,7 +400,8 @@
}
static const char *ipi_types[NR_IPI] = {
-#define S(x,s) [x - IPI_TIMER] = s
+#define S(x,s) [x - IPI_CPU_START] = s
+ S(IPI_CPU_START, "CPU start interrupts"),
S(IPI_TIMER, "Timer broadcast interrupts"),
S(IPI_RESCHEDULE, "Rescheduling interrupts"),
S(IPI_CALL_FUNC, "Function call interrupts"),
@@ -563,10 +565,13 @@
unsigned int cpu = smp_processor_id();
struct pt_regs *old_regs = set_irq_regs(regs);
- if (ipinr >= IPI_TIMER && ipinr < IPI_TIMER + NR_IPI)
- __inc_irq_stat(cpu, ipi_irqs[ipinr - IPI_TIMER]);
+ if (ipinr >= IPI_CPU_START && ipinr < IPI_CPU_START + NR_IPI)
+ __inc_irq_stat(cpu, ipi_irqs[ipinr - IPI_CPU_START]);
switch (ipinr) {
+ case IPI_CPU_START:
+ /* Wake up from WFI/WFE using SGI */
+ break;
case IPI_TIMER:
ipi_timer();
break;
diff --git a/arch/arm/mach-msm/Kconfig b/arch/arm/mach-msm/Kconfig
index fc67689..2acc8e0 100644
--- a/arch/arm/mach-msm/Kconfig
+++ b/arch/arm/mach-msm/Kconfig
@@ -896,13 +896,6 @@
prompt "Package 4"
endchoice
-config MSM_IPC_ROUTER_SMD_XPRT
- depends on MSM_SMD
- default n
- bool "MSM SMD XPRT Layer"
- help
- SMD Transport Layer for IPC Router
-
config MSM_RPC_SDIO_XPRT
depends on MSM_SDIO_AL
default y
@@ -1064,13 +1057,21 @@
the ARM9 and ARM11
config MSM_IPC_ROUTER
- depends on MSM_IPC_ROUTER_SMD_XPRT
+ depends on NET
default n
bool "MSM IPC Router support"
help
Support for the MSM IPC Router for communication between
the APPs and the MODEM
+config MSM_IPC_ROUTER_SMD_XPRT
+ depends on MSM_SMD
+ depends on MSM_IPC_ROUTER
+ default n
+ bool "MSM SMD XPRT Layer"
+ help
+ SMD Transport Layer for IPC Router
+
config MSM_ONCRPCROUTER_DEBUG
depends on MSM_ONCRPCROUTER
default y
diff --git a/arch/arm/mach-msm/Makefile b/arch/arm/mach-msm/Makefile
index e81bdcd..0d36b0a 100644
--- a/arch/arm/mach-msm/Makefile
+++ b/arch/arm/mach-msm/Makefile
@@ -158,7 +158,7 @@
obj-$(CONFIG_ARCH_MSM8X60) += devices-msm8x60.o clock-local.o clock-8x60.o acpuclock-8x60.o
obj-$(CONFIG_ARCH_MSM8X60) += clock-rpm.o
obj-$(CONFIG_ARCH_MSM8X60) += saw-regulator.o
-obj-$(CONFIG_ARCH_MSM8X60) += rpm-regulator.o
+obj-$(CONFIG_ARCH_MSM8X60) += rpm-regulator.o rpm-regulator-8660.o
obj-$(CONFIG_ARCH_MSM8X60) += footswitch-8x60.o
ifdef CONFIG_MSM_SUBSYSTEM_RESTART
@@ -209,7 +209,8 @@
obj-$(CONFIG_ARCH_MSM8960) += clock-local.o clock-dss-8960.o clock-8960.o clock-rpm.o
obj-$(CONFIG_ARCH_MSM8960) += footswitch-8x60.o
obj-$(CONFIG_ARCH_MSM8960) += acpuclock-8960.o
-obj-$(CONFIG_ARCH_MSM8960) += saw-regulator.o rpm-regulator-8960.o memory_topology.o
+obj-$(CONFIG_ARCH_MSM8960) += memory_topology.o
+obj-$(CONFIG_ARCH_MSM8960) += saw-regulator.o rpm-regulator.o rpm-regulator-8960.o
obj-$(CONFIG_MACH_MSM8960_SIM) += board-msm8960.o devices-8960.o board-msm8960-regulator.o
obj-$(CONFIG_MACH_MSM8960_RUMI3) += board-msm8960.o devices-8960.o board-msm8960-regulator.o
obj-$(CONFIG_MACH_MSM8960_CDP) += board-msm8960.o devices-8960.o board-msm8960-regulator.o
@@ -219,6 +220,7 @@
obj-$(CONFIG_ARCH_APQ8064) += board-apq8064.o devices-8064.o board-apq8064-regulator.o
obj-$(CONFIG_ARCH_MSM9615) += board-9615.o devices-9615.o board-9615-regulator.o
obj-$(CONFIG_ARCH_MSM9615) += clock-local.o clock-9615.o acpuclock-9615.o clock-rpm.o
+obj-$(CONFIG_ARCH_MSM9615) += rpm-regulator.o rpm-regulator-9615.o
obj-$(CONFIG_MACH_SAPPHIRE) += board-sapphire.o board-sapphire-gpio.o
obj-$(CONFIG_MACH_SAPPHIRE) += board-sapphire-keypad.o board-sapphire-panel.o
diff --git a/arch/arm/mach-msm/acpuclock-8960.c b/arch/arm/mach-msm/acpuclock-8960.c
index 307bd60..90a7504 100644
--- a/arch/arm/mach-msm/acpuclock-8960.c
+++ b/arch/arm/mach-msm/acpuclock-8960.c
@@ -223,8 +223,6 @@
static struct l2_level *l2_freq_tbl;
static struct acpu_level *acpu_freq_tbl;
static int l2_freq_tbl_size;
-static int cpu_boot_idx;
-static int l2_boot_idx;
/* Instantaneous bandwidth requests in MB/s. */
#define BW_MBPS(_bw) \
@@ -278,20 +276,6 @@
[9] = { { 810000, HFPLL, 1, 0, 0x1E }, 1150000, 1150000, 3 },
[10] = { { 864000, HFPLL, 1, 0, 0x20 }, 1150000, 1150000, 3 },
[11] = { { 918000, HFPLL, 1, 0, 0x22 }, 1150000, 1150000, 3 },
- [12] = { { 972000, HFPLL, 1, 0, 0x24 }, 1150000, 1150000, 3 },
- [13] = { { 1026000, HFPLL, 1, 0, 0x26 }, 1150000, 1150000, 4 },
- [14] = { { 1080000, HFPLL, 1, 0, 0x28 }, 1150000, 1150000, 4 },
- [15] = { { 1134000, HFPLL, 1, 0, 0x2A }, 1150000, 1150000, 4 },
- [16] = { { 1188000, HFPLL, 1, 0, 0x2C }, 1150000, 1150000, 4 },
- [17] = { { 1242000, HFPLL, 1, 0, 0x2E }, 1150000, 1150000, 5 },
- [18] = { { 1296000, HFPLL, 1, 0, 0x30 }, 1150000, 1150000, 5 },
- [19] = { { 1350000, HFPLL, 1, 0, 0x32 }, 1150000, 1150000, 5 },
- [20] = { { 1404000, HFPLL, 1, 0, 0x34 }, 1150000, 1150000, 5 },
- [21] = { { 1458000, HFPLL, 1, 0, 0x36 }, 1150000, 1150000, 5 },
- [22] = { { 1512000, HFPLL, 1, 0, 0x38 }, 1150000, 1150000, 5 },
- [23] = { { 1566000, HFPLL, 1, 0, 0x3A }, 1150000, 1150000, 5 },
- [24] = { { 1620000, HFPLL, 1, 0, 0x3C }, 1150000, 1150000, 5 },
- [25] = { { 1674000, HFPLL, 1, 0, 0x3E }, 1150000, 1150000, 5 },
};
/* TODO: Update core voltages when data is available. */
@@ -304,10 +288,10 @@
{ 1, { 594000, HFPLL, 1, 0, 0x16 }, L2(6), 1050000 },
{ 1, { 648000, HFPLL, 1, 0, 0x18 }, L2(6), 1050000 },
{ 1, { 702000, HFPLL, 1, 0, 0x1A }, L2(6), 1050000 },
- { 1, { 756000, HFPLL, 1, 0, 0x1C }, L2(13), 1150000 },
- { 1, { 810000, HFPLL, 1, 0, 0x1E }, L2(13), 1150000 },
- { 1, { 864000, HFPLL, 1, 0, 0x20 }, L2(13), 1150000 },
- { 1, { 918000, HFPLL, 1, 0, 0x22 }, L2(13), 1150000 },
+ { 1, { 756000, HFPLL, 1, 0, 0x1C }, L2(11), 1150000 },
+ { 1, { 810000, HFPLL, 1, 0, 0x1E }, L2(11), 1150000 },
+ { 1, { 864000, HFPLL, 1, 0, 0x20 }, L2(11), 1150000 },
+ { 1, { 918000, HFPLL, 1, 0, 0x22 }, L2(11), 1150000 },
{ 0, { 0 } }
};
@@ -871,9 +855,11 @@
static void __init per_cpu_init(void *data)
{
+ struct acpu_level *max_acpu_level = data;
int cpu = smp_processor_id();
- init_clock_sources(&scalable[cpu], &acpu_freq_tbl[cpu_boot_idx].speed);
- scalable[cpu].l2_vote = &l2_freq_tbl[l2_boot_idx];
+
+ init_clock_sources(&scalable[cpu], &max_acpu_level->speed);
+ scalable[cpu].l2_vote = max_acpu_level->l2_level;
}
/* Register with bus driver. */
@@ -984,6 +970,35 @@
.notifier_call = acpuclock_cpu_callback,
};
+static struct acpu_level * __init select_freq_plan(void)
+{
+ struct acpu_level *l, *max_acpu_level = NULL;
+
+ /* Select frequency tables. */
+ if (cpu_is_msm8960()) {
+ scalable = scalable_8960;
+ acpu_freq_tbl = acpu_freq_tbl_8960;
+ l2_freq_tbl = l2_freq_tbl_8960;
+ l2_freq_tbl_size = ARRAY_SIZE(l2_freq_tbl_8960);
+ } else if (cpu_is_apq8064()) {
+ scalable = scalable_8064;
+ acpu_freq_tbl = acpu_freq_tbl_8064;
+ l2_freq_tbl = l2_freq_tbl_8064;
+ l2_freq_tbl_size = ARRAY_SIZE(l2_freq_tbl_8064);
+ } else {
+ BUG();
+ }
+
+ /* Find the max supported scaling frequency. */
+ for (l = acpu_freq_tbl; l->speed.khz != 0; l++)
+ if (l->use_for_scaling)
+ max_acpu_level = l;
+ BUG_ON(!max_acpu_level);
+ pr_info("Max ACPU freq: %u KHz\n", max_acpu_level->speed.khz);
+
+ return max_acpu_level;
+}
+
static struct acpuclk_data acpuclk_8960_data = {
.set_rate = acpuclk_8960_set_rate,
.get_rate = acpuclk_8960_get_rate,
@@ -993,24 +1008,9 @@
static int __init acpuclk_8960_init(struct acpuclk_soc_data *soc_data)
{
- if (cpu_is_msm8960()) {
- scalable = scalable_8960;
- acpu_freq_tbl = acpu_freq_tbl_8960;
- l2_freq_tbl = l2_freq_tbl_8960;
- l2_freq_tbl_size = ARRAY_SIZE(l2_freq_tbl_8960);
- l2_boot_idx = 11;
- cpu_boot_idx = 11;
- } else if (cpu_is_apq8064()) {
- scalable = scalable_8064;
- acpu_freq_tbl = acpu_freq_tbl_8064;
- l2_freq_tbl = l2_freq_tbl_8064;
- l2_freq_tbl_size = ARRAY_SIZE(l2_freq_tbl_8064);
- l2_boot_idx = 11;
- cpu_boot_idx = 11;
- }
-
- init_clock_sources(&scalable[L2], &l2_freq_tbl[l2_boot_idx].speed);
- on_each_cpu(per_cpu_init, NULL, true);
+ struct acpu_level *max_acpu_level = select_freq_plan();
+ init_clock_sources(&scalable[L2], &max_acpu_level->l2_level->speed);
+ on_each_cpu(per_cpu_init, max_acpu_level, true);
regulator_init();
bus_init();
diff --git a/arch/arm/mach-msm/acpuclock-9615.c b/arch/arm/mach-msm/acpuclock-9615.c
index e12caeb..924a46a 100644
--- a/arch/arm/mach-msm/acpuclock-9615.c
+++ b/arch/arm/mach-msm/acpuclock-9615.c
@@ -122,7 +122,7 @@
goto out;
}
- pr_info("Switching from CPU rate %u KHz -> %u KHz\n",
+ pr_debug("Switching from CPU rate %u KHz -> %u KHz\n",
strt_s->khz, tgt_s->khz);
/* Switch CPU speed. */
@@ -131,7 +131,7 @@
clk_disable(clocks[strt_s->src].clk);
drv_state.current_speed = tgt_s;
- pr_info("CPU speed change complete\n");
+ pr_debug("CPU speed change complete\n");
out:
if (reason == SETRATE_CPUFREQ)
diff --git a/arch/arm/mach-msm/board-msm7x27.c b/arch/arm/mach-msm/board-msm7x27.c
index 5f205f4..9629b5c 100644
--- a/arch/arm/mach-msm/board-msm7x27.c
+++ b/arch/arm/mach-msm/board-msm7x27.c
@@ -58,16 +58,17 @@
#include <linux/android_pmem.h>
#include <mach/camera.h>
+#ifdef CONFIG_USB_G_ANDROID
+#include <linux/usb/android.h>
+#include <mach/usbdiag.h>
+#endif
+
#include "devices.h"
#include "clock.h"
#include "acpuclock.h"
#include "msm-keypad-devices.h"
#include "pm.h"
-#ifdef CONFIG_USB_ANDROID
-#include <linux/usb/android_composite.h>
-#endif
-
#ifdef CONFIG_ARCH_MSM7X25
#define MSM_PMEM_MDP_SIZE 0xb21000
#define MSM_PMEM_ADSP_SIZE 0x97b000
@@ -103,135 +104,16 @@
},
};
-#ifdef CONFIG_USB_FUNCTION
-static struct usb_mass_storage_platform_data usb_mass_storage_pdata = {
- .nluns = 0x02,
- .buf_size = 16384,
- .vendor = "GOOGLE",
- .product = "Mass storage",
- .release = 0xffff,
+static struct platform_device smc91x_device = {
+ .name = "smc91x",
+ .id = 0,
+ .num_resources = ARRAY_SIZE(smc91x_resources),
+ .resource = smc91x_resources,
};
-static struct platform_device mass_storage_device = {
- .name = "usb_mass_storage",
- .id = -1,
- .dev = {
- .platform_data = &usb_mass_storage_pdata,
- },
-};
-#endif
-#ifdef CONFIG_USB_ANDROID
-static char *usb_functions_default[] = {
- "diag",
- "modem",
- "nmea",
- "rmnet",
- "usb_mass_storage",
-};
-
-static char *usb_functions_default_adb[] = {
- "diag",
- "adb",
- "modem",
- "nmea",
- "rmnet",
- "usb_mass_storage",
-};
-
-static char *usb_functions_rndis[] = {
- "rndis",
-};
-
-static char *usb_functions_rndis_adb[] = {
- "rndis",
- "adb",
-};
-
-static char *usb_functions_all[] = {
-#ifdef CONFIG_USB_ANDROID_RNDIS
- "rndis",
-#endif
-#ifdef CONFIG_USB_ANDROID_DIAG
- "diag",
-#endif
- "adb",
-#ifdef CONFIG_USB_F_SERIAL
- "modem",
- "nmea",
-#endif
-#ifdef CONFIG_USB_ANDROID_RMNET
- "rmnet",
-#endif
- "usb_mass_storage",
-#ifdef CONFIG_USB_ANDROID_ACM
- "acm",
-#endif
-};
-
-static struct android_usb_product usb_products[] = {
- {
- .product_id = 0x9026,
- .num_functions = ARRAY_SIZE(usb_functions_default),
- .functions = usb_functions_default,
- },
- {
- .product_id = 0x9025,
- .num_functions = ARRAY_SIZE(usb_functions_default_adb),
- .functions = usb_functions_default_adb,
- },
- {
- .product_id = 0xf00e,
- .num_functions = ARRAY_SIZE(usb_functions_rndis),
- .functions = usb_functions_rndis,
- },
- {
- .product_id = 0x9024,
- .num_functions = ARRAY_SIZE(usb_functions_rndis_adb),
- .functions = usb_functions_rndis_adb,
- },
-};
-
-static struct usb_mass_storage_platform_data mass_storage_pdata = {
- .nluns = 1,
- .vendor = "Qualcomm Incorporated",
- .product = "Mass storage",
- .release = 0x0100,
- .can_stall = 1,
-};
-
-static struct platform_device usb_mass_storage_device = {
- .name = "usb_mass_storage",
- .id = -1,
- .dev = {
- .platform_data = &mass_storage_pdata,
- },
-};
-
-static struct usb_ether_platform_data rndis_pdata = {
- /* ethaddr is filled by board_serialno_setup */
- .vendorID = 0x05C6,
- .vendorDescr = "Qualcomm Incorporated",
-};
-
-static struct platform_device rndis_device = {
- .name = "rndis",
- .id = -1,
- .dev = {
- .platform_data = &rndis_pdata,
- },
-};
-
+#ifdef CONFIG_USB_G_ANDROID
static struct android_usb_platform_data android_usb_pdata = {
- .vendor_id = 0x05C6,
- .product_id = 0x9026,
- .version = 0x0100,
- .product_name = "Qualcomm HSUSB Device",
- .manufacturer_name = "Qualcomm Incorporated",
- .num_products = ARRAY_SIZE(usb_products),
- .products = usb_products,
- .num_functions = ARRAY_SIZE(usb_functions_all),
- .functions = usb_functions_all,
- .serial_number = "1234567890ABCDEF",
+ .update_pid_and_serial_num = usb_diag_update_pid_and_serial_num,
};
static struct platform_device android_usb_device = {
@@ -241,114 +123,6 @@
.platform_data = &android_usb_pdata,
},
};
-
-static int __init board_serialno_setup(char *serialno)
-{
- int i;
- char *src = serialno;
-
- /* create a fake MAC address from our serial number.
- * first byte is 0x02 to signify locally administered.
- */
- rndis_pdata.ethaddr[0] = 0x02;
- for (i = 0; *src; i++) {
- /* XOR the USB serial across the remaining bytes */
- rndis_pdata.ethaddr[i % (ETH_ALEN - 1) + 1] ^= *src++;
- }
-
- android_usb_pdata.serial_number = serialno;
- return 1;
-}
-__setup("androidboot.serialno=", board_serialno_setup);
-#endif
-
-static struct platform_device smc91x_device = {
- .name = "smc91x",
- .id = 0,
- .num_resources = ARRAY_SIZE(smc91x_resources),
- .resource = smc91x_resources,
-};
-
-#ifdef CONFIG_USB_FUNCTION
-static struct usb_function_map usb_functions_map[] = {
- {"diag", 0},
- {"adb", 1},
- {"modem", 2},
- {"nmea", 3},
- {"mass_storage", 4},
- {"ethernet", 5},
- {"rmnet", 6},
-};
-
-/* dynamic composition */
-static struct usb_composition usb_func_composition[] = {
- {
- .product_id = 0x9012,
- .functions = 0x5, /* 0101 */
- },
-
- {
- .product_id = 0x9013,
- .functions = 0x15, /* 10101 */
- },
-
- {
- .product_id = 0x9014,
- .functions = 0x30, /* 110000 */
- },
-
- {
- .product_id = 0x9016,
- .functions = 0xD, /* 01101 */
- },
-
- {
- .product_id = 0x9017,
- .functions = 0x1D, /* 11101 */
- },
-
- {
- .product_id = 0xF000,
- .functions = 0x10, /* 10000 */
- },
-
- {
- .product_id = 0xF009,
- .functions = 0x20, /* 100000 */
- },
-
- {
- .product_id = 0x9018,
- .functions = 0x1F, /* 011111 */
- },
-#ifdef CONFIG_USB_FUNCTION_RMNET
- {
- .product_id = 0x9021,
- /* DIAG + RMNET */
- .functions = 0x41,
- },
- {
- .product_id = 0x9022,
- /* DIAG + ADB + RMNET */
- .functions = 0x43,
- },
-#endif
-
-};
-
-static struct msm_hsusb_platform_data msm_hsusb_pdata = {
- .version = 0x0100,
- .phy_info = (USB_PHY_INTEGRATED | USB_PHY_MODEL_65NM),
- .vendor_id = 0x5c6,
- .product_name = "Qualcomm HSUSB Device",
- .serial_number = "1234567890ABCDEF",
- .manufacturer_name = "Qualcomm Incorporated",
- .compositions = usb_func_composition,
- .num_compositions = ARRAY_SIZE(usb_func_composition),
- .function_map = usb_functions_map,
- .num_functions = ARRAY_SIZE(usb_functions_map),
- .config_gpio = NULL,
-};
#endif
#ifdef CONFIG_USB_EHCI_MSM_72K
@@ -1410,22 +1184,10 @@
#endif
#endif
-#ifdef CONFIG_USB_FUNCTION
- &msm_device_hsusb_peripheral,
- &mass_storage_device,
-#endif
-
-#ifdef CONFIG_USB_ANDROID
- &usb_mass_storage_device,
- &rndis_device,
-#ifdef CONFIG_USB_ANDROID_DIAG
- &usb_diag_device,
-#endif
-#ifdef CONFIG_USB_F_SERIAL
- &usb_gadget_fserial_device,
-#endif
+#ifdef CONFIG_USB_G_ANDROID
&android_usb_device,
#endif
+
&msm_device_i2c,
&smc91x_device,
&msm_device_tssc,
@@ -1891,13 +1653,6 @@
usb_mpp_init();
-#ifdef CONFIG_USB_FUNCTION
- msm_hsusb_pdata.swfi_latency =
- msm7x27_pm_data
- [MSM_PM_SLEEP_MODE_RAMP_DOWN_AND_WAIT_FOR_INTERRUPT].latency;
-
- msm_device_hsusb_peripheral.dev.platform_data = &msm_hsusb_pdata;
-#endif
#ifdef CONFIG_USB_MSM_OTG_72K
msm_device_otg.dev.platform_data = &msm_otg_pdata;
diff --git a/arch/arm/mach-msm/board-msm7x27a.c b/arch/arm/mach-msm/board-msm7x27a.c
index 653afc6..67b1dcc 100644
--- a/arch/arm/mach-msm/board-msm7x27a.c
+++ b/arch/arm/mach-msm/board-msm7x27a.c
@@ -638,65 +638,80 @@
goto reg_disable;
}
+ rc = on ? regulator_set_voltage(bt_vregs[i].reg,
+ bt_vregs[i].level, bt_vregs[i].level) : 0;
+ if (rc) {
+ dev_err(&msm_bt_power_device.dev,
+ "%s: could not set voltage for %s: %d\n",
+ __func__, bt_vregs[i].name, rc);
+ goto reg_disable;
+ }
+
+ rc = on ? regulator_enable(bt_vregs[i].reg) : 0;
+ if (rc) {
+ dev_err(&msm_bt_power_device.dev,
+ "%s: could not %sable regulator %s: %d\n",
+ __func__, "en", bt_vregs[i].name, rc);
+ goto reg_disable;
+ }
+
if (bt_vregs[i].is_pin_controlled) {
- rc = pmapp_vreg_pincntrl_vote(id,
+ rc = pmapp_vreg_lpm_pincntrl_vote(id,
bt_vregs[i].pmapp_id,
PMAPP_CLOCK_ID_D1,
on ? PMAPP_CLOCK_VOTE_ON :
PMAPP_CLOCK_VOTE_OFF);
- } else {
- rc = on ? regulator_enable(bt_vregs[i].reg) :
- regulator_disable(bt_vregs[i].reg);
+ if (rc) {
+ dev_err(&msm_bt_power_device.dev,
+ "%s: pin control failed for %s: %d\n",
+ __func__, bt_vregs[i].name, rc);
+ goto pin_cnt_fail;
+ }
}
+ rc = on ? 0 : regulator_disable(bt_vregs[i].reg);
if (rc) {
dev_err(&msm_bt_power_device.dev,
"%s: could not %sable regulator %s: %d\n",
- __func__, on ? "en" : "dis",
- bt_vregs[i].name, rc);
- i++;
+ __func__, "dis", bt_vregs[i].name, rc);
goto reg_disable;
}
}
return rc;
-
+pin_cnt_fail:
+ if (on)
+ regulator_disable(bt_vregs[i].reg);
reg_disable:
- while (i--) {
- if (bt_vregs[i].is_pin_controlled) {
- pmapp_vreg_pincntrl_vote(id, bt_vregs[i].pmapp_id,
- PMAPP_CLOCK_ID_D1,
- on ? PMAPP_CLOCK_VOTE_OFF :
- PMAPP_CLOCK_VOTE_ON);
- } else {
- if (on)
- regulator_disable(bt_vregs[i].reg);
- else
- regulator_enable(bt_vregs[i].reg);
+ while (i) {
+ if (on) {
+ i--;
+ regulator_disable(bt_vregs[i].reg);
+ regulator_put(bt_vregs[i].reg);
}
}
return rc;
}
-static struct regulator *reg_bahama;
+static struct regulator *reg_s3;
static unsigned int msm_bahama_setup_power(void)
{
int rc = 0;
- reg_bahama = regulator_get(NULL, "msme1");
- if (IS_ERR(reg_bahama)) {
- rc = PTR_ERR(reg_bahama);
+ reg_s3 = regulator_get(NULL, "msme1");
+ if (IS_ERR(reg_s3)) {
+ rc = PTR_ERR(reg_s3);
pr_err("%s: could not get regulator: %d\n", __func__, rc);
goto out;
}
- rc = regulator_set_voltage(reg_bahama, 1800000, 1800000);
+ rc = regulator_set_voltage(reg_s3, 1800000, 1800000);
if (rc) {
pr_err("%s: could not set voltage: %d\n", __func__, rc);
goto reg_fail;
}
- rc = regulator_enable(reg_bahama);
+ rc = regulator_enable(reg_s3);
if (rc < 0) {
pr_err("%s: could not enable regulator: %d\n", __func__, rc);
goto reg_fail;
@@ -722,11 +737,11 @@
gpio_fail:
gpio_free(GPIO_BT_SYS_REST_EN);
reg_disable:
- regulator_disable(reg_bahama);
+ regulator_disable(reg_s3);
reg_fail:
- regulator_put(reg_bahama);
+ regulator_put(reg_s3);
out:
- reg_bahama = NULL;
+ reg_s3 = NULL;
return rc;
}
@@ -734,12 +749,12 @@
{
int rc = 0;
- if (IS_ERR_OR_NULL(reg_bahama)) {
- rc = reg_bahama ? PTR_ERR(reg_bahama) : -ENODEV;
+ if (IS_ERR_OR_NULL(reg_s3)) {
+ rc = reg_s3 ? PTR_ERR(reg_s3) : -ENODEV;
goto out;
}
- rc = regulator_disable(reg_bahama);
+ rc = regulator_disable(reg_s3);
if (rc) {
pr_err("%s: could not disable regulator: %d\n", __func__, rc);
goto out;
@@ -750,18 +765,15 @@
if (rc) {
pr_err("%s: bt_set_gpio = %d\n",
__func__, rc);
- goto reg_enable;
}
gpio_free(GPIO_BT_SYS_REST_EN);
}
- regulator_put(reg_bahama);
- reg_bahama = NULL;
+ regulator_put(reg_s3);
+ reg_s3 = NULL;
return 0;
-reg_enable:
- regulator_enable(reg_bahama);
out:
return rc;
}
@@ -933,21 +945,12 @@
__func__, bt_vregs[i].name, rc);
goto reg_get_fail;
}
- rc = regulator_set_voltage(bt_vregs[i].reg,
- bt_vregs[i].level, bt_vregs[i].level);
- if (rc) {
- dev_err(dev, "%s: could not set voltage for %s: %d\n",
- __func__, bt_vregs[i].name, rc);
- goto reg_set_fail;
- }
}
dev->platform_data = &bluetooth_power;
return rc;
-reg_set_fail:
- i++;
reg_get_fail:
while (i--) {
regulator_put(bt_vregs[i].reg);
diff --git a/arch/arm/mach-msm/board-msm8960-regulator.c b/arch/arm/mach-msm/board-msm8960-regulator.c
index 3b6da9a..e85202d 100644
--- a/arch/arm/mach-msm/board-msm8960-regulator.c
+++ b/arch/arm/mach-msm/board-msm8960-regulator.c
@@ -383,8 +383,8 @@
| REGULATOR_MODE_IDLE, REGULATOR_CHANGE_VOLTAGE \
| REGULATOR_CHANGE_STATUS | REGULATOR_CHANGE_MODE \
| REGULATOR_CHANGE_DRMS, 0, _max_uV, _init_peak_uA, 0, _pd, \
- RPM_VREG_PIN_CTRL_NONE, NONE, RPM_VREG_PIN_FN_NONE, \
- RPM_VREG_FORCE_MODE_NONE, RPM_VREG_POWER_MODE_PWM, \
+ RPM_VREG_PIN_CTRL_NONE, NONE, RPM_VREG_PIN_FN_8960_NONE, \
+ RPM_VREG_FORCE_MODE_8960_NONE, RPM_VREG_POWER_MODE_8960_PWM, \
RPM_VREG_STATE_OFF, _sleep_selectable, _always_on, \
_supply_regulator, _system_uA)
@@ -394,15 +394,15 @@
| REGULATOR_MODE_IDLE, REGULATOR_CHANGE_VOLTAGE \
| REGULATOR_CHANGE_STATUS | REGULATOR_CHANGE_MODE \
| REGULATOR_CHANGE_DRMS, 0, _max_uV, _system_uA, 0, _pd, \
- RPM_VREG_PIN_CTRL_NONE, _freq, RPM_VREG_PIN_FN_NONE, \
- RPM_VREG_FORCE_MODE_NONE, RPM_VREG_POWER_MODE_PWM, \
+ RPM_VREG_PIN_CTRL_NONE, _freq, RPM_VREG_PIN_FN_8960_NONE, \
+ RPM_VREG_FORCE_MODE_8960_NONE, RPM_VREG_POWER_MODE_8960_PWM, \
RPM_VREG_STATE_OFF, _sleep_selectable, _always_on, \
_supply_regulator, _system_uA)
#define RPM_VS(_id, _always_on, _pd, _sleep_selectable, _supply_regulator) \
RPM_INIT(_id, 0, 0, 0, REGULATOR_CHANGE_STATUS, 0, 0, 1000, 1000, _pd, \
- RPM_VREG_PIN_CTRL_NONE, NONE, RPM_VREG_PIN_FN_NONE, \
- RPM_VREG_FORCE_MODE_NONE, RPM_VREG_POWER_MODE_PWM, \
+ RPM_VREG_PIN_CTRL_NONE, NONE, RPM_VREG_PIN_FN_8960_NONE, \
+ RPM_VREG_FORCE_MODE_8960_NONE, RPM_VREG_POWER_MODE_8960_PWM, \
RPM_VREG_STATE_OFF, _sleep_selectable, _always_on, \
_supply_regulator, 0)
@@ -410,8 +410,8 @@
_supply_regulator, _freq) \
RPM_INIT(_id, _min_uV, _max_uV, 0, REGULATOR_CHANGE_VOLTAGE \
| REGULATOR_CHANGE_STATUS, 0, _max_uV, 1000, 1000, 0, \
- RPM_VREG_PIN_CTRL_NONE, _freq, RPM_VREG_PIN_FN_NONE, \
- RPM_VREG_FORCE_MODE_NONE, RPM_VREG_POWER_MODE_PWM, \
+ RPM_VREG_PIN_CTRL_NONE, _freq, RPM_VREG_PIN_FN_8960_NONE, \
+ RPM_VREG_FORCE_MODE_8960_NONE, RPM_VREG_POWER_MODE_8960_PWM, \
RPM_VREG_STATE_OFF, _sleep_selectable, _always_on, \
_supply_regulator, 0)
@@ -429,7 +429,7 @@
.supply_regulator = _supply_regulator, \
}, \
.id = RPM_VREG_ID_PM8921_##_id##_PC, \
- .pin_fn = RPM_VREG_PIN_FN_##_pin_fn, \
+ .pin_fn = RPM_VREG_PIN_FN_8960_##_pin_fn, \
.pin_ctrl = _pin_ctrl, \
}
@@ -520,6 +520,9 @@
ARRAY_SIZE(msm_pm8921_regulator_pdata);
struct rpm_regulator_platform_data msm_rpm_regulator_pdata __devinitdata = {
- .init_data = msm_rpm_regulator_init_data,
- .num_regulators = ARRAY_SIZE(msm_rpm_regulator_init_data),
+ .init_data = msm_rpm_regulator_init_data,
+ .num_regulators = ARRAY_SIZE(msm_rpm_regulator_init_data),
+ .version = RPM_VREG_VERSION_8960,
+ .vreg_id_vdd_mem = RPM_VREG_ID_PM8921_L24,
+ .vreg_id_vdd_dig = RPM_VREG_ID_PM8921_S3,
};
diff --git a/arch/arm/mach-msm/board-msm8960.c b/arch/arm/mach-msm/board-msm8960.c
index 7b2c778..2cf0a70 100644
--- a/arch/arm/mach-msm/board-msm8960.c
+++ b/arch/arm/mach-msm/board-msm8960.c
@@ -1018,8 +1018,6 @@
};
#endif
-#ifdef CONFIG_MSM_BUS_SCALING
-
static struct msm_bus_vectors cam_init_vectors[] = {
{
.src = MSM_BUS_MASTER_VFE,
@@ -1153,24 +1151,19 @@
ARRAY_SIZE(cam_bus_client_config),
.name = "msm_camera",
};
-#endif
struct msm_camera_device_platform_data msm_camera_csi_device_data[] = {
{
.ioclk.mclk_clk_rate = 24000000,
.ioclk.vfe_clk_rate = 228570000,
.csid_core = 0,
-#ifdef CONFIG_MSM_BUS_SCALING
.cam_bus_scale_table = &cam_bus_client_pdata,
-#endif
},
{
.ioclk.mclk_clk_rate = 24000000,
.ioclk.vfe_clk_rate = 228570000,
.csid_core = 1,
-#ifdef CONFIG_MSM_BUS_SCALING
.cam_bus_scale_table = &cam_bus_client_pdata,
-#endif
},
};
@@ -2685,8 +2678,18 @@
static struct msm_mmc_pad_pull sdc3_pad_pull_off_cfg[] = {
{TLMM_PULL_SDC3_CLK, GPIO_CFG_NO_PULL},
- {TLMM_PULL_SDC3_CMD, GPIO_CFG_PULL_DOWN},
- {TLMM_PULL_SDC3_DATA, GPIO_CFG_PULL_DOWN}
+ /*
+ * SDC3 CMD line should be PULLed UP otherwise fluid platform will
+ * see transitions (1 -> 0 and 0 -> 1) on card detection line,
+ * which would result in false card detection interrupts.
+ */
+ {TLMM_PULL_SDC3_CMD, GPIO_CFG_PULL_UP},
+ /*
+ * Keeping DATA lines status to PULL UP will make sure that
+ * there is no current leak during sleep if external pull up
+ * is connected to DATA lines.
+ */
+ {TLMM_PULL_SDC3_DATA, GPIO_CFG_PULL_UP}
};
struct msm_mmc_pad_pull_data mmc_pad_pull_data[MAX_SDCC_CONTROLLER] = {
@@ -3654,7 +3657,7 @@
static void __init msm8960_gfx_init(void)
{
- uint32_t soc_platform_version = socinfo_get_platform_version();
+ uint32_t soc_platform_version = socinfo_get_version();
if (SOCINFO_VERSION_MAJOR(soc_platform_version) == 1) {
struct kgsl_device_platform_data *kgsl_3d0_pdata =
msm_kgsl_3d0.dev.platform_data;
diff --git a/arch/arm/mach-msm/board-msm8x60.c b/arch/arm/mach-msm/board-msm8x60.c
index 79bad3f..6804a99 100644
--- a/arch/arm/mach-msm/board-msm8x60.c
+++ b/arch/arm/mach-msm/board-msm8x60.c
@@ -3841,35 +3841,73 @@
REGULATOR_SUPPLY("8901_mvs0", NULL),
};
+/* Pin control regulators */
+static struct regulator_consumer_supply vreg_consumers_PM8058_L8_PC[] = {
+ REGULATOR_SUPPLY("8058_l8_pc", NULL),
+};
+static struct regulator_consumer_supply vreg_consumers_PM8058_L20_PC[] = {
+ REGULATOR_SUPPLY("8058_l20_pc", NULL),
+};
+static struct regulator_consumer_supply vreg_consumers_PM8058_L21_PC[] = {
+ REGULATOR_SUPPLY("8058_l21_pc", NULL),
+};
+static struct regulator_consumer_supply vreg_consumers_PM8058_S2_PC[] = {
+ REGULATOR_SUPPLY("8058_s2_pc", NULL),
+};
+static struct regulator_consumer_supply vreg_consumers_PM8901_L0_PC[] = {
+ REGULATOR_SUPPLY("8901_l0_pc", NULL),
+};
+static struct regulator_consumer_supply vreg_consumers_PM8901_S4_PC[] = {
+ REGULATOR_SUPPLY("8901_s4_pc", NULL),
+};
+
#define RPM_VREG_INIT(_id, _min_uV, _max_uV, _modes, _ops, _apply_uV, \
_default_uV, _peak_uA, _avg_uA, _pull_down, _pin_ctrl, \
- _freq, _pin_fn, _rpm_mode, _state, _sleep_selectable, \
+ _freq, _pin_fn, _force_mode, _state, _sleep_selectable, \
_always_on) \
- [RPM_VREG_ID_##_id] = { \
+ { \
.init_data = { \
.constraints = { \
- .valid_modes_mask = _modes, \
- .valid_ops_mask = _ops, \
- .min_uV = _min_uV, \
- .max_uV = _max_uV, \
- .input_uV = _min_uV, \
- .apply_uV = _apply_uV, \
- .always_on = _always_on, \
+ .valid_modes_mask = _modes, \
+ .valid_ops_mask = _ops, \
+ .min_uV = _min_uV, \
+ .max_uV = _max_uV, \
+ .input_uV = _min_uV, \
+ .apply_uV = _apply_uV, \
+ .always_on = _always_on, \
}, \
- .consumer_supplies = vreg_consumers_##_id, \
- .num_consumer_supplies = \
+ .consumer_supplies = vreg_consumers_##_id, \
+ .num_consumer_supplies = \
ARRAY_SIZE(vreg_consumers_##_id), \
}, \
- .default_uV = _default_uV, \
- .peak_uA = _peak_uA, \
- .avg_uA = _avg_uA, \
- .pull_down_enable = _pull_down, \
+ .id = RPM_VREG_ID_##_id, \
+ .default_uV = _default_uV, \
+ .peak_uA = _peak_uA, \
+ .avg_uA = _avg_uA, \
+ .pull_down_enable = _pull_down, \
+ .pin_ctrl = _pin_ctrl, \
+ .freq = RPM_VREG_FREQ_##_freq, \
+ .pin_fn = _pin_fn, \
+ .force_mode = _force_mode, \
+ .state = _state, \
+ .sleep_selectable = _sleep_selectable, \
+ }
+
+/* Pin control initialization */
+#define RPM_PC(_id, _always_on, _pin_fn, _pin_ctrl) \
+ { \
+ .init_data = { \
+ .constraints = { \
+ .valid_ops_mask = REGULATOR_CHANGE_STATUS, \
+ .always_on = _always_on, \
+ }, \
+ .num_consumer_supplies = \
+ ARRAY_SIZE(vreg_consumers_##_id##_PC), \
+ .consumer_supplies = vreg_consumers_##_id##_PC, \
+ }, \
+ .id = RPM_VREG_ID_##_id##_PC, \
+ .pin_fn = RPM_VREG_PIN_FN_8660_##_pin_fn, \
.pin_ctrl = _pin_ctrl, \
- .freq = _freq, \
- .pin_fn = _pin_fn, \
- .mode = _rpm_mode, \
- .state = _state, \
- .sleep_selectable = _sleep_selectable, \
}
/*
@@ -3882,198 +3920,165 @@
* .init_data.constraints.initial_mode.
*/
-#define RPM_VREG_INIT_LDO(_id, _always_on, _pd, _sleep_selectable, _min_uV, \
- _max_uV, _init_peak_uA, _pin_ctrl) \
+#define RPM_LDO(_id, _always_on, _pd, _sleep_selectable, _min_uV, _max_uV, \
+ _init_peak_uA) \
RPM_VREG_INIT(_id, _min_uV, _max_uV, REGULATOR_MODE_FAST | \
REGULATOR_MODE_NORMAL | REGULATOR_MODE_IDLE | \
REGULATOR_MODE_STANDBY, REGULATOR_CHANGE_VOLTAGE | \
REGULATOR_CHANGE_STATUS | REGULATOR_CHANGE_MODE | \
REGULATOR_CHANGE_DRMS, 0, _min_uV, _init_peak_uA, \
- _init_peak_uA, _pd, _pin_ctrl, RPM_VREG_FREQ_NONE, \
- RPM_VREG_PIN_FN_ENABLE, RPM_VREG_MODE_NONE, \
- RPM_VREG_STATE_OFF, _sleep_selectable, _always_on)
-
-#define RPM_VREG_INIT_LDO_PF(_id, _always_on, _pd, _sleep_selectable, _min_uV, \
- _max_uV, _init_peak_uA, _pin_ctrl, _pin_fn) \
- RPM_VREG_INIT(_id, _min_uV, _max_uV, REGULATOR_MODE_FAST | \
- REGULATOR_MODE_NORMAL | REGULATOR_MODE_IDLE | \
- REGULATOR_MODE_STANDBY, REGULATOR_CHANGE_VOLTAGE | \
- REGULATOR_CHANGE_STATUS | REGULATOR_CHANGE_MODE | \
- REGULATOR_CHANGE_DRMS, 0, _min_uV, _init_peak_uA, \
- _init_peak_uA, _pd, _pin_ctrl, RPM_VREG_FREQ_NONE, \
- _pin_fn, RPM_VREG_MODE_NONE, RPM_VREG_STATE_OFF, \
+ _init_peak_uA, _pd, RPM_VREG_PIN_CTRL_NONE, NONE, \
+ RPM_VREG_PIN_FN_8660_ENABLE, \
+ RPM_VREG_FORCE_MODE_8660_NONE, RPM_VREG_STATE_OFF, \
_sleep_selectable, _always_on)
-#define RPM_VREG_INIT_SMPS(_id, _always_on, _pd, _sleep_selectable, _min_uV, \
- _max_uV, _init_peak_uA, _pin_ctrl, _freq) \
+#define RPM_SMPS(_id, _always_on, _pd, _sleep_selectable, _min_uV, _max_uV, \
+ _init_peak_uA, _freq) \
RPM_VREG_INIT(_id, _min_uV, _max_uV, REGULATOR_MODE_FAST | \
REGULATOR_MODE_NORMAL | REGULATOR_MODE_IDLE | \
REGULATOR_MODE_STANDBY, REGULATOR_CHANGE_VOLTAGE | \
REGULATOR_CHANGE_STATUS | REGULATOR_CHANGE_MODE | \
REGULATOR_CHANGE_DRMS, 0, _min_uV, _init_peak_uA, \
- _init_peak_uA, _pd, _pin_ctrl, _freq, \
- RPM_VREG_PIN_FN_ENABLE, RPM_VREG_MODE_NONE, \
- RPM_VREG_STATE_OFF, _sleep_selectable, _always_on)
+ _init_peak_uA, _pd, RPM_VREG_PIN_CTRL_NONE, _freq, \
+ RPM_VREG_PIN_FN_8660_ENABLE, \
+ RPM_VREG_FORCE_MODE_8660_NONE, RPM_VREG_STATE_OFF, \
+ _sleep_selectable, _always_on)
-#define RPM_VREG_INIT_VS(_id, _always_on, _pd, _sleep_selectable, _pin_ctrl) \
+#define RPM_VS(_id, _always_on, _pd, _sleep_selectable) \
RPM_VREG_INIT(_id, 0, 0, REGULATOR_MODE_NORMAL | REGULATOR_MODE_IDLE, \
REGULATOR_CHANGE_STATUS | REGULATOR_CHANGE_MODE, 0, 0, \
- 1000, 1000, _pd, _pin_ctrl, RPM_VREG_FREQ_NONE, \
- RPM_VREG_PIN_FN_ENABLE, RPM_VREG_MODE_NONE, \
- RPM_VREG_STATE_OFF, _sleep_selectable, _always_on)
+ 1000, 1000, _pd, RPM_VREG_PIN_CTRL_NONE, NONE, \
+ RPM_VREG_PIN_FN_8660_ENABLE, \
+ RPM_VREG_FORCE_MODE_8660_NONE, RPM_VREG_STATE_OFF, \
+ _sleep_selectable, _always_on)
-#define RPM_VREG_INIT_NCP(_id, _always_on, _pd, _sleep_selectable, _min_uV, \
- _max_uV, _pin_ctrl) \
+#define RPM_NCP(_id, _always_on, _pd, _sleep_selectable, _min_uV, _max_uV) \
RPM_VREG_INIT(_id, _min_uV, _max_uV, REGULATOR_MODE_NORMAL, \
REGULATOR_CHANGE_VOLTAGE | REGULATOR_CHANGE_STATUS, 0, \
- _min_uV, 1000, 1000, _pd, _pin_ctrl, RPM_VREG_FREQ_NONE, \
- RPM_VREG_PIN_FN_ENABLE, RPM_VREG_MODE_NONE, \
- RPM_VREG_STATE_OFF, _sleep_selectable, _always_on)
+ _min_uV, 1000, 1000, _pd, RPM_VREG_PIN_CTRL_NONE, NONE, \
+ RPM_VREG_PIN_FN_8660_ENABLE, \
+ RPM_VREG_FORCE_MODE_8660_NONE, RPM_VREG_STATE_OFF, \
+ _sleep_selectable, _always_on)
-#define LDO50HMIN RPM_VREG_LDO_50_HPM_MIN_LOAD
-#define LDO150HMIN RPM_VREG_LDO_150_HPM_MIN_LOAD
-#define LDO300HMIN RPM_VREG_LDO_300_HPM_MIN_LOAD
-#define SMPS_HMIN RPM_VREG_SMPS_HPM_MIN_LOAD
-#define FTS_HMIN RPM_VREG_FTSMPS_HPM_MIN_LOAD
+#define LDO50HMIN RPM_VREG_8660_LDO_50_HPM_MIN_LOAD
+#define LDO150HMIN RPM_VREG_8660_LDO_150_HPM_MIN_LOAD
+#define LDO300HMIN RPM_VREG_8660_LDO_300_HPM_MIN_LOAD
+#define SMPS_HMIN RPM_VREG_8660_SMPS_HPM_MIN_LOAD
+#define FTS_HMIN RPM_VREG_8660_FTSMPS_HPM_MIN_LOAD
-static struct rpm_vreg_pdata rpm_vreg_init_pdata[RPM_VREG_ID_MAX] = {
- RPM_VREG_INIT_LDO(PM8058_L0, 0, 1, 0, 1200000, 1200000, LDO150HMIN, 0),
- RPM_VREG_INIT_LDO(PM8058_L1, 0, 1, 0, 1200000, 1200000, LDO300HMIN, 0),
- RPM_VREG_INIT_LDO(PM8058_L2, 0, 1, 0, 1800000, 2600000, LDO300HMIN, 0),
- RPM_VREG_INIT_LDO(PM8058_L3, 0, 1, 0, 1800000, 1800000, LDO150HMIN, 0),
- RPM_VREG_INIT_LDO(PM8058_L4, 0, 1, 0, 2850000, 2850000, LDO50HMIN, 0),
- RPM_VREG_INIT_LDO(PM8058_L5, 0, 1, 0, 2850000, 2850000, LDO300HMIN, 0),
- RPM_VREG_INIT_LDO(PM8058_L6, 0, 1, 0, 3000000, 3600000, LDO50HMIN, 0),
- RPM_VREG_INIT_LDO(PM8058_L7, 0, 1, 0, 1800000, 1800000, LDO50HMIN, 0),
- RPM_VREG_INIT_LDO_PF(PM8058_L8, 0, 1, 0, 2900000, 3050000, LDO300HMIN,
- RPM_VREG_PIN_CTRL_NONE, RPM_VREG_PIN_FN_SLEEP_B),
- RPM_VREG_INIT_LDO(PM8058_L9, 0, 1, 0, 1800000, 1800000, LDO300HMIN, 0),
- RPM_VREG_INIT_LDO(PM8058_L10, 0, 1, 0, 2600000, 2600000, LDO300HMIN, 0),
- RPM_VREG_INIT_LDO(PM8058_L11, 0, 1, 0, 1500000, 1500000, LDO150HMIN, 0),
- RPM_VREG_INIT_LDO(PM8058_L12, 0, 1, 0, 2900000, 2900000, LDO150HMIN, 0),
- RPM_VREG_INIT_LDO(PM8058_L13, 0, 1, 0, 2050000, 2050000, LDO300HMIN, 0),
- RPM_VREG_INIT_LDO(PM8058_L14, 0, 0, 0, 2850000, 2850000, LDO300HMIN, 0),
- RPM_VREG_INIT_LDO(PM8058_L15, 0, 1, 0, 2850000, 2850000, LDO300HMIN, 0),
- RPM_VREG_INIT_LDO(PM8058_L16, 1, 1, 0, 1800000, 1800000, LDO300HMIN, 0),
- RPM_VREG_INIT_LDO(PM8058_L17, 0, 1, 0, 2600000, 2600000, LDO150HMIN, 0),
- RPM_VREG_INIT_LDO(PM8058_L18, 0, 1, 0, 2200000, 2200000, LDO150HMIN, 0),
- RPM_VREG_INIT_LDO(PM8058_L19, 0, 1, 0, 2500000, 2500000, LDO150HMIN, 0),
- RPM_VREG_INIT_LDO_PF(PM8058_L20, 0, 1, 0, 1800000, 1800000, LDO150HMIN,
- RPM_VREG_PIN_CTRL_NONE, RPM_VREG_PIN_FN_SLEEP_B),
- RPM_VREG_INIT_LDO_PF(PM8058_L21, 1, 1, 0, 1200000, 1200000, LDO150HMIN,
- RPM_VREG_PIN_CTRL_NONE, RPM_VREG_PIN_FN_SLEEP_B),
- RPM_VREG_INIT_LDO(PM8058_L22, 0, 1, 0, 1150000, 1150000, LDO300HMIN, 0),
- RPM_VREG_INIT_LDO(PM8058_L23, 0, 1, 0, 1200000, 1200000, LDO300HMIN, 0),
- RPM_VREG_INIT_LDO(PM8058_L24, 0, 1, 0, 1200000, 1200000, LDO150HMIN, 0),
- RPM_VREG_INIT_LDO(PM8058_L25, 0, 1, 0, 1200000, 1200000, LDO150HMIN, 0),
-
- RPM_VREG_INIT_SMPS(PM8058_S0, 0, 1, 1, 500000, 1250000, SMPS_HMIN, 0,
- RPM_VREG_FREQ_1p60),
- RPM_VREG_INIT_SMPS(PM8058_S1, 0, 1, 1, 500000, 1250000, SMPS_HMIN, 0,
- RPM_VREG_FREQ_1p60),
- RPM_VREG_INIT_SMPS(PM8058_S2, 0, 1, 1, 1200000, 1400000, SMPS_HMIN,
- RPM_VREG_PIN_CTRL_A0, RPM_VREG_FREQ_1p60),
- RPM_VREG_INIT_SMPS(PM8058_S3, 1, 1, 0, 1800000, 1800000, SMPS_HMIN, 0,
- RPM_VREG_FREQ_1p60),
- RPM_VREG_INIT_SMPS(PM8058_S4, 1, 1, 0, 2200000, 2200000, SMPS_HMIN, 0,
- RPM_VREG_FREQ_1p60),
-
- RPM_VREG_INIT_VS(PM8058_LVS0, 0, 1, 0, 0),
- RPM_VREG_INIT_VS(PM8058_LVS1, 0, 1, 0, 0),
-
- RPM_VREG_INIT_NCP(PM8058_NCP, 0, 1, 0, 1800000, 1800000, 0),
-
- RPM_VREG_INIT_LDO(PM8901_L0, 0, 1, 0, 1200000, 1200000, LDO300HMIN,
- RPM_VREG_PIN_CTRL_A0),
- RPM_VREG_INIT_LDO(PM8901_L1, 0, 1, 0, 3300000, 3300000, LDO300HMIN, 0),
- RPM_VREG_INIT_LDO(PM8901_L2, 0, 1, 0, 2850000, 3300000, LDO300HMIN, 0),
- RPM_VREG_INIT_LDO(PM8901_L3, 0, 1, 0, 3300000, 3300000, LDO300HMIN, 0),
- RPM_VREG_INIT_LDO(PM8901_L4, 0, 1, 0, 2600000, 2600000, LDO300HMIN, 0),
- RPM_VREG_INIT_LDO(PM8901_L5, 0, 1, 0, 2850000, 2850000, LDO300HMIN, 0),
- RPM_VREG_INIT_LDO(PM8901_L6, 0, 1, 0, 2200000, 2200000, LDO300HMIN, 0),
-
- RPM_VREG_INIT_SMPS(PM8901_S2, 0, 1, 0, 1300000, 1300000, FTS_HMIN, 0,
- RPM_VREG_FREQ_1p60),
- RPM_VREG_INIT_SMPS(PM8901_S3, 0, 1, 0, 1100000, 1100000, FTS_HMIN, 0,
- RPM_VREG_FREQ_1p60),
- RPM_VREG_INIT_SMPS(PM8901_S4, 0, 1, 0, 1225000, 1225000, FTS_HMIN,
- RPM_VREG_PIN_CTRL_A0, RPM_VREG_FREQ_1p60),
-
- RPM_VREG_INIT_VS(PM8901_LVS0, 1, 1, 0, 0),
- RPM_VREG_INIT_VS(PM8901_LVS1, 0, 1, 0, 0),
- RPM_VREG_INIT_VS(PM8901_LVS2, 0, 1, 0, 0),
- RPM_VREG_INIT_VS(PM8901_LVS3, 0, 1, 0, 0),
- RPM_VREG_INIT_VS(PM8901_MVS0, 0, 1, 0, 0),
+/* RPM early regulator constraints */
+static struct rpm_regulator_init_data rpm_regulator_early_init_data[] = {
+ /* ID a_on pd ss min_uV max_uV init_ip freq */
+ RPM_SMPS(PM8058_S0, 0, 1, 1, 500000, 1250000, SMPS_HMIN, 1p60),
+ RPM_SMPS(PM8058_S1, 0, 1, 1, 500000, 1250000, SMPS_HMIN, 1p60),
};
-#define RPM_VREG(_id) \
- [_id] = { \
- .name = "rpm-regulator", \
- .id = _id, \
- .dev = { \
- .platform_data = &rpm_vreg_init_pdata[_id], \
- }, \
- }
+/* RPM regulator constraints */
+static struct rpm_regulator_init_data rpm_regulator_init_data[] = {
+ /* ID a_on pd ss min_uV max_uV init_ip */
+ RPM_LDO(PM8058_L0, 0, 1, 0, 1200000, 1200000, LDO150HMIN),
+ RPM_LDO(PM8058_L1, 0, 1, 0, 1200000, 1200000, LDO300HMIN),
+ RPM_LDO(PM8058_L2, 0, 1, 0, 1800000, 2600000, LDO300HMIN),
+ RPM_LDO(PM8058_L3, 0, 1, 0, 1800000, 1800000, LDO150HMIN),
+ RPM_LDO(PM8058_L4, 0, 1, 0, 2850000, 2850000, LDO50HMIN),
+ RPM_LDO(PM8058_L5, 0, 1, 0, 2850000, 2850000, LDO300HMIN),
+ RPM_LDO(PM8058_L6, 0, 1, 0, 3000000, 3600000, LDO50HMIN),
+ RPM_LDO(PM8058_L7, 0, 1, 0, 1800000, 1800000, LDO50HMIN),
+ RPM_LDO(PM8058_L8, 0, 1, 0, 2900000, 3050000, LDO300HMIN),
+ RPM_LDO(PM8058_L9, 0, 1, 0, 1800000, 1800000, LDO300HMIN),
+ RPM_LDO(PM8058_L10, 0, 1, 0, 2600000, 2600000, LDO300HMIN),
+ RPM_LDO(PM8058_L11, 0, 1, 0, 1500000, 1500000, LDO150HMIN),
+ RPM_LDO(PM8058_L12, 0, 1, 0, 2900000, 2900000, LDO150HMIN),
+ RPM_LDO(PM8058_L13, 0, 1, 0, 2050000, 2050000, LDO300HMIN),
+ RPM_LDO(PM8058_L14, 0, 0, 0, 2850000, 2850000, LDO300HMIN),
+ RPM_LDO(PM8058_L15, 0, 1, 0, 2850000, 2850000, LDO300HMIN),
+ RPM_LDO(PM8058_L16, 1, 1, 0, 1800000, 1800000, LDO300HMIN),
+ RPM_LDO(PM8058_L17, 0, 1, 0, 2600000, 2600000, LDO150HMIN),
+ RPM_LDO(PM8058_L18, 0, 1, 0, 2200000, 2200000, LDO150HMIN),
+ RPM_LDO(PM8058_L19, 0, 1, 0, 2500000, 2500000, LDO150HMIN),
+ RPM_LDO(PM8058_L20, 0, 1, 0, 1800000, 1800000, LDO150HMIN),
+ RPM_LDO(PM8058_L21, 1, 1, 0, 1200000, 1200000, LDO150HMIN),
+ RPM_LDO(PM8058_L22, 0, 1, 0, 1150000, 1150000, LDO300HMIN),
+ RPM_LDO(PM8058_L23, 0, 1, 0, 1200000, 1200000, LDO300HMIN),
+ RPM_LDO(PM8058_L24, 0, 1, 0, 1200000, 1200000, LDO150HMIN),
+ RPM_LDO(PM8058_L25, 0, 1, 0, 1200000, 1200000, LDO150HMIN),
-static struct platform_device rpm_vreg_device[RPM_VREG_ID_MAX] = {
- RPM_VREG(RPM_VREG_ID_PM8058_L0),
- RPM_VREG(RPM_VREG_ID_PM8058_L1),
- RPM_VREG(RPM_VREG_ID_PM8058_L2),
- RPM_VREG(RPM_VREG_ID_PM8058_L3),
- RPM_VREG(RPM_VREG_ID_PM8058_L4),
- RPM_VREG(RPM_VREG_ID_PM8058_L5),
- RPM_VREG(RPM_VREG_ID_PM8058_L6),
- RPM_VREG(RPM_VREG_ID_PM8058_L7),
- RPM_VREG(RPM_VREG_ID_PM8058_L8),
- RPM_VREG(RPM_VREG_ID_PM8058_L9),
- RPM_VREG(RPM_VREG_ID_PM8058_L10),
- RPM_VREG(RPM_VREG_ID_PM8058_L11),
- RPM_VREG(RPM_VREG_ID_PM8058_L12),
- RPM_VREG(RPM_VREG_ID_PM8058_L13),
- RPM_VREG(RPM_VREG_ID_PM8058_L14),
- RPM_VREG(RPM_VREG_ID_PM8058_L15),
- RPM_VREG(RPM_VREG_ID_PM8058_L16),
- RPM_VREG(RPM_VREG_ID_PM8058_L17),
- RPM_VREG(RPM_VREG_ID_PM8058_L18),
- RPM_VREG(RPM_VREG_ID_PM8058_L19),
- RPM_VREG(RPM_VREG_ID_PM8058_L20),
- RPM_VREG(RPM_VREG_ID_PM8058_L21),
- RPM_VREG(RPM_VREG_ID_PM8058_L22),
- RPM_VREG(RPM_VREG_ID_PM8058_L23),
- RPM_VREG(RPM_VREG_ID_PM8058_L24),
- RPM_VREG(RPM_VREG_ID_PM8058_L25),
- RPM_VREG(RPM_VREG_ID_PM8058_S0),
- RPM_VREG(RPM_VREG_ID_PM8058_S1),
- RPM_VREG(RPM_VREG_ID_PM8058_S2),
- RPM_VREG(RPM_VREG_ID_PM8058_S3),
- RPM_VREG(RPM_VREG_ID_PM8058_S4),
- RPM_VREG(RPM_VREG_ID_PM8058_LVS0),
- RPM_VREG(RPM_VREG_ID_PM8058_LVS1),
- RPM_VREG(RPM_VREG_ID_PM8058_NCP),
- RPM_VREG(RPM_VREG_ID_PM8901_L0),
- RPM_VREG(RPM_VREG_ID_PM8901_L1),
- RPM_VREG(RPM_VREG_ID_PM8901_L2),
- RPM_VREG(RPM_VREG_ID_PM8901_L3),
- RPM_VREG(RPM_VREG_ID_PM8901_L4),
- RPM_VREG(RPM_VREG_ID_PM8901_L5),
- RPM_VREG(RPM_VREG_ID_PM8901_L6),
- RPM_VREG(RPM_VREG_ID_PM8901_S2),
- RPM_VREG(RPM_VREG_ID_PM8901_S3),
- RPM_VREG(RPM_VREG_ID_PM8901_S4),
- RPM_VREG(RPM_VREG_ID_PM8901_LVS0),
- RPM_VREG(RPM_VREG_ID_PM8901_LVS1),
- RPM_VREG(RPM_VREG_ID_PM8901_LVS2),
- RPM_VREG(RPM_VREG_ID_PM8901_LVS3),
- RPM_VREG(RPM_VREG_ID_PM8901_MVS0),
+ /* ID a_on pd ss min_uV max_uV init_ip freq */
+ RPM_SMPS(PM8058_S2, 0, 1, 1, 1200000, 1400000, SMPS_HMIN, 1p60),
+ RPM_SMPS(PM8058_S3, 1, 1, 0, 1800000, 1800000, SMPS_HMIN, 1p60),
+ RPM_SMPS(PM8058_S4, 1, 1, 0, 2200000, 2200000, SMPS_HMIN, 1p60),
+
+ /* ID a_on pd ss */
+ RPM_VS(PM8058_LVS0, 0, 1, 0),
+ RPM_VS(PM8058_LVS1, 0, 1, 0),
+
+ /* ID a_on pd ss min_uV max_uV */
+ RPM_NCP(PM8058_NCP, 0, 1, 0, 1800000, 1800000),
+
+ /* ID a_on pd ss min_uV max_uV init_ip */
+ RPM_LDO(PM8901_L0, 0, 1, 0, 1200000, 1200000, LDO300HMIN),
+ RPM_LDO(PM8901_L1, 0, 1, 0, 3300000, 3300000, LDO300HMIN),
+ RPM_LDO(PM8901_L2, 0, 1, 0, 2850000, 3300000, LDO300HMIN),
+ RPM_LDO(PM8901_L3, 0, 1, 0, 3300000, 3300000, LDO300HMIN),
+ RPM_LDO(PM8901_L4, 0, 1, 0, 2600000, 2600000, LDO300HMIN),
+ RPM_LDO(PM8901_L5, 0, 1, 0, 2850000, 2850000, LDO300HMIN),
+ RPM_LDO(PM8901_L6, 0, 1, 0, 2200000, 2200000, LDO300HMIN),
+
+ /* ID a_on pd ss min_uV max_uV init_ip freq */
+ RPM_SMPS(PM8901_S2, 0, 1, 0, 1300000, 1300000, FTS_HMIN, 1p60),
+ RPM_SMPS(PM8901_S3, 0, 1, 0, 1100000, 1100000, FTS_HMIN, 1p60),
+ RPM_SMPS(PM8901_S4, 0, 1, 0, 1225000, 1225000, FTS_HMIN, 1p60),
+
+ /* ID a_on pd ss */
+ RPM_VS(PM8901_LVS0, 1, 1, 0),
+ RPM_VS(PM8901_LVS1, 0, 1, 0),
+ RPM_VS(PM8901_LVS2, 0, 1, 0),
+ RPM_VS(PM8901_LVS3, 0, 1, 0),
+ RPM_VS(PM8901_MVS0, 0, 1, 0),
+
+ /* ID a_on pin_func pin_ctrl */
+ RPM_PC(PM8058_L8, 0, SLEEP_B, RPM_VREG_PIN_CTRL_NONE),
+ RPM_PC(PM8058_L20, 0, SLEEP_B, RPM_VREG_PIN_CTRL_NONE),
+ RPM_PC(PM8058_L21, 1, SLEEP_B, RPM_VREG_PIN_CTRL_NONE),
+ RPM_PC(PM8058_S2, 0, ENABLE, RPM_VREG_PIN_CTRL_PM8058_A0),
+ RPM_PC(PM8901_L0, 0, ENABLE, RPM_VREG_PIN_CTRL_PM8901_A0),
+ RPM_PC(PM8901_S4, 0, ENABLE, RPM_VREG_PIN_CTRL_PM8901_A0),
+};
+
+static struct rpm_regulator_platform_data rpm_regulator_early_pdata = {
+ .init_data = rpm_regulator_early_init_data,
+ .num_regulators = ARRAY_SIZE(rpm_regulator_early_init_data),
+ .version = RPM_VREG_VERSION_8660,
+ .vreg_id_vdd_mem = RPM_VREG_ID_PM8058_S0,
+ .vreg_id_vdd_dig = RPM_VREG_ID_PM8058_S1,
+};
+
+static struct rpm_regulator_platform_data rpm_regulator_pdata = {
+ .init_data = rpm_regulator_init_data,
+ .num_regulators = ARRAY_SIZE(rpm_regulator_init_data),
+ .version = RPM_VREG_VERSION_8660,
+};
+
+static struct platform_device rpm_regulator_early_device = {
+ .name = "rpm-regulator",
+ .id = 0,
+ .dev = {
+ .platform_data = &rpm_regulator_early_pdata,
+ },
+};
+
+static struct platform_device rpm_regulator_device = {
+ .name = "rpm-regulator",
+ .id = 1,
+ .dev = {
+ .platform_data = &rpm_regulator_pdata,
+ },
};
static struct platform_device *early_regulators[] __initdata = {
&msm_device_saw_s0,
&msm_device_saw_s1,
-#ifdef CONFIG_PMIC8058
- &rpm_vreg_device[RPM_VREG_ID_PM8058_S0],
- &rpm_vreg_device[RPM_VREG_ID_PM8058_S1],
-#endif
+ &rpm_regulator_early_device,
};
static struct platform_device *early_devices[] __initdata = {
@@ -5061,57 +5066,7 @@
#ifdef CONFIG_SENSORS_MSM_ADC
&msm_adc_device,
#endif
-#ifdef CONFIG_PMIC8058
- &rpm_vreg_device[RPM_VREG_ID_PM8058_L0],
- &rpm_vreg_device[RPM_VREG_ID_PM8058_L1],
- &rpm_vreg_device[RPM_VREG_ID_PM8058_L2],
- &rpm_vreg_device[RPM_VREG_ID_PM8058_L3],
- &rpm_vreg_device[RPM_VREG_ID_PM8058_L4],
- &rpm_vreg_device[RPM_VREG_ID_PM8058_L5],
- &rpm_vreg_device[RPM_VREG_ID_PM8058_L6],
- &rpm_vreg_device[RPM_VREG_ID_PM8058_L7],
- &rpm_vreg_device[RPM_VREG_ID_PM8058_L8],
- &rpm_vreg_device[RPM_VREG_ID_PM8058_L9],
- &rpm_vreg_device[RPM_VREG_ID_PM8058_L10],
- &rpm_vreg_device[RPM_VREG_ID_PM8058_L11],
- &rpm_vreg_device[RPM_VREG_ID_PM8058_L12],
- &rpm_vreg_device[RPM_VREG_ID_PM8058_L13],
- &rpm_vreg_device[RPM_VREG_ID_PM8058_L14],
- &rpm_vreg_device[RPM_VREG_ID_PM8058_L15],
- &rpm_vreg_device[RPM_VREG_ID_PM8058_L16],
- &rpm_vreg_device[RPM_VREG_ID_PM8058_L17],
- &rpm_vreg_device[RPM_VREG_ID_PM8058_L18],
- &rpm_vreg_device[RPM_VREG_ID_PM8058_L19],
- &rpm_vreg_device[RPM_VREG_ID_PM8058_L20],
- &rpm_vreg_device[RPM_VREG_ID_PM8058_L21],
- &rpm_vreg_device[RPM_VREG_ID_PM8058_L22],
- &rpm_vreg_device[RPM_VREG_ID_PM8058_L23],
- &rpm_vreg_device[RPM_VREG_ID_PM8058_L24],
- &rpm_vreg_device[RPM_VREG_ID_PM8058_L25],
- &rpm_vreg_device[RPM_VREG_ID_PM8058_S2],
- &rpm_vreg_device[RPM_VREG_ID_PM8058_S3],
- &rpm_vreg_device[RPM_VREG_ID_PM8058_S4],
- &rpm_vreg_device[RPM_VREG_ID_PM8058_LVS0],
- &rpm_vreg_device[RPM_VREG_ID_PM8058_LVS1],
- &rpm_vreg_device[RPM_VREG_ID_PM8058_NCP],
-#endif
-#ifdef CONFIG_PMIC8901
- &rpm_vreg_device[RPM_VREG_ID_PM8901_L0],
- &rpm_vreg_device[RPM_VREG_ID_PM8901_L1],
- &rpm_vreg_device[RPM_VREG_ID_PM8901_L2],
- &rpm_vreg_device[RPM_VREG_ID_PM8901_L3],
- &rpm_vreg_device[RPM_VREG_ID_PM8901_L4],
- &rpm_vreg_device[RPM_VREG_ID_PM8901_L5],
- &rpm_vreg_device[RPM_VREG_ID_PM8901_L6],
- &rpm_vreg_device[RPM_VREG_ID_PM8901_S2],
- &rpm_vreg_device[RPM_VREG_ID_PM8901_S3],
- &rpm_vreg_device[RPM_VREG_ID_PM8901_S4],
- &rpm_vreg_device[RPM_VREG_ID_PM8901_LVS0],
- &rpm_vreg_device[RPM_VREG_ID_PM8901_LVS1],
- &rpm_vreg_device[RPM_VREG_ID_PM8901_LVS2],
- &rpm_vreg_device[RPM_VREG_ID_PM8901_LVS3],
- &rpm_vreg_device[RPM_VREG_ID_PM8901_MVS0],
-#endif
+ &rpm_regulator_device,
#if defined(CONFIG_CRYPTO_DEV_QCRYPTO) || \
defined(CONFIG_CRYPTO_DEV_QCRYPTO_MODULE)
@@ -10118,10 +10073,15 @@
* un-reworked SURF cannot resume from.
*/
if (machine_is_msm8x60_surf()) {
- rpm_vreg_init_pdata[RPM_VREG_ID_PM8901_L4]
- .init_data.constraints.always_on = 1;
- rpm_vreg_init_pdata[RPM_VREG_ID_PM8901_L6]
- .init_data.constraints.always_on = 1;
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(rpm_regulator_init_data); i++)
+ if (rpm_regulator_init_data[i].id
+ == RPM_VREG_ID_PM8901_L4
+ || rpm_regulator_init_data[i].id
+ == RPM_VREG_ID_PM8901_L6)
+ rpm_regulator_init_data[i]
+ .init_data.constraints.always_on = 1;
}
/*
diff --git a/arch/arm/mach-msm/clock-7x30.c b/arch/arm/mach-msm/clock-7x30.c
index 5d7736f..50be14b 100644
--- a/arch/arm/mach-msm/clock-7x30.c
+++ b/arch/arm/mach-msm/clock-7x30.c
@@ -2750,7 +2750,7 @@
{ CLK_LOOKUP("ebi1_lcdc_clk", ebi_lcdc_clk.c, NULL) },
{ CLK_LOOKUP("ebi1_mddi_clk", ebi_mddi_clk.c, NULL) },
{ CLK_LOOKUP("ebi1_tv_clk", ebi_tv_clk.c, NULL) },
- { CLK_LOOKUP("ebi1_vcd_clk", ebi_vcd_clk.c, NULL) },
+ { CLK_LOOKUP("mem_clk", ebi_vcd_clk.c, "msm_vidc.0") },
{ CLK_LOOKUP("ebi1_vfe_clk", ebi_vfe_clk.c, NULL) },
{ CLK_LOOKUP("mem_clk", ebi_adm_clk.c, "msm_dmov") },
@@ -2850,10 +2850,10 @@
OWN(APPS3, 11, "csi_pclk", csi0_p_clk, NULL),
OWN(APPS3, 0, "mdp_clk", mdp_clk, NULL),
OWN(APPS3, 0, "core_clk", mdp_clk, "footswitch-pcom.4"),
- OWN(APPS3, 2, "mfc_clk", mfc_clk, NULL),
+ OWN(APPS3, 2, "core_clk", mfc_clk, "msm_vidc.0"),
OWN(APPS3, 2, "core_clk", mfc_clk, "footswitch-pcom.5"),
- OWN(APPS3, 2, "mfc_div2_clk", mfc_div2_clk, NULL),
- OWN(APPS3, 2, "mfc_pclk", mfc_p_clk, NULL),
+ OWN(APPS3, 2, "core_div2_clk", mfc_div2_clk, "msm_vidc.0"),
+ OWN(APPS3, 2, "iface_clk", mfc_p_clk, "msm_vidc.0"),
OWN(APPS3, 2, "iface_clk", mfc_p_clk, "footswitch-pcom.5"),
OWN(APPS3, 4, "vpe_clk", vpe_clk, NULL),
OWN(APPS3, 4, "core_clk", vpe_clk, "footswitch-pcom.9"),
diff --git a/arch/arm/mach-msm/clock-8960.c b/arch/arm/mach-msm/clock-8960.c
index 21abb8b..ea2d9d2 100644
--- a/arch/arm/mach-msm/clock-8960.c
+++ b/arch/arm/mach-msm/clock-8960.c
@@ -5160,6 +5160,7 @@
CLK_LOOKUP("mmfab_a_clk", mmfab_a_clk.c, NULL),
CLK_LOOKUP("mmfpb_clk", mmfpb_clk.c, NULL),
CLK_LOOKUP("mmfpb_a_clk", mmfpb_a_clk.c, NULL),
+ CLK_LOOKUP("mmfpb_a_clk", mmfpb_a_clk.c, "clock-8960"),
CLK_LOOKUP("sfab_clk", sfab_clk.c, NULL),
CLK_LOOKUP("sfab_a_clk", sfab_a_clk.c, NULL),
CLK_LOOKUP("sfpb_clk", sfpb_clk.c, NULL),
@@ -5296,7 +5297,7 @@
CLK_LOOKUP("tv_src_clk", tv_src_clk.c, NULL),
CLK_LOOKUP("tv_enc_clk", tv_enc_clk.c, NULL),
CLK_LOOKUP("tv_dac_clk", tv_dac_clk.c, NULL),
- CLK_LOOKUP("vcodec_clk", vcodec_clk.c, NULL),
+ CLK_LOOKUP("core_clk", vcodec_clk.c, "msm_vidc.0"),
CLK_LOOKUP("core_clk", vcodec_clk.c, "footswitch-8x60.7"),
CLK_LOOKUP("mdp_tv_clk", mdp_tv_clk.c, NULL),
CLK_LOOKUP("hdmi_clk", hdmi_tv_clk.c, NULL),
@@ -5337,7 +5338,7 @@
CLK_LOOKUP("rotator_pclk", rot_p_clk.c, NULL),
CLK_LOOKUP("iface_clk", rot_p_clk.c, "footswitch-8x60.6"),
CLK_LOOKUP("tv_enc_pclk", tv_enc_p_clk.c, NULL),
- CLK_LOOKUP("vcodec_pclk", vcodec_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("iface_clk", vfe_p_clk.c, "footswitch-8x60.8"),
@@ -5763,6 +5764,20 @@
static int __init msm8960_clock_late_init(void)
{
+ int rc;
+ struct clk *mmfpb_a_clk = clk_get_sys("clock-8960", "mmfpb_a_clk");
+
+ /* Vote for MMFPB to be at least 76.8MHz when an Apps CPU is active. */
+ 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);
+ if (WARN(rc, "mmfpb_a_clk rate was not set (%d)\n", rc))
+ return rc;
+ rc = clk_enable(mmfpb_a_clk);
+ if (WARN(rc, "mmfpb_a_clk not enabled (%d)\n", rc))
+ return rc;
+
return local_unvote_sys_vdd(HIGH);
}
diff --git a/arch/arm/mach-msm/clock-8x60.c b/arch/arm/mach-msm/clock-8x60.c
index 4ca366f..1273198 100644
--- a/arch/arm/mach-msm/clock-8x60.c
+++ b/arch/arm/mach-msm/clock-8x60.c
@@ -3653,7 +3653,7 @@
CLK_LOOKUP("core_clk", rot_clk.c, "footswitch-8x60.6"),
CLK_LOOKUP("tv_enc_clk", tv_enc_clk.c, NULL),
CLK_LOOKUP("tv_dac_clk", tv_dac_clk.c, NULL),
- CLK_LOOKUP("vcodec_clk", vcodec_clk.c, NULL),
+ CLK_LOOKUP("core_clk", vcodec_clk.c, "msm_vidc.0"),
CLK_LOOKUP("core_clk", vcodec_clk.c, "footswitch-8x60.7"),
CLK_LOOKUP("mdp_tv_clk", mdp_tv_clk.c, NULL),
CLK_LOOKUP("hdmi_clk", hdmi_tv_clk.c, NULL),
@@ -3699,7 +3699,7 @@
CLK_LOOKUP("rotator_pclk", rot_p_clk.c, NULL),
CLK_LOOKUP("iface_clk", rot_p_clk.c, "footswitch-8x60.6"),
CLK_LOOKUP("tv_enc_pclk", tv_enc_p_clk.c, NULL),
- CLK_LOOKUP("vcodec_pclk", vcodec_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("iface_clk", vfe_p_clk.c, "footswitch-8x60.8"),
diff --git a/arch/arm/mach-msm/clock-9615.c b/arch/arm/mach-msm/clock-9615.c
index 96e626d..a5db9b2 100644
--- a/arch/arm/mach-msm/clock-9615.c
+++ b/arch/arm/mach-msm/clock-9615.c
@@ -1666,9 +1666,36 @@
set_fsm_mode(SC_PLL0_MODE_REG);
- } else if (readl_relaxed(SC_PLL0_MODE_REG) & BIT(20))
+ } else if (!(readl_relaxed(SC_PLL0_MODE_REG) & BIT(20)))
WARN(1, "PLL9 enabled in non-FSM mode!\n");
+ /* Check if PLL14 is enabled in FSM mode */
+ is_pll_enabled = readl_relaxed(BB_PLL14_STATUS_REG) & BIT(16);
+
+ if (!is_pll_enabled) {
+ writel_relaxed(0x19, BB_PLL14_L_VAL_REG);
+ writel_relaxed(0x0, BB_PLL14_M_VAL_REG);
+ writel_relaxed(0x1, BB_PLL14_N_VAL_REG);
+
+ regval = readl_relaxed(BB_PLL14_CONFIG_REG);
+
+ /* Enable main output and the MN accumulator */
+ regval |= BIT(23) | BIT(22);
+
+ /* Set pre-divider and post-divider values to 1 and 1 */
+ regval &= ~BIT(19);
+ regval &= ~BM(21, 20);
+
+ /* Set VCO frequency */
+ regval &= ~BM(17, 16);
+
+ writel_relaxed(regval, BB_PLL14_CONFIG_REG);
+
+ set_fsm_mode(BB_PLL14_MODE_REG);
+
+ } else if (!(readl_relaxed(BB_PLL14_MODE_REG) & BIT(20)))
+ WARN(1, "PLL14 enabled in non-FSM mode!\n");
+
/* Enable PLL4 source on the LPASS Primary PLL Mux */
regval = readl_relaxed(LCC_PRI_PLL_CLK_CTL_REG);
writel_relaxed(regval | BIT(0), LCC_PRI_PLL_CLK_CTL_REG);
diff --git a/arch/arm/mach-msm/devices-8960.c b/arch/arm/mach-msm/devices-8960.c
index cc1264d..ffe273e 100644
--- a/arch/arm/mach-msm/devices-8960.c
+++ b/arch/arm/mach-msm/devices-8960.c
@@ -1780,7 +1780,7 @@
.src = MSM_BUS_MASTER_GRAPHICS_3D,
.dst = MSM_BUS_SLAVE_EBI_CH0,
.ab = 0,
- .ib = 1200000000U,
+ .ib = KGSL_CONVERT_TO_MBPS(1200),
},
};
@@ -1789,7 +1789,7 @@
.src = MSM_BUS_MASTER_GRAPHICS_3D,
.dst = MSM_BUS_SLAVE_EBI_CH0,
.ab = 0,
- .ib = 2048000000U,
+ .ib = KGSL_CONVERT_TO_MBPS(2048),
},
};
@@ -1798,7 +1798,7 @@
.src = MSM_BUS_MASTER_GRAPHICS_3D,
.dst = MSM_BUS_SLAVE_EBI_CH0,
.ab = 0,
- .ib = 2656000000U,
+ .ib = KGSL_CONVERT_TO_MBPS(2656),
},
};
@@ -1807,7 +1807,7 @@
.src = MSM_BUS_MASTER_GRAPHICS_3D,
.dst = MSM_BUS_SLAVE_EBI_CH0,
.ab = 0,
- .ib = 3968000000U,
+ .ib = KGSL_CONVERT_TO_MBPS(3968),
},
};
@@ -1854,7 +1854,7 @@
.src = MSM_BUS_MASTER_GRAPHICS_2D_CORE0,
.dst = MSM_BUS_SLAVE_EBI_CH0,
.ab = 0,
- .ib = 204800000U,
+ .ib = KGSL_CONVERT_TO_MBPS(204.8),
},
};
@@ -1889,7 +1889,7 @@
.src = MSM_BUS_MASTER_GRAPHICS_2D_CORE1,
.dst = MSM_BUS_SLAVE_EBI_CH0,
.ab = 0,
- .ib = 204800000U,
+ .ib = KGSL_CONVERT_TO_MBPS(204.8),
},
};
diff --git a/arch/arm/mach-msm/devices-msm7x27.c b/arch/arm/mach-msm/devices-msm7x27.c
index 250cbad..3772884 100644
--- a/arch/arm/mach-msm/devices-msm7x27.c
+++ b/arch/arm/mach-msm/devices-msm7x27.c
@@ -33,7 +33,6 @@
#include <asm/mach/mmc.h>
#include <mach/msm_hsusb.h>
#include <mach/usbdiag.h>
-#include <mach/usb_gadget_fserial.h>
#include <mach/rpc_hsusb.h>
static struct resource resources_uart1[] = {
@@ -299,35 +298,6 @@
return platform_device_register(pdev);
}
-#ifdef CONFIG_USB_ANDROID_DIAG
-struct usb_diag_platform_data usb_diag_pdata = {
- .ch_name = DIAG_LEGACY,
- .update_pid_and_serial_num = usb_diag_update_pid_and_serial_num,
-};
-
-struct platform_device usb_diag_device = {
- .name = "usb_diag",
- .id = -1,
- .dev = {
- .platform_data = &usb_diag_pdata,
- },
-};
-#endif
-
-#ifdef CONFIG_USB_F_SERIAL
-static struct usb_gadget_fserial_platform_data fserial_pdata = {
- .no_ports = 2,
-};
-
-struct platform_device usb_gadget_fserial_device = {
- .name = "usb_fserial",
- .id = -1,
- .dev = {
- .platform_data = &fserial_pdata,
- },
-};
-#endif
-
struct platform_device asoc_msm_pcm = {
.name = "msm-dsp-audio",
.id = 0,
diff --git a/arch/arm/mach-msm/devices-msm7x30.c b/arch/arm/mach-msm/devices-msm7x30.c
index e1a3b4c..0da9de3 100644
--- a/arch/arm/mach-msm/devices-msm7x30.c
+++ b/arch/arm/mach-msm/devices-msm7x30.c
@@ -666,14 +666,14 @@
},
{
.name = "sdcc_dma_chnl",
- .start = DMOV_SDC4_CHAN,
- .end = DMOV_SDC4_CHAN,
+ .start = DMOV_SDC3_CHAN,
+ .end = DMOV_SDC3_CHAN,
.flags = IORESOURCE_DMA,
},
{
.name = "sdcc_dma_crci",
- .start = DMOV_SDC4_CRCI,
- .end = DMOV_SDC4_CRCI,
+ .start = DMOV_SDC3_CRCI,
+ .end = DMOV_SDC3_CRCI,
.flags = IORESOURCE_DMA,
},
};
@@ -691,14 +691,14 @@
},
{
.name = "sdcc_dma_chnl",
- .start = DMOV_SDC3_CHAN,
- .end = DMOV_SDC3_CHAN,
+ .start = DMOV_SDC4_CHAN,
+ .end = DMOV_SDC4_CHAN,
.flags = IORESOURCE_DMA,
},
{
.name = "sdcc_dma_crci",
- .start = DMOV_SDC3_CRCI,
- .end = DMOV_SDC3_CRCI,
+ .start = DMOV_SDC4_CRCI,
+ .end = DMOV_SDC4_CRCI,
.flags = IORESOURCE_DMA,
},
};
diff --git a/arch/arm/mach-msm/devices-msm8x60.c b/arch/arm/mach-msm/devices-msm8x60.c
index 8280aa0..2b15967 100644
--- a/arch/arm/mach-msm/devices-msm8x60.c
+++ b/arch/arm/mach-msm/devices-msm8x60.c
@@ -489,7 +489,7 @@
.src = MSM_BUS_MASTER_GRAPHICS_3D,
.dst = MSM_BUS_SLAVE_EBI_CH0,
.ab = 0,
- .ib = 990000000U,
+ .ib = KGSL_CONVERT_TO_MBPS(990),
},
};
@@ -498,7 +498,7 @@
.src = MSM_BUS_MASTER_GRAPHICS_3D,
.dst = MSM_BUS_SLAVE_EBI_CH0,
.ab = 0,
- .ib = 1300000000U,
+ .ib = KGSL_CONVERT_TO_MBPS(1300),
},
};
@@ -507,7 +507,7 @@
.src = MSM_BUS_MASTER_GRAPHICS_3D,
.dst = MSM_BUS_SLAVE_EBI_CH0,
.ab = 0,
- .ib = 2008000000U,
+ .ib = KGSL_CONVERT_TO_MBPS(2008),
},
};
@@ -516,7 +516,7 @@
.src = MSM_BUS_MASTER_GRAPHICS_3D,
.dst = MSM_BUS_SLAVE_EBI_CH0,
.ab = 0,
- .ib = 2484000000U,
+ .ib = KGSL_CONVERT_TO_MBPS(2484),
},
};
@@ -563,7 +563,7 @@
.src = MSM_BUS_MASTER_GRAPHICS_2D_CORE0,
.dst = MSM_BUS_SLAVE_EBI_CH0,
.ab = 0,
- .ib = 990000000U,
+ .ib = KGSL_CONVERT_TO_MBPS(990),
},
};
@@ -598,7 +598,7 @@
.src = MSM_BUS_MASTER_GRAPHICS_2D_CORE1,
.dst = MSM_BUS_SLAVE_EBI_CH0,
.ab = 0,
- .ib = 990000000U,
+ .ib = KGSL_CONVERT_TO_MBPS(990),
},
};
diff --git a/arch/arm/mach-msm/include/mach/board.h b/arch/arm/mach-msm/include/mach/board.h
index 2dbbc7d..df6a64c 100644
--- a/arch/arm/mach-msm/include/mach/board.h
+++ b/arch/arm/mach-msm/include/mach/board.h
@@ -24,9 +24,7 @@
#include <linux/leds-pmic8058.h>
#include <linux/clkdev.h>
#include <linux/msm_ssbi.h>
-#ifdef CONFIG_MSM_BUS_SCALING
#include <mach/msm_bus.h>
-#endif
struct msm_camera_io_ext {
uint32_t mdcphy;
@@ -62,9 +60,7 @@
struct msm_camera_io_ext ioext;
struct msm_camera_io_clk ioclk;
uint8_t csid_core;
-#ifdef CONFIG_MSM_BUS_SCALING
struct msm_bus_scale_pdata *cam_bus_scale_table;
-#endif
};
enum msm_camera_csi_data_format {
CSI_8BIT,
diff --git a/arch/arm/mach-msm/include/mach/camera.h b/arch/arm/mach-msm/include/mach/camera.h
index 0d1da49..1b6497d 100644
--- a/arch/arm/mach-msm/include/mach/camera.h
+++ b/arch/arm/mach-msm/include/mach/camera.h
@@ -543,7 +543,10 @@
CAMIO_CSI1_SRC_CLK,
CAMIO_CSI_PIX_CLK,
+ CAMIO_CSI_PIX1_CLK,
CAMIO_CSI_RDI_CLK,
+ CAMIO_CSI_RDI1_CLK,
+ CAMIO_CSI_RDI2_CLK,
CAMIO_CSIPHY0_TIMER_CLK,
CAMIO_CSIPHY1_TIMER_CLK,
diff --git a/arch/arm/mach-msm/include/mach/rpm-8960.h b/arch/arm/mach-msm/include/mach/rpm-8960.h
index bee47a5..d5ebba0 100644
--- a/arch/arm/mach-msm/include/mach/rpm-8960.h
+++ b/arch/arm/mach-msm/include/mach/rpm-8960.h
@@ -440,8 +440,10 @@
MSM_RPM_STATUS_ID_HDMI_SWITCH = 120,
MSM_RPM_STATUS_ID_DDR_DMM_0 = 121,
MSM_RPM_STATUS_ID_DDR_DMM_1 = 122,
+ MSM_RPM_STATUS_ID_EBI1_CH0_RANGE = 123,
+ MSM_RPM_STATUS_ID_EBI1_CH1_RANGE = 124,
- MSM_RPM_STATUS_ID_LAST = MSM_RPM_STATUS_ID_DDR_DMM_1
+ MSM_RPM_STATUS_ID_LAST = MSM_RPM_STATUS_ID_EBI1_CH1_RANGE,
};
#endif /* __ARCH_ARM_MACH_MSM_RPM_8960_H */
diff --git a/arch/arm/mach-msm/include/mach/rpm-regulator-8660.h b/arch/arm/mach-msm/include/mach/rpm-regulator-8660.h
index 3bcebd4..85dcd89 100644
--- a/arch/arm/mach-msm/include/mach/rpm-regulator-8660.h
+++ b/arch/arm/mach-msm/include/mach/rpm-regulator-8660.h
@@ -11,67 +11,61 @@
* GNU General Public License for more details.
*/
-#ifndef __ARCH_ARM_MACH_MSM_RPM_REGULATOR_8660_H
-#define __ARCH_ARM_MACH_MSM_RPM_REGULATOR_8660_H
+#ifndef __ARCH_ARM_MACH_MSM_INCLUDE_MACH_RPM_REGULATOR_8660_H
+#define __ARCH_ARM_MACH_MSM_INCLUDE_MACH_RPM_REGULATOR_8660_H
-#define RPM_VREG_PIN_CTRL_NONE 0x00
-#define RPM_VREG_PIN_CTRL_A0 0x01
-#define RPM_VREG_PIN_CTRL_A1 0x02
-#define RPM_VREG_PIN_CTRL_D0 0x04
-#define RPM_VREG_PIN_CTRL_D1 0x08
+#define RPM_VREG_PIN_CTRL_PM8058_A0 0x01
+#define RPM_VREG_PIN_CTRL_PM8058_A1 0x02
+#define RPM_VREG_PIN_CTRL_PM8058_D0 0x04
+#define RPM_VREG_PIN_CTRL_PM8058_D1 0x08
-/*
- * Pin Function
- * ENABLE - pin control switches between disable and enable
- * MODE - pin control switches between LPM and HPM
- * SLEEP_B - regulator is forced into LPM by asserting sleep_b signal
- * NONE - do not use pin control
+#define RPM_VREG_PIN_CTRL_PM8901_A0 0x01
+#define RPM_VREG_PIN_CTRL_PM8901_A1 0x02
+#define RPM_VREG_PIN_CTRL_PM8901_D0 0x04
+#define RPM_VREG_PIN_CTRL_PM8901_D1 0x08
+
+
+/**
+ * enum rpm_vreg_pin_fn_8660 - RPM regulator pin function choices
+ * %RPM_VREG_PIN_FN_8660_ENABLE: pin control switches between disable and
+ * enable
+ * %RPM_VREG_PIN_FN_8660_MODE: pin control switches between LPM and HPM
+ * %RPM_VREG_PIN_FN_8660_SLEEP_B: regulator is forced into LPM when
+ * sleep_b signal is asserted
+ * %RPM_VREG_PIN_FN_8660_NONE: do not use pin control for the regulator
+ * and do not allow another master to
+ * request pin control
*
* The pin function specified in platform data corresponds to the active state
* pin function value. Pin function will be NONE until a consumer requests
- * pin control with regulator_set_mode(vreg, REGULATOR_MODE_IDLE).
+ * pin control to be enabled.
*/
-enum rpm_vreg_pin_fn {
- RPM_VREG_PIN_FN_ENABLE = 0,
- RPM_VREG_PIN_FN_MODE,
- RPM_VREG_PIN_FN_SLEEP_B,
- RPM_VREG_PIN_FN_NONE,
+enum rpm_vreg_pin_fn_8660 {
+ RPM_VREG_PIN_FN_8660_ENABLE = 0,
+ RPM_VREG_PIN_FN_8660_MODE,
+ RPM_VREG_PIN_FN_8660_SLEEP_B,
+ RPM_VREG_PIN_FN_8660_NONE,
};
-enum rpm_vreg_mode {
- RPM_VREG_MODE_PIN_CTRL = 0,
- RPM_VREG_MODE_NONE = 0,
- RPM_VREG_MODE_LPM,
- RPM_VREG_MODE_HPM,
+/**
+ * enum rpm_vreg_force_mode_8660 - RPM regulator force mode choices
+ * %RPM_VREG_FORCE_MODE_8660_PIN_CTRL: allow pin control usage
+ * %RPM_VREG_FORCE_MODE_8660_NONE: do not force any mode
+ * %RPM_VREG_FORCE_MODE_8660_LPM: force into low power mode
+ * %RPM_VREG_FORCE_MODE_8660_HPM: force into high power mode
+ *
+ * Force mode is used to override aggregation with other masters and to set
+ * special operating modes.
+ */
+enum rpm_vreg_force_mode_8660 {
+ RPM_VREG_FORCE_MODE_8660_PIN_CTRL = 0,
+ RPM_VREG_FORCE_MODE_8660_NONE = 0,
+ RPM_VREG_FORCE_MODE_8660_LPM,
+ RPM_VREG_FORCE_MODE_8660_HPM,
};
-enum rpm_vreg_state {
- RPM_VREG_STATE_OFF = 0,
- RPM_VREG_STATE_ON,
-};
-
-enum rpm_vreg_freq {
- RPM_VREG_FREQ_NONE,
- RPM_VREG_FREQ_19p20,
- RPM_VREG_FREQ_9p60,
- RPM_VREG_FREQ_6p40,
- RPM_VREG_FREQ_4p80,
- RPM_VREG_FREQ_3p84,
- RPM_VREG_FREQ_3p20,
- RPM_VREG_FREQ_2p74,
- RPM_VREG_FREQ_2p40,
- RPM_VREG_FREQ_2p13,
- RPM_VREG_FREQ_1p92,
- RPM_VREG_FREQ_1p75,
- RPM_VREG_FREQ_1p60,
- RPM_VREG_FREQ_1p48,
- RPM_VREG_FREQ_1p37,
- RPM_VREG_FREQ_1p28,
- RPM_VREG_FREQ_1p20,
-};
-
-enum rpm_vreg_id {
- RPM_VREG_ID_PM8058_L0 = 0,
+enum rpm_vreg_id_8660 {
+ RPM_VREG_ID_PM8058_L0,
RPM_VREG_ID_PM8058_L1,
RPM_VREG_ID_PM8058_L2,
RPM_VREG_ID_PM8058_L3,
@@ -122,55 +116,68 @@
RPM_VREG_ID_PM8901_LVS2,
RPM_VREG_ID_PM8901_LVS3,
RPM_VREG_ID_PM8901_MVS0,
- RPM_VREG_ID_MAX,
+ RPM_VREG_ID_8660_MAX_REAL = RPM_VREG_ID_PM8901_MVS0,
+
+ /* The following are IDs for regulator devices to enable pin control. */
+ RPM_VREG_ID_PM8058_L0_PC,
+ RPM_VREG_ID_PM8058_L1_PC,
+ RPM_VREG_ID_PM8058_L2_PC,
+ RPM_VREG_ID_PM8058_L3_PC,
+ RPM_VREG_ID_PM8058_L4_PC,
+ RPM_VREG_ID_PM8058_L5_PC,
+ RPM_VREG_ID_PM8058_L6_PC,
+ RPM_VREG_ID_PM8058_L7_PC,
+ RPM_VREG_ID_PM8058_L8_PC,
+ RPM_VREG_ID_PM8058_L9_PC,
+ RPM_VREG_ID_PM8058_L10_PC,
+ RPM_VREG_ID_PM8058_L11_PC,
+ RPM_VREG_ID_PM8058_L12_PC,
+ RPM_VREG_ID_PM8058_L13_PC,
+ RPM_VREG_ID_PM8058_L14_PC,
+ RPM_VREG_ID_PM8058_L15_PC,
+ RPM_VREG_ID_PM8058_L16_PC,
+ RPM_VREG_ID_PM8058_L17_PC,
+ RPM_VREG_ID_PM8058_L18_PC,
+ RPM_VREG_ID_PM8058_L19_PC,
+ RPM_VREG_ID_PM8058_L20_PC,
+ RPM_VREG_ID_PM8058_L21_PC,
+ RPM_VREG_ID_PM8058_L22_PC,
+ RPM_VREG_ID_PM8058_L23_PC,
+ RPM_VREG_ID_PM8058_L24_PC,
+ RPM_VREG_ID_PM8058_L25_PC,
+ RPM_VREG_ID_PM8058_S0_PC,
+ RPM_VREG_ID_PM8058_S1_PC,
+ RPM_VREG_ID_PM8058_S2_PC,
+ RPM_VREG_ID_PM8058_S3_PC,
+ RPM_VREG_ID_PM8058_S4_PC,
+ RPM_VREG_ID_PM8058_LVS0_PC,
+ RPM_VREG_ID_PM8058_LVS1_PC,
+
+ RPM_VREG_ID_PM8901_L0_PC,
+ RPM_VREG_ID_PM8901_L1_PC,
+ RPM_VREG_ID_PM8901_L2_PC,
+ RPM_VREG_ID_PM8901_L3_PC,
+ RPM_VREG_ID_PM8901_L4_PC,
+ RPM_VREG_ID_PM8901_L5_PC,
+ RPM_VREG_ID_PM8901_L6_PC,
+ RPM_VREG_ID_PM8901_S0_PC,
+ RPM_VREG_ID_PM8901_S1_PC,
+ RPM_VREG_ID_PM8901_S2_PC,
+ RPM_VREG_ID_PM8901_S3_PC,
+ RPM_VREG_ID_PM8901_S4_PC,
+ RPM_VREG_ID_PM8901_LVS0_PC,
+ RPM_VREG_ID_PM8901_LVS1_PC,
+ RPM_VREG_ID_PM8901_LVS2_PC,
+ RPM_VREG_ID_PM8901_LVS3_PC,
+ RPM_VREG_ID_PM8901_MVS0_PC,
+ RPM_VREG_ID_8660_MAX = RPM_VREG_ID_PM8901_MVS0_PC,
};
/* Minimum high power mode loads in uA. */
-#define RPM_VREG_LDO_50_HPM_MIN_LOAD 5000
-#define RPM_VREG_LDO_150_HPM_MIN_LOAD 10000
-#define RPM_VREG_LDO_300_HPM_MIN_LOAD 10000
-#define RPM_VREG_SMPS_HPM_MIN_LOAD 50000
-#define RPM_VREG_FTSMPS_HPM_MIN_LOAD 100000
-
-/*
- * default_uV = initial voltage to set the regulator to if enable is called
- * before set_voltage (e.g. when boot_on or always_on is set).
- * peak_uA = initial load requirement sent in RPM request; used to determine
- * initial mode.
- * avg_uA = initial avg load requirement sent in RPM request; overwritten
- * along with peak_uA when regulator_set_mode or
- * regulator_set_optimum_mode is called.
- * pin_fn = RPM_VREG_PIN_FN_ENABLE - pin control ON/OFF
- * = RPM_VREG_PIN_FN_MODE - pin control LPM/HPM
- * = RPM_VREG_PIN_FN_SLEEP_B - regulator is forced into LPM by
- * asserting sleep_b signal
- * = RPM_VREG_PIN_FN_NONE - do not use pin control
- * mode = used to specify a force mode which overrides the votes of other
- * RPM masters.
- * state = initial state sent in RPM request.
- * sleep_selectable = flag which indicates that regulator should be accessable
- * by external private API and that spinlocks should be used.
- */
-struct rpm_vreg_pdata {
- struct regulator_init_data init_data;
- int default_uV;
- unsigned peak_uA;
- unsigned avg_uA;
- unsigned pull_down_enable;
- unsigned pin_ctrl;
- enum rpm_vreg_freq freq;
- enum rpm_vreg_pin_fn pin_fn;
- enum rpm_vreg_mode mode;
- enum rpm_vreg_state state;
- int sleep_selectable;
-};
-
-enum rpm_vreg_voter {
- RPM_VREG_VOTER_REG_FRAMEWORK = 0, /* for internal use only */
- RPM_VREG_VOTER1, /* for use by the acpu-clock driver */
- RPM_VREG_VOTER2, /* for use by the acpu-clock driver */
- RPM_VREG_VOTER3, /* for use by other drivers */
- RPM_VREG_VOTER_COUNT,
-};
+#define RPM_VREG_8660_LDO_50_HPM_MIN_LOAD 5000
+#define RPM_VREG_8660_LDO_150_HPM_MIN_LOAD 10000
+#define RPM_VREG_8660_LDO_300_HPM_MIN_LOAD 10000
+#define RPM_VREG_8660_SMPS_HPM_MIN_LOAD 50000
+#define RPM_VREG_8660_FTSMPS_HPM_MIN_LOAD 100000
#endif
diff --git a/arch/arm/mach-msm/include/mach/rpm-regulator-8960.h b/arch/arm/mach-msm/include/mach/rpm-regulator-8960.h
index de7571b..6de47bd 100644
--- a/arch/arm/mach-msm/include/mach/rpm-regulator-8960.h
+++ b/arch/arm/mach-msm/include/mach/rpm-regulator-8960.h
@@ -11,118 +11,83 @@
* GNU General Public License for more details.
*/
-#ifndef __ARCH_ARM_MACH_MSM_RPM_REGULATOR_8960_H
-#define __ARCH_ARM_MACH_MSM_RPM_REGULATOR_8960_H
+#ifndef __ARCH_ARM_MACH_MSM_INCLUDE_MACH_RPM_REGULATOR_8960_H
+#define __ARCH_ARM_MACH_MSM_INCLUDE_MACH_RPM_REGULATOR_8960_H
/* Pin control input signals. */
-#define RPM_VREG_PIN_CTRL_NONE 0x00
-#define RPM_VREG_PIN_CTRL_EN0 0x01
-#define RPM_VREG_PIN_CTRL_EN1 0x02
-#define RPM_VREG_PIN_CTRL_EN2 0x04
-#define RPM_VREG_PIN_CTRL_EN3 0x08
-#define RPM_VREG_PIN_CTRL_ALL 0x0F
-
-#define RPM_VREG_PIN_CTRL_PM8921_D1 RPM_VREG_PIN_CTRL_EN0
-#define RPM_VREG_PIN_CTRL_PM8921_A0 RPM_VREG_PIN_CTRL_EN1
-#define RPM_VREG_PIN_CTRL_PM8921_A1 RPM_VREG_PIN_CTRL_EN2
-#define RPM_VREG_PIN_CTRL_PM8921_A2 RPM_VREG_PIN_CTRL_EN3
+#define RPM_VREG_PIN_CTRL_PM8921_D1 0x01
+#define RPM_VREG_PIN_CTRL_PM8921_A0 0x02
+#define RPM_VREG_PIN_CTRL_PM8921_A1 0x04
+#define RPM_VREG_PIN_CTRL_PM8921_A2 0x08
/**
- * enum rpm_vreg_pin_fn - RPM regulator pin function choices
- * %RPM_VREG_PIN_FN_DONT_CARE: do not care about pin control state of the
- * regulator; allow another master processor to
- * specify pin control
- * %RPM_VREG_PIN_FN_ENABLE: pin control switches between disable and enable
- * %RPM_VREG_PIN_FN_MODE: pin control switches between LPM and HPM
- * %RPM_VREG_PIN_FN_SLEEP_B: regulator is forced into LPM when sleep_b signal
- * is asserted
- * %RPM_VREG_PIN_FN_NONE: do not use pin control for the regulator and do
- * not allow another master to request pin control
+ * enum rpm_vreg_pin_fn_8960 - RPM regulator pin function choices
+ * %RPM_VREG_PIN_FN_8960_DONT_CARE: do not care about pin control state of
+ * the regulator; allow another master
+ * processor to specify pin control
+ * %RPM_VREG_PIN_FN_8960_ENABLE: pin control switches between disable and
+ * enable
+ * %RPM_VREG_PIN_FN_8960_MODE: pin control switches between LPM and HPM
+ * %RPM_VREG_PIN_FN_8960_SLEEP_B: regulator is forced into LPM when
+ * sleep_b signal is asserted
+ * %RPM_VREG_PIN_FN_8960_NONE: do not use pin control for the regulator
+ * and do not allow another master to
+ * request pin control
*
* The pin function specified in platform data corresponds to the active state
* pin function value. Pin function will be NONE until a consumer requests
* pin control to be enabled.
*/
-enum rpm_vreg_pin_fn {
- RPM_VREG_PIN_FN_DONT_CARE,
- RPM_VREG_PIN_FN_ENABLE,
- RPM_VREG_PIN_FN_MODE,
- RPM_VREG_PIN_FN_SLEEP_B,
- RPM_VREG_PIN_FN_NONE,
+enum rpm_vreg_pin_fn_8960 {
+ RPM_VREG_PIN_FN_8960_DONT_CARE,
+ RPM_VREG_PIN_FN_8960_ENABLE,
+ RPM_VREG_PIN_FN_8960_MODE,
+ RPM_VREG_PIN_FN_8960_SLEEP_B,
+ RPM_VREG_PIN_FN_8960_NONE,
};
/**
- * enum rpm_vreg_force_mode - RPM regulator force mode choices
- * %RPM_VREG_FORCE_MODE_PIN_CTRL: allow pin control usage
- * %RPM_VREG_FORCE_MODE_NONE: do not force any mode
- * %RPM_VREG_FORCE_MODE_LPM: force into low power mode
- * %RPM_VREG_FORCE_MODE_AUTO: allow regulator to automatically select its
- * own mode based on realtime current draw
- * (only available for SMPS regulators)
- * %RPM_VREG_FORCE_MODE_HPM: force into high power mode
- * %RPM_VREG_FORCE_MODE_BYPASS: set regulator to use bypass mode, i.e. to act
- * as a switch and not regulate (only available
- * for LDO regulators)
+ * enum rpm_vreg_force_mode_8960 - RPM regulator force mode choices
+ * %RPM_VREG_FORCE_MODE_8960_PIN_CTRL: allow pin control usage
+ * %RPM_VREG_FORCE_MODE_8960_NONE: do not force any mode
+ * %RPM_VREG_FORCE_MODE_8960_LPM: force into low power mode
+ * %RPM_VREG_FORCE_MODE_8960_AUTO: allow regulator to automatically select
+ * its own mode based on realtime current
+ * draw (only available for SMPS
+ * regulators)
+ * %RPM_VREG_FORCE_MODE_8960_HPM: force into high power mode
+ * %RPM_VREG_FORCE_MODE_8960_BYPASS: set regulator to use bypass mode, i.e.
+ * to act as a switch and not regulate
+ * (only available for LDO regulators)
*
* Force mode is used to override aggregation with other masters and to set
* special operating modes.
*/
-enum rpm_vreg_force_mode {
- RPM_VREG_FORCE_MODE_PIN_CTRL = 0,
- RPM_VREG_FORCE_MODE_NONE = 0,
- RPM_VREG_FORCE_MODE_LPM,
- RPM_VREG_FORCE_MODE_AUTO, /* SMPS only */
- RPM_VREG_FORCE_MODE_HPM,
- RPM_VREG_FORCE_MODE_BYPASS, /* LDO only */
+enum rpm_vreg_force_mode_8960 {
+ RPM_VREG_FORCE_MODE_8960_PIN_CTRL = 0,
+ RPM_VREG_FORCE_MODE_8960_NONE = 0,
+ RPM_VREG_FORCE_MODE_8960_LPM,
+ RPM_VREG_FORCE_MODE_8960_AUTO, /* SMPS only */
+ RPM_VREG_FORCE_MODE_8960_HPM,
+ RPM_VREG_FORCE_MODE_8960_BYPASS, /* LDO only */
};
/**
- * enum rpm_vreg_power_mode - power mode for SMPS regulators
- * %RPM_VREG_POWER_MODE_HYSTERETIC: Use hysteretic mode for HPM and when
- * usage goes high in AUTO
- * %RPM_VREG_POWER_MODE_PWM: Use PWM mode for HPM and when usage goes
- * high in AUTO
+ * enum rpm_vreg_power_mode_8960 - power mode for SMPS regulators
+ * %RPM_VREG_POWER_MODE_8960_HYSTERETIC: Use hysteretic mode for HPM and when
+ * usage goes high in AUTO
+ * %RPM_VREG_POWER_MODE_8960_PWM: Use PWM mode for HPM and when usage
+ * goes high in AUTO
*/
-enum rpm_vreg_power_mode {
- RPM_VREG_POWER_MODE_HYSTERETIC,
- RPM_VREG_POWER_MODE_PWM,
-};
-
-/**
- * enum rpm_vreg_state - enable state for switch or NCP
- */
-enum rpm_vreg_state {
- RPM_VREG_STATE_OFF,
- RPM_VREG_STATE_ON,
-};
-
-/**
- * enum rpm_vreg_freq - switching frequency for SMPS or NCP
- */
-enum rpm_vreg_freq {
- RPM_VREG_FREQ_NONE,
- RPM_VREG_FREQ_19p20,
- RPM_VREG_FREQ_9p60,
- RPM_VREG_FREQ_6p40,
- RPM_VREG_FREQ_4p80,
- RPM_VREG_FREQ_3p84,
- RPM_VREG_FREQ_3p20,
- RPM_VREG_FREQ_2p74,
- RPM_VREG_FREQ_2p40,
- RPM_VREG_FREQ_2p13,
- RPM_VREG_FREQ_1p92,
- RPM_VREG_FREQ_1p75,
- RPM_VREG_FREQ_1p60,
- RPM_VREG_FREQ_1p48,
- RPM_VREG_FREQ_1p37,
- RPM_VREG_FREQ_1p28,
- RPM_VREG_FREQ_1p20,
+enum rpm_vreg_power_mode_8960 {
+ RPM_VREG_POWER_MODE_8960_HYSTERETIC,
+ RPM_VREG_POWER_MODE_8960_PWM,
};
/**
* enum rpm_vreg_id - RPM regulator ID numbers (both real and pin control)
*/
-enum rpm_vreg_id {
+enum rpm_vreg_id_8960 {
RPM_VREG_ID_PM8921_L1,
RPM_VREG_ID_PM8921_L2,
RPM_VREG_ID_PM8921_L3,
@@ -211,76 +176,12 @@
};
/* Minimum high power mode loads in uA. */
-#define RPM_VREG_LDO_50_HPM_MIN_LOAD 5000
-#define RPM_VREG_LDO_150_HPM_MIN_LOAD 10000
-#define RPM_VREG_LDO_300_HPM_MIN_LOAD 10000
-#define RPM_VREG_LDO_600_HPM_MIN_LOAD 10000
-#define RPM_VREG_LDO_1200_HPM_MIN_LOAD 10000
-#define RPM_VREG_SMPS_1500_HPM_MIN_LOAD 100000
-#define RPM_VREG_SMPS_2000_HPM_MIN_LOAD 100000
-
-/**
- * struct rpm_regulator_init_data - RPM regulator initialization data
- * @init_data: regulator constraints
- * @id: regulator id; from enum rpm_vreg_id
- * @sleep_selectable: flag which indicates that regulator should be accessable
- * by external private API and that spinlocks should be
- * used instead of mutex locks
- * @system_uA: current drawn from regulator not accounted for by any
- * regulator framework consumer
- * @pull_down_enable: 0 = no pulldown, 1 = pulldown when regulator disabled
- * @freq: enum value representing the switching frequency of an
- * SMPS or NCP
- * @pin_ctrl: pin control inputs to use for the regulator; should be
- * a combination of RPM_VREG_PIN_CTRL_* values
- * @pin_fn: action to perform when pin control pin(s) is/are active
- * @force_mode: used to specify a force mode which overrides the votes
- * of other RPM masters.
- * @default_uV: initial voltage to set the regulator to if enable is
- * called before set_voltage (e.g. when boot_on or
- * always_on is set).
- * @peak_uA: initial peak load requirement sent in RPM request; used
- * to determine initial mode.
- * @avg_uA: average load requirement sent in RPM request
- * @state: initial enable state sent in RPM request for switch or
- * NCP
- */
-struct rpm_regulator_init_data {
- struct regulator_init_data init_data;
- enum rpm_vreg_id id;
- int sleep_selectable;
- int system_uA;
- unsigned pull_down_enable;
- enum rpm_vreg_freq freq;
- unsigned pin_ctrl;
- enum rpm_vreg_pin_fn pin_fn;
- enum rpm_vreg_force_mode force_mode;
- enum rpm_vreg_power_mode power_mode;
- int default_uV;
- unsigned peak_uA;
- unsigned avg_uA;
- enum rpm_vreg_state state;
-};
-
-/**
- * struct rpm_regulator_platform_data - RPM regulator platform data
- */
-struct rpm_regulator_platform_data {
- struct rpm_regulator_init_data *init_data;
- int num_regulators;
-};
-
-/**
- * enum rpm_vreg_voter - RPM regulator voter IDs for private APIs
- */
-enum rpm_vreg_voter {
- RPM_VREG_VOTER_REG_FRAMEWORK, /* for internal use only */
- RPM_VREG_VOTER1, /* for use by the acpu-clock driver */
- RPM_VREG_VOTER2, /* for use by the acpu-clock driver */
- RPM_VREG_VOTER3, /* for use by other drivers */
- RPM_VREG_VOTER4, /* for use by the acpu-clock driver */
- RPM_VREG_VOTER5, /* for use by the acpu-clock driver */
- RPM_VREG_VOTER_COUNT,
-};
+#define RPM_VREG_8960_LDO_50_HPM_MIN_LOAD 5000
+#define RPM_VREG_8960_LDO_150_HPM_MIN_LOAD 10000
+#define RPM_VREG_8960_LDO_300_HPM_MIN_LOAD 10000
+#define RPM_VREG_8960_LDO_600_HPM_MIN_LOAD 10000
+#define RPM_VREG_8960_LDO_1200_HPM_MIN_LOAD 10000
+#define RPM_VREG_8960_SMPS_1500_HPM_MIN_LOAD 100000
+#define RPM_VREG_8960_SMPS_2000_HPM_MIN_LOAD 100000
#endif
diff --git a/arch/arm/mach-msm/include/mach/rpm-regulator-9615.h b/arch/arm/mach-msm/include/mach/rpm-regulator-9615.h
new file mode 100644
index 0000000..f5fa8ca
--- /dev/null
+++ b/arch/arm/mach-msm/include/mach/rpm-regulator-9615.h
@@ -0,0 +1,138 @@
+/*
+ * Copyright (c) 2011, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#ifndef __ARCH_ARM_MACH_MSM_INCLUDE_MACH_RPM_REGULATOR_9615_H
+#define __ARCH_ARM_MACH_MSM_INCLUDE_MACH_RPM_REGULATOR_9615_H
+
+/* Pin control input signals. */
+#define RPM_VREG_PIN_CTRL_PM8018_D1 0x01
+#define RPM_VREG_PIN_CTRL_PM8018_A0 0x02
+#define RPM_VREG_PIN_CTRL_PM8018_A1 0x04
+#define RPM_VREG_PIN_CTRL_PM8018_A2 0x08
+
+/**
+ * enum rpm_vreg_pin_fn_9615 - RPM regulator pin function choices
+ * %RPM_VREG_PIN_FN_9615_DONT_CARE: do not care about pin control state of
+ * the regulator; allow another master
+ * processor to specify pin control
+ * %RPM_VREG_PIN_FN_9615_ENABLE: pin control switches between disable and
+ * enable
+ * %RPM_VREG_PIN_FN_9615_MODE: pin control switches between LPM and HPM
+ * %RPM_VREG_PIN_FN_9615_SLEEP_B: regulator is forced into LPM when
+ * sleep_b signal is asserted
+ * %RPM_VREG_PIN_FN_9615_NONE: do not use pin control for the regulator
+ * and do not allow another master to
+ * request pin control
+ *
+ * The pin function specified in platform data corresponds to the active state
+ * pin function value. Pin function will be NONE until a consumer requests
+ * pin control to be enabled.
+ */
+enum rpm_vreg_pin_fn_9615 {
+ RPM_VREG_PIN_FN_9615_DONT_CARE,
+ RPM_VREG_PIN_FN_9615_ENABLE,
+ RPM_VREG_PIN_FN_9615_MODE,
+ RPM_VREG_PIN_FN_9615_SLEEP_B,
+ RPM_VREG_PIN_FN_9615_NONE,
+};
+
+/**
+ * enum rpm_vreg_force_mode_9615 - RPM regulator force mode choices
+ * %RPM_VREG_FORCE_MODE_9615_PIN_CTRL: allow pin control usage
+ * %RPM_VREG_FORCE_MODE_9615_NONE: do not force any mode
+ * %RPM_VREG_FORCE_MODE_9615_LPM: force into low power mode
+ * %RPM_VREG_FORCE_MODE_9615_AUTO: allow regulator to automatically select
+ * its own mode based on realtime current
+ * draw (only available for SMPS
+ * regulators)
+ * %RPM_VREG_FORCE_MODE_9615_HPM: force into high power mode
+ * %RPM_VREG_FORCE_MODE_9615_BYPASS: set regulator to use bypass mode, i.e.
+ * to act as a switch and not regulate
+ * (only available for LDO regulators)
+ *
+ * Force mode is used to override aggregation with other masters and to set
+ * special operating modes.
+ */
+enum rpm_vreg_force_mode_9615 {
+ RPM_VREG_FORCE_MODE_9615_PIN_CTRL = 0,
+ RPM_VREG_FORCE_MODE_9615_NONE = 0,
+ RPM_VREG_FORCE_MODE_9615_LPM,
+ RPM_VREG_FORCE_MODE_9615_AUTO, /* SMPS only */
+ RPM_VREG_FORCE_MODE_9615_HPM,
+ RPM_VREG_FORCE_MODE_9615_BYPASS, /* LDO only */
+};
+
+/**
+ * enum rpm_vreg_power_mode_9615 - power mode for SMPS regulators
+ * %RPM_VREG_POWER_MODE_9615_HYSTERETIC: Use hysteretic mode for HPM and when
+ * usage goes high in AUTO
+ * %RPM_VREG_POWER_MODE_9615_PWM: Use PWM mode for HPM and when usage
+ * goes high in AUTO
+ */
+enum rpm_vreg_power_mode_9615 {
+ RPM_VREG_POWER_MODE_9615_HYSTERETIC,
+ RPM_VREG_POWER_MODE_9615_PWM,
+};
+
+/**
+ * enum rpm_vreg_id - RPM regulator ID numbers (both real and pin control)
+ */
+enum rpm_vreg_id_9615 {
+ RPM_VREG_ID_PM8018_L2,
+ RPM_VREG_ID_PM8018_L3,
+ RPM_VREG_ID_PM8018_L4,
+ RPM_VREG_ID_PM8018_L5,
+ RPM_VREG_ID_PM8018_L6,
+ RPM_VREG_ID_PM8018_L7,
+ RPM_VREG_ID_PM8018_L8,
+ RPM_VREG_ID_PM8018_L9,
+ RPM_VREG_ID_PM8018_L10,
+ RPM_VREG_ID_PM8018_L11,
+ RPM_VREG_ID_PM8018_L12,
+ RPM_VREG_ID_PM8018_L13,
+ RPM_VREG_ID_PM8018_L14,
+ RPM_VREG_ID_PM8018_S1,
+ RPM_VREG_ID_PM8018_S2,
+ RPM_VREG_ID_PM8018_S3,
+ RPM_VREG_ID_PM8018_S4,
+ RPM_VREG_ID_PM8018_S5,
+ RPM_VREG_ID_PM8018_LVS1,
+ RPM_VREG_ID_PM8018_MAX_REAL = RPM_VREG_ID_PM8018_LVS1,
+
+ /* The following are IDs for regulator devices to enable pin control. */
+ RPM_VREG_ID_PM8018_L2_PC,
+ RPM_VREG_ID_PM8018_L3_PC,
+ RPM_VREG_ID_PM8018_L4_PC,
+ RPM_VREG_ID_PM8018_L5_PC,
+ RPM_VREG_ID_PM8018_L6_PC,
+ RPM_VREG_ID_PM8018_L7_PC,
+ RPM_VREG_ID_PM8018_L8_PC,
+ RPM_VREG_ID_PM8018_L13_PC,
+ RPM_VREG_ID_PM8018_L14_PC,
+ RPM_VREG_ID_PM8018_S1_PC,
+ RPM_VREG_ID_PM8018_S2_PC,
+ RPM_VREG_ID_PM8018_S3_PC,
+ RPM_VREG_ID_PM8018_S4_PC,
+ RPM_VREG_ID_PM8018_S5_PC,
+ RPM_VREG_ID_PM8018_LVS1_PC,
+ RPM_VREG_ID_PM8018_MAX = RPM_VREG_ID_PM8018_LVS1_PC,
+};
+
+/* Minimum high power mode loads in uA. */
+#define RPM_VREG_9615_LDO_50_HPM_MIN_LOAD 5000
+#define RPM_VREG_9615_LDO_150_HPM_MIN_LOAD 10000
+#define RPM_VREG_9615_LDO_300_HPM_MIN_LOAD 10000
+#define RPM_VREG_9615_LDO_1200_HPM_MIN_LOAD 10000
+#define RPM_VREG_9615_SMPS_1500_HPM_MIN_LOAD 100000
+
+#endif
diff --git a/arch/arm/mach-msm/include/mach/rpm-regulator.h b/arch/arm/mach-msm/include/mach/rpm-regulator.h
index 1187efc..8b5a1e7 100644
--- a/arch/arm/mach-msm/include/mach/rpm-regulator.h
+++ b/arch/arm/mach-msm/include/mach/rpm-regulator.h
@@ -10,18 +10,130 @@
* GNU General Public License for more details.
*/
-#ifndef __ARCH_ARM_MACH_MSM_RPM_REGULATOR_H
-#define __ARCH_ARM_MACH_MSM_RPM_REGULATOR_H
+#ifndef __ARCH_ARM_MACH_MSM_INCLUDE_MACH_RPM_REGULATOR_H
+#define __ARCH_ARM_MACH_MSM_INCLUDE_MACH_RPM_REGULATOR_H
#include <linux/regulator/machine.h>
#define RPM_REGULATOR_DEV_NAME "rpm-regulator"
-#if defined(CONFIG_ARCH_MSM8X60)
#include <mach/rpm-regulator-8660.h>
-#elif defined(CONFIG_ARCH_MSM8960)
#include <mach/rpm-regulator-8960.h>
-#endif
+#include <mach/rpm-regulator-9615.h>
+
+/**
+ * enum rpm_vreg_version - supported RPM regulator versions
+ */
+enum rpm_vreg_version {
+ RPM_VREG_VERSION_8660,
+ RPM_VREG_VERSION_8960,
+ RPM_VREG_VERSION_9615,
+ RPM_VREG_VERSION_MAX = RPM_VREG_VERSION_9615,
+};
+
+#define RPM_VREG_PIN_CTRL_NONE 0x00
+
+/**
+ * enum rpm_vreg_state - enable state for switch or NCP
+ */
+enum rpm_vreg_state {
+ RPM_VREG_STATE_OFF,
+ RPM_VREG_STATE_ON,
+};
+
+/**
+ * enum rpm_vreg_freq - switching frequency for SMPS or NCP
+ */
+enum rpm_vreg_freq {
+ RPM_VREG_FREQ_NONE,
+ RPM_VREG_FREQ_19p20,
+ RPM_VREG_FREQ_9p60,
+ RPM_VREG_FREQ_6p40,
+ RPM_VREG_FREQ_4p80,
+ RPM_VREG_FREQ_3p84,
+ RPM_VREG_FREQ_3p20,
+ RPM_VREG_FREQ_2p74,
+ RPM_VREG_FREQ_2p40,
+ RPM_VREG_FREQ_2p13,
+ RPM_VREG_FREQ_1p92,
+ RPM_VREG_FREQ_1p75,
+ RPM_VREG_FREQ_1p60,
+ RPM_VREG_FREQ_1p48,
+ RPM_VREG_FREQ_1p37,
+ RPM_VREG_FREQ_1p28,
+ RPM_VREG_FREQ_1p20,
+};
+
+/**
+ * struct rpm_regulator_init_data - RPM regulator initialization data
+ * @init_data: regulator constraints
+ * @id: regulator id; from enum rpm_vreg_id
+ * @sleep_selectable: flag which indicates that regulator should be accessable
+ * by external private API and that spinlocks should be
+ * used instead of mutex locks
+ * @system_uA: current drawn from regulator not accounted for by any
+ * regulator framework consumer
+ * @enable_time: time in us taken to enable a regulator to the maximum
+ * allowed voltage for the system. This is dependent upon
+ * the load and capacitance for a regulator on the board.
+ * @pull_down_enable: 0 = no pulldown, 1 = pulldown when regulator disabled
+ * @freq: enum value representing the switching frequency of an
+ * SMPS or NCP
+ * @pin_ctrl: pin control inputs to use for the regulator; should be
+ * a combination of RPM_VREG_PIN_CTRL_* values
+ * @pin_fn: action to perform when pin control pin(s) is/are active
+ * @force_mode: used to specify a force mode which overrides the votes
+ * of other RPM masters.
+ * @default_uV: initial voltage to set the regulator to if enable is
+ * called before set_voltage (e.g. when boot_on or
+ * always_on is set).
+ * @peak_uA: initial peak load requirement sent in RPM request; used
+ * to determine initial mode.
+ * @avg_uA: average load requirement sent in RPM request
+ * @state: initial enable state sent in RPM request for switch or
+ * NCP
+ */
+struct rpm_regulator_init_data {
+ struct regulator_init_data init_data;
+ int id;
+ int sleep_selectable;
+ int system_uA;
+ int enable_time;
+ unsigned pull_down_enable;
+ enum rpm_vreg_freq freq;
+ unsigned pin_ctrl;
+ int pin_fn;
+ int force_mode;
+ int power_mode;
+ int default_uV;
+ unsigned peak_uA;
+ unsigned avg_uA;
+ enum rpm_vreg_state state;
+};
+
+/**
+ * struct rpm_regulator_platform_data - RPM regulator platform data
+ */
+struct rpm_regulator_platform_data {
+ struct rpm_regulator_init_data *init_data;
+ int num_regulators;
+ enum rpm_vreg_version version;
+ int vreg_id_vdd_mem;
+ int vreg_id_vdd_dig;
+};
+
+/**
+ * enum rpm_vreg_voter - RPM regulator voter IDs for private APIs
+ */
+enum rpm_vreg_voter {
+ RPM_VREG_VOTER_REG_FRAMEWORK, /* for internal use only */
+ RPM_VREG_VOTER1, /* for use by the acpu-clock driver */
+ RPM_VREG_VOTER2, /* for use by the acpu-clock driver */
+ RPM_VREG_VOTER3, /* for use by other drivers */
+ RPM_VREG_VOTER4, /* for use by the acpu-clock driver */
+ RPM_VREG_VOTER5, /* for use by the acpu-clock driver */
+ RPM_VREG_VOTER_COUNT,
+};
/**
* rpm_vreg_set_voltage - vote for a min_uV value of specified regualtor
@@ -44,8 +156,8 @@
* This function may only be called for regulators which have the sleep flag
* specified in their private data.
*/
-int rpm_vreg_set_voltage(enum rpm_vreg_id vreg_id, enum rpm_vreg_voter voter,
- int min_uV, int max_uV, int sleep_also);
+int rpm_vreg_set_voltage(int vreg_id, enum rpm_vreg_voter voter, int min_uV,
+ int max_uV, int sleep_also);
/**
* rpm_vreg_set_frequency - sets the frequency of a switching regulator
@@ -54,6 +166,6 @@
*
* Returns 0 on success or errno.
*/
-int rpm_vreg_set_frequency(enum rpm_vreg_id vreg_id, enum rpm_vreg_freq freq);
+int rpm_vreg_set_frequency(int vreg_id, enum rpm_vreg_freq freq);
#endif
diff --git a/arch/arm/mach-msm/ipc_router.c b/arch/arm/mach-msm/ipc_router.c
index ea9d246..3d34a30 100644
--- a/arch/arm/mach-msm/ipc_router.c
+++ b/arch/arm/mach-msm/ipc_router.c
@@ -176,6 +176,8 @@
static DEFINE_MUTEX(xprt_info_list_lock);
DECLARE_COMPLETION(msm_ipc_remote_router_up);
+static DECLARE_COMPLETION(msm_ipc_local_router_up);
+#define IPC_ROUTER_INIT_TIMEOUT (10 * HZ)
static uint32_t next_port_id;
static DEFINE_MUTEX(next_port_id_lock);
@@ -2399,8 +2401,16 @@
struct msm_ipc_router_xprt_info *xprt_info = xprt->priv;
struct msm_ipc_router_xprt_work *xprt_work;
struct rr_packet *pkt;
+ unsigned long ret;
- BUG_ON(!msm_ipc_router_workqueue);
+ if (!msm_ipc_router_workqueue) {
+ ret = wait_for_completion_timeout(&msm_ipc_local_router_up,
+ IPC_ROUTER_INIT_TIMEOUT);
+ if (!ret || !msm_ipc_router_workqueue) {
+ pr_err("%s: IPC Router not initialized\n", __func__);
+ return;
+ }
+ }
switch (event) {
case IPC_ROUTER_XPRT_EVENT_OPEN:
@@ -2515,6 +2525,7 @@
if (ret < 0)
pr_err("%s: Init sockets failed\n", __func__);
+ complete_all(&msm_ipc_local_router_up);
return ret;
}
diff --git a/arch/arm/mach-msm/ipc_router_smd_xprt.c b/arch/arm/mach-msm/ipc_router_smd_xprt.c
index 5987752..997d4b5 100644
--- a/arch/arm/mach-msm/ipc_router_smd_xprt.c
+++ b/arch/arm/mach-msm/ipc_router_smd_xprt.c
@@ -46,7 +46,14 @@
static struct msm_ipc_router_smd_xprt smd_remote_xprt;
+struct msm_ipc_router_smd_xprt_work {
+ struct msm_ipc_router_xprt *xprt;
+ struct work_struct work;
+};
+
static void smd_xprt_read_data(struct work_struct *work);
+static void smd_xprt_open_event(struct work_struct *work);
+static void smd_xprt_close_event(struct work_struct *work);
static DECLARE_DELAYED_WORK(work_read_data, smd_xprt_read_data);
static struct workqueue_struct *smd_xprt_workqueue;
@@ -201,8 +208,10 @@
D("%s: Allocated rr_packet\n", __func__);
}
- if ((pkt_size >= MIN_FRAG_SZ) &&
- (smd_read_avail(smd_remote_xprt.channel) < MIN_FRAG_SZ))
+ if (((pkt_size >= MIN_FRAG_SZ) &&
+ (smd_read_avail(smd_remote_xprt.channel) < MIN_FRAG_SZ)) ||
+ ((pkt_size < MIN_FRAG_SZ) &&
+ (smd_read_avail(smd_remote_xprt.channel) < pkt_size)))
return;
sz = smd_read_avail(smd_remote_xprt.channel);
@@ -249,9 +258,32 @@
}
}
+static void smd_xprt_open_event(struct work_struct *work)
+{
+ struct msm_ipc_router_smd_xprt_work *xprt_work =
+ container_of(work, struct msm_ipc_router_smd_xprt_work, work);
+
+ msm_ipc_router_xprt_notify(xprt_work->xprt,
+ IPC_ROUTER_XPRT_EVENT_OPEN, NULL);
+ D("%s: Notified IPC Router of OPEN Event\n", __func__);
+ kfree(xprt_work);
+}
+
+static void smd_xprt_close_event(struct work_struct *work)
+{
+ struct msm_ipc_router_smd_xprt_work *xprt_work =
+ container_of(work, struct msm_ipc_router_smd_xprt_work, work);
+
+ msm_ipc_router_xprt_notify(xprt_work->xprt,
+ IPC_ROUTER_XPRT_EVENT_CLOSE, NULL);
+ D("%s: Notified IPC Router of CLOSE Event\n", __func__);
+ kfree(xprt_work);
+}
+
static void msm_ipc_router_smd_remote_notify(void *_dev, unsigned event)
{
unsigned long flags;
+ struct msm_ipc_router_smd_xprt_work *xprt_work;
switch (event) {
case SMD_EVENT_DATA:
@@ -266,9 +298,16 @@
spin_lock_irqsave(&modem_reset_lock, flags);
modem_reset = 0;
spin_unlock_irqrestore(&modem_reset_lock, flags);
- msm_ipc_router_xprt_notify(&smd_remote_xprt.xprt,
- IPC_ROUTER_XPRT_EVENT_OPEN, NULL);
- D("%s: Notified IPC Router of OPEN Event\n", __func__);
+ xprt_work = kmalloc(sizeof(struct msm_ipc_router_smd_xprt_work),
+ GFP_ATOMIC);
+ if (!xprt_work) {
+ pr_err("%s: Couldn't notify %d event to IPC Router\n",
+ __func__, event);
+ return;
+ }
+ xprt_work->xprt = &smd_remote_xprt.xprt;
+ INIT_WORK(&xprt_work->work, smd_xprt_open_event);
+ queue_work(smd_xprt_workqueue, &xprt_work->work);
break;
case SMD_EVENT_CLOSE:
@@ -276,9 +315,16 @@
modem_reset = 1;
spin_unlock_irqrestore(&modem_reset_lock, flags);
wake_up(&write_avail_wait_q);
- msm_ipc_router_xprt_notify(&smd_remote_xprt.xprt,
- IPC_ROUTER_XPRT_EVENT_CLOSE, NULL);
- D("%s: Notified IPC Router of CLOSE Event\n", __func__);
+ xprt_work = kmalloc(sizeof(struct msm_ipc_router_smd_xprt_work),
+ GFP_ATOMIC);
+ if (!xprt_work) {
+ pr_err("%s: Couldn't notify %d event to IPC Router\n",
+ __func__, event);
+ return;
+ }
+ xprt_work->xprt = &smd_remote_xprt.xprt;
+ INIT_WORK(&xprt_work->work, smd_xprt_close_event);
+ queue_work(smd_xprt_workqueue, &xprt_work->work);
break;
}
}
diff --git a/arch/arm/mach-msm/msm_watchdog.c b/arch/arm/mach-msm/msm_watchdog.c
index c517178..8a9ac36 100644
--- a/arch/arm/mach-msm/msm_watchdog.c
+++ b/arch/arm/mach-msm/msm_watchdog.c
@@ -39,7 +39,7 @@
static void __iomem *msm_tmr0_base;
/* Watchdog pet interval in ms */
-#define PET_DELAY 3000
+#define PET_DELAY 10000
static unsigned long delay_time;
static unsigned long long last_pet;
@@ -317,11 +317,11 @@
/* 32768 ticks = 1 second */
if (machine_is_msm8960_sim()) {
- __raw_writel(32768*8, msm_tmr0_base + WDT0_BARK_TIME);
- __raw_writel(32768*10, msm_tmr0_base + WDT0_BITE_TIME);
+ __raw_writel(32768*15, msm_tmr0_base + WDT0_BARK_TIME);
+ __raw_writel(32768*17, msm_tmr0_base + WDT0_BITE_TIME);
} else {
- __raw_writel(32768*4, msm_tmr0_base + WDT0_BARK_TIME);
- __raw_writel(32768*5, msm_tmr0_base + WDT0_BITE_TIME);
+ __raw_writel(32768*11, msm_tmr0_base + WDT0_BARK_TIME);
+ __raw_writel(32768*12, msm_tmr0_base + WDT0_BITE_TIME);
}
ret = register_pm_notifier(&msm_watchdog_power_notifier);
diff --git a/arch/arm/mach-msm/peripheral-loader.h b/arch/arm/mach-msm/peripheral-loader.h
index 7357432..097d9d7 100644
--- a/arch/arm/mach-msm/peripheral-loader.h
+++ b/arch/arm/mach-msm/peripheral-loader.h
@@ -9,8 +9,8 @@
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*/
-#ifndef __MACH_PERIPHERAL_LOADER_H
-#define __MACH_PERIPHERAL_LOADER_H
+#ifndef __MSM_PERIPHERAL_LOADER_H
+#define __MSM_PERIPHERAL_LOADER_H
#include <linux/list.h>
#include <linux/mutex.h>
diff --git a/arch/arm/mach-msm/qdsp6v2/pcm_out.c b/arch/arm/mach-msm/qdsp6v2/pcm_out.c
index b8521f6..75975cc 100644
--- a/arch/arm/mach-msm/qdsp6v2/pcm_out.c
+++ b/arch/arm/mach-msm/qdsp6v2/pcm_out.c
@@ -52,7 +52,6 @@
atomic_t out_stopped;
atomic_t out_prefill;
struct wake_lock wakelock;
- struct wake_lock idlelock;
};
void pcm_out_cb(uint32_t opcode, uint32_t token,
@@ -77,14 +76,12 @@
{
pr_debug("%s:\n", __func__);
wake_lock(&audio->wakelock);
- wake_lock(&audio->idlelock);
}
static void audio_allow_sleep(struct pcm *audio)
{
pr_debug("%s:\n", __func__);
wake_unlock(&audio->wakelock);
- wake_unlock(&audio->idlelock);
}
static int pcm_out_enable(struct pcm *pcm)
@@ -336,8 +333,6 @@
atomic_set(&pcm->out_opened, 1);
snprintf(name, sizeof name, "audio_pcm_%x", pcm->ac->session);
wake_lock_init(&pcm->wakelock, WAKE_LOCK_SUSPEND, name);
- snprintf(name, sizeof name, "audio_pcm_idle_%x", pcm->ac->session);
- wake_lock_init(&pcm->idlelock, WAKE_LOCK_IDLE, name);
rc = auddev_register_evt_listner(pcm->stream_event,
AUDDEV_CLNT_DEC,
@@ -441,7 +436,6 @@
q6asm_audio_client_free(pcm->ac);
audio_allow_sleep(pcm);
wake_lock_destroy(&pcm->wakelock);
- wake_lock_destroy(&pcm->idlelock);
mutex_destroy(&pcm->lock);
mutex_destroy(&pcm->write_lock);
kfree(pcm);
diff --git a/arch/arm/mach-msm/qdss-etb.c b/arch/arm/mach-msm/qdss-etb.c
index 726084d..16f8a5b 100644
--- a/arch/arm/mach-msm/qdss-etb.c
+++ b/arch/arm/mach-msm/qdss-etb.c
@@ -51,6 +51,7 @@
#define BYTES_PER_WORD 4
#define ETB_SIZE_WORDS 4096
+#define FRAME_SIZE_WORDS 4
#define ETB_LOCK() \
do { \
@@ -136,12 +137,24 @@
uint32_t read_data;
uint32_t read_ptr;
uint32_t write_ptr;
+ uint32_t frame_off;
+ uint32_t frame_endoff;
ETB_UNLOCK();
read_ptr = etb_readl(etb, ETB_RAM_READ_POINTER);
write_ptr = etb_readl(etb, ETB_RAM_WRITE_POINTER);
+ frame_off = write_ptr % FRAME_SIZE_WORDS;
+ frame_endoff = FRAME_SIZE_WORDS - frame_off;
+ if (frame_off) {
+ dev_err(etb.dev, "write_ptr: %lu not aligned to formatter "
+ "frame size\n", (unsigned long)write_ptr);
+ dev_err(etb.dev, "frameoff: %lu, frame_endoff: %lu\n",
+ (unsigned long)frame_off, (unsigned long)frame_endoff);
+ write_ptr += frame_endoff;
+ }
+
if ((etb_readl(etb, ETB_STATUS_REG) & BIT(0)) == 0)
etb_writel(etb, 0x0, ETB_RAM_READ_POINTER);
else
@@ -150,14 +163,20 @@
buf_ptr = etb.buf;
for (i = 0; i < ETB_SIZE_WORDS; i++) {
read_data = etb_readl(etb, ETB_RAM_READ_DATA_REG);
- *buf_ptr = read_data >> 0;
- buf_ptr++;
- *buf_ptr = read_data >> 8;
- buf_ptr++;
- *buf_ptr = read_data >> 16;
- buf_ptr++;
- *buf_ptr = read_data >> 24;
- buf_ptr++;
+ *buf_ptr++ = read_data >> 0;
+ *buf_ptr++ = read_data >> 8;
+ *buf_ptr++ = read_data >> 16;
+ *buf_ptr++ = read_data >> 24;
+ }
+
+ if (frame_off) {
+ buf_ptr -= (frame_endoff * BYTES_PER_WORD);
+ for (i = 0; i < frame_endoff; i++) {
+ *buf_ptr++ = 0x0;
+ *buf_ptr++ = 0x0;
+ *buf_ptr++ = 0x0;
+ *buf_ptr++ = 0x0;
+ }
}
etb_writel(etb, read_ptr, ETB_RAM_READ_POINTER);
diff --git a/arch/arm/mach-msm/rpm-regulator-8660.c b/arch/arm/mach-msm/rpm-regulator-8660.c
new file mode 100644
index 0000000..6c4a9ad
--- /dev/null
+++ b/arch/arm/mach-msm/rpm-regulator-8660.c
@@ -0,0 +1,292 @@
+/*
+ * Copyright (c) 2011, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#define pr_fmt(fmt) "%s: " fmt, __func__
+
+#include "rpm-regulator-private.h"
+
+/* RPM regulator request formats */
+static struct rpm_vreg_parts ldo_parts = {
+ .request_len = 2,
+ .mV = REQUEST_MEMBER(0, 0x00000FFF, 0),
+ .ip = REQUEST_MEMBER(0, 0x00FFF000, 12),
+ .fm = REQUEST_MEMBER(0, 0x03000000, 24),
+ .pc = REQUEST_MEMBER(0, 0x3C000000, 26),
+ .pf = REQUEST_MEMBER(0, 0xC0000000, 30),
+ .pd = REQUEST_MEMBER(1, 0x00000001, 0),
+ .ia = REQUEST_MEMBER(1, 0x00001FFE, 1),
+};
+
+static struct rpm_vreg_parts smps_parts = {
+ .request_len = 2,
+ .mV = REQUEST_MEMBER(0, 0x00000FFF, 0),
+ .ip = REQUEST_MEMBER(0, 0x00FFF000, 12),
+ .fm = REQUEST_MEMBER(0, 0x03000000, 24),
+ .pc = REQUEST_MEMBER(0, 0x3C000000, 26),
+ .pf = REQUEST_MEMBER(0, 0xC0000000, 30),
+ .pd = REQUEST_MEMBER(1, 0x00000001, 0),
+ .ia = REQUEST_MEMBER(1, 0x00001FFE, 1),
+ .freq = REQUEST_MEMBER(1, 0x001FE000, 13),
+ .freq_clk_src = REQUEST_MEMBER(1, 0x00600000, 21),
+};
+
+static struct rpm_vreg_parts switch_parts = {
+ .request_len = 1,
+ .enable_state = REQUEST_MEMBER(0, 0x00000001, 0),
+ .pd = REQUEST_MEMBER(0, 0x00000002, 1),
+ .pc = REQUEST_MEMBER(0, 0x0000003C, 2),
+ .pf = REQUEST_MEMBER(0, 0x000000C0, 6),
+ .hpm = REQUEST_MEMBER(0, 0x00000300, 8),
+};
+
+static struct rpm_vreg_parts ncp_parts = {
+ .request_len = 1,
+ .mV = REQUEST_MEMBER(0, 0x00000FFF, 0),
+ .enable_state = REQUEST_MEMBER(0, 0x00001000, 12),
+ .comp_mode = REQUEST_MEMBER(0, 0x00002000, 13),
+ .freq = REQUEST_MEMBER(0, 0x003FC000, 14),
+};
+
+/* Physically available PMIC regulator voltage setpoint ranges */
+static struct vreg_range pldo_ranges[] = {
+ VOLTAGE_RANGE( 750000, 1487500, 12500),
+ VOLTAGE_RANGE(1500000, 3075000, 25000),
+ VOLTAGE_RANGE(3100000, 4900000, 50000),
+};
+
+static struct vreg_range nldo_ranges[] = {
+ VOLTAGE_RANGE( 750000, 1537500, 12500),
+};
+
+static struct vreg_range smps_ranges[] = {
+ VOLTAGE_RANGE( 375000, 737500, 12500),
+ VOLTAGE_RANGE( 750000, 1487500, 12500),
+ VOLTAGE_RANGE(1500000, 3075000, 25000),
+};
+
+static struct vreg_range ftsmps_ranges[] = {
+ VOLTAGE_RANGE( 350000, 650000, 50000),
+ VOLTAGE_RANGE( 700000, 1400000, 12500),
+ VOLTAGE_RANGE(1500000, 3300000, 50000),
+};
+
+static struct vreg_range ncp_ranges[] = {
+ VOLTAGE_RANGE(1500000, 3050000, 50000),
+};
+
+static struct vreg_set_points pldo_set_points = SET_POINTS(pldo_ranges);
+static struct vreg_set_points nldo_set_points = SET_POINTS(nldo_ranges);
+static struct vreg_set_points smps_set_points = SET_POINTS(smps_ranges);
+static struct vreg_set_points ftsmps_set_points = SET_POINTS(ftsmps_ranges);
+static struct vreg_set_points ncp_set_points = SET_POINTS(ncp_ranges);
+
+static struct vreg_set_points *all_set_points[] = {
+ &pldo_set_points,
+ &nldo_set_points,
+ &smps_set_points,
+ &ftsmps_set_points,
+ &ncp_set_points,
+};
+
+#define LDO(_vreg_id, _rpm_id, _name, _name_pc, _ranges, _hpm_min_load) \
+ [RPM_VREG_ID_##_vreg_id] = { \
+ .req = { \
+ [0] = { .id = MSM_RPM_ID_##_rpm_id##_0, }, \
+ [1] = { .id = MSM_RPM_ID_##_rpm_id##_1, }, \
+ }, \
+ .hpm_min_load = RPM_VREG_8660_##_hpm_min_load##_HPM_MIN_LOAD, \
+ .type = RPM_REGULATOR_TYPE_LDO, \
+ .set_points = &_ranges##_set_points, \
+ .part = &ldo_parts, \
+ .id = RPM_VREG_ID_##_vreg_id, \
+ .rdesc.name = _name, \
+ .rdesc_pc.name = _name_pc, \
+ }
+
+#define SMPS(_vreg_id, _rpm_id, _name, _name_pc, _ranges, _hpm_min_load) \
+ [RPM_VREG_ID_##_vreg_id] = { \
+ .req = { \
+ [0] = { .id = MSM_RPM_ID_##_rpm_id##_0, }, \
+ [1] = { .id = MSM_RPM_ID_##_rpm_id##_1, }, \
+ }, \
+ .hpm_min_load = RPM_VREG_8660_##_hpm_min_load##_HPM_MIN_LOAD, \
+ .type = RPM_REGULATOR_TYPE_SMPS, \
+ .set_points = &_ranges##_set_points, \
+ .part = &smps_parts, \
+ .id = RPM_VREG_ID_##_vreg_id, \
+ .rdesc.name = _name, \
+ .rdesc_pc.name = _name_pc, \
+ }
+
+#define LVS(_vreg_id, _rpm_id, _name, _name_pc) \
+ [RPM_VREG_ID_##_vreg_id] = { \
+ .req = { \
+ [0] = { .id = MSM_RPM_ID_##_rpm_id, }, \
+ [1] = { .id = -1, }, \
+ }, \
+ .type = RPM_REGULATOR_TYPE_VS, \
+ .part = &switch_parts, \
+ .id = RPM_VREG_ID_##_vreg_id, \
+ .rdesc.name = _name, \
+ .rdesc_pc.name = _name_pc, \
+ }
+
+#define MVS(_vreg_id, _rpm_id, _name, _name_pc) \
+ LVS(_vreg_id, _rpm_id, _name, _name_pc)
+
+#define NCP(_vreg_id, _rpm_id, _name, _name_pc) \
+ [RPM_VREG_ID_##_vreg_id] = { \
+ .req = { \
+ [0] = { .id = MSM_RPM_ID_##_rpm_id##_0, }, \
+ [1] = { .id = MSM_RPM_ID_##_rpm_id##_1, }, \
+ }, \
+ .type = RPM_REGULATOR_TYPE_NCP, \
+ .set_points = &ncp_set_points, \
+ .part = &ncp_parts, \
+ .id = RPM_VREG_ID_##_vreg_id, \
+ .rdesc.name = _name, \
+ .rdesc_pc.name = _name_pc, \
+ }
+
+static struct vreg vregs[] = {
+ LDO(PM8058_L0, LDO0, "8058_l0", "8058_l0_pc", nldo, LDO_150),
+ LDO(PM8058_L1, LDO1, "8058_l1", "8058_l1_pc", nldo, LDO_300),
+ LDO(PM8058_L2, LDO2, "8058_l2", "8058_l2_pc", pldo, LDO_300),
+ LDO(PM8058_L3, LDO3, "8058_l3", "8058_l3_pc", pldo, LDO_150),
+ LDO(PM8058_L4, LDO4, "8058_l4", "8058_l4_pc", pldo, LDO_50),
+ LDO(PM8058_L5, LDO5, "8058_l5", "8058_l5_pc", pldo, LDO_300),
+ LDO(PM8058_L6, LDO6, "8058_l6", "8058_l6_pc", pldo, LDO_50),
+ LDO(PM8058_L7, LDO7, "8058_l7", "8058_l7_pc", pldo, LDO_50),
+ LDO(PM8058_L8, LDO8, "8058_l8", "8058_l8_pc", pldo, LDO_300),
+ LDO(PM8058_L9, LDO9, "8058_l9", "8058_l9_pc", pldo, LDO_300),
+ LDO(PM8058_L10, LDO10, "8058_l10", "8058_l10_pc", pldo, LDO_300),
+ LDO(PM8058_L11, LDO11, "8058_l11", "8058_l11_pc", pldo, LDO_150),
+ LDO(PM8058_L12, LDO12, "8058_l12", "8058_l12_pc", pldo, LDO_150),
+ LDO(PM8058_L13, LDO13, "8058_l13", "8058_l13_pc", pldo, LDO_300),
+ LDO(PM8058_L14, LDO14, "8058_l14", "8058_l14_pc", pldo, LDO_300),
+ LDO(PM8058_L15, LDO15, "8058_l15", "8058_l15_pc", pldo, LDO_300),
+ LDO(PM8058_L16, LDO16, "8058_l16", "8058_l16_pc", pldo, LDO_300),
+ LDO(PM8058_L17, LDO17, "8058_l17", "8058_l17_pc", pldo, LDO_150),
+ LDO(PM8058_L18, LDO18, "8058_l18", "8058_l18_pc", pldo, LDO_150),
+ LDO(PM8058_L19, LDO19, "8058_l19", "8058_l19_pc", pldo, LDO_150),
+ LDO(PM8058_L20, LDO20, "8058_l20", "8058_l20_pc", pldo, LDO_150),
+ LDO(PM8058_L21, LDO21, "8058_l21", "8058_l21_pc", nldo, LDO_150),
+ LDO(PM8058_L22, LDO22, "8058_l22", "8058_l22_pc", nldo, LDO_300),
+ LDO(PM8058_L23, LDO23, "8058_l23", "8058_l23_pc", nldo, LDO_300),
+ LDO(PM8058_L24, LDO24, "8058_l24", "8058_l24_pc", nldo, LDO_150),
+ LDO(PM8058_L25, LDO25, "8058_l25", "8058_l25_pc", nldo, LDO_150),
+
+ SMPS(PM8058_S0, SMPS0, "8058_s0", "8058_s0_pc", smps, SMPS),
+ SMPS(PM8058_S1, SMPS1, "8058_s1", "8058_s1_pc", smps, SMPS),
+ SMPS(PM8058_S2, SMPS2, "8058_s2", "8058_s2_pc", smps, SMPS),
+ SMPS(PM8058_S3, SMPS3, "8058_s3", "8058_s3_pc", smps, SMPS),
+ SMPS(PM8058_S4, SMPS4, "8058_s4", "8058_s4_pc", smps, SMPS),
+
+ LVS(PM8058_LVS0, LVS0, "8058_lvs0", "8058_lvs0_pc"),
+ LVS(PM8058_LVS1, LVS1, "8058_lvs1", "8058_lvs1_pc"),
+
+ NCP(PM8058_NCP, NCP, "8058_ncp", NULL),
+
+ LDO(PM8901_L0, LDO0B, "8901_l0", "8901_l0_pc", nldo, LDO_300),
+ LDO(PM8901_L1, LDO1B, "8901_l1", "8901_l1_pc", pldo, LDO_300),
+ LDO(PM8901_L2, LDO2B, "8901_l2", "8901_l2_pc", pldo, LDO_300),
+ LDO(PM8901_L3, LDO3B, "8901_l3", "8901_l3_pc", pldo, LDO_300),
+ LDO(PM8901_L4, LDO4B, "8901_l4", "8901_l4_pc", pldo, LDO_300),
+ LDO(PM8901_L5, LDO5B, "8901_l5", "8901_l5_pc", pldo, LDO_300),
+ LDO(PM8901_L6, LDO6B, "8901_l6", "8901_l6_pc", pldo, LDO_300),
+
+ SMPS(PM8901_S0, SMPS0B, "8901_s0", "8901_s0_pc", ftsmps, FTSMPS),
+ SMPS(PM8901_S1, SMPS1B, "8901_s1", "8901_s1_pc", ftsmps, FTSMPS),
+ SMPS(PM8901_S2, SMPS2B, "8901_s2", "8901_s2_pc", ftsmps, FTSMPS),
+ SMPS(PM8901_S3, SMPS3B, "8901_s3", "8901_s3_pc", ftsmps, FTSMPS),
+ SMPS(PM8901_S4, SMPS4B, "8901_s4", "8901_s4_pc", ftsmps, FTSMPS),
+
+ LVS(PM8901_LVS0, LVS0B, "8901_lvs0", "8901_lvs0_pc"),
+ LVS(PM8901_LVS1, LVS1B, "8901_lvs1", "8901_lvs1_pc"),
+ LVS(PM8901_LVS2, LVS2B, "8901_lvs2", "8901_lvs2_pc"),
+ LVS(PM8901_LVS3, LVS3B, "8901_lvs3", "8901_lvs3_pc"),
+
+ MVS(PM8901_MVS0, MVS, "8901_mvs0", "8901_mvs0_pc"),
+};
+
+static const char *pin_func_label[] = {
+ [RPM_VREG_PIN_FN_8660_ENABLE] = "on/off",
+ [RPM_VREG_PIN_FN_8660_MODE] = "HPM/LPM",
+ [RPM_VREG_PIN_FN_8660_SLEEP_B] = "sleep_b",
+ [RPM_VREG_PIN_FN_8660_NONE] = "none",
+};
+
+static const char *force_mode_label[] = {
+ [RPM_VREG_FORCE_MODE_8660_NONE] = "none",
+ [RPM_VREG_FORCE_MODE_8660_LPM] = "LPM",
+ [RPM_VREG_FORCE_MODE_8660_HPM] = "HPM",
+};
+
+static const char *pin_control_label[] = {
+ " A0",
+ " A1",
+ " D0",
+ " D1",
+};
+
+static int is_real_id(int id)
+{
+ return (id >= 0) && (id <= RPM_VREG_ID_8660_MAX_REAL);
+}
+
+static int pc_id_to_real_id(int id)
+{
+ int real_id;
+
+ if (id >= RPM_VREG_ID_PM8058_L0_PC && id <= RPM_VREG_ID_PM8058_LVS1_PC)
+ real_id = id - RPM_VREG_ID_PM8058_L0_PC + RPM_VREG_ID_PM8058_L0;
+ else
+ real_id = id - RPM_VREG_ID_PM8901_L0_PC + RPM_VREG_ID_PM8901_L0;
+
+ return real_id;
+}
+
+static struct vreg_config config = {
+ .vregs = vregs,
+ .vregs_len = ARRAY_SIZE(vregs),
+
+ .vreg_id_min = RPM_VREG_ID_PM8058_L0,
+ .vreg_id_max = RPM_VREG_ID_8660_MAX,
+
+ .pin_func_none = RPM_VREG_PIN_FN_8660_NONE,
+ .pin_func_sleep_b = RPM_VREG_PIN_FN_8660_SLEEP_B,
+
+ .mode_lpm = REGULATOR_MODE_IDLE,
+ .mode_hpm = REGULATOR_MODE_NORMAL,
+
+ .set_points = all_set_points,
+ .set_points_len = ARRAY_SIZE(all_set_points),
+
+ .label_pin_ctrl = pin_control_label,
+ .label_pin_ctrl_len = ARRAY_SIZE(pin_control_label),
+ .label_pin_func = pin_func_label,
+ .label_pin_func_len = ARRAY_SIZE(pin_func_label),
+ .label_force_mode = force_mode_label,
+ .label_force_mode_len = ARRAY_SIZE(force_mode_label),
+
+ .is_real_id = is_real_id,
+ .pc_id_to_real_id = pc_id_to_real_id,
+
+ .use_legacy_optimum_mode = 1,
+ .ia_follows_ip = 1,
+};
+
+struct vreg_config *get_config_8660(void)
+{
+ return &config;
+}
diff --git a/arch/arm/mach-msm/rpm-regulator-8960.c b/arch/arm/mach-msm/rpm-regulator-8960.c
index 52cc77d..8726ed4 100644
--- a/arch/arm/mach-msm/rpm-regulator-8960.c
+++ b/arch/arm/mach-msm/rpm-regulator-8960.c
@@ -13,84 +13,10 @@
#define pr_fmt(fmt) "%s: " fmt, __func__
-#include <linux/module.h>
-#include <linux/err.h>
-#include <linux/kernel.h>
-#include <linux/init.h>
-#include <linux/slab.h>
-#include <linux/spinlock.h>
-#include <linux/platform_device.h>
-#include <linux/regulator/driver.h>
-#include <mach/rpm.h>
-#include <mach/rpm-regulator.h>
-#include <mach/socinfo.h>
+#include "rpm-regulator-private.h"
-#include "rpm_resources.h"
-
-/* Debug Definitions */
-
-enum {
- MSM_RPM_VREG_DEBUG_REQUEST = BIT(0),
- MSM_RPM_VREG_DEBUG_VOTE = BIT(1),
- MSM_RPM_VREG_DEBUG_DUPLICATE = BIT(2),
- MSM_RPM_VREG_DEBUG_IGNORE_VDD_MEM_DIG = BIT(3),
-};
-
-static int msm_rpm_vreg_debug_mask;
-module_param_named(
- debug_mask, msm_rpm_vreg_debug_mask, int, S_IRUSR | S_IWUSR
-);
-
-#define REGULATOR_TYPE_LDO 0
-#define REGULATOR_TYPE_SMPS 1
-#define REGULATOR_TYPE_VS 2
-#define REGULATOR_TYPE_NCP 3
-
-#define MICRO_TO_MILLI(uV) ((uV) / 1000)
-#define MILLI_TO_MICRO(mV) ((mV) * 1000)
-
-#define SET_PART(_vreg, _part, _val) \
- _vreg->req[_vreg->part->_part.word].value \
- = (_vreg->req[_vreg->part->_part.word].value \
- & ~vreg->part->_part.mask) \
- | (((_val) << vreg->part->_part.shift) & vreg->part->_part.mask)
-
-#define GET_PART(_vreg, _part) \
- ((_vreg->req[_vreg->part->_part.word].value & vreg->part->_part.mask) \
- >> vreg->part->_part.shift)
-
-struct request_member {
- int word;
- unsigned int mask;
- int shift;
-};
-
-struct rpm_vreg_parts {
- struct request_member mV; /* voltage: used if voltage is in mV */
- struct request_member uV; /* voltage: used if voltage is in uV */
- struct request_member ip; /* peak current in mA */
- struct request_member pd; /* pull down enable */
- struct request_member ia; /* average current in mA */
- struct request_member fm; /* force mode */
- struct request_member pm; /* power mode */
- struct request_member pc; /* pin control */
- struct request_member pf; /* pin function */
- struct request_member enable_state; /* NCP and switch */
- struct request_member comp_mode; /* NCP */
- struct request_member freq; /* frequency: NCP and SMPS */
- struct request_member freq_clk_src; /* clock source: SMPS */
- struct request_member hpm; /* switch: control OCP ans SS */
- int request_len;
-};
-
-#define REQUEST_MEMBER(_word, _mask, _shift) \
- { \
- .word = _word, \
- .mask = _mask, \
- .shift = _shift, \
- }
-
-struct rpm_vreg_parts ldo_parts = {
+/* RPM regulator request formats */
+static struct rpm_vreg_parts ldo_parts = {
.request_len = 2,
.uV = REQUEST_MEMBER(0, 0x007FFFFF, 0),
.pd = REQUEST_MEMBER(0, 0x00800000, 23),
@@ -101,7 +27,7 @@
.fm = REQUEST_MEMBER(1, 0x00700000, 20),
};
-struct rpm_vreg_parts smps_parts = {
+static struct rpm_vreg_parts smps_parts = {
.request_len = 2,
.uV = REQUEST_MEMBER(0, 0x007FFFFF, 0),
.pd = REQUEST_MEMBER(0, 0x00800000, 23),
@@ -115,7 +41,7 @@
.freq_clk_src = REQUEST_MEMBER(1, 0x60000000, 29),
};
-struct rpm_vreg_parts switch_parts = {
+static struct rpm_vreg_parts switch_parts = {
.request_len = 1,
.enable_state = REQUEST_MEMBER(0, 0x00000001, 0),
.pd = REQUEST_MEMBER(0, 0x00000002, 1),
@@ -124,7 +50,7 @@
.hpm = REQUEST_MEMBER(0, 0x00000C00, 10),
};
-struct rpm_vreg_parts ncp_parts = {
+static struct rpm_vreg_parts ncp_parts = {
.request_len = 1,
.uV = REQUEST_MEMBER(0, 0x007FFFFF, 0),
.enable_state = REQUEST_MEMBER(0, 0x00800000, 23),
@@ -132,26 +58,7 @@
.freq = REQUEST_MEMBER(0, 0x3E000000, 25),
};
-struct vreg_range {
- int min_uV;
- int max_uV;
- int step_uV;
- unsigned n_voltages;
-};
-
-struct vreg_set_points {
- struct vreg_range *range;
- int count;
- unsigned n_voltages;
-};
-
-#define VOLTAGE_RANGE(_min_uV, _max_uV, _step_uV) \
- { \
- .min_uV = _min_uV, \
- .max_uV = _max_uV, \
- .step_uV = _step_uV, \
- }
-
+/* Physically available PMIC regulator voltage setpoint ranges */
static struct vreg_range pldo_ranges[] = {
VOLTAGE_RANGE( 750000, 1487500, 12500),
VOLTAGE_RANGE(1500000, 3075000, 25000),
@@ -183,12 +90,6 @@
VOLTAGE_RANGE(1500000, 3050000, 50000),
};
-#define SET_POINTS(_ranges) \
-{ \
- .range = _ranges, \
- .count = ARRAY_SIZE(_ranges), \
-};
-
static struct vreg_set_points pldo_set_points = SET_POINTS(pldo_ranges);
static struct vreg_set_points nldo_set_points = SET_POINTS(nldo_ranges);
static struct vreg_set_points nldo1200_set_points = SET_POINTS(nldo1200_ranges);
@@ -196,1217 +97,164 @@
static struct vreg_set_points ftsmps_set_points = SET_POINTS(ftsmps_ranges);
static struct vreg_set_points ncp_set_points = SET_POINTS(ncp_ranges);
-/*
- * This is used when voting for LPM or HPM by subtracting or adding to the
- * hpm_min_load of a regulator. It has units of uA.
- */
-#define LOAD_THRESHOLD_STEP 1000
-
-/* This is the maximum uA load that can be passed to the RPM. */
-#define MAX_POSSIBLE_LOAD (MILLI_TO_MICRO(0xFFF))
-
-struct vreg {
- struct msm_rpm_iv_pair req[2];
- struct msm_rpm_iv_pair prev_active_req[2];
- struct msm_rpm_iv_pair prev_sleep_req[2];
- struct rpm_regulator_init_data pdata;
- struct regulator_dev *rdev;
- struct regulator_dev *rdev_pc;
- const char *name;
- struct vreg_set_points *set_points;
- struct rpm_vreg_parts *part;
- int type;
- enum rpm_vreg_id id;
- struct mutex pc_lock;
- int save_uV;
- int mode;
- bool is_enabled;
- bool is_enabled_pc;
- const int hpm_min_load;
- int active_min_uV_vote[RPM_VREG_VOTER_COUNT];
- int sleep_min_uV_vote[RPM_VREG_VOTER_COUNT];
-
+static struct vreg_set_points *all_set_points[] = {
+ &pldo_set_points,
+ &nldo_set_points,
+ &nldo1200_set_points,
+ &smps_set_points,
+ &ftsmps_set_points,
+ &ncp_set_points,
};
-#define LDO(_id, _ranges, _hpm_min_load) \
+#define LDO(_id, _name, _name_pc, _ranges, _hpm_min_load) \
[RPM_VREG_ID_PM8921_##_id] = { \
.req = { \
[0] = { .id = MSM_RPM_ID_PM8921_##_id##_0, }, \
[1] = { .id = MSM_RPM_ID_PM8921_##_id##_1, }, \
}, \
- .hpm_min_load = RPM_VREG_##_hpm_min_load##_HPM_MIN_LOAD, \
- .type = REGULATOR_TYPE_LDO, \
+ .hpm_min_load = RPM_VREG_8960_##_hpm_min_load##_HPM_MIN_LOAD, \
+ .type = RPM_REGULATOR_TYPE_LDO, \
.set_points = &_ranges##_set_points, \
.part = &ldo_parts, \
.id = RPM_VREG_ID_PM8921_##_id, \
+ .rdesc.name = _name, \
+ .rdesc_pc.name = _name_pc, \
}
-#define SMPS(_id, _ranges, _hpm_min_load) \
+#define SMPS(_id, _name, _name_pc, _ranges, _hpm_min_load) \
[RPM_VREG_ID_PM8921_##_id] = { \
.req = { \
[0] = { .id = MSM_RPM_ID_PM8921_##_id##_0, }, \
[1] = { .id = MSM_RPM_ID_PM8921_##_id##_1, }, \
}, \
- .hpm_min_load = RPM_VREG_##_hpm_min_load##_HPM_MIN_LOAD, \
- .type = REGULATOR_TYPE_SMPS, \
+ .hpm_min_load = RPM_VREG_8960_##_hpm_min_load##_HPM_MIN_LOAD, \
+ .type = RPM_REGULATOR_TYPE_SMPS, \
.set_points = &_ranges##_set_points, \
.part = &smps_parts, \
.id = RPM_VREG_ID_PM8921_##_id, \
+ .rdesc.name = _name, \
+ .rdesc_pc.name = _name_pc, \
}
-#define LVS(_id) \
+#define LVS(_id, _name, _name_pc) \
[RPM_VREG_ID_PM8921_##_id] = { \
.req = { \
[0] = { .id = MSM_RPM_ID_PM8921_##_id, }, \
[1] = { .id = -1, }, \
}, \
- .type = REGULATOR_TYPE_VS, \
+ .type = RPM_REGULATOR_TYPE_VS, \
.part = &switch_parts, \
.id = RPM_VREG_ID_PM8921_##_id, \
+ .rdesc.name = _name, \
+ .rdesc_pc.name = _name_pc, \
}
-#define MVS(_vreg_id, _rpm_id) \
+#define MVS(_vreg_id, _name, _name_pc, _rpm_id) \
[RPM_VREG_ID_PM8921_##_vreg_id] = { \
.req = { \
[0] = { .id = MSM_RPM_ID_##_rpm_id, }, \
[1] = { .id = -1, }, \
}, \
- .type = REGULATOR_TYPE_VS, \
+ .type = RPM_REGULATOR_TYPE_VS, \
.part = &switch_parts, \
.id = RPM_VREG_ID_PM8921_##_vreg_id, \
+ .rdesc.name = _name, \
+ .rdesc_pc.name = _name_pc, \
}
-#define NCP(_id) \
+#define NCP(_id, _name, _name_pc) \
[RPM_VREG_ID_PM8921_##_id] = { \
.req = { \
[0] = { .id = MSM_RPM_ID_##_id##_0, }, \
[1] = { .id = MSM_RPM_ID_##_id##_1, }, \
}, \
- .type = REGULATOR_TYPE_NCP, \
+ .type = RPM_REGULATOR_TYPE_NCP, \
.set_points = &ncp_set_points, \
.part = &ncp_parts, \
.id = RPM_VREG_ID_PM8921_##_id, \
+ .rdesc.name = _name, \
+ .rdesc_pc.name = _name_pc, \
}
static struct vreg vregs[] = {
- LDO(L1, nldo, LDO_150),
- LDO(L2, nldo, LDO_150),
- LDO(L3 , pldo, LDO_150),
- LDO(L4, pldo, LDO_50),
- LDO(L5, pldo, LDO_300),
- LDO(L6, pldo, LDO_600),
- LDO(L7, pldo, LDO_150),
- LDO(L8, pldo, LDO_300),
- LDO(L9, pldo, LDO_300),
- LDO(L10, pldo, LDO_600),
- LDO(L11, pldo, LDO_150),
- LDO(L12, nldo, LDO_150),
- LDO(L14, pldo, LDO_50),
- LDO(L15, pldo, LDO_150),
- LDO(L16, pldo, LDO_300),
- LDO(L17, pldo, LDO_150),
- LDO(L18, nldo, LDO_150),
- LDO(L21, pldo, LDO_150),
- LDO(L22, pldo, LDO_150),
- LDO(L23, pldo, LDO_150),
- LDO(L24, nldo1200, LDO_1200),
- LDO(L25, nldo1200, LDO_1200),
- LDO(L26, nldo1200, LDO_1200),
- LDO(L27, nldo1200, LDO_1200),
- LDO(L28, nldo1200, LDO_1200),
- LDO(L29, pldo, LDO_150),
+ LDO(L1, "8921_l1", "8921_l1_pc", nldo, LDO_150),
+ LDO(L2, "8921_l2", "8921_l2_pc", nldo, LDO_150),
+ LDO(L3, "8921_l3", "8921_l3_pc", pldo, LDO_150),
+ LDO(L4, "8921_l4", "8921_l4_pc", pldo, LDO_50),
+ LDO(L5, "8921_l5", "8921_l5_pc", pldo, LDO_300),
+ LDO(L6, "8921_l6", "8921_l6_pc", pldo, LDO_600),
+ LDO(L7, "8921_l7", "8921_l7_pc", pldo, LDO_150),
+ LDO(L8, "8921_l8", "8921_l8_pc", pldo, LDO_300),
+ LDO(L9, "8921_l9", "8921_l9_pc", pldo, LDO_300),
+ LDO(L10, "8921_l10", "8921_l10_pc", pldo, LDO_600),
+ LDO(L11, "8921_l11", "8921_l11_pc", pldo, LDO_150),
+ LDO(L12, "8921_l12", "8921_l12_pc", nldo, LDO_150),
+ LDO(L14, "8921_l14", "8921_l14_pc", pldo, LDO_50),
+ LDO(L15, "8921_l15", "8921_l15_pc", pldo, LDO_150),
+ LDO(L16, "8921_l16", "8921_l16_pc", pldo, LDO_300),
+ LDO(L17, "8921_l17", "8921_l17_pc", pldo, LDO_150),
+ LDO(L18, "8921_l18", "8921_l18_pc", nldo, LDO_150),
+ LDO(L21, "8921_l21", "8921_l21_pc", pldo, LDO_150),
+ LDO(L22, "8921_l22", "8921_l22_pc", pldo, LDO_150),
+ LDO(L23, "8921_l23", "8921_l23_pc", pldo, LDO_150),
+ LDO(L24, "8921_l24", NULL, nldo1200, LDO_1200),
+ LDO(L25, "8921_l25", NULL, nldo1200, LDO_1200),
+ LDO(L26, "8921_l26", NULL, nldo1200, LDO_1200),
+ LDO(L27, "8921_l27", NULL, nldo1200, LDO_1200),
+ LDO(L28, "8921_l28", NULL, nldo1200, LDO_1200),
+ LDO(L29, "8921_l29", "8921_l29_pc", pldo, LDO_150),
- SMPS(S1, smps, SMPS_1500),
- SMPS(S2, smps, SMPS_1500),
- SMPS(S3, smps, SMPS_1500),
- SMPS(S4, smps, SMPS_1500),
- SMPS(S5, ftsmps, SMPS_2000),
- SMPS(S6, ftsmps, SMPS_2000),
- SMPS(S7, smps, SMPS_1500),
- SMPS(S8, smps, SMPS_1500),
+ SMPS(S1, "8921_s1", "8921_s1_pc", smps, SMPS_1500),
+ SMPS(S2, "8921_s2", "8921_s2_pc", smps, SMPS_1500),
+ SMPS(S3, "8921_s3", "8921_s3_pc", smps, SMPS_1500),
+ SMPS(S4, "8921_s4", "8921_s4_pc", smps, SMPS_1500),
+ SMPS(S5, "8921_s5", NULL, ftsmps, SMPS_2000),
+ SMPS(S6, "8921_s6", NULL, ftsmps, SMPS_2000),
+ SMPS(S7, "8921_s7", "8921_s7_pc", smps, SMPS_1500),
+ SMPS(S8, "8921_s8", "8921_s8_pc", smps, SMPS_1500),
- LVS(LVS1),
- LVS(LVS2),
- LVS(LVS3),
- LVS(LVS4),
- LVS(LVS5),
- LVS(LVS6),
- LVS(LVS7),
- MVS(USB_OTG, USB_OTG_SWITCH),
- MVS(HDMI_MVS, HDMI_SWITCH),
+ LVS(LVS1, "8921_lvs1", "8921_lvs1_pc"),
+ LVS(LVS2, "8921_lvs2", NULL),
+ LVS(LVS3, "8921_lvs3", "8921_lvs3_pc"),
+ LVS(LVS4, "8921_lvs4", "8921_lvs4_pc"),
+ LVS(LVS5, "8921_lvs5", "8921_lvs5_pc"),
+ LVS(LVS6, "8921_lvs6", "8921_lvs6_pc"),
+ LVS(LVS7, "8921_lvs7", "8921_lvs7_pc"),
+ MVS(USB_OTG, "8921_usb_otg", NULL, USB_OTG_SWITCH),
+ MVS(HDMI_MVS, "8921_hdmi_mvs", NULL, HDMI_SWITCH),
- NCP(NCP),
+ NCP(NCP, "8921_ncp", NULL),
};
-#define vreg_err(vreg, fmt, ...) \
- pr_err("%s: " fmt, vreg->name, ##__VA_ARGS__)
-
-#define VREG_ID_IS_VDD_MEM_OR_DIG(id) \
- ((id == RPM_VREG_ID_PM8921_L24) || (id == RPM_VREG_ID_PM8921_S3))
-
-const char *pin_func_label[] = {
- [RPM_VREG_PIN_FN_DONT_CARE] = "don't care",
- [RPM_VREG_PIN_FN_ENABLE] = "on/off",
- [RPM_VREG_PIN_FN_MODE] = "HPM/LPM",
- [RPM_VREG_PIN_FN_SLEEP_B] = "sleep_b",
- [RPM_VREG_PIN_FN_NONE] = "none",
+static const char *pin_func_label[] = {
+ [RPM_VREG_PIN_FN_8960_DONT_CARE] = "don't care",
+ [RPM_VREG_PIN_FN_8960_ENABLE] = "on/off",
+ [RPM_VREG_PIN_FN_8960_MODE] = "HPM/LPM",
+ [RPM_VREG_PIN_FN_8960_SLEEP_B] = "sleep_b",
+ [RPM_VREG_PIN_FN_8960_NONE] = "none",
};
-const char *force_mode_label[] = {
- [RPM_VREG_FORCE_MODE_NONE] = "none",
- [RPM_VREG_FORCE_MODE_LPM] = "LPM",
- [RPM_VREG_FORCE_MODE_AUTO] = "auto",
- [RPM_VREG_FORCE_MODE_HPM] = "HPM",
- [RPM_VREG_FORCE_MODE_BYPASS] = "BYP",
+static const char *force_mode_label[] = {
+ [RPM_VREG_FORCE_MODE_8960_NONE] = "none",
+ [RPM_VREG_FORCE_MODE_8960_LPM] = "LPM",
+ [RPM_VREG_FORCE_MODE_8960_AUTO] = "auto",
+ [RPM_VREG_FORCE_MODE_8960_HPM] = "HPM",
+ [RPM_VREG_FORCE_MODE_8960_BYPASS] = "BYP",
};
-const char *power_mode_label[] = {
- [RPM_VREG_POWER_MODE_HYSTERETIC] = "HYS",
- [RPM_VREG_POWER_MODE_PWM] = "PWM",
+static const char *power_mode_label[] = {
+ [RPM_VREG_POWER_MODE_8960_HYSTERETIC] = "HYS",
+ [RPM_VREG_POWER_MODE_8960_PWM] = "PWM",
};
-static void rpm_regulator_req(struct vreg *vreg, int set)
-{
- int uV, ip, fm, pm, pc, pf, pd, ia, freq, clk, state, hpm, comp_mode;
- const char *pf_label = "", *fm_label = "", *pc_total = "";
- const char *pc_en0 = "", *pc_en1 = "", *pc_en2 = "", *pc_en3 = "";
- const char *pm_label = "";
-
- /* Suppress VDD_MEM and VDD_DIG printing. */
- if ((msm_rpm_vreg_debug_mask & MSM_RPM_VREG_DEBUG_IGNORE_VDD_MEM_DIG)
- && VREG_ID_IS_VDD_MEM_OR_DIG(vreg->id))
- return;
-
- if (vreg->part->uV.mask)
- uV = GET_PART(vreg, uV);
- else
- uV = MILLI_TO_MICRO(GET_PART(vreg, mV));
-
- ip = GET_PART(vreg, ip);
- fm = GET_PART(vreg, fm);
- pm = GET_PART(vreg, pm);
- pc = GET_PART(vreg, pc);
- pf = GET_PART(vreg, pf);
- pd = GET_PART(vreg, pd);
- ia = GET_PART(vreg, ia);
- freq = GET_PART(vreg, freq);
- clk = GET_PART(vreg, freq_clk_src);
- state = GET_PART(vreg, enable_state);
- hpm = GET_PART(vreg, hpm);
- comp_mode = GET_PART(vreg, comp_mode);
-
- if (pf >= 0 && pf < ARRAY_SIZE(pin_func_label))
- pf_label = pin_func_label[pf];
-
- if (fm >= 0 && fm < ARRAY_SIZE(force_mode_label))
- fm_label = force_mode_label[fm];
-
- if (pm >= 0 && pm < ARRAY_SIZE(power_mode_label))
- pm_label = power_mode_label[pm];
-
- if (pc & RPM_VREG_PIN_CTRL_EN0)
- pc_en0 = " D1";
- if (pc & RPM_VREG_PIN_CTRL_EN1)
- pc_en1 = " A0";
- if (pc & RPM_VREG_PIN_CTRL_EN2)
- pc_en2 = " A1";
- if (pc & RPM_VREG_PIN_CTRL_EN3)
- pc_en3 = " A2";
- if (pc == RPM_VREG_PIN_CTRL_NONE)
- pc_total = " none";
-
- switch (vreg->type) {
- case REGULATOR_TYPE_LDO:
- pr_info("%s %-9s: s=%c, v=%7d uV, ip=%4d mA, fm=%s (%d), "
- "pc=%s%s%s%s%s (%d), pf=%s (%d), pd=%s (%d), "
- "ia=%4d mA; req[0]={%d, 0x%08X}, req[1]={%d, 0x%08X}\n",
- (set == MSM_RPM_CTX_SET_0 ? "sending " : "buffered"),
- vreg->name,
- (set == MSM_RPM_CTX_SET_0 ? 'A' : 'S'), uV, ip,
- fm_label, fm, pc_en0, pc_en1, pc_en2, pc_en3, pc_total,
- pc, pf_label, pf, (pd == 1 ? "Y" : "N"), pd, ia,
- vreg->req[0].id, vreg->req[0].value,
- vreg->req[1].id, vreg->req[1].value);
- break;
- case REGULATOR_TYPE_SMPS:
- pr_info("%s %-9s: s=%c, v=%7d uV, ip=%4d mA, fm=%s (%d), "
- "pc=%s%s%s%s%s (%d), pf=%s (%d), pd=%s (%d), "
- "ia=%4d mA, freq=%2d, pm=%s (%d), clk_src=%d; "
- "req[0]={%d, 0x%08X}, req[1]={%d, 0x%08X}\n",
- (set == MSM_RPM_CTX_SET_0 ? "sending " : "buffered"),
- vreg->name,
- (set == MSM_RPM_CTX_SET_0 ? 'A' : 'S'), uV, ip,
- fm_label, fm, pc_en0, pc_en1, pc_en2, pc_en3, pc_total,
- pc, pf_label, pf, (pd == 1 ? "Y" : "N"), pd, ia, freq,
- pm_label, pm, clk, vreg->req[0].id, vreg->req[0].value,
- vreg->req[1].id, vreg->req[1].value);
- break;
- case REGULATOR_TYPE_VS:
- pr_info("%s %-9s: s=%c, state=%s (%d), pd=%s (%d), "
- "pc =%s%s%s%s%s (%d), pf=%s (%d), hpm=%d; "
- "req[0]={%d, 0x%08X}\n",
- (set == MSM_RPM_CTX_SET_0 ? "sending " : "buffered"),
- vreg->name, (set == MSM_RPM_CTX_SET_0 ? 'A' : 'S'),
- (state == 1 ? "on" : "off"), state,
- (pd == 1 ? "Y" : "N"), pd, pc_en0, pc_en1, pc_en2,
- pc_en3, pc_total, pc, pf_label, pf, hpm,
- vreg->req[0].id, vreg->req[0].value);
- break;
- case REGULATOR_TYPE_NCP:
- pr_info("%s %-9s: s=%c, v=-%7d uV, state=%s (%d), freq=%2d, "
- "comp=%d; req[0]={%d, 0x%08X}\n",
- (set == MSM_RPM_CTX_SET_0 ? "sending " : "buffered"),
- vreg->name, (set == MSM_RPM_CTX_SET_0 ? 'A' : 'S'),
- uV, (state == 1 ? "on" : "off"), state, freq, comp_mode,
- vreg->req[0].id, vreg->req[0].value);
- break;
- }
-}
-
-static void rpm_regulator_vote(struct vreg *vreg, enum rpm_vreg_voter voter,
- int set, int voter_uV, int aggregate_uV)
-{
- /* Suppress VDD_MEM and VDD_DIG printing. */
- if ((msm_rpm_vreg_debug_mask & MSM_RPM_VREG_DEBUG_IGNORE_VDD_MEM_DIG)
- && VREG_ID_IS_VDD_MEM_OR_DIG(vreg->id))
- return;
-
- pr_info("vote received %-9s: voter=%d, set=%c, v_voter=%7d uV, "
- "v_aggregate=%7d uV\n", vreg->name, voter,
- (set == 0 ? 'A' : 'S'), voter_uV, aggregate_uV);
-}
-
-static void rpm_regulator_duplicate(struct vreg *vreg, int set, int cnt)
-{
- /* Suppress VDD_MEM and VDD_DIG printing. */
- if ((msm_rpm_vreg_debug_mask & MSM_RPM_VREG_DEBUG_IGNORE_VDD_MEM_DIG)
- && VREG_ID_IS_VDD_MEM_OR_DIG(vreg->id))
- return;
-
- if (cnt == 2)
- pr_info("ignored request %-9s: set=%c; req[0]={%d, 0x%08X}, "
- "req[1]={%d, 0x%08X}\n", vreg->name,
- (set == 0 ? 'A' : 'S'),
- vreg->req[0].id, vreg->req[0].value,
- vreg->req[1].id, vreg->req[1].value);
- else if (cnt == 1)
- pr_info("ignored request %-9s: set=%c; req[0]={%d, 0x%08X}\n",
- vreg->name, (set == 0 ? 'A' : 'S'),
- vreg->req[0].id, vreg->req[0].value);
-}
-
-/* Spin lock needed for sleep-selectable regulators. */
-static DEFINE_SPINLOCK(pm8921_noirq_lock);
-
-static int voltage_from_req(struct vreg *vreg)
-{
- int uV = 0;
-
- if (vreg->part->uV.mask)
- uV = GET_PART(vreg, uV);
- else
- uV = MILLI_TO_MICRO(GET_PART(vreg, mV));
-
- return uV;
-}
-
-static void voltage_to_req(int uV, struct vreg *vreg)
-{
- if (vreg->part->uV.mask)
- SET_PART(vreg, uV, uV);
- else
- SET_PART(vreg, mV, MICRO_TO_MILLI(uV));
-}
-
-static int vreg_send_request(struct vreg *vreg, enum rpm_vreg_voter voter,
- int set, unsigned mask0, unsigned val0,
- unsigned mask1, unsigned val1, unsigned cnt,
- int update_voltage)
-{
- struct msm_rpm_iv_pair *prev_req;
- int rc = 0, max_uV_vote = 0;
- unsigned prev0, prev1;
- int *min_uV_vote;
- int i;
-
- if (set == MSM_RPM_CTX_SET_0) {
- min_uV_vote = vreg->active_min_uV_vote;
- prev_req = vreg->prev_active_req;
- } else {
- min_uV_vote = vreg->sleep_min_uV_vote;
- prev_req = vreg->prev_sleep_req;
- }
-
- prev0 = vreg->req[0].value;
- vreg->req[0].value &= ~mask0;
- vreg->req[0].value |= val0 & mask0;
-
- prev1 = vreg->req[1].value;
- vreg->req[1].value &= ~mask1;
- vreg->req[1].value |= val1 & mask1;
-
- if (update_voltage)
- min_uV_vote[voter] = voltage_from_req(vreg);
-
- /* Find the highest voltage voted for and use it. */
- for (i = 0; i < RPM_VREG_VOTER_COUNT; i++)
- max_uV_vote = max(max_uV_vote, min_uV_vote[i]);
- voltage_to_req(max_uV_vote, vreg);
-
- if (msm_rpm_vreg_debug_mask & MSM_RPM_VREG_DEBUG_VOTE)
- rpm_regulator_vote(vreg, voter, set, min_uV_vote[voter],
- max_uV_vote);
-
- /* Ignore duplicate requests */
- if (vreg->req[0].value != prev_req[0].value ||
- vreg->req[1].value != prev_req[1].value) {
- rc = msm_rpmrs_set_noirq(set, vreg->req, cnt);
- if (rc) {
- vreg->req[0].value = prev0;
- vreg->req[1].value = prev1;
-
- vreg_err(vreg, "msm_rpmrs_set_noirq failed - "
- "set=%s, id=%d, rc=%d\n",
- (set == MSM_RPM_CTX_SET_0 ? "active" : "sleep"),
- vreg->req[0].id, rc);
- } else {
- /* Only save if nonzero and active set. */
- if (max_uV_vote && (set == MSM_RPM_CTX_SET_0))
- vreg->save_uV = max_uV_vote;
- if (msm_rpm_vreg_debug_mask
- & MSM_RPM_VREG_DEBUG_REQUEST)
- rpm_regulator_req(vreg, set);
- prev_req[0].value = vreg->req[0].value;
- prev_req[1].value = vreg->req[1].value;
- }
- } else if (msm_rpm_vreg_debug_mask & MSM_RPM_VREG_DEBUG_DUPLICATE) {
- rpm_regulator_duplicate(vreg, set, cnt);
- }
-
- return rc;
-}
-
-static int vreg_set_noirq(struct vreg *vreg, enum rpm_vreg_voter voter,
- int sleep, unsigned mask0, unsigned val0,
- unsigned mask1, unsigned val1, unsigned cnt,
- int update_voltage)
-{
- unsigned int s_mask[2] = {mask0, mask1}, s_val[2] = {val0, val1};
- unsigned long flags;
- int rc;
-
- if (voter < 0 || voter >= RPM_VREG_VOTER_COUNT)
- return -EINVAL;
-
- spin_lock_irqsave(&pm8921_noirq_lock, flags);
-
- /*
- * Send sleep set request first so that subsequent set_mode, etc calls
- * use the voltage from the active set.
- */
- if (sleep)
- rc = vreg_send_request(vreg, voter, MSM_RPM_CTX_SET_SLEEP,
- mask0, val0, mask1, val1, cnt, update_voltage);
- else {
- /*
- * Vote for 0 V in the sleep set when active set-only is
- * specified. This ensures that a disable vote will be issued
- * at some point for the sleep set of the regulator.
- */
- if (vreg->part->uV.mask) {
- s_val[vreg->part->uV.word] = 0 << vreg->part->uV.shift;
- s_mask[vreg->part->uV.word] = vreg->part->uV.mask;
- } else {
- s_val[vreg->part->mV.word] = 0 << vreg->part->mV.shift;
- s_mask[vreg->part->mV.word] = vreg->part->mV.mask;
- }
-
- rc = vreg_send_request(vreg, voter, MSM_RPM_CTX_SET_SLEEP,
- s_mask[0], s_val[0], s_mask[1], s_val[1],
- cnt, update_voltage);
- }
-
- rc = vreg_send_request(vreg, voter, MSM_RPM_CTX_SET_0, mask0, val0,
- mask1, val1, cnt, update_voltage);
-
- spin_unlock_irqrestore(&pm8921_noirq_lock, flags);
-
- return rc;
-}
-
-/**
- * rpm_vreg_set_voltage - vote for a min_uV value of specified regualtor
- * @vreg: ID for regulator
- * @voter: ID for the voter
- * @min_uV: minimum acceptable voltage (in uV) that is voted for
- * @max_uV: maximum acceptable voltage (in uV) that is voted for
- * @sleep_also: 0 for active set only, non-0 for active set and sleep set
- *
- * Returns 0 on success or errno.
- *
- * This function is used to vote for the voltage of a regulator without
- * using the regulator framework. It is needed by consumers which hold spin
- * locks or have interrupts disabled because the regulator framework can sleep.
- * It is also needed by consumers which wish to only vote for active set
- * regulator voltage.
- *
- * If sleep_also == 0, then a sleep-set value of 0V will be voted for.
- *
- * This function may only be called for regulators which have the sleep flag
- * specified in their private data.
- */
-int rpm_vreg_set_voltage(enum rpm_vreg_id vreg_id, enum rpm_vreg_voter voter,
- int min_uV, int max_uV, int sleep_also)
-{
- unsigned int mask[2] = {0}, val[2] = {0};
- struct vreg_range *range;
- struct vreg *vreg;
- int uV = min_uV;
- int lim_min_uV, lim_max_uV, i, rc;
-
- if (vreg_id < 0 || vreg_id > RPM_VREG_ID_PM8921_MAX_REAL) {
- pr_err("invalid regulator id=%d\n", vreg_id);
- return -EINVAL;
- }
-
- /*
- * TODO: make this function a no-op for 8064 so that it can be called by
- * consumers on 8064 before RPM capabilities are present. (needed for
- * acpuclock driver)
- */
- if (cpu_is_apq8064())
- return 0;
-
- vreg = &vregs[vreg_id];
- range = &vreg->set_points->range[0];
-
- if (!vreg->pdata.sleep_selectable) {
- vreg_err(vreg, "regulator is not marked sleep selectable\n");
- return -EINVAL;
- }
-
- /*
- * Check if request voltage is outside of allowed range. The regulator
- * core has already checked that constraint range is inside of the
- * physically allowed range.
- */
- lim_min_uV = vreg->pdata.init_data.constraints.min_uV;
- lim_max_uV = vreg->pdata.init_data.constraints.max_uV;
-
- if (uV < lim_min_uV && max_uV >= lim_min_uV)
- uV = lim_min_uV;
-
- if (uV < lim_min_uV || uV > lim_max_uV) {
- vreg_err(vreg,
- "request v=[%d, %d] is outside allowed v=[%d, %d]\n",
- min_uV, max_uV, lim_min_uV, lim_max_uV);
- return -EINVAL;
- }
-
- /* Find the range which uV is inside of. */
- for (i = vreg->set_points->count - 1; i > 0; i--) {
- if (uV > vreg->set_points->range[i - 1].max_uV) {
- range = &vreg->set_points->range[i];
- break;
- }
- }
-
- /*
- * Force uV to be an allowed set point and apply a ceiling function
- * to non-set point values.
- */
- uV = (uV - range->min_uV + range->step_uV - 1) / range->step_uV;
- uV = uV * range->step_uV + range->min_uV;
-
- if (vreg->part->uV.mask) {
- val[vreg->part->uV.word] = uV << vreg->part->uV.shift;
- mask[vreg->part->uV.word] = vreg->part->uV.mask;
- } else {
- val[vreg->part->mV.word]
- = MICRO_TO_MILLI(uV) << vreg->part->mV.shift;
- mask[vreg->part->mV.word] = vreg->part->mV.mask;
- }
-
- rc = vreg_set_noirq(vreg, voter, sleep_also, mask[0], val[0], mask[1],
- val[1], vreg->part->request_len, 1);
- if (rc)
- vreg_err(vreg, "vreg_set_noirq failed, rc=%d\n", rc);
-
- return rc;
-}
-EXPORT_SYMBOL_GPL(rpm_vreg_set_voltage);
-
-/**
- * rpm_vreg_set_frequency - sets the frequency of a switching regulator
- * @vreg: ID for regulator
- * @freq: enum corresponding to desired frequency
- *
- * Returns 0 on success or errno.
- */
-int rpm_vreg_set_frequency(enum rpm_vreg_id vreg_id, enum rpm_vreg_freq freq)
-{
- unsigned int mask[2] = {0}, val[2] = {0};
- struct vreg *vreg;
- int rc;
-
- if (vreg_id < 0 || vreg_id > RPM_VREG_ID_PM8921_MAX_REAL) {
- pr_err("invalid regulator id=%d\n", vreg_id);
- return -EINVAL;
- }
-
- /*
- * TODO: make this function a no-op for 8064 so that it can be called by
- * consumers on 8064 before RPM capabilities are present.
- */
- if (cpu_is_apq8064())
- return 0;
-
- vreg = &vregs[vreg_id];
-
- if (freq < 0 || freq > RPM_VREG_FREQ_1p20) {
- vreg_err(vreg, "invalid frequency=%d\n", freq);
- return -EINVAL;
- }
- if (!vreg->pdata.sleep_selectable) {
- vreg_err(vreg, "regulator is not marked sleep selectable\n");
- return -EINVAL;
- }
- if (!vreg->part->freq.mask) {
- vreg_err(vreg, "frequency not supported\n");
- return -EINVAL;
- }
-
- val[vreg->part->freq.word] = freq << vreg->part->freq.shift;
- mask[vreg->part->freq.word] = vreg->part->freq.mask;
-
- rc = vreg_set_noirq(vreg, RPM_VREG_VOTER_REG_FRAMEWORK, 1, mask[0],
- val[0], mask[1], val[1], vreg->part->request_len, 0);
- if (rc)
- vreg_err(vreg, "vreg_set failed, rc=%d\n", rc);
-
- return rc;
-}
-EXPORT_SYMBOL_GPL(rpm_vreg_set_frequency);
-
-static inline int vreg_hpm_min_uA(struct vreg *vreg)
-{
- return vreg->hpm_min_load;
-}
-
-static inline int vreg_lpm_max_uA(struct vreg *vreg)
-{
- return vreg->hpm_min_load - LOAD_THRESHOLD_STEP;
-}
-
-static inline unsigned saturate_peak_load(struct vreg *vreg, unsigned load_uA)
-{
- unsigned load_max
- = MILLI_TO_MICRO(vreg->part->ip.mask >> vreg->part->ip.shift);
-
- return (load_uA > load_max ? load_max : load_uA);
-}
-
-static inline unsigned saturate_avg_load(struct vreg *vreg, unsigned load_uA)
-{
- unsigned load_max
- = MILLI_TO_MICRO(vreg->part->ia.mask >> vreg->part->ia.shift);
- return (load_uA > load_max ? load_max : load_uA);
-}
-
-/* Change vreg->req, but do not send it to the RPM. */
-static int vreg_store(struct vreg *vreg, unsigned mask0, unsigned val0,
- unsigned mask1, unsigned val1)
-{
- unsigned long flags = 0;
-
- if (vreg->pdata.sleep_selectable)
- spin_lock_irqsave(&pm8921_noirq_lock, flags);
-
- vreg->req[0].value &= ~mask0;
- vreg->req[0].value |= val0 & mask0;
-
- vreg->req[1].value &= ~mask1;
- vreg->req[1].value |= val1 & mask1;
-
- if (vreg->pdata.sleep_selectable)
- spin_unlock_irqrestore(&pm8921_noirq_lock, flags);
-
- return 0;
-}
-
-static int vreg_set(struct vreg *vreg, unsigned mask0, unsigned val0,
- unsigned mask1, unsigned val1, unsigned cnt)
-{
- unsigned prev0 = 0, prev1 = 0;
- int rc;
-
- /*
- * Bypass the normal route for regulators that can be called to change
- * just the active set values.
- */
- if (vreg->pdata.sleep_selectable)
- return vreg_set_noirq(vreg, RPM_VREG_VOTER_REG_FRAMEWORK, 1,
- mask0, val0, mask1, val1, cnt, 1);
-
- prev0 = vreg->req[0].value;
- vreg->req[0].value &= ~mask0;
- vreg->req[0].value |= val0 & mask0;
-
- prev1 = vreg->req[1].value;
- vreg->req[1].value &= ~mask1;
- vreg->req[1].value |= val1 & mask1;
-
- /* Ignore duplicate requests */
- if (vreg->req[0].value == vreg->prev_active_req[0].value &&
- vreg->req[1].value == vreg->prev_active_req[1].value) {
- if (msm_rpm_vreg_debug_mask & MSM_RPM_VREG_DEBUG_DUPLICATE)
- rpm_regulator_duplicate(vreg, MSM_RPM_CTX_SET_0, cnt);
- return 0;
- }
-
- rc = msm_rpm_set(MSM_RPM_CTX_SET_0, vreg->req, cnt);
- if (rc) {
- vreg->req[0].value = prev0;
- vreg->req[1].value = prev1;
-
- vreg_err(vreg, "msm_rpm_set failed, set=active, id=%d, rc=%d\n",
- vreg->req[0].id, rc);
- } else {
- if (msm_rpm_vreg_debug_mask & MSM_RPM_VREG_DEBUG_REQUEST)
- rpm_regulator_req(vreg, MSM_RPM_CTX_SET_0);
- vreg->prev_active_req[0].value = vreg->req[0].value;
- vreg->prev_active_req[1].value = vreg->req[1].value;
- }
-
- return rc;
-}
-
-static int vreg_is_enabled(struct regulator_dev *rdev)
-{
- struct vreg *vreg = rdev_get_drvdata(rdev);
- int enabled;
-
- mutex_lock(&vreg->pc_lock);
- enabled = vreg->is_enabled;
- mutex_unlock(&vreg->pc_lock);
-
- return enabled;
-}
-
-static void set_enable(struct vreg *vreg, unsigned int *mask, unsigned int *val)
-{
- switch (vreg->type) {
- case REGULATOR_TYPE_LDO:
- case REGULATOR_TYPE_SMPS:
- /* Enable by setting a voltage. */
- if (vreg->part->uV.mask) {
- val[vreg->part->uV.word]
- |= vreg->save_uV << vreg->part->uV.shift;
- mask[vreg->part->uV.word] |= vreg->part->uV.mask;
- } else {
- val[vreg->part->mV.word]
- |= MICRO_TO_MILLI(vreg->save_uV)
- << vreg->part->mV.shift;
- mask[vreg->part->mV.word] |= vreg->part->mV.mask;
- }
- break;
- case REGULATOR_TYPE_VS:
- case REGULATOR_TYPE_NCP:
- /* Enable by setting enable_state. */
- val[vreg->part->enable_state.word]
- |= RPM_VREG_STATE_ON << vreg->part->enable_state.shift;
- mask[vreg->part->enable_state.word]
- |= vreg->part->enable_state.mask;
- }
-}
-
-static int vreg_enable(struct regulator_dev *rdev)
-{
- struct vreg *vreg = rdev_get_drvdata(rdev);
- unsigned int mask[2] = {0}, val[2] = {0};
- int rc = 0;
-
- set_enable(vreg, mask, val);
-
- mutex_lock(&vreg->pc_lock);
-
- rc = vreg_set(vreg, mask[0], val[0], mask[1], val[1],
- vreg->part->request_len);
- if (!rc)
- vreg->is_enabled = true;
-
- mutex_unlock(&vreg->pc_lock);
-
- if (rc)
- vreg_err(vreg, "vreg_set failed, rc=%d\n", rc);
-
- return rc;
-}
-
-static void set_disable(struct vreg *vreg, unsigned int *mask,
- unsigned int *val)
-{
- switch (vreg->type) {
- case REGULATOR_TYPE_LDO:
- case REGULATOR_TYPE_SMPS:
- /* Disable by setting a voltage of 0 uV. */
- if (vreg->part->uV.mask) {
- val[vreg->part->uV.word] |= 0 << vreg->part->uV.shift;
- mask[vreg->part->uV.word] |= vreg->part->uV.mask;
- } else {
- val[vreg->part->mV.word] |= 0 << vreg->part->mV.shift;
- mask[vreg->part->mV.word] |= vreg->part->mV.mask;
- }
- break;
- case REGULATOR_TYPE_VS:
- case REGULATOR_TYPE_NCP:
- /* Disable by setting enable_state. */
- val[vreg->part->enable_state.word]
- |= RPM_VREG_STATE_OFF << vreg->part->enable_state.shift;
- mask[vreg->part->enable_state.word]
- |= vreg->part->enable_state.mask;
- }
-}
-
-static int vreg_disable(struct regulator_dev *rdev)
-{
- struct vreg *vreg = rdev_get_drvdata(rdev);
- unsigned int mask[2] = {0}, val[2] = {0};
- int rc = 0;
-
- set_disable(vreg, mask, val);
-
- mutex_lock(&vreg->pc_lock);
-
- /* Only disable if pin control is not in use. */
- if (!vreg->is_enabled_pc)
- rc = vreg_set(vreg, mask[0], val[0], mask[1], val[1],
- vreg->part->request_len);
-
- if (!rc)
- vreg->is_enabled = false;
-
- mutex_unlock(&vreg->pc_lock);
-
- if (rc)
- vreg_err(vreg, "vreg_set failed, rc=%d\n", rc);
-
- return rc;
-}
-
-static int vreg_set_voltage(struct regulator_dev *rdev, int min_uV, int max_uV,
- unsigned *selector)
-{
- struct vreg *vreg = rdev_get_drvdata(rdev);
- struct vreg_range *range = &vreg->set_points->range[0];
- unsigned int mask[2] = {0}, val[2] = {0};
- int rc = 0, uV = min_uV;
- int lim_min_uV, lim_max_uV, i;
-
- /* Check if request voltage is outside of physically settable range. */
- lim_min_uV = vreg->set_points->range[0].min_uV;
- lim_max_uV =
- vreg->set_points->range[vreg->set_points->count - 1].max_uV;
-
- if (uV < lim_min_uV && max_uV >= lim_min_uV)
- uV = lim_min_uV;
-
- if (uV < lim_min_uV || uV > lim_max_uV) {
- vreg_err(vreg,
- "request v=[%d, %d] is outside possible v=[%d, %d]\n",
- min_uV, max_uV, lim_min_uV, lim_max_uV);
- return -EINVAL;
- }
-
- /* Find the range which uV is inside of. */
- for (i = vreg->set_points->count - 1; i > 0; i--) {
- if (uV > vreg->set_points->range[i - 1].max_uV) {
- range = &vreg->set_points->range[i];
- break;
- }
- }
-
- /*
- * Force uV to be an allowed set point and apply a ceiling function
- * to non-set point values.
- */
- uV = (uV - range->min_uV + range->step_uV - 1) / range->step_uV;
- uV = uV * range->step_uV + range->min_uV;
-
- if (vreg->part->uV.mask) {
- val[vreg->part->uV.word] = uV << vreg->part->uV.shift;
- mask[vreg->part->uV.word] = vreg->part->uV.mask;
- } else {
- val[vreg->part->mV.word]
- = MICRO_TO_MILLI(uV) << vreg->part->mV.shift;
- mask[vreg->part->mV.word] = vreg->part->mV.mask;
- }
-
- mutex_lock(&vreg->pc_lock);
-
- /*
- * Only send a request for a new voltage if the regulator is currently
- * enabled. This will ensure that LDO and SMPS regulators are not
- * inadvertently turned on because voltage > 0 is equivalent to
- * enabling. For NCP, this just removes unnecessary RPM requests.
- */
- if (vreg->is_enabled) {
- rc = vreg_set(vreg, mask[0], val[0], mask[1], val[1],
- vreg->part->request_len);
- if (rc)
- vreg_err(vreg, "vreg_set failed, rc=%d\n", rc);
- } else if (vreg->type == REGULATOR_TYPE_NCP) {
- /* Regulator is disabled; store but don't send new request. */
- rc = vreg_store(vreg, mask[0], val[0], mask[1], val[1]);
- }
-
- if (!rc && (!vreg->pdata.sleep_selectable || !vreg->is_enabled))
- vreg->save_uV = uV;
-
- mutex_unlock(&vreg->pc_lock);
-
- return rc;
-}
-
-static int vreg_get_voltage(struct regulator_dev *rdev)
-{
- struct vreg *vreg = rdev_get_drvdata(rdev);
-
- return vreg->save_uV;
-}
-
-static int vreg_list_voltage(struct regulator_dev *rdev, unsigned selector)
-{
- struct vreg *vreg = rdev_get_drvdata(rdev);
- int uV = 0;
- int i;
-
- if (!vreg->set_points) {
- vreg_err(vreg, "no voltages available\n");
- return -EINVAL;
- }
-
- if (selector >= vreg->set_points->n_voltages)
- return 0;
-
- for (i = 0; i < vreg->set_points->count; i++) {
- if (selector < vreg->set_points->range[i].n_voltages) {
- uV = selector * vreg->set_points->range[i].step_uV
- + vreg->set_points->range[i].min_uV;
- break;
- } else {
- selector -= vreg->set_points->range[i].n_voltages;
- }
- }
-
- return uV;
-}
-
-static int vreg_set_mode(struct regulator_dev *rdev, unsigned int mode)
-{
- struct vreg *vreg = rdev_get_drvdata(rdev);
- unsigned int mask[2] = {0}, val[2] = {0};
- int rc = 0;
- int peak_uA;
-
- mutex_lock(&vreg->pc_lock);
-
- peak_uA = MILLI_TO_MICRO((vreg->req[vreg->part->ip.word].value
- & vreg->part->ip.mask) >> vreg->part->ip.shift);
-
- switch (mode) {
- case REGULATOR_MODE_NORMAL:
- /* Make sure that request currents are in HPM range. */
- if (peak_uA < vreg_hpm_min_uA(vreg)) {
- val[vreg->part->ip.word]
- = MICRO_TO_MILLI(vreg_hpm_min_uA(vreg))
- << vreg->part->ip.shift;
- mask[vreg->part->ip.word] = vreg->part->ip.mask;
- }
- break;
- case REGULATOR_MODE_IDLE:
- /* Make sure that request currents are in LPM range. */
- if (peak_uA > vreg_lpm_max_uA(vreg)) {
- val[vreg->part->ip.word]
- = MICRO_TO_MILLI(vreg_lpm_max_uA(vreg))
- << vreg->part->ip.shift;
- mask[vreg->part->ip.word] = vreg->part->ip.mask;
- }
- break;
- default:
- vreg_err(vreg, "invalid mode: %u\n", mode);
- mutex_unlock(&vreg->pc_lock);
- return -EINVAL;
- }
-
- if (vreg->is_enabled) {
- rc = vreg_set(vreg, mask[0], val[0], mask[1], val[1],
- vreg->part->request_len);
- } else {
- /* Regulator is disabled; store but don't send new request. */
- rc = vreg_store(vreg, mask[0], val[0], mask[1], val[1]);
- }
-
- if (rc)
- vreg_err(vreg, "vreg_set failed, rc=%d\n", rc);
- else
- vreg->mode = mode;
-
- mutex_unlock(&vreg->pc_lock);
-
- return rc;
-}
-
-static unsigned int vreg_get_mode(struct regulator_dev *rdev)
-{
- struct vreg *vreg = rdev_get_drvdata(rdev);
-
- return vreg->mode;
-}
-
-static unsigned int vreg_get_optimum_mode(struct regulator_dev *rdev,
- int input_uV, int output_uV, int load_uA)
-{
- struct vreg *vreg = rdev_get_drvdata(rdev);
- unsigned int mode;
-
- load_uA += vreg->pdata.system_uA;
-
- mutex_lock(&vreg->pc_lock);
- SET_PART(vreg, ip, MICRO_TO_MILLI(saturate_peak_load(vreg, load_uA)));
- mutex_unlock(&vreg->pc_lock);
-
- if (load_uA >= vreg->hpm_min_load)
- mode = REGULATOR_MODE_NORMAL;
- else
- mode = REGULATOR_MODE_IDLE;
-
- return mode;
-}
-
-/*
- * Returns the logical pin control enable state because the pin control options
- * present in the hardware out of restart could be different from those desired
- * by the consumer.
- */
-static int vreg_pin_control_is_enabled(struct regulator_dev *rdev)
-{
- struct vreg *vreg = rdev_get_drvdata(rdev);
-
- return vreg->is_enabled_pc;
-}
-
-static int vreg_pin_control_enable(struct regulator_dev *rdev)
-{
- struct vreg *vreg = rdev_get_drvdata(rdev);
- unsigned int mask[2] = {0}, val[2] = {0};
- int rc;
-
- mutex_lock(&vreg->pc_lock);
-
- val[vreg->part->pc.word]
- |= vreg->pdata.pin_ctrl << vreg->part->pc.shift;
- mask[vreg->part->pc.word] |= vreg->part->pc.mask;
-
- val[vreg->part->pf.word] |= vreg->pdata.pin_fn << vreg->part->pf.shift;
- mask[vreg->part->pf.word] |= vreg->part->pf.mask;
-
- if (!vreg->is_enabled)
- set_enable(vreg, mask, val);
-
- rc = vreg_set(vreg, mask[0], val[0], mask[1], val[1],
- vreg->part->request_len);
-
- if (!rc)
- vreg->is_enabled_pc = true;
-
- mutex_unlock(&vreg->pc_lock);
-
- if (rc)
- vreg_err(vreg, "vreg_set failed, rc=%d\n", rc);
-
- return rc;
-}
-
-static int vreg_pin_control_disable(struct regulator_dev *rdev)
-{
- struct vreg *vreg = rdev_get_drvdata(rdev);
- unsigned int mask[2] = {0}, val[2] = {0};
- enum rpm_vreg_pin_fn pin_fn;
- int rc;
-
- mutex_lock(&vreg->pc_lock);
-
- val[vreg->part->pc.word]
- |= RPM_VREG_PIN_CTRL_NONE << vreg->part->pc.shift;
- mask[vreg->part->pc.word] |= vreg->part->pc.mask;
-
- pin_fn = RPM_VREG_PIN_FN_NONE;
- if (vreg->pdata.pin_fn == RPM_VREG_PIN_FN_SLEEP_B)
- pin_fn = RPM_VREG_PIN_FN_SLEEP_B;
- val[vreg->part->pf.word] |= pin_fn << vreg->part->pf.shift;
- mask[vreg->part->pf.word] |= vreg->part->pf.mask;
-
- if (!vreg->is_enabled)
- set_disable(vreg, mask, val);
-
- rc = vreg_set(vreg, mask[0], val[0], mask[1], val[1],
- vreg->part->request_len);
-
- if (!rc)
- vreg->is_enabled_pc = false;
-
- mutex_unlock(&vreg->pc_lock);
-
- if (rc)
- vreg_err(vreg, "vreg_set failed, rc=%d\n", rc);
-
- return rc;
-}
-
-/* Real regulator operations. */
-static struct regulator_ops ldo_ops = {
- .enable = vreg_enable,
- .disable = vreg_disable,
- .is_enabled = vreg_is_enabled,
- .set_voltage = vreg_set_voltage,
- .get_voltage = vreg_get_voltage,
- .list_voltage = vreg_list_voltage,
- .set_mode = vreg_set_mode,
- .get_mode = vreg_get_mode,
- .get_optimum_mode = vreg_get_optimum_mode,
+static const char *pin_control_label[] = {
+ " D1",
+ " A0",
+ " A1",
+ " A2",
};
-static struct regulator_ops smps_ops = {
- .enable = vreg_enable,
- .disable = vreg_disable,
- .is_enabled = vreg_is_enabled,
- .set_voltage = vreg_set_voltage,
- .get_voltage = vreg_get_voltage,
- .list_voltage = vreg_list_voltage,
- .set_mode = vreg_set_mode,
- .get_mode = vreg_get_mode,
- .get_optimum_mode = vreg_get_optimum_mode,
-};
-
-static struct regulator_ops switch_ops = {
- .enable = vreg_enable,
- .disable = vreg_disable,
- .is_enabled = vreg_is_enabled,
-};
-
-static struct regulator_ops ncp_ops = {
- .enable = vreg_enable,
- .disable = vreg_disable,
- .is_enabled = vreg_is_enabled,
- .set_voltage = vreg_set_voltage,
- .get_voltage = vreg_get_voltage,
- .list_voltage = vreg_list_voltage,
-};
-
-/* Pin control regulator operations. */
-static struct regulator_ops pin_control_ops = {
- .enable = vreg_pin_control_enable,
- .disable = vreg_pin_control_disable,
- .is_enabled = vreg_pin_control_is_enabled,
-};
-
-#define VREG_DESC(_id, _name, _ops) \
- [RPM_VREG_ID_PM8921_##_id] = { \
- .id = RPM_VREG_ID_PM8921_##_id, \
- .name = _name, \
- .ops = _ops, \
- .type = REGULATOR_VOLTAGE, \
- .owner = THIS_MODULE, \
- }
-
-static struct regulator_desc vreg_description[] = {
- VREG_DESC(L1, "8921_l1", &ldo_ops),
- VREG_DESC(L2, "8921_l2", &ldo_ops),
- VREG_DESC(L3, "8921_l3", &ldo_ops),
- VREG_DESC(L4, "8921_l4", &ldo_ops),
- VREG_DESC(L5, "8921_l5", &ldo_ops),
- VREG_DESC(L6, "8921_l6", &ldo_ops),
- VREG_DESC(L7, "8921_l7", &ldo_ops),
- VREG_DESC(L8, "8921_l8", &ldo_ops),
- VREG_DESC(L9, "8921_l9", &ldo_ops),
- VREG_DESC(L10, "8921_l10", &ldo_ops),
- VREG_DESC(L11, "8921_l11", &ldo_ops),
- VREG_DESC(L12, "8921_l12", &ldo_ops),
- VREG_DESC(L14, "8921_l14", &ldo_ops),
- VREG_DESC(L15, "8921_l15", &ldo_ops),
- VREG_DESC(L16, "8921_l16", &ldo_ops),
- VREG_DESC(L17, "8921_l17", &ldo_ops),
- VREG_DESC(L18, "8921_l18", &ldo_ops),
- VREG_DESC(L21, "8921_l21", &ldo_ops),
- VREG_DESC(L22, "8921_l22", &ldo_ops),
- VREG_DESC(L23, "8921_l23", &ldo_ops),
- VREG_DESC(L24, "8921_l24", &ldo_ops),
- VREG_DESC(L25, "8921_l25", &ldo_ops),
- VREG_DESC(L26, "8921_l26", &ldo_ops),
- VREG_DESC(L27, "8921_l27", &ldo_ops),
- VREG_DESC(L28, "8921_l28", &ldo_ops),
- VREG_DESC(L29, "8921_l29", &ldo_ops),
-
- VREG_DESC(S1, "8921_s1", &smps_ops),
- VREG_DESC(S2, "8921_s2", &smps_ops),
- VREG_DESC(S3, "8921_s3", &smps_ops),
- VREG_DESC(S4, "8921_s4", &smps_ops),
- VREG_DESC(S5, "8921_s5", &smps_ops),
- VREG_DESC(S6, "8921_s6", &smps_ops),
- VREG_DESC(S7, "8921_s7", &smps_ops),
- VREG_DESC(S8, "8921_s8", &smps_ops),
-
- VREG_DESC(LVS1, "8921_lvs1", &switch_ops),
- VREG_DESC(LVS2, "8921_lvs2", &switch_ops),
- VREG_DESC(LVS3, "8921_lvs3", &switch_ops),
- VREG_DESC(LVS4, "8921_lvs4", &switch_ops),
- VREG_DESC(LVS5, "8921_lvs5", &switch_ops),
- VREG_DESC(LVS6, "8921_lvs6", &switch_ops),
- VREG_DESC(LVS7, "8921_lvs7", &switch_ops),
-
- VREG_DESC(USB_OTG, "8921_usb_otg", &switch_ops),
- VREG_DESC(HDMI_MVS, "8921_hdmi_mvs", &switch_ops),
- VREG_DESC(NCP, "8921_ncp", &ncp_ops),
-
- VREG_DESC(L1_PC, "8921_l1_pc", &pin_control_ops),
- VREG_DESC(L2_PC, "8921_l2_pc", &pin_control_ops),
- VREG_DESC(L3_PC, "8921_l3_pc", &pin_control_ops),
- VREG_DESC(L4_PC, "8921_l4_pc", &pin_control_ops),
- VREG_DESC(L5_PC, "8921_l5_pc", &pin_control_ops),
- VREG_DESC(L6_PC, "8921_l6_pc", &pin_control_ops),
- VREG_DESC(L7_PC, "8921_l7_pc", &pin_control_ops),
- VREG_DESC(L8_PC, "8921_l8_pc", &pin_control_ops),
- VREG_DESC(L9_PC, "8921_l9_pc", &pin_control_ops),
- VREG_DESC(L10_PC, "8921_l10_pc", &pin_control_ops),
- VREG_DESC(L11_PC, "8921_l11_pc", &pin_control_ops),
- VREG_DESC(L12_PC, "8921_l12_pc", &pin_control_ops),
- VREG_DESC(L14_PC, "8921_l14_pc", &pin_control_ops),
- VREG_DESC(L15_PC, "8921_l15_pc", &pin_control_ops),
- VREG_DESC(L16_PC, "8921_l16_pc", &pin_control_ops),
- VREG_DESC(L17_PC, "8921_l17_pc", &pin_control_ops),
- VREG_DESC(L18_PC, "8921_l18_pc", &pin_control_ops),
- VREG_DESC(L21_PC, "8921_l21_pc", &pin_control_ops),
- VREG_DESC(L22_PC, "8921_l22_pc", &pin_control_ops),
- VREG_DESC(L23_PC, "8921_l23_pc", &pin_control_ops),
- VREG_DESC(L29_PC, "8921_l29_pc", &pin_control_ops),
-
- VREG_DESC(S1_PC, "8921_s1_pc", &pin_control_ops),
- VREG_DESC(S2_PC, "8921_s2_pc", &pin_control_ops),
- VREG_DESC(S3_PC, "8921_s3_pc", &pin_control_ops),
- VREG_DESC(S4_PC, "8921_s4_pc", &pin_control_ops),
- VREG_DESC(S7_PC, "8921_s7_pc", &pin_control_ops),
- VREG_DESC(S8_PC, "8921_s8_pc", &pin_control_ops),
-
- VREG_DESC(LVS1_PC, "8921_lvs1_pc", &pin_control_ops),
- VREG_DESC(LVS3_PC, "8921_lvs3_pc", &pin_control_ops),
- VREG_DESC(LVS4_PC, "8921_lvs4_pc", &pin_control_ops),
- VREG_DESC(LVS5_PC, "8921_lvs5_pc", &pin_control_ops),
- VREG_DESC(LVS6_PC, "8921_lvs6_pc", &pin_control_ops),
- VREG_DESC(LVS7_PC, "8921_lvs7_pc", &pin_control_ops),
-};
-
-static inline int is_real_regulator(int id)
+static int is_real_id(int id)
{
return (id >= 0) && (id <= RPM_VREG_ID_PM8921_MAX_REAL);
}
@@ -1431,237 +279,36 @@
return real_id;
}
-static int __devinit
-rpm_vreg_init_regulator(const struct rpm_regulator_init_data *pdata,
- struct device *dev)
-{
- enum rpm_vreg_pin_fn pin_fn;
- struct regulator_desc *rdesc;
- struct regulator_dev *rdev;
- struct vreg *vreg;
- const char *reg_name = "";
- unsigned pin_ctrl;
- int rc = 0, id = pdata->id;
+static struct vreg_config config = {
+ .vregs = vregs,
+ .vregs_len = ARRAY_SIZE(vregs),
- if (id < 0 || id > RPM_VREG_ID_PM8921_MAX) {
- pr_err("invalid regulator id: %d\n", id);
- return -ENODEV;
- }
+ .vreg_id_min = RPM_VREG_ID_PM8921_L1,
+ .vreg_id_max = RPM_VREG_ID_PM8921_MAX,
- rdesc = &vreg_description[pdata->id];
- if (!is_real_regulator(pdata->id))
- id = pc_id_to_real_id(pdata->id);
- vreg = &vregs[id];
- reg_name = vreg_description[pdata->id].name;
- if (!pdata) {
- pr_err("%s: requires platform data\n", reg_name);
- return -EINVAL;
- }
- if (vreg->set_points)
- rdesc->n_voltages = vreg->set_points->n_voltages;
- else
- rdesc->n_voltages = 0;
+ .pin_func_none = RPM_VREG_PIN_FN_8960_NONE,
+ .pin_func_sleep_b = RPM_VREG_PIN_FN_8960_SLEEP_B,
- mutex_lock(&vreg->pc_lock);
+ .mode_lpm = REGULATOR_MODE_IDLE,
+ .mode_hpm = REGULATOR_MODE_NORMAL,
- if (is_real_regulator(pdata->id)) {
- /* Do not modify pin control and pin function values. */
- pin_ctrl = vreg->pdata.pin_ctrl;
- pin_fn = vreg->pdata.pin_fn;
- memcpy(&(vreg->pdata), pdata,
- sizeof(struct rpm_regulator_init_data));
- vreg->pdata.pin_ctrl = pin_ctrl;
- vreg->pdata.pin_fn = pin_fn;
- vreg->name = reg_name;
+ .set_points = all_set_points,
+ .set_points_len = ARRAY_SIZE(all_set_points),
- vreg->save_uV = vreg->pdata.default_uV;
- if (vreg->pdata.peak_uA >= vreg->hpm_min_load)
- vreg->mode = REGULATOR_MODE_NORMAL;
- else
- vreg->mode = REGULATOR_MODE_IDLE;
+ .label_pin_ctrl = pin_control_label,
+ .label_pin_ctrl_len = ARRAY_SIZE(pin_control_label),
+ .label_pin_func = pin_func_label,
+ .label_pin_func_len = ARRAY_SIZE(pin_func_label),
+ .label_force_mode = force_mode_label,
+ .label_force_mode_len = ARRAY_SIZE(force_mode_label),
+ .label_power_mode = power_mode_label,
+ .label_power_mode_len = ARRAY_SIZE(power_mode_label),
- /* Initialize the RPM request. */
- SET_PART(vreg, ip,
- MICRO_TO_MILLI(saturate_peak_load(vreg, vreg->pdata.peak_uA)));
- SET_PART(vreg, fm, vreg->pdata.force_mode);
- SET_PART(vreg, pm, vreg->pdata.power_mode);
- SET_PART(vreg, pd, vreg->pdata.pull_down_enable);
- SET_PART(vreg, ia,
- MICRO_TO_MILLI(saturate_avg_load(vreg, vreg->pdata.avg_uA)));
- SET_PART(vreg, freq, vreg->pdata.freq);
- SET_PART(vreg, freq_clk_src, 0);
- SET_PART(vreg, comp_mode, 0);
- SET_PART(vreg, hpm, 0);
- if (!vreg->is_enabled_pc) {
- SET_PART(vreg, pf, RPM_VREG_PIN_FN_NONE);
- SET_PART(vreg, pc, RPM_VREG_PIN_CTRL_NONE);
- }
- } else {
- /* Pin control regulator */
- if ((pdata->pin_ctrl & RPM_VREG_PIN_CTRL_ALL)
- == RPM_VREG_PIN_CTRL_NONE
- && pdata->pin_fn != RPM_VREG_PIN_FN_SLEEP_B) {
- pr_err("%s: no pin control input specified\n",
- reg_name);
- mutex_unlock(&vreg->pc_lock);
- return -EINVAL;
- }
- vreg->pdata.pin_ctrl = pdata->pin_ctrl;
- vreg->pdata.pin_fn = pdata->pin_fn;
- if (!vreg->name)
- vreg->name = reg_name;
-
- /* Initialize the RPM request. */
- pin_fn = RPM_VREG_PIN_FN_NONE;
- /* Allow pf=sleep_b to be specified by platform data. */
- if (vreg->pdata.pin_fn == RPM_VREG_PIN_FN_SLEEP_B)
- pin_fn = RPM_VREG_PIN_FN_SLEEP_B;
- SET_PART(vreg, pf, pin_fn);
- SET_PART(vreg, pc, RPM_VREG_PIN_CTRL_NONE);
- }
-
- mutex_unlock(&vreg->pc_lock);
-
- if (rc)
- goto bail;
-
- rdev = regulator_register(rdesc, dev, &(pdata->init_data), vreg);
- if (IS_ERR(rdev)) {
- rc = PTR_ERR(rdev);
- pr_err("regulator_register failed: %s, rc=%d\n", reg_name, rc);
- return rc;
- } else {
- if (is_real_regulator(pdata->id))
- vreg->rdev = rdev;
- else
- vreg->rdev_pc = rdev;
- }
-
-bail:
- if (rc)
- pr_err("error for %s, rc=%d\n", reg_name, rc);
-
- return rc;
-}
-
-static int __devinit rpm_vreg_probe(struct platform_device *pdev)
-{
- struct rpm_regulator_platform_data *platform_data;
- int rc = 0;
- int i;
-
- platform_data = pdev->dev.platform_data;
- if (!platform_data) {
- pr_err("rpm-regulator requires platform data\n");
- return -EINVAL;
- }
-
- /* Initialize all of the regulators listed in the platform data. */
- for (i = 0; i < platform_data->num_regulators; i++) {
- rc = rpm_vreg_init_regulator(&platform_data->init_data[i],
- &pdev->dev);
- if (rc) {
- pr_err("rpm_vreg_init_regulator failed, rc=%d\n", rc);
- goto remove_regulators;
- }
- }
-
- platform_set_drvdata(pdev, platform_data);
-
- return rc;
-
-remove_regulators:
- /* Unregister all regulators added before the erroring one. */
- for (; i >= 0; i--) {
- if (is_real_regulator(platform_data->init_data[i].id))
- regulator_unregister(vregs[i].rdev);
- else
- regulator_unregister(
- vregs[pc_id_to_real_id(i)].rdev_pc);
- }
-
- return rc;
-}
-
-static int __devexit rpm_vreg_remove(struct platform_device *pdev)
-{
- struct rpm_regulator_platform_data *platform_data;
- int i, id;
-
- platform_data = platform_get_drvdata(pdev);
- platform_set_drvdata(pdev, NULL);
-
- if (platform_data) {
- for (i = 0; i < platform_data->num_regulators; i++) {
- id = platform_data->init_data[i].id;
- if (is_real_regulator(id)) {
- regulator_unregister(vregs[id].rdev);
- vregs[id].rdev = NULL;
- } else {
- regulator_unregister(
- vregs[pc_id_to_real_id(id)].rdev_pc);
- vregs[id].rdev_pc = NULL;
- }
- }
- }
-
- return 0;
-}
-
-static struct platform_driver rpm_vreg_driver = {
- .probe = rpm_vreg_probe,
- .remove = __devexit_p(rpm_vreg_remove),
- .driver = {
- .name = RPM_REGULATOR_DEV_NAME,
- .owner = THIS_MODULE,
- },
+ .is_real_id = is_real_id,
+ .pc_id_to_real_id = pc_id_to_real_id,
};
-static int __init rpm_vreg_init(void)
+struct vreg_config *get_config_8960(void)
{
- struct vreg_set_points *set_points[] = {
- &pldo_set_points,
- &nldo_set_points,
- &nldo1200_set_points,
- &smps_set_points,
- &ftsmps_set_points,
- &ncp_set_points,
- };
- int i, j;
-
- /* Calculate the number of set points available for each regualtor. */
- for (i = 0; i < ARRAY_SIZE(set_points); i++) {
- for (j = 0; j < set_points[i]->count; j++) {
- set_points[i]->range[j].n_voltages
- = (set_points[i]->range[j].max_uV
- - set_points[i]->range[j].min_uV)
- / set_points[i]->range[j].step_uV + 1;
- set_points[i]->n_voltages
- += set_points[i]->range[j].n_voltages;
- }
- }
-
- /* Initialize pin control mutexes */
- for (i = 0; i < ARRAY_SIZE(vregs); i++)
- mutex_init(&vregs[i].pc_lock);
-
- return platform_driver_register(&rpm_vreg_driver);
+ return &config;
}
-
-static void __exit rpm_vreg_exit(void)
-{
- int i;
-
- platform_driver_unregister(&rpm_vreg_driver);
-
- for (i = 0; i < ARRAY_SIZE(vregs); i++)
- mutex_destroy(&vregs[i].pc_lock);
-}
-
-postcore_initcall(rpm_vreg_init);
-module_exit(rpm_vreg_exit);
-
-MODULE_LICENSE("GPL v2");
-MODULE_DESCRIPTION("MSM8960 rpm regulator driver");
-MODULE_VERSION("1.0");
-MODULE_ALIAS("platform:" RPM_REGULATOR_DEV_NAME);
diff --git a/arch/arm/mach-msm/rpm-regulator-9615.c b/arch/arm/mach-msm/rpm-regulator-9615.c
new file mode 100644
index 0000000..23c0ee3
--- /dev/null
+++ b/arch/arm/mach-msm/rpm-regulator-9615.c
@@ -0,0 +1,232 @@
+/*
+ * Copyright (c) 2011, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#define pr_fmt(fmt) "%s: " fmt, __func__
+
+#include "rpm-regulator-private.h"
+
+/* RPM regulator request formats */
+static struct rpm_vreg_parts ldo_parts = {
+ .request_len = 2,
+ .uV = REQUEST_MEMBER(0, 0x007FFFFF, 0),
+ .pd = REQUEST_MEMBER(0, 0x00800000, 23),
+ .pc = REQUEST_MEMBER(0, 0x0F000000, 24),
+ .pf = REQUEST_MEMBER(0, 0xF0000000, 28),
+ .ip = REQUEST_MEMBER(1, 0x000003FF, 0),
+ .ia = REQUEST_MEMBER(1, 0x000FFC00, 10),
+ .fm = REQUEST_MEMBER(1, 0x00700000, 20),
+};
+
+static struct rpm_vreg_parts smps_parts = {
+ .request_len = 2,
+ .uV = REQUEST_MEMBER(0, 0x007FFFFF, 0),
+ .pd = REQUEST_MEMBER(0, 0x00800000, 23),
+ .pc = REQUEST_MEMBER(0, 0x0F000000, 24),
+ .pf = REQUEST_MEMBER(0, 0xF0000000, 28),
+ .ip = REQUEST_MEMBER(1, 0x000003FF, 0),
+ .ia = REQUEST_MEMBER(1, 0x000FFC00, 10),
+ .fm = REQUEST_MEMBER(1, 0x00700000, 20),
+ .pm = REQUEST_MEMBER(1, 0x00800000, 23),
+ .freq = REQUEST_MEMBER(1, 0x1F000000, 24),
+ .freq_clk_src = REQUEST_MEMBER(1, 0x60000000, 29),
+};
+
+static struct rpm_vreg_parts switch_parts = {
+ .request_len = 1,
+ .enable_state = REQUEST_MEMBER(0, 0x00000001, 0),
+ .pd = REQUEST_MEMBER(0, 0x00000002, 1),
+ .pc = REQUEST_MEMBER(0, 0x0000003C, 2),
+ .pf = REQUEST_MEMBER(0, 0x000003C0, 6),
+ .hpm = REQUEST_MEMBER(0, 0x00000C00, 10),
+};
+
+/* Physically available PMIC regulator voltage setpoint ranges */
+static struct vreg_range pldo_ranges[] = {
+ VOLTAGE_RANGE( 750000, 1487500, 12500),
+ VOLTAGE_RANGE(1500000, 3075000, 25000),
+ VOLTAGE_RANGE(3100000, 4900000, 50000),
+};
+
+static struct vreg_range nldo_ranges[] = {
+ VOLTAGE_RANGE( 750000, 1537500, 12500),
+};
+
+static struct vreg_range nldo1200_ranges[] = {
+ VOLTAGE_RANGE( 375000, 743750, 6250),
+ VOLTAGE_RANGE( 750000, 1537500, 12500),
+};
+
+static struct vreg_range smps_ranges[] = {
+ VOLTAGE_RANGE( 375000, 737500, 12500),
+ VOLTAGE_RANGE( 750000, 1487500, 12500),
+ VOLTAGE_RANGE(1500000, 3075000, 25000),
+};
+
+static struct vreg_set_points pldo_set_points = SET_POINTS(pldo_ranges);
+static struct vreg_set_points nldo_set_points = SET_POINTS(nldo_ranges);
+static struct vreg_set_points nldo1200_set_points = SET_POINTS(nldo1200_ranges);
+static struct vreg_set_points smps_set_points = SET_POINTS(smps_ranges);
+
+static struct vreg_set_points *all_set_points[] = {
+ &pldo_set_points,
+ &nldo_set_points,
+ &nldo1200_set_points,
+ &smps_set_points,
+};
+
+#define LDO(_id, _name, _name_pc, _ranges, _hpm_min_load) \
+ [RPM_VREG_ID_PM8018_##_id] = { \
+ .req = { \
+ [0] = { .id = MSM_RPM_ID_PM8018_##_id##_0, }, \
+ [1] = { .id = MSM_RPM_ID_PM8018_##_id##_1, }, \
+ }, \
+ .hpm_min_load = RPM_VREG_9615_##_hpm_min_load##_HPM_MIN_LOAD, \
+ .type = RPM_REGULATOR_TYPE_LDO, \
+ .set_points = &_ranges##_set_points, \
+ .part = &ldo_parts, \
+ .id = RPM_VREG_ID_PM8018_##_id, \
+ .rdesc.name = _name, \
+ .rdesc_pc.name = _name_pc, \
+ }
+
+#define SMPS(_id, _name, _name_pc, _ranges, _hpm_min_load) \
+ [RPM_VREG_ID_PM8018_##_id] = { \
+ .req = { \
+ [0] = { .id = MSM_RPM_ID_PM8018_##_id##_0, }, \
+ [1] = { .id = MSM_RPM_ID_PM8018_##_id##_1, }, \
+ }, \
+ .hpm_min_load = RPM_VREG_9615_##_hpm_min_load##_HPM_MIN_LOAD, \
+ .type = RPM_REGULATOR_TYPE_SMPS, \
+ .set_points = &_ranges##_set_points, \
+ .part = &smps_parts, \
+ .id = RPM_VREG_ID_PM8018_##_id, \
+ .rdesc.name = _name, \
+ .rdesc_pc.name = _name_pc, \
+ }
+
+#define LVS(_id, _name, _name_pc) \
+ [RPM_VREG_ID_PM8018_##_id] = { \
+ .req = { \
+ [0] = { .id = MSM_RPM_ID_PM8018_##_id, }, \
+ [1] = { .id = -1, }, \
+ }, \
+ .type = RPM_REGULATOR_TYPE_VS, \
+ .part = &switch_parts, \
+ .id = RPM_VREG_ID_PM8018_##_id, \
+ .rdesc.name = _name, \
+ .rdesc_pc.name = _name_pc, \
+ }
+
+static struct vreg vregs[] = {
+ LDO(L2, "8018_l2", "8018_l2_pc", pldo, LDO_50),
+ LDO(L3, "8018_l3", "8018_l3_pc", pldo, LDO_50),
+ LDO(L4, "8018_l4", "8018_l4_pc", pldo, LDO_300),
+ LDO(L5, "8018_l5", "8018_l5_pc", pldo, LDO_150),
+ LDO(L6, "8018_l6", "8018_l6_pc", pldo, LDO_150),
+ LDO(L7, "8018_l7", "8018_l7_pc", pldo, LDO_300),
+ LDO(L8, "8018_l8", "8018_l8_pc", nldo, LDO_150),
+ LDO(L9, "8018_l9", NULL, nldo1200, LDO_1200),
+ LDO(L10, "8018_l10", NULL, nldo1200, LDO_1200),
+ LDO(L11, "8018_l11", NULL, nldo1200, LDO_1200),
+ LDO(L12, "8018_l12", NULL, nldo1200, LDO_1200),
+ LDO(L13, "8018_l13", "8018_l13_pc", pldo, LDO_50),
+ LDO(L14, "8018_l14", "8018_l14_pc", pldo, LDO_50),
+
+ SMPS(S1, "8018_s1", "8018_s1_pc", smps, SMPS_1500),
+ SMPS(S2, "8018_s2", "8018_s2_pc", smps, SMPS_1500),
+ SMPS(S3, "8018_s3", "8018_s3_pc", smps, SMPS_1500),
+ SMPS(S4, "8018_s4", "8018_s4_pc", smps, SMPS_1500),
+ SMPS(S5, "8018_s5", "8018_s5_pc", smps, SMPS_1500),
+
+ LVS(LVS1, "8018_lvs1", "8018_lvs1_pc"),
+};
+
+static const char *pin_control_label[] = {
+ " D1",
+ " A0",
+ " A1",
+ " A2",
+};
+
+static const char *pin_func_label[] = {
+ [RPM_VREG_PIN_FN_9615_DONT_CARE] = "don't care",
+ [RPM_VREG_PIN_FN_9615_ENABLE] = "on/off",
+ [RPM_VREG_PIN_FN_9615_MODE] = "HPM/LPM",
+ [RPM_VREG_PIN_FN_9615_SLEEP_B] = "sleep_b",
+ [RPM_VREG_PIN_FN_9615_NONE] = "none",
+};
+
+static const char *force_mode_label[] = {
+ [RPM_VREG_FORCE_MODE_9615_NONE] = "none",
+ [RPM_VREG_FORCE_MODE_9615_LPM] = "LPM",
+ [RPM_VREG_FORCE_MODE_9615_AUTO] = "auto",
+ [RPM_VREG_FORCE_MODE_9615_HPM] = "HPM",
+ [RPM_VREG_FORCE_MODE_9615_BYPASS] = "BYP",
+};
+
+static const char *power_mode_label[] = {
+ [RPM_VREG_POWER_MODE_9615_HYSTERETIC] = "HYS",
+ [RPM_VREG_POWER_MODE_9615_PWM] = "PWM",
+};
+
+static int is_real_id(int id)
+{
+ return (id >= 0) && (id <= RPM_VREG_ID_PM8018_MAX_REAL);
+}
+
+static int pc_id_to_real_id(int id)
+{
+ int real_id;
+
+ if (id >= RPM_VREG_ID_PM8018_L2_PC && id <= RPM_VREG_ID_PM8018_L8_PC)
+ real_id = id - RPM_VREG_ID_PM8018_L2_PC + RPM_VREG_ID_PM8018_L2;
+ else
+ real_id = id - RPM_VREG_ID_PM8018_L13_PC
+ + RPM_VREG_ID_PM8018_L13;
+
+ return real_id;
+}
+
+static struct vreg_config config = {
+ .vregs = vregs,
+ .vregs_len = ARRAY_SIZE(vregs),
+
+ .vreg_id_min = RPM_VREG_ID_PM8018_L2,
+ .vreg_id_max = RPM_VREG_ID_PM8018_MAX,
+
+ .pin_func_none = RPM_VREG_PIN_FN_9615_NONE,
+ .pin_func_sleep_b = RPM_VREG_PIN_FN_9615_SLEEP_B,
+
+ .mode_lpm = REGULATOR_MODE_IDLE,
+ .mode_hpm = REGULATOR_MODE_NORMAL,
+
+ .set_points = all_set_points,
+ .set_points_len = ARRAY_SIZE(all_set_points),
+
+ .label_pin_ctrl = pin_control_label,
+ .label_pin_ctrl_len = ARRAY_SIZE(pin_control_label),
+ .label_pin_func = pin_func_label,
+ .label_pin_func_len = ARRAY_SIZE(pin_func_label),
+ .label_force_mode = force_mode_label,
+ .label_force_mode_len = ARRAY_SIZE(force_mode_label),
+ .label_power_mode = power_mode_label,
+ .label_power_mode_len = ARRAY_SIZE(power_mode_label),
+
+ .is_real_id = is_real_id,
+ .pc_id_to_real_id = pc_id_to_real_id,
+};
+
+struct vreg_config *get_config_9615(void)
+{
+ return &config;
+}
diff --git a/arch/arm/mach-msm/rpm-regulator-private.h b/arch/arm/mach-msm/rpm-regulator-private.h
new file mode 100644
index 0000000..ff127d9
--- /dev/null
+++ b/arch/arm/mach-msm/rpm-regulator-private.h
@@ -0,0 +1,174 @@
+/*
+ * Copyright (c) 2011, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#ifndef __ARCH_ARM_MACH_MSM_RPM_REGULATOR_INT_H
+#define __ARCH_ARM_MACH_MSM_RPM_REGULATOR_INT_H
+
+#include <linux/regulator/driver.h>
+#include <mach/rpm.h>
+#include <mach/rpm-regulator.h>
+
+/* Possible RPM regulator request types */
+enum rpm_regulator_type {
+ RPM_REGULATOR_TYPE_LDO,
+ RPM_REGULATOR_TYPE_SMPS,
+ RPM_REGULATOR_TYPE_VS,
+ RPM_REGULATOR_TYPE_NCP,
+ RPM_REGULATOR_TYPE_MAX = RPM_REGULATOR_TYPE_NCP,
+};
+
+struct request_member {
+ int word;
+ unsigned int mask;
+ int shift;
+};
+
+/* Possible RPM regulator request members */
+struct rpm_vreg_parts {
+ struct request_member mV; /* voltage: used if voltage is in mV */
+ struct request_member uV; /* voltage: used if voltage is in uV */
+ struct request_member ip; /* peak current in mA */
+ struct request_member pd; /* pull down enable */
+ struct request_member ia; /* average current in mA */
+ struct request_member fm; /* force mode */
+ struct request_member pm; /* power mode */
+ struct request_member pc; /* pin control */
+ struct request_member pf; /* pin function */
+ struct request_member enable_state; /* NCP and switch */
+ struct request_member comp_mode; /* NCP */
+ struct request_member freq; /* frequency: NCP and SMPS */
+ struct request_member freq_clk_src; /* clock source: SMPS */
+ struct request_member hpm; /* switch: control OCP and SS */
+ int request_len;
+};
+
+struct vreg_range {
+ int min_uV;
+ int max_uV;
+ int step_uV;
+ unsigned n_voltages;
+};
+
+struct vreg_set_points {
+ struct vreg_range *range;
+ int count;
+ unsigned n_voltages;
+};
+
+struct vreg {
+ struct msm_rpm_iv_pair req[2];
+ struct msm_rpm_iv_pair prev_active_req[2];
+ struct msm_rpm_iv_pair prev_sleep_req[2];
+ struct rpm_regulator_init_data pdata;
+ struct regulator_desc rdesc;
+ struct regulator_desc rdesc_pc;
+ struct regulator_dev *rdev;
+ struct regulator_dev *rdev_pc;
+ struct vreg_set_points *set_points;
+ struct rpm_vreg_parts *part;
+ int type;
+ int id;
+ struct mutex pc_lock;
+ int save_uV;
+ int mode;
+ bool is_enabled;
+ bool is_enabled_pc;
+ const int hpm_min_load;
+ int active_min_uV_vote[RPM_VREG_VOTER_COUNT];
+ int sleep_min_uV_vote[RPM_VREG_VOTER_COUNT];
+};
+
+struct vreg_config {
+ struct vreg *vregs;
+ int vregs_len;
+
+ int vreg_id_min;
+ int vreg_id_max;
+
+ int pin_func_none;
+ int pin_func_sleep_b;
+
+ unsigned int mode_lpm;
+ unsigned int mode_hpm;
+
+ struct vreg_set_points **set_points;
+ int set_points_len;
+
+ const char **label_pin_ctrl;
+ int label_pin_ctrl_len;
+ const char **label_pin_func;
+ int label_pin_func_len;
+ const char **label_force_mode;
+ int label_force_mode_len;
+ const char **label_power_mode;
+ int label_power_mode_len;
+
+ int (*is_real_id) (int vreg_id);
+ int (*pc_id_to_real_id) (int vreg_id);
+
+ /* Legacy options to be used with MSM8660 */
+ int use_legacy_optimum_mode;
+ int ia_follows_ip;
+};
+
+#define REQUEST_MEMBER(_word, _mask, _shift) \
+ { \
+ .word = _word, \
+ .mask = _mask, \
+ .shift = _shift, \
+ }
+
+#define VOLTAGE_RANGE(_min_uV, _max_uV, _step_uV) \
+ { \
+ .min_uV = _min_uV, \
+ .max_uV = _max_uV, \
+ .step_uV = _step_uV, \
+ }
+
+#define SET_POINTS(_ranges) \
+{ \
+ .range = _ranges, \
+ .count = ARRAY_SIZE(_ranges), \
+};
+
+#define MICRO_TO_MILLI(uV) ((uV) / 1000)
+#define MILLI_TO_MICRO(mV) ((mV) * 1000)
+
+#if defined(CONFIG_ARCH_MSM8X60)
+struct vreg_config *get_config_8660(void);
+#else
+static inline struct vreg_config *get_config_8660(void)
+{
+ return NULL;
+}
+#endif
+
+#if defined(CONFIG_ARCH_MSM8960) || defined(CONFIG_ARCH_APQ8064)
+struct vreg_config *get_config_8960(void);
+#else
+static inline struct vreg_config *get_config_8960(void)
+{
+ return NULL;
+}
+#endif
+
+#if defined(CONFIG_ARCH_MSM9615)
+struct vreg_config *get_config_9615(void);
+#else
+static inline struct vreg_config *get_config_9615(void)
+{
+ return NULL;
+}
+#endif
+
+#endif
diff --git a/arch/arm/mach-msm/rpm-regulator.c b/arch/arm/mach-msm/rpm-regulator.c
index b9e577a..2494969 100644
--- a/arch/arm/mach-msm/rpm-regulator.c
+++ b/arch/arm/mach-msm/rpm-regulator.c
@@ -1,4 +1,5 @@
-/* Copyright (c) 2010-2011, 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,18 +11,22 @@
* GNU General Public License for more details.
*/
+#define pr_fmt(fmt) "%s: " fmt, __func__
+
#include <linux/module.h>
#include <linux/err.h>
#include <linux/kernel.h>
#include <linux/init.h>
+#include <linux/slab.h>
#include <linux/spinlock.h>
#include <linux/platform_device.h>
#include <linux/regulator/driver.h>
-#include <linux/mfd/pmic8901.h>
#include <mach/rpm.h>
#include <mach/rpm-regulator.h>
+#include <mach/socinfo.h>
#include "rpm_resources.h"
+#include "rpm-regulator-private.h"
/* Debug Definitions */
@@ -29,7 +34,7 @@
MSM_RPM_VREG_DEBUG_REQUEST = BIT(0),
MSM_RPM_VREG_DEBUG_VOTE = BIT(1),
MSM_RPM_VREG_DEBUG_DUPLICATE = BIT(2),
- MSM_RPM_VREG_DEBUG_IGNORE_8058_S0_S1 = BIT(3),
+ MSM_RPM_VREG_DEBUG_IGNORE_VDD_MEM_DIG = BIT(3),
};
static int msm_rpm_vreg_debug_mask;
@@ -37,241 +42,242 @@
debug_mask, msm_rpm_vreg_debug_mask, int, S_IRUSR | S_IWUSR
);
-#define MICRO_TO_MILLI(uV) ((uV) / 1000)
-#define MILLI_TO_MICRO(mV) ((mV) * 1000)
+struct vreg_config *(*get_config[])(void) = {
+ [RPM_VREG_VERSION_8660] = get_config_8660,
+ [RPM_VREG_VERSION_8960] = get_config_8960,
+ [RPM_VREG_VERSION_9615] = get_config_9615,
+};
-/* LDO register word 1 */
-#define LDO_VOLTAGE 0x00000FFF
-#define LDO_VOLTAGE_SHIFT 0
-#define LDO_PEAK_CURRENT 0x00FFF000
-#define LDO_PEAK_CURRENT_SHIFT 12
-#define LDO_MODE 0x03000000
-#define LDO_MODE_SHIFT 24
-#define LDO_PIN_CTRL 0x3C000000
-#define LDO_PIN_CTRL_SHIFT 26
-#define LDO_PIN_FN 0xC0000000
-#define LDO_PIN_FN_SHIFT 30
+#define SET_PART(_vreg, _part, _val) \
+ _vreg->req[_vreg->part->_part.word].value \
+ = (_vreg->req[_vreg->part->_part.word].value \
+ & ~vreg->part->_part.mask) \
+ | (((_val) << vreg->part->_part.shift) & vreg->part->_part.mask)
-/* LDO register word 2 */
-#define LDO_PULL_DOWN_ENABLE 0x00000001
-#define LDO_PULL_DOWN_ENABLE_SHIFT 0
-#define LDO_AVG_CURRENT 0x00001FFE
-#define LDO_AVG_CURRENT_SHIFT 1
+#define GET_PART(_vreg, _part) \
+ ((_vreg->req[_vreg->part->_part.word].value & vreg->part->_part.mask) \
+ >> vreg->part->_part.shift)
-/* SMPS register word 1 */
-#define SMPS_VOLTAGE 0x00000FFF
-#define SMPS_VOLTAGE_SHIFT 0
-#define SMPS_PEAK_CURRENT 0x00FFF000
-#define SMPS_PEAK_CURRENT_SHIFT 12
-#define SMPS_MODE 0x03000000
-#define SMPS_MODE_SHIFT 24
-#define SMPS_PIN_CTRL 0x3C000000
-#define SMPS_PIN_CTRL_SHIFT 26
-#define SMPS_PIN_FN 0xC0000000
-#define SMPS_PIN_FN_SHIFT 30
+#define USES_PART(_vreg, _part) (vreg->part->_part.mask)
-/* SMPS register word 2 */
-#define SMPS_PULL_DOWN_ENABLE 0x00000001
-#define SMPS_PULL_DOWN_ENABLE_SHIFT 0
-#define SMPS_AVG_CURRENT 0x00001FFE
-#define SMPS_AVG_CURRENT_SHIFT 1
-#define SMPS_FREQ 0x001FE000
-#define SMPS_FREQ_SHIFT 13
-#define SMPS_CLK_SRC 0x00600000
-#define SMPS_CLK_SRC_SHIFT 21
+#define vreg_err(vreg, fmt, ...) \
+ pr_err("%s: " fmt, vreg->rdesc.name, ##__VA_ARGS__)
-/* SWITCH register word 1 */
-#define SWITCH_STATE 0x0001
-#define SWITCH_STATE_SHIFT 0
-#define SWITCH_PULL_DOWN_ENABLE 0x0002
-#define SWITCH_PULL_DOWN_ENABLE_SHIFT 1
-#define SWITCH_PIN_CTRL 0x003C
-#define SWITCH_PIN_CTRL_SHIFT 2
-#define SWITCH_PIN_FN 0x00C0
-#define SWITCH_PIN_FN_SHIFT 6
+#define RPM_VREG_PIN_CTRL_EN0 0x01
+#define RPM_VREG_PIN_CTRL_EN1 0x02
+#define RPM_VREG_PIN_CTRL_EN2 0x04
+#define RPM_VREG_PIN_CTRL_EN3 0x08
+#define RPM_VREG_PIN_CTRL_ALL 0x0F
-/* NCP register word 1 */
-#define NCP_VOLTAGE 0x0FFF
-#define NCP_VOLTAGE_SHIFT 0
-#define NCP_STATE 0x1000
-#define NCP_STATE_SHIFT 12
-
+static const char *label_freq[] = {
+ [RPM_VREG_FREQ_NONE] = " N/A",
+ [RPM_VREG_FREQ_19p20] = "19.2",
+ [RPM_VREG_FREQ_9p60] = "9.60",
+ [RPM_VREG_FREQ_6p40] = "6.40",
+ [RPM_VREG_FREQ_4p80] = "4.80",
+ [RPM_VREG_FREQ_3p84] = "3.84",
+ [RPM_VREG_FREQ_3p20] = "3.20",
+ [RPM_VREG_FREQ_2p74] = "2.74",
+ [RPM_VREG_FREQ_2p40] = "2.40",
+ [RPM_VREG_FREQ_2p13] = "2.13",
+ [RPM_VREG_FREQ_1p92] = "1.92",
+ [RPM_VREG_FREQ_1p75] = "1.75",
+ [RPM_VREG_FREQ_1p60] = "1.60",
+ [RPM_VREG_FREQ_1p48] = "1.48",
+ [RPM_VREG_FREQ_1p37] = "1.37",
+ [RPM_VREG_FREQ_1p28] = "1.28",
+ [RPM_VREG_FREQ_1p20] = "1.20",
+};
/*
* This is used when voting for LPM or HPM by subtracting or adding to the
* hpm_min_load of a regulator. It has units of uA.
*/
-#define LOAD_THRESHOLD_STEP 1000
+#define LOAD_THRESHOLD_STEP 1000
-/* This is the maximum uA load that can be passed to the RPM. */
-#define MAX_POSSIBLE_LOAD (MILLI_TO_MICRO(0xFFF))
+/* rpm_version keeps track of the version for the currently running driver. */
+enum rpm_vreg_version rpm_version = -1;
-/* Voltage regulator types */
-#define IS_LDO(id) ((id >= RPM_VREG_ID_PM8058_L0 && \
- id <= RPM_VREG_ID_PM8058_L25) || \
- (id >= RPM_VREG_ID_PM8901_L0 && \
- id <= RPM_VREG_ID_PM8901_L6))
-#define IS_SMPS(id) ((id >= RPM_VREG_ID_PM8058_S0 && \
- id <= RPM_VREG_ID_PM8058_S4) || \
- (id >= RPM_VREG_ID_PM8901_S0 && \
- id <= RPM_VREG_ID_PM8901_S4))
-#define IS_SWITCH(id) ((id >= RPM_VREG_ID_PM8058_LVS0 && \
- id <= RPM_VREG_ID_PM8058_LVS1) || \
- (id >= RPM_VREG_ID_PM8901_LVS0 && \
- id <= RPM_VREG_ID_PM8901_LVS3) || \
- (id == RPM_VREG_ID_PM8901_MVS0))
-#define IS_NCP(id) (id == RPM_VREG_ID_PM8058_NCP)
+/* config holds all configuration data of the currently running driver. */
+static struct vreg_config *config;
-#define IS_8901_SMPS(id) ((id >= RPM_VREG_ID_PM8901_S0 && \
- id <= RPM_VREG_ID_PM8901_S4))
+/* These regulator ID values are specified in the board file. */
+static int vreg_id_vdd_mem, vreg_id_vdd_dig;
-struct vreg {
- struct msm_rpm_iv_pair req[2];
- struct msm_rpm_iv_pair prev_active_req[2];
- struct msm_rpm_iv_pair prev_sleep_req[2];
- struct rpm_vreg_pdata *pdata;
- int save_uV;
- const int hpm_min_load;
- unsigned pc_vote;
- unsigned optimum;
- unsigned mode_initialized;
- int active_min_mV_vote[RPM_VREG_VOTER_COUNT];
- int sleep_min_mV_vote[RPM_VREG_VOTER_COUNT];
- enum rpm_vreg_id id;
-};
+static inline int vreg_id_is_vdd_mem_or_dig(int id)
+{
+ return id == vreg_id_vdd_mem || id == vreg_id_vdd_dig;
+}
-#define RPM_VREG_NCP_HPM_MIN_LOAD 0
+#define DEBUG_PRINT_BUFFER_SIZE 512
-#define VREG_2(_vreg_id, _rpm_id, _hpm_min_load) \
- [RPM_VREG_ID_##_vreg_id] = { \
- .req = { \
- [0] = { .id = MSM_RPM_ID_##_rpm_id##_0, }, \
- [1] = { .id = MSM_RPM_ID_##_rpm_id##_1, }, \
- }, \
- .hpm_min_load = RPM_VREG_##_hpm_min_load, \
+static void rpm_regulator_req(struct vreg *vreg, int set)
+{
+ int uV, mV, fm, pm, pc, pf, pd, freq, state, i;
+ const char *pf_label = "", *fm_label = "", *pc_total = "";
+ const char *pc_en[4] = {"", "", "", ""};
+ const char *pm_label = "", *freq_label = "";
+ char buf[DEBUG_PRINT_BUFFER_SIZE];
+ size_t buflen = DEBUG_PRINT_BUFFER_SIZE;
+ int pos = 0;
+
+ /* Suppress VDD_MEM and VDD_DIG printing. */
+ if ((msm_rpm_vreg_debug_mask & MSM_RPM_VREG_DEBUG_IGNORE_VDD_MEM_DIG)
+ && vreg_id_is_vdd_mem_or_dig(vreg->id))
+ return;
+
+ uV = GET_PART(vreg, uV);
+ mV = GET_PART(vreg, mV);
+ if (vreg->type == RPM_REGULATOR_TYPE_NCP) {
+ uV = -uV;
+ mV = -mV;
}
-#define VREG_1(_vreg_id, _rpm_id) \
- [RPM_VREG_ID_##_vreg_id] = { \
- .req = { \
- [0] = { .id = MSM_RPM_ID_##_rpm_id, }, \
- [1] = { .id = -1, }, \
- }, \
+ fm = GET_PART(vreg, fm);
+ pm = GET_PART(vreg, pm);
+ pc = GET_PART(vreg, pc);
+ pf = GET_PART(vreg, pf);
+ pd = GET_PART(vreg, pd);
+ freq = GET_PART(vreg, freq);
+ state = GET_PART(vreg, enable_state);
+
+ if (pf >= 0 && pf < config->label_pin_func_len)
+ pf_label = config->label_pin_func[pf];
+
+ if (fm >= 0 && fm < config->label_force_mode_len)
+ fm_label = config->label_force_mode[fm];
+
+ if (pm >= 0 && pm < config->label_power_mode_len)
+ pm_label = config->label_power_mode[pm];
+
+ if (freq >= 0 && freq < ARRAY_SIZE(label_freq))
+ freq_label = label_freq[freq];
+
+ for (i = 0; i < config->label_pin_ctrl_len; i++)
+ if (pc & (1 << i))
+ pc_en[i] = config->label_pin_ctrl[i];
+
+ if (pc == RPM_VREG_PIN_CTRL_NONE)
+ pc_total = " none";
+
+ pos += scnprintf(buf + pos, buflen - pos, "%s%s: ",
+ KERN_INFO, __func__);
+
+ pos += scnprintf(buf + pos, buflen - pos, "%s %-9s: s=%c",
+ (set == MSM_RPM_CTX_SET_0 ? "sending " : "buffered"),
+ vreg->rdesc.name,
+ (set == MSM_RPM_CTX_SET_0 ? 'A' : 'S'));
+
+ if (USES_PART(vreg, uV))
+ pos += scnprintf(buf + pos, buflen - pos, ", v=%7d uV", uV);
+ if (USES_PART(vreg, mV))
+ pos += scnprintf(buf + pos, buflen - pos, ", v=%4d mV", mV);
+ if (USES_PART(vreg, enable_state))
+ pos += scnprintf(buf + pos, buflen - pos, ", state=%s (%d)",
+ (state == 1 ? "on" : "off"), state);
+ if (USES_PART(vreg, ip))
+ pos += scnprintf(buf + pos, buflen - pos,
+ ", ip=%4d mA", GET_PART(vreg, ip));
+ if (USES_PART(vreg, fm))
+ pos += scnprintf(buf + pos, buflen - pos,
+ ", fm=%s (%d)", fm_label, fm);
+ if (USES_PART(vreg, pc))
+ pos += scnprintf(buf + pos, buflen - pos,
+ ", pc=%s%s%s%s%s (%X)", pc_en[0], pc_en[1],
+ pc_en[2], pc_en[3], pc_total, pc);
+ if (USES_PART(vreg, pf))
+ pos += scnprintf(buf + pos, buflen - pos,
+ ", pf=%s (%d)", pf_label, pf);
+ if (USES_PART(vreg, pd))
+ pos += scnprintf(buf + pos, buflen - pos,
+ ", pd=%s (%d)", (pd == 1 ? "Y" : "N"), pd);
+ if (USES_PART(vreg, ia))
+ pos += scnprintf(buf + pos, buflen - pos,
+ ", ia=%4d mA", GET_PART(vreg, ia));
+ if (USES_PART(vreg, freq)) {
+ if (vreg->type == RPM_REGULATOR_TYPE_NCP)
+ pos += scnprintf(buf + pos, buflen - pos,
+ ", freq=%2d", freq);
+ else
+ pos += scnprintf(buf + pos, buflen - pos,
+ ", freq=%s MHz (%2d)", freq_label, freq);
}
+ if (USES_PART(vreg, pm))
+ pos += scnprintf(buf + pos, buflen - pos,
+ ", pm=%s (%d)", pm_label, pm);
+ if (USES_PART(vreg, freq_clk_src))
+ pos += scnprintf(buf + pos, buflen - pos,
+ ", clk_src=%d", GET_PART(vreg, freq_clk_src));
+ if (USES_PART(vreg, comp_mode))
+ pos += scnprintf(buf + pos, buflen - pos,
+ ", comp=%d", GET_PART(vreg, comp_mode));
+ if (USES_PART(vreg, hpm))
+ pos += scnprintf(buf + pos, buflen - pos,
+ ", hpm=%d", GET_PART(vreg, hpm));
-static struct vreg vregs[RPM_VREG_ID_MAX] = {
- VREG_2(PM8058_L0, LDO0, LDO_150_HPM_MIN_LOAD),
- VREG_2(PM8058_L1, LDO1, LDO_300_HPM_MIN_LOAD),
- VREG_2(PM8058_L2, LDO2, LDO_300_HPM_MIN_LOAD),
- VREG_2(PM8058_L3, LDO3, LDO_150_HPM_MIN_LOAD),
- VREG_2(PM8058_L4, LDO4, LDO_50_HPM_MIN_LOAD),
- VREG_2(PM8058_L5, LDO5, LDO_300_HPM_MIN_LOAD),
- VREG_2(PM8058_L6, LDO6, LDO_50_HPM_MIN_LOAD),
- VREG_2(PM8058_L7, LDO7, LDO_50_HPM_MIN_LOAD),
- VREG_2(PM8058_L8, LDO8, LDO_300_HPM_MIN_LOAD),
- VREG_2(PM8058_L9, LDO9, LDO_300_HPM_MIN_LOAD),
- VREG_2(PM8058_L10, LDO10, LDO_300_HPM_MIN_LOAD),
- VREG_2(PM8058_L11, LDO11, LDO_150_HPM_MIN_LOAD),
- VREG_2(PM8058_L12, LDO12, LDO_150_HPM_MIN_LOAD),
- VREG_2(PM8058_L13, LDO13, LDO_300_HPM_MIN_LOAD),
- VREG_2(PM8058_L14, LDO14, LDO_300_HPM_MIN_LOAD),
- VREG_2(PM8058_L15, LDO15, LDO_300_HPM_MIN_LOAD),
- VREG_2(PM8058_L16, LDO16, LDO_300_HPM_MIN_LOAD),
- VREG_2(PM8058_L17, LDO17, LDO_150_HPM_MIN_LOAD),
- VREG_2(PM8058_L18, LDO18, LDO_150_HPM_MIN_LOAD),
- VREG_2(PM8058_L19, LDO19, LDO_150_HPM_MIN_LOAD),
- VREG_2(PM8058_L20, LDO20, LDO_150_HPM_MIN_LOAD),
- VREG_2(PM8058_L21, LDO21, LDO_150_HPM_MIN_LOAD),
- VREG_2(PM8058_L22, LDO22, LDO_300_HPM_MIN_LOAD),
- VREG_2(PM8058_L23, LDO23, LDO_300_HPM_MIN_LOAD),
- VREG_2(PM8058_L24, LDO24, LDO_150_HPM_MIN_LOAD),
- VREG_2(PM8058_L25, LDO25, LDO_150_HPM_MIN_LOAD),
+ pos += scnprintf(buf + pos, buflen - pos, "; req[0]={%d, 0x%08X}",
+ vreg->req[0].id, vreg->req[0].value);
+ if (vreg->part->request_len > 1)
+ pos += scnprintf(buf + pos, buflen - pos,
+ ", req[1]={%d, 0x%08X}", vreg->req[1].id,
+ vreg->req[1].value);
- VREG_2(PM8058_S0, SMPS0, SMPS_HPM_MIN_LOAD),
- VREG_2(PM8058_S1, SMPS1, SMPS_HPM_MIN_LOAD),
- VREG_2(PM8058_S2, SMPS2, SMPS_HPM_MIN_LOAD),
- VREG_2(PM8058_S3, SMPS3, SMPS_HPM_MIN_LOAD),
- VREG_2(PM8058_S4, SMPS4, SMPS_HPM_MIN_LOAD),
+ pos += scnprintf(buf + pos, buflen - pos, "\n");
+ printk(buf);
+}
- VREG_1(PM8058_LVS0, LVS0),
- VREG_1(PM8058_LVS1, LVS1),
+static void rpm_regulator_vote(struct vreg *vreg, enum rpm_vreg_voter voter,
+ int set, int voter_uV, int aggregate_uV)
+{
+ /* Suppress VDD_MEM and VDD_DIG printing. */
+ if ((msm_rpm_vreg_debug_mask & MSM_RPM_VREG_DEBUG_IGNORE_VDD_MEM_DIG)
+ && vreg_id_is_vdd_mem_or_dig(vreg->id))
+ return;
- VREG_2(PM8058_NCP, NCP, NCP_HPM_MIN_LOAD),
+ pr_info("vote received %-9s: voter=%d, set=%c, v_voter=%7d uV, "
+ "v_aggregate=%7d uV\n", vreg->rdesc.name, voter,
+ (set == 0 ? 'A' : 'S'), voter_uV, aggregate_uV);
+}
- VREG_2(PM8901_L0, LDO0B, LDO_300_HPM_MIN_LOAD),
- VREG_2(PM8901_L1, LDO1B, LDO_300_HPM_MIN_LOAD),
- VREG_2(PM8901_L2, LDO2B, LDO_300_HPM_MIN_LOAD),
- VREG_2(PM8901_L3, LDO3B, LDO_300_HPM_MIN_LOAD),
- VREG_2(PM8901_L4, LDO4B, LDO_300_HPM_MIN_LOAD),
- VREG_2(PM8901_L5, LDO5B, LDO_300_HPM_MIN_LOAD),
- VREG_2(PM8901_L6, LDO6B, LDO_300_HPM_MIN_LOAD),
+static void rpm_regulator_duplicate(struct vreg *vreg, int set, int cnt)
+{
+ /* Suppress VDD_MEM and VDD_DIG printing. */
+ if ((msm_rpm_vreg_debug_mask & MSM_RPM_VREG_DEBUG_IGNORE_VDD_MEM_DIG)
+ && vreg_id_is_vdd_mem_or_dig(vreg->id))
+ return;
- VREG_2(PM8901_S0, SMPS0B, FTSMPS_HPM_MIN_LOAD),
- VREG_2(PM8901_S1, SMPS1B, FTSMPS_HPM_MIN_LOAD),
- VREG_2(PM8901_S2, SMPS2B, FTSMPS_HPM_MIN_LOAD),
- VREG_2(PM8901_S3, SMPS3B, FTSMPS_HPM_MIN_LOAD),
- VREG_2(PM8901_S4, SMPS4B, FTSMPS_HPM_MIN_LOAD),
-
- VREG_1(PM8901_LVS0, LVS0B),
- VREG_1(PM8901_LVS1, LVS1B),
- VREG_1(PM8901_LVS2, LVS2B),
- VREG_1(PM8901_LVS3, LVS3B),
-
- VREG_1(PM8901_MVS0, MVS),
-};
-
-static void print_rpm_request(struct vreg *vreg, int set);
-static void print_rpm_vote(struct vreg *vreg, enum rpm_vreg_voter voter,
- int set, int voter_mV, int aggregate_mV);
-static void print_rpm_duplicate(struct vreg *vreg, int set, int cnt);
-
-static unsigned int smps_get_mode(struct regulator_dev *dev);
-static unsigned int ldo_get_mode(struct regulator_dev *dev);
-static unsigned int switch_get_mode(struct regulator_dev *dev);
+ if (cnt == 2)
+ pr_info("ignored request %-9s: set=%c; req[0]={%d, 0x%08X}, "
+ "req[1]={%d, 0x%08X}\n", vreg->rdesc.name,
+ (set == 0 ? 'A' : 'S'),
+ vreg->req[0].id, vreg->req[0].value,
+ vreg->req[1].id, vreg->req[1].value);
+ else if (cnt == 1)
+ pr_info("ignored request %-9s: set=%c; req[0]={%d, 0x%08X}\n",
+ vreg->rdesc.name, (set == 0 ? 'A' : 'S'),
+ vreg->req[0].id, vreg->req[0].value);
+}
/* Spin lock needed for sleep-selectable regulators. */
-static DEFINE_SPINLOCK(pm8058_noirq_lock);
+static DEFINE_SPINLOCK(rpm_noirq_lock);
static int voltage_from_req(struct vreg *vreg)
{
- int shift = 0;
- uint32_t value = 0, mask = 0;
+ int uV = 0;
- value = vreg->req[0].value;
+ if (vreg->part->uV.mask)
+ uV = GET_PART(vreg, uV);
+ else
+ uV = MILLI_TO_MICRO(GET_PART(vreg, mV));
- if (IS_SMPS(vreg->id)) {
- mask = SMPS_VOLTAGE;
- shift = SMPS_VOLTAGE_SHIFT;
- } else if (IS_LDO(vreg->id)) {
- mask = LDO_VOLTAGE;
- shift = LDO_VOLTAGE_SHIFT;
- } else if (IS_NCP(vreg->id)) {
- mask = NCP_VOLTAGE;
- shift = NCP_VOLTAGE_SHIFT;
- }
-
- return (value & mask) >> shift;
+ return uV;
}
-static void voltage_to_req(int voltage, struct vreg *vreg)
+static void voltage_to_req(int uV, struct vreg *vreg)
{
- int shift = 0;
- uint32_t *value = NULL, mask = 0;
-
- value = &(vreg->req[0].value);
-
- if (IS_SMPS(vreg->id)) {
- mask = SMPS_VOLTAGE;
- shift = SMPS_VOLTAGE_SHIFT;
- } else if (IS_LDO(vreg->id)) {
- mask = LDO_VOLTAGE;
- shift = LDO_VOLTAGE_SHIFT;
- } else if (IS_NCP(vreg->id)) {
- mask = NCP_VOLTAGE;
- shift = NCP_VOLTAGE_SHIFT;
- }
-
- *value &= ~mask;
- *value |= (voltage << shift) & mask;
+ if (vreg->part->uV.mask)
+ SET_PART(vreg, uV, uV);
+ else
+ SET_PART(vreg, mV, MICRO_TO_MILLI(uV));
}
static int vreg_send_request(struct vreg *vreg, enum rpm_vreg_voter voter,
@@ -280,15 +286,16 @@
int update_voltage)
{
struct msm_rpm_iv_pair *prev_req;
- int rc = 0, max_mV_vote = 0, i;
+ int rc = 0, max_uV_vote = 0;
unsigned prev0, prev1;
- int *min_mV_vote;
+ int *min_uV_vote;
+ int i;
if (set == MSM_RPM_CTX_SET_0) {
- min_mV_vote = vreg->active_min_mV_vote;
+ min_uV_vote = vreg->active_min_uV_vote;
prev_req = vreg->prev_active_req;
} else {
- min_mV_vote = vreg->sleep_min_mV_vote;
+ min_uV_vote = vreg->sleep_min_uV_vote;
prev_req = vreg->prev_sleep_req;
}
@@ -301,42 +308,41 @@
vreg->req[1].value |= val1 & mask1;
if (update_voltage)
- min_mV_vote[voter] = voltage_from_req(vreg);
+ min_uV_vote[voter] = voltage_from_req(vreg);
/* Find the highest voltage voted for and use it. */
for (i = 0; i < RPM_VREG_VOTER_COUNT; i++)
- max_mV_vote = max(max_mV_vote, min_mV_vote[i]);
- voltage_to_req(max_mV_vote, vreg);
+ max_uV_vote = max(max_uV_vote, min_uV_vote[i]);
+ voltage_to_req(max_uV_vote, vreg);
if (msm_rpm_vreg_debug_mask & MSM_RPM_VREG_DEBUG_VOTE)
- print_rpm_vote(vreg, voter, set, min_mV_vote[voter],
- max_mV_vote);
+ rpm_regulator_vote(vreg, voter, set, min_uV_vote[voter],
+ max_uV_vote);
/* Ignore duplicate requests */
if (vreg->req[0].value != prev_req[0].value ||
vreg->req[1].value != prev_req[1].value) {
-
rc = msm_rpmrs_set_noirq(set, vreg->req, cnt);
if (rc) {
vreg->req[0].value = prev0;
vreg->req[1].value = prev1;
- pr_err("%s: msm_rpmrs_set_noirq failed - "
- "set=%s, id=%d, rc=%d\n", __func__,
+ vreg_err(vreg, "msm_rpmrs_set_noirq failed - "
+ "set=%s, id=%d, rc=%d\n",
(set == MSM_RPM_CTX_SET_0 ? "active" : "sleep"),
vreg->req[0].id, rc);
} else {
/* Only save if nonzero and active set. */
- if (max_mV_vote && (set == MSM_RPM_CTX_SET_0))
- vreg->save_uV = MILLI_TO_MICRO(max_mV_vote);
+ if (max_uV_vote && (set == MSM_RPM_CTX_SET_0))
+ vreg->save_uV = max_uV_vote;
if (msm_rpm_vreg_debug_mask
& MSM_RPM_VREG_DEBUG_REQUEST)
- print_rpm_request(vreg, set);
+ rpm_regulator_req(vreg, set);
prev_req[0].value = vreg->req[0].value;
prev_req[1].value = vreg->req[1].value;
}
} else if (msm_rpm_vreg_debug_mask & MSM_RPM_VREG_DEBUG_DUPLICATE) {
- print_rpm_duplicate(vreg, set, cnt);
+ rpm_regulator_duplicate(vreg, set, cnt);
}
return rc;
@@ -347,14 +353,14 @@
unsigned mask1, unsigned val1, unsigned cnt,
int update_voltage)
{
+ unsigned int s_mask[2] = {mask0, mask1}, s_val[2] = {val0, val1};
unsigned long flags;
int rc;
- unsigned val0_sleep, mask0_sleep;
if (voter < 0 || voter >= RPM_VREG_VOTER_COUNT)
return -EINVAL;
- spin_lock_irqsave(&pm8058_noirq_lock, flags);
+ spin_lock_irqsave(&rpm_noirq_lock, flags);
/*
* Send sleep set request first so that subsequent set_mode, etc calls
@@ -369,28 +375,23 @@
* specified. This ensures that a disable vote will be issued
* at some point for the sleep set of the regulator.
*/
- val0_sleep = val0;
- mask0_sleep = mask0;
- if (IS_SMPS(vreg->id)) {
- val0_sleep &= ~SMPS_VOLTAGE;
- mask0_sleep |= SMPS_VOLTAGE;
- } else if (IS_LDO(vreg->id)) {
- val0_sleep &= ~LDO_VOLTAGE;
- mask0_sleep |= LDO_VOLTAGE;
- } else if (IS_NCP(vreg->id)) {
- val0_sleep &= ~NCP_VOLTAGE;
- mask0_sleep |= NCP_VOLTAGE;
+ if (vreg->part->uV.mask) {
+ s_val[vreg->part->uV.word] = 0 << vreg->part->uV.shift;
+ s_mask[vreg->part->uV.word] = vreg->part->uV.mask;
+ } else {
+ s_val[vreg->part->mV.word] = 0 << vreg->part->mV.shift;
+ s_mask[vreg->part->mV.word] = vreg->part->mV.mask;
}
rc = vreg_send_request(vreg, voter, MSM_RPM_CTX_SET_SLEEP,
- mask0_sleep, val0_sleep,
- mask1, val1, cnt, update_voltage);
+ s_mask[0], s_val[0], s_mask[1], s_val[1],
+ cnt, update_voltage);
}
rc = vreg_send_request(vreg, voter, MSM_RPM_CTX_SET_0, mask0, val0,
mask1, val1, cnt, update_voltage);
- spin_unlock_irqrestore(&pm8058_noirq_lock, flags);
+ spin_unlock_irqrestore(&rpm_noirq_lock, flags);
return rc;
}
@@ -416,38 +417,87 @@
* This function may only be called for regulators which have the sleep flag
* specified in their private data.
*/
-int rpm_vreg_set_voltage(enum rpm_vreg_id vreg_id, enum rpm_vreg_voter voter,
- int min_uV, int max_uV, int sleep_also)
+int rpm_vreg_set_voltage(int vreg_id, enum rpm_vreg_voter voter, int min_uV,
+ int max_uV, int sleep_also)
{
- int rc;
- unsigned val0 = 0, val1 = 0, mask0 = 0, mask1 = 0, cnt = 2;
+ unsigned int mask[2] = {0}, val[2] = {0};
+ struct vreg_range *range;
+ struct vreg *vreg;
+ int uV = min_uV;
+ int lim_min_uV, lim_max_uV, i, rc;
- if (vreg_id < 0 || vreg_id >= RPM_VREG_ID_MAX)
- return -EINVAL;
+ /*
+ * HACK: make this function a no-op for 8064 so that it can be called by
+ * consumers on 8064 before RPM capabilities are present. (needed for
+ * acpuclock driver)
+ */
+ if (cpu_is_apq8064())
+ return 0;
- if (!vregs[vreg_id].pdata->sleep_selectable)
- return -EINVAL;
-
- if (min_uV < vregs[vreg_id].pdata->init_data.constraints.min_uV ||
- min_uV > vregs[vreg_id].pdata->init_data.constraints.max_uV)
- return -EINVAL;
-
- if (IS_SMPS(vreg_id)) {
- mask0 = SMPS_VOLTAGE;
- val0 = MICRO_TO_MILLI(min_uV) << SMPS_VOLTAGE_SHIFT;
- } else if (IS_LDO(vreg_id)) {
- mask0 = LDO_VOLTAGE;
- val0 = MICRO_TO_MILLI(min_uV) << LDO_VOLTAGE_SHIFT;
- } else if (IS_NCP(vreg_id)) {
- mask0 = NCP_VOLTAGE;
- val0 = MICRO_TO_MILLI(min_uV) << NCP_VOLTAGE_SHIFT;
- cnt = 1;
- } else {
- cnt = 1;
+ if (!config) {
+ pr_err("rpm-regulator driver has not probed yet.\n");
+ return -ENODEV;
}
- rc = vreg_set_noirq(&vregs[vreg_id], voter, sleep_also, mask0, val0,
- mask1, val1, cnt, 1);
+ if (vreg_id < config->vreg_id_min || vreg_id > config->vreg_id_max) {
+ pr_err("invalid regulator id=%d\n", vreg_id);
+ return -EINVAL;
+ }
+
+ vreg = &config->vregs[vreg_id];
+ range = &vreg->set_points->range[0];
+
+ if (!vreg->pdata.sleep_selectable) {
+ vreg_err(vreg, "regulator is not marked sleep selectable\n");
+ return -EINVAL;
+ }
+
+ /*
+ * Check if request voltage is outside of allowed range. The regulator
+ * core has already checked that constraint range is inside of the
+ * physically allowed range.
+ */
+ lim_min_uV = vreg->pdata.init_data.constraints.min_uV;
+ lim_max_uV = vreg->pdata.init_data.constraints.max_uV;
+
+ if (uV < lim_min_uV && max_uV >= lim_min_uV)
+ uV = lim_min_uV;
+
+ if (uV < lim_min_uV || uV > lim_max_uV) {
+ vreg_err(vreg,
+ "request v=[%d, %d] is outside allowed v=[%d, %d]\n",
+ min_uV, max_uV, lim_min_uV, lim_max_uV);
+ return -EINVAL;
+ }
+
+ /* Find the range which uV is inside of. */
+ for (i = vreg->set_points->count - 1; i > 0; i--) {
+ if (uV > vreg->set_points->range[i - 1].max_uV) {
+ range = &vreg->set_points->range[i];
+ break;
+ }
+ }
+
+ /*
+ * Force uV to be an allowed set point and apply a ceiling function
+ * to non-set point values.
+ */
+ uV = (uV - range->min_uV + range->step_uV - 1) / range->step_uV;
+ uV = uV * range->step_uV + range->min_uV;
+
+ if (vreg->part->uV.mask) {
+ val[vreg->part->uV.word] = uV << vreg->part->uV.shift;
+ mask[vreg->part->uV.word] = vreg->part->uV.mask;
+ } else {
+ val[vreg->part->mV.word]
+ = MICRO_TO_MILLI(uV) << vreg->part->mV.shift;
+ mask[vreg->part->mV.word] = vreg->part->mV.mask;
+ }
+
+ rc = vreg_set_noirq(vreg, voter, sleep_also, mask[0], val[0], mask[1],
+ val[1], vreg->part->request_len, 1);
+ if (rc)
+ vreg_err(vreg, "vreg_set_noirq failed, rc=%d\n", rc);
return rc;
}
@@ -456,52 +506,60 @@
/**
* rpm_vreg_set_frequency - sets the frequency of a switching regulator
* @vreg: ID for regulator
- * @min_uV: minimum acceptable frequency of operation
+ * @freq: enum corresponding to desired frequency
*
* Returns 0 on success or errno.
*/
-int rpm_vreg_set_frequency(enum rpm_vreg_id vreg_id, enum rpm_vreg_freq freq)
+int rpm_vreg_set_frequency(int vreg_id, enum rpm_vreg_freq freq)
{
- unsigned val0 = 0, val1 = 0, mask0 = 0, mask1 = 0, cnt = 2;
+ unsigned int mask[2] = {0}, val[2] = {0};
+ struct vreg *vreg;
int rc;
- if (vreg_id < 0 || vreg_id >= RPM_VREG_ID_MAX) {
- pr_err("%s: invalid regulator id=%d\n", __func__, vreg_id);
+ /*
+ * HACK: make this function a no-op for 8064 so that it can be called by
+ * consumers on 8064 before RPM capabilities are present.
+ */
+ if (cpu_is_apq8064())
+ return 0;
+
+ if (!config) {
+ pr_err("rpm-regulator driver has not probed yet.\n");
+ return -ENODEV;
+ }
+
+ if (vreg_id < config->vreg_id_min || vreg_id > config->vreg_id_max) {
+ pr_err("invalid regulator id=%d\n", vreg_id);
return -EINVAL;
}
+ vreg = &config->vregs[vreg_id];
+
if (freq < 0 || freq > RPM_VREG_FREQ_1p20) {
- pr_err("%s: invalid frequency=%d\n", __func__, freq);
+ vreg_err(vreg, "invalid frequency=%d\n", freq);
+ return -EINVAL;
+ }
+ if (!vreg->pdata.sleep_selectable) {
+ vreg_err(vreg, "regulator is not marked sleep selectable\n");
+ return -EINVAL;
+ }
+ if (!vreg->part->freq.mask) {
+ vreg_err(vreg, "frequency not supported\n");
return -EINVAL;
}
- if (!IS_SMPS(vreg_id)) {
- pr_err("%s: regulator id=%d does not support frequency\n",
- __func__, vreg_id);
- return -EINVAL;
- }
+ val[vreg->part->freq.word] = freq << vreg->part->freq.shift;
+ mask[vreg->part->freq.word] = vreg->part->freq.mask;
- if (!vregs[vreg_id].pdata->sleep_selectable) {
- pr_err("%s: regulator id=%d is not marked sleep selectable\n",
- __func__, vreg_id);
- return -EINVAL;
- }
-
- mask1 = SMPS_FREQ;
- val1 = freq << SMPS_FREQ_SHIFT;
-
- rc = vreg_set_noirq(&vregs[vreg_id], RPM_VREG_VOTER_REG_FRAMEWORK,
- 1, mask0, val0, mask1, val1, cnt, 0);
+ rc = vreg_set_noirq(vreg, RPM_VREG_VOTER_REG_FRAMEWORK, 1, mask[0],
+ val[0], mask[1], val[1], vreg->part->request_len, 0);
+ if (rc)
+ vreg_err(vreg, "vreg_set failed, rc=%d\n", rc);
return rc;
}
EXPORT_SYMBOL_GPL(rpm_vreg_set_frequency);
-#define IS_PMIC_8901_V1(rev) ((rev) == PM_8901_REV_1p0 || \
- (rev) == PM_8901_REV_1p1)
-
-#define PMIC_8901_V1_SCALE(uV) ((((uV) - 62100) * 23) / 25)
-
static inline int vreg_hpm_min_uA(struct vreg *vreg)
{
return vreg->hpm_min_load;
@@ -512,9 +570,19 @@
return vreg->hpm_min_load - LOAD_THRESHOLD_STEP;
}
-static inline unsigned saturate_load(unsigned load_uA)
+static inline unsigned saturate_peak_load(struct vreg *vreg, unsigned load_uA)
{
- return (load_uA > MAX_POSSIBLE_LOAD ? MAX_POSSIBLE_LOAD : load_uA);
+ unsigned load_max
+ = MILLI_TO_MICRO(vreg->part->ip.mask >> vreg->part->ip.shift);
+
+ return (load_uA > load_max ? load_max : load_uA);
+}
+
+static inline unsigned saturate_avg_load(struct vreg *vreg, unsigned load_uA)
+{
+ unsigned load_max
+ = MILLI_TO_MICRO(vreg->part->ia.mask >> vreg->part->ia.shift);
+ return (load_uA > load_max ? load_max : load_uA);
}
/* Change vreg->req, but do not send it to the RPM. */
@@ -523,8 +591,8 @@
{
unsigned long flags = 0;
- if (vreg->pdata->sleep_selectable)
- spin_lock_irqsave(&pm8058_noirq_lock, flags);
+ if (vreg->pdata.sleep_selectable)
+ spin_lock_irqsave(&rpm_noirq_lock, flags);
vreg->req[0].value &= ~mask0;
vreg->req[0].value |= val0 & mask0;
@@ -532,8 +600,8 @@
vreg->req[1].value &= ~mask1;
vreg->req[1].value |= val1 & mask1;
- if (vreg->pdata->sleep_selectable)
- spin_unlock_irqrestore(&pm8058_noirq_lock, flags);
+ if (vreg->pdata.sleep_selectable)
+ spin_unlock_irqrestore(&rpm_noirq_lock, flags);
return 0;
}
@@ -548,7 +616,7 @@
* Bypass the normal route for regulators that can be called to change
* just the active set values.
*/
- if (vreg->pdata->sleep_selectable)
+ if (vreg->pdata.sleep_selectable)
return vreg_set_noirq(vreg, RPM_VREG_VOTER_REG_FRAMEWORK, 1,
mask0, val0, mask1, val1, cnt, 1);
@@ -564,7 +632,7 @@
if (vreg->req[0].value == vreg->prev_active_req[0].value &&
vreg->req[1].value == vreg->prev_active_req[1].value) {
if (msm_rpm_vreg_debug_mask & MSM_RPM_VREG_DEBUG_DUPLICATE)
- print_rpm_duplicate(vreg, MSM_RPM_CTX_SET_0, cnt);
+ rpm_regulator_duplicate(vreg, MSM_RPM_CTX_SET_0, cnt);
return 0;
}
@@ -573,11 +641,11 @@
vreg->req[0].value = prev0;
vreg->req[1].value = prev1;
- pr_err("%s: msm_rpm_set fail id=%d, rc=%d\n",
- __func__, vreg->req[0].id, rc);
+ vreg_err(vreg, "msm_rpm_set failed, set=active, id=%d, rc=%d\n",
+ vreg->req[0].id, rc);
} else {
if (msm_rpm_vreg_debug_mask & MSM_RPM_VREG_DEBUG_REQUEST)
- print_rpm_request(vreg, MSM_RPM_CTX_SET_0);
+ rpm_regulator_req(vreg, MSM_RPM_CTX_SET_0);
vreg->prev_active_req[0].value = vreg->req[0].value;
vreg->prev_active_req[1].value = vreg->req[1].value;
}
@@ -585,880 +653,736 @@
return rc;
}
-static int smps_is_enabled(struct regulator_dev *dev)
+static int vreg_is_enabled(struct regulator_dev *rdev)
{
- struct vreg *vreg = rdev_get_drvdata(dev);
- return ((vreg->req[0].value & SMPS_VOLTAGE) >> SMPS_VOLTAGE_SHIFT) != 0;
+ struct vreg *vreg = rdev_get_drvdata(rdev);
+ int enabled;
+
+ mutex_lock(&vreg->pc_lock);
+ enabled = vreg->is_enabled;
+ mutex_unlock(&vreg->pc_lock);
+
+ return enabled;
}
-static int _smps_set_voltage(struct regulator_dev *dev, int min_uV)
+static void set_enable(struct vreg *vreg, unsigned int *mask, unsigned int *val)
{
- struct vreg *vreg = rdev_get_drvdata(dev);
- int scaled_min_uV = min_uV;
- static int pmic8901_rev;
-
- /* Scale input request voltage down if using v1 PMIC 8901. */
- if (IS_8901_SMPS(vreg->id) && min_uV) {
- if (pmic8901_rev <= 0)
- pmic8901_rev = pm8901_rev(NULL);
-
- if (pmic8901_rev < 0)
- pr_err("%s: setting %s to %d uV; PMIC 8901 revision "
- "unavailable, no scaling can be performed.\n",
- __func__, dev->desc->name, min_uV);
- else if (IS_PMIC_8901_V1(pmic8901_rev))
- scaled_min_uV = PMIC_8901_V1_SCALE(min_uV);
+ switch (vreg->type) {
+ case RPM_REGULATOR_TYPE_LDO:
+ case RPM_REGULATOR_TYPE_SMPS:
+ /* Enable by setting a voltage. */
+ if (vreg->part->uV.mask) {
+ val[vreg->part->uV.word]
+ |= vreg->save_uV << vreg->part->uV.shift;
+ mask[vreg->part->uV.word] |= vreg->part->uV.mask;
+ } else {
+ val[vreg->part->mV.word]
+ |= MICRO_TO_MILLI(vreg->save_uV)
+ << vreg->part->mV.shift;
+ mask[vreg->part->mV.word] |= vreg->part->mV.mask;
+ }
+ break;
+ case RPM_REGULATOR_TYPE_VS:
+ case RPM_REGULATOR_TYPE_NCP:
+ /* Enable by setting enable_state. */
+ val[vreg->part->enable_state.word]
+ |= RPM_VREG_STATE_ON << vreg->part->enable_state.shift;
+ mask[vreg->part->enable_state.word]
+ |= vreg->part->enable_state.mask;
}
-
- return vreg_set(vreg, SMPS_VOLTAGE,
- MICRO_TO_MILLI(scaled_min_uV) << SMPS_VOLTAGE_SHIFT,
- 0, 0, 2);
}
-static int smps_set_voltage(struct regulator_dev *dev, int min_uV, int max_uV,
+static int vreg_enable(struct regulator_dev *rdev)
+{
+ struct vreg *vreg = rdev_get_drvdata(rdev);
+ unsigned int mask[2] = {0}, val[2] = {0};
+ int rc = 0;
+
+ set_enable(vreg, mask, val);
+
+ mutex_lock(&vreg->pc_lock);
+
+ rc = vreg_set(vreg, mask[0], val[0], mask[1], val[1],
+ vreg->part->request_len);
+ if (!rc)
+ vreg->is_enabled = true;
+
+ mutex_unlock(&vreg->pc_lock);
+
+ if (rc)
+ vreg_err(vreg, "vreg_set failed, rc=%d\n", rc);
+
+ return rc;
+}
+
+static void set_disable(struct vreg *vreg, unsigned int *mask,
+ unsigned int *val)
+{
+ switch (vreg->type) {
+ case RPM_REGULATOR_TYPE_LDO:
+ case RPM_REGULATOR_TYPE_SMPS:
+ /* Disable by setting a voltage of 0 uV. */
+ if (vreg->part->uV.mask) {
+ val[vreg->part->uV.word] |= 0 << vreg->part->uV.shift;
+ mask[vreg->part->uV.word] |= vreg->part->uV.mask;
+ } else {
+ val[vreg->part->mV.word] |= 0 << vreg->part->mV.shift;
+ mask[vreg->part->mV.word] |= vreg->part->mV.mask;
+ }
+ break;
+ case RPM_REGULATOR_TYPE_VS:
+ case RPM_REGULATOR_TYPE_NCP:
+ /* Disable by setting enable_state. */
+ val[vreg->part->enable_state.word]
+ |= RPM_VREG_STATE_OFF << vreg->part->enable_state.shift;
+ mask[vreg->part->enable_state.word]
+ |= vreg->part->enable_state.mask;
+ }
+}
+
+static int vreg_disable(struct regulator_dev *rdev)
+{
+ struct vreg *vreg = rdev_get_drvdata(rdev);
+ unsigned int mask[2] = {0}, val[2] = {0};
+ int rc = 0;
+
+ set_disable(vreg, mask, val);
+
+ mutex_lock(&vreg->pc_lock);
+
+ /* Only disable if pin control is not in use. */
+ if (!vreg->is_enabled_pc)
+ rc = vreg_set(vreg, mask[0], val[0], mask[1], val[1],
+ vreg->part->request_len);
+
+ if (!rc)
+ vreg->is_enabled = false;
+
+ mutex_unlock(&vreg->pc_lock);
+
+ if (rc)
+ vreg_err(vreg, "vreg_set failed, rc=%d\n", rc);
+
+ return rc;
+}
+
+static int vreg_set_voltage(struct regulator_dev *rdev, int min_uV, int max_uV,
unsigned *selector)
{
- struct vreg *vreg = rdev_get_drvdata(dev);
- int rc = 0;
+ struct vreg *vreg = rdev_get_drvdata(rdev);
+ struct vreg_range *range = &vreg->set_points->range[0];
+ unsigned int mask[2] = {0}, val[2] = {0};
+ int rc = 0, uV = min_uV;
+ int lim_min_uV, lim_max_uV, i;
- if (smps_is_enabled(dev))
- rc = _smps_set_voltage(dev, min_uV);
- if (rc)
- return rc;
+ /* Check if request voltage is outside of physically settable range. */
+ lim_min_uV = vreg->set_points->range[0].min_uV;
+ lim_max_uV =
+ vreg->set_points->range[vreg->set_points->count - 1].max_uV;
- /* only save if nonzero (or not disabling) */
- if (min_uV && (!vreg->pdata->sleep_selectable || !smps_is_enabled(dev)))
- vreg->save_uV = min_uV;
+ if (uV < lim_min_uV && max_uV >= lim_min_uV)
+ uV = lim_min_uV;
- return rc;
-}
-
-static int smps_get_voltage(struct regulator_dev *dev)
-{
- struct vreg *vreg = rdev_get_drvdata(dev);
- return vreg->save_uV;
-}
-
-static int smps_enable(struct regulator_dev *dev)
-{
- struct vreg *vreg = rdev_get_drvdata(dev);
- int rc = 0;
- unsigned mask, val;
-
- /* enable by setting voltage */
- if (MICRO_TO_MILLI(vreg->save_uV) > 0) {
- /* reenable pin control if it is in use */
- if (smps_get_mode(dev) == REGULATOR_MODE_IDLE) {
- mask = SMPS_PIN_CTRL | SMPS_PIN_FN;
- val = vreg->pdata->pin_ctrl << SMPS_PIN_CTRL_SHIFT
- | vreg->pdata->pin_fn << SMPS_PIN_FN_SHIFT;
- vreg_store(vreg, mask, val, 0, 0);
- }
-
- rc = _smps_set_voltage(dev, vreg->save_uV);
- }
- return rc;
-}
-
-static int smps_disable(struct regulator_dev *dev)
-{
- struct vreg *vreg = rdev_get_drvdata(dev);
- unsigned mask, val;
-
- /* turn off pin control */
- mask = SMPS_PIN_CTRL | SMPS_PIN_FN;
- val = RPM_VREG_PIN_CTRL_NONE << SMPS_PIN_CTRL_SHIFT
- | RPM_VREG_PIN_FN_NONE << SMPS_PIN_FN_SHIFT;
- vreg_store(vreg, mask, val, 0, 0);
-
- /* disable by setting voltage to zero */
- return _smps_set_voltage(dev, 0);
-}
-
-/*
- * Optimum mode programming:
- * REGULATOR_MODE_FAST: Go to HPM (highest priority)
- * REGULATOR_MODE_STANDBY: Go to pin ctrl mode if there are any pin ctrl
- * votes, else go to LPM
- *
- * Pin ctrl mode voting via regulator set_mode:
- * REGULATOR_MODE_IDLE: Go to pin ctrl mode if the optimum mode is LPM, else
- * go to HPM
- * REGULATOR_MODE_NORMAL: Go to LPM if it is the optimum mode, else go to HPM
- *
- * Pin ctrl mode takes priority on the RPM when force mode is not set;
- * therefore, pin ctrl bits must be cleared if LPM or HPM is being voted for.
- */
-static int smps_set_mode(struct regulator_dev *dev, unsigned int mode)
-{
- struct vreg *vreg = rdev_get_drvdata(dev);
- unsigned optimum = vreg->optimum;
- unsigned pc_vote = vreg->pc_vote;
- unsigned mode_initialized = vreg->mode_initialized;
- unsigned mask0 = 0, val0 = 0, mask1 = 0, val1 = 0;
- int set_hpm = -1, set_pin_control = -1;
- int peak_uA;
- int rc = 0;
-
- peak_uA = MILLI_TO_MICRO((vreg->req[0].value & SMPS_PEAK_CURRENT) >>
- SMPS_PEAK_CURRENT_SHIFT);
-
- switch (mode) {
- case REGULATOR_MODE_FAST:
- set_hpm = 1;
- set_pin_control = 0;
- optimum = REGULATOR_MODE_FAST;
- mode_initialized = 1;
- break;
-
- case REGULATOR_MODE_STANDBY:
- set_hpm = 0;
- if (pc_vote)
- set_pin_control = 1;
- else
- set_pin_control = 0;
- optimum = REGULATOR_MODE_STANDBY;
- mode_initialized = 1;
- break;
-
- case REGULATOR_MODE_IDLE:
- if (pc_vote++)
- goto done; /* already taken care of */
-
- if (mode_initialized && optimum == REGULATOR_MODE_FAST) {
- set_hpm = 1;
- set_pin_control = 0;
- } else {
- set_pin_control = 1;
- }
- break;
-
- case REGULATOR_MODE_NORMAL:
- if (pc_vote && --pc_vote)
- goto done; /* already taken care of */
-
- if (optimum == REGULATOR_MODE_STANDBY)
- set_hpm = 0;
- else
- set_hpm = 1;
- set_pin_control = 0;
- break;
-
- default:
+ if (uV < lim_min_uV || uV > lim_max_uV) {
+ vreg_err(vreg,
+ "request v=[%d, %d] is outside possible v=[%d, %d]\n",
+ min_uV, max_uV, lim_min_uV, lim_max_uV);
return -EINVAL;
}
- if (set_hpm == 1) {
- /* Make sure that request currents are at HPM level. */
- if (peak_uA < vreg_hpm_min_uA(vreg)) {
- mask0 = SMPS_PEAK_CURRENT;
- mask1 = SMPS_AVG_CURRENT;
- val0 = (MICRO_TO_MILLI(vreg_hpm_min_uA(vreg)) <<
- SMPS_PEAK_CURRENT_SHIFT) & SMPS_PEAK_CURRENT;
- val1 = (MICRO_TO_MILLI(vreg_hpm_min_uA(vreg)) <<
- SMPS_AVG_CURRENT_SHIFT) & SMPS_AVG_CURRENT;
- }
- } else if (set_hpm == 0) {
- /* Make sure that request currents are at LPM level. */
- if (peak_uA > vreg_lpm_max_uA(vreg)) {
- mask0 = SMPS_PEAK_CURRENT;
- mask1 = SMPS_AVG_CURRENT;
- val0 = (MICRO_TO_MILLI(vreg_lpm_max_uA(vreg)) <<
- SMPS_PEAK_CURRENT_SHIFT) & SMPS_PEAK_CURRENT;
- val1 = (MICRO_TO_MILLI(vreg_lpm_max_uA(vreg)) <<
- SMPS_AVG_CURRENT_SHIFT) & SMPS_AVG_CURRENT;
+ /* Find the range which uV is inside of. */
+ for (i = vreg->set_points->count - 1; i > 0; i--) {
+ if (uV > vreg->set_points->range[i - 1].max_uV) {
+ range = &vreg->set_points->range[i];
+ break;
}
}
- if (set_pin_control == 1) {
- /* Enable pin control and pin function. */
- mask0 |= SMPS_PIN_CTRL | SMPS_PIN_FN;
- val0 |= vreg->pdata->pin_ctrl << SMPS_PIN_CTRL_SHIFT
- | vreg->pdata->pin_fn << SMPS_PIN_FN_SHIFT;
- } else if (set_pin_control == 0) {
- /* Clear pin control and pin function*/
- mask0 |= SMPS_PIN_CTRL | SMPS_PIN_FN;
- val0 |= RPM_VREG_PIN_CTRL_NONE << SMPS_PIN_CTRL_SHIFT
- | RPM_VREG_PIN_FN_NONE << SMPS_PIN_FN_SHIFT;
- }
+ /*
+ * Force uV to be an allowed set point and apply a ceiling function
+ * to non-set point values.
+ */
+ uV = (uV - range->min_uV + range->step_uV - 1) / range->step_uV;
+ uV = uV * range->step_uV + range->min_uV;
- if (smps_is_enabled(dev)) {
- rc = vreg_set(vreg, mask0, val0, mask1, val1, 2);
+ if (vreg->part->uV.mask) {
+ val[vreg->part->uV.word] = uV << vreg->part->uV.shift;
+ mask[vreg->part->uV.word] = vreg->part->uV.mask;
} else {
+ val[vreg->part->mV.word]
+ = MICRO_TO_MILLI(uV) << vreg->part->mV.shift;
+ mask[vreg->part->mV.word] = vreg->part->mV.mask;
+ }
+
+ mutex_lock(&vreg->pc_lock);
+
+ /*
+ * Only send a request for a new voltage if the regulator is currently
+ * enabled. This will ensure that LDO and SMPS regulators are not
+ * inadvertently turned on because voltage > 0 is equivalent to
+ * enabling. For NCP, this just removes unnecessary RPM requests.
+ */
+ if (vreg->is_enabled) {
+ rc = vreg_set(vreg, mask[0], val[0], mask[1], val[1],
+ vreg->part->request_len);
+ if (rc)
+ vreg_err(vreg, "vreg_set failed, rc=%d\n", rc);
+ } else if (vreg->type == RPM_REGULATOR_TYPE_NCP) {
/* Regulator is disabled; store but don't send new request. */
- rc = vreg_store(vreg, mask0, val0, mask1, val1);
- }
- if (rc)
- return rc;
-
-done:
- vreg->mode_initialized = mode_initialized;
- vreg->optimum = optimum;
- vreg->pc_vote = pc_vote;
-
- return 0;
-}
-
-static unsigned int smps_get_mode(struct regulator_dev *dev)
-{
- struct vreg *vreg = rdev_get_drvdata(dev);
-
- if ((vreg->optimum == REGULATOR_MODE_FAST) && vreg->mode_initialized)
- return REGULATOR_MODE_FAST;
- else if (vreg->pc_vote)
- return REGULATOR_MODE_IDLE;
- else if (vreg->optimum == REGULATOR_MODE_STANDBY)
- return REGULATOR_MODE_STANDBY;
- return REGULATOR_MODE_FAST;
-}
-
-unsigned int smps_get_optimum_mode(struct regulator_dev *dev, int input_uV,
- int output_uV, int load_uA)
-{
- struct vreg *vreg = rdev_get_drvdata(dev);
-
- if (MICRO_TO_MILLI(load_uA) > 0) {
- vreg->req[0].value &= ~SMPS_PEAK_CURRENT;
- vreg->req[0].value |= (MICRO_TO_MILLI(saturate_load(load_uA)) <<
- SMPS_PEAK_CURRENT_SHIFT) & SMPS_PEAK_CURRENT;
- vreg->req[1].value &= ~SMPS_AVG_CURRENT;
- vreg->req[1].value |= (MICRO_TO_MILLI(saturate_load(load_uA)) <<
- SMPS_AVG_CURRENT_SHIFT) & SMPS_AVG_CURRENT;
- } else {
- /*
- * smps_get_optimum_mode is being called before consumers have
- * specified their load currents via regulator_set_optimum_mode.
- * Return whatever the existing mode is.
- */
- return smps_get_mode(dev);
+ rc = vreg_store(vreg, mask[0], val[0], mask[1], val[1]);
}
- if (load_uA >= vreg->hpm_min_load)
- return REGULATOR_MODE_FAST;
- return REGULATOR_MODE_STANDBY;
-}
+ if (!rc && (!vreg->pdata.sleep_selectable || !vreg->is_enabled))
+ vreg->save_uV = uV;
-static int ldo_is_enabled(struct regulator_dev *dev)
-{
- struct vreg *vreg = rdev_get_drvdata(dev);
- return ((vreg->req[0].value & LDO_VOLTAGE) >> LDO_VOLTAGE_SHIFT) != 0;
-}
-
-static int _ldo_set_voltage(struct regulator_dev *dev, int min_uV)
-{
- struct vreg *vreg = rdev_get_drvdata(dev);
-
- return vreg_set(vreg, LDO_VOLTAGE,
- MICRO_TO_MILLI(min_uV) << LDO_VOLTAGE_SHIFT,
- 0, 0, 2);
-}
-
-static int ldo_set_voltage(struct regulator_dev *dev, int min_uV, int max_uV,
- unsigned *selector)
-{
- struct vreg *vreg = rdev_get_drvdata(dev);
- int rc = 0;
-
- if (ldo_is_enabled(dev))
- rc = _ldo_set_voltage(dev, min_uV);
- if (rc)
- return rc;
-
- /* only save if nonzero (or not disabling) */
- if (min_uV && (!vreg->pdata->sleep_selectable || !ldo_is_enabled(dev)))
- vreg->save_uV = min_uV;
+ mutex_unlock(&vreg->pc_lock);
return rc;
}
-static int ldo_get_voltage(struct regulator_dev *dev)
+static int vreg_get_voltage(struct regulator_dev *rdev)
{
- struct vreg *vreg = rdev_get_drvdata(dev);
+ struct vreg *vreg = rdev_get_drvdata(rdev);
+
return vreg->save_uV;
}
-static int ldo_enable(struct regulator_dev *dev)
+static int vreg_list_voltage(struct regulator_dev *rdev, unsigned selector)
{
- struct vreg *vreg = rdev_get_drvdata(dev);
- int rc = 0;
- unsigned mask, val;
+ struct vreg *vreg = rdev_get_drvdata(rdev);
+ int uV = 0;
+ int i;
- /* enable by setting voltage */
- if (MICRO_TO_MILLI(vreg->save_uV) > 0) {
- /* reenable pin control if it is in use */
- if (ldo_get_mode(dev) == REGULATOR_MODE_IDLE) {
- mask = LDO_PIN_CTRL | LDO_PIN_FN;
- val = vreg->pdata->pin_ctrl << LDO_PIN_CTRL_SHIFT
- | vreg->pdata->pin_fn << LDO_PIN_FN_SHIFT;
- vreg_store(vreg, mask, val, 0, 0);
- }
-
- rc = _ldo_set_voltage(dev, vreg->save_uV);
- }
- return rc;
-}
-
-static int ldo_disable(struct regulator_dev *dev)
-{
- struct vreg *vreg = rdev_get_drvdata(dev);
- unsigned mask, val;
-
- /* turn off pin control */
- mask = LDO_PIN_CTRL | LDO_PIN_FN;
- val = RPM_VREG_PIN_CTRL_NONE << LDO_PIN_CTRL_SHIFT
- | RPM_VREG_PIN_FN_NONE << LDO_PIN_FN_SHIFT;
- vreg_store(vreg, mask, val, 0, 0);
-
- /* disable by setting voltage to zero */
- return _ldo_set_voltage(dev, 0);
-}
-
-/*
- * Optimum mode programming:
- * REGULATOR_MODE_FAST: Go to HPM (highest priority)
- * REGULATOR_MODE_STANDBY: Go to pin ctrl mode if there are any pin ctrl
- * votes, else go to LPM
- *
- * Pin ctrl mode voting via regulator set_mode:
- * REGULATOR_MODE_IDLE: Go to pin ctrl mode if the optimum mode is LPM, else
- * go to HPM
- * REGULATOR_MODE_NORMAL: Go to LPM if it is the optimum mode, else go to HPM
- *
- * Pin ctrl mode takes priority on the RPM when force mode is not set;
- * therefore, pin ctrl bits must be cleared if LPM or HPM is being voted for.
- */
-static int ldo_set_mode(struct regulator_dev *dev, unsigned int mode)
-{
- struct vreg *vreg = rdev_get_drvdata(dev);
- unsigned optimum = vreg->optimum;
- unsigned pc_vote = vreg->pc_vote;
- unsigned mode_initialized = vreg->mode_initialized;
- unsigned mask0 = 0, val0 = 0, mask1 = 0, val1 = 0;
- int set_hpm = -1, set_pin_control = -1;
- int peak_uA;
- int rc = 0;
-
- peak_uA = MILLI_TO_MICRO((vreg->req[0].value & LDO_PEAK_CURRENT) >>
- LDO_PEAK_CURRENT_SHIFT);
-
- switch (mode) {
- case REGULATOR_MODE_FAST:
- set_hpm = 1;
- set_pin_control = 0;
- optimum = REGULATOR_MODE_FAST;
- mode_initialized = 1;
- break;
-
- case REGULATOR_MODE_STANDBY:
- set_hpm = 0;
- if (pc_vote)
- set_pin_control = 1;
- else
- set_pin_control = 0;
- optimum = REGULATOR_MODE_STANDBY;
- mode_initialized = 1;
- break;
-
- case REGULATOR_MODE_IDLE:
- if (pc_vote++)
- goto done; /* already taken care of */
-
- if (mode_initialized && optimum == REGULATOR_MODE_FAST) {
- set_hpm = 1;
- set_pin_control = 0;
- } else {
- set_pin_control = 1;
- }
- break;
-
- case REGULATOR_MODE_NORMAL:
- if (pc_vote && --pc_vote)
- goto done; /* already taken care of */
-
- if (optimum == REGULATOR_MODE_STANDBY)
- set_hpm = 0;
- else
- set_hpm = 1;
- set_pin_control = 0;
- break;
-
- default:
+ if (!vreg->set_points) {
+ vreg_err(vreg, "no voltages available\n");
return -EINVAL;
}
- if (set_hpm == 1) {
- /* Make sure that request currents are at HPM level. */
+ if (selector >= vreg->set_points->n_voltages)
+ return 0;
+
+ for (i = 0; i < vreg->set_points->count; i++) {
+ if (selector < vreg->set_points->range[i].n_voltages) {
+ uV = selector * vreg->set_points->range[i].step_uV
+ + vreg->set_points->range[i].min_uV;
+ break;
+ } else {
+ selector -= vreg->set_points->range[i].n_voltages;
+ }
+ }
+
+ return uV;
+}
+
+static int vreg_set_mode(struct regulator_dev *rdev, unsigned int mode)
+{
+ struct vreg *vreg = rdev_get_drvdata(rdev);
+ unsigned int mask[2] = {0}, val[2] = {0};
+ int rc = 0;
+ int peak_uA;
+
+ mutex_lock(&vreg->pc_lock);
+
+ peak_uA = MILLI_TO_MICRO((vreg->req[vreg->part->ip.word].value
+ & vreg->part->ip.mask) >> vreg->part->ip.shift);
+
+ if (mode == config->mode_hpm) {
+ /* Make sure that request currents are in HPM range. */
if (peak_uA < vreg_hpm_min_uA(vreg)) {
- mask0 = LDO_PEAK_CURRENT;
- mask1 = LDO_AVG_CURRENT;
- val0 = (MICRO_TO_MILLI(vreg_hpm_min_uA(vreg)) <<
- LDO_PEAK_CURRENT_SHIFT) & LDO_PEAK_CURRENT;
- val1 = (MICRO_TO_MILLI(vreg_hpm_min_uA(vreg)) <<
- LDO_AVG_CURRENT_SHIFT) & LDO_AVG_CURRENT;
+ val[vreg->part->ip.word]
+ = MICRO_TO_MILLI(vreg_hpm_min_uA(vreg))
+ << vreg->part->ip.shift;
+ mask[vreg->part->ip.word] = vreg->part->ip.mask;
+
+ if (config->ia_follows_ip) {
+ val[vreg->part->ia.word]
+ |= MICRO_TO_MILLI(vreg_hpm_min_uA(vreg))
+ << vreg->part->ia.shift;
+ mask[vreg->part->ia.word]
+ |= vreg->part->ia.mask;
+ }
}
- } else if (set_hpm == 0) {
- /* Make sure that request currents are at LPM level. */
+ } else if (mode == config->mode_lpm) {
+ /* Make sure that request currents are in LPM range. */
if (peak_uA > vreg_lpm_max_uA(vreg)) {
- mask0 = LDO_PEAK_CURRENT;
- mask1 = LDO_AVG_CURRENT;
- val0 = (MICRO_TO_MILLI(vreg_lpm_max_uA(vreg)) <<
- LDO_PEAK_CURRENT_SHIFT) & LDO_PEAK_CURRENT;
- val1 = (MICRO_TO_MILLI(vreg_lpm_max_uA(vreg)) <<
- LDO_AVG_CURRENT_SHIFT) & LDO_AVG_CURRENT;
+ val[vreg->part->ip.word]
+ = MICRO_TO_MILLI(vreg_lpm_max_uA(vreg))
+ << vreg->part->ip.shift;
+ mask[vreg->part->ip.word] = vreg->part->ip.mask;
+
+ if (config->ia_follows_ip) {
+ val[vreg->part->ia.word]
+ |= MICRO_TO_MILLI(vreg_lpm_max_uA(vreg))
+ << vreg->part->ia.shift;
+ mask[vreg->part->ia.word]
+ |= vreg->part->ia.mask;
+ }
}
+ } else {
+ vreg_err(vreg, "invalid mode: %u\n", mode);
+ mutex_unlock(&vreg->pc_lock);
+ return -EINVAL;
}
- if (set_pin_control == 1) {
- /* Enable pin control and pin function. */
- mask0 |= LDO_PIN_CTRL | LDO_PIN_FN;
- val0 |= vreg->pdata->pin_ctrl << LDO_PIN_CTRL_SHIFT
- | vreg->pdata->pin_fn << LDO_PIN_FN_SHIFT;
- } else if (set_pin_control == 0) {
- /* Clear pin control and pin function*/
- mask0 |= LDO_PIN_CTRL | LDO_PIN_FN;
- val0 |= RPM_VREG_PIN_CTRL_NONE << LDO_PIN_CTRL_SHIFT
- | RPM_VREG_PIN_FN_NONE << LDO_PIN_FN_SHIFT;
- }
-
- if (ldo_is_enabled(dev)) {
- rc = vreg_set(vreg, mask0, val0, mask1, val1, 2);
+ if (vreg->is_enabled) {
+ rc = vreg_set(vreg, mask[0], val[0], mask[1], val[1],
+ vreg->part->request_len);
} else {
/* Regulator is disabled; store but don't send new request. */
- rc = vreg_store(vreg, mask0, val0, mask1, val1);
+ rc = vreg_store(vreg, mask[0], val[0], mask[1], val[1]);
}
+
if (rc)
- return rc;
+ vreg_err(vreg, "vreg_set failed, rc=%d\n", rc);
+ else
+ vreg->mode = mode;
-done:
- vreg->mode_initialized = mode_initialized;
- vreg->optimum = optimum;
- vreg->pc_vote = pc_vote;
+ mutex_unlock(&vreg->pc_lock);
- return 0;
+ return rc;
}
-static unsigned int ldo_get_mode(struct regulator_dev *dev)
+static unsigned int vreg_get_mode(struct regulator_dev *rdev)
{
- struct vreg *vreg = rdev_get_drvdata(dev);
+ struct vreg *vreg = rdev_get_drvdata(rdev);
- if ((vreg->optimum == REGULATOR_MODE_FAST) && vreg->mode_initialized)
- return REGULATOR_MODE_FAST;
- else if (vreg->pc_vote)
- return REGULATOR_MODE_IDLE;
- else if (vreg->optimum == REGULATOR_MODE_STANDBY)
- return REGULATOR_MODE_STANDBY;
- return REGULATOR_MODE_FAST;
+ return vreg->mode;
}
-unsigned int ldo_get_optimum_mode(struct regulator_dev *dev, int input_uV,
- int output_uV, int load_uA)
+static unsigned int vreg_get_optimum_mode(struct regulator_dev *rdev,
+ int input_uV, int output_uV, int load_uA)
{
- struct vreg *vreg = rdev_get_drvdata(dev);
+ struct vreg *vreg = rdev_get_drvdata(rdev);
+ unsigned int mode;
- if (MICRO_TO_MILLI(load_uA) > 0) {
- vreg->req[0].value &= ~LDO_PEAK_CURRENT;
- vreg->req[0].value |= (MICRO_TO_MILLI(saturate_load(load_uA)) <<
- LDO_PEAK_CURRENT_SHIFT) & LDO_PEAK_CURRENT;
- vreg->req[1].value &= ~LDO_AVG_CURRENT;
- vreg->req[1].value |= (MICRO_TO_MILLI(saturate_load(load_uA)) <<
- LDO_AVG_CURRENT_SHIFT) & LDO_AVG_CURRENT;
- } else {
- /*
- * ldo_get_optimum_mode is being called before consumers have
- * specified their load currents via regulator_set_optimum_mode.
- * Return whatever the existing mode is.
- */
- return ldo_get_mode(dev);
- }
+ load_uA += vreg->pdata.system_uA;
+
+ mutex_lock(&vreg->pc_lock);
+ SET_PART(vreg, ip, MICRO_TO_MILLI(saturate_peak_load(vreg, load_uA)));
+ if (config->ia_follows_ip)
+ SET_PART(vreg, ia,
+ MICRO_TO_MILLI(saturate_avg_load(vreg, load_uA)));
+ mutex_unlock(&vreg->pc_lock);
if (load_uA >= vreg->hpm_min_load)
- return REGULATOR_MODE_FAST;
- return REGULATOR_MODE_STANDBY;
+ mode = config->mode_hpm;
+ else
+ mode = config->mode_lpm;
+
+ return mode;
}
-static int switch_enable(struct regulator_dev *dev)
+static unsigned int vreg_legacy_get_optimum_mode(struct regulator_dev *rdev,
+ int input_uV, int output_uV, int load_uA)
{
- struct vreg *vreg = rdev_get_drvdata(dev);
- unsigned mask = 0, val = 0;
+ struct vreg *vreg = rdev_get_drvdata(rdev);
- /* reenable pin control if it is in use */
- if (switch_get_mode(dev) == REGULATOR_MODE_IDLE) {
- mask = SWITCH_PIN_CTRL | SWITCH_PIN_FN;
- val = vreg->pdata->pin_ctrl << SWITCH_PIN_CTRL_SHIFT
- | vreg->pdata->pin_fn << SWITCH_PIN_FN_SHIFT;
+ if (MICRO_TO_MILLI(load_uA) <= 0) {
+ /*
+ * vreg_legacy_get_optimum_mode is being called before consumers
+ * have specified their load currents via
+ * regulator_set_optimum_mode. Return whatever the existing mode
+ * is.
+ */
+ return vreg->mode;
}
- return vreg_set(rdev_get_drvdata(dev), SWITCH_STATE | mask,
- (RPM_VREG_STATE_ON << SWITCH_STATE_SHIFT) | val, 0, 0, 1);
-}
-
-static int switch_disable(struct regulator_dev *dev)
-{
- unsigned mask, val;
-
- /* turn off pin control */
- mask = SWITCH_PIN_CTRL | SWITCH_PIN_FN;
- val = RPM_VREG_PIN_CTRL_NONE << SWITCH_PIN_CTRL_SHIFT
- | RPM_VREG_PIN_FN_NONE << SWITCH_PIN_FN_SHIFT;
-
- return vreg_set(rdev_get_drvdata(dev), SWITCH_STATE | mask,
- (RPM_VREG_STATE_OFF << SWITCH_STATE_SHIFT) | val, 0, 0, 1);
-}
-
-static int switch_is_enabled(struct regulator_dev *dev)
-{
- struct vreg *vreg = rdev_get_drvdata(dev);
- enum rpm_vreg_state state;
-
- state = (vreg->req[0].value & SWITCH_STATE) >> SWITCH_STATE_SHIFT;
-
- return state == RPM_VREG_STATE_ON;
+ return vreg_get_optimum_mode(rdev, input_uV, output_uV, load_uA);
}
/*
- * Pin ctrl mode voting via regulator set_mode:
- * REGULATOR_MODE_IDLE: Go to pin ctrl mode if the optimum mode is LPM, else
- * go to HPM
- * REGULATOR_MODE_NORMAL: Go to LPM if it is the optimum mode, else go to HPM
+ * Returns the logical pin control enable state because the pin control options
+ * present in the hardware out of restart could be different from those desired
+ * by the consumer.
*/
-static int switch_set_mode(struct regulator_dev *dev, unsigned int mode)
+static int vreg_pin_control_is_enabled(struct regulator_dev *rdev)
{
- struct vreg *vreg = rdev_get_drvdata(dev);
- unsigned pc_vote = vreg->pc_vote;
- unsigned mask, val;
+ struct vreg *vreg = rdev_get_drvdata(rdev);
+
+ return vreg->is_enabled_pc;
+}
+
+static int vreg_pin_control_enable(struct regulator_dev *rdev)
+{
+ struct vreg *vreg = rdev_get_drvdata(rdev);
+ unsigned int mask[2] = {0}, val[2] = {0};
int rc;
- switch (mode) {
- case REGULATOR_MODE_IDLE:
- if (pc_vote++)
- goto done; /* already taken care of */
+ mutex_lock(&vreg->pc_lock);
- mask = SWITCH_PIN_CTRL | SWITCH_PIN_FN;
- val = vreg->pdata->pin_ctrl << SWITCH_PIN_CTRL_SHIFT
- | vreg->pdata->pin_fn << SWITCH_PIN_FN_SHIFT;
- break;
+ val[vreg->part->pc.word]
+ |= vreg->pdata.pin_ctrl << vreg->part->pc.shift;
+ mask[vreg->part->pc.word] |= vreg->part->pc.mask;
- case REGULATOR_MODE_NORMAL:
- if (--pc_vote)
- goto done; /* already taken care of */
+ val[vreg->part->pf.word] |= vreg->pdata.pin_fn << vreg->part->pf.shift;
+ mask[vreg->part->pf.word] |= vreg->part->pf.mask;
- mask = SWITCH_PIN_CTRL | SWITCH_PIN_FN;
- val = RPM_VREG_PIN_CTRL_NONE << SWITCH_PIN_CTRL_SHIFT
- | RPM_VREG_PIN_FN_NONE << SWITCH_PIN_FN_SHIFT;
- break;
+ if (!vreg->is_enabled)
+ set_enable(vreg, mask, val);
- default:
- return -EINVAL;
- }
+ rc = vreg_set(vreg, mask[0], val[0], mask[1], val[1],
+ vreg->part->request_len);
- if (switch_is_enabled(dev)) {
- rc = vreg_set(vreg, mask, val, 0, 0, 2);
- } else {
- /* Regulator is disabled; store but don't send new request. */
- rc = vreg_store(vreg, mask, val, 0, 0);
- }
+ if (!rc)
+ vreg->is_enabled_pc = true;
+
+ mutex_unlock(&vreg->pc_lock);
+
if (rc)
- return rc;
+ vreg_err(vreg, "vreg_set failed, rc=%d\n", rc);
-done:
- vreg->pc_vote = pc_vote;
- return 0;
+ return rc;
}
-static unsigned int switch_get_mode(struct regulator_dev *dev)
+static int vreg_pin_control_disable(struct regulator_dev *rdev)
{
- struct vreg *vreg = rdev_get_drvdata(dev);
+ struct vreg *vreg = rdev_get_drvdata(rdev);
+ unsigned int mask[2] = {0}, val[2] = {0};
+ int pin_fn, rc;
- if (vreg->pc_vote)
- return REGULATOR_MODE_IDLE;
- return REGULATOR_MODE_NORMAL;
+ mutex_lock(&vreg->pc_lock);
+
+ val[vreg->part->pc.word]
+ |= RPM_VREG_PIN_CTRL_NONE << vreg->part->pc.shift;
+ mask[vreg->part->pc.word] |= vreg->part->pc.mask;
+
+ pin_fn = config->pin_func_none;
+ if (vreg->pdata.pin_fn == config->pin_func_sleep_b)
+ pin_fn = config->pin_func_sleep_b;
+ val[vreg->part->pf.word] |= pin_fn << vreg->part->pf.shift;
+ mask[vreg->part->pf.word] |= vreg->part->pf.mask;
+
+ if (!vreg->is_enabled)
+ set_disable(vreg, mask, val);
+
+ rc = vreg_set(vreg, mask[0], val[0], mask[1], val[1],
+ vreg->part->request_len);
+
+ if (!rc)
+ vreg->is_enabled_pc = false;
+
+ mutex_unlock(&vreg->pc_lock);
+
+ if (rc)
+ vreg_err(vreg, "vreg_set failed, rc=%d\n", rc);
+
+ return rc;
}
-static int ncp_enable(struct regulator_dev *dev)
+static int vreg_enable_time(struct regulator_dev *rdev)
{
- return vreg_set(rdev_get_drvdata(dev), NCP_STATE,
- RPM_VREG_STATE_ON << NCP_STATE_SHIFT, 0, 0, 2);
+ struct vreg *vreg = rdev_get_drvdata(rdev);
+
+ return vreg->pdata.enable_time;
}
-static int ncp_disable(struct regulator_dev *dev)
-{
- return vreg_set(rdev_get_drvdata(dev), NCP_STATE,
- RPM_VREG_STATE_OFF << NCP_STATE_SHIFT, 0, 0, 2);
-}
-
-static int ncp_is_enabled(struct regulator_dev *dev)
-{
- struct vreg *vreg = rdev_get_drvdata(dev);
- enum rpm_vreg_state state;
-
- state = (vreg->req[0].value & NCP_STATE) >> NCP_STATE_SHIFT;
-
- return state == RPM_VREG_STATE_ON;
-}
-
-static int ncp_set_voltage(struct regulator_dev *dev, int min_uV, int max_uV,
- unsigned *selector)
-{
- return vreg_set(rdev_get_drvdata(dev), NCP_VOLTAGE,
- MICRO_TO_MILLI(min_uV) << NCP_VOLTAGE_SHIFT, 0, 0, 2);
-}
-
-static int ncp_get_voltage(struct regulator_dev *dev)
-{
- struct vreg *vreg = rdev_get_drvdata(dev);
-
- return MILLI_TO_MICRO((vreg->req[0].value & NCP_VOLTAGE) >>
- NCP_VOLTAGE_SHIFT);
-}
-
+/* Real regulator operations. */
static struct regulator_ops ldo_ops = {
- .enable = ldo_enable,
- .disable = ldo_disable,
- .is_enabled = ldo_is_enabled,
- .set_voltage = ldo_set_voltage,
- .get_voltage = ldo_get_voltage,
- .set_mode = ldo_set_mode,
- .get_optimum_mode = ldo_get_optimum_mode,
- .get_mode = ldo_get_mode,
+ .enable = vreg_enable,
+ .disable = vreg_disable,
+ .is_enabled = vreg_is_enabled,
+ .set_voltage = vreg_set_voltage,
+ .get_voltage = vreg_get_voltage,
+ .list_voltage = vreg_list_voltage,
+ .set_mode = vreg_set_mode,
+ .get_mode = vreg_get_mode,
+ .get_optimum_mode = vreg_get_optimum_mode,
+ .enable_time = vreg_enable_time,
};
static struct regulator_ops smps_ops = {
- .enable = smps_enable,
- .disable = smps_disable,
- .is_enabled = smps_is_enabled,
- .set_voltage = smps_set_voltage,
- .get_voltage = smps_get_voltage,
- .set_mode = smps_set_mode,
- .get_optimum_mode = smps_get_optimum_mode,
- .get_mode = smps_get_mode,
+ .enable = vreg_enable,
+ .disable = vreg_disable,
+ .is_enabled = vreg_is_enabled,
+ .set_voltage = vreg_set_voltage,
+ .get_voltage = vreg_get_voltage,
+ .list_voltage = vreg_list_voltage,
+ .set_mode = vreg_set_mode,
+ .get_mode = vreg_get_mode,
+ .get_optimum_mode = vreg_get_optimum_mode,
+ .enable_time = vreg_enable_time,
};
static struct regulator_ops switch_ops = {
- .enable = switch_enable,
- .disable = switch_disable,
- .is_enabled = switch_is_enabled,
- .set_mode = switch_set_mode,
- .get_mode = switch_get_mode,
+ .enable = vreg_enable,
+ .disable = vreg_disable,
+ .is_enabled = vreg_is_enabled,
+ .enable_time = vreg_enable_time,
};
static struct regulator_ops ncp_ops = {
- .enable = ncp_enable,
- .disable = ncp_disable,
- .is_enabled = ncp_is_enabled,
- .set_voltage = ncp_set_voltage,
- .get_voltage = ncp_get_voltage,
+ .enable = vreg_enable,
+ .disable = vreg_disable,
+ .is_enabled = vreg_is_enabled,
+ .set_voltage = vreg_set_voltage,
+ .get_voltage = vreg_get_voltage,
+ .list_voltage = vreg_list_voltage,
+ .enable_time = vreg_enable_time,
};
-#define DESC(_id, _name, _ops) \
- [_id] = { \
- .id = _id, \
- .name = _name, \
- .ops = _ops, \
- .type = REGULATOR_VOLTAGE, \
- .owner = THIS_MODULE, \
+/* Pin control regulator operations. */
+static struct regulator_ops pin_control_ops = {
+ .enable = vreg_pin_control_enable,
+ .disable = vreg_pin_control_disable,
+ .is_enabled = vreg_pin_control_is_enabled,
+};
+
+struct regulator_ops *vreg_ops[] = {
+ [RPM_REGULATOR_TYPE_LDO] = &ldo_ops,
+ [RPM_REGULATOR_TYPE_SMPS] = &smps_ops,
+ [RPM_REGULATOR_TYPE_VS] = &switch_ops,
+ [RPM_REGULATOR_TYPE_NCP] = &ncp_ops,
+};
+
+static int __devinit
+rpm_vreg_init_regulator(const struct rpm_regulator_init_data *pdata,
+ struct device *dev)
+{
+ struct regulator_desc *rdesc = NULL;
+ struct regulator_dev *rdev;
+ struct vreg *vreg;
+ unsigned pin_ctrl;
+ int id, pin_fn;
+ int rc = 0;
+
+ if (!pdata) {
+ pr_err("platform data missing\n");
+ return -EINVAL;
}
-static struct regulator_desc vreg_descrip[RPM_VREG_ID_MAX] = {
- DESC(RPM_VREG_ID_PM8058_L0, "8058_l0", &ldo_ops),
- DESC(RPM_VREG_ID_PM8058_L1, "8058_l1", &ldo_ops),
- DESC(RPM_VREG_ID_PM8058_L2, "8058_l2", &ldo_ops),
- DESC(RPM_VREG_ID_PM8058_L3, "8058_l3", &ldo_ops),
- DESC(RPM_VREG_ID_PM8058_L4, "8058_l4", &ldo_ops),
- DESC(RPM_VREG_ID_PM8058_L5, "8058_l5", &ldo_ops),
- DESC(RPM_VREG_ID_PM8058_L6, "8058_l6", &ldo_ops),
- DESC(RPM_VREG_ID_PM8058_L7, "8058_l7", &ldo_ops),
- DESC(RPM_VREG_ID_PM8058_L8, "8058_l8", &ldo_ops),
- DESC(RPM_VREG_ID_PM8058_L9, "8058_l9", &ldo_ops),
- DESC(RPM_VREG_ID_PM8058_L10, "8058_l10", &ldo_ops),
- DESC(RPM_VREG_ID_PM8058_L11, "8058_l11", &ldo_ops),
- DESC(RPM_VREG_ID_PM8058_L12, "8058_l12", &ldo_ops),
- DESC(RPM_VREG_ID_PM8058_L13, "8058_l13", &ldo_ops),
- DESC(RPM_VREG_ID_PM8058_L14, "8058_l14", &ldo_ops),
- DESC(RPM_VREG_ID_PM8058_L15, "8058_l15", &ldo_ops),
- DESC(RPM_VREG_ID_PM8058_L16, "8058_l16", &ldo_ops),
- DESC(RPM_VREG_ID_PM8058_L17, "8058_l17", &ldo_ops),
- DESC(RPM_VREG_ID_PM8058_L18, "8058_l18", &ldo_ops),
- DESC(RPM_VREG_ID_PM8058_L19, "8058_l19", &ldo_ops),
- DESC(RPM_VREG_ID_PM8058_L20, "8058_l20", &ldo_ops),
- DESC(RPM_VREG_ID_PM8058_L21, "8058_l21", &ldo_ops),
- DESC(RPM_VREG_ID_PM8058_L22, "8058_l22", &ldo_ops),
- DESC(RPM_VREG_ID_PM8058_L23, "8058_l23", &ldo_ops),
- DESC(RPM_VREG_ID_PM8058_L24, "8058_l24", &ldo_ops),
- DESC(RPM_VREG_ID_PM8058_L25, "8058_l25", &ldo_ops),
+ id = pdata->id;
- DESC(RPM_VREG_ID_PM8058_S0, "8058_s0", &smps_ops),
- DESC(RPM_VREG_ID_PM8058_S1, "8058_s1", &smps_ops),
- DESC(RPM_VREG_ID_PM8058_S2, "8058_s2", &smps_ops),
- DESC(RPM_VREG_ID_PM8058_S3, "8058_s3", &smps_ops),
- DESC(RPM_VREG_ID_PM8058_S4, "8058_s4", &smps_ops),
+ if (id < config->vreg_id_min || id > config->vreg_id_max) {
+ pr_err("invalid regulator id: %d\n", id);
+ return -ENODEV;
+ }
- DESC(RPM_VREG_ID_PM8058_LVS0, "8058_lvs0", &switch_ops),
- DESC(RPM_VREG_ID_PM8058_LVS1, "8058_lvs1", &switch_ops),
+ if (!config->is_real_id(pdata->id))
+ id = config->pc_id_to_real_id(pdata->id);
+ vreg = &config->vregs[id];
- DESC(RPM_VREG_ID_PM8058_NCP, "8058_ncp", &ncp_ops),
-
- DESC(RPM_VREG_ID_PM8901_L0, "8901_l0", &ldo_ops),
- DESC(RPM_VREG_ID_PM8901_L1, "8901_l1", &ldo_ops),
- DESC(RPM_VREG_ID_PM8901_L2, "8901_l2", &ldo_ops),
- DESC(RPM_VREG_ID_PM8901_L3, "8901_l3", &ldo_ops),
- DESC(RPM_VREG_ID_PM8901_L4, "8901_l4", &ldo_ops),
- DESC(RPM_VREG_ID_PM8901_L5, "8901_l5", &ldo_ops),
- DESC(RPM_VREG_ID_PM8901_L6, "8901_l6", &ldo_ops),
-
- DESC(RPM_VREG_ID_PM8901_S0, "8901_s0", &smps_ops),
- DESC(RPM_VREG_ID_PM8901_S1, "8901_s1", &smps_ops),
- DESC(RPM_VREG_ID_PM8901_S2, "8901_s2", &smps_ops),
- DESC(RPM_VREG_ID_PM8901_S3, "8901_s3", &smps_ops),
- DESC(RPM_VREG_ID_PM8901_S4, "8901_s4", &smps_ops),
-
- DESC(RPM_VREG_ID_PM8901_LVS0, "8901_lvs0", &switch_ops),
- DESC(RPM_VREG_ID_PM8901_LVS1, "8901_lvs1", &switch_ops),
- DESC(RPM_VREG_ID_PM8901_LVS2, "8901_lvs2", &switch_ops),
- DESC(RPM_VREG_ID_PM8901_LVS3, "8901_lvs3", &switch_ops),
-
- DESC(RPM_VREG_ID_PM8901_MVS0, "8901_mvs0", &switch_ops),
-};
-
-static void ldo_init(struct vreg *vreg)
-{
- enum rpm_vreg_pin_fn pf = RPM_VREG_PIN_FN_NONE;
-
- /* Allow pf=sleep_b to be specified by platform data. */
- if (vreg->pdata->pin_fn == RPM_VREG_PIN_FN_SLEEP_B)
- pf = RPM_VREG_PIN_FN_SLEEP_B;
-
- vreg->req[0].value =
- MICRO_TO_MILLI(saturate_load(vreg->pdata->peak_uA)) <<
- LDO_PEAK_CURRENT_SHIFT |
- vreg->pdata->mode << LDO_MODE_SHIFT | pf << LDO_PIN_FN_SHIFT |
- RPM_VREG_PIN_CTRL_NONE << LDO_PIN_CTRL_SHIFT;
-
- vreg->req[1].value =
- vreg->pdata->pull_down_enable << LDO_PULL_DOWN_ENABLE_SHIFT |
- MICRO_TO_MILLI(saturate_load(vreg->pdata->avg_uA)) <<
- LDO_AVG_CURRENT_SHIFT;
-}
-
-static void smps_init(struct vreg *vreg)
-{
- enum rpm_vreg_pin_fn pf = RPM_VREG_PIN_FN_NONE;
-
- /* Allow pf=sleep_b to be specified by platform data. */
- if (vreg->pdata->pin_fn == RPM_VREG_PIN_FN_SLEEP_B)
- pf = RPM_VREG_PIN_FN_SLEEP_B;
-
- vreg->req[0].value =
- MICRO_TO_MILLI(saturate_load(vreg->pdata->peak_uA)) <<
- SMPS_PEAK_CURRENT_SHIFT |
- vreg->pdata->mode << SMPS_MODE_SHIFT | pf << SMPS_PIN_FN_SHIFT |
- RPM_VREG_PIN_CTRL_NONE << SMPS_PIN_CTRL_SHIFT;
-
-
- vreg->req[1].value =
- vreg->pdata->pull_down_enable << SMPS_PULL_DOWN_ENABLE_SHIFT |
- MICRO_TO_MILLI(saturate_load(vreg->pdata->avg_uA)) <<
- SMPS_AVG_CURRENT_SHIFT |
- vreg->pdata->freq << SMPS_FREQ_SHIFT |
- 0 << SMPS_CLK_SRC_SHIFT;
-}
-
-static void ncp_init(struct vreg *vreg)
-{
- vreg->req[0].value = vreg->pdata->state << NCP_STATE_SHIFT;
-}
-
-static void switch_init(struct vreg *vreg)
-{
- enum rpm_vreg_pin_fn pf = RPM_VREG_PIN_FN_NONE;
-
- /* Allow pf=sleep_b to be specified by platform data. */
- if (vreg->pdata->pin_fn == RPM_VREG_PIN_FN_SLEEP_B)
- pf = RPM_VREG_PIN_FN_SLEEP_B;
-
- vreg->req[0].value =
- vreg->pdata->state << SWITCH_STATE_SHIFT |
- vreg->pdata->pull_down_enable <<
- SWITCH_PULL_DOWN_ENABLE_SHIFT |
- pf << SWITCH_PIN_FN_SHIFT |
- RPM_VREG_PIN_CTRL_NONE << SWITCH_PIN_CTRL_SHIFT;
-}
-
-static int vreg_init(enum rpm_vreg_id id, struct vreg *vreg)
-{
- vreg->save_uV = vreg->pdata->default_uV;
-
- if (vreg->pdata->peak_uA >= vreg->hpm_min_load)
- vreg->optimum = REGULATOR_MODE_FAST;
+ if (config->is_real_id(pdata->id))
+ rdesc = &vreg->rdesc;
else
- vreg->optimum = REGULATOR_MODE_STANDBY;
+ rdesc = &vreg->rdesc_pc;
- vreg->mode_initialized = 0;
-
- if (IS_LDO(id))
- ldo_init(vreg);
- else if (IS_SMPS(id))
- smps_init(vreg);
- else if (IS_NCP(id))
- ncp_init(vreg);
- else if (IS_SWITCH(id))
- switch_init(vreg);
- else
+ if (vreg->type < 0 || vreg->type > RPM_REGULATOR_TYPE_MAX) {
+ pr_err("%s: invalid regulator type: %d\n",
+ vreg->rdesc.name, vreg->type);
return -EINVAL;
+ }
- return 0;
+ mutex_lock(&vreg->pc_lock);
+
+ if (vreg->set_points)
+ rdesc->n_voltages = vreg->set_points->n_voltages;
+ else
+ rdesc->n_voltages = 0;
+
+ rdesc->id = pdata->id;
+ rdesc->owner = THIS_MODULE;
+ rdesc->type = REGULATOR_VOLTAGE;
+
+ if (config->is_real_id(pdata->id)) {
+ /*
+ * Real regulator; do not modify pin control and pin function
+ * values.
+ */
+ rdesc->ops = vreg_ops[vreg->type];
+ pin_ctrl = vreg->pdata.pin_ctrl;
+ pin_fn = vreg->pdata.pin_fn;
+ memcpy(&(vreg->pdata), pdata,
+ sizeof(struct rpm_regulator_init_data));
+ vreg->pdata.pin_ctrl = pin_ctrl;
+ vreg->pdata.pin_fn = pin_fn;
+
+ vreg->save_uV = vreg->pdata.default_uV;
+ if (vreg->pdata.peak_uA >= vreg->hpm_min_load)
+ vreg->mode = config->mode_hpm;
+ else
+ vreg->mode = config->mode_lpm;
+
+ /* Initialize the RPM request. */
+ SET_PART(vreg, ip,
+ MICRO_TO_MILLI(saturate_peak_load(vreg, vreg->pdata.peak_uA)));
+ SET_PART(vreg, fm, vreg->pdata.force_mode);
+ SET_PART(vreg, pm, vreg->pdata.power_mode);
+ SET_PART(vreg, pd, vreg->pdata.pull_down_enable);
+ SET_PART(vreg, ia,
+ MICRO_TO_MILLI(saturate_avg_load(vreg, vreg->pdata.avg_uA)));
+ SET_PART(vreg, freq, vreg->pdata.freq);
+ SET_PART(vreg, freq_clk_src, 0);
+ SET_PART(vreg, comp_mode, 0);
+ SET_PART(vreg, hpm, 0);
+ if (!vreg->is_enabled_pc) {
+ SET_PART(vreg, pf, config->pin_func_none);
+ SET_PART(vreg, pc, RPM_VREG_PIN_CTRL_NONE);
+ }
+ } else {
+ if ((pdata->pin_ctrl & RPM_VREG_PIN_CTRL_ALL)
+ == RPM_VREG_PIN_CTRL_NONE
+ && pdata->pin_fn != config->pin_func_sleep_b) {
+ pr_err("%s: no pin control input specified\n",
+ vreg->rdesc.name);
+ mutex_unlock(&vreg->pc_lock);
+ return -EINVAL;
+ }
+ rdesc->ops = &pin_control_ops;
+ vreg->pdata.pin_ctrl = pdata->pin_ctrl;
+ vreg->pdata.pin_fn = pdata->pin_fn;
+
+ /* Initialize the RPM request. */
+ pin_fn = config->pin_func_none;
+ /* Allow pf=sleep_b to be specified by platform data. */
+ if (vreg->pdata.pin_fn == config->pin_func_sleep_b)
+ pin_fn = config->pin_func_sleep_b;
+ SET_PART(vreg, pf, pin_fn);
+ SET_PART(vreg, pc, RPM_VREG_PIN_CTRL_NONE);
+ }
+
+ mutex_unlock(&vreg->pc_lock);
+
+ if (rc)
+ goto bail;
+
+ rdev = regulator_register(rdesc, dev, &(pdata->init_data), vreg);
+ if (IS_ERR(rdev)) {
+ rc = PTR_ERR(rdev);
+ pr_err("regulator_register failed: %s, rc=%d\n",
+ vreg->rdesc.name, rc);
+ return rc;
+ } else {
+ if (config->is_real_id(pdata->id))
+ vreg->rdev = rdev;
+ else
+ vreg->rdev_pc = rdev;
+ }
+
+bail:
+ if (rc)
+ pr_err("error for %s, rc=%d\n", vreg->rdesc.name, rc);
+
+ return rc;
+}
+
+static void rpm_vreg_set_point_init(void)
+{
+ struct vreg_set_points **set_points;
+ int i, j, temp;
+
+ set_points = config->set_points;
+
+ /* Calculate the number of set points available for each regulator. */
+ for (i = 0; i < config->set_points_len; i++) {
+ temp = 0;
+ for (j = 0; j < set_points[i]->count; j++) {
+ set_points[i]->range[j].n_voltages
+ = (set_points[i]->range[j].max_uV
+ - set_points[i]->range[j].min_uV)
+ / set_points[i]->range[j].step_uV + 1;
+ temp += set_points[i]->range[j].n_voltages;
+ }
+ set_points[i]->n_voltages = temp;
+ }
}
static int __devinit rpm_vreg_probe(struct platform_device *pdev)
{
- struct regulator_desc *rdesc;
- struct regulator_dev *rdev;
- struct vreg *vreg;
- int rc;
+ struct rpm_regulator_platform_data *platform_data;
+ int rc = 0;
+ int i, id;
- if (pdev == NULL)
+ platform_data = pdev->dev.platform_data;
+ if (!platform_data) {
+ pr_err("rpm-regulator requires platform data\n");
return -EINVAL;
-
- if (pdev->id < 0 || pdev->id >= RPM_VREG_ID_MAX)
- return -ENODEV;
-
- vreg = &vregs[pdev->id];
- vreg->pdata = pdev->dev.platform_data;
- vreg->id = pdev->id;
- rdesc = &vreg_descrip[pdev->id];
-
- rc = vreg_init(pdev->id, vreg);
- if (rc) {
- pr_err("%s: vreg_init failed, rc=%d\n", __func__, rc);
- return rc;
}
- /* Disallow idle and normal modes if pin control isn't set. */
- if ((vreg->pdata->pin_ctrl == RPM_VREG_PIN_CTRL_NONE)
- && ((vreg->pdata->pin_fn == RPM_VREG_PIN_FN_ENABLE)
- || (vreg->pdata->pin_fn == RPM_VREG_PIN_FN_MODE)))
- vreg->pdata->init_data.constraints.valid_modes_mask
- &= ~(REGULATOR_MODE_NORMAL | REGULATOR_MODE_IDLE);
-
- rdev = regulator_register(rdesc, &pdev->dev,
- &vreg->pdata->init_data, vreg);
- if (IS_ERR(rdev)) {
- rc = PTR_ERR(rdev);
- pr_err("%s: id=%d, rc=%d\n", __func__,
- pdev->id, rc);
- return rc;
+ if (rpm_version >= 0 && rpm_version <= RPM_VREG_VERSION_MAX
+ && platform_data->version != rpm_version) {
+ pr_err("rpm version %d does not match previous version %d\n",
+ platform_data->version, rpm_version);
+ return -EINVAL;
}
- platform_set_drvdata(pdev, rdev);
+ if (platform_data->version < 0
+ || platform_data->version > RPM_VREG_VERSION_MAX) {
+ pr_err("rpm version %d is invalid\n", platform_data->version);
+ return -EINVAL;
+ }
+
+ if (rpm_version < 0 || rpm_version > RPM_VREG_VERSION_MAX) {
+ rpm_version = platform_data->version;
+ config = get_config[platform_data->version]();
+ vreg_id_vdd_mem = platform_data->vreg_id_vdd_mem;
+ vreg_id_vdd_dig = platform_data->vreg_id_vdd_dig;
+ if (!config) {
+ pr_err("rpm version %d is not available\n",
+ platform_data->version);
+ return -ENODEV;
+ }
+ if (config->use_legacy_optimum_mode)
+ for (i = 0; i < ARRAY_SIZE(vreg_ops); i++)
+ vreg_ops[i]->get_optimum_mode
+ = vreg_legacy_get_optimum_mode;
+ rpm_vreg_set_point_init();
+ /* First time probed; initialize pin control mutexes. */
+ for (i = 0; i < config->vregs_len; i++)
+ mutex_init(&config->vregs[i].pc_lock);
+ }
+
+ /* Initialize all of the regulators listed in the platform data. */
+ for (i = 0; i < platform_data->num_regulators; i++) {
+ rc = rpm_vreg_init_regulator(&platform_data->init_data[i],
+ &pdev->dev);
+ if (rc) {
+ pr_err("rpm_vreg_init_regulator failed, rc=%d\n", rc);
+ goto remove_regulators;
+ }
+ }
+
+ platform_set_drvdata(pdev, platform_data);
+
+ return rc;
+
+remove_regulators:
+ /* Unregister all regulators added before the erroring one. */
+ for (; i >= 0; i--) {
+ id = platform_data->init_data[i].id;
+ if (config->is_real_id(id)) {
+ regulator_unregister(config->vregs[id].rdev);
+ config->vregs[id].rdev = NULL;
+ } else {
+ regulator_unregister(config->vregs[
+ config->pc_id_to_real_id(id)].rdev_pc);
+ config->vregs[id].rdev_pc = NULL;
+ }
+ }
return rc;
}
static int __devexit rpm_vreg_remove(struct platform_device *pdev)
{
- struct regulator_dev *rdev = platform_get_drvdata(pdev);
+ struct rpm_regulator_platform_data *platform_data;
+ int i, id;
+ platform_data = platform_get_drvdata(pdev);
platform_set_drvdata(pdev, NULL);
- regulator_unregister(rdev);
+
+ if (platform_data) {
+ for (i = 0; i < platform_data->num_regulators; i++) {
+ id = platform_data->init_data[i].id;
+ if (config->is_real_id(id)) {
+ regulator_unregister(config->vregs[id].rdev);
+ config->vregs[id].rdev = NULL;
+ } else {
+ regulator_unregister(config->vregs[
+ config->pc_id_to_real_id(id)].rdev_pc);
+ config->vregs[id].rdev_pc = NULL;
+ }
+ }
+ }
return 0;
}
@@ -1467,7 +1391,7 @@
.probe = rpm_vreg_probe,
.remove = __devexit_p(rpm_vreg_remove),
.driver = {
- .name = "rpm-regulator",
+ .name = RPM_REGULATOR_DEV_NAME,
.owner = THIS_MODULE,
},
};
@@ -1479,189 +1403,18 @@
static void __exit rpm_vreg_exit(void)
{
+ int i;
+
platform_driver_unregister(&rpm_vreg_driver);
+
+ for (i = 0; i < config->vregs_len; i++)
+ mutex_destroy(&config->vregs[i].pc_lock);
}
postcore_initcall(rpm_vreg_init);
module_exit(rpm_vreg_exit);
-#define VREG_ID_IS_8058_S0_OR_S1(id) \
- ((id == RPM_VREG_ID_PM8058_S0) || (id == RPM_VREG_ID_PM8058_S1))
-
-static void print_rpm_request(struct vreg *vreg, int set)
-{
- int v, ip, fm, pc, pf, pd, ia, freq, clk, state;
-
- /* Suppress 8058_s0 and 8058_s1 printing. */
- if ((msm_rpm_vreg_debug_mask & MSM_RPM_VREG_DEBUG_IGNORE_8058_S0_S1)
- && VREG_ID_IS_8058_S0_OR_S1(vreg->id))
- return;
-
- if (IS_LDO(vreg->id)) {
- v = (vreg->req[0].value & LDO_VOLTAGE) >> LDO_VOLTAGE_SHIFT;
- ip = (vreg->req[0].value & LDO_PEAK_CURRENT)
- >> LDO_PEAK_CURRENT_SHIFT;
- fm = (vreg->req[0].value & LDO_MODE) >> LDO_MODE_SHIFT;
- pc = (vreg->req[0].value & LDO_PIN_CTRL) >> LDO_PIN_CTRL_SHIFT;
- pf = (vreg->req[0].value & LDO_PIN_FN) >> LDO_PIN_FN_SHIFT;
- pd = (vreg->req[1].value & LDO_PULL_DOWN_ENABLE)
- >> LDO_PULL_DOWN_ENABLE_SHIFT;
- ia = (vreg->req[1].value & LDO_AVG_CURRENT)
- >> LDO_AVG_CURRENT_SHIFT;
-
- pr_info("rpm-regulator: %s %-9s: s=%c, v=%4d mV, ip=%4d "
- "mA, fm=%s (%d), pc=%s%s%s%s%s (%d), pf=%s (%d), pd=%s "
- "(%d), ia=%4d mA; req[0]={%d, 0x%08X}, "
- "req[1]={%d, 0x%08X}\n",
- (set == MSM_RPM_CTX_SET_0 ? "sending " : "buffered"),
- vreg_descrip[vreg->id].name,
- (set == MSM_RPM_CTX_SET_0 ? 'A' : 'S'), v, ip,
- (fm == RPM_VREG_MODE_NONE ? "none" :
- (fm == RPM_VREG_MODE_LPM ? "LPM" :
- (fm == RPM_VREG_MODE_HPM ? "HPM" : ""))),
- fm,
- (pc & RPM_VREG_PIN_CTRL_A0 ? " A0" : ""),
- (pc & RPM_VREG_PIN_CTRL_A1 ? " A1" : ""),
- (pc & RPM_VREG_PIN_CTRL_D0 ? " D0" : ""),
- (pc & RPM_VREG_PIN_CTRL_D1 ? " D1" : ""),
- (pc == RPM_VREG_PIN_CTRL_NONE ? " none" : ""), pc,
- (pf == RPM_VREG_PIN_FN_NONE ?
- "none" :
- (pf == RPM_VREG_PIN_FN_ENABLE ?
- "on/off" :
- (pf == RPM_VREG_PIN_FN_MODE ?
- "HPM/LPM" :
- (pf == RPM_VREG_PIN_FN_SLEEP_B ?
- "sleep_b" : "")))),
- pf, (pd == 1 ? "Y" : "N"), pd, ia,
- vreg->req[0].id, vreg->req[0].value,
- vreg->req[1].id, vreg->req[1].value);
-
- } else if (IS_SMPS(vreg->id)) {
- v = (vreg->req[0].value & SMPS_VOLTAGE) >> SMPS_VOLTAGE_SHIFT;
- ip = (vreg->req[0].value & SMPS_PEAK_CURRENT)
- >> SMPS_PEAK_CURRENT_SHIFT;
- fm = (vreg->req[0].value & SMPS_MODE) >> SMPS_MODE_SHIFT;
- pc = (vreg->req[0].value & SMPS_PIN_CTRL)
- >> SMPS_PIN_CTRL_SHIFT;
- pf = (vreg->req[0].value & SMPS_PIN_FN) >> SMPS_PIN_FN_SHIFT;
- pd = (vreg->req[1].value & SMPS_PULL_DOWN_ENABLE)
- >> SMPS_PULL_DOWN_ENABLE_SHIFT;
- ia = (vreg->req[1].value & SMPS_AVG_CURRENT)
- >> SMPS_AVG_CURRENT_SHIFT;
- freq = (vreg->req[1].value & SMPS_FREQ) >> SMPS_FREQ_SHIFT;
- clk = (vreg->req[1].value & SMPS_CLK_SRC) >> SMPS_CLK_SRC_SHIFT;
-
- pr_info("rpm-regulator: %s %-9s: s=%c, v=%4d mV, ip=%4d "
- "mA, fm=%s (%d), pc=%s%s%s%s%s (%d), pf=%s (%d), pd=%s "
- "(%d), ia=%4d mA, freq=%2d, clk=%d; "
- "req[0]={%d, 0x%08X}, req[1]={%d, 0x%08X}\n",
- (set == MSM_RPM_CTX_SET_0 ? "sending " : "buffered"),
- vreg_descrip[vreg->id].name,
- (set == MSM_RPM_CTX_SET_0 ? 'A' : 'S'), v, ip,
- (fm == RPM_VREG_MODE_NONE ? "none" :
- (fm == RPM_VREG_MODE_LPM ? "LPM" :
- (fm == RPM_VREG_MODE_HPM ? "HPM" : ""))),
- fm,
- (pc & RPM_VREG_PIN_CTRL_A0 ? " A0" : ""),
- (pc & RPM_VREG_PIN_CTRL_A1 ? " A1" : ""),
- (pc & RPM_VREG_PIN_CTRL_D0 ? " D0" : ""),
- (pc & RPM_VREG_PIN_CTRL_D1 ? " D1" : ""),
- (pc == RPM_VREG_PIN_CTRL_NONE ? " none" : ""), pc,
- (pf == RPM_VREG_PIN_FN_NONE ?
- "none" :
- (pf == RPM_VREG_PIN_FN_ENABLE ?
- "on/off" :
- (pf == RPM_VREG_PIN_FN_MODE ?
- "HPM/LPM" :
- (pf == RPM_VREG_PIN_FN_SLEEP_B ?
- "sleep_b" : "")))),
- pf, (pd == 1 ? "Y" : "N"), pd, ia, freq, clk,
- vreg->req[0].id, vreg->req[0].value,
- vreg->req[1].id, vreg->req[1].value);
-
- } else if (IS_SWITCH(vreg->id)) {
- state = (vreg->req[0].value & SWITCH_STATE)
- >> SWITCH_STATE_SHIFT;
- pd = (vreg->req[0].value & SWITCH_PULL_DOWN_ENABLE)
- >> SWITCH_PULL_DOWN_ENABLE_SHIFT;
- pc = (vreg->req[0].value & SWITCH_PIN_CTRL)
- >> SWITCH_PIN_CTRL_SHIFT;
- pf = (vreg->req[0].value & SWITCH_PIN_FN)
- >> SWITCH_PIN_FN_SHIFT;
-
- pr_info("rpm-regulator: %s %-9s: s=%c, state=%s (%d), "
- "pd=%s (%d), pc =%s%s%s%s%s (%d), pf=%s (%d); "
- "req[0]={%d, 0x%08X}\n",
- (set == MSM_RPM_CTX_SET_0 ? "sending " : "buffered"),
- vreg_descrip[vreg->id].name,
- (set == MSM_RPM_CTX_SET_0 ? 'A' : 'S'),
- (state == 1 ? "on" : "off"), state,
- (pd == 1 ? "Y" : "N"), pd,
- (pc & RPM_VREG_PIN_CTRL_A0 ? " A0" : ""),
- (pc & RPM_VREG_PIN_CTRL_A1 ? " A1" : ""),
- (pc & RPM_VREG_PIN_CTRL_D0 ? " D0" : ""),
- (pc & RPM_VREG_PIN_CTRL_D1 ? " D1" : ""),
- (pc == RPM_VREG_PIN_CTRL_NONE ? " none" : ""), pc,
- (pf == RPM_VREG_PIN_FN_NONE ?
- "none" :
- (pf == RPM_VREG_PIN_FN_ENABLE ?
- "on/off" :
- (pf == RPM_VREG_PIN_FN_MODE ?
- "HPM/LPM" :
- (pf == RPM_VREG_PIN_FN_SLEEP_B ?
- "sleep_b" : "")))),
- pf, vreg->req[0].id, vreg->req[0].value);
-
- } else if (IS_NCP(vreg->id)) {
- v = (vreg->req[0].value & NCP_VOLTAGE) >> NCP_VOLTAGE_SHIFT;
- state = (vreg->req[0].value & NCP_STATE) >> NCP_STATE_SHIFT;
-
- pr_info("rpm-regulator: %s %-9s: s=%c, v=-%4d mV, "
- "state=%s (%d); req[0]={%d, 0x%08X}\n",
- (set == MSM_RPM_CTX_SET_0 ? "sending " : "buffered"),
- vreg_descrip[vreg->id].name,
- (set == MSM_RPM_CTX_SET_0 ? 'A' : 'S'),
- v, (state == 1 ? "on" : "off"), state,
- vreg->req[0].id, vreg->req[0].value);
- }
-}
-
-static void print_rpm_vote(struct vreg *vreg, enum rpm_vreg_voter voter,
- int set, int voter_mV, int aggregate_mV)
-{
- /* Suppress 8058_s0 and 8058_s1 printing. */
- if ((msm_rpm_vreg_debug_mask & MSM_RPM_VREG_DEBUG_IGNORE_8058_S0_S1)
- && VREG_ID_IS_8058_S0_OR_S1(vreg->id))
- return;
-
- pr_info("rpm-regulator: vote received %-9s: voter=%d, set=%c, "
- "v_voter=%4d mV, v_aggregate=%4d mV\n",
- vreg_descrip[vreg->id].name, voter, (set == 0 ? 'A' : 'S'),
- voter_mV, aggregate_mV);
-}
-
-static void print_rpm_duplicate(struct vreg *vreg, int set, int cnt)
-{
- /* Suppress 8058_s0 and 8058_s1 printing. */
- if ((msm_rpm_vreg_debug_mask & MSM_RPM_VREG_DEBUG_IGNORE_8058_S0_S1)
- && VREG_ID_IS_8058_S0_OR_S1(vreg->id))
- return;
-
- if (cnt == 2)
- pr_info("rpm-regulator: ignored duplicate request %-9s: set=%c;"
- " req[0]={%d, 0x%08X}, req[1]={%d, 0x%08X}\n",
- vreg_descrip[vreg->id].name, (set == 0 ? 'A' : 'S'),
- vreg->req[0].id, vreg->req[0].value,
- vreg->req[1].id, vreg->req[1].value);
- else if (cnt == 1)
- pr_info("rpm-regulator: ignored duplicate request %-9s: set=%c;"
- " req[0]={%d, 0x%08X}\n",
- vreg_descrip[vreg->id].name, (set == 0 ? 'A' : 'S'),
- vreg->req[0].id, vreg->req[0].value);
-}
-
MODULE_LICENSE("GPL v2");
-MODULE_DESCRIPTION("rpm regulator driver");
+MODULE_DESCRIPTION("MSM RPM regulator driver");
MODULE_VERSION("1.0");
-MODULE_ALIAS("platform:rpm-regulator");
+MODULE_ALIAS("platform:" RPM_REGULATOR_DEV_NAME);
diff --git a/arch/arm/mach-msm/sdio_al.c b/arch/arm/mach-msm/sdio_al.c
index 3acd4a4..1967a14 100644
--- a/arch/arm/mach-msm/sdio_al.c
+++ b/arch/arm/mach-msm/sdio_al.c
@@ -993,7 +993,7 @@
}
/* Prevent modem to go to sleep until we get the PROG_DONE on
the dummy CMD52 */
- msmsdcc_set_pwrsave(sdio_al_dev->card->host, 0);
+ msmsdcc_set_pwrsave(sdio_al_dev->host, 0);
/* Mark HOST_OK_TOSLEEP */
sdio_al_dev->is_ok_to_sleep = 1;
write_lpm_info(sdio_al_dev);
@@ -2359,10 +2359,9 @@
u32 not_from_int, struct sdio_channel *ch)
{
int ret = 0;
- struct sdio_func *wk_func =
- sdio_al_dev->card->sdio_func[SDIO_AL_WAKEUP_FUNC-1];
+ struct sdio_func *wk_func = NULL;
unsigned long time_to_wait;
- struct mmc_host *host = wk_func->card->host;
+ struct mmc_host *host = sdio_al_dev->host;
if (sdio_al_dev->is_err) {
SDIO_AL_ERR(__func__);
@@ -2398,7 +2397,7 @@
sdio_al_vote_for_sleep(sdio_al_dev, 0);
msmsdcc_lpm_disable(host);
- msmsdcc_set_pwrsave(sdio_al_dev->card->host, 0);
+ msmsdcc_set_pwrsave(host, 0);
/* Poll the GPIO */
time_to_wait = jiffies + msecs_to_jiffies(1000);
while (time_before(jiffies, time_to_wait)) {
@@ -2416,6 +2415,13 @@
"get_mdm2ap_status() is 0\n");
/* Enable Wake up Function */
+ if (!sdio_al_dev->card ||
+ !sdio_al_dev->card->sdio_func[SDIO_AL_WAKEUP_FUNC-1]) {
+ sdio_al_loge(sdio_al_dev->dev_log, MODULE_NAME
+ ": NULL card or wk_func\n");
+ return -ENODEV;
+ }
+ wk_func = sdio_al_dev->card->sdio_func[SDIO_AL_WAKEUP_FUNC-1];
ret = sdio_al_enable_func_retry(wk_func, "wakeup func");
if (ret) {
sdio_al_loge(sdio_al_dev->dev_log, MODULE_NAME ": "
@@ -2442,13 +2448,13 @@
LPM_DEBUG(sdio_al_dev->dev_log, MODULE_NAME "Finished Wake up sequence"
" for card %d", sdio_al_dev->host->index);
- msmsdcc_set_pwrsave(sdio_al_dev->card->host, 1);
+ msmsdcc_set_pwrsave(host, 1);
pr_debug(MODULE_NAME ":Turn clock off\n");
return ret;
error_exit:
sdio_al_vote_for_sleep(sdio_al_dev, 1);
- msmsdcc_set_pwrsave(sdio_al_dev->card->host, 1);
+ msmsdcc_set_pwrsave(host, 1);
WARN_ON(ret);
sdio_al_get_into_err_state(sdio_al_dev);
return ret;
@@ -2476,8 +2482,7 @@
pr_debug(MODULE_NAME ":start %s.\n", __func__);
if (sdio_al_dev == NULL) {
- sdio_al_loge(&sdio_al->gen_log, MODULE_NAME ": NULL sdio_al_dev"
- " for card %d\n", func->card->host->index);
+ sdio_al_loge(&sdio_al->gen_log, MODULE_NAME ": NULL device");
return;
}
@@ -2527,18 +2532,13 @@
int i = 0;
int fn = 0;
- if (card == NULL) {
- sdio_al_loge(sdio_al_dev->dev_log, MODULE_NAME ": "
- "sdio_al_setup: No Card detected\n");
+ if (sdio_al_verify_func1(sdio_al_dev, __func__))
return -ENODEV;
- }
-
+ func1 = card->sdio_func[0];
sdio_al_logi(sdio_al_dev->dev_log, MODULE_NAME ":sdio_al_setup for "
"card %d\n", sdio_al_dev->host->index);
- func1 = card->sdio_func[0];
-
ret = sdio_al->pdata->config_mdm2ap_status(1);
if (ret) {
sdio_al_loge(sdio_al_dev->dev_log, MODULE_NAME "Could not "
@@ -2560,13 +2560,13 @@
sdio_set_drvdata(func1, sdio_al_dev);
sdio_al_logi(sdio_al_dev->dev_log, MODULE_NAME ":claim IRQ for card "
- "%d\n", card->host->index);
+ "%d\n", sdio_al_dev->host->index);
ret = sdio_claim_irq(func1, sdio_func_irq);
if (ret) {
sdio_al_loge(sdio_al_dev->dev_log, MODULE_NAME ":Fail to claim"
" IRQ for card %d\n",
- card->host->index);
+ sdio_al_dev->host->index);
return ret;
}
diff --git a/drivers/bluetooth/hci_smd.c b/drivers/bluetooth/hci_smd.c
index 2719891..8f8ba03 100644
--- a/drivers/bluetooth/hci_smd.c
+++ b/drivers/bluetooth/hci_smd.c
@@ -42,6 +42,8 @@
struct wake_lock wake_lock_tx;
struct wake_lock wake_lock_rx;
struct timer_list rx_q_timer;
+ struct tasklet_struct hci_event_task;
+ struct tasklet_struct hci_data_task;
};
struct hci_smd_data hs;
@@ -306,7 +308,7 @@
switch (event) {
case SMD_EVENT_DATA:
- hci_smd_recv_event(event);
+ tasklet_hi_schedule(&hs.hci_event_task);
break;
case SMD_EVENT_OPEN:
hci_smd_open(hdev);
@@ -329,7 +331,7 @@
switch (event) {
case SMD_EVENT_DATA:
- hci_smd_recv_data(event);
+ tasklet_hi_schedule(&hs.hci_data_task);
break;
case SMD_EVENT_OPEN:
hci_smd_open(hdev);
@@ -364,6 +366,11 @@
hdev->destruct = hci_smd_destruct;
hdev->owner = THIS_MODULE;
+ tasklet_init(&hsmd->hci_event_task,
+ hci_smd_recv_event, (unsigned long) hsmd);
+ tasklet_init(&hsmd->hci_data_task,
+ hci_smd_recv_data, (unsigned long) hsmd);
+
wake_lock_init(&hs.wake_lock_rx, WAKE_LOCK_SUSPEND, "msm_smd_Rx");
wake_lock_init(&hs.wake_lock_tx, WAKE_LOCK_SUSPEND, "msm_smd_Tx");
/*
@@ -414,6 +421,8 @@
/*Destroy the timer used to monitor the Rx queue for emptiness */
del_timer_sync(&hs.rx_q_timer);
+ tasklet_kill(&hs.hci_event_task);
+ tasklet_kill(&hs.hci_data_task);
}
static int hci_smd_init(void)
diff --git a/drivers/char/msm_rotator.c b/drivers/char/msm_rotator.c
index 01a0504..555e4fa 100644
--- a/drivers/char/msm_rotator.c
+++ b/drivers/char/msm_rotator.c
@@ -61,6 +61,10 @@
#define MSM_ROTATOR_MAX_H 0x1fff
#define MSM_ROTATOR_MAX_W 0x1fff
+#define IS_NONPLANAR 0x0
+#define IS_PLANAR 0x1
+#define IS_PLANAR_16ALIGNED 0x2
+
/* from lsb to msb */
#define GET_PACK_PATTERN(a, x, y, z, bit) \
(((a)<<((bit)*3))|((x)<<((bit)*2))|((y)<<(bit))|(z))
@@ -260,6 +264,7 @@
case MDP_Y_CRCB_H2V2:
case MDP_Y_CB_CR_H2V2:
case MDP_Y_CR_CB_H2V2:
+ case MDP_Y_CR_CB_GH2V2:
case MDP_Y_CRCB_H2V2_TILE:
case MDP_Y_CBCR_H2V2_TILE:
return 1;
@@ -375,7 +380,7 @@
int new_session,
unsigned int in_chroma_paddr,
unsigned int out_chroma_paddr,
- int is_planar)
+ int planar_mode)
{
int bpp;
unsigned int in_chr_addr, out_chr_addr;
@@ -385,7 +390,13 @@
return -ENOTTY;
if (!in_chroma_paddr) {
- in_chr_addr = chroma_addr(in_paddr, info->src.width,
+ if (planar_mode & IS_PLANAR_16ALIGNED)
+ in_chr_addr = chroma_addr(in_paddr,
+ ALIGN(info->src.width, 16),
+ info->src.height,
+ bpp);
+ else
+ in_chr_addr = chroma_addr(in_paddr, info->src.width,
info->src.height,
bpp);
} else
@@ -408,19 +419,33 @@
((info->dst_y * info->dst.width)/2 + info->dst_x),
MSM_ROTATOR_OUTP1_ADDR);
- if (is_planar) {
- iowrite32(in_chr_addr +
+ if (planar_mode & IS_PLANAR) {
+ if (planar_mode & IS_PLANAR_16ALIGNED)
+ iowrite32(in_chr_addr +
+ ALIGN((info->src.width / 2), 16) *
+ (info->src.height / 2),
+ MSM_ROTATOR_SRCP2_ADDR);
+ else
+ iowrite32(in_chr_addr +
(info->src.width / 2) * (info->src.height / 2),
MSM_ROTATOR_SRCP2_ADDR);
}
if (new_session) {
- if (is_planar) {
- iowrite32(info->src.width |
+ if (planar_mode & IS_PLANAR) {
+ if (planar_mode & IS_PLANAR_16ALIGNED) {
+ iowrite32(ALIGN(info->src.width, 16) |
+ ALIGN((info->src.width / 2), 16) << 16,
+ MSM_ROTATOR_SRC_YSTRIDE1);
+ iowrite32(ALIGN((info->src.width / 2), 16),
+ MSM_ROTATOR_SRC_YSTRIDE2);
+ } else {
+ iowrite32(info->src.width |
(info->src.width / 2) << 16,
MSM_ROTATOR_SRC_YSTRIDE1);
- iowrite32((info->src.width / 2),
+ iowrite32((info->src.width / 2),
MSM_ROTATOR_SRC_YSTRIDE2);
+ }
} else {
iowrite32(info->src.width |
info->src.width << 16,
@@ -448,7 +473,8 @@
MSM_ROTATOR_SUB_BLOCK_CFG);
iowrite32(0 << 29 | /* frame format 0 = linear */
(use_imem ? 0 : 1) << 22 | /* tile size */
- (is_planar ? 1 : 2) << 19 | /* fetch planes */
+ ((planar_mode & IS_PLANAR) ?
+ 1 : 2) << 19 | /* fetch planes */
0 << 18 | /* unpack align */
1 << 17 | /* unpack tight */
1 << 13 | /* unpack count 0=1 component */
@@ -911,7 +937,7 @@
!= s,
in_chroma_paddr,
out_chroma_paddr,
- 0);
+ IS_NONPLANAR);
break;
case MDP_Y_CB_CR_H2V2:
case MDP_Y_CR_CB_H2V2:
@@ -921,7 +947,16 @@
!= s,
in_chroma_paddr,
out_chroma_paddr,
- 1);
+ IS_PLANAR);
+ break;
+ case MDP_Y_CR_CB_GH2V2:
+ rc = msm_rotator_ycxcx_h2v2(msm_rotator_dev->img_info[s],
+ in_paddr, out_paddr, use_imem,
+ msm_rotator_dev->last_session_idx
+ != s,
+ in_chroma_paddr,
+ out_chroma_paddr,
+ IS_PLANAR | IS_PLANAR_16ALIGNED);
break;
case MDP_Y_CRCB_H2V2_TILE:
case MDP_Y_CBCR_H2V2_TILE:
@@ -1033,6 +1068,7 @@
case MDP_Y_CRCB_H2V2:
case MDP_Y_CB_CR_H2V2:
case MDP_Y_CR_CB_H2V2:
+ case MDP_Y_CR_CB_GH2V2:
case MDP_Y_CBCR_H2V1:
case MDP_Y_CRCB_H2V1:
case MDP_YCRYCB_H2V1:
diff --git a/drivers/gpu/msm/adreno_a2xx.c b/drivers/gpu/msm/adreno_a2xx.c
index 8a7ab35..064b05e 100644
--- a/drivers/gpu/msm/adreno_a2xx.c
+++ b/drivers/gpu/msm/adreno_a2xx.c
@@ -1520,6 +1520,7 @@
if (status & (CP_INT_CNTL__IB1_INT_MASK | CP_INT_CNTL__RB_INT_MASK)) {
KGSL_CMD_WARN(rb->device, "ringbuffer ib1/rb interrupt\n");
+ queue_work(device->work_queue, &device->ts_expired_ws);
wake_up_interruptible_all(&device->wait_queue);
atomic_notifier_call_chain(&(device->ts_notifier_list),
device->id,
diff --git a/drivers/gpu/msm/kgsl.c b/drivers/gpu/msm/kgsl.c
index e146ab8..165bbbf 100644
--- a/drivers/gpu/msm/kgsl.c
+++ b/drivers/gpu/msm/kgsl.c
@@ -180,35 +180,28 @@
list_add_tail(&entry->list, &device->memqueue);
}
-static void kgsl_memqueue_drain(struct kgsl_device *device)
+static void kgsl_timestamp_expired(struct work_struct *work)
{
+ struct kgsl_device *device = container_of(work, struct kgsl_device,
+ ts_expired_ws);
struct kgsl_mem_entry *entry, *entry_tmp;
uint32_t ts_processed;
- BUG_ON(!mutex_is_locked(&device->mutex));
+ mutex_lock(&device->mutex);
/* get current EOP timestamp */
ts_processed = device->ftbl->readtimestamp(device,
KGSL_TIMESTAMP_RETIRED);
+ /* Flush the freememontimestamp queue */
list_for_each_entry_safe(entry, entry_tmp, &device->memqueue, list) {
- KGSL_MEM_INFO(device,
- "ts_processed %d ts_free %d gpuaddr %x)\n",
- ts_processed, entry->free_timestamp,
- entry->memdesc.gpuaddr);
if (!timestamp_cmp(ts_processed, entry->free_timestamp))
break;
list_del(&entry->list);
kgsl_mem_entry_put(entry);
}
-}
-static void kgsl_memqueue_drain_unlocked(struct kgsl_device *device)
-{
- mutex_lock(&device->mutex);
- kgsl_check_suspended(device);
- kgsl_memqueue_drain(device);
mutex_unlock(&device->mutex);
}
@@ -771,8 +764,6 @@
param->timestamp,
param->timeout);
- kgsl_memqueue_drain(dev_priv->device);
-
/* Fire off any pending suspend operations that are in flight */
INIT_COMPLETION(dev_priv->device->suspend_gate);
@@ -950,7 +941,6 @@
if (entry) {
kgsl_memqueue_freememontimestamp(dev_priv->device, entry,
param->timestamp, param->type);
- kgsl_memqueue_drain(dev_priv->device);
} else {
KGSL_DRV_ERR(dev_priv->device,
"invalid gpuaddr %08x\n", param->gpuaddr);
@@ -1062,9 +1052,6 @@
if (!kgsl_mmu_enabled())
return -ENODEV;
- /* Make sure all pending freed memory is collected */
- kgsl_memqueue_drain_unlocked(dev_priv->device);
-
if (!param->hostptr) {
KGSL_CORE_ERR("invalid hostptr %x\n", param->hostptr);
result = -EINVAL;
@@ -1383,8 +1370,6 @@
if (entry == NULL)
return -ENOMEM;
- kgsl_memqueue_drain_unlocked(dev_priv->device);
-
if (_IOC_SIZE(cmd) == sizeof(struct kgsl_sharedmem_from_pmem))
memtype = KGSL_USER_MEM_TYPE_PMEM;
else
@@ -1524,9 +1509,6 @@
if (entry == NULL)
return -ENOMEM;
- /* Make sure all pending freed memory is collected */
- kgsl_memqueue_drain_unlocked(dev_priv->device);
-
result = kgsl_allocate_user(&entry->memdesc, private->pagetable,
param->size, param->flags);
@@ -1914,6 +1896,7 @@
goto err_devlist;
INIT_WORK(&device->idle_check_ws, kgsl_idle_check);
+ INIT_WORK(&device->ts_expired_ws, kgsl_timestamp_expired);
INIT_LIST_HEAD(&device->memqueue);
diff --git a/drivers/gpu/msm/kgsl_device.h b/drivers/gpu/msm/kgsl_device.h
index 10e345a..2f369ed 100644
--- a/drivers/gpu/msm/kgsl_device.h
+++ b/drivers/gpu/msm/kgsl_device.h
@@ -165,6 +165,7 @@
struct kgsl_pwrscale pwrscale;
struct kobject pwrscale_kobj;
struct pm_qos_request_list pm_qos_req_dma;
+ struct work_struct ts_expired_ws;
};
struct kgsl_context {
diff --git a/drivers/gpu/msm/z180.c b/drivers/gpu/msm/z180.c
index a81eeaa..61a3edb 100644
--- a/drivers/gpu/msm/z180.c
+++ b/drivers/gpu/msm/z180.c
@@ -234,6 +234,7 @@
count &= 255;
z180_dev->timestamp += count;
+ queue_work(device->work_queue, &device->ts_expired_ws);
wake_up_interruptible(&device->wait_queue);
atomic_notifier_call_chain(
diff --git a/drivers/i2c/busses/i2c-qup.c b/drivers/i2c/busses/i2c-qup.c
index c6bbb0d..00c7633 100644
--- a/drivers/i2c/busses/i2c-qup.c
+++ b/drivers/i2c/busses/i2c-qup.c
@@ -527,7 +527,7 @@
*/
if (rem > 1) {
struct i2c_msg *next = msg + 1;
- if (next->addr == msg->addr && (next->flags | I2C_M_RD)
+ if (next->addr == msg->addr && (next->flags & I2C_M_RD)
&& *idx == ((dev->wr_sz*2) - 4)) {
writel_relaxed(((last_entry |
msg->buf[dev->pos]) |
diff --git a/drivers/media/video/msm/msm.c b/drivers/media/video/msm/msm.c
index 847a1ec..727b751 100644
--- a/drivers/media/video/msm/msm.c
+++ b/drivers/media/video/msm/msm.c
@@ -136,17 +136,20 @@
struct msm_device_queue *queue = &server_dev->ctrl_q;
struct v4l2_event v4l2_evt;
- struct msm_isp_stats_event_ctrl *isp_event;
+ struct msm_isp_event_ctrl *isp_event;
+ isp_event = kzalloc(sizeof(struct msm_isp_event_ctrl), GFP_KERNEL);
+ if (!isp_event) {
+ pr_err("%s Insufficient memory. return", __func__);
+ return -ENOMEM;
+ }
D("%s\n", __func__);
v4l2_evt.type = V4L2_EVENT_PRIVATE_START + MSM_CAM_RESP_V4L2;
-
/* setup event object to transfer the command; */
- isp_event = (struct msm_isp_stats_event_ctrl *)v4l2_evt.u.data;
+ *((uint32_t *)v4l2_evt.u.data) = (uint32_t)isp_event;
isp_event->resptype = MSM_CAM_RESP_V4L2;
isp_event->isp_data.ctrl = *out;
-
- /* now send command to config thread in usersspace,
+ /* now send command to config thread in userspace,
* and wait for results */
v4l2_event_queue(server_dev->server_command_queue.pvdev,
&v4l2_evt);
@@ -181,6 +184,7 @@
out->value = value;
free_qcmd(rcmd);
+ kfree(isp_event);
D("%s: rc %d\n", __func__, rc);
/* rc is the time elapsed. */
if (rc >= 0) {
@@ -1739,45 +1743,80 @@
break;
case VIDIOC_DQEVENT: {
- void __user *u_ctrl_value = NULL;
- struct msm_isp_stats_event_ctrl *u_isp_event;
- struct msm_isp_stats_event_ctrl *k_isp_event;
+ void __user *u_ctrl_value = NULL, *user_ptr = NULL;
+ struct msm_isp_event_ctrl u_isp_event;
+ struct msm_isp_event_ctrl *k_isp_event;
- /* Make a copy of control value and event data pointer */
+ /* First, copy the event structure from userspace */
D("%s: VIDIOC_DQEVENT\n", __func__);
if (copy_from_user(&ev, (void __user *)arg,
- sizeof(struct v4l2_event)))
+ sizeof(struct v4l2_event))) {
break;
- u_isp_event = (struct msm_isp_stats_event_ctrl *)ev.u.data;
- u_ctrl_value = u_isp_event->isp_data.ctrl.value;
+ }
+ /* Next, get the pointer to event_ctrl structure
+ * embedded inside the v4l2_event.u.data array. */
+ user_ptr = (void __user *)(*((uint32_t *)ev.u.data));
+ /* Next, copy the userspace event ctrl structure */
+ if (copy_from_user((void *)&u_isp_event, user_ptr,
+ sizeof(struct msm_isp_event_ctrl))) {
+ break;
+ }
+
+ /* Save the pointer of the user allocated command buffer*/
+ u_ctrl_value = u_isp_event.isp_data.ctrl.value;
+
+ /* Dequeue the event queued into the v4l2 queue*/
rc = v4l2_event_dequeue(
&g_server_dev.server_command_queue.eventHandle,
- &ev, fp->f_flags & O_NONBLOCK);
+ &ev, fp->f_flags & O_NONBLOCK);
if (rc < 0) {
pr_err("no pending events?");
break;
}
- k_isp_event = (struct msm_isp_stats_event_ctrl *)ev.u.data;
- if (ev.type == V4L2_EVENT_PRIVATE_START+MSM_CAM_RESP_V4L2 &&
- k_isp_event->isp_data.ctrl.length > 0) {
- void *k_ctrl_value = k_isp_event->isp_data.ctrl.value;
- if (copy_to_user(u_ctrl_value, k_ctrl_value,
- u_isp_event->isp_data.ctrl.length)) {
+ /* Use k_isp_event to point to the event_ctrl structure
+ * embedded inside v4l2_event.u.data */
+ k_isp_event = (struct msm_isp_event_ctrl *)
+ (*((uint32_t *)ev.u.data));
+ if (!k_isp_event) {
+ pr_err("%s Invalid event ctrl structure. ", __func__);
+ break;
+ }
+
+ /* Copy the event structure into user struct*/
+ u_isp_event = *k_isp_event;
+
+ /* Restore the saved pointer of the user
+ * allocated command buffer. */
+ u_isp_event.isp_data.ctrl.value = u_ctrl_value;
+ if (ev.type == V4L2_EVENT_PRIVATE_START+MSM_CAM_RESP_V4L2) {
+ /* Copy the ctrl cmd, if present*/
+ if (k_isp_event->isp_data.ctrl.length > 0) {
+ void *k_ctrl_value =
+ k_isp_event->isp_data.ctrl.value;
+ if (copy_to_user(u_ctrl_value, k_ctrl_value,
+ k_isp_event->isp_data.ctrl.length)) {
+ rc = -EINVAL;
+ break;
+ }
+ }
+ /* Copy the event ctrl structure back into
+ * user's structure. */
+ if (copy_to_user(user_ptr, (void *)&u_isp_event,
+ sizeof(struct msm_isp_event_ctrl))) {
rc = -EINVAL;
break;
}
}
- k_isp_event->isp_data.ctrl.value = u_ctrl_value;
+ /* Copy the v4l2_event structure back to the user*/
if (copy_to_user((void __user *)arg, &ev,
sizeof(struct v4l2_event))) {
rc = -EINVAL;
break;
}
}
-
break;
case MSM_CAM_IOCTL_CTRL_CMD_DONE:
@@ -1900,46 +1939,77 @@
break;
case VIDIOC_DQEVENT: {
- void __user *u_msg_value = NULL;
- struct msm_isp_stats_event_ctrl *u_isp_event;
- struct msm_isp_stats_event_ctrl *k_isp_event;
+ void __user *u_msg_value = NULL, *user_ptr = NULL;
+ struct msm_isp_event_ctrl u_isp_event;
+ struct msm_isp_event_ctrl *k_isp_event;
- /* Make a copy of control value and event data pointer */
+ /* First, copy the v4l2 event structure from userspace */
D("%s: VIDIOC_DQEVENT\n", __func__);
if (copy_from_user(&ev, (void __user *)arg,
sizeof(struct v4l2_event)))
break;
- u_isp_event =
- (struct msm_isp_stats_event_ctrl *)ev.u.data;
- u_msg_value = u_isp_event->isp_data.isp_msg.data;
+ /* Next, get the pointer to event_ctrl structure
+ * embedded inside the v4l2_event.u.data array. */
+ user_ptr = (void __user *)(*((uint32_t *)ev.u.data));
+ /* Next, copy the userspace event ctrl structure */
+ if (copy_from_user((void *)&u_isp_event, user_ptr,
+ sizeof(struct msm_isp_event_ctrl))) {
+ break;
+ }
+ /* Save the pointer of the user allocated command buffer*/
+ u_msg_value = u_isp_event.isp_data.isp_msg.data;
+
+ /* Dequeue the event queued into the v4l2 queue*/
rc = v4l2_event_dequeue(
- &config_cam->config_stat_event_queue.eventHandle,
- &ev, fp->f_flags & O_NONBLOCK);
+ &config_cam->config_stat_event_queue.eventHandle,
+ &ev, fp->f_flags & O_NONBLOCK);
if (rc < 0) {
pr_err("no pending events?");
break;
}
+ /* Use k_isp_event to point to the event_ctrl structure
+ * embedded inside v4l2_event.u.data */
+ k_isp_event = (struct msm_isp_event_ctrl *)
+ (*((uint32_t *)ev.u.data));
+ /* Copy the event structure into user struct. */
+ u_isp_event = *k_isp_event;
+
if (ev.type != (V4L2_EVENT_PRIVATE_START +
MSM_CAM_RESP_DIV_FRAME_EVT_MSG) &&
ev.type != (V4L2_EVENT_PRIVATE_START +
MSM_CAM_RESP_MCTL_PP_EVENT)) {
- k_isp_event =
- (struct msm_isp_stats_event_ctrl *)ev.u.data;
+
+ /* Restore the saved pointer of the
+ * user allocated command buffer. */
+ u_isp_event.isp_data.isp_msg.data = u_msg_value;
+
if (ev.type == (V4L2_EVENT_PRIVATE_START +
- MSM_CAM_RESP_STAT_EVT_MSG) &&
- k_isp_event->isp_data.isp_msg.len > 0) {
- void *k_msg_value =
+ MSM_CAM_RESP_STAT_EVT_MSG)) {
+ if (k_isp_event->isp_data.isp_msg.len > 0) {
+ void *k_msg_value =
k_isp_event->isp_data.isp_msg.data;
- if (copy_to_user(u_msg_value, k_msg_value,
- k_isp_event->isp_data.isp_msg.len)) {
- rc = -EINVAL;
- break;
+ if (copy_to_user(u_msg_value,
+ k_msg_value,
+ k_isp_event->isp_data.isp_msg.len)) {
+ rc = -EINVAL;
+ break;
+ }
+ kfree(k_msg_value);
}
- kfree(k_msg_value);
}
- k_isp_event->isp_data.isp_msg.data = u_msg_value;
}
+ /* Copy the event ctrl structure back
+ * into user's structure. */
+ if (copy_to_user(user_ptr,
+ (void *)&u_isp_event, sizeof(
+ struct msm_isp_event_ctrl))) {
+ rc = -EINVAL;
+ break;
+ }
+ kfree(k_isp_event);
+
+ /* Copy the v4l2_event structure back to the user*/
if (copy_to_user((void __user *)arg, &ev,
sizeof(struct v4l2_event))) {
rc = -EINVAL;
diff --git a/drivers/media/video/msm/msm_io_8960.c b/drivers/media/video/msm/msm_io_8960.c
index 43f893b..45871bc 100644
--- a/drivers/media/video/msm/msm_io_8960.c
+++ b/drivers/media/video/msm/msm_io_8960.c
@@ -60,6 +60,7 @@
#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
@@ -105,6 +106,9 @@
#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;
@@ -113,7 +117,10 @@
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;
@@ -497,6 +504,13 @@
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");
@@ -504,6 +518,20 @@
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");
@@ -596,10 +624,22 @@
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;
@@ -744,6 +784,40 @@
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;
@@ -824,8 +898,18 @@
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);
@@ -1034,6 +1118,7 @@
if (rc < 0)
goto csiphy_irq_fail;
#endif
+ msm_camio_enable_v2_clks();
CDBG("camio enable done\n");
return 0;
#if DBG_CSIPHY
diff --git a/drivers/media/video/msm/msm_isp.c b/drivers/media/video/msm/msm_isp.c
index 701f2d9..d914404 100644
--- a/drivers/media/video/msm/msm_isp.c
+++ b/drivers/media/video/msm/msm_isp.c
@@ -142,7 +142,7 @@
{
int rc = 0;
struct v4l2_event v4l2_evt;
- struct msm_isp_stats_event_ctrl *isp_event;
+ struct msm_isp_event_ctrl *isp_event;
struct msm_sync *sync =
(struct msm_sync *)v4l2_get_subdev_hostdata(sd);
struct msm_cam_media_controller *pmctl = &sync->pcam_sync->mctl;
@@ -157,9 +157,16 @@
if (notification == NOTIFY_VFE_BUF_EVT)
return msm_isp_notify_VFE_BUF_EVT(sd, arg);
+ isp_event = kzalloc(sizeof(struct msm_isp_event_ctrl), GFP_KERNEL);
+ if (!isp_event) {
+ pr_err("%s Insufficient memory. return", __func__);
+ return -ENOMEM;
+ }
+
v4l2_evt.type = V4L2_EVENT_PRIVATE_START +
MSM_CAM_RESP_STAT_EVT_MSG;
- isp_event = (struct msm_isp_stats_event_ctrl *)v4l2_evt.u.data;
+ *((uint32_t *)v4l2_evt.u.data) = (uint32_t)isp_event;
+
isp_event->resptype = MSM_CAM_RESP_STAT_EVT_MSG;
isp_event->isp_data.isp_msg.type = MSM_CAMERA_MSG;
isp_event->isp_data.isp_msg.len = 0;
diff --git a/drivers/media/video/msm/msm_ispif.c b/drivers/media/video/msm/msm_ispif.c
index c5e38ef..8797d38 100644
--- a/drivers/media/video/msm/msm_ispif.c
+++ b/drivers/media/video/msm/msm_ispif.c
@@ -47,6 +47,7 @@
#define ISPIF_IRQ_MASK_1_ADDR 0X010C
#define ISPIF_IRQ_CLEAR_1_ADDR 0X0110
#define ISPIF_IRQ_STATUS_1_ADDR 0X0114
+#define ISPIF_IRQ_GLOBAL_CLEAR_CMD_ADDR 0x0124
/*ISPIF RESET BITS*/
@@ -73,9 +74,11 @@
#define ISPIF_IRQ_STATUS_MASK 0xA493000
#define ISPIF_IRQ_1_STATUS_MASK 0xA493000
#define ISPIF_IRQ_STATUS_RDI_SOF_MASK 0x492000
+#define ISPIF_IRQ_GLOBAL_CLEAR_CMD 0x1
#define MAX_CID 15
+
static struct ispif_device *ispif;
static uint32_t global_intf_cmd_mask = 0xFFFFFFFF;
@@ -207,6 +210,8 @@
ISPIF_IRQ_MASK_ADDR);
msm_io_w(ISPIF_IRQ_STATUS_MASK, ispif->base +
ISPIF_IRQ_CLEAR_ADDR);
+ msm_io_w(ISPIF_IRQ_GLOBAL_CLEAR_CMD, ispif->base +
+ ISPIF_IRQ_GLOBAL_CLEAR_CMD_ADDR);
return rc;
}
@@ -410,6 +415,8 @@
}
msm_io_w(out->ispifIrqStatus0,
ispif->base + ISPIF_IRQ_CLEAR_ADDR);
+ msm_io_w(ISPIF_IRQ_GLOBAL_CLEAR_CMD, ispif->base +
+ ISPIF_IRQ_GLOBAL_CLEAR_CMD_ADDR);
}
static irqreturn_t msm_io_ispif_irq(int irq_num, void *data)
diff --git a/drivers/media/video/msm/msm_mctl_buf.c b/drivers/media/video/msm/msm_mctl_buf.c
index a83fa00..a8554ee 100644
--- a/drivers/media/video/msm/msm_mctl_buf.c
+++ b/drivers/media/video/msm/msm_mctl_buf.c
@@ -516,8 +516,8 @@
idx = msm_mctl_out_type_to_inst_index(pmctl->sync.pcam_sync,
msg_type);
pcam_inst = pmctl->sync.pcam_sync->dev_inst[idx];
- if (!pcam_inst->streamon) {
- D("%s: stream 0x%p is off\n", __func__, pcam_inst);
+ if (!pcam_inst || !pcam_inst->streamon) {
+ D("%s: stream is turned off\n", __func__);
return rc;
}
spin_lock_irqsave(&pcam_inst->vq_irqlock, flags);
diff --git a/drivers/media/video/msm/msm_mctl_pp.c b/drivers/media/video/msm/msm_mctl_pp.c
index f0c1bfa..7040c29 100644
--- a/drivers/media/video/msm/msm_mctl_pp.c
+++ b/drivers/media/video/msm/msm_mctl_pp.c
@@ -41,14 +41,22 @@
struct msm_cam_evt_divert_frame *div)
{
struct v4l2_event v4l2_evt;
-
+ struct msm_isp_event_ctrl *isp_event;
+ isp_event = kzalloc(sizeof(struct msm_isp_event_ctrl),
+ GFP_KERNEL);
+ if (!isp_event) {
+ pr_err("%s Insufficient memory. return", __func__);
+ return -ENOMEM;
+ }
D("%s: msm_cam_evt_divert_frame=%d",
__func__, sizeof(struct msm_cam_evt_divert_frame));
memset(&v4l2_evt, 0, sizeof(v4l2_evt));
v4l2_evt.type = V4L2_EVENT_PRIVATE_START +
MSM_CAM_RESP_DIV_FRAME_EVT_MSG;
- memcpy(&v4l2_evt.u.data[0], div,
- sizeof(struct msm_cam_evt_divert_frame));
+ *((uint32_t *)v4l2_evt.u.data) = (uint32_t)isp_event;
+ /* Copy the divert frame struct into event ctrl struct. */
+ isp_event->isp_data.div_frame = *div;
+
D("%s inst=%p, img_mode=%d, frame_id=%d,phy=0x%x,len=%d\n",
__func__, pcam_inst, pcam_inst->image_mode, div->frame_id,
(uint32_t)div->phy_addr, div->length);
@@ -563,7 +571,7 @@
pp_frame_info->dest_frame.handle;
msm_mctl_buf_done_pp(
p_mctl, msg_type, &done_frame, 0);
- pr_err("%s: vpe done to app, vb=0x%x, path=%d, phy=0x%x",
+ pr_info("%s: vpe done to app, vb=0x%x, path=%d, phy=0x%x",
__func__, done_frame.vb,
pp_frame_cmd->path, done_frame.ch_paddr[0]);
}
@@ -571,21 +579,31 @@
pp_frame_cmd->vpe_output_action)) {
struct v4l2_event v4l2_evt;
struct msm_mctl_pp_event_info *pp_event_info;
+ struct msm_isp_event_ctrl *isp_event;
+ isp_event = kzalloc(sizeof(struct msm_isp_event_ctrl),
+ GFP_KERNEL);
+ if (!isp_event) {
+ pr_err("%s Insufficient memory.", __func__);
+ return -ENOMEM;
+ }
memset(&v4l2_evt, 0, sizeof(v4l2_evt));
- pp_event_info =
- (struct msm_mctl_pp_event_info *)v4l2_evt.
- u.data;
+ *((uint32_t *)v4l2_evt.u.data) = (uint32_t)isp_event;
+
+ /* Get hold of pp event info struct inside event ctrl.*/
+ pp_event_info = &(isp_event->isp_data.pp_event_info);
+
pp_event_info->event = MCTL_PP_EVENT_CMD_ACK;
pp_event_info->ack.cmd = pp_frame_info->user_cmd;
pp_event_info->ack.status = 0;
pp_event_info->ack.cookie = pp_frame_cmd->cookie;
v4l2_evt.type = V4L2_EVENT_PRIVATE_START +
MSM_CAM_RESP_MCTL_PP_EVENT;
+
v4l2_event_queue(
p_mctl->config_device->
config_stat_event_queue.pvdev,
&v4l2_evt);
- pr_err("%s: ack to daemon, cookie=0x%x, event = 0x%x",
+ D("%s: ack to daemon, cookie=0x%x, event = 0x%x",
__func__, pp_frame_info->pp_frame_cmd.cookie,
v4l2_evt.type);
}
diff --git a/drivers/media/video/msm/msm_vfe32.c b/drivers/media/video/msm/msm_vfe32.c
index c801e4a..ea70ce5 100644
--- a/drivers/media/video/msm/msm_vfe32.c
+++ b/drivers/media/video/msm/msm_vfe32.c
@@ -199,7 +199,7 @@
V32_DEMOSAICV3_DBCC_OFF},
{VFE_CMD_DEMOSAICV3_DBPC_UPDATE},
{VFE_CMD_XBAR_CFG},
- {VFE_CMD_EZTUNE_CFG},
+ {VFE_CMD_MODULE_CFG, V32_MODULE_CFG_LEN, V32_MODULE_CFG_OFF},
{VFE_CMD_ZSL},
/*115*/ {VFE_CMD_LINEARIZATION_UPDATE, V32_LINEARIZATION_LEN1,
V32_LINEARIZATION_OFF1},
@@ -678,7 +678,7 @@
msm_io_w(VFE_IMASK_WHILE_STOPPING_1,
vfe32_ctrl->vfebase + VFE_IRQ_MASK_1);
- msm_io_dump(vfe32_ctrl->vfebase, 0x740);
+ msm_io_dump(vfe32_ctrl->vfebase, 0x7B4);
/* Ensure the write order while writing
to the command register using the barrier */
@@ -1807,7 +1807,7 @@
vfe32_sync_timer_start(cmdp);
break;
- case VFE_CMD_EZTUNE_CFG: {
+ case VFE_CMD_MODULE_CFG: {
cmdp = kmalloc(cmd->length, GFP_ATOMIC);
if (!cmdp) {
rc = -ENOMEM;
@@ -1885,16 +1885,16 @@
msm_io_memcpy(vfe32_ctrl->vfebase + V33_PCA_ROLL_OFF_CFG_OFF2,
cmdp_local, V33_PCA_ROLL_OFF_CFG_LEN2);
+ cmdp_local += 3;
CDBG("%s: start writing RollOff Ram0 table\n", __func__);
vfe32_program_dmi_cfg(ROLLOFF_RAM0_BANK0);
msm_io_w(temp1, vfe32_ctrl->vfebase + VFE_DMI_ADDR);
for (i = 0 ; i < V33_PCA_ROLL_OFF_TABLE_SIZE ; i++) {
- msm_io_w(*cmdp_local,
+ msm_io_w(*(cmdp_local + 1),
vfe32_ctrl->vfebase + VFE33_DMI_DATA_HI);
- cmdp_local++;
msm_io_w(*cmdp_local,
vfe32_ctrl->vfebase + VFE33_DMI_DATA_LO);
- cmdp_local++;
+ cmdp_local += 2;
}
CDBG("%s: end writing RollOff Ram0 table\n", __func__);
@@ -1902,10 +1902,9 @@
vfe32_program_dmi_cfg(ROLLOFF_RAM1_BANK0);
msm_io_w(temp1, vfe32_ctrl->vfebase + VFE_DMI_ADDR);
for (i = 0 ; i < V33_PCA_ROLL_OFF_TABLE_SIZE ; i++) {
- cmdp_local++;
msm_io_w(*cmdp_local,
vfe32_ctrl->vfebase + VFE33_DMI_DATA_LO);
- cmdp_local++;
+ cmdp_local += 2;
}
CDBG("%s: end writing RollOff Ram1 table\n", __func__);
@@ -1941,12 +1940,11 @@
msm_io_w(temp1, vfe32_ctrl->vfebase + VFE_DMI_ADDR);
for (i = 0 ; i < V33_PCA_ROLL_OFF_TABLE_SIZE ; i++) {
- msm_io_w(*cmdp_local,
+ msm_io_w(*(cmdp_local + 1),
vfe32_ctrl->vfebase + VFE33_DMI_DATA_HI);
- cmdp_local++;
msm_io_w(*cmdp_local,
vfe32_ctrl->vfebase + VFE33_DMI_DATA_LO);
- cmdp_local++;
+ cmdp_local += 2;
}
CDBG("%s: end writing RollOff Ram0 table\n", __func__);
@@ -1958,10 +1956,9 @@
msm_io_w(temp1, vfe32_ctrl->vfebase + VFE_DMI_ADDR);
for (i = 0 ; i < V33_PCA_ROLL_OFF_TABLE_SIZE ; i++) {
- cmdp_local++;
msm_io_w(*cmdp_local,
vfe32_ctrl->vfebase + VFE33_DMI_DATA_LO);
- cmdp_local++;
+ cmdp_local += 2;
}
CDBG("%s: end writing RollOff Ram1 table\n", __func__);
diff --git a/drivers/media/video/msm/msm_vfe32.h b/drivers/media/video/msm/msm_vfe32.h
index d3ed0e6..d763c2e 100644
--- a/drivers/media/video/msm/msm_vfe32.h
+++ b/drivers/media/video/msm/msm_vfe32.h
@@ -332,8 +332,8 @@
#define V32_DEMOSAICV3_ABF_OFF 0x000002A4
#define V32_DEMOSAICV3_ABF_LEN 180
-#define V32_EZTUNE_CFG_OFF 0x00000010
-#define V32_EZTUNE_CFG_LEN 4
+#define V32_MODULE_CFG_OFF 0x00000010
+#define V32_MODULE_CFG_LEN 4
#define V32_CLF_CFG_OFF 0x000006B0
#define V32_CLF_CFG_LEN 72
diff --git a/drivers/misc/pmic8058-xoadc.c b/drivers/misc/pmic8058-xoadc.c
index d2d8cba..f21668a 100644
--- a/drivers/misc/pmic8058-xoadc.c
+++ b/drivers/misc/pmic8058-xoadc.c
@@ -23,6 +23,7 @@
#include <linux/slab.h>
#include <linux/ratelimit.h>
#include <linux/delay.h>
+#include <linux/wakelock.h>
#include <mach/mpp.h>
#include <mach/msm_xo.h>
@@ -65,6 +66,9 @@
struct adc_conv_slot conv_queue_elements[MAX_QUEUE_LENGTH];
int xoadc_num;
struct msm_xo_voter *adc_voter;
+ struct wake_lock adc_wakelock;
+ /* flag to warn/bug if wakelocks are taken after suspend_noirq */
+ int msm_suspend_check;
};
static struct pmic8058_adc *pmic_adc[XOADC_PMIC_0 + 1];
@@ -117,7 +121,7 @@
EXPORT_SYMBOL(pm8058_xoadc_slot_request);
static int32_t pm8058_xoadc_arb_cntrl(uint32_t arb_cntrl,
- uint32_t adc_instance)
+ uint32_t adc_instance, uint32_t channel)
{
struct pmic8058_adc *adc_pmic = pmic_adc[adc_instance];
int i, rc;
@@ -128,9 +132,13 @@
ADC_ARB_USRP_CNTRL_RSV4;
if (arb_cntrl) {
+ if (adc_pmic->msm_suspend_check)
+ pr_err("XOADC request being made after suspend irq "
+ "with channel id:%d\n", channel);
data_arb_cntrl |= ADC_ARB_USRP_CNTRL_EN_ARB;
msm_xo_mode_vote(adc_pmic->adc_voter, MSM_XO_MODE_ON);
adc_pmic->pdata->xoadc_mpp_config();
+ wake_lock(&adc_pmic->adc_wakelock);
}
/* Write twice to the CNTRL register for the arbiter settings
@@ -144,8 +152,10 @@
}
}
- if (!arb_cntrl)
+ if (!arb_cntrl) {
msm_xo_mode_vote(adc_pmic->adc_voter, MSM_XO_MODE_OFF);
+ wake_unlock(&adc_pmic->adc_wakelock);
+ }
return 0;
}
@@ -159,7 +169,7 @@
u8 data_dig_param, data_ana_param2;
int rc;
- rc = pm8058_xoadc_arb_cntrl(1, adc_instance);
+ rc = pm8058_xoadc_arb_cntrl(1, adc_instance, slot->chan_path);
if (rc < 0) {
pr_debug("%s: Configuring ADC Arbiter"
"enable failed\n", __func__);
@@ -461,7 +471,7 @@
/* Default value for switching off the arbiter after reading
the ADC value. Bit 0 set to 0. */
if (adc_pmic->xoadc_queue_count == 0) {
- rc = pm8058_xoadc_arb_cntrl(0, adc_instance);
+ rc = pm8058_xoadc_arb_cntrl(0, adc_instance, CHANNEL_MUXOFF);
if (rc < 0) {
pr_debug("%s: Configuring ADC Arbiter disable"
"failed\n", __func__);
@@ -607,6 +617,37 @@
}
EXPORT_SYMBOL(pm8058_xoadc_calibrate);
+#ifdef CONFIG_PM
+static int pm8058_xoadc_suspend_noirq(struct device *dev)
+{
+ struct platform_device *pdev = to_platform_device(dev);
+ struct pmic8058_adc *adc_pmic = platform_get_drvdata(pdev);
+
+ adc_pmic->msm_suspend_check = 1;
+
+ return 0;
+}
+
+static int pm8058_xoadc_resume_noirq(struct device *dev)
+{
+ struct platform_device *pdev = to_platform_device(dev);
+ struct pmic8058_adc *adc_pmic = platform_get_drvdata(pdev);
+
+ adc_pmic->msm_suspend_check = 0;
+
+ return 0;
+}
+
+static const struct dev_pm_ops pm8058_xoadc_dev_pm_ops = {
+ .suspend_noirq = pm8058_xoadc_suspend_noirq,
+ .resume_noirq = pm8058_xoadc_resume_noirq,
+};
+
+#define PM8058_XOADC_DEV_PM_OPS (&pm8058_xoadc_dev_pm_ops)
+#else
+#define PM8058_XOADC_DEV_PM_OPS NULL
+#endif
+
static int __devexit pm8058_xoadc_teardown(struct platform_device *pdev)
{
struct pmic8058_adc *adc_pmic = platform_get_drvdata(pdev);
@@ -614,6 +655,7 @@
if (adc_pmic->pdata->xoadc_vreg_shutdown != NULL)
adc_pmic->pdata->xoadc_vreg_shutdown();
+ wake_lock_destroy(&adc_pmic->adc_wakelock);
msm_xo_put(adc_pmic->adc_voter);
platform_set_drvdata(pdev, adc_pmic->pm_chip);
device_init_wakeup(&pdev->dev, 0);
@@ -728,6 +770,9 @@
}
}
+ wake_lock_init(&adc_pmic->adc_wakelock, WAKE_LOCK_SUSPEND,
+ "pmic8058_xoadc_wakelock");
+
pmic_adc[adc_pmic->xoadc_num] = adc_pmic;
if (pdata->xoadc_vreg_setup != NULL)
@@ -750,6 +795,7 @@
.driver = {
.name = "pm8058-xoadc",
.owner = THIS_MODULE,
+ .pm = PM8058_XOADC_DEV_PM_OPS,
},
};
diff --git a/drivers/net/wireless/libra/qcomwlan7x27a_pwrif.c b/drivers/net/wireless/libra/qcomwlan7x27a_pwrif.c
index 51dd125..5da7a42 100644
--- a/drivers/net/wireless/libra/qcomwlan7x27a_pwrif.c
+++ b/drivers/net/wireless/libra/qcomwlan7x27a_pwrif.c
@@ -65,19 +65,11 @@
goto out;
}
- rc = regulator_bulk_set_voltage(ARRAY_SIZE(regs), regs);
- if (rc) {
- pr_err("%s: could not set voltages: %d\n", __func__, rc);
- goto reg_free;
- }
-
for (i = 0; i < ARRAY_SIZE(regs); i++)
vreg_info[i].reg = regs[i].consumer;
return 0;
-reg_free:
- regulator_bulk_free(ARRAY_SIZE(regs), regs);
out:
return rc;
}
@@ -134,6 +126,25 @@
for (index = 0; index < ARRAY_SIZE(vreg_info); index++) {
if (on) {
+
+ rc = regulator_set_voltage(vreg_info[index].reg,
+ vreg_info[index].vreg_level,
+ vreg_info[index].vreg_level);
+ if (rc) {
+ pr_err("%s:%s set voltage failed %d\n",
+ __func__, vreg_info[index].vreg_id, rc);
+
+ goto vreg_fail;
+ }
+
+ rc = regulator_enable(vreg_info[index].reg);
+ if (rc) {
+ pr_err("%s:%s vreg enable failed %d\n",
+ __func__, vreg_info[index].vreg_id, rc);
+
+ goto vreg_fail;
+ }
+
if (vreg_info[index].is_vreg_pin_controlled) {
rc = pmapp_vreg_lpm_pincntrl_vote(id,
vreg_info[index].pmapp_id,
@@ -143,17 +154,10 @@
" for enable failed %d\n",
__func__,
vreg_info[index].vreg_id, rc);
- goto vreg_fail;
- }
- } else {
- rc = regulator_enable(vreg_info[index].reg);
- if (rc) {
- pr_err("%s:%s vreg enable failed %d\n",
- __func__,
- vreg_info[index].vreg_id, rc);
- goto vreg_fail;
+ goto vreg_clock_vote_fail;
}
}
+
/*At this point CLK_PWR_REQ is high*/
if (WLAN_VREG_L6 == index) {
/*
@@ -182,13 +186,11 @@
__func__,
vreg_info[index].vreg_id, rc);
}
- } else {
- rc = regulator_disable(vreg_info[index].reg);
- if (rc) {
- pr_err("%s:%s vreg disable failed %d\n",
- __func__,
- vreg_info[index].vreg_id, rc);
- }
+ }
+ rc = regulator_disable(vreg_info[index].reg);
+ if (rc) {
+ pr_err("%s:%s vreg disable failed %d\n",
+ __func__, vreg_info[index].vreg_id, rc);
}
}
}
@@ -196,7 +198,7 @@
vreg_fail:
index--;
vreg_clock_vote_fail:
- while (index > 0) {
+ while (index >= 0) {
rc = regulator_disable(vreg_info[index].reg);
if (rc) {
pr_err("%s:%s vreg disable failed %d\n",
diff --git a/drivers/net/wireless/libra/qcomwlan_pwrif.c b/drivers/net/wireless/libra/qcomwlan_pwrif.c
index 721e9c3..de8b918 100644
--- a/drivers/net/wireless/libra/qcomwlan_pwrif.c
+++ b/drivers/net/wireless/libra/qcomwlan_pwrif.c
@@ -42,6 +42,15 @@
"8058_s2",
"8058_s1",
};
+ static const char *vregs_qwlan_pc_name[] = {
+ "8058_l20_pc",
+ "8058_l8_pc",
+ NULL,
+ NULL,
+ "8901_l0_pc",
+ "8058_s2_pc",
+ NULL,
+ };
static const int vregs_qwlan_val_min[] = {
1800000,
3050000,
@@ -80,6 +89,7 @@
};
bool const *vregs_is_pin_controlled;
static struct regulator *vregs_qwlan[ARRAY_SIZE(vregs_qwlan_name)];
+ static struct regulator *vregs_pc_qwlan[ARRAY_SIZE(vregs_qwlan_name)];
static struct msm_xo_voter *wlan_clock;
int ret, i, rc = 0;
unsigned wlan_gpio_deep_sleep = GPIO_WLAN_DEEP_SLEEP_N;
@@ -157,11 +167,14 @@
}
/* vote for pin control (if needed) */
if (vregs_is_pin_controlled[i]) {
- rc = regulator_set_mode(vregs_qwlan[i],
- REGULATOR_MODE_IDLE);
- if (rc) {
- pr_err("regulator_set_mode(%s) failed\n",
- vregs_qwlan_name[i]);
+ vregs_pc_qwlan[i] = regulator_get(NULL,
+ vregs_qwlan_pc_name[i]);
+ if (IS_ERR(vregs_pc_qwlan[i])) {
+ pr_err("regulator get of %s failed "
+ "(%ld)\n",
+ vregs_qwlan_pc_name[i],
+ PTR_ERR(vregs_pc_qwlan[i]));
+ rc = PTR_ERR(vregs_pc_qwlan[i]);
goto vreg_fail;
}
}
@@ -173,7 +186,23 @@
vregs_qwlan_name[i], rc);
goto vreg_fail;
}
+ if (vregs_is_pin_controlled[i]) {
+ rc = regulator_enable(vregs_pc_qwlan[i]);
+ if (rc < 0) {
+ pr_err("vreg %s enable failed (%d)\n",
+ vregs_qwlan_pc_name[i], rc);
+ goto vreg_fail;
+ }
+ }
} else if (!on && wlan_on) {
+ if (vregs_is_pin_controlled[i]) {
+ rc = regulator_disable(vregs_pc_qwlan[i]);
+ if (rc < 0) {
+ pr_err("vreg %s disable failed (%d)\n",
+ vregs_qwlan_pc_name[i], rc);
+ goto vreg_fail;
+ }
+ }
rc = regulator_disable(vregs_qwlan[i]);
if (rc < 0) {
pr_err("vreg %s disable failed (%d)\n",
@@ -192,6 +221,8 @@
vreg_fail:
regulator_put(vregs_qwlan[i]);
+ if (vregs_is_pin_controlled[i])
+ regulator_put(vregs_pc_qwlan[i]);
vreg_get_fail:
i--;
while (i >= 0) {
@@ -202,7 +233,18 @@
vregs_qwlan_name[i],
!on ? "enable" : "disable", ret);
}
+ if (vregs_is_pin_controlled[i]) {
+ ret = !on ? regulator_enable(vregs_pc_qwlan[i]) :
+ regulator_disable(vregs_pc_qwlan[i]);
+ if (ret < 0) {
+ pr_err("vreg %s %s failed (%d) in err path\n",
+ vregs_qwlan_pc_name[i],
+ !on ? "enable" : "disable", ret);
+ }
+ }
regulator_put(vregs_qwlan[i]);
+ if (vregs_is_pin_controlled[i])
+ regulator_put(vregs_pc_qwlan[i]);
i--;
}
if (!on)
diff --git a/drivers/net/wireless/wcnss/wcnss_wlan.c b/drivers/net/wireless/wcnss/wcnss_wlan.c
index e6945d5..c16632e 100644
--- a/drivers/net/wireless/wcnss/wcnss_wlan.c
+++ b/drivers/net/wireless/wcnss/wcnss_wlan.c
@@ -85,8 +85,10 @@
static int __devinit
wcnss_wlan_ctrl_probe(struct platform_device *pdev)
{
- if (penv)
- penv->smd_channel_ready = 1;
+ if (!penv)
+ return -ENODEV;
+
+ penv->smd_channel_ready = 1;
pr_info("%s: SMD ctrl channel up\n", __func__);
diff --git a/drivers/usb/gadget/f_rmnet.c b/drivers/usb/gadget/f_rmnet.c
index 2a61337..ebbd1d8 100644
--- a/drivers/usb/gadget/f_rmnet.c
+++ b/drivers/usb/gadget/f_rmnet.c
@@ -41,6 +41,7 @@
int ifc_id;
u8 port_num;
atomic_t online;
+ atomic_t ctrl_online;
struct usb_composite_dev *cdev;
spinlock_t lock;
@@ -297,6 +298,8 @@
static void frmnet_disable(struct usb_function *f)
{
struct f_rmnet *dev = func_to_rmnet(f);
+ unsigned long flags;
+ struct rmnet_ctrl_pkt *cpkt;
pr_debug("%s: port#%d\n", __func__, dev->port_num);
@@ -304,6 +307,17 @@
atomic_set(&dev->online, 0);
+ spin_lock_irqsave(&dev->lock, flags);
+ while (!list_empty(&dev->cpkt_resp_q)) {
+ cpkt = list_first_entry(&dev->cpkt_resp_q,
+ struct rmnet_ctrl_pkt, list);
+
+ list_del(&cpkt->list);
+ rmnet_free_ctrl_pkt(cpkt);
+ }
+ atomic_set(&dev->notify_count, 0);
+ spin_unlock_irqrestore(&dev->lock, flags);
+
gport_rmnet_disconnect(dev);
}
@@ -384,6 +398,73 @@
}
}
+static void frmnet_connect(struct grmnet *gr)
+{
+ struct f_rmnet *dev;
+
+ if (!gr) {
+ pr_err("%s: Invalid grmnet:%p\n", __func__, gr);
+ return;
+ }
+
+ dev = port_to_rmnet(gr);
+
+ atomic_set(&dev->ctrl_online, 1);
+}
+
+static void frmnet_disconnect(struct grmnet *gr)
+{
+ struct f_rmnet *dev;
+ unsigned long flags;
+ struct usb_cdc_notification *event;
+ int status;
+ struct rmnet_ctrl_pkt *cpkt;
+
+ if (!gr) {
+ pr_err("%s: Invalid grmnet:%p\n", __func__, gr);
+ return;
+ }
+
+ dev = port_to_rmnet(gr);
+
+ atomic_set(&dev->ctrl_online, 0);
+
+ if (!atomic_read(&dev->online)) {
+ pr_debug("%s: nothing to do\n", __func__);
+ return;
+ }
+
+ usb_ep_fifo_flush(dev->notify);
+
+ event = dev->notify_req->buf;
+ event->bmRequestType = USB_DIR_IN | USB_TYPE_CLASS
+ | USB_RECIP_INTERFACE;
+ event->bNotificationType = USB_CDC_NOTIFY_NETWORK_CONNECTION;
+ event->wValue = cpu_to_le16(0);
+ event->wIndex = cpu_to_le16(dev->ifc_id);
+ event->wLength = cpu_to_le16(0);
+
+ status = usb_ep_queue(dev->notify, dev->notify_req, GFP_KERNEL);
+ if (status < 0) {
+ if (!atomic_read(&dev->online))
+ return;
+ pr_err("%s: rmnet notify ep enqueue error %d\n",
+ __func__, status);
+ }
+
+ spin_lock_irqsave(&dev->lock, flags);
+ while (!list_empty(&dev->cpkt_resp_q)) {
+ cpkt = list_first_entry(&dev->cpkt_resp_q,
+ struct rmnet_ctrl_pkt, list);
+
+ list_del(&cpkt->list);
+ rmnet_free_ctrl_pkt(cpkt);
+ }
+ atomic_set(&dev->notify_count, 0);
+ spin_unlock_irqrestore(&dev->lock, flags);
+
+}
+
static int
frmnet_send_cpkt_response(struct grmnet *gr, struct rmnet_ctrl_pkt *cpkt)
{
@@ -400,7 +481,7 @@
pr_debug("%s: dev:%p port#%d\n", __func__, dev, dev->port_num);
- if (!atomic_read(&dev->online)) {
+ if (!atomic_read(&dev->online) || !atomic_read(&dev->ctrl_online)) {
rmnet_free_ctrl_pkt(cpkt);
return 0;
}
@@ -459,6 +540,9 @@
pr_err("rmnet notify ep error %d\n", status);
/* FALLTHROUGH */
case 0:
+ if (!atomic_read(&dev->ctrl_online))
+ break;
+
if (atomic_dec_and_test(&dev->notify_count))
break;
@@ -706,6 +790,8 @@
f->set_alt = frmnet_set_alt;
f->setup = frmnet_setup;
dev->port.send_cpkt_response = frmnet_send_cpkt_response;
+ dev->port.disconnect = frmnet_disconnect;
+ dev->port.connect = frmnet_connect;
status = usb_add_function(c, f);
if (status) {
diff --git a/drivers/usb/gadget/u_rmnet.h b/drivers/usb/gadget/u_rmnet.h
index aeaddee..3c21316 100644
--- a/drivers/usb/gadget/u_rmnet.h
+++ b/drivers/usb/gadget/u_rmnet.h
@@ -48,6 +48,9 @@
void (*send_cbits_tomodem)(struct grmnet *g,
u8 port_num,
int cbits);
+
+ void (*disconnect)(struct grmnet *g);
+ void (*connect)(struct grmnet *g);
};
int gbam_setup(unsigned int count);
diff --git a/drivers/usb/gadget/u_rmnet_ctrl_smd.c b/drivers/usb/gadget/u_rmnet_ctrl_smd.c
index b4d2828..fc159cc 100644
--- a/drivers/usb/gadget/u_rmnet_ctrl_smd.c
+++ b/drivers/usb/gadget/u_rmnet_ctrl_smd.c
@@ -273,6 +273,8 @@
{
struct rmnet_ctrl_port *port = p;
struct smd_ch_info *c = &port->ctrl_ch;
+ struct rmnet_ctrl_pkt *cpkt;
+ unsigned long flags;
pr_debug("%s: EVENT_(%s)\n", __func__, get_smd_event(event));
@@ -285,10 +287,27 @@
break;
case SMD_EVENT_OPEN:
set_bit(CH_OPENED, &c->flags);
- wake_up(&c->wait);
+
+ if (port && port->port_usb && port->port_usb->connect)
+ port->port_usb->connect(port->port_usb);
+
break;
case SMD_EVENT_CLOSE:
clear_bit(CH_OPENED, &c->flags);
+
+ if (port && port->port_usb && port->port_usb->disconnect)
+ port->port_usb->disconnect(port->port_usb);
+
+ spin_lock_irqsave(&port->port_lock, flags);
+ while (!list_empty(&c->tx_q)) {
+ cpkt = list_first_entry(&c->tx_q,
+ struct rmnet_ctrl_pkt, list);
+
+ list_del(&cpkt->list);
+ free_rmnet_ctrl_pkt(cpkt);
+ }
+ spin_unlock_irqrestore(&port->port_lock, flags);
+
break;
}
}
@@ -357,6 +376,7 @@
struct rmnet_ctrl_port *port;
unsigned long flags;
struct smd_ch_info *c;
+ struct rmnet_ctrl_pkt *cpkt;
pr_debug("%s: grmnet:%p port#%d\n", __func__, gr, port_num);
@@ -378,6 +398,14 @@
gr->send_cpkt_request = 0;
gr->send_cbits_tomodem = 0;
c->cbits_tomodem = 0;
+
+ while (!list_empty(&c->tx_q)) {
+ cpkt = list_first_entry(&c->tx_q, struct rmnet_ctrl_pkt, list);
+
+ list_del(&cpkt->list);
+ free_rmnet_ctrl_pkt(cpkt);
+ }
+
spin_unlock_irqrestore(&port->port_lock, flags);
if (test_bit(CH_OPENED, &c->flags)) {
diff --git a/drivers/usb/otg/msm_otg.c b/drivers/usb/otg/msm_otg.c
index 3c130e9..4658469 100644
--- a/drivers/usb/otg/msm_otg.c
+++ b/drivers/usb/otg/msm_otg.c
@@ -2144,7 +2144,6 @@
static int msm_otg_pm_resume(struct device *dev)
{
struct msm_otg *motg = dev_get_drvdata(dev);
- int ret = 0;
dev_dbg(dev, "OTG PM resume\n");
@@ -2153,7 +2152,7 @@
* Do not resume hardware as part of system resume,
* rather, wait for the ASYNC INT from the h/w
*/
- return ret;
+ return 0;
#endif
return msm_otg_resume(motg);
diff --git a/drivers/video/msm/hdmi_msm.c b/drivers/video/msm/hdmi_msm.c
index fe3c614..7eca334 100644
--- a/drivers/video/msm/hdmi_msm.c
+++ b/drivers/video/msm/hdmi_msm.c
@@ -276,17 +276,18 @@
} else {
hdmi_msm_state->hpd_cable_chg_detected = FALSE;
mutex_unlock(&hdmi_msm_state_mutex);
+ /* QDSP OFF preceding the HPD event notification */
+ envp[0] = "HDCP_STATE=FAIL";
+ envp[1] = NULL;
+ DEV_INFO("HDMI HPD: QDSP OFF\n");
+ kobject_uevent_env(external_common_state->uevent_kobj,
+ KOBJ_CHANGE, envp);
if (hpd_state) {
hdmi_msm_read_edid();
#ifdef CONFIG_FB_MSM_HDMI_MSM_PANEL_HDCP_SUPPORT
hdmi_msm_state->reauth = FALSE ;
#endif
/* Build EDID table */
- envp[0] = "HDCP_STATE=FAIL";
- envp[1] = NULL;
- DEV_INFO("HDMI HPD: QDSP OFF\n");
- kobject_uevent_env(external_common_state->uevent_kobj,
- KOBJ_CHANGE, envp);
hdmi_msm_turn_on();
DEV_INFO("HDMI HPD: sense CONNECTED: send ONLINE\n");
kobject_uevent(external_common_state->uevent_kobj,
@@ -3351,7 +3352,7 @@
hdmi_msm_hpd_off();
hdmi_msm_powerdown_phy();
hdmi_msm_dump_regs("HDMI-OFF: ");
- hdmi_msm_hpd_on(false);
+ hdmi_msm_hpd_on(true);
mutex_lock(&external_common_state_hpd_mutex);
if (!external_common_state->hpd_feature_on)
diff --git a/drivers/video/msm/mdp.c b/drivers/video/msm/mdp.c
index 37c9ca8..c522b0f 100644
--- a/drivers/video/msm/mdp.c
+++ b/drivers/video/msm/mdp.c
@@ -541,7 +541,7 @@
#ifdef CONFIG_FB_MSM_MDP303
#ifdef CONFIG_FB_MSM_MIPI_DSI
- mipi_dsi_cmd_mdp_sw_trigger();
+ mipi_dsi_cmd_mdp_start();
#endif
#endif
diff --git a/drivers/video/msm/mdp4_overlay.c b/drivers/video/msm/mdp4_overlay.c
index ecefdc3..f8cadbb 100644
--- a/drivers/video/msm/mdp4_overlay.c
+++ b/drivers/video/msm/mdp4_overlay.c
@@ -453,7 +453,8 @@
*luma_off = 0;
*chroma_off = 0;
- if (pipe->src_x) {
+ if (pipe->src_x && (pipe->frame_format ==
+ MDP4_FRAME_FORMAT_LINEAR)) {
src_xy = (pipe->src_y << 16) | pipe->src_x;
src_xy &= 0xffff0000;
outpdw(vg_base + 0x0004, src_xy); /* MDP_RGB_SRC_XY */
@@ -540,7 +541,7 @@
outpdw(vg_base + 0x0008, dst_size); /* MDP_RGB_DST_SIZE */
outpdw(vg_base + 0x000c, dst_xy); /* MDP_RGB_DST_XY */
- if (pipe->frame_format)
+ if (pipe->frame_format != MDP4_FRAME_FORMAT_LINEAR)
outpdw(vg_base + 0x0048, frame_size); /* TILE frame size */
/*
diff --git a/drivers/video/msm/mdp4_overlay_dsi_cmd.c b/drivers/video/msm/mdp4_overlay_dsi_cmd.c
index 4cd69ef..0020fd5 100644
--- a/drivers/video/msm/mdp4_overlay_dsi_cmd.c
+++ b/drivers/video/msm/mdp4_overlay_dsi_cmd.c
@@ -171,8 +171,8 @@
* dma_p = 0, dma_s = 1
*/
MDP_OUTP(MDP_BASE + 0x000a0, 0x10);
- /* enable dsi trigger on dma_p */
- MDP_OUTP(MDP_BASE + 0x000a4, 0x01);
+ /* disable dsi trigger */
+ MDP_OUTP(MDP_BASE + 0x000a4, 0x00);
/* whole screen for base layer */
src = (uint8 *) iBuf->buf;
@@ -461,7 +461,7 @@
/* kick off dmap */
outpdw(MDP_BASE + 0x000c, 0x0);
/* trigger dsi cmd engine */
- mipi_dsi_cmd_mdp_sw_trigger();
+ mipi_dsi_cmd_mdp_start();
mdp_pipe_ctrl(MDP_OVERLAY0_BLOCK, MDP_BLOCK_POWER_OFF, TRUE);
}
@@ -521,7 +521,7 @@
/* kick off dmap */
outpdw(MDP_BASE + 0x000c, 0x0);
/* trigger dsi cmd engine */
- mipi_dsi_cmd_mdp_sw_trigger();
+ mipi_dsi_cmd_mdp_start();
mdp_disable_irq_nosync(MDP_OVERLAY0_TERM);
}
@@ -638,6 +638,11 @@
/* change mdp clk */
mdp4_set_perf_level();
+ mipi_dsi_mdp_busy_wait(mfd);
+
+ if (dsi_pipe->blt_addr == 0)
+ mipi_dsi_cmd_mdp_start();
+
mdp4_overlay_dsi_state_set(ST_DSI_PLAYING);
spin_lock_irqsave(&mdp_spin_lock, flag);
@@ -648,11 +653,6 @@
/* start OVERLAY pipe */
spin_unlock_irqrestore(&mdp_spin_lock, flag);
mdp_pipe_kickoff(MDP_OVERLAY0_TERM, mfd);
-
- if (dsi_pipe->blt_addr == 0) {
- /* trigger dsi cmd engine */
- mipi_dsi_cmd_mdp_sw_trigger();
- }
}
void mdp4_dsi_cmd_overlay(struct msm_fb_data_type *mfd)
diff --git a/drivers/video/msm/mipi_dsi.c b/drivers/video/msm/mipi_dsi.c
index c18f2a0..00256e6 100644
--- a/drivers/video/msm/mipi_dsi.c
+++ b/drivers/video/msm/mipi_dsi.c
@@ -87,6 +87,7 @@
if (mdp_rev >= MDP_REV_41) {
mdp4_dsi_cmd_dma_busy_wait(mfd);
mdp4_dsi_blt_dmap_busy_wait(mfd);
+ mipi_dsi_mdp_busy_wait(mfd);
} else {
mdp3_dsi_cmd_dma_busy_wait(mfd);
}
diff --git a/drivers/video/msm/mipi_dsi.h b/drivers/video/msm/mipi_dsi.h
index 14d6bd9..9907109 100644
--- a/drivers/video/msm/mipi_dsi.h
+++ b/drivers/video/msm/mipi_dsi.h
@@ -222,6 +222,17 @@
#define DTYPE_PERIPHERAL_OFF 0x22
#define DTYPE_PERIPHERAL_ON 0x32
+/*
+ * dcs response
+ */
+#define DTYPE_ACK_ERR_RESP 0x02
+#define DTYPE_EOT_RESP 0x08 /* end of tx */
+#define DTYPE_GEN_READ1_RESP 0x11 /* 1 parameter, short */
+#define DTYPE_GEN_READ2_RESP 0x12 /* 2 parameter, short */
+#define DTYPE_GEN_LREAD_RESP 0x1a
+#define DTYPE_DCS_LREAD_RESP 0x1c
+#define DTYPE_DCS_READ1_RESP 0x21 /* 1 parameter, short */
+#define DTYPE_DCS_READ2_RESP 0x22 /* 2 parameter, short */
struct dsi_cmd_desc {
int dtype;
@@ -261,7 +272,7 @@
void mipi_dsi_op_mode_config(int mode);
void mipi_dsi_cmd_mode_ctrl(int enable);
void mdp4_dsi_cmd_trigger(void);
-void mipi_dsi_cmd_mdp_sw_trigger(void);
+void mipi_dsi_cmd_mdp_start(void);
void mipi_dsi_cmd_bta_sw_trigger(void);
void mipi_dsi_ack_err_status(void);
void mipi_dsi_set_tear_on(struct msm_fb_data_type *mfd);
@@ -276,6 +287,7 @@
void mipi_dsi_post_kickoff_del(struct dsi_kickoff_action *act);
void mipi_dsi_controller_cfg(int enable);
void mipi_dsi_sw_reset(void);
+void mipi_dsi_mdp_busy_wait(struct msm_fb_data_type *mfd);
irqreturn_t mipi_dsi_isr(int irq, void *ptr);
diff --git a/drivers/video/msm/mipi_dsi_host.c b/drivers/video/msm/mipi_dsi_host.c
index 0697aac..9caa154 100644
--- a/drivers/video/msm/mipi_dsi_host.c
+++ b/drivers/video/msm/mipi_dsi_host.c
@@ -41,10 +41,12 @@
int mipi_dsi_clk_on;
static struct completion dsi_dma_comp;
+static struct completion dsi_mdp_comp;
static struct dsi_buf dsi_tx_buf;
static int dsi_irq_enabled;
-static int dsi_cmd_trigger;
-static spinlock_t dsi_lock;
+static spinlock_t dsi_irq_lock;
+static spinlock_t dsi_mdp_lock;
+static int dsi_mdp_busy;
static struct list_head pre_kickoff_list;
static struct list_head post_kickoff_list;
@@ -52,54 +54,44 @@
void mipi_dsi_init(void)
{
init_completion(&dsi_dma_comp);
+ init_completion(&dsi_mdp_comp);
mipi_dsi_buf_alloc(&dsi_tx_buf, DSI_BUF_SIZE);
- spin_lock_init(&dsi_lock);
+ spin_lock_init(&dsi_irq_lock);
+ spin_lock_init(&dsi_mdp_lock);
INIT_LIST_HEAD(&pre_kickoff_list);
INIT_LIST_HEAD(&post_kickoff_list);
}
-void mipi_dsi_enable_irq(enum dsi_trigger_type type)
+void mipi_dsi_enable_irq(void)
{
unsigned long flags;
- spin_lock_irqsave(&dsi_lock, flags);
- if (type == DSI_CMD_MODE_DMA)
- dsi_cmd_trigger = 1;
-
- pr_debug("%s(): dsi_irq_enabled %u, dsi_cmd_trigger %u\n",
- __func__, dsi_irq_enabled, dsi_cmd_trigger);
-
+ spin_lock_irqsave(&dsi_irq_lock, flags);
if (dsi_irq_enabled) {
pr_debug("%s: IRQ aleady enabled\n", __func__);
- spin_unlock_irqrestore(&dsi_lock, flags);
+ spin_unlock_irqrestore(&dsi_irq_lock, flags);
return;
}
dsi_irq_enabled = 1;
enable_irq(dsi_irq);
- spin_unlock_irqrestore(&dsi_lock, flags);
+ spin_unlock_irqrestore(&dsi_irq_lock, flags);
}
-void mipi_dsi_disable_irq(enum dsi_trigger_type type)
+void mipi_dsi_disable_irq(void)
{
unsigned long flags;
- spin_lock_irqsave(&dsi_lock, flags);
- if (type == DSI_CMD_MODE_DMA)
- dsi_cmd_trigger = 0;
-
- pr_debug("%s(): dsi_irq_enabled %u, dsi_cmd_trigger %u\n",
- __func__, dsi_irq_enabled, dsi_cmd_trigger);
-
+ spin_lock_irqsave(&dsi_irq_lock, flags);
if (dsi_irq_enabled == 0) {
pr_debug("%s: IRQ already disabled\n", __func__);
- spin_unlock_irqrestore(&dsi_lock, flags);
+ spin_unlock_irqrestore(&dsi_irq_lock, flags);
return;
}
dsi_irq_enabled = 0;
disable_irq(dsi_irq);
- spin_unlock_irqrestore(&dsi_lock, flags);
+ spin_unlock_irqrestore(&dsi_irq_lock, flags);
}
/*
@@ -108,19 +100,16 @@
*/
void mipi_dsi_disable_irq_nosync(void)
{
- spin_lock(&dsi_lock);
- pr_debug("%s(): dsi_irq_enabled %u, dsi_cmd_trigger %u\n",
- __func__, dsi_irq_enabled, dsi_cmd_trigger);
-
- if (dsi_irq_enabled == 0 || dsi_cmd_trigger == 1) {
+ spin_lock(&dsi_irq_lock);
+ if (dsi_irq_enabled == 0) {
pr_debug("%s: IRQ cannot be disabled\n", __func__);
- spin_unlock(&dsi_lock);
+ spin_unlock(&dsi_irq_lock);
return;
}
dsi_irq_enabled = 0;
disable_irq_nosync(dsi_irq);
- spin_unlock(&dsi_lock);
+ spin_unlock(&dsi_irq_lock);
}
void mipi_dsi_turn_on_clks(void)
@@ -728,6 +717,43 @@
return len;
}
+/*
+ * mipi_dsi_short_read1_resp: 1 parameter
+ */
+static int mipi_dsi_short_read1_resp(struct dsi_buf *rp)
+{
+ /* strip out dcs type */
+ rp->data++;
+ rp->len = 1;
+ return rp->len;
+}
+
+/*
+ * mipi_dsi_short_read2_resp: 2 parameter
+ */
+static int mipi_dsi_short_read2_resp(struct dsi_buf *rp)
+{
+ /* strip out dcs type */
+ rp->data++;
+ rp->len = 2;
+ return rp->len;
+}
+
+static int mipi_dsi_long_read_resp(struct dsi_buf *rp)
+{
+ short len;
+
+ len = rp->data[2];
+ len <<= 8;
+ len |= rp->data[1];
+ /* strip out dcs header */
+ rp->data += 4;
+ rp->len -= 4;
+ /* strip out 2 bytes of checksum */
+ rp->len -= 2;
+ return len;
+}
+
void mipi_dsi_host_init(struct mipi_panel_info *pinfo)
{
uint32 dsi_ctrl, intr_ctrl;
@@ -936,12 +962,42 @@
wmb();
}
-void mipi_dsi_cmd_mdp_sw_trigger(void)
+void mipi_dsi_mdp_busy_wait(struct msm_fb_data_type *mfd)
{
- mipi_dsi_pre_kickoff_action();
- mipi_dsi_enable_irq(DSI_CMD_MODE_MDP);
- MIPI_OUTP(MIPI_DSI_BASE + 0x090, 0x01); /* trigger */
- wmb();
+ unsigned long flag;
+ int need_wait = 0;
+
+ pr_debug("%s: start pid=%d\n",
+ __func__, current->pid);
+ spin_lock_irqsave(&dsi_mdp_lock, flag);
+ if (dsi_mdp_busy == TRUE) {
+ INIT_COMPLETION(dsi_mdp_comp);
+ need_wait++;
+ }
+ spin_unlock_irqrestore(&dsi_mdp_lock, flag);
+
+ if (need_wait) {
+ /* wait until DMA finishes the current job */
+ pr_debug("%s: pending pid=%d\n",
+ __func__, current->pid);
+ wait_for_completion(&dsi_mdp_comp);
+ }
+ pr_debug("%s: done pid=%d\n",
+ __func__, current->pid);
+}
+
+void mipi_dsi_cmd_mdp_start(void)
+{
+ unsigned long flag;
+
+
+ if (!in_interrupt())
+ mipi_dsi_pre_kickoff_action();
+
+ spin_lock_irqsave(&dsi_mdp_lock, flag);
+ mipi_dsi_enable_irq();
+ dsi_mdp_busy = TRUE;
+ spin_unlock_irqrestore(&dsi_mdp_lock, flag);
}
@@ -1024,6 +1080,7 @@
struct dsi_cmd_desc *cm;
uint32 dsi_ctrl, ctrl;
int i, video_mode;
+ unsigned long flag;
/* turn on cmd mode
* for video mode, do not send cmds more than
@@ -1050,7 +1107,11 @@
}
}
- mipi_dsi_enable_irq(DSI_CMD_MODE_DMA);
+ spin_lock_irqsave(&dsi_mdp_lock, flag);
+ mipi_dsi_enable_irq();
+ dsi_mdp_busy = TRUE;
+ spin_unlock_irqrestore(&dsi_mdp_lock, flag);
+
cm = cmds;
mipi_dsi_buf_init(tp);
for (i = 0; i < cnt; i++) {
@@ -1061,7 +1122,12 @@
msleep(cm->wait);
cm++;
}
- mipi_dsi_disable_irq(DSI_CMD_MODE_DMA);
+
+ spin_lock_irqsave(&dsi_mdp_lock, flag);
+ dsi_mdp_busy = FALSE;
+ mipi_dsi_disable_irq();
+ complete(&dsi_mdp_comp);
+ spin_unlock_irqrestore(&dsi_mdp_lock, flag);
if (video_mode)
MIPI_OUTP(MIPI_DSI_BASE + 0x0000, dsi_ctrl); /* restore */
@@ -1091,10 +1157,14 @@
*/
int mipi_dsi_cmds_rx(struct msm_fb_data_type *mfd,
struct dsi_buf *tp, struct dsi_buf *rp,
- struct dsi_cmd_desc *cmds, int len)
+ struct dsi_cmd_desc *cmds, int rlen)
{
- int cnt;
- static int pkt_size;
+ int cnt, len, diff, pkt_size;
+ unsigned long flag;
+ char cmd;
+
+ len = rlen;
+ diff = 0;
if (len <= 2)
cnt = 4; /* short read */
@@ -1108,6 +1178,7 @@
len = MIPI_DSI_LEN; /* 8 bytes at most */
len = (len + 3) & ~0x03; /* len 4 bytes align */
+ diff = len - rlen;
/*
* add extra 2 bytes to len to have overall
* packet size is multipe by 4. This also make
@@ -1128,16 +1199,17 @@
#endif
}
- mipi_dsi_enable_irq(DSI_CMD_MODE_DMA);
- if (pkt_size != len) {
- /* set new max pkt size */
- pkt_size = len;
- max_pktsize[0] = pkt_size;
+ spin_lock_irqsave(&dsi_mdp_lock, flag);
+ mipi_dsi_enable_irq();
+ dsi_mdp_busy = TRUE;
+ spin_unlock_irqrestore(&dsi_mdp_lock, flag);
- mipi_dsi_buf_init(tp);
- mipi_dsi_cmd_dma_add(tp, pkt_size_cmd);
- mipi_dsi_cmd_dma_tx(tp);
- }
+ /* packet size need to be set at every read */
+ pkt_size = len;
+ max_pktsize[0] = pkt_size;
+ mipi_dsi_buf_init(tp);
+ mipi_dsi_cmd_dma_add(tp, pkt_size_cmd);
+ mipi_dsi_cmd_dma_tx(tp);
mipi_dsi_buf_init(tp);
mipi_dsi_cmd_dma_add(tp, cmds);
@@ -1149,21 +1221,36 @@
* return data from client is ready and stored
* at RDBK_DATA register already
*/
+ mipi_dsi_buf_init(rp);
mipi_dsi_cmd_dma_rx(rp, cnt);
- mipi_dsi_disable_irq(DSI_CMD_MODE_DMA);
+ spin_lock_irqsave(&dsi_mdp_lock, flag);
+ dsi_mdp_busy = FALSE;
+ mipi_dsi_disable_irq();
+ complete(&dsi_mdp_comp);
+ spin_unlock_irqrestore(&dsi_mdp_lock, flag);
- /* strip off dcs header & crc */
- if (cnt > 4) { /* long response */
- if (mfd->panel_info.mipi.fixed_packet_size)
- rp->data += (cnt - len - 6); /* skip padding */
-
- rp->data += 4; /* skip dcs header */
- rp->len -= 6; /* deduct 4 bytes header + 2 bytes crc */
+ cmd = rp->data[0];
+ switch (cmd) {
+ case DTYPE_ACK_ERR_RESP:
+ pr_debug("%s: rx ACK_ERR_PACLAGE\n", __func__);
+ break;
+ case DTYPE_GEN_READ1_RESP:
+ case DTYPE_DCS_READ1_RESP:
+ mipi_dsi_short_read1_resp(rp);
+ break;
+ case DTYPE_GEN_READ2_RESP:
+ case DTYPE_DCS_READ2_RESP:
+ mipi_dsi_short_read2_resp(rp);
+ break;
+ case DTYPE_GEN_LREAD_RESP:
+ case DTYPE_DCS_LREAD_RESP:
+ mipi_dsi_long_read_resp(rp);
rp->len -= 2; /* extra 2 bytes added */
- } else {
- rp->data += 1; /* skip dcs short header */
- rp->len -= 2; /* deduct 1 byte header + 1 byte ecc */
+ rp->len -= diff; /* align bytes */
+ break;
+ default:
+ break;
}
return rp->len;
@@ -1343,6 +1430,10 @@
}
if (isr & DSI_INTR_CMD_MDP_DONE) {
+ spin_lock(&dsi_mdp_lock);
+ dsi_mdp_busy = FALSE;
+ spin_unlock(&dsi_mdp_lock);
+ complete(&dsi_mdp_comp);
mipi_dsi_disable_irq_nosync();
mipi_dsi_post_kickoff_action();
}
diff --git a/drivers/video/msm/mipi_novatek.c b/drivers/video/msm/mipi_novatek.c
index c6fdeff..1ff950d 100644
--- a/drivers/video/msm/mipi_novatek.c
+++ b/drivers/video/msm/mipi_novatek.c
@@ -312,9 +312,6 @@
tp = &novatek_tx_buf;
rp = &novatek_rx_buf;
- mipi_dsi_buf_init(rp);
- mipi_dsi_buf_init(tp);
-
cmd = &novatek_manufacture_id_cmd;
mipi_dsi_cmds_rx(mfd, tp, rp, cmd, 3);
lp = (uint32 *)rp->data;
@@ -445,6 +442,7 @@
/* 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);
+ mipi_dsi_mdp_busy_wait(mfd);
led_pwm1[1] = (unsigned char)(mfd->bl_level);
mipi_dsi_cmds_tx(mfd, &novatek_tx_buf, novatek_cmd_backlight_cmds,
diff --git a/drivers/video/msm/mipi_novatek_cmd_qhd_pt.c b/drivers/video/msm/mipi_novatek_cmd_qhd_pt.c
index 19c91f4..fbd2495 100644
--- a/drivers/video/msm/mipi_novatek_cmd_qhd_pt.c
+++ b/drivers/video/msm/mipi_novatek_cmd_qhd_pt.c
@@ -79,7 +79,7 @@
pinfo.mipi.t_clk_post = 0x22;
pinfo.mipi.t_clk_pre = 0x3f;
pinfo.mipi.stream = 0; /* dma_p */
- pinfo.mipi.mdp_trigger = DSI_CMD_TRIGGER_SW;
+ pinfo.mipi.mdp_trigger = DSI_CMD_TRIGGER_NONE;
pinfo.mipi.dma_trigger = DSI_CMD_TRIGGER_SW;
pinfo.mipi.te_sel = 1; /* TE from vsycn gpio */
pinfo.mipi.interleave_max = 1;
diff --git a/drivers/video/msm/vidc/1080p/resource_tracker/vcd_res_tracker.c b/drivers/video/msm/vidc/1080p/resource_tracker/vcd_res_tracker.c
index 501a4592..8f745ec 100644
--- a/drivers/video/msm/vidc/1080p/resource_tracker/vcd_res_tracker.c
+++ b/drivers/video/msm/vidc/1080p/resource_tracker/vcd_res_tracker.c
@@ -47,16 +47,16 @@
goto bail_out;
}
resource_context.vcodec_clk = clk_get(resource_context.device,
- "vcodec_clk");
+ "core_clk");
if (IS_ERR(resource_context.vcodec_clk)) {
- VCDRES_MSG_ERROR("%s(): vcodec_clk get failed\n",
+ VCDRES_MSG_ERROR("%s(): core_clk get failed\n",
__func__);
goto bail_out;
}
resource_context.vcodec_pclk = clk_get(resource_context.device,
- "vcodec_pclk");
+ "iface_clk");
if (IS_ERR(resource_context.vcodec_pclk)) {
- VCDRES_MSG_ERROR("%s(): vcodec_pclk get failed\n",
+ VCDRES_MSG_ERROR("%s(): iface_clk get failed\n",
__func__);
goto release_vcodec_clk;
}
diff --git a/drivers/video/msm/vidc/720p/resource_tracker/vcd_res_tracker.c b/drivers/video/msm/vidc/720p/resource_tracker/vcd_res_tracker.c
index fe3bfaa..54d48b8 100644
--- a/drivers/video/msm/vidc/720p/resource_tracker/vcd_res_tracker.c
+++ b/drivers/video/msm/vidc/720p/resource_tracker/vcd_res_tracker.c
@@ -277,29 +277,29 @@
__func__, rc);
resource_context.pclk = clk_get(resource_context.device,
- "mfc_pclk");
+ "iface_clk");
if (IS_ERR(resource_context.pclk)) {
- VCDRES_MSG_ERROR("%s(): mfc_pclk get failed\n"
+ VCDRES_MSG_ERROR("%s(): iface_clk get failed\n"
, __func__);
goto disable_regulator;
}
resource_context.hclk = clk_get(resource_context.device,
- "mfc_clk");
+ "core_clk");
if (IS_ERR(resource_context.hclk)) {
- VCDRES_MSG_ERROR("%s(): mfc_clk get failed\n"
+ VCDRES_MSG_ERROR("%s(): core_clk get failed\n"
, __func__);
goto release_pclk;
}
resource_context.hclk_div2 =
- clk_get(resource_context.device, "mfc_div2_clk");
+ clk_get(resource_context.device, "core_div2_clk");
if (IS_ERR(resource_context.hclk_div2)) {
- VCDRES_MSG_ERROR("%s(): mfc_div2_clk get failed\n"
+ VCDRES_MSG_ERROR("%s(): core_div2_clk get failed\n"
, __func__);
goto release_hclk_pclk;
}
@@ -407,7 +407,7 @@
{
VCDRES_MSG_MED("\n res_trk_power_up():: "
"Calling AXI add requirement\n");
- ebi1_clk = clk_get(NULL, "ebi1_vcd_clk");
+ ebi1_clk = clk_get(NULL, "mem_clk");
if (IS_ERR(ebi1_clk)) {
VCDRES_MSG_ERROR("Request AXI bus QOS fails.");
return false;
diff --git a/include/linux/msm_kgsl.h b/include/linux/msm_kgsl.h
index ae26f27..b55cfe1 100644
--- a/include/linux/msm_kgsl.h
+++ b/include/linux/msm_kgsl.h
@@ -27,6 +27,9 @@
#define KGSL_MAX_PWRLEVELS 5
+#define KGSL_CONVERT_TO_MBPS(val) \
+ (val*1000*1000U)
+
/* device id */
enum kgsl_deviceid {
KGSL_DEVICE_3D0 = 0x00000000,
diff --git a/include/linux/msm_mdp.h b/include/linux/msm_mdp.h
index 26994fc..144caa0 100644
--- a/include/linux/msm_mdp.h
+++ b/include/linux/msm_mdp.h
@@ -79,6 +79,7 @@
MDP_Y_CRCB_H2V2_TILE, /* Y and CrCb, pseudo planer tile */
MDP_Y_CBCR_H2V2_TILE, /* Y and CbCr, pseudo planer tile */
MDP_Y_CR_CB_H2V2, /* Y, Cr and Cb, planar */
+ MDP_Y_CR_CB_GH2V2, /* Y, Cr and Cb, planar aligned to Android YV12 */
MDP_Y_CB_CR_H2V2, /* Y, Cb and Cr, planar */
MDP_Y_CRCB_H1V1, /* Y and CrCb, pseduo planer w/ Cr is in MSB */
MDP_Y_CBCR_H1V1, /* Y and CbCr, pseduo planer w/ Cb is in MSB */
diff --git a/include/media/msm_camera.h b/include/media/msm_camera.h
index 3c47a92..4c9b53e 100644
--- a/include/media/msm_camera.h
+++ b/include/media/msm_camera.h
@@ -239,11 +239,26 @@
uint32_t vb;
};
-struct msm_isp_stats_event_ctrl {
+struct msm_mctl_pp_cmd_ack_event {
+ uint32_t cmd; /* VPE_CMD_ZOOM? */
+ int status; /* 0 done, < 0 err */
+ uint32_t cookie; /* daemon's cookie */
+};
+
+struct msm_mctl_pp_event_info {
+ int32_t event;
+ union {
+ struct msm_mctl_pp_cmd_ack_event ack;
+ };
+};
+
+struct msm_isp_event_ctrl {
unsigned short resptype;
union {
struct msm_cam_evt_msg isp_msg;
struct msm_ctrl_cmd ctrl;
+ struct msm_cam_evt_divert_frame div_frame;
+ struct msm_mctl_pp_event_info pp_event_info;
} isp_data;
};
diff --git a/include/media/msm_isp.h b/include/media/msm_isp.h
index fd46692..f6668ef 100644
--- a/include/media/msm_isp.h
+++ b/include/media/msm_isp.h
@@ -156,7 +156,7 @@
#define VFE_CMD_DEMOSAICV3_DBCC_UPDATE 110
#define VFE_CMD_DEMOSAICV3_DBPC_UPDATE 111
#define VFE_CMD_XBAR_CFG 112
-#define VFE_CMD_EZTUNE_CFG 113
+#define VFE_CMD_MODULE_CFG 113
#define VFE_CMD_ZSL 114
#define VFE_CMD_LINEARIZATION_UPDATE 115
#define VFE_CMD_DEMOSAICV3_ABF_UPDATE 116
@@ -273,12 +273,6 @@
/* TBD: 3D related */
};
-struct msm_mctl_pp_cmd_ack_event {
- uint32_t cmd; /* VPE_CMD_ZOOM? */
- int status; /* 0 done, < 0 err */
- uint32_t cookie; /* daemon's cookie */
-};
-
struct msm_pp_frame_sp {
unsigned long phy_addr;
uint32_t y_off;
@@ -307,13 +301,5 @@
};
};
-struct msm_mctl_pp_event_info {
- int32_t event;
- union {
- struct msm_mctl_pp_cmd_ack_event ack;
- };
-};
-
-
#endif /*__MSM_ISP_H__*/
diff --git a/kernel/power/wakelock.c b/kernel/power/wakelock.c
index 9f77f61..e9f49b5 100644
--- a/kernel/power/wakelock.c
+++ b/kernel/power/wakelock.c
@@ -386,7 +386,8 @@
if (debug_mask & DEBUG_SUSPEND)
pr_info("power_suspend_late return %d\n", ret);
- msm_suspend_check_done = 1;
+ if (ret == 0)
+ msm_suspend_check_done = 1;
return ret;
}
diff --git a/kernel/printk.c b/kernel/printk.c
index ccdfac7..bddd32b 100644
--- a/kernel/printk.c
+++ b/kernel/printk.c
@@ -53,10 +53,6 @@
#define __LOG_BUF_LEN (1 << CONFIG_LOG_BUF_SHIFT)
-#ifdef CONFIG_DEBUG_LL
-extern void printascii(char *);
-#endif
-
/* printk's without a loglevel use this.. */
#define DEFAULT_MESSAGE_LOGLEVEL CONFIG_DEFAULT_MESSAGE_LOGLEVEL
@@ -928,9 +924,6 @@
printed_len += vscnprintf(printk_buf + printed_len,
sizeof(printk_buf) - printed_len, fmt, args);
-#ifdef CONFIG_DEBUG_LL
- printascii(printk_buf);
-#endif
p = printk_buf;
diff --git a/net/bluetooth/l2cap_core.c b/net/bluetooth/l2cap_core.c
index d103bef6..dea21c1 100644
--- a/net/bluetooth/l2cap_core.c
+++ b/net/bluetooth/l2cap_core.c
@@ -909,6 +909,37 @@
}
}
+/* Find socket with fixed cid with given source and destination bdaddrs.
+ * Returns closest match, locked.
+ */
+static struct sock *l2cap_get_sock_by_fixed_scid(int state,
+ __le16 cid, bdaddr_t *src, bdaddr_t *dst)
+{
+ struct sock *sk = NULL, *sk1 = NULL;
+ struct hlist_node *node;
+
+ read_lock(&l2cap_sk_list.lock);
+
+ sk_for_each(sk, node, &l2cap_sk_list.head) {
+ if (state && sk->sk_state != state)
+ continue;
+
+ if (l2cap_pi(sk)->scid == cid && !bacmp(&bt_sk(sk)->dst, dst)) {
+ /* Exact match. */
+ if (!bacmp(&bt_sk(sk)->src, src))
+ break;
+
+ /* Closest match */
+ if (!bacmp(&bt_sk(sk)->src, BDADDR_ANY))
+ sk1 = sk;
+ }
+ }
+
+ read_unlock(&l2cap_sk_list.lock);
+
+ return node ? sk : sk1;
+}
+
/* Find socket with cid and source bdaddr.
* Returns closest match, locked.
*/
@@ -7051,7 +7082,7 @@
{
struct sock *sk;
- sk = l2cap_get_sock_by_scid(0, cid, conn->src);
+ sk = l2cap_get_sock_by_fixed_scid(0, cid, conn->src, conn->dst);
if (!sk)
goto drop;
diff --git a/net/bluetooth/smp.c b/net/bluetooth/smp.c
index a6e2aab..6838fd5 100644
--- a/net/bluetooth/smp.c
+++ b/net/bluetooth/smp.c
@@ -438,6 +438,7 @@
smp_send_cmd(conn, SMP_CMD_PAIRING_FAIL, sizeof(reason),
&reason);
del_timer(&hcon->smp_timer);
+ clear_bit(HCI_CONN_ENCRYPT_PEND, &hcon->pend);
mgmt_auth_failed(hcon->hdev->id, conn->dst, reason);
hci_conn_put(hcon);
} else if (hcon->cfm_pending) {
@@ -686,6 +687,8 @@
set_bit(HCI_CONN_ENCRYPT_PEND, &hcon->pend);
+ hci_conn_hold(hcon);
+
return 0;
}
@@ -846,6 +849,7 @@
reason = 0;
err = -EPERM;
del_timer(&hcon->smp_timer);
+ clear_bit(HCI_CONN_ENCRYPT_PEND, &hcon->pend);
mgmt_auth_failed(hcon->hdev->id, conn->dst, skb->data[1]);
hci_conn_put(hcon);
break;
@@ -895,6 +899,7 @@
smp_send_cmd(conn, SMP_CMD_PAIRING_FAIL, sizeof(reason),
&reason);
del_timer(&hcon->smp_timer);
+ clear_bit(HCI_CONN_ENCRYPT_PEND, &hcon->pend);
mgmt_auth_failed(hcon->hdev->id, conn->dst, reason);
hci_conn_put(hcon);
}
@@ -989,6 +994,7 @@
hcon->disconn_cfm_cb(hcon, 0);
del_timer(&hcon->smp_timer);
+ clear_bit(HCI_CONN_ENCRYPT_PEND, &hcon->pend);
mgmt_auth_failed(hcon->hdev->id, conn->dst, SMP_UNSPECIFIED);
hci_conn_put(hcon);
}
@@ -1002,6 +1008,8 @@
BT_DBG("smp: %d %d %d", status, encrypt, hcon->sec_req);
+ clear_bit(HCI_CONN_ENCRYPT_PEND, &hcon->pend);
+
if (!status && encrypt && !hcon->sec_req)
smp_distribute_keys(conn, 0);
@@ -1009,6 +1017,9 @@
else if (hcon->sec_req && (status || !encrypt))
smp_conn_security(conn, hcon->sec_level);
+ else
+ hci_conn_put(hcon);
+
return 0;
}
@@ -1020,6 +1031,7 @@
BT_DBG("%p", conn);
smp_send_cmd(conn, SMP_CMD_PAIRING_FAIL, sizeof(reason), &reason);
+ clear_bit(HCI_CONN_ENCRYPT_PEND, &conn->hcon->pend);
mgmt_auth_failed(conn->hcon->hdev->id, conn->dst, SMP_UNSPECIFIED);
hci_conn_put(conn->hcon);
}
diff --git a/sound/soc/codecs/wcd9310-tables.c b/sound/soc/codecs/wcd9310-tables.c
index 98a5139..a97a981 100644
--- a/sound/soc/codecs/wcd9310-tables.c
+++ b/sound/soc/codecs/wcd9310-tables.c
@@ -319,6 +319,18 @@
[TABLA_A_CDC_TX8_DMIC_CTL] = 1,
[TABLA_A_CDC_TX9_DMIC_CTL] = 1,
[TABLA_A_CDC_TX10_DMIC_CTL] = 1,
+ [TABLA_A_CDC_ANC2_CTL] = 1,
+ [TABLA_A_CDC_ANC2_SHIFT] = 1,
+ [TABLA_A_CDC_ANC2_FILT1_B1_CTL] = 1,
+ [TABLA_A_CDC_ANC2_FILT1_B2_CTL] = 1,
+ [TABLA_A_CDC_ANC2_FILT1_B3_CTL] = 1,
+ [TABLA_A_CDC_ANC2_FILT1_B4_CTL] = 1,
+ [TABLA_A_CDC_ANC2_FILT2_B1_CTL] = 1,
+ [TABLA_A_CDC_ANC2_FILT2_B2_CTL] = 1,
+ [TABLA_A_CDC_ANC2_FILT2_B3_CTL] = 1,
+ [TABLA_A_CDC_ANC2_SPARE] = 1,
+ [TABLA_A_CDC_ANC2_FILT3_CTL] = 1,
+ [TABLA_A_CDC_ANC2_FILT4_CTL] = 1,
[TABLA_A_CDC_SRC1_PDA_CFG] = 1,
[TABLA_A_CDC_SRC2_PDA_CFG] = 1,
[TABLA_A_CDC_SRC1_FS_CTL] = 1,
diff --git a/sound/soc/msm/msm8960.c b/sound/soc/msm/msm8960.c
index fd00253..548b834 100644
--- a/sound/soc/msm/msm8960.c
+++ b/sound/soc/msm/msm8960.c
@@ -1095,7 +1095,7 @@
pr_err("%s: Failed to configure gpio %d\n", __func__,
PM8921_GPIO_PM_TO_SYS(35));
else
- gpio_direction_output(PM8921_GPIO_PM_TO_SYS(35), 1);
+ gpio_direction_output(PM8921_GPIO_PM_TO_SYS(35), 0);
return 0;
}