Merge "slim_msm: Make sure runtime PM reference count doesn't go -ve" into msm-3.0
diff --git a/arch/arm/configs/msm8960-perf_defconfig b/arch/arm/configs/msm8960-perf_defconfig
index 860e2bf..eca2ffa 100644
--- a/arch/arm/configs/msm8960-perf_defconfig
+++ b/arch/arm/configs/msm8960-perf_defconfig
@@ -66,6 +66,7 @@
CONFIG_MSM_PIL_QDSP6V4=y
CONFIG_MSM_PIL_RIVA=y
CONFIG_MSM_PIL_TZAPPS=y
+CONFIG_MSM_PIL_GSS=y
CONFIG_MSM_SUBSYSTEM_RESTART=y
CONFIG_MSM_MODEM_8960=y
CONFIG_MSM_LPASS_8960=y
diff --git a/arch/arm/configs/msm8960_defconfig b/arch/arm/configs/msm8960_defconfig
index eb4244f..18e9085 100644
--- a/arch/arm/configs/msm8960_defconfig
+++ b/arch/arm/configs/msm8960_defconfig
@@ -66,6 +66,7 @@
CONFIG_MSM_PIL_QDSP6V4=y
CONFIG_MSM_PIL_RIVA=y
CONFIG_MSM_PIL_TZAPPS=y
+CONFIG_MSM_PIL_GSS=y
CONFIG_MSM_SUBSYSTEM_RESTART=y
CONFIG_MSM_MODEM_8960=y
CONFIG_MSM_LPASS_8960=y
diff --git a/arch/arm/mach-msm/Kconfig b/arch/arm/mach-msm/Kconfig
index 3f04ce0..904839b 100644
--- a/arch/arm/mach-msm/Kconfig
+++ b/arch/arm/mach-msm/Kconfig
@@ -1705,6 +1705,13 @@
used to decrypt data and perform secure operations on the behalf of
the kernel.
+config MSM_PIL_GSS
+ tristate "GSS (Coretx A5) Boot Support"
+ depends on MSM_PIL
+ help
+ Support for booting and shutting down Cortex A5 processors which run
+ GPS subsystem firmware.
+
config MSM_SCM
bool "Secure Channel Manager (SCM) support"
default n
diff --git a/arch/arm/mach-msm/Makefile b/arch/arm/mach-msm/Makefile
index 939b036..19a316e 100644
--- a/arch/arm/mach-msm/Makefile
+++ b/arch/arm/mach-msm/Makefile
@@ -71,6 +71,7 @@
obj-$(CONFIG_MSM_PIL_RIVA) += pil-riva.o
obj-$(CONFIG_MSM_PIL_TZAPPS) += pil-tzapps.o
obj-$(CONFIG_MSM_PIL_MODEM) += pil-modem.o
+obj-$(CONFIG_MSM_PIL_GSS) += pil-gss.o
obj-$(CONFIG_ARCH_QSD8X50) += sirc.o
obj-$(CONFIG_ARCH_FSM9XXX) += sirc-fsm9xxx.o
obj-$(CONFIG_MSM_FIQ_SUPPORT) += fiq_glue.o
diff --git a/arch/arm/mach-msm/acpuclock-7201.c b/arch/arm/mach-msm/acpuclock-7201.c
index 23d03ef..6140559 100644
--- a/arch/arm/mach-msm/acpuclock-7201.c
+++ b/arch/arm/mach-msm/acpuclock-7201.c
@@ -369,34 +369,39 @@
};
#ifdef CONFIG_CPU_FREQ_MSM
-static struct cpufreq_frequency_table freq_table[20];
+static struct cpufreq_frequency_table freq_table[NR_CPUS][20];
static void __init cpufreq_table_init(void)
{
- unsigned int i;
- unsigned int freq_cnt = 0;
+ int cpu;
+ for_each_possible_cpu(cpu) {
+ unsigned int i, freq_cnt = 0;
- /* Construct the freq_table table from acpu_freq_tbl since the
- * freq_table values need to match frequencies specified in
- * acpu_freq_tbl and acpu_freq_tbl needs to be fixed up during init.
- */
- for (i = 0; acpu_freq_tbl[i].a11clk_khz != 0
- && freq_cnt < ARRAY_SIZE(freq_table)-1; i++) {
- if (acpu_freq_tbl[i].use_for_scaling) {
- freq_table[freq_cnt].index = freq_cnt;
- freq_table[freq_cnt].frequency
- = acpu_freq_tbl[i].a11clk_khz;
- freq_cnt++;
+ /* Construct the freq_table table from acpu_freq_tbl since
+ * the freq_table values need to match frequencies specified
+ * in acpu_freq_tbl and acpu_freq_tbl needs to be fixed up
+ * during init.
+ */
+ for (i = 0; acpu_freq_tbl[i].a11clk_khz != 0
+ && freq_cnt < ARRAY_SIZE(*freq_table)-1; i++) {
+ if (acpu_freq_tbl[i].use_for_scaling) {
+ freq_table[cpu][freq_cnt].index = freq_cnt;
+ freq_table[cpu][freq_cnt].frequency
+ = acpu_freq_tbl[i].a11clk_khz;
+ freq_cnt++;
+ }
}
+
+ /* freq_table not big enough to store all usable freqs. */
+ BUG_ON(acpu_freq_tbl[i].a11clk_khz != 0);
+
+ freq_table[cpu][freq_cnt].index = freq_cnt;
+ freq_table[cpu][freq_cnt].frequency = CPUFREQ_TABLE_END;
+ /* Register table with CPUFreq. */
+ cpufreq_frequency_table_get_attr(freq_table[cpu], cpu);
+ pr_info("CPU%d: %d scaling frequencies supported.\n",
+ cpu, freq_cnt);
}
-
- /* freq_table not big enough to store all usable freqs. */
- BUG_ON(acpu_freq_tbl[i].a11clk_khz != 0);
-
- freq_table[freq_cnt].index = freq_cnt;
- freq_table[freq_cnt].frequency = CPUFREQ_TABLE_END;
-
- pr_info("%d scaling frequencies supported.\n", freq_cnt);
}
#endif
@@ -995,7 +1000,6 @@
#ifdef CONFIG_CPU_FREQ_MSM
cpufreq_table_init();
- cpufreq_frequency_table_get_attr(freq_table, smp_processor_id());
#endif
return 0;
}
diff --git a/arch/arm/mach-msm/board-8064-gpiomux.c b/arch/arm/mach-msm/board-8064-gpiomux.c
index 57f4a0a..de80a3e 100644
--- a/arch/arm/mach-msm/board-8064-gpiomux.c
+++ b/arch/arm/mach-msm/board-8064-gpiomux.c
@@ -21,6 +21,7 @@
#include <mach/board.h>
#include <mach/gpio.h>
#include <mach/gpiomux.h>
+#include <mach/socinfo.h>
#include "devices.h"
#include "board-8064.h"
@@ -34,17 +35,24 @@
/* The SPI configurations apply to GSBI 5*/
static struct gpiomux_setting gpio_spi_config = {
.func = GPIOMUX_FUNC_2,
- .drv = GPIOMUX_DRV_8MA,
+ .drv = GPIOMUX_DRV_12MA,
.pull = GPIOMUX_PULL_NONE,
};
/* The SPI configurations apply to GSBI 5 chip select 2*/
static struct gpiomux_setting gpio_spi_cs2_config = {
.func = GPIOMUX_FUNC_3,
- .drv = GPIOMUX_DRV_8MA,
+ .drv = GPIOMUX_DRV_12MA,
.pull = GPIOMUX_PULL_NONE,
};
+/* Chip selects for SPI clients */
+static struct gpiomux_setting gpio_spi_cs_config = {
+ .func = GPIOMUX_FUNC_GPIO,
+ .drv = GPIOMUX_DRV_12MA,
+ .pull = GPIOMUX_PULL_UP,
+};
+
struct msm_gpiomux_config apq8064_ethernet_configs[] = {
{
.gpio = 43,
@@ -89,6 +97,45 @@
.pull = GPIOMUX_PULL_NONE,
};
+static struct gpiomux_setting ext_regulator_config = {
+ .func = GPIOMUX_FUNC_GPIO,
+ .drv = GPIOMUX_DRV_8MA,
+ .pull = GPIOMUX_PULL_NONE,
+ .dir = GPIOMUX_OUT_LOW,
+};
+
+#ifdef CONFIG_USB_EHCI_MSM_HSIC
+static struct gpiomux_setting hsic_act_cfg = {
+ .func = GPIOMUX_FUNC_1,
+ .drv = GPIOMUX_DRV_8MA,
+ .pull = GPIOMUX_PULL_NONE,
+};
+
+static struct gpiomux_setting hsic_sus_cfg = {
+ .func = GPIOMUX_FUNC_GPIO,
+ .drv = GPIOMUX_DRV_2MA,
+ .pull = GPIOMUX_PULL_DOWN,
+ .dir = GPIOMUX_OUT_LOW,
+};
+
+static struct msm_gpiomux_config apq8064_hsic_configs[] = {
+ {
+ .gpio = 88, /*HSIC_STROBE */
+ .settings = {
+ [GPIOMUX_ACTIVE] = &hsic_act_cfg,
+ [GPIOMUX_SUSPENDED] = &hsic_sus_cfg,
+ },
+ },
+ {
+ .gpio = 89, /* HSIC_DATA */
+ .settings = {
+ [GPIOMUX_ACTIVE] = &hsic_act_cfg,
+ [GPIOMUX_SUSPENDED] = &hsic_sus_cfg,
+ },
+ },
+};
+#endif
+
static struct msm_gpiomux_config apq8064_gsbi_configs[] __initdata = {
{
.gpio = 18, /* GSBI1 UART TX */
@@ -116,6 +163,12 @@
},
},
{
+ .gpio = 53, /* Funny CS0 */
+ .settings = {
+ [GPIOMUX_SUSPENDED] = &gpio_spi_config,
+ },
+ },
+ {
.gpio = 31, /* GSBI5 QUP SPI_CS2_N */
.settings = {
[GPIOMUX_SUSPENDED] = &gpio_spi_cs2_config,
@@ -128,6 +181,24 @@
},
},
#endif
+ {
+ .gpio = 30, /* FP CS */
+ .settings = {
+ [GPIOMUX_SUSPENDED] = &gpio_spi_cs_config,
+ },
+ },
+ {
+ .gpio = 32, /* EPM CS */
+ .settings = {
+ [GPIOMUX_SUSPENDED] = &gpio_spi_cs_config,
+ },
+ },
+ {
+ .gpio = 53, /* NOR CS */
+ .settings = {
+ [GPIOMUX_SUSPENDED] = &gpio_spi_cs_config,
+ },
+ },
};
static struct msm_gpiomux_config apq8064_slimbus_config[] __initdata = {
@@ -185,6 +256,78 @@
},
};
+/* External 3.3 V regulator enable */
+static struct msm_gpiomux_config apq8064_ext_regulator_configs[] __initdata = {
+ {
+ .gpio = APQ8064_EXT_3P3V_REG_EN_GPIO,
+ .settings = {
+ [GPIOMUX_SUSPENDED] = &ext_regulator_config,
+ },
+ },
+};
+
+static struct gpiomux_setting ap2mdm_cfg = {
+ .func = GPIOMUX_FUNC_GPIO,
+ .drv = GPIOMUX_DRV_8MA,
+ .pull = GPIOMUX_PULL_DOWN,
+};
+
+static struct gpiomux_setting mdm2ap_status_cfg = {
+ .func = GPIOMUX_FUNC_GPIO,
+ .drv = GPIOMUX_DRV_8MA,
+ .pull = GPIOMUX_PULL_NONE,
+};
+
+static struct gpiomux_setting mdm2ap_errfatal_cfg = {
+ .func = GPIOMUX_FUNC_GPIO,
+ .drv = GPIOMUX_DRV_16MA,
+ .pull = GPIOMUX_PULL_DOWN,
+};
+
+static struct gpiomux_setting ap2mdm_pon_reset_n_cfg = {
+ .func = GPIOMUX_FUNC_GPIO,
+ .drv = GPIOMUX_DRV_8MA,
+ .pull = GPIOMUX_PULL_DOWN,
+};
+
+static struct msm_gpiomux_config mdm_configs[] __initdata = {
+ /* AP2MDM_STATUS */
+ {
+ .gpio = 48,
+ .settings = {
+ [GPIOMUX_SUSPENDED] = &ap2mdm_cfg,
+ }
+ },
+ /* MDM2AP_STATUS */
+ {
+ .gpio = 49,
+ .settings = {
+ [GPIOMUX_SUSPENDED] = &mdm2ap_status_cfg,
+ }
+ },
+ /* MDM2AP_ERRFATAL */
+ {
+ .gpio = 19,
+ .settings = {
+ [GPIOMUX_SUSPENDED] = &mdm2ap_errfatal_cfg,
+ }
+ },
+ /* AP2MDM_ERRFATAL */
+ {
+ .gpio = 18,
+ .settings = {
+ [GPIOMUX_SUSPENDED] = &ap2mdm_cfg,
+ }
+ },
+ /* AP2MDM_PON_RESET_N */
+ {
+ .gpio = 27,
+ .settings = {
+ [GPIOMUX_SUSPENDED] = &ap2mdm_pon_reset_n_cfg,
+ }
+ }
+};
+
void __init apq8064_init_gpiomux(void)
{
int rc;
@@ -211,4 +354,16 @@
msm_gpiomux_install(apq8064_audio_auxpcm_configs,
ARRAY_SIZE(apq8064_audio_auxpcm_configs));
+
+ msm_gpiomux_install(apq8064_ext_regulator_configs,
+ ARRAY_SIZE(apq8064_ext_regulator_configs));
+
+ if (machine_is_apq8064_mtp())
+ msm_gpiomux_install(mdm_configs,
+ ARRAY_SIZE(mdm_configs));
+
+#ifdef CONFIG_USB_EHCI_MSM_HSIC
+ msm_gpiomux_install(apq8064_hsic_configs,
+ ARRAY_SIZE(apq8064_hsic_configs));
+#endif
}
diff --git a/arch/arm/mach-msm/board-8064-pmic.c b/arch/arm/mach-msm/board-8064-pmic.c
index 2182079..5204e48 100644
--- a/arch/arm/mach-msm/board-8064-pmic.c
+++ b/arch/arm/mach-msm/board-8064-pmic.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2011, Code Aurora Forum. All rights reserved.
+/* Copyright (c) 2011-2012, Code Aurora Forum. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -15,15 +15,236 @@
#include <linux/ioport.h>
#include <linux/platform_device.h>
#include <linux/bootmem.h>
+#include <linux/mfd/pm8xxx/pm8921.h>
+#include <linux/leds.h>
+#include <linux/leds-pm8xxx.h>
+#include <linux/mfd/pm8xxx/pm8xxx-adc.h>
#include <asm/mach-types.h>
#include <asm/mach/mmc.h>
#include <mach/msm_bus_board.h>
#include <mach/board.h>
#include <mach/gpio.h>
#include <mach/gpiomux.h>
+#include <mach/restart.h>
#include "devices.h"
#include "board-8064.h"
+struct pm8xxx_gpio_init {
+ unsigned gpio;
+ struct pm_gpio config;
+};
+
+struct pm8xxx_mpp_init {
+ unsigned mpp;
+ struct pm8xxx_mpp_config_data config;
+};
+
+#define PM8921_GPIO_INIT(_gpio, _dir, _buf, _val, _pull, _vin, _out_strength, \
+ _func, _inv, _disable) \
+{ \
+ .gpio = PM8921_GPIO_PM_TO_SYS(_gpio), \
+ .config = { \
+ .direction = _dir, \
+ .output_buffer = _buf, \
+ .output_value = _val, \
+ .pull = _pull, \
+ .vin_sel = _vin, \
+ .out_strength = _out_strength, \
+ .function = _func, \
+ .inv_int_pol = _inv, \
+ .disable_pin = _disable, \
+ } \
+}
+
+#define PM8921_MPP_INIT(_mpp, _type, _level, _control) \
+{ \
+ .mpp = PM8921_MPP_PM_TO_SYS(_mpp), \
+ .config = { \
+ .type = PM8XXX_MPP_TYPE_##_type, \
+ .level = _level, \
+ .control = PM8XXX_MPP_##_control, \
+ } \
+}
+
+#define PM8821_MPP_INIT(_mpp, _type, _level, _control) \
+{ \
+ .mpp = PM8821_MPP_PM_TO_SYS(_mpp), \
+ .config = { \
+ .type = PM8XXX_MPP_TYPE_##_type, \
+ .level = _level, \
+ .control = PM8XXX_MPP_##_control, \
+ } \
+}
+
+#define PM8921_GPIO_DISABLE(_gpio) \
+ PM8921_GPIO_INIT(_gpio, PM_GPIO_DIR_IN, 0, 0, 0, PM_GPIO_VIN_S4, \
+ 0, 0, 0, 1)
+
+#define PM8921_GPIO_OUTPUT(_gpio, _val, _strength) \
+ PM8921_GPIO_INIT(_gpio, PM_GPIO_DIR_OUT, PM_GPIO_OUT_BUF_CMOS, _val, \
+ PM_GPIO_PULL_NO, PM_GPIO_VIN_S4, \
+ PM_GPIO_STRENGTH_##_strength, \
+ PM_GPIO_FUNC_NORMAL, 0, 0)
+
+#define PM8921_GPIO_INPUT(_gpio, _pull) \
+ PM8921_GPIO_INIT(_gpio, PM_GPIO_DIR_IN, PM_GPIO_OUT_BUF_CMOS, 0, \
+ _pull, PM_GPIO_VIN_S4, \
+ PM_GPIO_STRENGTH_NO, \
+ PM_GPIO_FUNC_NORMAL, 0, 0)
+
+#define PM8921_GPIO_OUTPUT_FUNC(_gpio, _val, _func) \
+ PM8921_GPIO_INIT(_gpio, PM_GPIO_DIR_OUT, PM_GPIO_OUT_BUF_CMOS, _val, \
+ PM_GPIO_PULL_NO, PM_GPIO_VIN_S4, \
+ PM_GPIO_STRENGTH_HIGH, \
+ _func, 0, 0)
+
+#define PM8921_GPIO_OUTPUT_VIN(_gpio, _val, _vin) \
+ PM8921_GPIO_INIT(_gpio, PM_GPIO_DIR_OUT, PM_GPIO_OUT_BUF_CMOS, _val, \
+ PM_GPIO_PULL_NO, _vin, \
+ PM_GPIO_STRENGTH_HIGH, \
+ PM_GPIO_FUNC_NORMAL, 0, 0)
+
+/* Initial PM8921 GPIO configurations */
+static struct pm8xxx_gpio_init pm8921_gpios[] __initdata = {
+};
+
+/* Initial PM8XXX MPP configurations */
+static struct pm8xxx_mpp_init pm8xxx_mpps[] __initdata = {
+ /* External 5V regulator enable; shared by HDMI and USB_OTG switches. */
+ PM8921_MPP_INIT(7, D_INPUT, PM8921_MPP_DIG_LEVEL_VPH, DIN_TO_INT),
+};
+
+void __init apq8064_pm8xxx_gpio_mpp_init(void)
+{
+ int i, rc;
+
+ for (i = 0; i < ARRAY_SIZE(pm8921_gpios); i++) {
+ rc = pm8xxx_gpio_config(pm8921_gpios[i].gpio,
+ &pm8921_gpios[i].config);
+ if (rc) {
+ pr_err("%s: pm8xxx_gpio_config: rc=%d\n", __func__, rc);
+ break;
+ }
+ }
+
+ for (i = 0; i < ARRAY_SIZE(pm8xxx_mpps); i++) {
+ rc = pm8xxx_mpp_config(pm8xxx_mpps[i].mpp,
+ &pm8xxx_mpps[i].config);
+ if (rc) {
+ pr_err("%s: pm8xxx_mpp_config: rc=%d\n", __func__, rc);
+ break;
+ }
+ }
+}
+
+static struct pm8xxx_pwrkey_platform_data apq8064_pm8921_pwrkey_pdata = {
+ .pull_up = 1,
+ .kpd_trigger_delay_us = 15625,
+ .wakeup = 1,
+};
+
+static struct pm8xxx_misc_platform_data apq8064_pm8921_misc_pdata = {
+ .priority = 0,
+};
+
+#define PM8921_LC_LED_MAX_CURRENT 4 /* I = 4mA */
+#define PM8921_LC_LED_LOW_CURRENT 1 /* I = 1mA */
+#define PM8XXX_LED_PWM_PERIOD 1000
+#define PM8XXX_LED_PWM_DUTY_MS 20
+/**
+ * PM8XXX_PWM_CHANNEL_NONE shall be used when LED shall not be
+ * driven using PWM feature.
+ */
+#define PM8XXX_PWM_CHANNEL_NONE -1
+
+static struct led_info pm8921_led_info[] = {
+ [0] = {
+ .name = "led:red",
+ .default_trigger = "ac-online",
+ },
+};
+
+static struct led_platform_data pm8921_led_core_pdata = {
+ .num_leds = ARRAY_SIZE(pm8921_led_info),
+ .leds = pm8921_led_info,
+};
+
+static int pm8921_led0_pwm_duty_pcts[56] = {
+ 1, 4, 8, 12, 16, 20, 24, 28, 32, 36,
+ 40, 44, 46, 52, 56, 60, 64, 68, 72, 76,
+ 80, 84, 88, 92, 96, 100, 100, 100, 98, 95,
+ 92, 88, 84, 82, 78, 74, 70, 66, 62, 58,
+ 58, 54, 50, 48, 42, 38, 34, 30, 26, 22,
+ 14, 10, 6, 4, 1
+};
+
+static struct pm8xxx_pwm_duty_cycles pm8921_led0_pwm_duty_cycles = {
+ .duty_pcts = (int *)&pm8921_led0_pwm_duty_pcts,
+ .num_duty_pcts = ARRAY_SIZE(pm8921_led0_pwm_duty_pcts),
+ .duty_ms = PM8XXX_LED_PWM_DUTY_MS,
+ .start_idx = 0,
+};
+
+static struct pm8xxx_led_config pm8921_led_configs[] = {
+ [0] = {
+ .id = PM8XXX_ID_LED_0,
+ .mode = PM8XXX_LED_MODE_PWM2,
+ .max_current = PM8921_LC_LED_MAX_CURRENT,
+ .pwm_channel = 5,
+ .pwm_period_us = PM8XXX_LED_PWM_PERIOD,
+ .pwm_duty_cycles = &pm8921_led0_pwm_duty_cycles,
+ },
+};
+
+static struct pm8xxx_led_platform_data apq8064_pm8921_leds_pdata = {
+ .led_core = &pm8921_led_core_pdata,
+ .configs = pm8921_led_configs,
+ .num_configs = ARRAY_SIZE(pm8921_led_configs),
+};
+
+static struct pm8xxx_adc_amux apq8064_pm8921_adc_channels_data[] = {
+ {"vcoin", CHANNEL_VCOIN, CHAN_PATH_SCALING2, AMUX_RSV1,
+ ADC_DECIMATION_TYPE2, ADC_SCALE_DEFAULT},
+ {"vbat", CHANNEL_VBAT, CHAN_PATH_SCALING2, AMUX_RSV1,
+ ADC_DECIMATION_TYPE2, ADC_SCALE_DEFAULT},
+ {"dcin", CHANNEL_DCIN, CHAN_PATH_SCALING4, AMUX_RSV1,
+ ADC_DECIMATION_TYPE2, ADC_SCALE_DEFAULT},
+ {"ichg", CHANNEL_ICHG, CHAN_PATH_SCALING1, AMUX_RSV1,
+ ADC_DECIMATION_TYPE2, ADC_SCALE_DEFAULT},
+ {"vph_pwr", CHANNEL_VPH_PWR, CHAN_PATH_SCALING2, AMUX_RSV1,
+ ADC_DECIMATION_TYPE2, ADC_SCALE_DEFAULT},
+ {"ibat", CHANNEL_IBAT, CHAN_PATH_SCALING1, AMUX_RSV1,
+ ADC_DECIMATION_TYPE2, ADC_SCALE_DEFAULT},
+ {"batt_therm", CHANNEL_BATT_THERM, CHAN_PATH_SCALING1, AMUX_RSV2,
+ ADC_DECIMATION_TYPE2, ADC_SCALE_BATT_THERM},
+ {"batt_id", CHANNEL_BATT_ID, CHAN_PATH_SCALING1, AMUX_RSV1,
+ ADC_DECIMATION_TYPE2, ADC_SCALE_DEFAULT},
+ {"usbin", CHANNEL_USBIN, CHAN_PATH_SCALING3, AMUX_RSV1,
+ ADC_DECIMATION_TYPE2, ADC_SCALE_DEFAULT},
+ {"pmic_therm", CHANNEL_DIE_TEMP, CHAN_PATH_SCALING1, AMUX_RSV1,
+ ADC_DECIMATION_TYPE2, ADC_SCALE_PMIC_THERM},
+ {"625mv", CHANNEL_625MV, CHAN_PATH_SCALING1, AMUX_RSV1,
+ ADC_DECIMATION_TYPE2, ADC_SCALE_DEFAULT},
+ {"125v", CHANNEL_125V, CHAN_PATH_SCALING1, AMUX_RSV1,
+ ADC_DECIMATION_TYPE2, ADC_SCALE_DEFAULT},
+ {"chg_temp", CHANNEL_CHG_TEMP, CHAN_PATH_SCALING1, AMUX_RSV1,
+ ADC_DECIMATION_TYPE2, ADC_SCALE_DEFAULT},
+ {"xo_therm", CHANNEL_MUXOFF, CHAN_PATH_SCALING1, AMUX_RSV0,
+ ADC_DECIMATION_TYPE2, ADC_SCALE_XOTHERM},
+};
+
+static struct pm8xxx_adc_properties apq8064_pm8921_adc_data = {
+ .adc_vdd_reference = 1800, /* milli-voltage for this adc */
+ .bitresolution = 15,
+ .bipolar = 0,
+};
+
+static struct pm8xxx_adc_platform_data apq8064_pm8921_adc_pdata = {
+ .adc_channel = apq8064_pm8921_adc_channels_data,
+ .adc_num_board_channel = ARRAY_SIZE(apq8064_pm8921_adc_channels_data),
+ .adc_prop = &apq8064_pm8921_adc_data,
+ .adc_mpp_base = PM8921_MPP_PM_TO_SYS(1),
+};
static struct pm8xxx_mpp_platform_data
apq8064_pm8921_mpp_pdata __devinitdata = {
@@ -49,6 +270,48 @@
.rtc_alarm_powerup = false,
};
+static int apq8064_pm8921_therm_mitigation[] = {
+ 1100,
+ 700,
+ 600,
+ 325,
+};
+
+#define MAX_VOLTAGE_MV 4200
+static struct pm8921_charger_platform_data
+apq8064_pm8921_chg_pdata __devinitdata = {
+ .safety_time = 180,
+ .update_time = 60000,
+ .max_voltage = MAX_VOLTAGE_MV,
+ .min_voltage = 3200,
+ .resume_voltage_delta = 100,
+ .term_current = 100,
+ .cool_temp = 10,
+ .warm_temp = 40,
+ .temp_check_period = 1,
+ .max_bat_chg_current = 1100,
+ .cool_bat_chg_current = 350,
+ .warm_bat_chg_current = 350,
+ .cool_bat_voltage = 4100,
+ .warm_bat_voltage = 4100,
+ .thermal_mitigation = apq8064_pm8921_therm_mitigation,
+ .thermal_levels = ARRAY_SIZE(apq8064_pm8921_therm_mitigation),
+};
+
+static struct pm8xxx_ccadc_platform_data
+apq8064_pm8xxx_ccadc_pdata = {
+ .r_sense = 10,
+};
+
+static struct pm8921_bms_platform_data
+apq8064_pm8921_bms_pdata __devinitdata = {
+ .r_sense = 10,
+ .i_test = 2500,
+ .v_failure = 3000,
+ .calib_delay_ms = 600000,
+ .max_voltage_uv = MAX_VOLTAGE_MV * 1000,
+};
+
static struct pm8921_platform_data
apq8064_pm8921_platform_data __devinitdata = {
.regulator_pdatas = msm8064_pm8921_regulator_pdata,
@@ -56,12 +319,19 @@
.gpio_pdata = &apq8064_pm8921_gpio_pdata,
.mpp_pdata = &apq8064_pm8921_mpp_pdata,
.rtc_pdata = &apq8064_pm8921_rtc_pdata,
+ .pwrkey_pdata = &apq8064_pm8921_pwrkey_pdata,
+ .misc_pdata = &apq8064_pm8921_misc_pdata,
+ .leds_pdata = &apq8064_pm8921_leds_pdata,
+ .adc_pdata = &apq8064_pm8921_adc_pdata,
+ .charger_pdata = &apq8064_pm8921_chg_pdata,
+ .bms_pdata = &apq8064_pm8921_bms_pdata,
+ .ccadc_pdata = &apq8064_pm8xxx_ccadc_pdata,
};
static struct pm8xxx_irq_platform_data
apq8064_pm8821_irq_pdata __devinitdata = {
.irq_base = PM8821_IRQ_BASE,
- .devirq = PM8821_USR_IRQ_N,
+ .devirq = PM8821_SEC_IRQ_N,
.irq_trigger_flag = IRQF_TRIGGER_HIGH,
.dev_id = 1,
};
@@ -95,6 +365,8 @@
void __init apq8064_init_pmic(void)
{
+ pmic_reset_irq = PM8921_IRQ_BASE + PM8921_RESOUT_IRQ;
+
apq8064_device_ssbi_pmic1.dev.platform_data =
&apq8064_ssbi_pm8921_pdata;
apq8064_device_ssbi_pmic2.dev.platform_data =
diff --git a/arch/arm/mach-msm/board-8064-regulator.c b/arch/arm/mach-msm/board-8064-regulator.c
index 7267f96..f3eebce 100644
--- a/arch/arm/mach-msm/board-8064-regulator.c
+++ b/arch/arm/mach-msm/board-8064-regulator.c
@@ -129,6 +129,7 @@
REGULATOR_SUPPLY("HSUSB_VDDCX", "msm_otg"),
REGULATOR_SUPPLY("HSUSB_VDDCX", "msm_ehci_host.0"),
REGULATOR_SUPPLY("HSUSB_VDDCX", "msm_ehci_host.1"),
+ REGULATOR_SUPPLY("HSIC_VDDCX", "msm_hsic_host"),
REGULATOR_SUPPLY("riva_vddcx", "wcnss_wlan.0"),
};
VREG_CONSUMERS(S4) = {
@@ -179,6 +180,7 @@
};
VREG_CONSUMERS(USB_OTG) = {
REGULATOR_SUPPLY("8921_usb_otg", NULL),
+ REGULATOR_SUPPLY("vbus_otg", "msm_otg"),
};
VREG_CONSUMERS(HDMI_MVS) = {
REGULATOR_SUPPLY("8921_hdmi_mvs", NULL),
@@ -194,6 +196,14 @@
REGULATOR_SUPPLY("8821_s1", NULL),
REGULATOR_SUPPLY("krait3", NULL),
};
+VREG_CONSUMERS(EXT_5V) = {
+ REGULATOR_SUPPLY("ext_5v", NULL),
+};
+VREG_CONSUMERS(EXT_3P3V) = {
+ REGULATOR_SUPPLY("ext_3p3v", NULL),
+ REGULATOR_SUPPLY("vdd_io", "spi0.2"),
+ REGULATOR_SUPPLY("mhl_ext_3p3v", "msm_otg"),
+};
#define PM8XXX_VREG_INIT(_id, _name, _min_uV, _max_uV, _modes, _ops, \
_apply_uV, _pull_down, _always_on, _supply_regulator, \
@@ -290,6 +300,22 @@
.pin_ctrl = _pin_ctrl, \
}
+#define GPIO_VREG(_id, _reg_name, _gpio_label, _gpio, _supply_regulator) \
+ [GPIO_VREG_ID_##_id] = { \
+ .init_data = { \
+ .constraints = { \
+ .valid_ops_mask = REGULATOR_CHANGE_STATUS, \
+ }, \
+ .num_consumer_supplies = \
+ ARRAY_SIZE(vreg_consumers_##_id), \
+ .consumer_supplies = vreg_consumers_##_id, \
+ .supply_regulator = _supply_regulator, \
+ }, \
+ .regulator_name = _reg_name, \
+ .gpio_label = _gpio_label, \
+ .gpio = _gpio, \
+ }
+
#define SAW_VREG_INIT(_id, _name, _min_uV, _max_uV) \
{ \
.constraints = { \
@@ -302,6 +328,15 @@
.consumer_supplies = vreg_consumers_##_id, \
}
+/* GPIO regulator constraints */
+struct gpio_regulator_platform_data
+apq8064_gpio_regulator_pdata[] __devinitdata = {
+ /* ID vreg_name gpio_label gpio supply */
+ GPIO_VREG(EXT_5V, "ext_5v", "ext_5v_en", PM8921_MPP_PM_TO_SYS(7), NULL),
+ GPIO_VREG(EXT_3P3V, "ext_3p3v", "ext_3p3v_en",
+ APQ8064_EXT_3P3V_REG_EN_GPIO, NULL),
+};
+
/* SAW regulator constraints */
struct regulator_init_data msm8064_saw_regulator_pdata_8921_s5 =
/* ID vreg_name min_uV max_uV */
@@ -329,7 +364,7 @@
3),
PM8XXX_SMPS(S4, "8921_s4", 1, 1, 1800000, 1800000, 500, NULL, 100000,
4),
- PM8XXX_SMPS(S7, "8921_s7", 0, 1, 1200000, 1200000, 500, NULL, 100000,
+ PM8XXX_SMPS(S7, "8921_s7", 0, 1, 1300000, 1300000, 500, NULL, 100000,
5),
PM8XXX_LDO(L1, "8921_l1", 1, 1, 1100000, 1100000, 200, "8921_s4", 0,
@@ -337,10 +372,11 @@
PM8XXX_LDO(L2, "8921_l2", 0, 1, 1200000, 1200000, 200, "8921_s4", 0,
7),
PM8XXX_LDO(L3, "8921_l3", 0, 1, 3075000, 3075000, 200, NULL, 0, 8),
- PM8XXX_LDO(L4, "8921_l4", 1, 1, 1800000, 1800000, 200, NULL, 0, 9),
+ PM8XXX_LDO(L4, "8921_l4", 1, 1, 1800000, 1800000, 200, NULL, 10000,
+ 9),
PM8XXX_LDO(L5, "8921_l5", 0, 1, 2950000, 2950000, 200, NULL, 0, 10),
PM8XXX_LDO(L6, "8921_l6", 0, 1, 2950000, 2950000, 200, NULL, 0, 11),
- PM8XXX_LDO(L7, "8921_l7", 1, 1, 1850000, 2950000, 200, NULL, 0, 12),
+ PM8XXX_LDO(L7, "8921_l7", 0, 1, 1850000, 2950000, 200, NULL, 0, 12),
PM8XXX_LDO(L8, "8921_l8", 0, 1, 2800000, 2800000, 200, NULL, 0, 13),
PM8XXX_LDO(L9, "8921_l9", 0, 1, 2850000, 2850000, 200, NULL, 0, 14),
PM8XXX_LDO(L10, "8921_l10", 0, 1, 2900000, 2900000, 200, NULL, 0, 15),
@@ -358,10 +394,10 @@
PM8XXX_NLDO1200(L24, "8921_l24", 1, 1, 1150000, 1150000, 200, "8921_s1",
10000, 25),
PM8XXX_NLDO1200(L25, "8921_l25", 1, 1, 1225000, 1225000, 200, "8921_s1",
- 0, 26),
+ 10000, 26),
PM8XXX_NLDO1200(L26, "8921_l26", 0, 1, 1050000, 1050000, 200, "8921_s7",
0, 27),
- PM8XXX_NLDO1200(L27, "8921_l27", 0, 1, 1000000, 1000000, 200, "8921_s7",
+ PM8XXX_NLDO1200(L27, "8921_l27", 0, 1, 1100000, 1100000, 200, "8921_s7",
0, 28),
PM8XXX_NLDO1200(L28, "8921_l28", 0, 1, 1050000, 1050000, 200, "8921_s7",
0, 29),
@@ -375,8 +411,8 @@
PM8XXX_VS(LVS6, "8921_lvs6", 0, 1, 0, "8921_s4", 35),
PM8XXX_VS(LVS7, "8921_lvs7", 1, 1, 0, "8921_s4", 36),
- PM8XXX_VS300(USB_OTG, "8921_usb_otg", 0, 1, 0, NULL, 37),
- PM8XXX_VS300(HDMI_MVS, "8921_hdmi_mvs", 0, 1, 0, NULL, 38),
+ PM8XXX_VS300(USB_OTG, "8921_usb_otg", 0, 0, 0, "ext_5v", 37),
+ PM8XXX_VS300(HDMI_MVS, "8921_hdmi_mvs", 0, 1, 0, "ext_5v", 38),
/* ID name always_on min_uV max_uV en_t supply reg_ID */
PM8XXX_NCP(NCP, "8921_ncp", 0, 1800000, 1800000, 200, "8921_l6", 39),
diff --git a/arch/arm/mach-msm/board-8064.c b/arch/arm/mach-msm/board-8064.c
index 3e99b2a..79b4c07 100644
--- a/arch/arm/mach-msm/board-8064.c
+++ b/arch/arm/mach-msm/board-8064.c
@@ -49,8 +49,8 @@
#include <asm/setup.h>
#include <mach/dma.h>
#include <mach/msm_bus_board.h>
-#include <mach/pm.h>
#include <mach/cpuidle.h>
+#include <mach/mdm2.h>
#include "msm_watchdog.h"
#include "board-8064.h"
@@ -58,6 +58,7 @@
#include "spm.h"
#include "mpm.h"
#include "rpm_resources.h"
+#include "pm.h"
#include "pm-boot.h"
#include "devices-msm8x60.h"
@@ -374,15 +375,26 @@
msm_reserve();
}
+#ifdef CONFIG_USB_EHCI_MSM_HSIC
+static struct msm_hsic_host_platform_data msm_hsic_pdata = {
+ .strobe = 88,
+ .data = 89,
+};
+#else
+static struct msm_hsic_host_platform_data msm_hsic_pdata;
+#endif
+
static struct platform_device android_usb_device = {
.name = "android_usb",
.id = -1,
};
static struct msm_otg_platform_data msm_otg_pdata = {
- .mode = USB_PERIPHERAL,
- .otg_control = OTG_PHY_CONTROL,
+ .mode = USB_OTG,
+ .otg_control = OTG_PMIC_CONTROL,
.phy_type = SNPS_28NM_INTEGRATED_PHY,
+ .pmic_id_irq = PM8921_USB_ID_IN_IRQ(PM8921_IRQ_BASE),
+ .power_budget = 750,
};
#define TABLA_INTERRUPT_BASE (NR_MSM_IRQS + NR_GPIO_IRQS + NR_PM8921_IRQS)
@@ -567,6 +579,11 @@
};
#endif
+static struct mdm_platform_data mdm_platform_data = {
+ .mdm_version = "3.0",
+ .ramdump_delay_ms = 2000,
+ .peripheral_platform_device = &apq8064_device_hsic_host,
+};
#define MSM_SHARED_RAM_PHYS 0x80000000
static void __init apq8064_map_io(void)
@@ -1006,16 +1023,38 @@
msm_bus_8064_cpss_fpb.dev.platform_data = &msm_bus_8064_cpss_fpb_pdata;
}
+static struct platform_device apq8064_device_ext_5v_vreg __devinitdata = {
+ .name = GPIO_REGULATOR_DEV_NAME,
+ .id = PM8921_MPP_PM_TO_SYS(7),
+ .dev = {
+ .platform_data
+ = &apq8064_gpio_regulator_pdata[GPIO_VREG_ID_EXT_5V],
+ },
+};
+
+static struct platform_device apq8064_device_ext_3p3v_vreg __devinitdata = {
+ .name = GPIO_REGULATOR_DEV_NAME,
+ .id = APQ8064_EXT_3P3V_REG_EN_GPIO,
+ .dev = {
+ .platform_data =
+ &apq8064_gpio_regulator_pdata[GPIO_VREG_ID_EXT_3P3V],
+ },
+};
+
static struct platform_device *common_devices[] __initdata = {
&apq8064_device_dmov,
&apq8064_device_qup_i2c_gsbi4,
&apq8064_device_qup_spi_gsbi5,
&apq8064_slim_ctrl,
+ &apq8064_device_ext_5v_vreg,
+ &apq8064_device_ext_3p3v_vreg,
&apq8064_device_ssbi_pmic1,
&apq8064_device_ssbi_pmic2,
&msm_device_smd_apq8064,
&apq8064_device_otg,
&apq8064_device_gadget_peripheral,
+ &apq8064_device_hsusb_host,
+ &apq8064_device_hsic_host,
&android_usb_device,
#ifdef CONFIG_ANDROID_PMEM
#ifndef CONFIG_MSM_MULTIMEDIA_USE_ION
@@ -1078,6 +1117,7 @@
&msm_device_vidc,
&msm_8960_riva,
&msm_8960_q6_lpass,
+ &msm_gss,
};
static struct platform_device *sim_devices[] __initdata = {
@@ -1099,7 +1139,7 @@
};
static struct msm_spi_platform_data apq8064_qup_spi_gsbi5_pdata = {
- .max_clock_speed = 24000000,
+ .max_clock_speed = 1100000,
};
#define KS8851_IRQ_GPIO 43
@@ -1138,7 +1178,7 @@
&apq8064_i2c_qup_gsbi4_pdata;
}
-#ifdef CONFIG_KS8851
+#if defined(CONFIG_KS8851) || defined(CONFIG_KS8851_MODULE)
static int ethernet_init(void)
{
int ret;
@@ -1180,9 +1220,13 @@
apq8064_device_qup_spi_gsbi5.dev.platform_data =
&apq8064_qup_spi_gsbi5_pdata;
apq8064_init_pmic();
+ if (machine_is_apq8064_liquid())
+ msm_otg_pdata.mhl_enable = true;
apq8064_device_otg.dev.platform_data = &msm_otg_pdata;
+ apq8064_device_hsic_host.dev.platform_data = &msm_hsic_pdata;
apq8064_init_buses();
platform_add_devices(common_devices, ARRAY_SIZE(common_devices));
+ apq8064_pm8xxx_gpio_mpp_init();
apq8064_init_mmc();
slim_register_board_info(apq8064_slim_devices,
ARRAY_SIZE(apq8064_slim_devices));
@@ -1195,6 +1239,10 @@
msm_pm_data);
BUG_ON(msm_pm_boot_init(&msm_pm_boot_pdata));
+ if (machine_is_apq8064_mtp()) {
+ mdm_8064_device.dev.platform_data = &mdm_platform_data;
+ platform_device_register(&mdm_8064_device);
+ }
}
static void __init apq8064_allocate_memory_regions(void)
diff --git a/arch/arm/mach-msm/board-8064.h b/arch/arm/mach-msm/board-8064.h
index 4735504..e1451f5 100644
--- a/arch/arm/mach-msm/board-8064.h
+++ b/arch/arm/mach-msm/board-8064.h
@@ -13,9 +13,12 @@
#ifndef __ARCH_ARM_MACH_MSM_BOARD_APQ8064_H
#define __ARCH_ARM_MACH_MSM_BOARD_APQ8064_H
+#include <linux/regulator/gpio-regulator.h>
#include <linux/mfd/pm8xxx/pm8921.h>
#include <linux/mfd/pm8xxx/pm8821.h>
#include <mach/msm_memtypes.h>
+#include <mach/irqs.h>
+
/* Macros assume PMIC GPIOs and MPPs start at 1 */
#define PM8921_GPIO_BASE NR_GPIO_IRQS
#define PM8921_GPIO_PM_TO_SYS(pm_gpio) (pm_gpio - 1 + PM8921_GPIO_BASE)
@@ -32,6 +35,14 @@
extern int msm8064_pm8921_regulator_pdata_len __devinitdata;
+#define GPIO_VREG_ID_EXT_5V 0
+#define GPIO_VREG_ID_EXT_3P3V 1
+
+#define APQ8064_EXT_3P3V_REG_EN_GPIO 77
+
+extern struct gpio_regulator_platform_data
+ apq8064_gpio_regulator_pdata[] __devinitdata;
+
extern struct regulator_init_data msm8064_saw_regulator_pdata_8921_s5;
extern struct regulator_init_data msm8064_saw_regulator_pdata_8921_s6;
extern struct regulator_init_data msm8064_saw_regulator_pdata_8821_s0;
@@ -54,5 +65,6 @@
void apq8064_mdp_writeback(struct memtype_reserve *reserve_table);
void apq8064_init_gpu(void);
+void apq8064_pm8xxx_gpio_mpp_init(void);
#endif
diff --git a/arch/arm/mach-msm/board-8930.c b/arch/arm/mach-msm/board-8930.c
index f080d50..3858e63 100644
--- a/arch/arm/mach-msm/board-8930.c
+++ b/arch/arm/mach-msm/board-8930.c
@@ -81,7 +81,7 @@
#include "devices.h"
#include "devices-msm8x60.h"
#include "spm.h"
-#include <mach/pm.h>
+#include "pm.h"
#include <mach/cpuidle.h>
#include "rpm_resources.h"
#include "mpm.h"
diff --git a/arch/arm/mach-msm/board-8960.c b/arch/arm/mach-msm/board-8960.c
index 075f358..9985b32 100644
--- a/arch/arm/mach-msm/board-8960.c
+++ b/arch/arm/mach-msm/board-8960.c
@@ -87,7 +87,7 @@
#include "devices-msm8x60.h"
#include "spm.h"
#include "board-8960.h"
-#include <mach/pm.h>
+#include "pm.h"
#include <mach/cpuidle.h>
#include "rpm_resources.h"
#include "mpm.h"
diff --git a/arch/arm/mach-msm/board-9615.c b/arch/arm/mach-msm/board-9615.c
index 9c0a80e..84a8a42 100644
--- a/arch/arm/mach-msm/board-9615.c
+++ b/arch/arm/mach-msm/board-9615.c
@@ -35,7 +35,7 @@
#include "devices.h"
#include "board-9615.h"
#include <mach/cpuidle.h>
-#include <mach/pm.h>
+#include "pm.h"
#include "acpuclock.h"
#include "pm-boot.h"
diff --git a/arch/arm/mach-msm/board-fsm9xxx.c b/arch/arm/mach-msm/board-fsm9xxx.c
index 36ab719..87fea3f 100644
--- a/arch/arm/mach-msm/board-fsm9xxx.c
+++ b/arch/arm/mach-msm/board-fsm9xxx.c
@@ -38,7 +38,7 @@
#include "devices.h"
#include "timer.h"
#include "acpuclock.h"
-#include <mach/pm.h>
+#include "pm.h"
#include "spm.h"
#include <linux/regulator/consumer.h>
#include <linux/regulator/machine.h>
diff --git a/arch/arm/mach-msm/board-msm7x27.c b/arch/arm/mach-msm/board-msm7x27.c
index 5c189fe..8eb92a4 100644
--- a/arch/arm/mach-msm/board-msm7x27.c
+++ b/arch/arm/mach-msm/board-msm7x27.c
@@ -68,7 +68,7 @@
#include "clock.h"
#include "acpuclock.h"
#include "msm-keypad-devices.h"
-#include <mach/pm.h>
+#include "pm.h"
#include "pm-boot.h"
#ifdef CONFIG_ARCH_MSM7X25
diff --git a/arch/arm/mach-msm/board-msm7x27a.c b/arch/arm/mach-msm/board-msm7x27a.c
index 0437134..d2add18 100644
--- a/arch/arm/mach-msm/board-msm7x27a.c
+++ b/arch/arm/mach-msm/board-msm7x27a.c
@@ -50,7 +50,7 @@
#include "timer.h"
#include "board-msm7x27a-regulator.h"
#include "devices-msm7x2xa.h"
-#include <mach/pm.h>
+#include "pm.h"
#include <mach/rpc_server_handset.h>
#include <mach/socinfo.h>
#include "pm-boot.h"
diff --git a/arch/arm/mach-msm/board-msm7x30.c b/arch/arm/mach-msm/board-msm7x30.c
index 3e7b7f4..e0b3c49 100644
--- a/arch/arm/mach-msm/board-msm7x30.c
+++ b/arch/arm/mach-msm/board-msm7x30.c
@@ -78,7 +78,7 @@
#include <linux/usb/android.h>
#include <mach/usbdiag.h>
#endif
-#include <mach/pm.h>
+#include "pm.h"
#include "pm-boot.h"
#include "spm.h"
#include "acpuclock.h"
diff --git a/arch/arm/mach-msm/board-msm8x60.c b/arch/arm/mach-msm/board-msm8x60.c
index 5cb022e..29f5fac 100644
--- a/arch/arm/mach-msm/board-msm8x60.c
+++ b/arch/arm/mach-msm/board-msm8x60.c
@@ -89,7 +89,7 @@
#include "devices.h"
#include "devices-msm8x60.h"
#include <mach/cpuidle.h>
-#include <mach/pm.h>
+#include "pm.h"
#include "mpm.h"
#include "spm.h"
#include "rpm_log.h"
diff --git a/arch/arm/mach-msm/board-qrd7627a.c b/arch/arm/mach-msm/board-qrd7627a.c
index 5052bb0..1222b67 100644
--- a/arch/arm/mach-msm/board-qrd7627a.c
+++ b/arch/arm/mach-msm/board-qrd7627a.c
@@ -49,7 +49,7 @@
#include "board-msm7x27a-regulator.h"
#include "devices.h"
#include "devices-msm7x2xa.h"
-#include <mach/pm.h>
+#include "pm.h"
#include "timer.h"
#include "pm-boot.h"
#include "board-msm7x27a-regulator.h"
diff --git a/arch/arm/mach-msm/board-qsd8x50.c b/arch/arm/mach-msm/board-qsd8x50.c
index 65aaa9a..5a77333 100644
--- a/arch/arm/mach-msm/board-qsd8x50.c
+++ b/arch/arm/mach-msm/board-qsd8x50.c
@@ -54,7 +54,7 @@
#include "timer.h"
#include "msm-keypad-devices.h"
#include "acpuclock.h"
-#include <mach/pm.h>
+#include "pm.h"
#include "pm-boot.h"
#include "proc_comm.h"
#ifdef CONFIG_USB_ANDROID
diff --git a/arch/arm/mach-msm/clock-8960.c b/arch/arm/mach-msm/clock-8960.c
index eb3cb13..47e51a3 100644
--- a/arch/arm/mach-msm/clock-8960.c
+++ b/arch/arm/mach-msm/clock-8960.c
@@ -69,6 +69,7 @@
#define PDM_CLK_NS_REG REG(0x2CC0)
/* 8064 name BB_PLL_ENA_APCS_REG */
#define BB_PLL_ENA_SC0_REG REG(0x34C0)
+#define BB_PLL_ENA_RPM_REG REG(0x34A0)
#define BB_PLL0_STATUS_REG REG(0x30D8)
#define BB_PLL5_STATUS_REG REG(0x30F8)
#define BB_PLL6_STATUS_REG REG(0x3118)
@@ -364,6 +365,7 @@
#define PLL_RATE(l, m, n, v, d, i) { l, m, n, v, (d>>1), i }
static int rpm_vreg_id_vdd_dig;
+static int rpm_vreg_id_vdd_sr2_pll;
enum vdd_dig_levels {
VDD_DIG_NONE,
@@ -399,16 +401,16 @@
.fmax[VDD_DIG_##l2] = (f2), \
.fmax[VDD_DIG_##l3] = (f3)
-enum vdd_l23_levels {
- VDD_L23_OFF,
- VDD_L23_ON
+enum vdd_sr2_pll_levels {
+ VDD_SR2_PLL_OFF,
+ VDD_SR2_PLL_ON
};
-static int set_vdd_l23(struct clk_vdd_class *vdd_class, int level)
+static int set_vdd_sr2_pll(struct clk_vdd_class *vdd_class, int level)
{
int rc = 0;
if (cpu_is_msm8960()) {
- if (level == VDD_L23_OFF) {
+ if (level == VDD_SR2_PLL_OFF) {
rc = rpm_vreg_set_voltage(RPM_VREG_ID_PM8921_L23,
RPM_VREG_VOTER3, 0, 0, 1);
if (rc)
@@ -429,14 +431,14 @@
rpm_vreg_set_voltage(RPM_VREG_ID_PM8921_S8,
RPM_VREG_VOTER3, 0, 0, 1);
}
- } else if (cpu_is_msm8930() || cpu_is_msm8627()) {
- if (level == VDD_L23_OFF) {
- rc = rpm_vreg_set_voltage(RPM_VREG_ID_PM8038_L23,
+ } else {
+ if (level == VDD_SR2_PLL_OFF) {
+ rc = rpm_vreg_set_voltage(rpm_vreg_id_vdd_sr2_pll,
RPM_VREG_VOTER3, 0, 0, 1);
if (rc)
return rc;
} else {
- rc = rpm_vreg_set_voltage(RPM_VREG_ID_PM8038_L23,
+ rc = rpm_vreg_set_voltage(rpm_vreg_id_vdd_sr2_pll,
RPM_VREG_VOTER3, 1800000, 1800000, 1);
if (rc)
return rc;
@@ -446,7 +448,7 @@
return rc;
}
-static DEFINE_VDD_CLASS(vdd_l23, set_vdd_l23);
+static DEFINE_VDD_CLASS(vdd_sr2_pll, set_vdd_sr2_pll);
/*
* Clock Descriptions
@@ -524,8 +526,8 @@
.c = {
.dbg_name = "pll3_clk",
.ops = &clk_ops_pll,
- .vdd_class = &vdd_l23,
- .fmax[VDD_L23_ON] = ULONG_MAX,
+ .vdd_class = &vdd_sr2_pll,
+ .fmax[VDD_SR2_PLL_ON] = ULONG_MAX,
CLK_INIT(pll3_clk.c),
},
};
@@ -3323,37 +3325,12 @@
F_GFX3D(200000000, pll2, 1, 4),
F_GFX3D(228571000, pll2, 2, 7),
F_GFX3D(266667000, pll2, 1, 3),
- F_GFX3D(320000000, pll2, 2, 5),
- F_END
-};
-
-static struct clk_freq_tbl clk_tbl_gfx3d_8960_v2[] = {
- F_GFX3D( 0, gnd, 0, 0),
- F_GFX3D( 27000000, pxo, 0, 0),
- F_GFX3D( 48000000, pll8, 1, 8),
- F_GFX3D( 54857000, pll8, 1, 7),
- F_GFX3D( 64000000, pll8, 1, 6),
- F_GFX3D( 76800000, pll8, 1, 5),
- F_GFX3D( 96000000, pll8, 1, 4),
- F_GFX3D(128000000, pll8, 1, 3),
- F_GFX3D(145455000, pll2, 2, 11),
- F_GFX3D(160000000, pll2, 1, 5),
- F_GFX3D(177778000, pll2, 2, 9),
- F_GFX3D(200000000, pll2, 1, 4),
- F_GFX3D(228571000, pll2, 2, 7),
- F_GFX3D(266667000, pll2, 1, 3),
F_GFX3D(300000000, pll3, 1, 4),
F_GFX3D(320000000, pll2, 2, 5),
F_GFX3D(400000000, pll2, 1, 2),
F_END
};
-static unsigned long fmax_gfx3d_8960_v2[MAX_VDD_LEVELS] __initdata = {
- [VDD_DIG_LOW] = 128000000,
- [VDD_DIG_NOMINAL] = 300000000,
- [VDD_DIG_HIGH] = 400000000
-};
-
static struct clk_freq_tbl clk_tbl_gfx3d_8064[] = {
F_GFX3D( 0, gnd, 0, 0),
F_GFX3D( 27000000, pxo, 0, 0),
@@ -3418,8 +3395,8 @@
.c = {
.dbg_name = "gfx3d_clk",
.ops = &clk_ops_rcg_8960,
- VDD_DIG_FMAX_MAP3(LOW, 128000000, NOMINAL, 266667000,
- HIGH, 320000000),
+ VDD_DIG_FMAX_MAP3(LOW, 128000000, NOMINAL, 300000000,
+ HIGH, 400000000),
CLK_INIT(gfx3d_clk.c),
.depends = &gmem_axi_clk.c,
},
@@ -3528,12 +3505,6 @@
F_END
};
-static unsigned long fmax_ijpeg_8960_v2[MAX_VDD_LEVELS] __initdata = {
- [VDD_DIG_LOW] = 110000000,
- [VDD_DIG_NOMINAL] = 266667000,
- [VDD_DIG_HIGH] = 320000000
-};
-
static unsigned long fmax_ijpeg_8064[MAX_VDD_LEVELS] __initdata = {
[VDD_DIG_LOW] = 128000000,
[VDD_DIG_NOMINAL] = 266667000,
@@ -3562,7 +3533,8 @@
.c = {
.dbg_name = "ijpeg_clk",
.ops = &clk_ops_rcg_8960,
- VDD_DIG_FMAX_MAP2(LOW, 110000000, NOMINAL, 266667000),
+ VDD_DIG_FMAX_MAP3(LOW, 110000000, NOMINAL, 266667000,
+ HIGH, 320000000),
CLK_INIT(ijpeg_clk.c),
.depends = &ijpeg_axi_clk.c,
},
@@ -4139,12 +4111,6 @@
F_END
};
-static unsigned long fmax_vfe_8960_v2[MAX_VDD_LEVELS] __initdata = {
- [VDD_DIG_LOW] = 110000000,
- [VDD_DIG_NOMINAL] = 266667000,
- [VDD_DIG_HIGH] = 320000000
-};
-
static unsigned long fmax_vfe_8064[MAX_VDD_LEVELS] __initdata = {
[VDD_DIG_LOW] = 128000000,
[VDD_DIG_NOMINAL] = 266667000,
@@ -4173,7 +4139,8 @@
.c = {
.dbg_name = "vfe_clk",
.ops = &clk_ops_rcg_8960,
- VDD_DIG_FMAX_MAP2(LOW, 110000000, NOMINAL, 266667000),
+ VDD_DIG_FMAX_MAP3(LOW, 110000000, NOMINAL, 266667000,
+ HIGH, 320000000),
CLK_INIT(vfe_clk.c),
.depends = &vfe_axi_clk.c,
},
@@ -4475,6 +4442,8 @@
static DEFINE_CLK_MEASURE(l2_m_clk);
static DEFINE_CLK_MEASURE(krait0_m_clk);
static DEFINE_CLK_MEASURE(krait1_m_clk);
+static DEFINE_CLK_MEASURE(krait2_m_clk);
+static DEFINE_CLK_MEASURE(krait3_m_clk);
static DEFINE_CLK_MEASURE(q6sw_clk);
static DEFINE_CLK_MEASURE(q6fw_clk);
static DEFINE_CLK_MEASURE(q6_func_clk);
@@ -4661,8 +4630,8 @@
{ TEST_MM_HS(0x32), &csi_rdi2_clk.c },
{ TEST_MM_HS(0x33), &vcap_clk.c },
{ TEST_MM_HS(0x34), &vcap_npl_clk.c },
- { TEST_MM_HS(0x36), &vcap_axi_clk.c },
- { TEST_MM_HS(0x39), &gfx3d_axi_clk.c },
+ { TEST_MM_HS(0x35), &vcap_axi_clk.c },
+ { TEST_MM_HS(0x38), &gfx3d_axi_clk.c },
{ TEST_LPA(0x0F), &mi2s_bit_clk.c },
{ TEST_LPA(0x10), &codec_i2s_mic_bit_clk.c },
@@ -4677,6 +4646,8 @@
{ TEST_CPUL2(0x2), &l2_m_clk },
{ TEST_CPUL2(0x0), &krait0_m_clk },
{ TEST_CPUL2(0x1), &krait1_m_clk },
+ { TEST_CPUL2(0x4), &krait2_m_clk },
+ { TEST_CPUL2(0x5), &krait3_m_clk },
};
static struct measure_sel *find_measure_sel(struct clk *clk)
@@ -4869,6 +4840,7 @@
CLK_LOOKUP("xo", pxo_clk.c, "pil_qdsp6v4.0"),
CLK_LOOKUP("xo", cxo_clk.c, "pil_qdsp6v4.1"),
CLK_LOOKUP("xo", cxo_clk.c, "pil_qdsp6v4.2"),
+ CLK_LOOKUP("xo", cxo_clk.c, "pil_gss"),
CLK_LOOKUP("pll2", pll2_clk.c, NULL),
CLK_LOOKUP("pll8", pll8_clk.c, NULL),
CLK_LOOKUP("pll4", pll4_clk.c, NULL),
@@ -4896,7 +4868,7 @@
CLK_LOOKUP("core_clk", gp0_clk.c, ""),
CLK_LOOKUP("core_clk", gp1_clk.c, ""),
CLK_LOOKUP("core_clk", gp2_clk.c, ""),
- CLK_LOOKUP("core_clk", gsbi1_uart_clk.c, ""),
+ CLK_LOOKUP("core_clk", gsbi1_uart_clk.c, "msm_serial_hsl.0"),
CLK_LOOKUP("core_clk", gsbi2_uart_clk.c, ""),
CLK_LOOKUP("core_clk", gsbi3_uart_clk.c, ""),
CLK_LOOKUP("core_clk", gsbi4_uart_clk.c, ""),
@@ -4907,11 +4879,11 @@
CLK_LOOKUP("core_clk", gsbi2_qup_clk.c, ""),
CLK_LOOKUP("core_clk", gsbi3_qup_clk.c, ""),
CLK_LOOKUP("core_clk", gsbi4_qup_clk.c, ""),
- CLK_LOOKUP("core_clk", gsbi5_qup_clk.c, ""),
+ CLK_LOOKUP("core_clk", gsbi5_qup_clk.c, "spi_qsd.0"),
CLK_LOOKUP("core_clk", gsbi6_qup_clk.c, ""),
CLK_LOOKUP("core_clk", gsbi7_qup_clk.c, ""),
CLK_LOOKUP("core_clk", pdm_clk.c, ""),
- CLK_LOOKUP("pmem_clk", pmem_clk.c, NULL),
+ CLK_LOOKUP("mem_clk", pmem_clk.c, "msm_sps"),
CLK_DUMMY("core_clk", PRNG_CLK, "msm_rng.0", OFF),
CLK_LOOKUP("core_clk", sdc1_clk.c, "msm_sdcc.1"),
CLK_LOOKUP("core_clk", sdc2_clk.c, "msm_sdcc.2"),
@@ -4936,11 +4908,11 @@
CLK_LOOKUP("ce3_core_src_clk", ce3_src_clk.c, "qce.0"),
CLK_LOOKUP("ce3_core_src_clk", ce3_src_clk.c, "qcrypto.0"),
CLK_LOOKUP("dma_bam_pclk", dma_bam_p_clk.c, NULL),
- CLK_LOOKUP("iface_clk", gsbi1_p_clk.c, ""),
+ CLK_LOOKUP("iface_clk", gsbi1_p_clk.c, "msm_serial_hsl.0"),
CLK_LOOKUP("iface_clk", gsbi2_p_clk.c, ""),
CLK_LOOKUP("iface_clk", gsbi3_p_clk.c, ""),
CLK_LOOKUP("iface_clk", gsbi4_p_clk.c, ""),
- CLK_LOOKUP("iface_clk", gsbi5_p_clk.c, ""),
+ CLK_LOOKUP("iface_clk", gsbi5_p_clk.c, "spi_qsd.0"),
CLK_LOOKUP("iface_clk", gsbi6_p_clk.c, ""),
CLK_LOOKUP("iface_clk", gsbi7_p_clk.c, ""),
CLK_LOOKUP("iface_clk", tsif_p_clk.c, ""),
@@ -5049,7 +5021,7 @@
CLK_LOOKUP("mem_iface_clk", imem_p_clk.c, "kgsl-3d0.0"),
CLK_LOOKUP("mdp_pclk", mdp_p_clk.c, ""),
CLK_LOOKUP("iface_clk", mdp_p_clk.c, "footswitch-8x60.4"),
- CLK_LOOKUP("iface_clk", smmu_p_clk.c, ""),
+ CLK_LOOKUP("iface_clk", smmu_p_clk.c, "msm_iommu"),
CLK_LOOKUP("iface_clk", rot_p_clk.c, "msm_rotator.0"),
CLK_LOOKUP("iface_clk", rot_p_clk.c, "footswitch-8x60.6"),
CLK_LOOKUP("iface_clk", vcodec_p_clk.c, "msm_vidc.0"),
@@ -5070,7 +5042,7 @@
CLK_LOOKUP("i2s_spkr_osr_clk", spare_i2s_spkr_osr_clk.c, ""),
CLK_LOOKUP("pcm_clk", pcm_clk.c, ""),
CLK_LOOKUP("sps_slimbus_clk", sps_slimbus_clk.c, ""),
- CLK_LOOKUP("audio_slimbus_clk", audio_slimbus_clk.c, ""),
+ CLK_LOOKUP("audio_slimbus_clk", audio_slimbus_clk.c, NULL),
CLK_LOOKUP("core_clk", jpegd_axi_clk.c, ""),
CLK_LOOKUP("core_clk", vpe_axi_clk.c, ""),
CLK_LOOKUP("core_clk", mdp_axi_clk.c, ""),
@@ -5097,14 +5069,29 @@
CLK_LOOKUP("core_clk", usb_hsic_system_clk.c, "msm_hsic_host"),
CLK_LOOKUP("iface_clk", usb_hsic_p_clk.c, "msm_hsic_host"),
+ CLK_LOOKUP("core_clk", jpegd_axi_clk.c, "msm_iommu.0"),
+ CLK_LOOKUP("core_clk", vpe_axi_clk.c, "msm_iommu.1"),
+ CLK_LOOKUP("core_clk", mdp_axi_clk.c, "msm_iommu.2"),
+ CLK_LOOKUP("core_clk", mdp_axi_clk.c, "msm_iommu.3"),
+ CLK_LOOKUP("core_clk", rot_axi_clk.c, "msm_iommu.4"),
+ CLK_LOOKUP("core_clk", ijpeg_axi_clk.c, "msm_iommu.5"),
+ CLK_LOOKUP("core_clk", vfe_axi_clk.c, "msm_iommu.6"),
+ CLK_LOOKUP("core_clk", vcodec_axi_a_clk.c, "msm_iommu.7"),
+ CLK_LOOKUP("core_clk", vcodec_axi_b_clk.c, "msm_iommu.8"),
+ CLK_LOOKUP("core_clk", gfx3d_axi_clk.c, "msm_iommu.9"),
+ CLK_LOOKUP("core_clk", gfx3d_axi_clk.c, "msm_iommu.10"),
+ CLK_LOOKUP("core_clk", vcap_axi_clk.c, "msm_iommu.11"),
+
CLK_LOOKUP("mem_clk", ebi1_adm_clk.c, "msm_dmov"),
CLK_LOOKUP("l2_mclk", l2_m_clk, ""),
CLK_LOOKUP("krait0_mclk", krait0_m_clk, ""),
CLK_LOOKUP("krait1_mclk", krait1_m_clk, ""),
+ CLK_LOOKUP("krait2_mclk", krait2_m_clk, ""),
+ CLK_LOOKUP("krait3_mclk", krait3_m_clk, ""),
};
-static struct clk_lookup msm_clocks_8960_v1[] __initdata = {
+static struct clk_lookup msm_clocks_8960[] = {
CLK_LOOKUP("xo", cxo_clk.c, "msm_otg"),
CLK_LOOKUP("cxo", cxo_clk.c, "wcnss_wlan.0"),
CLK_LOOKUP("cxo", cxo_clk.c, "pil_riva"),
@@ -5182,6 +5169,11 @@
CLK_LOOKUP("alt_core_clk", usb_fs2_xcvr_clk.c, ""),
CLK_LOOKUP("sys_clk", usb_fs2_sys_clk.c, ""),
CLK_LOOKUP("src_clk", usb_fs2_src_clk.c, ""),
+ CLK_LOOKUP("alt_core_clk", usb_hsic_xcvr_fs_clk.c, "msm_hsic_host"),
+ CLK_LOOKUP("phy_clk", usb_hsic_hsic_clk.c, "msm_hsic_host"),
+ CLK_LOOKUP("cal_clk", usb_hsic_hsio_cal_clk.c, "msm_hsic_host"),
+ CLK_LOOKUP("core_clk", usb_hsic_system_clk.c, "msm_hsic_host"),
+ CLK_LOOKUP("iface_clk", usb_hsic_p_clk.c, "msm_hsic_host"),
CLK_LOOKUP("iface_clk", ce1_p_clk.c, "qce.0"),
CLK_LOOKUP("iface_clk", ce1_p_clk.c, "qcrypto.0"),
CLK_LOOKUP("core_clk", ce1_core_clk.c, "qce.0"),
@@ -5218,6 +5210,7 @@
CLK_LOOKUP("cam_clk", cam0_clk.c, "4-001a"),
CLK_LOOKUP("cam_clk", cam0_clk.c, "4-006c"),
CLK_LOOKUP("cam_clk", cam0_clk.c, "4-0048"),
+ CLK_LOOKUP("cam_clk", cam2_clk.c, NULL),
CLK_LOOKUP("csi_src_clk", csi0_src_clk.c, "msm_csid.0"),
CLK_LOOKUP("csi_src_clk", csi1_src_clk.c, "msm_csid.1"),
CLK_LOOKUP("csi_clk", csi0_clk.c, "msm_csid.0"),
@@ -5226,6 +5219,13 @@
CLK_LOOKUP("csi_phy_clk", csi1_phy_clk.c, "msm_csid.1"),
CLK_LOOKUP("csi_pix_clk", csi_pix_clk.c, "msm_ispif.0"),
CLK_LOOKUP("csi_rdi_clk", csi_rdi_clk.c, "msm_ispif.0"),
+ CLK_LOOKUP("csi_src_clk", csi2_src_clk.c, NULL),
+ CLK_LOOKUP("csi_clk", csi2_clk.c, NULL),
+ CLK_LOOKUP("csi_pix1_clk", csi_pix1_clk.c, "msm_ispif.0"),
+ CLK_LOOKUP("csi_rdi1_clk", csi_rdi1_clk.c, "msm_ispif.0"),
+ CLK_LOOKUP("csi_rdi2_clk", csi_rdi2_clk.c, "msm_ispif.0"),
+ CLK_LOOKUP("csi_phy_clk", csi2_phy_clk.c, NULL),
+ CLK_LOOKUP("csi2phy_timer_clk", csi2phy_timer_clk.c, NULL),
CLK_LOOKUP("csiphy_timer_src_clk",
csiphy_timer_src_clk.c, "msm_csiphy.0"),
CLK_LOOKUP("csiphy_timer_src_clk",
@@ -5361,26 +5361,6 @@
CLK_LOOKUP("q6_func_clk", q6_func_clk, ""),
};
-static struct clk_lookup msm_clocks_8960_v2[] __initdata = {
- CLK_LOOKUP("cam_clk", cam2_clk.c, NULL),
- CLK_LOOKUP("csi_src_clk", csi2_src_clk.c, NULL),
- CLK_LOOKUP("csi_clk", csi2_clk.c, NULL),
- CLK_LOOKUP("csi_pix1_clk", csi_pix1_clk.c, "msm_ispif.0"),
- CLK_LOOKUP("csi_rdi1_clk", csi_rdi1_clk.c, "msm_ispif.0"),
- CLK_LOOKUP("csi_rdi2_clk", csi_rdi2_clk.c, "msm_ispif.0"),
- CLK_LOOKUP("csi_phy_clk", csi2_phy_clk.c, NULL),
- CLK_LOOKUP("csi2phy_timer_clk", csi2phy_timer_clk.c, NULL),
- CLK_LOOKUP("alt_core_clk", usb_hsic_xcvr_fs_clk.c, "msm_hsic_host"),
- CLK_LOOKUP("phy_clk", usb_hsic_hsic_clk.c, "msm_hsic_host"),
- CLK_LOOKUP("cal_clk", usb_hsic_hsio_cal_clk.c, "msm_hsic_host"),
- CLK_LOOKUP("core_clk", usb_hsic_system_clk.c, "msm_hsic_host"),
- CLK_LOOKUP("iface_clk", usb_hsic_p_clk.c, "msm_hsic_host"),
-};
-
-/* Add v2 clocks dynamically at runtime */
-static struct clk_lookup msm_clocks_8960[ARRAY_SIZE(msm_clocks_8960_v1) +
- ARRAY_SIZE(msm_clocks_8960_v2)];
-
/*
* Miscellaneous clock register initializations
*/
@@ -5430,13 +5410,12 @@
*/
/*
* Initialize MM AHB registers: Enable the FPB clock and disable HW
- * gating on 8960v1/8064 for all clocks. Also set VFE_AHB's
+ * gating on non-8960 for all clocks. Also set VFE_AHB's
* FORCE_CORE_ON bit to prevent its memory from being collapsed when
* the clock is halted. The sleep and wake-up delays are set to safe
* values.
*/
- if (cpu_is_msm8960() &&
- SOCINFO_VERSION_MAJOR(socinfo_get_version()) >= 2) {
+ if (cpu_is_msm8960()) {
rmwreg(0x44000000, AHB_EN_REG, 0x6C000103);
writel_relaxed(0x3C7097F9, AHB_EN2_REG);
} else {
@@ -5466,8 +5445,7 @@
rmwreg(0x0027FCFF, MAXI_EN3_REG, 0x003FFFFF);
if (cpu_is_apq8064())
rmwreg(0x009FE4FF, MAXI_EN5_REG, 0x01FFEFFF);
- if (cpu_is_msm8960() &&
- SOCINFO_VERSION_MAJOR(socinfo_get_version()) >= 2)
+ if (cpu_is_msm8960())
rmwreg(0x00003C38, SAXI_EN_REG, 0x00003FFF);
else
rmwreg(0x000003C7, SAXI_EN_REG, 0x00003FFF);
@@ -5593,6 +5571,11 @@
writel_relaxed(regval, BB_PLL8_TEST_CTL_REG);
set_fsm_mode(BB_PLL8_MODE_REG);
+
+ /* Enable PLL8 by voting from RPM */
+ regval = readl_relaxed(BB_PLL_ENA_RPM_REG);
+ regval |= BIT(8);
+ writel_relaxed(regval, BB_PLL_ENA_RPM_REG);
}
/* Check if PLL3 is active */
is_pll_enabled = readl_relaxed(GPLL1_STATUS_REG) & BIT(16);
@@ -5709,19 +5692,21 @@
}
}
-struct clock_init_data msm8960_clock_init_data __initdata;
-
/* Local clock driver initialization. */
static void __init msm8960_clock_init(void)
{
- size_t num_lookups = ARRAY_SIZE(msm_clocks_8960_v1);
- if (cpu_is_msm8960() || cpu_is_apq8064())
+ if (cpu_is_msm8960()) {
rpm_vreg_id_vdd_dig = RPM_VREG_ID_PM8921_S3;
- else if (cpu_is_msm8930() || cpu_is_msm8627())
+ } else if (cpu_is_apq8064()) {
+ rpm_vreg_id_vdd_dig = RPM_VREG_ID_PM8921_S3;
+ rpm_vreg_id_vdd_sr2_pll = RPM_VREG_ID_PM8921_LVS7;
+ } else if (cpu_is_msm8930() || cpu_is_msm8627()) {
rpm_vreg_id_vdd_dig = RPM_VREG_ID_PM8038_S1;
- else
+ rpm_vreg_id_vdd_sr2_pll = RPM_VREG_ID_PM8038_L23;
+ } else {
BUG();
+ }
xo_pxo = msm_xo_get(MSM_XO_PXO, "clock-8960");
if (IS_ERR(xo_pxo)) {
@@ -5734,26 +5719,6 @@
BUG();
}
- if (cpu_is_msm8960() || cpu_is_msm8930()) {
- memcpy(msm_clocks_8960, msm_clocks_8960_v1,
- sizeof(msm_clocks_8960_v1));
- if (SOCINFO_VERSION_MAJOR(socinfo_get_version()) >= 2) {
- gfx3d_clk.freq_tbl = clk_tbl_gfx3d_8960_v2;
-
- memcpy(gfx3d_clk.c.fmax, fmax_gfx3d_8960_v2,
- sizeof(gfx3d_clk.c.fmax));
- memcpy(ijpeg_clk.c.fmax, fmax_ijpeg_8960_v2,
- sizeof(ijpeg_clk.c.fmax));
- memcpy(vfe_clk.c.fmax, fmax_vfe_8960_v2,
- sizeof(vfe_clk.c.fmax));
-
- memcpy(msm_clocks_8960 + ARRAY_SIZE(msm_clocks_8960_v1),
- msm_clocks_8960_v2, sizeof(msm_clocks_8960_v2));
- num_lookups = ARRAY_SIZE(msm_clocks_8960);
- }
- msm8960_clock_init_data.size = num_lookups;
- }
-
/*
* Change the freq tables for and voltage requirements for
* clocks which differ between 8960 and 8064.
@@ -5815,13 +5780,8 @@
rcg_clk_disable(&pdm_clk.c);
rcg_clk_enable(&tssc_clk.c);
rcg_clk_disable(&tssc_clk.c);
- if (cpu_is_msm8960() &&
- SOCINFO_VERSION_MAJOR(socinfo_get_version()) >= 2) {
- clk_enable(&usb_hsic_hsic_clk.c);
- clk_disable(&usb_hsic_hsic_clk.c);
- } else
- /* CSI2 hardware not present on 8960v1 devices */
- pix_rdi_mux_map[2] = NULL;
+ clk_enable(&usb_hsic_hsic_clk.c);
+ clk_disable(&usb_hsic_hsic_clk.c);
}
static int __init msm8960_clock_late_init(void)
diff --git a/arch/arm/mach-msm/cpufreq.c b/arch/arm/mach-msm/cpufreq.c
index 9bc8eb3..81d01c2 100644
--- a/arch/arm/mach-msm/cpufreq.c
+++ b/arch/arm/mach-msm/cpufreq.c
@@ -174,6 +174,8 @@
#endif
table = cpufreq_frequency_get_table(policy->cpu);
+ if (table == NULL)
+ return -ENODEV;
if (cpufreq_frequency_table_cpuinfo(policy, table)) {
#ifdef CONFIG_MSM_CPU_FREQ_SET_MIN_MAX
policy->cpuinfo.min_freq = CONFIG_MSM_CPU_FREQ_MIN;
diff --git a/arch/arm/mach-msm/cpuidle.c b/arch/arm/mach-msm/cpuidle.c
index abaa925..cccba2d 100644
--- a/arch/arm/mach-msm/cpuidle.c
+++ b/arch/arm/mach-msm/cpuidle.c
@@ -17,7 +17,8 @@
#include <linux/cpu_pm.h>
#include <mach/cpuidle.h>
-#include <mach/pm.h>
+
+#include "pm.h"
static DEFINE_PER_CPU_SHARED_ALIGNED(struct cpuidle_device, msm_cpuidle_devs);
static struct cpuidle_driver msm_cpuidle_driver = {
diff --git a/arch/arm/mach-msm/devices-8064.c b/arch/arm/mach-msm/devices-8064.c
index f3ef2ce..92bd59b 100644
--- a/arch/arm/mach-msm/devices-8064.c
+++ b/arch/arm/mach-msm/devices-8064.c
@@ -16,6 +16,7 @@
#include <linux/platform_device.h>
#include <linux/msm_rotator.h>
#include <linux/clkdev.h>
+#include <linux/dma-mapping.h>
#include <mach/irqs-8064.h>
#include <mach/board.h>
#include <mach/msm_iomap.h>
@@ -26,6 +27,7 @@
#include <sound/apr_audio.h>
#include <mach/msm_bus_board.h>
#include <mach/rpm.h>
+#include <mach/mdm2.h>
#include "clock.h"
#include "devices.h"
#include "msm_watchdog.h"
@@ -59,8 +61,8 @@
#define MSM_PMIC_SSBI_SIZE SZ_4K
/* Address of HS USBOTG1 */
-#define MSM_HSUSB_PHYS 0x12500000
-#define MSM_HSUSB_SIZE SZ_4K
+#define MSM_HSUSB1_PHYS 0x12500000
+#define MSM_HSUSB1_SIZE SZ_4K
static struct msm_watchdog_pdata msm_watchdog_pdata = {
.pet_time = 10000,
@@ -413,8 +415,8 @@
static struct resource resources_otg[] = {
{
- .start = MSM_HSUSB_PHYS,
- .end = MSM_HSUSB_PHYS + MSM_HSUSB_SIZE - 1,
+ .start = MSM_HSUSB1_PHYS,
+ .end = MSM_HSUSB1_PHYS + MSM_HSUSB1_SIZE - 1,
.flags = IORESOURCE_MEM,
},
{
@@ -436,8 +438,8 @@
static struct resource resources_hsusb[] = {
{
- .start = MSM_HSUSB_PHYS,
- .end = MSM_HSUSB_PHYS + MSM_HSUSB_SIZE - 1,
+ .start = MSM_HSUSB1_PHYS,
+ .end = MSM_HSUSB1_PHYS + MSM_HSUSB1_SIZE - 1,
.flags = IORESOURCE_MEM,
},
{
@@ -457,6 +459,61 @@
},
};
+static struct resource resources_hsusb_host[] = {
+ {
+ .start = MSM_HSUSB1_PHYS,
+ .end = MSM_HSUSB1_PHYS + MSM_HSUSB1_SIZE - 1,
+ .flags = IORESOURCE_MEM,
+ },
+ {
+ .start = USB1_HS_IRQ,
+ .end = USB1_HS_IRQ,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+static struct resource resources_hsic_host[] = {
+ {
+ .start = 0x12510000,
+ .end = 0x12510000 + SZ_4K - 1,
+ .flags = IORESOURCE_MEM,
+ },
+ {
+ .start = USB2_HSIC_IRQ,
+ .end = USB2_HSIC_IRQ,
+ .flags = IORESOURCE_IRQ,
+ },
+ {
+ .start = MSM_GPIO_TO_INT(49),
+ .end = MSM_GPIO_TO_INT(49),
+ .name = "peripheral_status_irq",
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+static u64 dma_mask = DMA_BIT_MASK(32);
+struct platform_device apq8064_device_hsusb_host = {
+ .name = "msm_hsusb_host",
+ .id = -1,
+ .num_resources = ARRAY_SIZE(resources_hsusb_host),
+ .resource = resources_hsusb_host,
+ .dev = {
+ .dma_mask = &dma_mask,
+ .coherent_dma_mask = 0xffffffff,
+ },
+};
+
+struct platform_device apq8064_device_hsic_host = {
+ .name = "msm_hsic_host",
+ .id = -1,
+ .num_resources = ARRAY_SIZE(resources_hsic_host),
+ .resource = resources_hsic_host,
+ .dev = {
+ .dma_mask = &dma_mask,
+ .coherent_dma_mask = DMA_BIT_MASK(32),
+ },
+};
+
#define MSM_SDC1_BASE 0x12400000
#define MSM_SDC1_DML_BASE (MSM_SDC1_BASE + 0x800)
#define MSM_SDC1_BAM_BASE (MSM_SDC1_BASE + 0x2000)
@@ -754,6 +811,21 @@
};
#endif
+static struct resource msm_gss_resources[] = {
+ {
+ .start = 0x10000000,
+ .end = 0x10000000 + SZ_256 - 1,
+ .flags = IORESOURCE_MEM,
+ },
+};
+
+struct platform_device msm_gss = {
+ .name = "pil_gss",
+ .id = -1,
+ .num_resources = ARRAY_SIZE(msm_gss_resources),
+ .resource = msm_gss_resources,
+};
+
static struct clk_lookup msm_clocks_8064_dummy[] = {
CLK_DUMMY("pll2", PLL2, NULL, 0),
CLK_DUMMY("pll8", PLL8, NULL, 0),
@@ -1329,3 +1401,50 @@
};
#endif
+
+#define MDM2AP_ERRFATAL 19
+#define AP2MDM_ERRFATAL 18
+#define MDM2AP_STATUS 49
+#define AP2MDM_STATUS 48
+#define AP2MDM_PMIC_RESET_N 27
+
+static struct resource mdm_resources[] = {
+ {
+ .start = MDM2AP_ERRFATAL,
+ .end = MDM2AP_ERRFATAL,
+ .name = "MDM2AP_ERRFATAL",
+ .flags = IORESOURCE_IO,
+ },
+ {
+ .start = AP2MDM_ERRFATAL,
+ .end = AP2MDM_ERRFATAL,
+ .name = "AP2MDM_ERRFATAL",
+ .flags = IORESOURCE_IO,
+ },
+ {
+ .start = MDM2AP_STATUS,
+ .end = MDM2AP_STATUS,
+ .name = "MDM2AP_STATUS",
+ .flags = IORESOURCE_IO,
+ },
+ {
+ .start = AP2MDM_STATUS,
+ .end = AP2MDM_STATUS,
+ .name = "AP2MDM_STATUS",
+ .flags = IORESOURCE_IO,
+ },
+ {
+ .start = AP2MDM_PMIC_RESET_N,
+ .end = AP2MDM_PMIC_RESET_N,
+ .name = "AP2MDM_PMIC_RESET_N",
+ .flags = IORESOURCE_IO,
+ },
+};
+
+struct platform_device mdm_8064_device = {
+ .name = "mdm2_modem",
+ .id = -1,
+ .num_resources = ARRAY_SIZE(mdm_resources),
+ .resource = mdm_resources,
+};
+
diff --git a/arch/arm/mach-msm/devices-8930.c b/arch/arm/mach-msm/devices-8930.c
index 257f372..c75a4e3 100644
--- a/arch/arm/mach-msm/devices-8930.c
+++ b/arch/arm/mach-msm/devices-8930.c
@@ -39,7 +39,8 @@
MSM_RPM_MAP(8930, NOTIFICATION_CONFIGURED_0, NOTIFICATION, 4),
MSM_RPM_MAP(8930, NOTIFICATION_REGISTERED_0, NOTIFICATION, 4),
MSM_RPM_MAP(8930, INVALIDATE_0, INVALIDATE, 8),
- MSM_RPM_MAP(8930, TRIGGER_TIMED_0, TRIGGER_TIMED_0, 2),
+ MSM_RPM_MAP(8960, TRIGGER_TIMED_TO, TRIGGER_TIMED, 1),
+ MSM_RPM_MAP(8960, TRIGGER_TIMED_SCLK_COUNT, TRIGGER_TIMED, 1),
MSM_RPM_MAP(8930, RPM_CTL, RPM_CTL, 1),
MSM_RPM_MAP(8930, CXO_CLK, CXO_CLK, 1),
MSM_RPM_MAP(8930, PXO_CLK, PXO_CLK, 1),
@@ -57,7 +58,7 @@
APPS_FABRIC_CFG_CLKMOD, 3),
MSM_RPM_MAP(8930, APPS_FABRIC_CFG_IOCTL,
APPS_FABRIC_CFG_IOCTL, 1),
- MSM_RPM_MAP(8930, APPS_FABRIC_ARB_0, APPS_FABRIC_ARB, 6),
+ MSM_RPM_MAP(8930, APPS_FABRIC_ARB_0, APPS_FABRIC_ARB, 12),
MSM_RPM_MAP(8930, SYS_FABRIC_CFG_HALT_0,
SYS_FABRIC_CFG_HALT, 2),
MSM_RPM_MAP(8930, SYS_FABRIC_CFG_CLKMOD_0,
@@ -65,14 +66,14 @@
MSM_RPM_MAP(8930, SYS_FABRIC_CFG_IOCTL,
SYS_FABRIC_CFG_IOCTL, 1),
MSM_RPM_MAP(8930, SYSTEM_FABRIC_ARB_0,
- SYSTEM_FABRIC_ARB, 20),
+ SYSTEM_FABRIC_ARB, 29),
MSM_RPM_MAP(8930, MMSS_FABRIC_CFG_HALT_0,
MMSS_FABRIC_CFG_HALT, 2),
MSM_RPM_MAP(8930, MMSS_FABRIC_CFG_CLKMOD_0,
MMSS_FABRIC_CFG_CLKMOD, 3),
MSM_RPM_MAP(8930, MMSS_FABRIC_CFG_IOCTL,
MMSS_FABRIC_CFG_IOCTL, 1),
- MSM_RPM_MAP(8930, MM_FABRIC_ARB_0, MM_FABRIC_ARB, 11),
+ MSM_RPM_MAP(8930, MM_FABRIC_ARB_0, MM_FABRIC_ARB, 23),
MSM_RPM_MAP(8930, PM8038_S1_0, PM8038_S1, 2),
MSM_RPM_MAP(8930, PM8038_S2_0, PM8038_S2, 2),
MSM_RPM_MAP(8930, PM8038_S3_0, PM8038_S3, 2),
@@ -217,6 +218,7 @@
MSM_RPM_STATUS_ID_MAP(8930, CXO_BUFFERS),
MSM_RPM_STATUS_ID_MAP(8930, USB_OTG_SWITCH),
MSM_RPM_STATUS_ID_MAP(8930, HDMI_SWITCH),
+ MSM_RPM_STATUS_ID_MAP(8930, QDSS_CLK),
},
.target_ctrl_id = {
MSM_RPM_CTRL_MAP(8930, VERSION_MAJOR),
diff --git a/arch/arm/mach-msm/devices-9615.c b/arch/arm/mach-msm/devices-9615.c
index 4fc05ce..1f2256f 100644
--- a/arch/arm/mach-msm/devices-9615.c
+++ b/arch/arm/mach-msm/devices-9615.c
@@ -30,7 +30,7 @@
#include <asm/hardware/cache-l2x0.h>
#include <mach/msm_sps.h>
#include <mach/dma.h>
-#include <mach/pm.h>
+#include "pm.h"
#include "devices.h"
#include "mpm.h"
#include "spm.h"
diff --git a/arch/arm/mach-msm/devices.h b/arch/arm/mach-msm/devices.h
index 5d42f99..9469de8 100644
--- a/arch/arm/mach-msm/devices.h
+++ b/arch/arm/mach-msm/devices.h
@@ -102,6 +102,8 @@
extern struct platform_device apq8064_device_otg;
extern struct platform_device apq8064_usb_diag_device;
extern struct platform_device apq8064_device_gadget_peripheral;
+extern struct platform_device apq8064_device_hsusb_host;
+extern struct platform_device apq8064_device_hsic_host;
extern struct platform_device msm_device_i2c;
@@ -193,6 +195,7 @@
extern struct platform_device msm_8960_q6_mss_fw;
extern struct platform_device msm_8960_q6_mss_sw;
extern struct platform_device msm_8960_riva;
+extern struct platform_device msm_gss;
extern struct platform_device apq_pcm;
extern struct platform_device apq_pcm_routing;
@@ -292,3 +295,5 @@
extern struct platform_device msm_bus_8064_mm_fabric;
extern struct platform_device msm_bus_8064_sys_fpb;
extern struct platform_device msm_bus_8064_cpss_fpb;
+
+extern struct platform_device mdm_8064_device;
diff --git a/arch/arm/mach-msm/hotplug.c b/arch/arm/mach-msm/hotplug.c
index 743e3de..26adec6 100644
--- a/arch/arm/mach-msm/hotplug.c
+++ b/arch/arm/mach-msm/hotplug.c
@@ -1,6 +1,7 @@
/*
* Copyright (C) 2002 ARM Ltd.
* All Rights Reserved
+ * Copyright (c) 2011-2012, 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 as
@@ -13,8 +14,7 @@
#include <asm/cacheflush.h>
#include <asm/vfp.h>
-#include <mach/pm.h>
-
+#include "pm.h"
#include "qdss.h"
#include "spm.h"
@@ -68,8 +68,13 @@
{
struct completion *killed =
&per_cpu(msm_hotplug_devices, cpu).cpu_killed;
+ int ret;
- return wait_for_completion_timeout(killed, HZ * 5);
+ ret = wait_for_completion_timeout(killed, HZ * 5);
+ if (ret)
+ return ret;
+
+ return msm_pm_wait_cpu_shutdown(cpu);
}
/*
diff --git a/arch/arm/mach-msm/include/mach/cpuidle.h b/arch/arm/mach-msm/include/mach/cpuidle.h
index b0aa902..37b8d00 100644
--- a/arch/arm/mach-msm/include/mach/cpuidle.h
+++ b/arch/arm/mach-msm/include/mach/cpuidle.h
@@ -15,7 +15,7 @@
#define __ARCH_ARM_MACH_MSM_CPUIDLE_H
#include <linux/notifier.h>
-#include <mach/pm.h>
+#include "pm.h"
struct msm_cpuidle_state {
unsigned int cpu;
diff --git a/arch/arm/mach-msm/include/mach/irqs-8064.h b/arch/arm/mach-msm/include/mach/irqs-8064.h
index 8597111..a5f78f5 100644
--- a/arch/arm/mach-msm/include/mach/irqs-8064.h
+++ b/arch/arm/mach-msm/include/mach/irqs-8064.h
@@ -57,7 +57,7 @@
#define TLMM_MSM_DIR_CONN_IRQ_8 (GIC_SPI_START + 12)
#define TLMM_MSM_DIR_CONN_IRQ_9 (GIC_SPI_START + 13)
#define PM8921_SEC_IRQ_N (GIC_SPI_START + 14)
-#define PM8018_SEC_IRQ_N (GIC_SPI_START + 15)
+#define PM8821_SEC_IRQ_N (GIC_SPI_START + 15)
#define TLMM_MSM_SUMMARY_IRQ (GIC_SPI_START + 16)
#define SPDM_RT_1_IRQ (GIC_SPI_START + 17)
#define SPDM_DIAG_IRQ (GIC_SPI_START + 18)
diff --git a/arch/arm/mach-msm/include/mach/mdm2.h b/arch/arm/mach-msm/include/mach/mdm2.h
index acfa38a..78ca88f 100644
--- a/arch/arm/mach-msm/include/mach/mdm2.h
+++ b/arch/arm/mach-msm/include/mach/mdm2.h
@@ -15,6 +15,8 @@
struct mdm_platform_data {
char *mdm_version;
+ int ramdump_delay_ms;
+ struct platform_device *peripheral_platform_device;
};
#endif
diff --git a/arch/arm/mach-msm/include/mach/qdsp5v2/codec_utils.h b/arch/arm/mach-msm/include/mach/qdsp5v2/codec_utils.h
index 68a3c44..d50fe2b 100644
--- a/arch/arm/mach-msm/include/mach/qdsp5v2/codec_utils.h
+++ b/arch/arm/mach-msm/include/mach/qdsp5v2/codec_utils.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2010, Code Aurora Forum. All rights reserved.
+/* Copyright (c) 2010, 2012, 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
@@ -41,6 +41,7 @@
unsigned used; /* Input usage actual DSP produced PCM size */
unsigned addr;
};
+struct audio;
#ifdef CONFIG_HAS_EARLYSUSPEND
struct audio_suspend_ctl {
diff --git a/arch/arm/mach-msm/include/mach/rpm-8930.h b/arch/arm/mach-msm/include/mach/rpm-8930.h
index 304a185..04218b2 100644
--- a/arch/arm/mach-msm/include/mach/rpm-8930.h
+++ b/arch/arm/mach-msm/include/mach/rpm-8930.h
@@ -117,8 +117,8 @@
MSM_RPM_8930_ID_INVALIDATE_7 =
MSM_RPM_8930_ID_INVALIDATE_0 + 7,
- MSM_RPM_8930_ID_TRIGGER_TIMED_0 = 16,
- MSM_RPM_8930_ID_TRIGGER_TIMED_1 = 17,
+ MSM_RPM_8930_ID_TRIGGER_TIMED_TO_ = 16,
+ MSM_RPM_8930_ID_TRIGGER_TIMED_SCLK_COUNT = 17,
MSM_RPM_8930_ID_RPM_CTL = 18,
MSM_RPM_8930_ID_RESERVED_0 = 19,
MSM_RPM_8930_ID_RESERVED_5 =
@@ -140,106 +140,105 @@
MSM_RPM_8930_ID_APPS_FABRIC_CFG_CLKMOD_2 = 39,
MSM_RPM_8930_ID_APPS_FABRIC_CFG_IOCTL = 40,
MSM_RPM_8930_ID_APPS_FABRIC_ARB_0 = 41,
- MSM_RPM_8930_ID_APPS_FABRIC_ARB_5 =
- MSM_RPM_8930_ID_APPS_FABRIC_ARB_0 + 5,
- MSM_RPM_8930_ID_SYS_FABRIC_CFG_HALT_0 = 47,
- MSM_RPM_8930_ID_SYS_FABRIC_CFG_HALT_1 = 48,
- MSM_RPM_8930_ID_SYS_FABRIC_CFG_CLKMOD_0 = 49,
- MSM_RPM_8930_ID_SYS_FABRIC_CFG_CLKMOD_1 = 50,
- MSM_RPM_8930_ID_SYS_FABRIC_CFG_CLKMOD_2 = 51,
- MSM_RPM_8930_ID_SYS_FABRIC_CFG_IOCTL = 52,
- MSM_RPM_8930_ID_SYSTEM_FABRIC_ARB_0 = 53,
- MSM_RPM_8930_ID_SYSTEM_FABRIC_ARB_19 =
- MSM_RPM_8930_ID_SYSTEM_FABRIC_ARB_0 + 19,
+ MSM_RPM_8930_ID_APPS_FABRIC_ARB_11 =
+ MSM_RPM_8930_ID_APPS_FABRIC_ARB_0 + 11,
+ MSM_RPM_8930_ID_SYS_FABRIC_CFG_HALT_0 = 53,
+ MSM_RPM_8930_ID_SYS_FABRIC_CFG_HALT_1 = 54,
+ MSM_RPM_8930_ID_SYS_FABRIC_CFG_CLKMOD_0 = 55,
+ MSM_RPM_8930_ID_SYS_FABRIC_CFG_CLKMOD_1 = 56,
+ MSM_RPM_8930_ID_SYS_FABRIC_CFG_CLKMOD_2 = 57,
+ MSM_RPM_8930_ID_SYS_FABRIC_CFG_IOCTL = 58,
+ MSM_RPM_8930_ID_SYSTEM_FABRIC_ARB_0 = 59,
+ MSM_RPM_8930_ID_SYSTEM_FABRIC_ARB_28 =
+ MSM_RPM_8930_ID_SYSTEM_FABRIC_ARB_0 + 28,
+ MSM_RPM_8930_ID_MMSS_FABRIC_CFG_HALT_0 = 88,
+ MSM_RPM_8930_ID_MMSS_FABRIC_CFG_HALT_1 = 89,
+ MSM_RPM_8930_ID_MMSS_FABRIC_CFG_CLKMOD_0 = 90,
+ MSM_RPM_8930_ID_MMSS_FABRIC_CFG_CLKMOD_1 = 91,
+ MSM_RPM_8930_ID_MMSS_FABRIC_CFG_CLKMOD_2 = 92,
+ MSM_RPM_8930_ID_MMSS_FABRIC_CFG_IOCTL = 93,
+ MSM_RPM_8930_ID_MM_FABRIC_ARB_0 = 94,
+ MSM_RPM_8930_ID_MM_FABRIC_ARB_22 =
+ MSM_RPM_8930_ID_MM_FABRIC_ARB_0 + 22,
- MSM_RPM_8930_ID_MMSS_FABRIC_CFG_HALT_0 = 73,
- MSM_RPM_8930_ID_MMSS_FABRIC_CFG_HALT_1 = 74,
- MSM_RPM_8930_ID_MMSS_FABRIC_CFG_CLKMOD_0 = 75,
- MSM_RPM_8930_ID_MMSS_FABRIC_CFG_CLKMOD_1 = 76,
- MSM_RPM_8930_ID_MMSS_FABRIC_CFG_CLKMOD_2 = 77,
- MSM_RPM_8930_ID_MMSS_FABRIC_CFG_IOCTL = 78,
- MSM_RPM_8930_ID_MM_FABRIC_ARB_0 = 79,
- MSM_RPM_8930_ID_MM_FABRIC_ARB_10 =
- MSM_RPM_8930_ID_MM_FABRIC_ARB_0 + 10,
-
- MSM_RPM_8930_ID_PM8038_S1_0 = 90,
- MSM_RPM_8930_ID_PM8038_S1_1 = 91,
- MSM_RPM_8930_ID_PM8038_S2_0 = 92,
- MSM_RPM_8930_ID_PM8038_S2_1 = 93,
- MSM_RPM_8930_ID_PM8038_S3_0 = 94,
- MSM_RPM_8930_ID_PM8038_S3_1 = 95,
- MSM_RPM_8930_ID_PM8038_S4_0 = 96,
- MSM_RPM_8930_ID_PM8038_S4_1 = 97,
- MSM_RPM_8930_ID_PM8038_S5_0 = 98,
- MSM_RPM_8930_ID_PM8038_S5_1 = 99,
- MSM_RPM_8930_ID_PM8038_S6_0 = 100,
- MSM_RPM_8930_ID_PM8038_S6_1 = 101,
- MSM_RPM_8930_ID_PM8038_L1_0 = 102,
- MSM_RPM_8930_ID_PM8038_L1_1 = 103,
- MSM_RPM_8930_ID_PM8038_L2_0 = 104,
- MSM_RPM_8930_ID_PM8038_L2_1 = 105,
- MSM_RPM_8930_ID_PM8038_L3_0 = 106,
- MSM_RPM_8930_ID_PM8038_L3_1 = 107,
- MSM_RPM_8930_ID_PM8038_L4_0 = 108,
- MSM_RPM_8930_ID_PM8038_L4_1 = 109,
- MSM_RPM_8930_ID_PM8038_L5_0 = 110,
- MSM_RPM_8930_ID_PM8038_L5_1 = 111,
- MSM_RPM_8930_ID_PM8038_L6_0 = 112,
- MSM_RPM_8930_ID_PM8038_L6_1 = 113,
- MSM_RPM_8930_ID_PM8038_L7_0 = 114,
- MSM_RPM_8930_ID_PM8038_L7_1 = 115,
- MSM_RPM_8930_ID_PM8038_L8_0 = 116,
- MSM_RPM_8930_ID_PM8038_L8_1 = 117,
- MSM_RPM_8930_ID_PM8038_L9_0 = 118,
- MSM_RPM_8930_ID_PM8038_L9_1 = 119,
- MSM_RPM_8930_ID_PM8038_L10_0 = 120,
- MSM_RPM_8930_ID_PM8038_L10_1 = 121,
- MSM_RPM_8930_ID_PM8038_L11_0 = 122,
- MSM_RPM_8930_ID_PM8038_L11_1 = 123,
- MSM_RPM_8930_ID_PM8038_L12_0 = 124,
- MSM_RPM_8930_ID_PM8038_L12_1 = 125,
- MSM_RPM_8930_ID_PM8038_L13_0 = 126,
- MSM_RPM_8930_ID_PM8038_L13_1 = 127,
- MSM_RPM_8930_ID_PM8038_L14_0 = 128,
- MSM_RPM_8930_ID_PM8038_L14_1 = 129,
- MSM_RPM_8930_ID_PM8038_L15_0 = 130,
- MSM_RPM_8930_ID_PM8038_L15_1 = 131,
- MSM_RPM_8930_ID_PM8038_L16_0 = 132,
- MSM_RPM_8930_ID_PM8038_L16_1 = 133,
- MSM_RPM_8930_ID_PM8038_L17_0 = 134,
- MSM_RPM_8930_ID_PM8038_L17_1 = 135,
- MSM_RPM_8930_ID_PM8038_L18_0 = 136,
- MSM_RPM_8930_ID_PM8038_L18_1 = 137,
- MSM_RPM_8930_ID_PM8038_L19_0 = 138,
- MSM_RPM_8930_ID_PM8038_L19_1 = 139,
- MSM_RPM_8930_ID_PM8038_L20_0 = 140,
- MSM_RPM_8930_ID_PM8038_L20_1 = 141,
- MSM_RPM_8930_ID_PM8038_L21_0 = 142,
- MSM_RPM_8930_ID_PM8038_L21_1 = 143,
- MSM_RPM_8930_ID_PM8038_L22_0 = 144,
- MSM_RPM_8930_ID_PM8038_L22_1 = 145,
- MSM_RPM_8930_ID_PM8038_L23_0 = 146,
- MSM_RPM_8930_ID_PM8038_L23_1 = 147,
- MSM_RPM_8930_ID_PM8038_L24_0 = 148,
- MSM_RPM_8930_ID_PM8038_L24_1 = 149,
- MSM_RPM_8930_ID_PM8038_L25_0 = 150,
- MSM_RPM_8930_ID_PM8038_L25_1 = 151,
- MSM_RPM_8930_ID_PM8038_L26_0 = 152,
- MSM_RPM_8930_ID_PM8038_L26_1 = 153,
- MSM_RPM_8930_ID_PM8038_L27_0 = 154,
- MSM_RPM_8930_ID_PM8038_L27_1 = 155,
- MSM_RPM_8930_ID_PM8038_CLK1_0 = 156,
- MSM_RPM_8930_ID_PM8038_CLK1_1 = 157,
- MSM_RPM_8930_ID_PM8038_CLK2_0 = 158,
- MSM_RPM_8930_ID_PM8038_CLK2_1 = 159,
- MSM_RPM_8930_ID_PM8038_LVS1 = 160,
- MSM_RPM_8930_ID_PM8038_LVS2 = 161,
- MSM_RPM_8930_ID_NCP_0 = 162,
- MSM_RPM_8930_ID_NCP_1 = 163,
- MSM_RPM_8930_ID_CXO_BUFFERS = 164,
- MSM_RPM_8930_ID_USB_OTG_SWITCH = 165,
- MSM_RPM_8930_ID_HDMI_SWITCH = 166,
- MSM_RPM_8930_ID_QDSS_CLK = 167,
+ MSM_RPM_8930_ID_PM8038_S1_0 = 117,
+ MSM_RPM_8930_ID_PM8038_S1_1 = 118,
+ MSM_RPM_8930_ID_PM8038_S2_0 = 119,
+ MSM_RPM_8930_ID_PM8038_S2_1 = 120,
+ MSM_RPM_8930_ID_PM8038_S3_0 = 121,
+ MSM_RPM_8930_ID_PM8038_S3_1 = 122,
+ MSM_RPM_8930_ID_PM8038_S4_0 = 123,
+ MSM_RPM_8930_ID_PM8038_S4_1 = 124,
+ MSM_RPM_8930_ID_PM8038_S5_0 = 125,
+ MSM_RPM_8930_ID_PM8038_S5_1 = 126,
+ MSM_RPM_8930_ID_PM8038_S6_0 = 127,
+ MSM_RPM_8930_ID_PM8038_S6_1 = 128,
+ MSM_RPM_8930_ID_PM8038_L1_0 = 129,
+ MSM_RPM_8930_ID_PM8038_L1_1 = 130,
+ MSM_RPM_8930_ID_PM8038_L2_0 = 131,
+ MSM_RPM_8930_ID_PM8038_L2_1 = 132,
+ MSM_RPM_8930_ID_PM8038_L3_0 = 133,
+ MSM_RPM_8930_ID_PM8038_L3_1 = 134,
+ MSM_RPM_8930_ID_PM8038_L4_0 = 135,
+ MSM_RPM_8930_ID_PM8038_L4_1 = 136,
+ MSM_RPM_8930_ID_PM8038_L5_0 = 137,
+ MSM_RPM_8930_ID_PM8038_L5_1 = 138,
+ MSM_RPM_8930_ID_PM8038_L6_0 = 139,
+ MSM_RPM_8930_ID_PM8038_L6_1 = 140,
+ MSM_RPM_8930_ID_PM8038_L7_0 = 141,
+ MSM_RPM_8930_ID_PM8038_L7_1 = 142,
+ MSM_RPM_8930_ID_PM8038_L8_0 = 143,
+ MSM_RPM_8930_ID_PM8038_L8_1 = 144,
+ MSM_RPM_8930_ID_PM8038_L9_0 = 145,
+ MSM_RPM_8930_ID_PM8038_L9_1 = 146,
+ MSM_RPM_8930_ID_PM8038_L10_0 = 147,
+ MSM_RPM_8930_ID_PM8038_L10_1 = 148,
+ MSM_RPM_8930_ID_PM8038_L11_0 = 149,
+ MSM_RPM_8930_ID_PM8038_L11_1 = 150,
+ MSM_RPM_8930_ID_PM8038_L12_0 = 151,
+ MSM_RPM_8930_ID_PM8038_L12_1 = 152,
+ MSM_RPM_8930_ID_PM8038_L13_0 = 153,
+ MSM_RPM_8930_ID_PM8038_L13_1 = 154,
+ MSM_RPM_8930_ID_PM8038_L14_0 = 155,
+ MSM_RPM_8930_ID_PM8038_L14_1 = 156,
+ MSM_RPM_8930_ID_PM8038_L15_0 = 157,
+ MSM_RPM_8930_ID_PM8038_L15_1 = 158,
+ MSM_RPM_8930_ID_PM8038_L16_0 = 159,
+ MSM_RPM_8930_ID_PM8038_L16_1 = 160,
+ MSM_RPM_8930_ID_PM8038_L17_0 = 161,
+ MSM_RPM_8930_ID_PM8038_L17_1 = 162,
+ MSM_RPM_8930_ID_PM8038_L18_0 = 163,
+ MSM_RPM_8930_ID_PM8038_L18_1 = 164,
+ MSM_RPM_8930_ID_PM8038_L19_0 = 165,
+ MSM_RPM_8930_ID_PM8038_L19_1 = 166,
+ MSM_RPM_8930_ID_PM8038_L20_0 = 167,
+ MSM_RPM_8930_ID_PM8038_L20_1 = 168,
+ MSM_RPM_8930_ID_PM8038_L21_0 = 169,
+ MSM_RPM_8930_ID_PM8038_L21_1 = 170,
+ MSM_RPM_8930_ID_PM8038_L22_0 = 171,
+ MSM_RPM_8930_ID_PM8038_L22_1 = 172,
+ MSM_RPM_8930_ID_PM8038_L23_0 = 173,
+ MSM_RPM_8930_ID_PM8038_L23_1 = 174,
+ MSM_RPM_8930_ID_PM8038_L24_0 = 175,
+ MSM_RPM_8930_ID_PM8038_L24_1 = 176,
+ MSM_RPM_8930_ID_PM8038_L25_0 = 177,
+ MSM_RPM_8930_ID_PM8038_L25_1 = 178,
+ MSM_RPM_8930_ID_PM8038_L26_0 = 179,
+ MSM_RPM_8930_ID_PM8038_L26_1 = 180,
+ MSM_RPM_8930_ID_PM8038_L27_0 = 181,
+ MSM_RPM_8930_ID_PM8038_L27_1 = 182,
+ MSM_RPM_8930_ID_PM8038_CLK1_0 = 183,
+ MSM_RPM_8930_ID_PM8038_CLK1_1 = 184,
+ MSM_RPM_8930_ID_PM8038_CLK2_0 = 185,
+ MSM_RPM_8930_ID_PM8038_CLK2_1 = 186,
+ MSM_RPM_8930_ID_PM8038_LVS1 = 187,
+ MSM_RPM_8930_ID_PM8038_LVS2 = 188,
+ MSM_RPM_8930_ID_NCP_0 = 189,
+ MSM_RPM_8930_ID_NCP_1 = 190,
+ MSM_RPM_8930_ID_CXO_BUFFERS = 191,
+ MSM_RPM_8930_ID_USB_OTG_SWITCH = 192,
+ MSM_RPM_8930_ID_HDMI_SWITCH = 193,
+ MSM_RPM_8930_ID_QDSS_CLK = 194,
MSM_RPM_8930_ID_LAST = MSM_RPM_8930_ID_QDSS_CLK,
};
@@ -284,10 +283,6 @@
MSM_RPM_8930_STATUS_ID_PM8038_S3_1 = 36,
MSM_RPM_8930_STATUS_ID_PM8038_S4_0 = 37,
MSM_RPM_8930_STATUS_ID_PM8038_S4_1 = 38,
- MSM_RPM_8930_STATUS_ID_PM8038_S5_0 = 39,
- MSM_RPM_8930_STATUS_ID_PM8038_S5_1 = 40,
- MSM_RPM_8930_STATUS_ID_PM8038_S6_0 = 41,
- MSM_RPM_8930_STATUS_ID_PM8038_S6_1 = 42,
MSM_RPM_8930_STATUS_ID_PM8038_L1_0 = 43,
MSM_RPM_8930_STATUS_ID_PM8038_L1_1 = 44,
MSM_RPM_8930_STATUS_ID_PM8038_L2_0 = 45,
@@ -353,7 +348,8 @@
MSM_RPM_8930_STATUS_ID_CXO_BUFFERS = 105,
MSM_RPM_8930_STATUS_ID_USB_OTG_SWITCH = 106,
MSM_RPM_8930_STATUS_ID_HDMI_SWITCH = 107,
- MSM_RPM_8930_STATUS_ID_LAST = MSM_RPM_8930_STATUS_ID_HDMI_SWITCH,
+ MSM_RPM_8930_STATUS_ID_QDSS_CLK = 108,
+ MSM_RPM_8930_STATUS_ID_LAST = MSM_RPM_8930_STATUS_ID_QDSS_CLK,
};
#endif /* __ARCH_ARM_MACH_MSM_RPM_8930_H */
diff --git a/arch/arm/mach-msm/include/mach/rpm.h b/arch/arm/mach-msm/include/mach/rpm.h
index 40a8c9b..80ec683 100644
--- a/arch/arm/mach-msm/include/mach/rpm.h
+++ b/arch/arm/mach-msm/include/mach/rpm.h
@@ -601,6 +601,7 @@
MSM_RPM_STATUS_ID_DDR_DMM_1,
MSM_RPM_STATUS_ID_EBI1_CH0_RANGE,
MSM_RPM_STATUS_ID_EBI1_CH1_RANGE,
+ MSM_RPM_STATUS_ID_QDSS_CLK,
/* 8660 Specific */
MSM_RPM_STATUS_ID_PLL_4,
diff --git a/arch/arm/mach-msm/mdm2.c b/arch/arm/mach-msm/mdm2.c
index bf4e6a4..5db8b40 100644
--- a/arch/arm/mach-msm/mdm2.c
+++ b/arch/arm/mach-msm/mdm2.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2011, Code Aurora Forum. All rights reserved.
+/* Copyright (c) 2011-2012, 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
@@ -33,7 +33,6 @@
#include <asm/mach-types.h>
#include <asm/uaccess.h>
#include <mach/mdm2.h>
-#include <mach/mdm-peripheral.h>
#include <mach/restart.h>
#include <mach/subsystem_notif.h>
#include <mach/subsystem_restart.h>
@@ -46,38 +45,63 @@
#define MDM_MODEM_TIMEOUT 6000
#define MDM_HOLD_TIME 4000
#define MDM_MODEM_DELTA 100
-#define IFLINE_UP 1
-#define IFLINE_DOWN 0
static int mdm_debug_on;
-static struct mdm_callbacks mdm_cb;
+static int first_power_on = 1;
+static int hsic_peripheral_status = 1;
+static DEFINE_MUTEX(hsic_status_lock);
-#define MDM_DBG(...) do { if (mdm_debug_on) \
- pr_info(__VA_ARGS__); \
- } while (0);
+static void mdm_peripheral_connect(struct mdm_modem_drv *mdm_drv)
+{
+ mutex_lock(&hsic_status_lock);
+ if (hsic_peripheral_status)
+ goto out;
+ if (mdm_drv->pdata->peripheral_platform_device)
+ platform_device_add(mdm_drv->pdata->peripheral_platform_device);
+ hsic_peripheral_status = 1;
+out:
+ mutex_unlock(&hsic_status_lock);
+}
+
+static void mdm_peripheral_disconnect(struct mdm_modem_drv *mdm_drv)
+{
+ mutex_lock(&hsic_status_lock);
+ if (!hsic_peripheral_status)
+ goto out;
+ if (mdm_drv->pdata->peripheral_platform_device)
+ platform_device_del(mdm_drv->pdata->peripheral_platform_device);
+ hsic_peripheral_status = 0;
+out:
+ mutex_unlock(&hsic_status_lock);
+}
static void power_on_mdm(struct mdm_modem_drv *mdm_drv)
{
- peripheral_disconnect();
+ mdm_peripheral_disconnect(mdm_drv);
- /* Pull both ERR_FATAL and RESET low */
- MDM_DBG("Pulling PWR and RESET gpio's low\n");
+ /* Pull RESET gpio low and wait for it to settle. */
+ pr_debug("Pulling RESET gpio low\n");
gpio_direction_output(mdm_drv->ap2mdm_pmic_reset_n_gpio, 0);
- gpio_direction_output(mdm_drv->ap2mdm_kpdpwr_n_gpio, 0);
- /* Wait for them to settle. */
usleep(1000);
/* Deassert RESET first and wait for ir to settle. */
- MDM_DBG("%s: Pulling RESET gpio high\n", __func__);
+ pr_debug("%s: Pulling RESET gpio high\n", __func__);
gpio_direction_output(mdm_drv->ap2mdm_pmic_reset_n_gpio, 1);
usleep(1000);
- /* Pull PWR gpio high and wait for it to settle. */
- MDM_DBG("%s: Powering on mdm modem\n", __func__);
- gpio_direction_output(mdm_drv->ap2mdm_kpdpwr_n_gpio, 1);
- usleep(1000);
-
- peripheral_connect();
+ /* Pull PWR gpio high and wait for it to settle, but only
+ * the first time the mdm is powered up.
+ * Some targets do not use ap2mdm_kpdpwr_n_gpio.
+ */
+ if (first_power_on) {
+ if (mdm_drv->ap2mdm_kpdpwr_n_gpio > 0) {
+ pr_debug("%s: Powering on mdm modem\n", __func__);
+ gpio_direction_output(mdm_drv->ap2mdm_kpdpwr_n_gpio, 1);
+ usleep(1000);
+ }
+ first_power_on = 0;
+ }
+ mdm_peripheral_connect(mdm_drv);
msleep(200);
}
@@ -92,7 +116,6 @@
if (gpio_get_value(mdm_drv->mdm2ap_status_gpio) == 0)
break;
}
-
if (i <= 0) {
pr_err("%s: MDM2AP_STATUS never went low.\n",
__func__);
@@ -103,12 +126,9 @@
msleep(MDM_MODEM_DELTA);
}
}
-
- peripheral_disconnect();
-}
-
-static void normal_boot_done(struct mdm_modem_drv *mdm_drv)
-{
+ if (mdm_drv->ap2mdm_kpdpwr_n_gpio > 0)
+ gpio_direction_output(mdm_drv->ap2mdm_kpdpwr_n_gpio, 0);
+ mdm_peripheral_disconnect(mdm_drv);
}
static void debug_state_changed(int value)
@@ -116,24 +136,25 @@
mdm_debug_on = value;
}
-static void mdm_status_changed(int value)
+static void mdm_status_changed(struct mdm_modem_drv *mdm_drv, int value)
{
- MDM_DBG("%s: value:%d\n", __func__, value);
+ pr_debug("%s: value:%d\n", __func__, value);
if (value) {
- peripheral_disconnect();
- peripheral_connect();
+ mdm_peripheral_disconnect(mdm_drv);
+ mdm_peripheral_connect(mdm_drv);
}
}
+static struct mdm_ops mdm_cb = {
+ .power_on_mdm_cb = power_on_mdm,
+ .power_down_mdm_cb = power_down_mdm,
+ .debug_state_changed_cb = debug_state_changed,
+ .status_cb = mdm_status_changed,
+};
+
static int __init mdm_modem_probe(struct platform_device *pdev)
{
- /* Instantiate driver object. */
- mdm_cb.power_on_mdm_cb = power_on_mdm;
- mdm_cb.power_down_mdm_cb = power_down_mdm;
- mdm_cb.normal_boot_done_cb = normal_boot_done;
- mdm_cb.debug_state_changed_cb = debug_state_changed;
- mdm_cb.status_cb = mdm_status_changed;
return mdm_common_create(pdev, &mdm_cb);
}
diff --git a/arch/arm/mach-msm/mdm_common.c b/arch/arm/mach-msm/mdm_common.c
index 023df69..b672957 100644
--- a/arch/arm/mach-msm/mdm_common.c
+++ b/arch/arm/mach-msm/mdm_common.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2011, Code Aurora Forum. All rights reserved.
+/* Copyright (c) 2011-2012, 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
@@ -48,10 +48,6 @@
#define EXTERNAL_MODEM "external_modem"
-#define MDM_DBG(...) do { if (mdm_debug_on) \
- pr_info(__VA_ARGS__); \
- } while (0);
-
static struct mdm_modem_drv *mdm_drv;
DECLARE_COMPLETION(mdm_needs_reload);
@@ -70,11 +66,11 @@
return -EINVAL;
}
- MDM_DBG("%s: Entering ioctl cmd = %d\n", __func__, _IOC_NR(cmd));
+ pr_debug("%s: Entering ioctl cmd = %d\n", __func__, _IOC_NR(cmd));
switch (cmd) {
case WAKE_CHARM:
- MDM_DBG("%s: Powering on\n", __func__);
- mdm_drv->power_on_mdm_cb(mdm_drv);
+ pr_info("%s: Powering on mdm\n", __func__);
+ mdm_drv->ops->power_on_mdm_cb(mdm_drv);
break;
case CHECK_FOR_BOOT:
if (gpio_get_value(mdm_drv->mdm2ap_status_gpio) == 0)
@@ -83,16 +79,19 @@
put_user(0, (unsigned long __user *) arg);
break;
case NORMAL_BOOT_DONE:
- MDM_DBG("%s: check if mdm is booted up\n", __func__);
+ pr_debug("%s: check if mdm is booted up\n", __func__);
get_user(status, (unsigned long __user *) arg);
- if (status)
+ if (status) {
+ pr_debug("%s: normal boot failed\n", __func__);
mdm_drv->mdm_boot_status = -EIO;
- else
+ } else {
+ pr_info("%s: normal boot done\n", __func__);
mdm_drv->mdm_boot_status = 0;
+ }
mdm_drv->mdm_ready = 1;
- if (mdm_drv->normal_boot_done_cb != NULL)
- mdm_drv->normal_boot_done_cb(mdm_drv);
+ if (mdm_drv->ops->normal_boot_done_cb != NULL)
+ mdm_drv->ops->normal_boot_done_cb(mdm_drv);
if (!first_boot)
complete(&mdm_boot);
@@ -100,16 +99,18 @@
first_boot = 0;
break;
case RAM_DUMP_DONE:
- MDM_DBG("%s: mdm done collecting RAM dumps\n", __func__);
+ pr_debug("%s: mdm done collecting RAM dumps\n", __func__);
get_user(status, (unsigned long __user *) arg);
if (status)
mdm_drv->mdm_ram_dump_status = -EIO;
- else
+ else {
+ pr_info("%s: ramdump collection completed\n", __func__);
mdm_drv->mdm_ram_dump_status = 0;
+ }
complete(&mdm_ram_dumps);
break;
case WAIT_FOR_RESTART:
- MDM_DBG("%s: wait for mdm to need images reloaded\n",
+ pr_debug("%s: wait for mdm to need images reloaded\n",
__func__);
ret = wait_for_completion_interruptible(&mdm_needs_reload);
if (!ret)
@@ -128,7 +129,7 @@
static void mdm_fatal_fn(struct work_struct *work)
{
- MDM_DBG("%s: Reseting the mdm due to an errfatal\n", __func__);
+ pr_info("%s: Reseting the mdm due to an errfatal\n", __func__);
subsystem_restart(EXTERNAL_MODEM);
}
@@ -138,15 +139,15 @@
{
int value = gpio_get_value(mdm_drv->mdm2ap_status_gpio);
- mdm_drv->status_cb(value);
+ mdm_drv->ops->status_cb(mdm_drv, value);
- MDM_DBG("%s: status:%d\n", __func__, value);
+ pr_debug("%s: status:%d\n", __func__, value);
if ((value == 0) && mdm_drv->mdm_ready) {
- MDM_DBG("%s: scheduling work now\n", __func__);
+ pr_info("%s: unexpected reset external modem\n", __func__);
subsystem_restart(EXTERNAL_MODEM);
} else if (value == 1) {
- MDM_DBG("%s: mdm is now ready\n", __func__);
+ pr_info("%s: status = 1: mdm is now ready\n", __func__);
}
}
@@ -161,10 +162,10 @@
static irqreturn_t mdm_errfatal(int irq, void *dev_id)
{
- MDM_DBG("%s: mdm got errfatal interrupt\n", __func__);
+ pr_debug("%s: mdm got errfatal interrupt\n", __func__);
if (mdm_drv->mdm_ready &&
(gpio_get_value(mdm_drv->mdm2ap_status_gpio) == 1)) {
- MDM_DBG("%s: scheduling work now\n", __func__);
+ pr_debug("%s: scheduling work now\n", __func__);
queue_work(mdm_queue, &mdm_fatal_work);
}
return IRQ_HANDLED;
@@ -193,7 +194,7 @@
{
int i;
- MDM_DBG("%s: setting AP2MDM_ERRFATAL high for a non graceful reset\n",
+ pr_debug("%s: setting AP2MDM_ERRFATAL high for a non graceful reset\n",
__func__);
mdm_disable_irqs();
gpio_set_value(mdm_drv->ap2mdm_errfatal_gpio, 1);
@@ -218,7 +219,7 @@
static irqreturn_t mdm_status_change(int irq, void *dev_id)
{
- MDM_DBG("%s: mdm sent status change interrupt\n", __func__);
+ pr_debug("%s: mdm sent status change interrupt\n", __func__);
queue_work(mdm_queue, &mdm_status_work);
@@ -229,13 +230,19 @@
{
mdm_drv->mdm_ready = 0;
gpio_direction_output(mdm_drv->ap2mdm_errfatal_gpio, 1);
- mdm_drv->power_down_mdm_cb(mdm_drv);
+ if (mdm_drv->pdata->ramdump_delay_ms > 0) {
+ /* Wait for the external modem to complete
+ * its preparation for ramdumps.
+ */
+ mdelay(mdm_drv->pdata->ramdump_delay_ms);
+ }
+ mdm_drv->ops->power_down_mdm_cb(mdm_drv);
return 0;
}
static int mdm_subsys_powerup(const struct subsys_data *crashed_subsys)
{
- mdm_drv->power_on_mdm_cb(mdm_drv);
+ mdm_drv->ops->power_on_mdm_cb(mdm_drv);
mdm_drv->boot_type = CHARM_NORMAL_BOOT;
complete(&mdm_needs_reload);
wait_for_completion(&mdm_boot);
@@ -254,7 +261,7 @@
wait_for_completion(&mdm_ram_dumps);
INIT_COMPLETION(mdm_ram_dumps);
gpio_direction_output(mdm_drv->ap2mdm_errfatal_gpio, 1);
- mdm_drv->power_down_mdm_cb(mdm_drv);
+ mdm_drv->ops->power_down_mdm_cb(mdm_drv);
}
return mdm_drv->mdm_ram_dump_status;
}
@@ -269,8 +276,8 @@
static int mdm_debug_on_set(void *data, u64 val)
{
mdm_debug_on = val;
- if (mdm_drv->debug_state_changed_cb)
- mdm_drv->debug_state_changed_cb(mdm_debug_on);
+ if (mdm_drv->ops->debug_state_changed_cb)
+ mdm_drv->ops->debug_state_changed_cb(mdm_debug_on);
return 0;
}
@@ -298,7 +305,7 @@
}
static void mdm_modem_initialize_data(struct platform_device *pdev,
- struct mdm_callbacks *p_mdm_cb)
+ struct mdm_ops *mdm_ops)
{
struct resource *pres;
@@ -352,15 +359,12 @@
mdm_drv->boot_type = CHARM_NORMAL_BOOT;
- mdm_drv->power_on_mdm_cb = p_mdm_cb->power_on_mdm_cb;
- mdm_drv->power_down_mdm_cb = p_mdm_cb->power_down_mdm_cb;
- mdm_drv->normal_boot_done_cb = p_mdm_cb->normal_boot_done_cb;
- mdm_drv->debug_state_changed_cb = p_mdm_cb->debug_state_changed_cb;
- mdm_drv->status_cb = p_mdm_cb->status_cb;
+ mdm_drv->ops = mdm_ops;
+ mdm_drv->pdata = pdev->dev.platform_data;
}
int mdm_common_create(struct platform_device *pdev,
- struct mdm_callbacks *p_mdm_cb)
+ struct mdm_ops *p_mdm_cb)
{
int ret = -1, irq;
@@ -371,8 +375,8 @@
}
mdm_modem_initialize_data(pdev, p_mdm_cb);
- if (mdm_drv->debug_state_changed_cb)
- mdm_drv->debug_state_changed_cb(mdm_debug_on);
+ if (mdm_drv->ops->debug_state_changed_cb)
+ mdm_drv->ops->debug_state_changed_cb(mdm_debug_on);
gpio_request(mdm_drv->ap2mdm_status_gpio, "AP2MDM_STATUS");
gpio_request(mdm_drv->ap2mdm_errfatal_gpio, "AP2MDM_ERRFATAL");
@@ -494,7 +498,7 @@
void mdm_common_modem_shutdown(struct platform_device *pdev)
{
- MDM_DBG("%s: setting AP2MDM_STATUS low for a graceful restart\n",
+ pr_debug("%s: setting AP2MDM_STATUS low for a graceful restart\n",
__func__);
mdm_disable_irqs();
@@ -504,7 +508,7 @@
if (mdm_drv->ap2mdm_wakeup_gpio > 0)
gpio_set_value(mdm_drv->ap2mdm_wakeup_gpio, 1);
- mdm_drv->power_down_mdm_cb(mdm_drv);
+ mdm_drv->ops->power_down_mdm_cb(mdm_drv);
if (mdm_drv->ap2mdm_wakeup_gpio > 0)
gpio_set_value(mdm_drv->ap2mdm_wakeup_gpio, 0);
diff --git a/arch/arm/mach-msm/mdm_private.h b/arch/arm/mach-msm/mdm_private.h
index bc8541e..206bd8b 100644
--- a/arch/arm/mach-msm/mdm_private.h
+++ b/arch/arm/mach-msm/mdm_private.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2011, Code Aurora Forum. All rights reserved.
+/* Copyright (c) 2011-2012, Code Aurora Forum. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -15,6 +15,14 @@
struct mdm_modem_drv;
+struct mdm_ops {
+ void (*power_on_mdm_cb)(struct mdm_modem_drv *mdm_drv);
+ void (*normal_boot_done_cb)(struct mdm_modem_drv *mdm_drv);
+ void (*power_down_mdm_cb)(struct mdm_modem_drv *mdm_drv);
+ void (*debug_state_changed_cb)(int value);
+ void (*status_cb)(struct mdm_modem_drv *mdm_drv, int value);
+};
+
/* Private mdm2 data structure */
struct mdm_modem_drv {
unsigned mdm2ap_errfatal_gpio;
@@ -34,23 +42,12 @@
enum charm_boot_type boot_type;
int mdm_debug_on;
- void (*power_on_mdm_cb)(struct mdm_modem_drv *mdm_drv);
- void (*normal_boot_done_cb)(struct mdm_modem_drv *mdm_drv);
- void (*power_down_mdm_cb)(struct mdm_modem_drv *mdm_drv);
- void (*debug_state_changed_cb)(int value);
- void (*status_cb)(int value);
-};
-
-struct mdm_callbacks {
- void (*power_on_mdm_cb)(struct mdm_modem_drv *mdm_drv);
- void (*normal_boot_done_cb)(struct mdm_modem_drv *mdm_drv);
- void (*power_down_mdm_cb)(struct mdm_modem_drv *mdm_drv);
- void (*debug_state_changed_cb)(int value);
- void (*status_cb)(int value);
+ struct mdm_ops *ops;
+ struct mdm_platform_data *pdata;
};
int mdm_common_create(struct platform_device *pdev,
- struct mdm_callbacks *mdm_cb);
+ struct mdm_ops *mdm_cb);
int mdm_common_modem_remove(struct platform_device *pdev);
void mdm_common_modem_shutdown(struct platform_device *pdev);
void mdm_common_set_debug_state(int value);
diff --git a/arch/arm/mach-msm/no-pm.c b/arch/arm/mach-msm/no-pm.c
index f51286f..d1c474b 100644
--- a/arch/arm/mach-msm/no-pm.c
+++ b/arch/arm/mach-msm/no-pm.c
@@ -15,7 +15,7 @@
#include <mach/cpuidle.h>
#include "idle.h"
-#include <mach/pm.h>
+#include "pm.h"
void arch_idle(void)
{ }
diff --git a/arch/arm/mach-msm/pil-gss.c b/arch/arm/mach-msm/pil-gss.c
new file mode 100644
index 0000000..4c94b83
--- /dev/null
+++ b/arch/arm/mach-msm/pil-gss.c
@@ -0,0 +1,369 @@
+/*
+ * Copyright (c) 2012, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/kernel.h>
+#include <linux/err.h>
+#include <linux/io.h>
+#include <linux/elf.h>
+#include <linux/delay.h>
+#include <linux/module.h>
+#include <linux/slab.h>
+#include <linux/platform_device.h>
+#include <linux/workqueue.h>
+#include <linux/clk.h>
+
+#include <mach/msm_iomap.h>
+#include <mach/msm_xo.h>
+
+#include "peripheral-loader.h"
+#include "scm-pas.h"
+
+#define GSS_CSR_AHB_CLK_SEL 0x0
+#define GSS_CSR_RESET 0x4
+#define GSS_CSR_CLK_BLK_CONFIG 0x8
+#define GSS_CSR_CLK_ENABLE 0xC
+#define GSS_CSR_BOOT_REMAP 0x14
+#define GSS_CSR_POWER_UP_DOWN 0x18
+
+#define GSS_SLP_CLK_CTL (MSM_CLK_CTL_BASE + 0x2C60)
+#define GSS_RESET (MSM_CLK_CTL_BASE + 0x2C64)
+#define GSS_CLAMP_ENA (MSM_CLK_CTL_BASE + 0x2C68)
+#define GSS_CXO_SRC_CTL (MSM_CLK_CTL_BASE + 0x2C74)
+
+#define PLL5_MODE (MSM_CLK_CTL_BASE + 0x30E0)
+#define PLL5_L_VAL (MSM_CLK_CTL_BASE + 0x30E4)
+#define PLL5_M_VAL (MSM_CLK_CTL_BASE + 0x30E8)
+#define PLL5_N_VAL (MSM_CLK_CTL_BASE + 0x30EC)
+#define PLL5_CONFIG (MSM_CLK_CTL_BASE + 0x30F4)
+#define PLL5_STATUS (MSM_CLK_CTL_BASE + 0x30F8)
+#define PLL_ENA_GSS (MSM_CLK_CTL_BASE + 0x3480)
+#define PLL_ENA_RPM (MSM_CLK_CTL_BASE + 0x34A0)
+
+#define PLL5_VOTE BIT(5)
+#define PLL_STATUS BIT(16)
+#define REMAP_ENABLE BIT(16)
+#define A5_POWER_STATUS BIT(4)
+#define A5_POWER_ENA BIT(0)
+#define NAV_POWER_ENA BIT(1)
+#define XO_CLK_BRANCH_ENA BIT(0)
+#define SLP_CLK_BRANCH_ENA BIT(4)
+#define A5_RESET BIT(0)
+
+#define PROXY_VOTE_TIMEOUT 10000
+
+struct gss_data {
+ void __iomem *base;
+ unsigned long start_addr;
+ struct delayed_work work;
+ struct clk *xo;
+};
+
+static int nop_verify_blob(struct pil_desc *pil, u32 phy_addr, size_t size)
+{
+ return 0;
+}
+
+static int pil_gss_init_image(struct pil_desc *pil, const u8 *metadata,
+ size_t size)
+{
+ const struct elf32_hdr *ehdr = (struct elf32_hdr *)metadata;
+ struct gss_data *drv = dev_get_drvdata(pil->dev);
+ drv->start_addr = ehdr->e_entry;
+ return 0;
+}
+
+static int make_gss_proxy_votes(struct device *dev)
+{
+ int ret;
+ struct gss_data *drv = dev_get_drvdata(dev);
+
+ ret = clk_prepare_enable(drv->xo);
+ if (ret) {
+ dev_err(dev, "Failed to enable XO\n");
+ return ret;
+ }
+ schedule_delayed_work(&drv->work, msecs_to_jiffies(PROXY_VOTE_TIMEOUT));
+ return 0;
+}
+
+static void remove_gss_proxy_votes(struct work_struct *work)
+{
+ struct gss_data *drv = container_of(work, struct gss_data, work.work);
+ clk_disable_unprepare(drv->xo);
+}
+
+static void remove_gss_proxy_votes_now(struct gss_data *drv)
+{
+ flush_delayed_work(&drv->work);
+}
+
+static void gss_init(struct gss_data *drv)
+{
+ void __iomem *base = drv->base;
+
+ /* Supply clocks to GSS. */
+ writel_relaxed(XO_CLK_BRANCH_ENA, GSS_CXO_SRC_CTL);
+ writel_relaxed(SLP_CLK_BRANCH_ENA, GSS_SLP_CLK_CTL);
+
+ /* Deassert GSS reset and clamps. */
+ writel_relaxed(0x0, GSS_RESET);
+ writel_relaxed(0x0, GSS_CLAMP_ENA);
+ mb();
+
+ /*
+ * Configure clock source and dividers for 288MHz core, 144MHz AXI and
+ * 72MHz AHB, all derived from the 288MHz PLL.
+ */
+ writel_relaxed(0x341, base + GSS_CSR_CLK_BLK_CONFIG);
+ writel_relaxed(0x1, base + GSS_CSR_AHB_CLK_SEL);
+
+ /* Assert all GSS resets. */
+ writel_relaxed(0x7F, base + GSS_CSR_RESET);
+
+ /* Enable all bus clocks and wait for resets to propagate. */
+ writel_relaxed(0x1F, base + GSS_CSR_CLK_ENABLE);
+ mb();
+ udelay(1);
+
+ /* Release subsystem from reset, but leave A5 in reset. */
+ writel_relaxed(A5_RESET, base + GSS_CSR_RESET);
+}
+
+static int pil_gss_reset(struct pil_desc *pil)
+{
+ struct gss_data *drv = dev_get_drvdata(pil->dev);
+ void __iomem *base = drv->base;
+ unsigned long start_addr = drv->start_addr;
+ int ret;
+
+ ret = make_gss_proxy_votes(pil->dev);
+ if (ret)
+ return ret;
+
+ /* Vote PLL on in GSS's voting register and wait for it to enable. */
+ writel_relaxed(PLL5_VOTE, PLL_ENA_GSS);
+ while ((readl_relaxed(PLL5_STATUS) & PLL_STATUS) == 0)
+ cpu_relax();
+
+ /* Perform GSS initialization. */
+ gss_init(drv);
+
+ /* Configure boot address and enable remap. */
+ writel_relaxed(REMAP_ENABLE | (start_addr >> 16),
+ base + GSS_CSR_BOOT_REMAP);
+
+ /* Power up A5 core. */
+ writel_relaxed(A5_POWER_ENA, base + GSS_CSR_POWER_UP_DOWN);
+ while (!(readl_relaxed(base + GSS_CSR_POWER_UP_DOWN) & A5_POWER_STATUS))
+ cpu_relax();
+
+ /* Release A5 from reset. */
+ writel_relaxed(0x0, base + GSS_CSR_RESET);
+
+ return 0;
+}
+
+static int pil_gss_shutdown(struct pil_desc *pil)
+{
+ struct gss_data *drv = dev_get_drvdata(pil->dev);
+ void __iomem *base = drv->base;
+ u32 regval;
+ int ret;
+
+ ret = clk_prepare_enable(drv->xo);
+ if (ret) {
+ dev_err(pil->dev, "Failed to enable XO\n");
+ return ret;
+ }
+
+ /*
+ * Vote PLL on in GSS's voting register and wait for it to enable.
+ * The PLL must be enable to switch the GFMUX to a low-power source.
+ */
+ writel_relaxed(PLL5_VOTE, PLL_ENA_GSS);
+ while ((readl_relaxed(PLL5_STATUS) & PLL_STATUS) == 0)
+ cpu_relax();
+
+ /* Perform one-time GSS initialization. */
+ gss_init(drv);
+
+ /* Assert A5 reset. */
+ regval = readl_relaxed(base + GSS_CSR_RESET);
+ regval |= A5_RESET;
+ writel_relaxed(regval, base + GSS_CSR_RESET);
+
+ /* Power down A5 and NAV. */
+ regval = readl_relaxed(base + GSS_CSR_POWER_UP_DOWN);
+ regval &= ~(A5_POWER_ENA|NAV_POWER_ENA);
+ writel_relaxed(regval, base + GSS_CSR_POWER_UP_DOWN);
+
+ /* Select XO clock source and increase dividers to save power. */
+ regval = readl_relaxed(base + GSS_CSR_CLK_BLK_CONFIG);
+ regval |= 0x3FF;
+ writel_relaxed(regval, base + GSS_CSR_CLK_BLK_CONFIG);
+
+ /* Disable bus clocks. */
+ writel_relaxed(0x1F, base + GSS_CSR_CLK_ENABLE);
+
+ /* Clear GSS PLL votes. */
+ writel_relaxed(0, PLL_ENA_GSS);
+ mb();
+
+ clk_disable_unprepare(drv->xo);
+ remove_gss_proxy_votes_now(drv);
+
+ return 0;
+}
+
+static struct pil_reset_ops pil_gss_ops = {
+ .init_image = pil_gss_init_image,
+ .verify_blob = nop_verify_blob,
+ .auth_and_reset = pil_gss_reset,
+ .shutdown = pil_gss_shutdown,
+};
+
+static void configure_gss_pll(struct gss_data *drv)
+{
+ u32 regval, is_pll_enabled;
+
+ /* Check if PLL5 is enabled by FSM. */
+ is_pll_enabled = readl_relaxed(PLL5_STATUS) & PLL_STATUS;
+ if (!is_pll_enabled) {
+ /* Enable XO reference for PLL5 */
+ clk_prepare_enable(drv->xo);
+
+ /*
+ * Assert a vote to hold PLL5 on in RPM register until other
+ * voters are in place.
+ */
+ regval = readl_relaxed(PLL_ENA_RPM);
+ regval |= PLL5_VOTE;
+ writel_relaxed(regval, PLL_ENA_RPM);
+
+ /* Ref clk = 27MHz and program pll5 to 288MHz */
+ writel_relaxed(0xF, PLL5_L_VAL);
+ writel_relaxed(0x0, PLL5_M_VAL);
+ writel_relaxed(0x1, PLL5_N_VAL);
+
+ regval = readl_relaxed(PLL5_CONFIG);
+ /* Disable the MN accumulator and enable the main output. */
+ regval &= ~BIT(22);
+ regval |= BIT(23);
+
+ /* Set pre-divider and post-divider values to 1 and 1 */
+ regval &= ~BIT(19);
+ regval &= ~(BIT(21)|BIT(20));
+
+ /* Set VCO frequency */
+ regval &= ~(BIT(17)|BIT(16));
+ writel_relaxed(regval, PLL5_CONFIG);
+
+ regval = readl_relaxed(PLL5_MODE);
+ /* De-assert reset to FSM */
+ regval &= ~BIT(21);
+ writel_relaxed(regval, PLL5_MODE);
+
+ /* Program bias count */
+ regval &= ~(0x3F << 14);
+ regval |= (0x1 << 14);
+ writel_relaxed(regval, PLL5_MODE);
+
+ /* Program lock count */
+ regval &= ~(0x3F << 8);
+ regval |= (0x8 << 8);
+ writel_relaxed(regval, PLL5_MODE);
+
+ /* Enable PLL FSM voting */
+ regval |= BIT(20);
+ writel_relaxed(regval, PLL5_MODE);
+ }
+}
+
+static int __devinit pil_gss_probe(struct platform_device *pdev)
+{
+ struct gss_data *drv;
+ struct resource *res;
+ struct pil_desc *desc;
+ int ret;
+
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ if (!res)
+ return -EINVAL;
+
+ drv = devm_kzalloc(&pdev->dev, sizeof(*drv), GFP_KERNEL);
+ if (!drv)
+ return -ENOMEM;
+ platform_set_drvdata(pdev, drv);
+
+ drv->base = devm_ioremap(&pdev->dev, res->start, resource_size(res));
+ if (!drv->base)
+ return -ENOMEM;
+
+ desc = devm_kzalloc(&pdev->dev, sizeof(*desc), GFP_KERNEL);
+ if (!desc)
+ return -ENOMEM;
+
+ drv->xo = clk_get(&pdev->dev, "xo");
+ if (IS_ERR(drv->xo))
+ return PTR_ERR(drv->xo);
+
+ desc->name = "gss";
+ desc->dev = &pdev->dev;
+
+ desc->ops = &pil_gss_ops;
+ dev_info(&pdev->dev, "using non-secure boot\n");
+
+ INIT_DELAYED_WORK(&drv->work, remove_gss_proxy_votes);
+
+ /* FIXME: Remove when PLL is configured by bootloaders. */
+ configure_gss_pll(drv);
+
+ ret = msm_pil_register(desc);
+ if (ret) {
+ flush_delayed_work_sync(&drv->work);
+ clk_put(drv->xo);
+ }
+ return ret;
+}
+
+static int __devexit pil_gss_remove(struct platform_device *pdev)
+{
+ struct gss_data *drv = platform_get_drvdata(pdev);
+ flush_delayed_work_sync(&drv->work);
+ clk_put(drv->xo);
+ return 0;
+}
+
+static struct platform_driver pil_gss_driver = {
+ .probe = pil_gss_probe,
+ .remove = __devexit_p(pil_gss_remove),
+ .driver = {
+ .name = "pil_gss",
+ .owner = THIS_MODULE,
+ },
+};
+
+static int __init pil_gss_init(void)
+{
+ return platform_driver_register(&pil_gss_driver);
+}
+module_init(pil_gss_init);
+
+static void __exit pil_gss_exit(void)
+{
+ platform_driver_unregister(&pil_gss_driver);
+}
+module_exit(pil_gss_exit);
+
+MODULE_DESCRIPTION("Support for booting the GSS processor");
+MODULE_LICENSE("GPL v2");
diff --git a/arch/arm/mach-msm/platsmp.c b/arch/arm/mach-msm/platsmp.c
index f1c6c48..3c422009 100644
--- a/arch/arm/mach-msm/platsmp.c
+++ b/arch/arm/mach-msm/platsmp.c
@@ -25,7 +25,7 @@
#include <mach/hardware.h>
#include <mach/msm_iomap.h>
-#include <mach/pm.h>
+#include "pm.h"
#include "scm-boot.h"
#include "spm.h"
diff --git a/arch/arm/mach-msm/pm-8x60.c b/arch/arm/mach-msm/pm-8x60.c
index 9bdc2b3..b3c6d1e 100644
--- a/arch/arm/mach-msm/pm-8x60.c
+++ b/arch/arm/mach-msm/pm-8x60.c
@@ -44,7 +44,7 @@
#include "avs.h"
#include <mach/cpuidle.h>
#include "idle.h"
-#include <mach/pm.h>
+#include "pm.h"
#include "rpm_resources.h"
#include "scm-boot.h"
#include "spm.h"
diff --git a/arch/arm/mach-msm/pm.c b/arch/arm/mach-msm/pm.c
index 3dcbfb3..d684a5a 100644
--- a/arch/arm/mach-msm/pm.c
+++ b/arch/arm/mach-msm/pm.c
@@ -44,7 +44,7 @@
#include "irq.h"
#include "gpio.h"
#include "timer.h"
-#include <mach/pm.h>
+#include "pm.h"
#include "pm-boot.h"
enum {
diff --git a/arch/arm/mach-msm/include/mach/pm.h b/arch/arm/mach-msm/pm.h
similarity index 88%
rename from arch/arm/mach-msm/include/mach/pm.h
rename to arch/arm/mach-msm/pm.h
index 689cd17..892472b 100644
--- a/arch/arm/mach-msm/include/mach/pm.h
+++ b/arch/arm/mach-msm/pm.h
@@ -1,7 +1,7 @@
/* arch/arm/mach-msm/pm.h
*
* Copyright (C) 2007 Google, Inc.
- * Copyright (c) 2009-2011, Code Aurora Forum. All rights reserved.
+ * Copyright (c) 2009-2012, Code Aurora Forum. All rights reserved.
* Author: San Mehat <san@android.com>
*
* This software is licensed under the terms of the GNU General Public
@@ -64,10 +64,14 @@
void __init msm_pm_init_sleep_status_data(
struct msm_pm_sleep_status_data *sleep_data);
-#ifdef CONFIG_PM
+#ifdef CONFIG_MSM_PM8X60
void msm_pm_set_rpm_wakeup_irq(unsigned int irq);
+int msm_pm_wait_cpu_shutdown(unsigned int cpu);
+bool msm_pm_verify_cpu_pc(unsigned int cpu);
#else
static inline void msm_pm_set_rpm_wakeup_irq(unsigned int irq) {}
+static inline int msm_pm_wait_cpu_shutdown(unsigned int cpu) { return 0; }
+static inline bool msm_pm_verify_cpu_pc(unsigned int cpu) { return true; }
#endif
#ifdef CONFIG_HOTPLUG_CPU
diff --git a/arch/arm/mach-msm/pm2.c b/arch/arm/mach-msm/pm2.c
index 0518ea2..4cdd7ae 100644
--- a/arch/arm/mach-msm/pm2.c
+++ b/arch/arm/mach-msm/pm2.c
@@ -58,7 +58,7 @@
#include "irq.h"
#include "gpio.h"
#include "timer.h"
-#include <mach/pm.h>
+#include "pm.h"
#include "spm.h"
#include "sirc.h"
#include "pm-boot.h"
diff --git a/arch/arm/mach-msm/qdsp5v2/audio_adpcm.c b/arch/arm/mach-msm/qdsp5v2/audio_adpcm.c
index 0ddba89..4b8b7a6 100644
--- a/arch/arm/mach-msm/qdsp5v2/audio_adpcm.c
+++ b/arch/arm/mach-msm/qdsp5v2/audio_adpcm.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2009-2011, Code Aurora Forum. All rights reserved.
+/* Copyright (c) 2009-2012, Code Aurora Forum. All rights reserved.
*
* Based on the mp3 native driver in arch/arm/mach-msm/qdsp5v2/audio_mp3.c
*
@@ -196,8 +196,10 @@
static void audplay_config_hostpcm(struct audio *audio);
static void audplay_buffer_refresh(struct audio *audio);
static void audio_dsp_event(void *private, unsigned id, uint16_t *msg);
+#ifdef CONFIG_HAS_EARLYSUSPEND
static void audadpcm_post_event(struct audio *audio, int type,
union msm_audio_event_payload payload);
+#endif
/* must be called with audio->lock held */
static int audio_enable(struct audio *audio)
@@ -1433,6 +1435,7 @@
return 0;
}
+#ifdef CONFIG_HAS_EARLYSUSPEND
static void audadpcm_post_event(struct audio *audio, int type,
union msm_audio_event_payload payload)
{
@@ -1461,7 +1464,6 @@
wake_up(&audio->event_wait);
}
-#ifdef CONFIG_HAS_EARLYSUSPEND
static void audadpcm_suspend(struct early_suspend *h)
{
struct audadpcm_suspend_ctl *ctl =
diff --git a/arch/arm/mach-msm/qdsp5v2/audio_amrnb.c b/arch/arm/mach-msm/qdsp5v2/audio_amrnb.c
index 85a3daa..a09b71b 100644
--- a/arch/arm/mach-msm/qdsp5v2/audio_amrnb.c
+++ b/arch/arm/mach-msm/qdsp5v2/audio_amrnb.c
@@ -1,7 +1,7 @@
/*
* amrnb audio decoder device
*
- * Copyright (c) 2008-2011, Code Aurora Forum. All rights reserved.
+ * Copyright (c) 2008-2012, Code Aurora Forum. All rights reserved.
*
* Based on the mp3 native driver in arch/arm/mach-msm/qdsp5/audio_mp3.c
*
@@ -194,8 +194,10 @@
static void audamrnb_config_hostpcm(struct audio *audio);
static void audamrnb_buffer_refresh(struct audio *audio);
static void audamrnb_dsp_event(void *private, unsigned id, uint16_t *msg);
+#ifdef CONFIG_HAS_EARLYSUSPEND
static void audamrnb_post_event(struct audio *audio, int type,
union msm_audio_event_payload payload);
+#endif
/* must be called with audio->lock held */
static int audamrnb_enable(struct audio *audio)
@@ -1330,6 +1332,7 @@
return 0;
}
+#ifdef CONFIG_HAS_EARLYSUSPEND
static void audamrnb_post_event(struct audio *audio, int type,
union msm_audio_event_payload payload)
{
@@ -1358,7 +1361,6 @@
wake_up(&audio->event_wait);
}
-#ifdef CONFIG_HAS_EARLYSUSPEND
static void audamrnb_suspend(struct early_suspend *h)
{
struct audamrnb_suspend_ctl *ctl =
diff --git a/arch/arm/mach-msm/qdsp5v2/audio_amrwb.c b/arch/arm/mach-msm/qdsp5v2/audio_amrwb.c
index d6cf21d..48e9a9f 100644
--- a/arch/arm/mach-msm/qdsp5v2/audio_amrwb.c
+++ b/arch/arm/mach-msm/qdsp5v2/audio_amrwb.c
@@ -1,6 +1,6 @@
/* amrwb audio decoder device
*
- * Copyright (c) 2008-2011, Code Aurora Forum. All rights reserved.
+ * Copyright (c) 2008-2012, Code Aurora Forum. All rights reserved.
*
* Based on the mp3 native driver in arch/arm/mach-msm/qdsp5v2/audio_mp3.c
*
@@ -195,8 +195,10 @@
static void audamrwb_config_hostpcm(struct audio *audio);
static void audamrwb_buffer_refresh(struct audio *audio);
static void audamrwb_dsp_event(void *private, unsigned id, uint16_t *msg);
+#ifdef CONFIG_HAS_EARLYSUSPEND
static void audamrwb_post_event(struct audio *audio, int type,
union msm_audio_event_payload payload);
+#endif
/* must be called with audio->lock held */
static int audamrwb_enable(struct audio *audio)
@@ -1414,6 +1416,7 @@
return 0;
}
+#ifdef CONFIG_HAS_EARLYSUSPEND
static void audamrwb_post_event(struct audio *audio, int type,
union msm_audio_event_payload payload)
{
@@ -1442,7 +1445,6 @@
wake_up(&audio->event_wait);
}
-#ifdef CONFIG_HAS_EARLYSUSPEND
static void audamrwb_suspend(struct early_suspend *h)
{
struct audamrwb_suspend_ctl *ctl =
diff --git a/arch/arm/mach-msm/qdsp5v2/audio_evrc.c b/arch/arm/mach-msm/qdsp5v2/audio_evrc.c
index e5261b5..9b5694d 100644
--- a/arch/arm/mach-msm/qdsp5v2/audio_evrc.c
+++ b/arch/arm/mach-msm/qdsp5v2/audio_evrc.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2008-2011, Code Aurora Forum. All rights reserved.
+ * Copyright (c) 2008-2012, Code Aurora Forum. All rights reserved.
*
* This code also borrows from audio_aac.c, which is
* Copyright (C) 2008 Google, Inc.
@@ -189,8 +189,10 @@
static void audevrc_dsp_event(void *private, unsigned id, uint16_t *msg);
static void audevrc_config_hostpcm(struct audio *audio);
static void audevrc_buffer_refresh(struct audio *audio);
+#ifdef CONFIG_HAS_EARLYSUSPEND
static void audevrc_post_event(struct audio *audio, int type,
union msm_audio_event_payload payload);
+#endif
/* must be called with audio->lock held */
static int audevrc_enable(struct audio *audio)
@@ -1324,6 +1326,7 @@
return 0;
}
+#ifdef CONFIG_HAS_EARLYSUSPEND
static void audevrc_post_event(struct audio *audio, int type,
union msm_audio_event_payload payload)
{
@@ -1352,7 +1355,6 @@
wake_up(&audio->event_wait);
}
-#ifdef CONFIG_HAS_EARLYSUSPEND
static void audevrc_suspend(struct early_suspend *h)
{
struct audevrc_suspend_ctl *ctl =
diff --git a/arch/arm/mach-msm/qdsp5v2/audio_mp3.c b/arch/arm/mach-msm/qdsp5v2/audio_mp3.c
index 0e61e84..c639833 100644
--- a/arch/arm/mach-msm/qdsp5v2/audio_mp3.c
+++ b/arch/arm/mach-msm/qdsp5v2/audio_mp3.c
@@ -2,7 +2,7 @@
*
* Copyright (C) 2008 Google, Inc.
* Copyright (C) 2008 HTC Corporation
- * Copyright (c) 2009-2011, Code Aurora Forum. All rights reserved.
+ * Copyright (c) 2009-2012, Code Aurora Forum. All rights reserved.
*
* This software is licensed under the terms of the GNU General Public
* License version 2, as published by the Free Software Foundation, and
@@ -112,6 +112,7 @@
int res = (IN_RANGE(__r1, __v) || IN_RANGE(__r1, __e)); \
res; \
})
+struct audio;
struct buffer {
void *data;
diff --git a/arch/arm/mach-msm/qdsp5v2/audio_pcm.c b/arch/arm/mach-msm/qdsp5v2/audio_pcm.c
index 139c16c..b22820b 100644
--- a/arch/arm/mach-msm/qdsp5v2/audio_pcm.c
+++ b/arch/arm/mach-msm/qdsp5v2/audio_pcm.c
@@ -3,7 +3,7 @@
*
* Copyright (C) 2008 Google, Inc.
* Copyright (C) 2008 HTC Corporation
- * Copyright (c) 2009-2011, Code Aurora Forum. All rights reserved.
+ * Copyright (c) 2009-2012, Code Aurora Forum. All rights reserved.
*
* This software is licensed under the terms of the GNU General Public
* License version 2, as published by the Free Software Foundation, and
@@ -101,6 +101,8 @@
res; \
})
+struct audio;
+
struct buffer {
void *data;
unsigned size;
diff --git a/arch/arm/mach-msm/qdsp5v2/audio_qcelp.c b/arch/arm/mach-msm/qdsp5v2/audio_qcelp.c
index f3f0619..ce5d421 100644
--- a/arch/arm/mach-msm/qdsp5v2/audio_qcelp.c
+++ b/arch/arm/mach-msm/qdsp5v2/audio_qcelp.c
@@ -1,7 +1,7 @@
/*
* qcelp 13k audio decoder device
*
- * Copyright (c) 2008-2011, Code Aurora Forum. All rights reserved.
+ * Copyright (c) 2008-2012, Code Aurora Forum. All rights reserved.
*
* This code is based in part on audio_mp3.c, which is
* Copyright (C) 2008 Google, Inc.
@@ -184,8 +184,10 @@
static void audqcelp_config_hostpcm(struct audio *audio);
static void audqcelp_buffer_refresh(struct audio *audio);
static void audqcelp_dsp_event(void *private, unsigned id, uint16_t *msg);
+#ifdef CONFIG_HAS_EARLYSUSPEND
static void audqcelp_post_event(struct audio *audio, int type,
union msm_audio_event_payload payload);
+#endif
/* must be called with audio->lock held */
static int audqcelp_enable(struct audio *audio)
@@ -1326,6 +1328,7 @@
return 0;
}
+#ifdef CONFIG_HAS_EARLYSUSPEND
static void audqcelp_post_event(struct audio *audio, int type,
union msm_audio_event_payload payload)
{
@@ -1354,7 +1357,6 @@
wake_up(&audio->event_wait);
}
-#ifdef CONFIG_HAS_EARLYSUSPEND
static void audqcelp_suspend(struct early_suspend *h)
{
struct audqcelp_suspend_ctl *ctl =
diff --git a/arch/arm/mach-msm/qdsp5v2/audio_wma.c b/arch/arm/mach-msm/qdsp5v2/audio_wma.c
index 464f66e..f29b078 100644
--- a/arch/arm/mach-msm/qdsp5v2/audio_wma.c
+++ b/arch/arm/mach-msm/qdsp5v2/audio_wma.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2009-2011, Code Aurora Forum. All rights reserved.
+/* Copyright (c) 2009-2012, Code Aurora Forum. All rights reserved.
*
* Based on the mp3 native driver in arch/arm/mach-msm/qdsp5v2/audio_mp3.c
*
@@ -200,9 +200,10 @@
static void audplay_config_hostpcm(struct audio *audio);
static void audplay_buffer_refresh(struct audio *audio);
static void audio_dsp_event(void *private, unsigned id, uint16_t *msg);
+#ifdef CONFIG_HAS_EARLYSUSPEND
static void audwma_post_event(struct audio *audio, int type,
union msm_audio_event_payload payload);
-
+#endif
/* must be called with audio->lock held */
static int audio_enable(struct audio *audio)
{
@@ -1472,6 +1473,7 @@
return 0;
}
+#ifdef CONFIG_HAS_EARLYSUSPEND
static void audwma_post_event(struct audio *audio, int type,
union msm_audio_event_payload payload)
{
@@ -1500,7 +1502,6 @@
wake_up(&audio->event_wait);
}
-#ifdef CONFIG_HAS_EARLYSUSPEND
static void audwma_suspend(struct early_suspend *h)
{
struct audwma_suspend_ctl *ctl =
diff --git a/arch/arm/mach-msm/qdsp5v2/audio_wmapro.c b/arch/arm/mach-msm/qdsp5v2/audio_wmapro.c
index 878237e..cf25359 100644
--- a/arch/arm/mach-msm/qdsp5v2/audio_wmapro.c
+++ b/arch/arm/mach-msm/qdsp5v2/audio_wmapro.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2009-2011, Code Aurora Forum. All rights reserved.
+/* Copyright (c) 2009-2012, Code Aurora Forum. All rights reserved.
*
* Based on the mp3 native driver in arch/arm/mach-msm/qdsp5v2/audio_mp3.c
*
@@ -200,8 +200,10 @@
static void audplay_config_hostpcm(struct audio *audio);
static void audplay_buffer_refresh(struct audio *audio);
static void audio_dsp_event(void *private, unsigned id, uint16_t *msg);
+#ifdef CONFIG_HAS_EARLYSUSPEND
static void audwmapro_post_event(struct audio *audio, int type,
union msm_audio_event_payload payload);
+#endif
/* must be called with audio->lock held */
static int audio_enable(struct audio *audio)
@@ -1484,6 +1486,7 @@
return 0;
}
+#ifdef CONFIG_HAS_EARLYSUSPEND
static void audwmapro_post_event(struct audio *audio, int type,
union msm_audio_event_payload payload)
{
@@ -1512,7 +1515,6 @@
wake_up(&audio->event_wait);
}
-#ifdef CONFIG_HAS_EARLYSUSPEND
static void audwmapro_suspend(struct early_suspend *h)
{
struct audwmapro_suspend_ctl *ctl =
diff --git a/arch/arm/mach-msm/rpm_resources.h b/arch/arm/mach-msm/rpm_resources.h
index da9d3ff..a5c61b2 100644
--- a/arch/arm/mach-msm/rpm_resources.h
+++ b/arch/arm/mach-msm/rpm_resources.h
@@ -15,7 +15,7 @@
#define __ARCH_ARM_MACH_MSM_RPM_RESOURCES_H
#include <mach/rpm.h>
-#include <mach/pm.h>
+#include "pm.h"
enum {
MSM_RPMRS_ID_PXO_CLK = 0,
diff --git a/arch/arm/mach-msm/spm_devices.c b/arch/arm/mach-msm/spm_devices.c
index 326faef..0aa1358 100644
--- a/arch/arm/mach-msm/spm_devices.c
+++ b/arch/arm/mach-msm/spm_devices.c
@@ -167,23 +167,26 @@
uint32_t val = 0;
uint32_t timeout = 0;
void *reg = NULL;
+ void *saw_bases[] = {
+ 0,
+ MSM_SAW1_BASE,
+ MSM_SAW2_BASE,
+ MSM_SAW3_BASE
+ };
- if (cpu >= num_possible_cpus())
+ if (cpu == 0 || cpu >= num_possible_cpus())
return -EINVAL;
- switch (cpu) {
- case 1:
- reg = MSM_SAW1_BASE;
- break;
- case 0:
- default:
- return -EFAULT;
- }
+ reg = saw_bases[cpu];
if (cpu_is_msm8960() || cpu_is_msm8930()) {
val = 0xB0;
reg += 0x14;
timeout = 512;
+ } else if (cpu_is_apq8064()) {
+ val = 0xA4;
+ reg += 0x14;
+ timeout = 512;
} else {
return -ENOSYS;
}
diff --git a/drivers/media/video/msm/msm_io_8x60.c b/drivers/media/video/msm/msm_io_8x60.c
index bac650a..49ec461 100644
--- a/drivers/media/video/msm/msm_io_8x60.c
+++ b/drivers/media/video/msm/msm_io_8x60.c
@@ -460,10 +460,12 @@
static irqreturn_t msm_io_csi_irq(int irq_num, void *data)
{
- uint32_t irq;
- irq = msm_io_r(csibase + MIPI_INTERRUPT_STATUS);
+ uint32_t irq = 0;
+ if (csibase != NULL)
+ irq = msm_io_r(csibase + MIPI_INTERRUPT_STATUS);
CDBG("%s MIPI_INTERRUPT_STATUS = 0x%x\n", __func__, irq);
- msm_io_w(irq, csibase + MIPI_INTERRUPT_STATUS);
+ if (csibase != NULL)
+ msm_io_w(irq, csibase + MIPI_INTERRUPT_STATUS);
return IRQ_HANDLED;
}
@@ -604,8 +606,10 @@
csi_irq_fail:
iounmap(csibase);
+ csibase = NULL;
csi_busy:
release_mem_region(camio_ext.csiphy, camio_ext.csisz);
+ csibase = NULL;
common_fail:
msm_camio_clk_disable(CAMIO_CAM_MCLK_CLK);
msm_camio_clk_disable(CAMIO_CSI0_VFE_CLK);
@@ -625,27 +629,29 @@
uint32_t val;
val = 0x0;
- CDBG("%s MIPI_PHY_D0_CONTROL2 val=0x%x\n", __func__, val);
- msm_io_w(val, csibase + MIPI_PHY_D0_CONTROL2);
- msm_io_w(val, csibase + MIPI_PHY_D1_CONTROL2);
- msm_io_w(val, csibase + MIPI_PHY_D2_CONTROL2);
- msm_io_w(val, csibase + MIPI_PHY_D3_CONTROL2);
-
- CDBG("%s MIPI_PHY_CL_CONTROL val=0x%x\n", __func__, val);
- msm_io_w(val, csibase + MIPI_PHY_CL_CONTROL);
- msleep(10);
-
- val = msm_io_r(csibase + MIPI_PHY_D1_CONTROL);
- val &= ~((0x1 << MIPI_PHY_D1_CONTROL_MIPI_CLK_PHY_SHUTDOWNB_SHFT) |
- (0x1 << MIPI_PHY_D1_CONTROL_MIPI_DATA_PHY_SHUTDOWNB_SHFT));
- CDBG("%s MIPI_PHY_D1_CONTROL val=0x%x\n", __func__, val);
- msm_io_w(val, csibase + MIPI_PHY_D1_CONTROL);
- usleep_range(5000, 6000);
- msm_io_w(0x0, csibase + MIPI_INTERRUPT_MASK);
- msm_io_w(0x0, csibase + MIPI_INTERRUPT_STATUS);
- csi_free_irq();
- iounmap(csibase);
- release_mem_region(camio_ext.csiphy, camio_ext.csisz);
+ if (csibase != NULL) {
+ CDBG("%s MIPI_PHY_D0_CONTROL2 val=0x%x\n", __func__, val);
+ msm_io_w(val, csibase + MIPI_PHY_D0_CONTROL2);
+ msm_io_w(val, csibase + MIPI_PHY_D1_CONTROL2);
+ msm_io_w(val, csibase + MIPI_PHY_D2_CONTROL2);
+ msm_io_w(val, csibase + MIPI_PHY_D3_CONTROL2);
+ CDBG("%s MIPI_PHY_CL_CONTROL val=0x%x\n", __func__, val);
+ msm_io_w(val, csibase + MIPI_PHY_CL_CONTROL);
+ msleep(20);
+ val = msm_io_r(csibase + MIPI_PHY_D1_CONTROL);
+ val &=
+ ~((0x1 << MIPI_PHY_D1_CONTROL_MIPI_CLK_PHY_SHUTDOWNB_SHFT)
+ |(0x1 << MIPI_PHY_D1_CONTROL_MIPI_DATA_PHY_SHUTDOWNB_SHFT));
+ CDBG("%s MIPI_PHY_D1_CONTROL val=0x%x\n", __func__, val);
+ msm_io_w(val, csibase + MIPI_PHY_D1_CONTROL);
+ usleep_range(5000, 6000);
+ msm_io_w(0x0, csibase + MIPI_INTERRUPT_MASK);
+ msm_io_w(0x0, csibase + MIPI_INTERRUPT_STATUS);
+ csi_free_irq();
+ iounmap(csibase);
+ csibase = NULL;
+ release_mem_region(camio_ext.csiphy, camio_ext.csisz);
+ }
}
void msm_camio_disable(struct platform_device *pdev)
{
@@ -727,78 +733,82 @@
int i;
CDBG("msm_camio_csi_config\n");
+ if (csibase != NULL) {
+ /* SOT_ECC_EN enable error correction for SYNC (data-lane) */
+ msm_io_w(0x4, csibase + MIPI_PHY_CONTROL);
- /* SOT_ECC_EN enable error correction for SYNC (data-lane) */
- msm_io_w(0x4, csibase + MIPI_PHY_CONTROL);
-
- /* SW_RST to the CSI core */
- msm_io_w(MIPI_PROTOCOL_CONTROL_SW_RST_BMSK,
+ /* SW_RST to the CSI core */
+ msm_io_w(MIPI_PROTOCOL_CONTROL_SW_RST_BMSK,
csibase + MIPI_PROTOCOL_CONTROL);
- /* PROTOCOL CONTROL */
- val = MIPI_PROTOCOL_CONTROL_LONG_PACKET_HEADER_CAPTURE_BMSK |
- MIPI_PROTOCOL_CONTROL_DECODE_ID_BMSK |
- MIPI_PROTOCOL_CONTROL_ECC_EN_BMSK;
- val |= (uint32_t)(csi_params->data_format) <<
- MIPI_PROTOCOL_CONTROL_DATA_FORMAT_SHFT;
- val |= csi_params->dpcm_scheme <<
- MIPI_PROTOCOL_CONTROL_DPCM_SCHEME_SHFT;
- CDBG("%s MIPI_PROTOCOL_CONTROL val=0x%x\n", __func__, val);
- msm_io_w(val, csibase + MIPI_PROTOCOL_CONTROL);
+ /* PROTOCOL CONTROL */
+ val = MIPI_PROTOCOL_CONTROL_LONG_PACKET_HEADER_CAPTURE_BMSK |
+ MIPI_PROTOCOL_CONTROL_DECODE_ID_BMSK |
+ MIPI_PROTOCOL_CONTROL_ECC_EN_BMSK;
+ val |= (uint32_t)(csi_params->data_format) <<
+ MIPI_PROTOCOL_CONTROL_DATA_FORMAT_SHFT;
+ val |= csi_params->dpcm_scheme <<
+ MIPI_PROTOCOL_CONTROL_DPCM_SCHEME_SHFT;
+ CDBG("%s MIPI_PROTOCOL_CONTROL val=0x%x\n", __func__, val);
+ msm_io_w(val, csibase + MIPI_PROTOCOL_CONTROL);
- /* settle_cnt is very sensitive to speed!
- increase this value to run at higher speeds */
- val = (csi_params->settle_cnt <<
- MIPI_PHY_D0_CONTROL2_SETTLE_COUNT_SHFT) |
- (0x0F << MIPI_PHY_D0_CONTROL2_HS_TERM_IMP_SHFT) |
- (0x1 << MIPI_PHY_D0_CONTROL2_LP_REC_EN_SHFT) |
- (0x1 << MIPI_PHY_D0_CONTROL2_ERR_SOT_HS_EN_SHFT);
- CDBG("%s MIPI_PHY_D0_CONTROL2 val=0x%x\n", __func__, val);
- for (i = 0; i < csi_params->lane_cnt; i++)
- msm_io_w(val, csibase + MIPI_PHY_D0_CONTROL2 + i * 4);
+ /* settle_cnt is very sensitive to speed!
+ increase this value to run at higher speeds */
+ val = (csi_params->settle_cnt <<
+ MIPI_PHY_D0_CONTROL2_SETTLE_COUNT_SHFT) |
+ (0x0F << MIPI_PHY_D0_CONTROL2_HS_TERM_IMP_SHFT) |
+ (0x1 << MIPI_PHY_D0_CONTROL2_LP_REC_EN_SHFT) |
+ (0x1 << MIPI_PHY_D0_CONTROL2_ERR_SOT_HS_EN_SHFT);
+ CDBG("%s MIPI_PHY_D0_CONTROL2 val=0x%x\n", __func__, val);
+ for (i = 0; i < csi_params->lane_cnt; i++)
+ msm_io_w(val, csibase + MIPI_PHY_D0_CONTROL2 + i * 4);
- val = (0x0F << MIPI_PHY_CL_CONTROL_HS_TERM_IMP_SHFT) |
- (0x1 << MIPI_PHY_CL_CONTROL_LP_REC_EN_SHFT);
- CDBG("%s MIPI_PHY_CL_CONTROL val=0x%x\n", __func__, val);
- msm_io_w(val, csibase + MIPI_PHY_CL_CONTROL);
+ val = (0x0F << MIPI_PHY_CL_CONTROL_HS_TERM_IMP_SHFT) |
+ (0x1 << MIPI_PHY_CL_CONTROL_LP_REC_EN_SHFT);
+ CDBG("%s MIPI_PHY_CL_CONTROL val=0x%x\n", __func__, val);
+ msm_io_w(val, csibase + MIPI_PHY_CL_CONTROL);
- val = 0 << MIPI_PHY_D0_CONTROL_HS_REC_EQ_SHFT;
- msm_io_w(val, csibase + MIPI_PHY_D0_CONTROL);
+ val = 0 << MIPI_PHY_D0_CONTROL_HS_REC_EQ_SHFT;
+ msm_io_w(val, csibase + MIPI_PHY_D0_CONTROL);
- val = (0x1 << MIPI_PHY_D1_CONTROL_MIPI_CLK_PHY_SHUTDOWNB_SHFT) |
- (0x1 << MIPI_PHY_D1_CONTROL_MIPI_DATA_PHY_SHUTDOWNB_SHFT);
- CDBG("%s MIPI_PHY_D1_CONTROL val=0x%x\n", __func__, val);
- msm_io_w(val, csibase + MIPI_PHY_D1_CONTROL);
+ val =
+ (0x1 << MIPI_PHY_D1_CONTROL_MIPI_CLK_PHY_SHUTDOWNB_SHFT)
+ |(0x1 << MIPI_PHY_D1_CONTROL_MIPI_DATA_PHY_SHUTDOWNB_SHFT);
+ CDBG("%s MIPI_PHY_D1_CONTROL val=0x%x\n", __func__, val);
+ msm_io_w(val, csibase + MIPI_PHY_D1_CONTROL);
- msm_io_w(0x00000000, csibase + MIPI_PHY_D2_CONTROL);
- msm_io_w(0x00000000, csibase + MIPI_PHY_D3_CONTROL);
+ msm_io_w(0x00000000, csibase + MIPI_PHY_D2_CONTROL);
+ msm_io_w(0x00000000, csibase + MIPI_PHY_D3_CONTROL);
- /* halcyon only supports 1 or 2 lane */
- switch (csi_params->lane_cnt) {
- case 1:
- msm_io_w(csi_params->lane_assign << 8 | 0x4,
- csibase + MIPI_CAMERA_CNTL);
- break;
- case 2:
- msm_io_w(csi_params->lane_assign << 8 | 0x5,
- csibase + MIPI_CAMERA_CNTL);
- break;
- case 3:
- msm_io_w(csi_params->lane_assign << 8 | 0x6,
- csibase + MIPI_CAMERA_CNTL);
- break;
- case 4:
- msm_io_w(csi_params->lane_assign << 8 | 0x7,
- csibase + MIPI_CAMERA_CNTL);
- break;
+ /* halcyon only supports 1 or 2 lane */
+ switch (csi_params->lane_cnt) {
+ case 1:
+ msm_io_w(csi_params->lane_assign << 8 | 0x4,
+ csibase + MIPI_CAMERA_CNTL);
+ break;
+ case 2:
+ msm_io_w(csi_params->lane_assign << 8 | 0x5,
+ csibase + MIPI_CAMERA_CNTL);
+ break;
+ case 3:
+ msm_io_w(csi_params->lane_assign << 8 | 0x6,
+ csibase + MIPI_CAMERA_CNTL);
+ break;
+ case 4:
+ msm_io_w(csi_params->lane_assign << 8 | 0x7,
+ csibase + MIPI_CAMERA_CNTL);
+ break;
+ }
+
+ /* mask out ID_ERROR[19], DATA_CMM_ERR[11]
+ and CLK_CMM_ERR[10] - de-featured */
+ msm_io_w(0xF017F3C0, csibase + MIPI_INTERRUPT_MASK);
+ /*clear IRQ bits*/
+ msm_io_w(0xF017F3C0, csibase + MIPI_INTERRUPT_STATUS);
+ } else {
+ pr_info("CSIBASE is NULL");
}
- /* mask out ID_ERROR[19], DATA_CMM_ERR[11]
- and CLK_CMM_ERR[10] - de-featured */
- msm_io_w(0xF017F3C0, csibase + MIPI_INTERRUPT_MASK);
- /*clear IRQ bits*/
- msm_io_w(0xF017F3C0, csibase + MIPI_INTERRUPT_STATUS);
-
return rc;
}
diff --git a/drivers/media/video/msm/wfd/Makefile b/drivers/media/video/msm/wfd/Makefile
index 7ea9db3..2b39e66 100644
--- a/drivers/media/video/msm/wfd/Makefile
+++ b/drivers/media/video/msm/wfd/Makefile
@@ -1,5 +1,4 @@
-#obj-$(CONFIG_MSM_WFD_V4L2) += wfd-ioctl.o
-#obj-$(CONFIG_MSM_WFD_V4L2) += enc-subdev.o
obj-y += mdp-subdev.o
obj-y += enc-subdev.o
+obj-y += vsg-subdev.o
obj-y += wfd-ioctl.o
diff --git a/drivers/media/video/msm/wfd/enc-subdev.c b/drivers/media/video/msm/wfd/enc-subdev.c
index 00a688c..e3d9d2d 100644
--- a/drivers/media/video/msm/wfd/enc-subdev.c
+++ b/drivers/media/video/msm/wfd/enc-subdev.c
@@ -147,7 +147,6 @@
struct vb2_buffer *vbuf;
struct mem_region *mregion;
struct vcd_frame_data *frame_data = (struct vcd_frame_data *)info;
- struct timespec ts;
if (!client_ctx) {
WFD_MSG_ERR("Client context is NULL\n");
@@ -190,9 +189,8 @@
break;
}
- ktime_get_ts(&ts);
- vbuf->v4l2_buf.timestamp.tv_sec = ts.tv_sec;
- vbuf->v4l2_buf.timestamp.tv_usec = ts.tv_nsec/1000;
+ vbuf->v4l2_buf.timestamp =
+ ns_to_timeval(frame_data->time_stamp);
WFD_MSG_DBG("bytes used %d, ts: %d.%d, frame type is %d\n",
frame_data->data_len,
@@ -942,8 +940,9 @@
vcd_property_hdr.prop_id = VCD_I_FRAME_RATE;
vcd_property_hdr.sz =
sizeof(struct vcd_property_frame_rate);
- vcd_frame_rate.fps_denominator = frate->denominator;
- vcd_frame_rate.fps_numerator = frate->numerator;
+ /* v4l2 passes in "fps" as "spf", so take reciprocal*/
+ vcd_frame_rate.fps_denominator = frate->numerator;
+ vcd_frame_rate.fps_numerator = frate->denominator;
rc = vcd_set_property(client_ctx->vcd_handle,
&vcd_property_hdr, &vcd_frame_rate);
if (rc)
@@ -988,8 +987,9 @@
mregion->offset,
32,
mregion->size);
- if (!rc) {
+ if (rc == (u32)false) {
WFD_MSG_ERR("Failed to insert outbuf in table\n");
+ rc = -EINVAL;
goto err;
}
WFD_MSG_DBG("size = %u, %p\n", mregion->size, mregion->kvaddr);
@@ -1040,14 +1040,15 @@
int rc = 0;
struct venc_inst *inst = sd->dev_priv;
struct video_client_ctx *client_ctx = &inst->venc_client;
- struct mem_region *mregion = arg;
+ struct venc_buf_info *venc_buf = arg;
+ struct mem_region *mregion = venc_buf->mregion;
struct vcd_frame_data vcd_input_buffer = {0};
vcd_input_buffer.virtual = mregion->kvaddr;
vcd_input_buffer.frm_clnt_data = (u32)mregion;
vcd_input_buffer.ip_frm_tag = (u32)mregion;
vcd_input_buffer.data_len = mregion->size;
- vcd_input_buffer.time_stamp = 0; /*TODO: Need to fix this*/
+ vcd_input_buffer.time_stamp = venc_buf->timestamp;
vcd_input_buffer.offset = 0;
rc = vcd_encode_frame(client_ctx->vcd_handle,
diff --git a/drivers/media/video/msm/wfd/enc-subdev.h b/drivers/media/video/msm/wfd/enc-subdev.h
index 890c973..0f7ca5f 100644
--- a/drivers/media/video/msm/wfd/enc-subdev.h
+++ b/drivers/media/video/msm/wfd/enc-subdev.h
@@ -11,6 +11,9 @@
*
*/
+#ifndef _WFD_ENC_SUBDEV_
+#define _WFD_ENC_SUBDEV_
+
#include <media/v4l2-subdev.h>
#include <media/videobuf2-core.h>
#define VENC_MAGIC_IOCTL 'V'
@@ -30,6 +33,12 @@
u32 width;
u32 size;
};
+
+struct venc_buf_info {
+ u64 timestamp;
+ struct mem_region *mregion;
+};
+
struct venc_msg_ops {
void *cookie;
void *cbdata;
@@ -42,7 +51,7 @@
#define OPEN _IOR('V', 1, void *)
#define CLOSE _IO('V', 2)
#define ENCODE_START _IO('V', 3)
-#define ENCODE_FRAME _IO('V', 4)
+#define ENCODE_FRAME _IOW('V', 4, struct venc_buf_info *)
#define PAUSE _IO('V', 5)
#define RESUME _IO('V', 6)
#define FLUSH _IO('V', 7)
@@ -66,3 +75,6 @@
extern int venc_init(struct v4l2_subdev *sd, u32 val);
extern int venc_load_fw(struct v4l2_subdev *sd);
extern long venc_ioctl(struct v4l2_subdev *sd, unsigned int cmd, void *arg);
+
+
+#endif /* _WFD_ENC_SUBDEV_ */
diff --git a/drivers/media/video/msm/wfd/mdp-subdev.c b/drivers/media/video/msm/wfd/mdp-subdev.c
index 9fd8a8e..e519a4d 100644
--- a/drivers/media/video/msm/wfd/mdp-subdev.c
+++ b/drivers/media/video/msm/wfd/mdp-subdev.c
@@ -135,8 +135,9 @@
fbdata.priv = (uint32_t)binfo->cookie;
WFD_MSG_INFO("queue buffer to mdp with offset = %u,"
- "fd = %u, priv = %u\n",
- fbdata.offset, fbdata.memory_id, fbdata.priv);
+ "fd = %u, priv = %p, iova = %p\n",
+ fbdata.offset, fbdata.memory_id,
+ (void *)fbdata.priv, (void *)fbdata.iova);
rc = msm_fb_writeback_queue_buffer(inst->mdp, &fbdata);
if (rc)
diff --git a/drivers/media/video/msm/wfd/mdp-subdev.h b/drivers/media/video/msm/wfd/mdp-subdev.h
index a6b3bc4..081fead 100644
--- a/drivers/media/video/msm/wfd/mdp-subdev.h
+++ b/drivers/media/video/msm/wfd/mdp-subdev.h
@@ -11,6 +11,9 @@
*
*/
+#ifndef _WFD_MDP_SUBDEV_
+#define _WFD_MDP_SUBDEV_
+
#include <linux/videodev2.h>
#include <media/v4l2-subdev.h>
@@ -30,6 +33,17 @@
u32 height;
u32 width;
};
+
+static inline bool mdp_buf_info_equals(struct mdp_buf_info *a,
+ struct mdp_buf_info *b)
+{
+ return a->inst == b->inst
+ && a->fd == b->fd
+ && a->offset == b->offset
+ && a->kvaddr == b->kvaddr
+ && a->paddr == b->paddr;
+}
+
#define MDP_Q_BUFFER _IOW(MDP_MAGIC_IOCTL, 1, struct mdp_buf_info *)
#define MDP_DQ_BUFFER _IOR(MDP_MAGIC_IOCTL, 2, struct mdp_out_buf *)
#define MDP_OPEN _IOR(MDP_MAGIC_IOCTL, 3, void **)
@@ -39,3 +53,6 @@
#define MDP_STOP _IOR(MDP_MAGIC_IOCTL, 7, void *)
extern int mdp_init(struct v4l2_subdev *sd, u32 val);
extern long mdp_ioctl(struct v4l2_subdev *sd, unsigned int cmd, void *arg);
+
+
+#endif /* _WFD_MDP_SUBDEV_ */
diff --git a/drivers/media/video/msm/wfd/vsg-subdev.c b/drivers/media/video/msm/wfd/vsg-subdev.c
new file mode 100644
index 0000000..53b6e20
--- /dev/null
+++ b/drivers/media/video/msm/wfd/vsg-subdev.c
@@ -0,0 +1,693 @@
+/* Copyright (c) 2012, Code Aurora Forum. All rights reserved.
+*
+* This program is free software; you can redistribute it and/or modify
+* it under the terms of the GNU General Public License version 2 and
+* only version 2 as published by the Free Software Foundation.
+*
+* This program is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+*/
+#include <linux/hrtimer.h>
+#include <linux/time.h>
+#include <linux/list.h>
+#include <media/videobuf2-core.h>
+#include "enc-subdev.h"
+#include "vsg-subdev.h"
+#include "wfd-util.h"
+
+#define DEFAULT_FRAME_INTERVAL (66*NSEC_PER_MSEC)
+#define DEFAULT_MAX_FRAME_INTERVAL (1*NSEC_PER_SEC)
+#define DEFAULT_MODE ((enum vsg_modes)VSG_MODE_CFR)
+
+static int vsg_release_input_buffer(struct vsg_context *context,
+ struct vsg_buf_info *buf)
+{
+ WFD_MSG_DBG("Releasing frame with ts %lld ms, paddr %p\n",
+ timespec_to_ns(&buf->time),
+ (void *)buf->mdp_buf_info.paddr);
+
+ if (buf->flags & VSG_NEVER_RELEASE)
+ WFD_MSG_WARN("Warning releasing buffer that's"
+ "not supposed to be released\n");
+
+ return context->vmops.release_input_frame(context->vmops.cbdata,
+ buf);
+
+}
+
+static int vsg_encode_frame(struct vsg_context *context,
+ struct vsg_buf_info *buf)
+{
+ WFD_MSG_DBG("Encoding frame with ts %lld ms, paddr %p\n",
+ timespec_to_ns(&buf->time),
+ (void *)buf->mdp_buf_info.paddr);
+
+ return context->vmops.encode_frame(context->vmops.cbdata,
+ buf);
+}
+
+static void vsg_set_last_buffer(struct vsg_context *context,
+ struct vsg_buf_info *buf)
+{
+ if (buf->flags & VSG_NEVER_SET_LAST_BUFFER)
+ WFD_MSG_WARN("Shouldn't be setting this to last buffer\n");
+
+ /* Update the last buffer and memcpy the data into the back up buffer*/
+ context->last_buffer = buf;
+
+ WFD_MSG_DBG("Setting last buffer to paddr %p\n",
+ (void *)buf->mdp_buf_info.paddr);
+
+ if (context->regen_buffer) {
+ int buf_size;
+ void *cookie;
+
+ /*FIXME: Somewhat hacky, looking into cookie */
+ cookie = buf->mdp_buf_info.cookie;
+ buf_size = ((struct mem_region *)cookie)->size;
+
+ memcpy((void *)context->regen_buffer->mdp_buf_info.kvaddr,
+ (void *)buf->mdp_buf_info.kvaddr,
+ buf_size);
+ context->send_regen_buffer = false;
+ }
+}
+
+static void vsg_work_func(struct work_struct *task)
+{
+ struct vsg_work *work =
+ container_of(task, struct vsg_work, work);
+ struct vsg_context *context = work->context;
+ struct vsg_buf_info *buf_info = NULL, *temp = NULL;
+ int rc = 0;
+ mutex_lock(&context->mutex);
+
+ if (list_empty(&context->free_queue.node)) {
+ WFD_MSG_DBG("%s: queue empty doing nothing\n", __func__);
+ goto err_skip_encode;
+ } else if (context->stopped) {
+ WFD_MSG_DBG("%s: vsg is stopped doing nothing\n", __func__);
+ goto err_skip_encode;
+ }
+
+ buf_info = list_first_entry(&context->free_queue.node,
+ struct vsg_buf_info, node);
+ list_del(&buf_info->node);
+ INIT_LIST_HEAD(&buf_info->node);
+
+ ktime_get_ts(&buf_info->time);
+ mod_timer(&context->threshold_timer, jiffies +
+ nsecs_to_jiffies(context->max_frame_interval));
+
+ list_for_each_entry(temp, &context->busy_queue.node, node) {
+ if (mdp_buf_info_equals(&temp->mdp_buf_info,
+ &buf_info->mdp_buf_info)) {
+ WFD_MSG_DBG("Buffer %p already in queue "
+ "to be encoded, delaying encoding\n",
+ (void *)temp->mdp_buf_info.paddr);
+ list_add(&buf_info->node, &context->free_queue.node);
+ /* just skip the push to encoder*/
+ goto err_skip_encode;
+ }
+ }
+
+ mutex_unlock(&context->mutex);
+ rc = vsg_encode_frame(context, buf_info);
+ if (rc < 0) {
+ WFD_MSG_ERR("frame encode failed");
+ goto err_encode_fail;
+ }
+ mutex_lock(&context->mutex);
+
+ list_add_tail(&buf_info->node, &context->busy_queue.node);
+err_skip_encode:
+ mutex_unlock(&context->mutex);
+err_encode_fail:
+ kfree(work);
+}
+
+static void vsg_timer_helper_func(struct work_struct *task)
+{
+ struct vsg_work *work =
+ container_of(task, struct vsg_work, work);
+ struct vsg_work *new_work = NULL;
+ struct vsg_context *context = work->context;
+ int num_bufs_to_queue = 1, c = 0;
+
+ mutex_lock(&context->mutex);
+
+ if (context->stopped)
+ goto err_locked;
+
+ if (list_empty(&context->free_queue.node)
+ && context->last_buffer) {
+ struct vsg_buf_info *info = NULL, *buf_to_encode = NULL;
+
+ if (context->mode == VSG_MODE_CFR)
+ num_bufs_to_queue = 1;
+ else if (context->mode == VSG_MODE_VFR)
+ num_bufs_to_queue = 2;
+
+ for (c = 0; c < num_bufs_to_queue; ++c) {
+ info = kzalloc(sizeof(*info), GFP_KERNEL);
+
+ if (!info) {
+ WFD_MSG_ERR("Couldn't allocate memory in %s\n",
+ __func__);
+ goto err_locked;
+ }
+
+ if (context->regen_buffer) {
+ if (context->send_regen_buffer) {
+ buf_to_encode =
+ context->regen_buffer;
+ } else {
+ buf_to_encode = context->last_buffer;
+ }
+
+ context->send_regen_buffer =
+ !context->send_regen_buffer;
+ } else {
+ WFD_MSG_WARN("Have no regen buffer\n");
+ buf_to_encode = context->last_buffer;
+ }
+
+ info->mdp_buf_info = buf_to_encode->mdp_buf_info;
+ info->flags = buf_to_encode->flags;
+ INIT_LIST_HEAD(&info->node);
+ list_add_tail(&info->node, &context->free_queue.node);
+ WFD_MSG_DBG("Regenerated frame with paddr %p\n",
+ (void *)info->mdp_buf_info.paddr);
+ }
+ }
+
+ for (c = 0; c < num_bufs_to_queue; ++c) {
+ new_work = kzalloc(sizeof(*new_work), GFP_KERNEL);
+ if (!new_work) {
+ WFD_MSG_ERR("Unable to allocate memory"
+ "to queue buffer\n");
+ goto err_locked;
+ }
+
+ INIT_WORK(&new_work->work, vsg_work_func);
+ new_work->context = context;
+ queue_work(context->work_queue, &new_work->work);
+ }
+
+err_locked:
+ mutex_unlock(&context->mutex);
+ kfree(work);
+}
+
+static void vsg_threshold_timeout_func(unsigned long data)
+{
+ struct vsg_context *context = (struct vsg_context *)data;
+ struct vsg_work *task = kzalloc(sizeof(*task), GFP_ATOMIC);
+
+ if (!task) {
+ WFD_MSG_ERR("Out of memory in %s", __func__);
+ goto threshold_err_bad_param;
+ } else if (!context) {
+ WFD_MSG_ERR("Context not proper in %s", __func__);
+ goto threshold_err_bad_param;
+ }
+
+ mod_timer(&context->threshold_timer, jiffies +
+ nsecs_to_jiffies(context->max_frame_interval));
+
+ INIT_WORK(&task->work, vsg_timer_helper_func);
+ task->context = context;
+
+ queue_work(context->work_queue, &task->work);
+threshold_err_bad_param:
+ return;
+}
+
+int vsg_init(struct v4l2_subdev *sd, u32 val)
+{
+ return 0;
+}
+
+static int vsg_open(struct v4l2_subdev *sd, void *arg)
+{
+ struct vsg_context *context = NULL;
+
+ if (!arg || !sd)
+ return -EINVAL;
+
+ context = kzalloc(sizeof(*context), GFP_KERNEL);
+ INIT_LIST_HEAD(&context->free_queue.node);
+ INIT_LIST_HEAD(&context->busy_queue.node);
+
+ context->vmops = *(struct vsg_msg_ops *)arg;
+ context->work_queue = create_singlethread_workqueue("v4l-vsg");
+
+ context->frame_interval = DEFAULT_FRAME_INTERVAL;
+ context->max_frame_interval = DEFAULT_MAX_FRAME_INTERVAL;
+
+ context->threshold_timer = (struct timer_list)
+ TIMER_INITIALIZER(vsg_threshold_timeout_func,
+ context->max_frame_interval,
+ (unsigned long)context);
+
+ context->last_buffer = context->regen_buffer = NULL;
+ context->send_regen_buffer = false;
+ context->mode = DEFAULT_MODE;
+ context->stopped = false;
+ mutex_init(&context->mutex);
+
+ sd->dev_priv = context;
+ return 0;
+}
+
+static int vsg_close(struct v4l2_subdev *sd)
+{
+ struct vsg_context *context = NULL;
+
+ if (!sd)
+ return -EINVAL;
+
+ context = (struct vsg_context *)sd->dev_priv;
+ destroy_workqueue(context->work_queue);
+ kfree(context->regen_buffer);
+ kfree(context);
+ return 0;
+}
+
+static int vsg_start(struct v4l2_subdev *sd)
+{
+ struct vsg_context *context = NULL;
+
+ if (!sd) {
+ WFD_MSG_ERR("ERROR, invalid arguments into %s\n", __func__);
+ return -EINVAL;
+ }
+
+ context = (struct vsg_context *)sd->dev_priv;
+ mod_timer(&context->threshold_timer, jiffies +
+ nsecs_to_jiffies(context->max_frame_interval));
+ return 0;
+}
+
+static int vsg_stop(struct v4l2_subdev *sd)
+{
+ struct vsg_context *context = NULL;
+
+ if (!sd) {
+ WFD_MSG_ERR("ERROR, invalid arguments into %s\n", __func__);
+ return -EINVAL;
+ }
+
+ context = (struct vsg_context *)sd->dev_priv;
+
+ mutex_lock(&context->mutex);
+ context->stopped = true;
+ { /*delete pending buffers as we're not going to encode them*/
+ struct list_head *pos, *next;
+ list_for_each_safe(pos, next, &context->free_queue.node) {
+ struct vsg_buf_info *temp =
+ list_entry(pos, struct vsg_buf_info, node);
+ list_del(&temp->node);
+ kfree(temp);
+ }
+ }
+
+ del_timer_sync(&context->threshold_timer);
+
+ mutex_unlock(&context->mutex);
+
+ flush_workqueue(context->work_queue);
+ return 0;
+}
+
+static long vsg_queue_buffer(struct v4l2_subdev *sd, void *arg)
+{
+ struct vsg_context *context = NULL;
+ struct vsg_buf_info *buf_info = kzalloc(sizeof(*buf_info), GFP_KERNEL);
+ int rc = 0;
+ bool push = false;
+
+ if (!arg || !sd) {
+ WFD_MSG_ERR("ERROR, invalid arguments into %s\n", __func__);
+ rc = -EINVAL;
+ goto queue_err_bad_param;
+ } else if (!buf_info) {
+ WFD_MSG_ERR("ERROR, out of memory in %s\n", __func__);
+ rc = -ENOMEM;
+ goto queue_err_bad_param;
+ }
+
+ context = (struct vsg_context *)sd->dev_priv;
+ mutex_lock(&context->mutex);
+
+ *buf_info = *(struct vsg_buf_info *)arg;
+ INIT_LIST_HEAD(&buf_info->node);
+ buf_info->flags = 0;
+ ktime_get_ts(&buf_info->time);
+
+ WFD_MSG_DBG("Queue frame with paddr %p\n",
+ (void *)buf_info->mdp_buf_info.paddr);
+
+ { /*return pending buffers as we're not going to encode them*/
+ struct list_head *pos, *next;
+ list_for_each_safe(pos, next, &context->free_queue.node) {
+ struct vsg_buf_info *temp =
+ list_entry(pos, struct vsg_buf_info, node);
+ bool is_last_buffer, is_regen_buffer;
+
+ is_last_buffer = context->last_buffer &&
+ mdp_buf_info_equals(
+ &context->last_buffer->mdp_buf_info,
+ &temp->mdp_buf_info);
+
+ is_regen_buffer = context->regen_buffer &&
+ mdp_buf_info_equals(
+ &context->regen_buffer->mdp_buf_info,
+ &temp->mdp_buf_info);
+
+ if (!is_last_buffer && !is_regen_buffer &&
+ !(temp->flags & VSG_NEVER_RELEASE)) {
+ vsg_release_input_buffer(context, temp);
+ }
+
+ list_del(&temp->node);
+ kfree(temp);
+ }
+ }
+
+ list_add_tail(&buf_info->node, &context->free_queue.node);
+
+ if (context->mode == VSG_MODE_VFR) {
+ if (!context->last_buffer)
+ push = true;
+ else {
+ struct timespec diff = timespec_sub(buf_info->time,
+ context->last_buffer->time);
+ struct timespec temp = ns_to_timespec(
+ context->frame_interval);
+
+ if (timespec_compare(&diff, &temp) >= 0)
+ push = true;
+ }
+ }
+
+ if (push) {
+ struct vsg_work *new_work =
+ kzalloc(sizeof(*new_work), GFP_KERNEL);
+
+ INIT_WORK(&new_work->work, vsg_work_func);
+ new_work->context = context;
+ queue_work(context->work_queue, &new_work->work);
+ }
+
+ mutex_unlock(&context->mutex);
+queue_err_bad_param:
+ if (rc < 0)
+ kfree(buf_info);
+
+ return rc;
+}
+
+static long vsg_return_ip_buffer(struct v4l2_subdev *sd, void *arg)
+{
+ struct vsg_context *context = NULL;
+ struct vsg_buf_info *buf_info, *last_buffer,
+ *regen_buffer, *expected_buffer;
+ int rc = 0;
+
+ if (!arg || !sd) {
+ WFD_MSG_ERR("ERROR, invalid arguments into %s\n", __func__);
+ rc = -EINVAL;
+ goto return_ip_buf_err_bad_param;
+ }
+
+ context = (struct vsg_context *)sd->dev_priv;
+ mutex_lock(&context->mutex);
+ buf_info = (struct vsg_buf_info *)arg;
+ last_buffer = context->last_buffer;
+ regen_buffer = context->regen_buffer;
+
+ expected_buffer = list_first_entry(&context->busy_queue.node,
+ struct vsg_buf_info, node);
+
+ WFD_MSG_DBG("Return frame with paddr %p\n",
+ (void *)buf_info->mdp_buf_info.paddr);
+
+ if (mdp_buf_info_equals(&expected_buffer->mdp_buf_info,
+ &buf_info->mdp_buf_info)) {
+ list_del(&expected_buffer->node);
+
+ if (!(expected_buffer->flags & VSG_NEVER_SET_LAST_BUFFER)) {
+ bool is_same_buffer = context->last_buffer &&
+ mdp_buf_info_equals(
+ &context->last_buffer->mdp_buf_info,
+ &expected_buffer->mdp_buf_info);
+
+ if (!context->last_buffer || !is_same_buffer) {
+ struct vsg_buf_info *old_last_buffer =
+ context->last_buffer;
+ if (context->last_buffer)
+ vsg_release_input_buffer(context,
+ context->last_buffer);
+ vsg_set_last_buffer(context, expected_buffer);
+ kfree(old_last_buffer);
+ }
+ } else
+ WFD_MSG_WARN("Couldn't set the last buffer\n");
+ } else {
+ WFD_MSG_ERR("Returned buffer %p is not latest buffer, "
+ "expected %p\n",
+ (void *)buf_info->mdp_buf_info.paddr,
+ (void *)expected_buffer->mdp_buf_info.paddr);
+ rc = -EINVAL;
+ goto return_ip_buf_bad_buf;
+ }
+
+return_ip_buf_bad_buf:
+ mutex_unlock(&context->mutex);
+return_ip_buf_err_bad_param:
+ return rc;
+}
+
+static long vsg_set_scratch_buffer(struct v4l2_subdev *sd, void *arg)
+{
+ struct vsg_context *context = NULL;
+ struct vsg_buf_info *buf_info;
+ struct vsg_buf_info *regen_buffer =
+ kzalloc(sizeof(*regen_buffer), GFP_KERNEL);
+ int rc = 0;
+
+ if (!arg || !sd) {
+ WFD_MSG_ERR("ERROR, invalid arguments into %s\n", __func__);
+ rc = -EINVAL;
+ goto set_scratch_buf_err_bad_param;
+ } else if (!regen_buffer) {
+ WFD_MSG_ERR("ERROR, out of memory in %s\n", __func__);
+ rc = -ENOMEM;
+ goto set_scratch_buf_err_bad_param;
+ }
+
+ context = (struct vsg_context *)sd->dev_priv;
+ buf_info = (struct vsg_buf_info *)arg;
+
+ mutex_lock(&context->mutex);
+ *regen_buffer = *buf_info;
+ regen_buffer->flags = VSG_NEVER_RELEASE | VSG_NEVER_SET_LAST_BUFFER;
+ context->regen_buffer = regen_buffer;
+ WFD_MSG_ERR("setting buffer with paddr %p as scratch buffer\n",
+ (void *)regen_buffer->mdp_buf_info.paddr);
+ mutex_unlock(&context->mutex);
+set_scratch_buf_err_bad_param:
+ return rc;
+}
+
+static long vsg_set_frame_interval(struct v4l2_subdev *sd, void *arg)
+{
+ struct vsg_context *context = NULL;
+ int64_t interval;
+
+ if (!arg || !sd) {
+ WFD_MSG_ERR("ERROR, invalid arguments into %s\n", __func__);
+ return -EINVAL;
+ }
+
+ context = (struct vsg_context *)sd->dev_priv;
+ interval = *(int64_t *)arg;
+
+ if (interval <= 0) {
+ WFD_MSG_ERR("ERROR, invalid interval %lld into %s\n",
+ interval, __func__);
+ return -EINVAL;
+ }
+
+ mutex_lock(&context->mutex);
+
+ context->frame_interval = interval;
+ if (interval > context->max_frame_interval) {
+ WFD_MSG_WARN("Changing max frame interval from %lld to %lld\n",
+ context->max_frame_interval, interval);
+ context->max_frame_interval = interval;
+ }
+
+ mutex_unlock(&context->mutex);
+ return 0;
+}
+
+static long vsg_get_frame_interval(struct v4l2_subdev *sd, void *arg)
+{
+ struct vsg_context *context = NULL;
+
+ if (!arg || !sd) {
+ WFD_MSG_ERR("ERROR, invalid arguments into %s\n", __func__);
+ return -EINVAL;
+ }
+
+ context = (struct vsg_context *)sd->dev_priv;
+ mutex_lock(&context->mutex);
+ *(int64_t *)arg = context->frame_interval;
+ mutex_unlock(&context->mutex);
+
+ return 0;
+}
+
+static long vsg_set_max_frame_interval(struct v4l2_subdev *sd, void *arg)
+{
+ struct vsg_context *context = NULL;
+ int64_t interval;
+
+ if (!arg || !sd) {
+ WFD_MSG_ERR("ERROR, invalid arguments into %s\n", __func__);
+ return -EINVAL;
+ }
+
+ context = (struct vsg_context *)sd->dev_priv;
+ interval = *(int64_t *)arg;
+
+ if (interval <= 0) {
+ WFD_MSG_ERR("ERROR, invalid interval %lld into %s\n",
+ interval, __func__);
+ return -EINVAL;
+ }
+
+ mutex_lock(&context->mutex);
+
+ context->max_frame_interval = interval;
+ if (interval < context->frame_interval) {
+ WFD_MSG_WARN("Changing frame interval from %lld to %lld\n",
+ context->frame_interval, interval);
+ context->frame_interval = interval;
+ }
+
+ mutex_unlock(&context->mutex);
+
+ return 0;
+}
+
+static long vsg_get_max_frame_interval(struct v4l2_subdev *sd, void *arg)
+{
+ struct vsg_context *context = NULL;
+
+ if (!arg || !sd) {
+ WFD_MSG_ERR("ERROR, invalid arguments into %s\n", __func__);
+ return -EINVAL;
+ }
+
+ context = (struct vsg_context *)sd->dev_priv;
+ mutex_lock(&context->mutex);
+ *(int64_t *)arg = context->max_frame_interval;
+ mutex_unlock(&context->mutex);
+
+ return 0;
+}
+
+static long vsg_set_mode(struct v4l2_subdev *sd, void *arg)
+{
+ struct vsg_context *context = NULL;
+ enum vsg_modes *mode = NULL;
+ int rc = 0;
+
+ if (!arg || !sd) {
+ WFD_MSG_ERR("ERROR, invalid arguments into %s\n", __func__);
+ rc = -EINVAL;
+ goto set_mode_err_bad_parm;
+ }
+
+ context = (struct vsg_context *)sd->dev_priv;
+ mutex_lock(&context->mutex);
+ mode = arg;
+
+ switch (*mode) {
+ case VSG_MODE_CFR:
+ context->max_frame_interval = context->frame_interval;
+ /*fall through*/
+ case VSG_MODE_VFR:
+ context->mode = *mode;
+ break;
+ default:
+ context->mode = DEFAULT_MODE;
+ rc = -EINVAL;
+ goto set_mode_err_bad_mode;
+ break;
+ }
+
+set_mode_err_bad_mode:
+ mutex_unlock(&context->mutex);
+set_mode_err_bad_parm:
+ return rc;
+}
+
+long vsg_ioctl(struct v4l2_subdev *sd, unsigned int cmd, void *arg)
+{
+ int rc = 0;
+
+ WFD_MSG_DBG("VSG ioctl: %d\n", cmd);
+ if (sd == NULL)
+ return -EINVAL;
+
+ switch (cmd) {
+ case VSG_OPEN:
+ rc = vsg_open(sd, arg);
+ break;
+ case VSG_CLOSE:
+ rc = vsg_close(sd);
+ break;
+ case VSG_START:
+ rc = vsg_start(sd);
+ break;
+ case VSG_STOP:
+ rc = vsg_stop(sd);
+ break;
+ case VSG_Q_BUFFER:
+ rc = vsg_queue_buffer(sd, arg);
+ break;
+ case VSG_RETURN_IP_BUFFER:
+ rc = vsg_return_ip_buffer(sd, arg);
+ break;
+ case VSG_SET_SCRATCH_BUFFER:
+ rc = vsg_set_scratch_buffer(sd, arg);
+ break;
+ case VSG_GET_FRAME_INTERVAL:
+ rc = vsg_get_frame_interval(sd, arg);
+ break;
+ case VSG_SET_FRAME_INTERVAL:
+ rc = vsg_set_frame_interval(sd, arg);
+ break;
+ case VSG_GET_MAX_FRAME_INTERVAL:
+ rc = vsg_get_max_frame_interval(sd, arg);
+ break;
+ case VSG_SET_MAX_FRAME_INTERVAL:
+ rc = vsg_set_max_frame_interval(sd, arg);
+ break;
+ case VSG_SET_MODE:
+ rc = vsg_set_mode(sd, arg);
+ break;
+ default:
+ rc = -ENOTSUPP;
+ break;
+ }
+
+ return rc;
+}
diff --git a/drivers/media/video/msm/wfd/vsg-subdev.h b/drivers/media/video/msm/wfd/vsg-subdev.h
new file mode 100644
index 0000000..1db45e8
--- /dev/null
+++ b/drivers/media/video/msm/wfd/vsg-subdev.h
@@ -0,0 +1,88 @@
+/* Copyright (c) 2012, 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 _WFD_VSG_SUBDEV_
+#define _WFD_VSG_SUBDEV_
+
+#include <linux/videodev2.h>
+#include <linux/list.h>
+#include <linux/ktime.h>
+#include <linux/workqueue.h>
+#include <media/v4l2-subdev.h>
+#include "mdp-subdev.h"
+
+#define VSG_MAGIC_IOCTL 'V'
+
+enum vsg_flags {
+ VSG_NEVER_RELEASE = 1<<0,
+ VSG_NEVER_SET_LAST_BUFFER = 1<<1,
+};
+
+enum vsg_modes {
+ VSG_MODE_CFR,
+ VSG_MODE_VFR,
+};
+
+struct vsg_buf_info {
+ struct mdp_buf_info mdp_buf_info;
+ struct timespec time;
+ /* Internal */
+ struct list_head node;
+ uint32_t flags;
+};
+
+struct vsg_msg_ops {
+ void *cbdata;
+ int (*encode_frame)(void *cbdata, struct vsg_buf_info *buffer);
+ int (*release_input_frame)(void *cbdata, struct vsg_buf_info *buffer);
+};
+
+struct vsg_context {
+ struct vsg_buf_info free_queue, busy_queue;
+ struct vsg_msg_ops vmops;
+ /* All time related values below in nanosecs */
+ int64_t frame_interval, max_frame_interval;
+ struct workqueue_struct *work_queue;
+ struct timer_list threshold_timer;
+ struct mutex mutex;
+ struct vsg_buf_info *last_buffer, *regen_buffer;
+ bool send_regen_buffer;
+ int mode;
+ bool stopped;
+};
+
+struct vsg_work {
+ struct vsg_context *context;
+ struct work_struct work;
+};
+
+#define VSG_OPEN _IO(VSG_MAGIC_IOCTL, 1)
+#define VSG_CLOSE _IO(VSG_MAGIC_IOCTL, 2)
+#define VSG_START _IO(VSG_MAGIC_IOCTL, 3)
+#define VSG_STOP _IO(VSG_MAGIC_IOCTL, 4)
+#define VSG_Q_BUFFER _IOW(VSG_MAGIC_IOCTL, 5, struct vsg_buf_info *)
+#define VSG_DQ_BUFFER _IOR(VSG_MAGIC_IOCTL, 6, struct vsg_out_buf *)
+#define VSG_RETURN_IP_BUFFER _IOW(VSG_MAGIC_IOCTL, 7, struct vsg_buf_info *)
+#define VSG_ENCODE_DONE _IO(VSG_MAGIC_IOCTL, 8)
+#define VSG_SET_SCRATCH_BUFFER _IOW(VSG_MAGIC_IOCTL, 9, struct vsg_buf_info *)
+/* Time related arguments for frame interval ioctls are always in nanosecs*/
+#define VSG_SET_FRAME_INTERVAL _IOW(VSG_MAGIC_IOCTL, 10, int64_t *)
+#define VSG_GET_FRAME_INTERVAL _IOR(VSG_MAGIC_IOCTL, 11, int64_t *)
+#define VSG_SET_MAX_FRAME_INTERVAL _IOW(VSG_MAGIC_IOCTL, 12, int64_t *)
+#define VSG_GET_MAX_FRAME_INTERVAL _IOR(VSG_MAGIC_IOCTL, 13, int64_t *)
+#define VSG_SET_MODE _IOW(VSG_MAGIC_IOCTL, 14, enum vsg_modes *)
+
+extern int vsg_init(struct v4l2_subdev *sd, u32 val);
+extern long vsg_ioctl(struct v4l2_subdev *sd, unsigned int cmd, void *arg);
+
+#endif /* _WFD_VSG_SUBDEV_ */
diff --git a/drivers/media/video/msm/wfd/wfd-ioctl.c b/drivers/media/video/msm/wfd/wfd-ioctl.c
index 93dd367..315705c 100644
--- a/drivers/media/video/msm/wfd/wfd-ioctl.c
+++ b/drivers/media/video/msm/wfd/wfd-ioctl.c
@@ -21,6 +21,7 @@
#include <linux/android_pmem.h>
#include <linux/sched.h>
#include <linux/kthread.h>
+#include <linux/time.h>
#include <media/v4l2-dev.h>
#include <media/v4l2-ioctl.h>
@@ -31,12 +32,14 @@
#include "wfd-util.h"
#include "mdp-subdev.h"
#include "enc-subdev.h"
+#include "vsg-subdev.h"
#define WFD_VERSION KERNEL_VERSION(0, 0, 1)
#define DEFAULT_WFD_WIDTH 640
#define DEFAULT_WFD_HEIGHT 480
-#define MIN_BUF_COUNT 2
-#define VENC_INPUT_BUFFERS 3
+#define VSG_SCRATCH_BUFFERS 1
+#define MDP_WRITEBACK_BUFFERS 3
+#define VENC_INPUT_BUFFERS (VSG_SCRATCH_BUFFERS + MDP_WRITEBACK_BUFFERS)
struct wfd_device {
struct platform_device *pdev;
@@ -44,6 +47,7 @@
struct video_device *pvdev;
struct v4l2_subdev mdp_sdev;
struct v4l2_subdev enc_sdev;
+ struct v4l2_subdev vsg_sdev;
};
struct mem_info {
@@ -116,7 +120,8 @@
struct mem_region *mregion;
int rc;
unsigned long flags;
- struct mdp_buf_info buf = {0};
+ struct mdp_buf_info mdp_buf = {0};
+ struct vsg_buf_info vsg_buf = {};
spin_lock_irqsave(&inst->inst_lock, flags);
if (inst->input_bufs_allocated) {
spin_unlock_irqrestore(&inst->inst_lock, flags);
@@ -133,27 +138,44 @@
if (rc) {
WFD_MSG_ERR("Failed to allocate input memory."
" This error causes memory leak!!!\n");
- break;
+ goto alloc_fail;
}
WFD_MSG_DBG("NOTE: paddr = %p, kvaddr = %p\n", mregion->paddr,
mregion->kvaddr);
list_add_tail(&mregion->list, &inst->input_mem_list);
- buf.inst = inst->mdp_inst;
- buf.cookie = mregion;
- buf.kvaddr = (u32) mregion->kvaddr;
- buf.paddr = (u32) mregion->paddr;
- rc = v4l2_subdev_call(&wfd_dev->mdp_sdev, core, ioctl,
- MDP_Q_BUFFER, (void *)&buf);
- if (rc) {
- WFD_MSG_ERR("Unable to queue the buffer to mdp\n");
- break;
+
+ mdp_buf.inst = inst->mdp_inst;
+ mdp_buf.cookie = mregion;
+ mdp_buf.kvaddr = (u32) mregion->kvaddr;
+ mdp_buf.paddr = (u32) mregion->paddr;
+ vsg_buf.mdp_buf_info = mdp_buf;
+
+ if (i < MDP_WRITEBACK_BUFFERS) {
+ rc = v4l2_subdev_call(&wfd_dev->mdp_sdev, core, ioctl,
+ MDP_Q_BUFFER, (void *)&mdp_buf);
+ if (rc) {
+ WFD_MSG_ERR("Unable to queue the"
+ " buffer to mdp\n");
+ break;
+ }
+ } else /*if (i < VSG_SCRATCH_BUFFERS*/ {
+ rc = v4l2_subdev_call(&wfd_dev->vsg_sdev, core, ioctl,
+ VSG_SET_SCRATCH_BUFFER,
+ (void *)&vsg_buf);
+ if (rc) {
+ WFD_MSG_ERR("Unable to set scratch"
+ " buffer to vsg\n");
+ break;
+ }
}
}
rc = v4l2_subdev_call(&wfd_dev->enc_sdev, core, ioctl,
ALLOC_RECON_BUFFERS, NULL);
- if (rc)
+ if (rc) {
WFD_MSG_ERR("Failed to allocate recon buffers\n");
-
+ goto alloc_fail;
+ }
+alloc_fail:
return rc;
}
void wfd_free_input_buffers(struct wfd_device *wfd_dev,
@@ -258,7 +280,7 @@
rc = wfd_allocate_input_buffers(wfd_dev, inst);
if (rc) {
WFD_MSG_ERR("Failed to allocate input buffers\n");
- goto err;
+ goto free_input_bufs;
}
rc = v4l2_subdev_call(&wfd_dev->enc_sdev, core, ioctl,
SET_OUTPUT_BUFFER, (void *)&mregion);
@@ -270,7 +292,6 @@
return rc;
free_input_bufs:
wfd_free_input_buffers(wfd_dev, inst);
-err:
return rc;
}
@@ -294,6 +315,12 @@
struct wfd_inst *inst = (struct wfd_inst *)priv_data->private_data;
struct mem_info *minfo = vb2_plane_cookie(vb, 0);
struct mem_region mregion;
+
+ if (minfo == NULL) {
+ WFD_MSG_ERR("not freeing buffers since allocation failed");
+ return;
+ }
+
mregion.fd = minfo->fd;
mregion.offset = minfo->offset;
mregion.cookie = (u32)vb;
@@ -306,6 +333,7 @@
wfd_unregister_out_buf(inst, minfo);
wfd_free_input_buffers(wfd_dev, inst);
}
+
static int mdp_output_thread(void *data)
{
int rc = 0;
@@ -313,11 +341,13 @@
struct wfd_inst *inst = filp->private_data;
struct wfd_device *wfd_dev =
(struct wfd_device *)video_drvdata(filp);
- struct mdp_buf_info obuf = {inst->mdp_inst, 0, 0, 0};
+ struct mdp_buf_info obuf_mdp = {inst->mdp_inst, 0, 0, 0};
+ struct mem_region *mregion;
+ struct vsg_buf_info ibuf_vsg;
while (!kthread_should_stop()) {
WFD_MSG_DBG("waiting for mdp output\n");
rc = v4l2_subdev_call(&wfd_dev->mdp_sdev,
- core, ioctl, MDP_DQ_BUFFER, (void *)&obuf);
+ core, ioctl, MDP_DQ_BUFFER, (void *)&obuf_mdp);
if (rc) {
WFD_MSG_ERR("Either streamoff called or"
@@ -325,8 +355,21 @@
break;
}
- rc = v4l2_subdev_call(&wfd_dev->enc_sdev, core, ioctl,
- ENCODE_FRAME, obuf.cookie);
+ mregion = obuf_mdp.cookie;
+ if (!mregion) {
+ WFD_MSG_ERR("mdp cookie is null\n");
+ rc = -EINVAL;
+ break;
+ }
+
+ ibuf_vsg.mdp_buf_info = obuf_mdp;
+ ibuf_vsg.mdp_buf_info.inst = inst->mdp_inst;
+ ibuf_vsg.mdp_buf_info.cookie = mregion;
+ ibuf_vsg.mdp_buf_info.kvaddr = (u32) mregion->kvaddr;
+ ibuf_vsg.mdp_buf_info.paddr = (u32) mregion->paddr;
+ rc = v4l2_subdev_call(&wfd_dev->vsg_sdev,
+ core, ioctl, VSG_Q_BUFFER, (void *)&ibuf_vsg);
+
if (rc) {
WFD_MSG_ERR("Failed to encode frame\n");
break;
@@ -348,20 +391,27 @@
ENCODE_START, (void *)inst->venc_inst);
if (rc) {
WFD_MSG_ERR("Failed to start encoder\n");
- goto err;
+ goto subdev_start_fail;
+ }
+
+ rc = v4l2_subdev_call(&wfd_dev->vsg_sdev, core, ioctl,
+ VSG_START, NULL);
+ if (rc) {
+ WFD_MSG_ERR("Failed to start vsg\n");
+ goto subdev_start_fail;
}
inst->mdp_task = kthread_run(mdp_output_thread, priv_data,
"mdp_output_thread");
if (IS_ERR(inst->mdp_task)) {
rc = PTR_ERR(inst->mdp_task);
- goto err;
+ goto subdev_start_fail;
}
rc = v4l2_subdev_call(&wfd_dev->mdp_sdev, core, ioctl,
MDP_START, (void *)inst->mdp_inst);
if (rc)
WFD_MSG_ERR("Failed to start MDP\n");
-err:
+subdev_start_fail:
return rc;
}
@@ -377,6 +427,11 @@
if (rc)
WFD_MSG_ERR("Failed to stop MDP\n");
+ rc = v4l2_subdev_call(&wfd_dev->vsg_sdev, core, ioctl,
+ VSG_STOP, NULL);
+ if (rc)
+ WFD_MSG_ERR("Failed to stop VSG\n");
+
kthread_stop(inst->mdp_task);
rc = v4l2_subdev_call(&wfd_dev->enc_sdev, core, ioctl,
ENCODE_STOP, (void *)inst->venc_inst);
@@ -441,8 +496,17 @@
static const struct v4l2_subdev_ops enc_subdev_ops = {
.core = &enc_subdev_core_ops,
-}
-;
+};
+
+static const struct v4l2_subdev_core_ops vsg_subdev_core_ops = {
+ .init = vsg_init,
+ .ioctl = vsg_ioctl,
+};
+
+static const struct v4l2_subdev_ops vsg_subdev_ops = {
+ .core = &vsg_subdev_core_ops,
+};
+
static int wfdioc_querycap(struct file *filp, void *fh,
struct v4l2_capability *cap) {
WFD_MSG_DBG("wfdioc_querycap: E\n");
@@ -476,6 +540,7 @@
spin_unlock_irqrestore(&inst->inst_lock, flags);
return 0;
}
+
static int wfdioc_s_fmt(struct file *filp, void *fh,
struct v4l2_format *fmt)
{
@@ -499,7 +564,7 @@
(void *)fmt);
if (rc) {
WFD_MSG_ERR("Failed to set format on encoder, rc = %d\n", rc);
- goto err;
+ return rc;
}
breq.count = VENC_INPUT_BUFFERS;
breq.height = fmt->fmt.pix.height;
@@ -508,7 +573,7 @@
SET_BUFFER_REQ, (void *)&breq);
if (rc) {
WFD_MSG_ERR("Failed to set buffer reqs on encoder\n");
- goto err;
+ return rc;
}
spin_lock_irqsave(&inst->inst_lock, flags);
inst->input_buf_size = breq.size;
@@ -521,7 +586,6 @@
(void *)&prop);
if (rc)
WFD_MSG_ERR("Failed to set height/width property on mdp\n");
-err:
return rc;
}
static int wfdioc_reqbufs(struct file *filp, void *fh,
@@ -542,13 +606,12 @@
GET_BUFFER_REQ, (void *)b);
if (rc) {
WFD_MSG_ERR("Failed to get buf reqs from encoder\n");
- goto err;
+ return rc;
}
spin_lock_irqsave(&inst->inst_lock, flags);
inst->buf_count = b->count;
spin_unlock_irqrestore(&inst->inst_lock, flags);
rc = vb2_reqbufs(&inst->vid_bufq, b);
-err:
return rc;
}
static int wfd_register_out_buf(struct wfd_inst *inst,
@@ -593,12 +656,11 @@
rc = wfd_register_out_buf(inst, b);
if (rc) {
WFD_MSG_ERR("Failed to register buffer\n");
- goto err;
+ return rc;
}
rc = vb2_qbuf(&inst->vid_bufq, b);
if (rc)
WFD_MSG_ERR("Failed to queue buffer\n");
-err:
return rc;
}
@@ -634,6 +696,13 @@
{
struct wfd_inst *inst = filp->private_data;
unsigned long flags;
+
+ if (i != V4L2_BUF_TYPE_VIDEO_CAPTURE) {
+ WFD_MSG_ERR("stream off for buffer type = %d is not "
+ "supported.\n", i);
+ return -EINVAL;
+ }
+
spin_lock_irqsave(&inst->inst_lock, flags);
if (inst->streamoff) {
WFD_MSG_ERR("Module is already in streamoff state\n");
@@ -642,11 +711,6 @@
}
inst->streamoff = true;
spin_unlock_irqrestore(&inst->inst_lock, flags);
- if (i != V4L2_BUF_TYPE_VIDEO_CAPTURE) {
- WFD_MSG_ERR("stream off for buffer type = %d is not "
- "supported.\n", i);
- return -EINVAL;
- }
WFD_MSG_DBG("Calling videobuf_streamoff\n");
vb2_streamoff(&inst->vid_bufq, i);
return 0;
@@ -680,6 +744,148 @@
WFD_MSG_ERR("Failed to set encoder property\n");
return rc;
}
+
+static int wfdioc_g_parm(struct file *filp, void *fh,
+ struct v4l2_streamparm *a)
+{
+ int rc = 0;
+ struct wfd_device *wfd_dev = video_drvdata(filp);
+ struct wfd_inst *inst = filp->private_data;
+ int64_t frame_interval = 0,
+ max_frame_interval = 0; /* both in nsecs*/
+ struct v4l2_qcom_frameskip frameskip, *usr_frameskip;
+
+ usr_frameskip = (struct v4l2_qcom_frameskip *)
+ a->parm.capture.extendedmode;
+
+ if (!usr_frameskip) {
+ rc = -EINVAL;
+ goto get_parm_fail;
+ }
+ rc = v4l2_subdev_call(&wfd_dev->vsg_sdev, core,
+ ioctl, VSG_GET_FRAME_INTERVAL, &frame_interval);
+
+ if (rc < 0)
+ goto get_parm_fail;
+
+ rc = v4l2_subdev_call(&wfd_dev->vsg_sdev, core,
+ ioctl, VSG_GET_MAX_FRAME_INTERVAL, &max_frame_interval);
+
+ if (rc < 0)
+ goto get_parm_fail;
+
+ frameskip = (struct v4l2_qcom_frameskip) {
+ .maxframeinterval = max_frame_interval,
+ };
+
+ a->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+ a->parm.capture = (struct v4l2_captureparm) {
+ .capability = V4L2_CAP_TIMEPERFRAME,
+ .capturemode = 0,
+ .timeperframe = (struct v4l2_fract) {
+ .numerator = frame_interval,
+ .denominator = NSEC_PER_SEC,
+ },
+ .readbuffers = inst->buf_count,
+ .extendedmode = (__u32)usr_frameskip,
+ .reserved = {0}
+ };
+
+ rc = copy_to_user((void *)a->parm.capture.extendedmode,
+ &frameskip, sizeof(frameskip));
+ if (rc < 0)
+ goto get_parm_fail;
+
+get_parm_fail:
+ return rc;
+}
+
+static int wfdioc_s_parm(struct file *filp, void *fh,
+ struct v4l2_streamparm *a)
+{
+ int rc = 0;
+ struct wfd_device *wfd_dev = video_drvdata(filp);
+ struct wfd_inst *inst = filp->private_data;
+ struct v4l2_qcom_frameskip frameskip;
+ int64_t frame_interval, max_frame_interval;
+ void *extendedmode = NULL;
+ enum vsg_modes mode = VSG_MODE_VFR;
+
+
+ if (a->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) {
+ rc = -ENOTSUPP;
+ goto set_parm_fail;
+ }
+
+ if (a->parm.capture.readbuffers == 0 ||
+ a->parm.capture.readbuffers == inst->buf_count) {
+ a->parm.capture.readbuffers = inst->buf_count;
+ } else {
+ rc = -EINVAL;
+ goto set_parm_fail;
+ }
+
+ extendedmode = (void *)a->parm.capture.extendedmode;
+ if (a->parm.capture.capability & V4L2_CAP_TIMEPERFRAME) {
+ if (a->parm.capture.timeperframe.denominator == 0) {
+ rc = -EINVAL;
+ goto set_parm_fail;
+ }
+ frame_interval =
+ a->parm.capture.timeperframe.numerator * NSEC_PER_SEC /
+ a->parm.capture.timeperframe.denominator;
+
+ rc = v4l2_subdev_call(&wfd_dev->vsg_sdev, core,
+ ioctl, VSG_SET_FRAME_INTERVAL,
+ &frame_interval);
+
+ if (rc)
+ goto set_parm_fail;
+
+ rc = v4l2_subdev_call(&wfd_dev->enc_sdev, core,
+ ioctl, SET_FRAMERATE,
+ &a->parm.capture.timeperframe);
+
+ if (rc)
+ goto set_parm_fail;
+ }
+
+ if (a->parm.capture.capability & V4L2_CAP_QCOM_FRAMESKIP &&
+ extendedmode) {
+ rc = copy_from_user(&frameskip,
+ extendedmode, sizeof(frameskip));
+
+ if (rc)
+ goto set_parm_fail;
+
+ max_frame_interval = (int64_t)frameskip.maxframeinterval;
+ mode = VSG_MODE_VFR;
+
+ rc = v4l2_subdev_call(&wfd_dev->vsg_sdev, core,
+ ioctl, VSG_SET_MAX_FRAME_INTERVAL,
+ &max_frame_interval);
+
+ if (rc)
+ goto set_parm_fail;
+
+ rc = v4l2_subdev_call(&wfd_dev->vsg_sdev, core,
+ ioctl, VSG_SET_MODE, &mode);
+
+ if (rc)
+ goto set_parm_fail;
+ } else {
+ mode = VSG_MODE_CFR;
+ rc = v4l2_subdev_call(&wfd_dev->vsg_sdev, core,
+ ioctl, VSG_SET_MODE, &mode);
+
+ if (rc)
+ goto set_parm_fail;
+ }
+
+set_parm_fail:
+ return rc;
+}
+
static const struct v4l2_ioctl_ops g_wfd_ioctl_ops = {
.vidioc_querycap = wfdioc_querycap,
.vidioc_s_fmt_vid_cap = wfdioc_s_fmt,
@@ -691,7 +897,8 @@
.vidioc_dqbuf = wfdioc_dqbuf,
.vidioc_g_ctrl = wfdioc_g_ctrl,
.vidioc_s_ctrl = wfdioc_s_ctrl,
-
+ .vidioc_g_parm = wfdioc_g_parm,
+ .vidioc_s_parm = wfdioc_s_parm,
};
static int wfd_set_default_properties(struct file *filp)
{
@@ -712,32 +919,69 @@
wfdioc_s_fmt(filp, filp->private_data, &fmt);
return 0;
}
-void venc_op_buffer_done(void *cookie, u32 status,
+static void venc_op_buffer_done(void *cookie, u32 status,
struct vb2_buffer *buf)
{
WFD_MSG_DBG("yay!! got callback\n");
vb2_buffer_done(buf, VB2_BUF_STATE_DONE);
}
-void venc_ip_buffer_done(void *cookie, u32 status,
+
+static void venc_ip_buffer_done(void *cookie, u32 status,
struct mem_region *mregion)
{
struct file *filp = cookie;
struct wfd_inst *inst = filp->private_data;
- struct mdp_buf_info buf = {0};
+ struct vsg_buf_info buf;
+ struct mdp_buf_info mdp_buf = {0};
struct wfd_device *wfd_dev =
(struct wfd_device *)video_drvdata(filp);
int rc = 0;
WFD_MSG_DBG("yay!! got ip callback\n");
- buf.inst = inst->mdp_inst;
- buf.cookie = mregion;
- buf.kvaddr = (u32) mregion->kvaddr;
- buf.paddr = (u32) mregion->paddr;
+ mdp_buf.inst = inst->mdp_inst;
+ mdp_buf.cookie = mregion;
+ mdp_buf.kvaddr = (u32) mregion->kvaddr;
+ mdp_buf.paddr = (u32) mregion->paddr;
+ buf.mdp_buf_info = mdp_buf;
+ rc = v4l2_subdev_call(&wfd_dev->vsg_sdev, core,
+ ioctl, VSG_RETURN_IP_BUFFER, (void *)&buf);
+ if (rc)
+ WFD_MSG_ERR("Failed to return buffer to vsg\n");
+}
+
+static int vsg_release_input_frame(void *cookie, struct vsg_buf_info *buf)
+{
+ struct file *filp = cookie;
+ struct wfd_device *wfd_dev =
+ (struct wfd_device *)video_drvdata(filp);
+ int rc = 0;
+
rc = v4l2_subdev_call(&wfd_dev->mdp_sdev, core,
- ioctl, MDP_Q_BUFFER, (void *)&buf);
+ ioctl, MDP_Q_BUFFER, buf);
if (rc)
WFD_MSG_ERR("Failed to Q buffer to mdp\n");
+ return rc;
}
+
+static int vsg_encode_frame(void *cookie, struct vsg_buf_info *buf)
+{
+ struct file *filp = cookie;
+ struct wfd_device *wfd_dev =
+ (struct wfd_device *)video_drvdata(filp);
+ struct venc_buf_info venc_buf;
+
+ if (!buf)
+ return -EINVAL;
+
+ venc_buf = (struct venc_buf_info){
+ .timestamp = timespec_to_ns(&buf->time),
+ .mregion = buf->mdp_buf_info.cookie
+ };
+
+ return v4l2_subdev_call(&wfd_dev->enc_sdev, core, ioctl,
+ ENCODE_FRAME, &venc_buf);
+}
+
void *wfd_vb2_mem_ops_get_userptr(void *alloc_ctx, unsigned long vaddr,
unsigned long size, int write)
{
@@ -776,14 +1020,17 @@
int rc = 0;
struct wfd_inst *inst;
struct wfd_device *wfd_dev;
- struct venc_msg_ops vmops;
+ struct venc_msg_ops enc_mops;
+ struct vsg_msg_ops vsg_mops;
+
WFD_MSG_DBG("wfd_open: E\n");
wfd_dev = video_drvdata(filp);
inst = kzalloc(sizeof(struct wfd_inst), GFP_KERNEL);
if (!inst || !wfd_dev) {
WFD_MSG_ERR("Could not allocate memory for "
"wfd instance\n");
- return -ENOMEM;
+ rc = -ENOMEM;
+ goto err_mdp_open;
}
filp->private_data = inst;
spin_lock_init(&inst->inst_lock);
@@ -801,21 +1048,34 @@
WFD_MSG_ERR("Failed to load video encoder firmware: %d\n", rc);
goto err_venc;
}
- vmops.op_buffer_done = venc_op_buffer_done;
- vmops.ip_buffer_done = venc_ip_buffer_done;
- vmops.cbdata = filp;
+ enc_mops.op_buffer_done = venc_op_buffer_done;
+ enc_mops.ip_buffer_done = venc_ip_buffer_done;
+ enc_mops.cbdata = filp;
rc = v4l2_subdev_call(&wfd_dev->enc_sdev, core, ioctl, OPEN,
- (void *)&vmops);
- if (rc || !vmops.cookie) {
+ (void *)&enc_mops);
+ if (rc || !enc_mops.cookie) {
WFD_MSG_ERR("Failed to open encoder subdevice: %d\n", rc);
goto err_venc;
}
- inst->venc_inst = vmops.cookie;
+ inst->venc_inst = enc_mops.cookie;
+
+ vsg_mops.encode_frame = vsg_encode_frame;
+ vsg_mops.release_input_frame = vsg_release_input_frame;
+ vsg_mops.cbdata = filp;
+ rc = v4l2_subdev_call(&wfd_dev->vsg_sdev, core, ioctl, VSG_OPEN,
+ &vsg_mops);
+ if (rc) {
+ WFD_MSG_ERR("Failed to open vsg subdevice: %d\n", rc);
+ goto err_vsg_open;
+ }
wfd_initialize_vb2_queue(&inst->vid_bufq, filp);
wfd_set_default_properties(filp);
WFD_MSG_DBG("wfd_open: X\n");
return rc;
+
+err_vsg_open:
+ v4l2_subdev_call(&wfd_dev->enc_sdev, core, ioctl, CLOSE, NULL);
err_venc:
v4l2_subdev_call(&wfd_dev->mdp_sdev, core, ioctl,
MDP_CLOSE, (void *)inst->mdp_inst);
@@ -842,9 +1102,16 @@
rc = v4l2_subdev_call(&wfd_dev->enc_sdev, core, ioctl,
CLOSE, (void *)inst->venc_inst);
+
if (rc)
WFD_MSG_ERR("Failed to CLOSE enc subdev: %d\n", rc);
+ rc = v4l2_subdev_call(&wfd_dev->vsg_sdev, core, ioctl,
+ VSG_CLOSE, NULL);
+
+ if (rc)
+ WFD_MSG_ERR("Failed to CLOSE vsg subdev: %d\n", rc);
+
kfree(inst);
}
WFD_MSG_DBG("wfd_close: X\n");
@@ -869,7 +1136,8 @@
if (!wfd_dev) {
WFD_MSG_ERR("Could not allocate memory for "
"wfd device\n");
- return -ENOMEM;
+ rc = -ENOMEM;
+ goto err_v4l2_registration;
}
pdev->dev.platform_data = (void *) wfd_dev;
rc = v4l2_device_register(&pdev->dev, &wfd_dev->v4l2_dev);
@@ -917,6 +1185,15 @@
goto err_venc_init;
}
+ v4l2_subdev_init(&wfd_dev->vsg_sdev, &vsg_subdev_ops);
+ strncpy(wfd_dev->vsg_sdev.name, "wfd-vsg", V4L2_SUBDEV_NAME_SIZE);
+ rc = v4l2_device_register_subdev(&wfd_dev->v4l2_dev,
+ &wfd_dev->vsg_sdev);
+ if (rc) {
+ WFD_MSG_ERR("Failed to register vsg subdevice: %d\n", rc);
+ goto err_venc_init;
+ }
+
WFD_MSG_DBG("__wfd_probe: X\n");
return rc;
diff --git a/drivers/media/video/msm/wfd/wfd-util.h b/drivers/media/video/msm/wfd/wfd-util.h
index 038a2cb..3fe03e6 100644
--- a/drivers/media/video/msm/wfd/wfd-util.h
+++ b/drivers/media/video/msm/wfd/wfd-util.h
@@ -16,15 +16,16 @@
/*#define DEBUG_WFD*/
+#define WFD_TAG "wfd: "
#ifdef DEBUG_WFD
- #define WFD_MSG_INFO(fmt...) pr_info(fmt)
- #define WFD_MSG_WARN(fmt...) pr_warning(fmt)
- #define WFD_MSG_DBG(fmt...) pr_debug(fmt)
+ #define WFD_MSG_INFO(fmt...) pr_info(WFD_TAG fmt)
+ #define WFD_MSG_WARN(fmt...) pr_warning(WFD_TAG fmt)
+ #define WFD_MSG_DBG(fmt...) pr_debug(WFD_TAG fmt)
#else
#define WFD_MSG_INFO(fmt...)
#define WFD_MSG_WARN(fmt...)
#define WFD_MSG_DBG(fmt...)
#endif
- #define WFD_MSG_ERR(fmt...) pr_err(KERN_ERR fmt)
- #define WFD_MSG_CRIT(fmt...) pr_crit(KERN_CRIT fmt)
+ #define WFD_MSG_ERR(fmt...) pr_err(KERN_ERR WFD_TAG fmt)
+ #define WFD_MSG_CRIT(fmt...) pr_crit(KERN_CRIT WFD_TAG fmt)
#endif
diff --git a/drivers/mfd/pm8821-core.c b/drivers/mfd/pm8821-core.c
index 8a556bd..ffcef99 100644
--- a/drivers/mfd/pm8821-core.c
+++ b/drivers/mfd/pm8821-core.c
@@ -29,7 +29,7 @@
#define REG_IRQ_BASE 0x1BB
#define PM8821_VERSION_MASK 0xFFF0
-#define PM8821_VERSION_VALUE 0x07F0
+#define PM8821_VERSION_VALUE 0x0BF0
#define PM8821_REVISION_MASK 0x000F
#define SINGLE_IRQ_RESOURCE(_name, _irq) \
diff --git a/drivers/net/wireless/wcnss/wcnss_riva.c b/drivers/net/wireless/wcnss/wcnss_riva.c
index f6997ac..0939dd8 100644
--- a/drivers/net/wireless/wcnss/wcnss_riva.c
+++ b/drivers/net/wireless/wcnss/wcnss_riva.c
@@ -61,11 +61,11 @@
};
static struct vregs_info iris_vregs[] = {
- {"iris_vddio", VREG_NULL_CONFIG, 0000000, 0, 0000000, 0, NULL},
+ {"iris_vddio", VREG_NULL_CONFIG, 1800000, 0, 1800000, 4000, NULL},
{"iris_vddxo", VREG_NULL_CONFIG, 1800000, 0, 1800000, 10000, NULL},
{"iris_vddrfa", VREG_NULL_CONFIG, 1300000, 0, 1300000, 100000, NULL},
- {"iris_vddpa", VREG_NULL_CONFIG, 3000000, 0, 3000000, 515000, NULL},
- {"iris_vdddig", VREG_NULL_CONFIG, 0000000, 0, 0000000, 0, NULL},
+ {"iris_vddpa", VREG_NULL_CONFIG, 2900000, 0, 3000000, 515000, NULL},
+ {"iris_vdddig", VREG_NULL_CONFIG, 1200000, 0, 1200000, 10000, NULL},
};
static struct vregs_info riva_vregs[] = {
@@ -220,7 +220,7 @@
static int wcnss_vregs_on(struct device *dev,
struct vregs_info regulators[], uint size)
{
- int i, rc = 0;
+ int i, rc = 0, reg_cnt;
for (i = 0; i < size; i++) {
/* Get regulator source */
@@ -233,9 +233,10 @@
goto fail;
}
regulators[i].state |= VREG_GET_REGULATOR_MASK;
-
+ reg_cnt = regulator_count_voltages(regulators[i].regulator);
/* Set voltage to nominal. Exclude swtiches e.g. LVS */
- if (regulators[i].nominal_min || regulators[i].max_voltage) {
+ if ((regulators[i].nominal_min || regulators[i].max_voltage)
+ && (reg_cnt > 0)) {
rc = regulator_set_voltage(regulators[i].regulator,
regulators[i].nominal_min,
regulators[i].max_voltage);
@@ -248,7 +249,7 @@
}
/* Vote for PWM/PFM mode if needed */
- if (regulators[i].uA_load) {
+ if (regulators[i].uA_load && (reg_cnt > 0)) {
rc = regulator_set_optimum_mode(regulators[i].regulator,
regulators[i].uA_load);
if (rc < 0) {
diff --git a/drivers/power/pm8921-charger.c b/drivers/power/pm8921-charger.c
index e24c700..fa8f866 100644
--- a/drivers/power/pm8921-charger.c
+++ b/drivers/power/pm8921-charger.c
@@ -293,6 +293,24 @@
return 0;
}
+static int pm_chg_get_rt_status(struct pm8921_chg_chip *chip, int irq_id)
+{
+ return pm8xxx_read_irq_stat(chip->dev->parent,
+ chip->pmic_chg_irq[irq_id]);
+}
+
+/* Treat OverVoltage/UnderVoltage as source missing */
+static int is_usb_chg_plugged_in(struct pm8921_chg_chip *chip)
+{
+ return pm_chg_get_rt_status(chip, USBIN_VALID_IRQ);
+}
+
+/* Treat OverVoltage/UnderVoltage as source missing */
+static int is_dc_chg_plugged_in(struct pm8921_chg_chip *chip)
+{
+ return pm_chg_get_rt_status(chip, DCIN_VALID_IRQ);
+}
+
#define CAPTURE_FSM_STATE_CMD 0xC2
#define READ_BANK_7 0x70
#define READ_BANK_4 0x40
@@ -407,21 +425,25 @@
#define PM8921_CHG_V_MIN_MV 3240
#define PM8921_CHG_V_STEP_MV 20
+#define PM8921_CHG_V_STEP_10_MV_BIT BIT(7)
#define PM8921_CHG_VDDMAX_MAX 4500
#define PM8921_CHG_VDDMAX_MIN 3400
#define PM8921_CHG_V_MASK 0x7F
-static int pm_chg_vddmax_set(struct pm8921_chg_chip *chip, int voltage)
+static int __pm_chg_vddmax_set(struct pm8921_chg_chip *chip, int voltage)
{
- u8 temp;
+ int remainder, voltage_20_step;
+ u8 temp = 0;
- if (voltage < PM8921_CHG_VDDMAX_MIN
- || voltage > PM8921_CHG_VDDMAX_MAX) {
- pr_err("bad mV=%d asked to set\n", voltage);
- return -EINVAL;
+ voltage_20_step = voltage;
+ remainder = voltage % 20;
+ if (remainder >= 10) {
+ voltage_20_step += 10;
+ temp = PM8921_CHG_V_STEP_10_MV_BIT;
}
- temp = (voltage - PM8921_CHG_V_MIN_MV) / PM8921_CHG_V_STEP_MV;
+
+ temp |= (voltage_20_step - PM8921_CHG_V_MIN_MV) / PM8921_CHG_V_STEP_MV;
pr_debug("voltage=%d setting %02x\n", voltage, temp);
- return pm_chg_masked_write(chip, CHG_VDD_MAX, PM8921_CHG_V_MASK, temp);
+ return pm8xxx_writeb(chip->dev->parent, CHG_VDD_MAX, temp);
}
static int pm_chg_vddmax_get(struct pm8921_chg_chip *chip, int *voltage)
@@ -437,9 +459,53 @@
}
temp &= PM8921_CHG_V_MASK;
*voltage = (int)temp * PM8921_CHG_V_STEP_MV + PM8921_CHG_V_MIN_MV;
+ if (temp & PM8921_CHG_V_STEP_10_MV_BIT)
+ *voltage = *voltage - 10;
return 0;
}
+static int pm_chg_vddmax_set(struct pm8921_chg_chip *chip, int voltage)
+{
+ int current_mv, ret, steps, i;
+ bool increase;
+
+ ret = 0;
+
+ if (voltage < PM8921_CHG_VDDMAX_MIN
+ || voltage > PM8921_CHG_VDDMAX_MAX) {
+ pr_err("bad mV=%d asked to set\n", voltage);
+ return -EINVAL;
+ }
+
+ ret = pm_chg_vddmax_get(chip, ¤t_mv);
+ if (ret) {
+ pr_err("Failed to read vddmax rc=%d\n", ret);
+ return -EINVAL;
+ }
+ if (current_mv == voltage)
+ return 0;
+
+ /* Only change in increments when USB is present */
+ if (is_usb_chg_plugged_in(chip)) {
+ if (current_mv < voltage) {
+ steps = (voltage - current_mv) / PM8921_CHG_V_STEP_MV;
+ increase = true;
+ } else {
+ steps = (current_mv - voltage) / PM8921_CHG_V_STEP_MV;
+ increase = false;
+ }
+ for (i = 0; i < steps; i++) {
+ if (increase)
+ current_mv += PM8921_CHG_V_STEP_MV;
+ else
+ current_mv -= PM8921_CHG_V_STEP_MV;
+ ret |= __pm_chg_vddmax_set(chip, current_mv);
+ }
+ }
+ ret |= __pm_chg_vddmax_set(chip, voltage);
+ return ret;
+}
+
#define PM8921_CHG_VDDSAFE_MIN 3400
#define PM8921_CHG_VDDSAFE_MAX 4500
static int pm_chg_vddsafe_set(struct pm8921_chg_chip *chip, int voltage)
@@ -860,24 +926,6 @@
return test_bit(interrupt, chip->enabled_irqs);
}
-static int pm_chg_get_rt_status(struct pm8921_chg_chip *chip, int irq_id)
-{
- return pm8xxx_read_irq_stat(chip->dev->parent,
- chip->pmic_chg_irq[irq_id]);
-}
-
-/* Treat OverVoltage/UnderVoltage as source missing */
-static int is_usb_chg_plugged_in(struct pm8921_chg_chip *chip)
-{
- return pm_chg_get_rt_status(chip, USBIN_VALID_IRQ);
-}
-
-/* Treat OverVoltage/UnderVoltage as source missing */
-static int is_dc_chg_plugged_in(struct pm8921_chg_chip *chip)
-{
- return pm_chg_get_rt_status(chip, DCIN_VALID_IRQ);
-}
-
static bool is_ext_charging(struct pm8921_chg_chip *chip)
{
union power_supply_propval ret = {0,};