Merge "arm/dt: msmcopper-sim: Add support for SDC2 slot" into msm-3.4
diff --git a/arch/arm/include/asm/mach/mmc.h b/arch/arm/include/asm/mach/mmc.h
index 745a3a4..0bdb0f1 100644
--- a/arch/arm/include/asm/mach/mmc.h
+++ b/arch/arm/include/asm/mach/mmc.h
@@ -59,8 +59,7 @@
*/
struct msm_mmc_slot_reg_data {
struct msm_mmc_reg_data *vdd_data; /* keeps VDD/VCC regulator info */
- struct msm_mmc_reg_data *vccq_data; /* keeps VCCQ regulator info */
- struct msm_mmc_reg_data *vddp_data; /* keeps VDD Pad regulator info */
+ struct msm_mmc_reg_data *vdd_io_data; /* keeps VDD IO regulator info */
};
struct msm_mmc_gpio {
diff --git a/arch/arm/mach-msm/Kconfig b/arch/arm/mach-msm/Kconfig
index cbdb51a..a2cba84 100644
--- a/arch/arm/mach-msm/Kconfig
+++ b/arch/arm/mach-msm/Kconfig
@@ -227,7 +227,7 @@
config ARCH_MSMCOPPER
bool "MSM Copper"
select ARCH_MSM_KRAITMP
- select GPIO_MSM_V2
+ select GPIO_MSM_V3
select ARM_GIC
select CPU_V7
select MSM_SCM if SMP
diff --git a/arch/arm/mach-msm/board-8064-regulator.c b/arch/arm/mach-msm/board-8064-regulator.c
index 40222b8..08dacea 100644
--- a/arch/arm/mach-msm/board-8064-regulator.c
+++ b/arch/arm/mach-msm/board-8064-regulator.c
@@ -54,7 +54,7 @@
};
VREG_CONSUMERS(L7) = {
REGULATOR_SUPPLY("8921_l7", NULL),
- REGULATOR_SUPPLY("sdc_vddp", "msm_sdcc.3"),
+ REGULATOR_SUPPLY("sdc_vdd_io", "msm_sdcc.3"),
};
VREG_CONSUMERS(L8) = {
REGULATOR_SUPPLY("8921_l8", NULL),
@@ -162,7 +162,7 @@
};
VREG_CONSUMERS(S4) = {
REGULATOR_SUPPLY("8921_s4", NULL),
- REGULATOR_SUPPLY("sdc_vccq", "msm_sdcc.1"),
+ REGULATOR_SUPPLY("sdc_vdd_io", "msm_sdcc.1"),
REGULATOR_SUPPLY("VDDIO_CDC", "tabla-slim"),
REGULATOR_SUPPLY("CDC_VDD_CP", "tabla-slim"),
REGULATOR_SUPPLY("CDC_VDDA_TX", "tabla-slim"),
diff --git a/arch/arm/mach-msm/board-8064-storage.c b/arch/arm/mach-msm/board-8064-storage.c
index 193fc4a..fb507c7 100644
--- a/arch/arm/mach-msm/board-8064-storage.c
+++ b/arch/arm/mach-msm/board-8064-storage.c
@@ -56,23 +56,19 @@
}
};
-/* Only slots having eMMC card will require VCCQ voltage */
-static struct msm_mmc_reg_data mmc_vccq_reg_data[1] = {
+/* SDCC controllers may require voting for VDD IO voltage */
+static struct msm_mmc_reg_data mmc_vdd_io_reg_data[MAX_SDCC_CONTROLLER] = {
/* SDCC1 : eMMC card connected */
[SDCC1] = {
- .name = "sdc_vccq",
+ .name = "sdc_vdd_io",
.always_on = 1,
.high_vol_level = 1800000,
.low_vol_level = 1800000,
.hpm_uA = 200000, /* 200mA */
- }
-};
-
-/* All SDCC controllers may require voting for VDD PAD voltage */
-static struct msm_mmc_reg_data mmc_vddp_reg_data[MAX_SDCC_CONTROLLER] = {
+ },
/* SDCC3 : External card slot connected */
[SDCC3] = {
- .name = "sdc_vddp",
+ .name = "sdc_vdd_io",
.high_vol_level = 2950000,
.low_vol_level = 1850000,
.always_on = 1,
@@ -92,12 +88,12 @@
/* SDCC1 : eMMC card connected */
[SDCC1] = {
.vdd_data = &mmc_vdd_reg_data[SDCC1],
- .vccq_data = &mmc_vccq_reg_data[SDCC1],
+ .vdd_io_data = &mmc_vdd_io_reg_data[SDCC1],
},
/* SDCC3 : External card slot connected */
[SDCC3] = {
.vdd_data = &mmc_vdd_reg_data[SDCC3],
- .vddp_data = &mmc_vddp_reg_data[SDCC3],
+ .vdd_io_data = &mmc_vdd_io_reg_data[SDCC3],
}
};
diff --git a/arch/arm/mach-msm/board-8930-regulator.c b/arch/arm/mach-msm/board-8930-regulator.c
index 2f24c95..cb8903c 100644
--- a/arch/arm/mach-msm/board-8930-regulator.c
+++ b/arch/arm/mach-msm/board-8930-regulator.c
@@ -80,7 +80,7 @@
REGULATOR_SUPPLY("vdd_dig", "3-004a"),
REGULATOR_SUPPLY("iris_vddio", "wcnss_wlan.0"),
REGULATOR_SUPPLY("riva_vddpx", "wcnss_wlan.0"),
- REGULATOR_SUPPLY("sdc_vccq", "msm_sdcc.1"),
+ REGULATOR_SUPPLY("sdc_vdd_io", "msm_sdcc.1"),
REGULATOR_SUPPLY("VDDIO_CDC", "sitar-slim"),
REGULATOR_SUPPLY("CDC_VDDA_TX", "sitar-slim"),
REGULATOR_SUPPLY("CDC_VDDA_RX", "sitar-slim"),
@@ -129,7 +129,7 @@
};
VREG_CONSUMERS(L22) = {
REGULATOR_SUPPLY("8038_l22", NULL),
- REGULATOR_SUPPLY("sdc_vddp", "msm_sdcc.3"),
+ REGULATOR_SUPPLY("sdc_vdd_io", "msm_sdcc.3"),
};
VREG_CONSUMERS(L23) = {
REGULATOR_SUPPLY("8038_l23", NULL),
diff --git a/arch/arm/mach-msm/board-8930-storage.c b/arch/arm/mach-msm/board-8930-storage.c
index 52a11bc..87143ff 100644
--- a/arch/arm/mach-msm/board-8930-storage.c
+++ b/arch/arm/mach-msm/board-8930-storage.c
@@ -57,23 +57,19 @@
}
};
-/* Only slots having eMMC card will require VCCQ voltage */
-static struct msm_mmc_reg_data mmc_vccq_reg_data[1] = {
+/* All SDCC controllers may require voting for VDD PAD voltage */
+static struct msm_mmc_reg_data mmc_vdd_io_reg_data[MAX_SDCC_CONTROLLER] = {
/* SDCC1 : eMMC card connected */
[SDCC1] = {
- .name = "sdc_vccq",
+ .name = "sdc_vdd_io",
.always_on = 1,
.high_vol_level = 1800000,
.low_vol_level = 1800000,
.hpm_uA = 200000, /* 200mA */
- }
-};
-
-/* All SDCC controllers may require voting for VDD PAD voltage */
-static struct msm_mmc_reg_data mmc_vddp_reg_data[MAX_SDCC_CONTROLLER] = {
+ },
/* SDCC3 : External card slot connected */
[SDCC3] = {
- .name = "sdc_vddp",
+ .name = "sdc_vdd_io",
.high_vol_level = 2950000,
.low_vol_level = 1850000,
.always_on = 1,
@@ -93,12 +89,12 @@
/* SDCC1 : eMMC card connected */
[SDCC1] = {
.vdd_data = &mmc_vdd_reg_data[SDCC1],
- .vccq_data = &mmc_vccq_reg_data[SDCC1],
+ .vdd_io_data = &mmc_vdd_io_reg_data[SDCC1],
},
/* SDCC3 : External card slot connected */
[SDCC3] = {
.vdd_data = &mmc_vdd_reg_data[SDCC3],
- .vddp_data = &mmc_vddp_reg_data[SDCC3],
+ .vdd_io_data = &mmc_vdd_io_reg_data[SDCC3],
}
};
diff --git a/arch/arm/mach-msm/board-8960-regulator.c b/arch/arm/mach-msm/board-8960-regulator.c
index 93c72ea..bc5a892 100644
--- a/arch/arm/mach-msm/board-8960-regulator.c
+++ b/arch/arm/mach-msm/board-8960-regulator.c
@@ -53,7 +53,7 @@
};
VREG_CONSUMERS(L7) = {
REGULATOR_SUPPLY("8921_l7", NULL),
- REGULATOR_SUPPLY("sdc_vddp", "msm_sdcc.3"),
+ REGULATOR_SUPPLY("sdc_vdd_io", "msm_sdcc.3"),
};
VREG_CONSUMERS(L8) = {
REGULATOR_SUPPLY("8921_l8", NULL),
@@ -162,9 +162,9 @@
};
VREG_CONSUMERS(S4) = {
REGULATOR_SUPPLY("8921_s4", NULL),
- REGULATOR_SUPPLY("sdc_vccq", "msm_sdcc.1"),
+ REGULATOR_SUPPLY("sdc_vdd_io", "msm_sdcc.1"),
REGULATOR_SUPPLY("sdc_vdd", "msm_sdcc.2"),
- REGULATOR_SUPPLY("sdc_vddp", "msm_sdcc.4"),
+ REGULATOR_SUPPLY("sdc_vdd_io", "msm_sdcc.4"),
REGULATOR_SUPPLY("riva_vddpx", "wcnss_wlan.0"),
REGULATOR_SUPPLY("hdmi_vcc", "hdmi_msm.0"),
REGULATOR_SUPPLY("VDDIO_CDC", "tabla-slim"),
diff --git a/arch/arm/mach-msm/board-8960-storage.c b/arch/arm/mach-msm/board-8960-storage.c
index 1279b75..85785fc 100644
--- a/arch/arm/mach-msm/board-8960-storage.c
+++ b/arch/arm/mach-msm/board-8960-storage.c
@@ -65,23 +65,19 @@
}
};
-/* Only slots having eMMC card will require VCCQ voltage */
-static struct msm_mmc_reg_data mmc_vccq_reg_data[1] = {
+/* SDCC controllers may require voting for IO operating voltage */
+static struct msm_mmc_reg_data mmc_vdd_io_reg_data[MAX_SDCC_CONTROLLER] = {
/* SDCC1 : eMMC card connected */
[SDCC1] = {
- .name = "sdc_vccq",
+ .name = "sdc_vdd_io",
.always_on = 1,
.high_vol_level = 1800000,
.low_vol_level = 1800000,
.hpm_uA = 200000, /* 200mA */
- }
-};
-
-/* All SDCC controllers may require voting for VDD PAD voltage */
-static struct msm_mmc_reg_data mmc_vddp_reg_data[MAX_SDCC_CONTROLLER] = {
+ },
/* SDCC3 : External card slot connected */
[SDCC3] = {
- .name = "sdc_vddp",
+ .name = "sdc_vdd_io",
.high_vol_level = 2950000,
.low_vol_level = 1850000,
.always_on = 1,
@@ -97,7 +93,7 @@
},
/* SDCC4 : SDIO slot connected */
[SDCC4] = {
- .name = "sdc_vddp",
+ .name = "sdc_vdd_io",
.high_vol_level = 1800000,
.low_vol_level = 1800000,
.always_on = 1,
@@ -111,7 +107,7 @@
/* SDCC1 : eMMC card connected */
[SDCC1] = {
.vdd_data = &mmc_vdd_reg_data[SDCC1],
- .vccq_data = &mmc_vccq_reg_data[SDCC1],
+ .vdd_io_data = &mmc_vdd_io_reg_data[SDCC1],
},
/* SDCC2 : SDIO card slot connected */
[SDCC2] = {
@@ -120,11 +116,11 @@
/* SDCC3 : External card slot connected */
[SDCC3] = {
.vdd_data = &mmc_vdd_reg_data[SDCC3],
- .vddp_data = &mmc_vddp_reg_data[SDCC3],
+ .vdd_io_data = &mmc_vdd_io_reg_data[SDCC3],
},
/* SDCC4 : SDIO card slot connected */
[SDCC4] = {
- .vddp_data = &mmc_vddp_reg_data[SDCC4],
+ .vdd_io_data = &mmc_vdd_io_reg_data[SDCC4],
},
};
diff --git a/arch/arm/mach-msm/board-9615-regulator.c b/arch/arm/mach-msm/board-9615-regulator.c
index 7ed350d..b771386 100644
--- a/arch/arm/mach-msm/board-9615-regulator.c
+++ b/arch/arm/mach-msm/board-9615-regulator.c
@@ -61,7 +61,7 @@
};
VREG_CONSUMERS(L13) = {
REGULATOR_SUPPLY("8018_l13", NULL),
- REGULATOR_SUPPLY("sdc_vddp", "msm_sdcc.1"),
+ REGULATOR_SUPPLY("sdc_vdd_io", "msm_sdcc.1"),
};
VREG_CONSUMERS(L14) = {
REGULATOR_SUPPLY("8018_l14", NULL),
diff --git a/arch/arm/mach-msm/board-9615-storage.c b/arch/arm/mach-msm/board-9615-storage.c
index 5bdeb94..51e2432 100644
--- a/arch/arm/mach-msm/board-9615-storage.c
+++ b/arch/arm/mach-msm/board-9615-storage.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
@@ -54,10 +54,10 @@
};
/* All SDCC controllers may require voting for VDD PAD voltage */
-static struct msm_mmc_reg_data mmc_vddp_reg_data[MAX_SDCC_CONTROLLER] = {
+static struct msm_mmc_reg_data mmc_vdd_io_reg_data[MAX_SDCC_CONTROLLER] = {
/* SDCC1 : External card slot connected */
[SDCC1] = {
- .name = "sdc_vddp",
+ .name = "sdc_vdd_io",
.high_vol_level = 2950000,
.low_vol_level = 1850000,
.always_on = true,
@@ -77,7 +77,7 @@
/* SDCC1 : External card slot connected */
[SDCC1] = {
.vdd_data = &mmc_vdd_reg_data[SDCC1],
- .vddp_data = &mmc_vddp_reg_data[SDCC1],
+ .vdd_io_data = &mmc_vdd_io_reg_data[SDCC1],
}
};
diff --git a/arch/arm/mach-msm/board-9615.c b/arch/arm/mach-msm/board-9615.c
index df114a3..bada29c 100644
--- a/arch/arm/mach-msm/board-9615.c
+++ b/arch/arm/mach-msm/board-9615.c
@@ -471,14 +471,6 @@
},
};
-static struct i2c_registry msm9615_i2c_devices[] __initdata = {
- {
- I2C_SURF | I2C_FFA | I2C_FLUID,
- MSM_9615_GSBI5_QUP_I2C_BUS_ID,
- wcd9xxx_device_info,
- ARRAY_SIZE(wcd9xxx_device_info),
- },
-};
/*
* MDM9x15 I2S.
*/
@@ -561,6 +553,17 @@
};
#endif
+static struct i2c_registry msm9615_i2c_devices[] __initdata = {
+#ifdef CONFIG_WCD9310_CODEC
+ {
+ I2C_SURF | I2C_FFA | I2C_FLUID,
+ MSM_9615_GSBI5_QUP_I2C_BUS_ID,
+ wcd9xxx_device_info,
+ ARRAY_SIZE(wcd9xxx_device_info),
+ },
+#endif
+};
+
static struct slim_boardinfo msm_slim_devices[] = {
/* add slimbus slaves as needed */
#ifdef CONFIG_WCD9310_CODEC
diff --git a/arch/arm/mach-msm/board-copper.c b/arch/arm/mach-msm/board-copper.c
index a8094e1..94d2543 100644
--- a/arch/arm/mach-msm/board-copper.c
+++ b/arch/arm/mach-msm/board-copper.c
@@ -481,6 +481,8 @@
"msm_serial_hsl.0", NULL),
OF_DEV_AUXDATA("qcom,hsusb-otg", 0xF9A55000, \
"msm_otg", NULL),
+ OF_DEV_AUXDATA("qcom,dwc-usb3-msm", 0xF9200000, \
+ "msm_dwc3", NULL),
OF_DEV_AUXDATA("qcom,spi-qup-v2", 0xF9924000, \
"spi_qsd.1", NULL),
OF_DEV_AUXDATA("qcom,spmi-pmic-arb", 0xFC4C0000, \
diff --git a/arch/arm/mach-msm/clock-copper.c b/arch/arm/mach-msm/clock-copper.c
index fc0b0af..dd7967d 100644
--- a/arch/arm/mach-msm/clock-copper.c
+++ b/arch/arm/mach-msm/clock-copper.c
@@ -4650,14 +4650,14 @@
CLK_LOOKUP("iface_clk", gcc_tsif_ahb_clk.c, ""),
CLK_LOOKUP("ref_clk", gcc_tsif_ref_clk.c, ""),
- CLK_LOOKUP("core_clk", gcc_usb30_master_clk.c, ""),
- CLK_LOOKUP("core_clk", gcc_usb30_mock_utmi_clk.c, ""),
- CLK_LOOKUP("iface_clk", gcc_usb_hs_ahb_clk.c, "msm_otg"),
- CLK_LOOKUP("core_clk", gcc_usb_hs_system_clk.c, ""),
- CLK_LOOKUP("iface_clk", gcc_usb_hsic_ahb_clk.c, ""),
- CLK_LOOKUP("core_clk", gcc_usb_hsic_clk.c, ""),
- CLK_LOOKUP("core_clk", gcc_usb_hsic_io_cal_clk.c, ""),
- CLK_LOOKUP("core_clk", gcc_usb_hsic_system_clk.c, ""),
+ CLK_LOOKUP("core_clk", gcc_usb30_master_clk.c, "msm_dwc3"),
+ CLK_LOOKUP("utmi_clk", gcc_usb30_mock_utmi_clk.c, "msm_dwc3"),
+ CLK_LOOKUP("iface_clk", gcc_usb_hs_ahb_clk.c, "msm_otg"),
+ CLK_LOOKUP("core_clk", gcc_usb_hs_system_clk.c, "msm_otg"),
+ CLK_LOOKUP("iface_clk", gcc_usb_hsic_ahb_clk.c, "msm_hsic_host"),
+ CLK_LOOKUP("phy_clk", gcc_usb_hsic_clk.c, "msm_hsic_host"),
+ CLK_LOOKUP("cal_clk", gcc_usb_hsic_io_cal_clk.c, "msm_hsic_host"),
+ CLK_LOOKUP("core_clk", gcc_usb_hsic_system_clk.c, "msm_hsic_host"),
/* Multimedia clocks */
CLK_LOOKUP("bus_clk_src", axi_clk_src.c, ""),
@@ -4782,8 +4782,6 @@
CLK_LOOKUP("core_clk", gcc_prng_ahb_clk.c, "msm_rng"),
/* TODO: Remove dummy clocks as soon as they become unnecessary */
- CLK_DUMMY("phy_clk", NULL, "msm_otg", OFF),
- CLK_DUMMY("core_clk", NULL, "msm_otg", OFF),
CLK_DUMMY("dfab_clk", DFAB_CLK, "msm_sps", OFF),
CLK_DUMMY("mem_clk", NULL, "msm_sps", OFF),
CLK_DUMMY("bus_clk", NULL, "scm", OFF),
diff --git a/arch/arm/mach-msm/clock-local.c b/arch/arm/mach-msm/clock-local.c
index 4f365fa..02e103d 100644
--- a/arch/arm/mach-msm/clock-local.c
+++ b/arch/arm/mach-msm/clock-local.c
@@ -464,10 +464,7 @@
if (nf->freq_hz == FREQ_END)
return -EINVAL;
- /* Check if frequency is actually changed. */
cf = clk->current_freq;
- if (nf == cf)
- return 0;
if (clk->enabled) {
/* Enable source clock dependency for the new freq. */
@@ -881,9 +878,6 @@
if (rate > clk->max_div)
return -EINVAL;
- /* Check if frequency is actually changed. */
- if (rate == clk->cur_div)
- return 0;
spin_lock(&local_clock_reg_lock);
reg_val = readl_relaxed(clk->ns_reg);
diff --git a/arch/arm/mach-msm/clock-local2.c b/arch/arm/mach-msm/clock-local2.c
index cf45e63..c84cfb8 100644
--- a/arch/arm/mach-msm/clock-local2.c
+++ b/arch/arm/mach-msm/clock-local2.c
@@ -166,10 +166,7 @@
if (nf->freq_hz == FREQ_END)
return -EINVAL;
- /* Check if frequency is actually changed. */
cf = rcg->current_freq;
- if (nf == cf)
- return 0;
if (rcg->c.count) {
/* TODO: Modify to use the prepare API */
diff --git a/arch/arm/mach-msm/clock-rpm.c b/arch/arm/mach-msm/clock-rpm.c
index ae87bb7..4539828 100644
--- a/arch/arm/mach-msm/clock-rpm.c
+++ b/arch/arm/mach-msm/clock-rpm.c
@@ -116,10 +116,6 @@
spin_lock_irqsave(&rpm_clock_lock, flags);
- /* Ignore duplicate requests. */
- if (r->last_set_khz == this_khz)
- goto out;
-
/* Active-only clocks don't care what the rate is during sleep. So,
* they vote for zero. */
if (r->active_only)
diff --git a/arch/arm/mach-msm/clock.c b/arch/arm/mach-msm/clock.c
index fb5b580..8a1c6eb 100644
--- a/arch/arm/mach-msm/clock.c
+++ b/arch/arm/mach-msm/clock.c
@@ -320,7 +320,7 @@
int clk_set_rate(struct clk *clk, unsigned long rate)
{
unsigned long start_rate, flags;
- int rc;
+ int rc = 0;
if (IS_ERR_OR_NULL(clk))
return -EINVAL;
@@ -329,6 +329,11 @@
return -ENOSYS;
spin_lock_irqsave(&clk->lock, flags);
+
+ /* Return early if the rate isn't going to change */
+ if (clk->rate == rate)
+ goto out;
+
trace_clock_set_rate(clk->dbg_name, rate, smp_processor_id());
if (clk->count) {
start_rate = clk->rate;
@@ -347,7 +352,7 @@
if (!rc)
clk->rate = rate;
-
+out:
spin_unlock_irqrestore(&clk->lock, flags);
return rc;
diff --git a/arch/arm/mach-msm/devices-8930.c b/arch/arm/mach-msm/devices-8930.c
index 2c4687f..c480bba 100644
--- a/arch/arm/mach-msm/devices-8930.c
+++ b/arch/arm/mach-msm/devices-8930.c
@@ -127,7 +127,6 @@
MSM_RPM_MAP(8930, CXO_BUFFERS, CXO_BUFFERS, 1),
MSM_RPM_MAP(8930, USB_OTG_SWITCH, USB_OTG_SWITCH, 1),
MSM_RPM_MAP(8930, HDMI_SWITCH, HDMI_SWITCH, 1),
- MSM_RPM_MAP(8930, DDR_DMM_0, DDR_DMM, 2),
MSM_RPM_MAP(8930, QDSS_CLK, QDSS_CLK, 1),
MSM_RPM_MAP(8930, VOLTAGE_CORNER, VOLTAGE_CORNER, 1),
},
@@ -232,8 +231,6 @@
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, DDR_DMM_0),
- MSM_RPM_STATUS_ID_MAP(8930, DDR_DMM_1),
MSM_RPM_STATUS_ID_MAP(8930, QDSS_CLK),
MSM_RPM_STATUS_ID_MAP(8930, VOLTAGE_CORNER),
},
diff --git a/arch/arm/mach-msm/include/mach/gpio.h b/arch/arm/mach-msm/include/mach/gpio.h
index 8aed079..1d32003 100644
--- a/arch/arm/mach-msm/include/mach/gpio.h
+++ b/arch/arm/mach-msm/include/mach/gpio.h
@@ -178,7 +178,7 @@
TLMM_PULL_SDC1_DATA,
};
-#ifdef CONFIG_GPIO_MSM_V2
+#if defined(CONFIG_GPIO_MSM_V2) || defined(CONFIG_GPIO_MSM_V3)
void msm_tlmm_set_hdrive(enum msm_tlmm_hdrive_tgt tgt, int drv_str);
void msm_tlmm_set_pull(enum msm_tlmm_pull_tgt tgt, int pull);
diff --git a/arch/arm/mach-msm/include/mach/irqs-copper.h b/arch/arm/mach-msm/include/mach/irqs-copper.h
index 6d27d69..8cd8620 100644
--- a/arch/arm/mach-msm/include/mach/irqs-copper.h
+++ b/arch/arm/mach-msm/include/mach/irqs-copper.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
@@ -35,7 +35,7 @@
#define SPS_BAM_DMA_IRQ (GIC_SPI_START + 105)
#define NR_MSM_IRQS 1020 /* Should be 256 - but higher due to bug in sim */
-#define NR_GPIO_IRQS 156
+#define NR_GPIO_IRQS 146
#define NR_QPNP_IRQS 32768 /* SPARSE_IRQ is required to support this */
#define NR_BOARD_IRQS NR_QPNP_IRQS
#define NR_TLMM_MSM_DIR_CONN_IRQ 8
diff --git a/arch/arm/mach-msm/include/mach/rpm-8930.h b/arch/arm/mach-msm/include/mach/rpm-8930.h
index 5ec3a74..6fd9cf4 100644
--- a/arch/arm/mach-msm/include/mach/rpm-8930.h
+++ b/arch/arm/mach-msm/include/mach/rpm-8930.h
@@ -240,10 +240,8 @@
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_DDR_DMM_0 = 167,
- MSM_RPM_8930_ID_DDR_DMM_1 = 168,
- MSM_RPM_8930_ID_QDSS_CLK = 168,
- MSM_RPM_8930_ID_VOLTAGE_CORNER = 169,
+ MSM_RPM_8930_ID_QDSS_CLK = 167,
+ MSM_RPM_8930_ID_VOLTAGE_CORNER = 168,
MSM_RPM_8930_ID_LAST = MSM_RPM_8930_ID_VOLTAGE_CORNER,
};
@@ -353,10 +351,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_DDR_DMM_0 = 108,
- MSM_RPM_8930_STATUS_ID_DDR_DMM_1 = 109,
- MSM_RPM_8930_STATUS_ID_QDSS_CLK = 110,
- MSM_RPM_8930_STATUS_ID_VOLTAGE_CORNER = 111,
+ MSM_RPM_8930_STATUS_ID_QDSS_CLK = 108,
+ MSM_RPM_8930_STATUS_ID_VOLTAGE_CORNER = 109,
MSM_RPM_8930_STATUS_ID_LAST = MSM_RPM_8930_STATUS_ID_VOLTAGE_CORNER,
};
diff --git a/arch/arm/mach-msm/smd_pkt.c b/arch/arm/mach-msm/smd_pkt.c
index b9cba8c..8d567f8 100644
--- a/arch/arm/mach-msm/smd_pkt.c
+++ b/arch/arm/mach-msm/smd_pkt.c
@@ -76,6 +76,7 @@
struct wake_lock pa_wake_lock; /* Packet Arrival Wake lock*/
struct work_struct packet_arrival_work;
struct spinlock pa_spinlock;
+ int wakelock_locked;
} *smd_pkt_devp[NUM_SMD_PKT_PORTS];
struct class *smd_pkt_classp;
@@ -233,16 +234,19 @@
static void packet_arrival_worker(struct work_struct *work)
{
struct smd_pkt_dev *smd_pkt_devp;
+ unsigned long flags;
smd_pkt_devp = container_of(work, struct smd_pkt_dev,
packet_arrival_work);
mutex_lock(&smd_pkt_devp->ch_lock);
- if (smd_pkt_devp->ch) {
+ spin_lock_irqsave(&smd_pkt_devp->pa_spinlock, flags);
+ if (smd_pkt_devp->ch && smd_pkt_devp->wakelock_locked) {
D_READ("%s locking smd_pkt_dev id:%d wakelock\n",
__func__, smd_pkt_devp->i);
wake_lock_timeout(&smd_pkt_devp->pa_wake_lock,
WAKELOCK_TIMEOUT);
}
+ spin_unlock_irqrestore(&smd_pkt_devp->pa_spinlock, flags);
mutex_unlock(&smd_pkt_devp->ch_lock);
}
@@ -398,6 +402,7 @@
if (smd_pkt_devp->poll_mode &&
!smd_cur_packet_size(smd_pkt_devp->ch)) {
wake_unlock(&smd_pkt_devp->pa_wake_lock);
+ smd_pkt_devp->wakelock_locked = 0;
smd_pkt_devp->poll_mode = 0;
D_READ("%s unlocked smd_pkt_dev id:%d wakelock\n",
__func__, smd_pkt_devp->i);
@@ -570,10 +575,11 @@
}
/* here we have a packet of size sz ready */
- wake_up(&smd_pkt_devp->ch_read_wait_queue);
spin_lock_irqsave(&smd_pkt_devp->pa_spinlock, flags);
wake_lock(&smd_pkt_devp->pa_wake_lock);
+ smd_pkt_devp->wakelock_locked = 1;
spin_unlock_irqrestore(&smd_pkt_devp->pa_spinlock, flags);
+ wake_up(&smd_pkt_devp->ch_read_wait_queue);
schedule_work(&smd_pkt_devp->packet_arrival_work);
D_READ("%s: wake_up smd_pkt_dev id:%d\n", __func__, smd_pkt_devp->i);
}
@@ -907,6 +913,7 @@
smd_pkt_devp->has_reset = 0;
smd_pkt_devp->do_reset_notification = 0;
+ smd_pkt_devp->wakelock_locked = 0;
wake_lock_destroy(&smd_pkt_devp->pa_wake_lock);
D_STATUS("Finished %s on smd_pkt_dev id:%d\n",
__func__, smd_pkt_devp->i);
@@ -962,6 +969,7 @@
init_waitqueue_head(&smd_pkt_devp[i]->ch_write_wait_queue);
smd_pkt_devp[i]->is_open = 0;
smd_pkt_devp[i]->poll_mode = 0;
+ smd_pkt_devp[i]->wakelock_locked = 0;
init_waitqueue_head(&smd_pkt_devp[i]->ch_opened_wait_queue);
spin_lock_init(&smd_pkt_devp[i]->pa_spinlock);
diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig
index ef077a5..0dcf1a4 100644
--- a/drivers/gpio/Kconfig
+++ b/drivers/gpio/Kconfig
@@ -124,6 +124,15 @@
Qualcomm MSM chips. Most of the pins on the MSM can be
selected for GPIO, and are controlled by this driver.
+config GPIO_MSM_V3
+ tristate "Qualcomm MSM GPIO v3"
+ depends on GPIOLIB && ARCH_MSM
+ help
+ Say yes here to support the GPIO interface on ARM v7 based
+ Qualcomm MSM chips for v3 version of the interface. Most of
+ the pins on the MSM can be selected for GPIO, and are
+ controlled by this driver.
+
config GPIO_FSM9XXX
tristate "Qualcomm FSM GPIO"
depends on GPIOLIB && ARCH_MSM
diff --git a/drivers/gpio/Makefile b/drivers/gpio/Makefile
index babd44d..d15b628 100644
--- a/drivers/gpio/Makefile
+++ b/drivers/gpio/Makefile
@@ -33,7 +33,8 @@
obj-$(CONFIG_GPIO_MPC5200) += gpio-mpc5200.o
obj-$(CONFIG_GPIO_MPC8XXX) += gpio-mpc8xxx.o
obj-$(CONFIG_GPIO_MSM_V1) += gpio-msm-v1.o
-obj-$(CONFIG_GPIO_MSM_V2) += gpio-msm-v2.o
+obj-$(CONFIG_GPIO_MSM_V2) += gpio-msm-common.o gpio-msm-v2.o
+obj-$(CONFIG_GPIO_MSM_V3) += gpio-msm-common.o gpio-msm-v3.o
obj-$(CONFIG_GPIO_FSM9XXX) += gpio-fsm9xxx.o
obj-$(CONFIG_GPIO_MXC) += gpio-mxc.o
obj-$(CONFIG_GPIO_MXS) += gpio-mxs.o
diff --git a/drivers/gpio/gpio-msm-common.c b/drivers/gpio/gpio-msm-common.c
new file mode 100644
index 0000000..9a9a783
--- /dev/null
+++ b/drivers/gpio/gpio-msm-common.c
@@ -0,0 +1,629 @@
+/* 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/bitmap.h>
+#include <linux/bitops.h>
+#include <linux/gpio.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/irq.h>
+#include <linux/io.h>
+#include <linux/module.h>
+#include <linux/spinlock.h>
+#include <linux/syscore_ops.h>
+#include <linux/irqdomain.h>
+#include <linux/of.h>
+#include <linux/err.h>
+
+#include <asm/mach/irq.h>
+
+#include <mach/msm_iomap.h>
+#include <mach/gpiomux.h>
+#include <mach/mpm.h>
+#include "gpio-msm-common.h"
+
+enum msm_tlmm_register {
+ SDC4_HDRV_PULL_CTL = 0x20a0,
+ SDC3_HDRV_PULL_CTL = 0x20a4,
+ SDC1_HDRV_PULL_CTL = 0x20a0,
+};
+
+struct tlmm_field_cfg {
+ enum msm_tlmm_register reg;
+ u8 off;
+};
+
+static const struct tlmm_field_cfg tlmm_hdrv_cfgs[] = {
+ {SDC4_HDRV_PULL_CTL, 6}, /* TLMM_HDRV_SDC4_CLK */
+ {SDC4_HDRV_PULL_CTL, 3}, /* TLMM_HDRV_SDC4_CMD */
+ {SDC4_HDRV_PULL_CTL, 0}, /* TLMM_HDRV_SDC4_DATA */
+ {SDC3_HDRV_PULL_CTL, 6}, /* TLMM_HDRV_SDC3_CLK */
+ {SDC3_HDRV_PULL_CTL, 3}, /* TLMM_HDRV_SDC3_CMD */
+ {SDC3_HDRV_PULL_CTL, 0}, /* TLMM_HDRV_SDC3_DATA */
+ {SDC1_HDRV_PULL_CTL, 6}, /* TLMM_HDRV_SDC1_CLK */
+ {SDC1_HDRV_PULL_CTL, 3}, /* TLMM_HDRV_SDC1_CMD */
+ {SDC1_HDRV_PULL_CTL, 0}, /* TLMM_HDRV_SDC1_DATA */
+};
+
+static const struct tlmm_field_cfg tlmm_pull_cfgs[] = {
+ {SDC4_HDRV_PULL_CTL, 11}, /* TLMM_PULL_SDC4_CMD */
+ {SDC4_HDRV_PULL_CTL, 9}, /* TLMM_PULL_SDC4_DATA */
+ {SDC3_HDRV_PULL_CTL, 14}, /* TLMM_PULL_SDC3_CLK */
+ {SDC3_HDRV_PULL_CTL, 11}, /* TLMM_PULL_SDC3_CMD */
+ {SDC3_HDRV_PULL_CTL, 9}, /* TLMM_PULL_SDC3_DATA */
+ {SDC1_HDRV_PULL_CTL, 13}, /* TLMM_PULL_SDC1_CLK */
+ {SDC1_HDRV_PULL_CTL, 11}, /* TLMM_PULL_SDC1_CMD */
+ {SDC1_HDRV_PULL_CTL, 9}, /* TLMM_PULL_SDC1_DATA */
+};
+
+/*
+ * Supported arch specific irq extension.
+ * Default make them NULL.
+ */
+struct irq_chip msm_gpio_irq_extn = {
+ .irq_eoi = NULL,
+ .irq_mask = NULL,
+ .irq_unmask = NULL,
+ .irq_retrigger = NULL,
+ .irq_set_type = NULL,
+ .irq_set_wake = NULL,
+ .irq_disable = NULL,
+};
+
+/**
+ * struct msm_gpio_dev: the MSM8660 SoC GPIO device structure
+ *
+ * @enabled_irqs: a bitmap used to optimize the summary-irq handler. By
+ * keeping track of which gpios are unmasked as irq sources, we avoid
+ * having to do __raw_readl calls on hundreds of iomapped registers each time
+ * the summary interrupt fires in order to locate the active interrupts.
+ *
+ * @wake_irqs: a bitmap for tracking which interrupt lines are enabled
+ * as wakeup sources. When the device is suspended, interrupts which are
+ * not wakeup sources are disabled.
+ *
+ * @dual_edge_irqs: a bitmap used to track which irqs are configured
+ * as dual-edge, as this is not supported by the hardware and requires
+ * some special handling in the driver.
+ */
+struct msm_gpio_dev {
+ struct gpio_chip gpio_chip;
+ DECLARE_BITMAP(enabled_irqs, NR_MSM_GPIOS);
+ DECLARE_BITMAP(wake_irqs, NR_MSM_GPIOS);
+ DECLARE_BITMAP(dual_edge_irqs, NR_MSM_GPIOS);
+ struct irq_domain domain;
+};
+
+static DEFINE_SPINLOCK(tlmm_lock);
+
+static inline struct msm_gpio_dev *to_msm_gpio_dev(struct gpio_chip *chip)
+{
+ return container_of(chip, struct msm_gpio_dev, gpio_chip);
+}
+
+static int msm_gpio_get(struct gpio_chip *chip, unsigned offset)
+{
+ int rc;
+ rc = __msm_gpio_get_inout(offset);
+ mb();
+ return rc;
+}
+
+static void msm_gpio_set(struct gpio_chip *chip, unsigned offset, int val)
+{
+ __msm_gpio_set_inout(offset, val);
+ mb();
+}
+
+static int msm_gpio_direction_input(struct gpio_chip *chip, unsigned offset)
+{
+ unsigned long irq_flags;
+
+ spin_lock_irqsave(&tlmm_lock, irq_flags);
+ __msm_gpio_set_config_direction(offset, 1, 0);
+ mb();
+ spin_unlock_irqrestore(&tlmm_lock, irq_flags);
+ return 0;
+}
+
+static int msm_gpio_direction_output(struct gpio_chip *chip,
+ unsigned offset,
+ int val)
+{
+ unsigned long irq_flags;
+
+ spin_lock_irqsave(&tlmm_lock, irq_flags);
+ __msm_gpio_set_config_direction(offset, 0, val);
+ mb();
+ spin_unlock_irqrestore(&tlmm_lock, irq_flags);
+ return 0;
+}
+
+#ifdef CONFIG_OF
+static int msm_gpio_to_irq(struct gpio_chip *chip, unsigned offset)
+{
+ struct msm_gpio_dev *g_dev = to_msm_gpio_dev(chip);
+ struct irq_domain *domain = &g_dev->domain;
+ return domain->irq_base + (offset - chip->base);
+}
+
+static inline int msm_irq_to_gpio(struct gpio_chip *chip, unsigned irq)
+{
+ struct msm_gpio_dev *g_dev = to_msm_gpio_dev(chip);
+ struct irq_domain *domain = &g_dev->domain;
+ return irq - domain->irq_base;
+}
+#else
+static int msm_gpio_to_irq(struct gpio_chip *chip, unsigned offset)
+{
+ return MSM_GPIO_TO_INT(offset - chip->base);
+}
+
+static inline int msm_irq_to_gpio(struct gpio_chip *chip, unsigned irq)
+{
+ return irq - MSM_GPIO_TO_INT(chip->base);
+}
+#endif
+
+static int msm_gpio_request(struct gpio_chip *chip, unsigned offset)
+{
+ return msm_gpiomux_get(chip->base + offset);
+}
+
+static void msm_gpio_free(struct gpio_chip *chip, unsigned offset)
+{
+ msm_gpiomux_put(chip->base + offset);
+}
+
+static struct msm_gpio_dev msm_gpio = {
+ .gpio_chip = {
+ .label = "msmgpio",
+ .base = 0,
+ .ngpio = NR_MSM_GPIOS,
+ .direction_input = msm_gpio_direction_input,
+ .direction_output = msm_gpio_direction_output,
+ .get = msm_gpio_get,
+ .set = msm_gpio_set,
+ .to_irq = msm_gpio_to_irq,
+ .request = msm_gpio_request,
+ .free = msm_gpio_free,
+ },
+};
+
+static void switch_mpm_config(struct irq_data *d, unsigned val)
+{
+ /* switch the configuration in the mpm as well */
+ if (!msm_gpio_irq_extn.irq_set_type)
+ return;
+
+ if (val)
+ msm_gpio_irq_extn.irq_set_type(d, IRQF_TRIGGER_FALLING);
+ else
+ msm_gpio_irq_extn.irq_set_type(d, IRQF_TRIGGER_RISING);
+}
+
+/* For dual-edge interrupts in software, since the hardware has no
+ * such support:
+ *
+ * At appropriate moments, this function may be called to flip the polarity
+ * settings of both-edge irq lines to try and catch the next edge.
+ *
+ * The attempt is considered successful if:
+ * - the status bit goes high, indicating that an edge was caught, or
+ * - the input value of the gpio doesn't change during the attempt.
+ * If the value changes twice during the process, that would cause the first
+ * test to fail but would force the second, as two opposite
+ * transitions would cause a detection no matter the polarity setting.
+ *
+ * The do-loop tries to sledge-hammer closed the timing hole between
+ * the initial value-read and the polarity-write - if the line value changes
+ * during that window, an interrupt is lost, the new polarity setting is
+ * incorrect, and the first success test will fail, causing a retry.
+ *
+ * Algorithm comes from Google's msmgpio driver, see mach-msm/gpio.c.
+ */
+static void msm_gpio_update_dual_edge_pos(struct irq_data *d, unsigned gpio)
+{
+ int loop_limit = 100;
+ unsigned val, val2, intstat;
+
+ do {
+ val = __msm_gpio_get_inout(gpio);
+ __msm_gpio_set_polarity(gpio, val);
+ val2 = __msm_gpio_get_inout(gpio);
+ intstat = __msm_gpio_get_intr_status(gpio);
+ if (intstat || val == val2) {
+ switch_mpm_config(d, val);
+ return;
+ }
+ } while (loop_limit-- > 0);
+ pr_err("%s: dual-edge irq failed to stabilize, %#08x != %#08x\n",
+ __func__, val, val2);
+}
+
+static void msm_gpio_irq_ack(struct irq_data *d)
+{
+ int gpio = msm_irq_to_gpio(&msm_gpio.gpio_chip, d->irq);
+
+ __msm_gpio_set_intr_status(gpio);
+ if (test_bit(gpio, msm_gpio.dual_edge_irqs))
+ msm_gpio_update_dual_edge_pos(d, gpio);
+ mb();
+}
+
+static void msm_gpio_irq_mask(struct irq_data *d)
+{
+ int gpio = msm_irq_to_gpio(&msm_gpio.gpio_chip, d->irq);
+ unsigned long irq_flags;
+
+ spin_lock_irqsave(&tlmm_lock, irq_flags);
+ __msm_gpio_set_intr_cfg_enable(gpio, 0);
+ __clear_bit(gpio, msm_gpio.enabled_irqs);
+ mb();
+ spin_unlock_irqrestore(&tlmm_lock, irq_flags);
+
+ if (msm_gpio_irq_extn.irq_mask)
+ msm_gpio_irq_extn.irq_mask(d);
+
+}
+
+static void msm_gpio_irq_unmask(struct irq_data *d)
+{
+ int gpio = msm_irq_to_gpio(&msm_gpio.gpio_chip, d->irq);
+ unsigned long irq_flags;
+
+ spin_lock_irqsave(&tlmm_lock, irq_flags);
+ __set_bit(gpio, msm_gpio.enabled_irqs);
+ __msm_gpio_set_intr_cfg_enable(gpio, 1);
+ mb();
+ spin_unlock_irqrestore(&tlmm_lock, irq_flags);
+
+ if (msm_gpio_irq_extn.irq_mask)
+ msm_gpio_irq_extn.irq_unmask(d);
+}
+
+static void msm_gpio_irq_disable(struct irq_data *d)
+{
+ if (msm_gpio_irq_extn.irq_disable)
+ msm_gpio_irq_extn.irq_disable(d);
+}
+
+static int msm_gpio_irq_set_type(struct irq_data *d, unsigned int flow_type)
+{
+ int gpio = msm_irq_to_gpio(&msm_gpio.gpio_chip, d->irq);
+ unsigned long irq_flags;
+
+ spin_lock_irqsave(&tlmm_lock, irq_flags);
+
+ if (flow_type & IRQ_TYPE_EDGE_BOTH) {
+ __irq_set_handler_locked(d->irq, handle_edge_irq);
+ if ((flow_type & IRQ_TYPE_EDGE_BOTH) == IRQ_TYPE_EDGE_BOTH)
+ __set_bit(gpio, msm_gpio.dual_edge_irqs);
+ else
+ __clear_bit(gpio, msm_gpio.dual_edge_irqs);
+ } else {
+ __irq_set_handler_locked(d->irq, handle_level_irq);
+ __clear_bit(gpio, msm_gpio.dual_edge_irqs);
+ }
+
+ __msm_gpio_set_intr_cfg_type(gpio, flow_type);
+
+ if ((flow_type & IRQ_TYPE_EDGE_BOTH) == IRQ_TYPE_EDGE_BOTH)
+ msm_gpio_update_dual_edge_pos(d, gpio);
+
+ mb();
+ spin_unlock_irqrestore(&tlmm_lock, irq_flags);
+
+ if (msm_gpio_irq_extn.irq_set_type)
+ msm_gpio_irq_extn.irq_set_type(d, flow_type);
+
+ return 0;
+}
+
+/*
+ * When the summary IRQ is raised, any number of GPIO lines may be high.
+ * It is the job of the summary handler to find all those GPIO lines
+ * which have been set as summary IRQ lines and which are triggered,
+ * and to call their interrupt handlers.
+ */
+static irqreturn_t msm_summary_irq_handler(int irq, void *data)
+{
+ unsigned long i;
+ struct irq_desc *desc = irq_to_desc(irq);
+ struct irq_chip *chip = irq_desc_get_chip(desc);
+
+ chained_irq_enter(chip, desc);
+
+ for (i = find_first_bit(msm_gpio.enabled_irqs, NR_MSM_GPIOS);
+ i < NR_MSM_GPIOS;
+ i = find_next_bit(msm_gpio.enabled_irqs, NR_MSM_GPIOS, i + 1)) {
+ if (__msm_gpio_get_intr_status(i))
+ generic_handle_irq(msm_gpio_to_irq(&msm_gpio.gpio_chip,
+ i));
+ }
+
+ chained_irq_exit(chip, desc);
+ return IRQ_HANDLED;
+}
+
+static int msm_gpio_irq_set_wake(struct irq_data *d, unsigned int on)
+{
+ int gpio = msm_irq_to_gpio(&msm_gpio.gpio_chip, d->irq);
+
+ if (on) {
+ if (bitmap_empty(msm_gpio.wake_irqs, NR_MSM_GPIOS))
+ irq_set_irq_wake(TLMM_MSM_SUMMARY_IRQ, 1);
+ set_bit(gpio, msm_gpio.wake_irqs);
+ } else {
+ clear_bit(gpio, msm_gpio.wake_irqs);
+ if (bitmap_empty(msm_gpio.wake_irqs, NR_MSM_GPIOS))
+ irq_set_irq_wake(TLMM_MSM_SUMMARY_IRQ, 0);
+ }
+
+ if (msm_gpio_irq_extn.irq_set_wake)
+ msm_gpio_irq_extn.irq_set_wake(d, on);
+
+ return 0;
+}
+
+static struct irq_chip msm_gpio_irq_chip = {
+ .name = "msmgpio",
+ .irq_mask = msm_gpio_irq_mask,
+ .irq_unmask = msm_gpio_irq_unmask,
+ .irq_ack = msm_gpio_irq_ack,
+ .irq_set_type = msm_gpio_irq_set_type,
+ .irq_set_wake = msm_gpio_irq_set_wake,
+ .irq_disable = msm_gpio_irq_disable,
+};
+
+/*
+ * This lock class tells lockdep that GPIO irqs are in a different
+ * category than their parent, so it won't report false recursion.
+ */
+static struct lock_class_key msm_gpio_lock_class;
+
+static int __devinit msm_gpio_probe(void)
+{
+ int i, irq, ret;
+
+ spin_lock_init(&tlmm_lock);
+ bitmap_zero(msm_gpio.enabled_irqs, NR_MSM_GPIOS);
+ bitmap_zero(msm_gpio.wake_irqs, NR_MSM_GPIOS);
+ bitmap_zero(msm_gpio.dual_edge_irqs, NR_MSM_GPIOS);
+ ret = gpiochip_add(&msm_gpio.gpio_chip);
+ if (ret < 0)
+ return ret;
+
+ for (i = 0; i < msm_gpio.gpio_chip.ngpio; ++i) {
+ irq = msm_gpio_to_irq(&msm_gpio.gpio_chip, i);
+ irq_set_lockdep_class(irq, &msm_gpio_lock_class);
+ irq_set_chip_and_handler(irq, &msm_gpio_irq_chip,
+ handle_level_irq);
+ set_irq_flags(irq, IRQF_VALID);
+ }
+
+ ret = request_irq(TLMM_MSM_SUMMARY_IRQ, msm_summary_irq_handler,
+ IRQF_TRIGGER_HIGH, "msmgpio", NULL);
+ if (ret) {
+ pr_err("Request_irq failed for TLMM_MSM_SUMMARY_IRQ - %d\n",
+ ret);
+ return ret;
+ }
+ return 0;
+}
+
+static int __devexit msm_gpio_remove(void)
+{
+ int ret = gpiochip_remove(&msm_gpio.gpio_chip);
+
+ if (ret < 0)
+ return ret;
+
+ irq_set_handler(TLMM_MSM_SUMMARY_IRQ, NULL);
+
+ return 0;
+}
+
+#ifdef CONFIG_PM
+static int msm_gpio_suspend(void)
+{
+ unsigned long irq_flags;
+ unsigned long i;
+
+ spin_lock_irqsave(&tlmm_lock, irq_flags);
+ for_each_set_bit(i, msm_gpio.enabled_irqs, NR_MSM_GPIOS)
+ __msm_gpio_set_intr_cfg_enable(i, 0);
+
+ for_each_set_bit(i, msm_gpio.wake_irqs, NR_MSM_GPIOS)
+ __msm_gpio_set_intr_cfg_enable(i, 1);
+ mb();
+ spin_unlock_irqrestore(&tlmm_lock, irq_flags);
+ return 0;
+}
+
+void msm_gpio_show_resume_irq(void)
+{
+ unsigned long irq_flags;
+ int i, irq, intstat;
+
+ if (!msm_show_resume_irq_mask)
+ return;
+
+ spin_lock_irqsave(&tlmm_lock, irq_flags);
+ for_each_set_bit(i, msm_gpio.wake_irqs, NR_MSM_GPIOS) {
+ intstat = __msm_gpio_get_intr_status(i);
+ if (intstat) {
+ irq = msm_gpio_to_irq(&msm_gpio.gpio_chip, i);
+ pr_warning("%s: %d triggered\n",
+ __func__, irq);
+ }
+ }
+ spin_unlock_irqrestore(&tlmm_lock, irq_flags);
+}
+
+static void msm_gpio_resume(void)
+{
+ unsigned long irq_flags;
+ unsigned long i;
+
+ msm_gpio_show_resume_irq();
+
+ spin_lock_irqsave(&tlmm_lock, irq_flags);
+ for_each_set_bit(i, msm_gpio.wake_irqs, NR_MSM_GPIOS)
+ __msm_gpio_set_intr_cfg_enable(i, 0);
+
+ for_each_set_bit(i, msm_gpio.enabled_irqs, NR_MSM_GPIOS)
+ __msm_gpio_set_intr_cfg_enable(i, 1);
+ mb();
+ spin_unlock_irqrestore(&tlmm_lock, irq_flags);
+}
+#else
+#define msm_gpio_suspend NULL
+#define msm_gpio_resume NULL
+#endif
+
+static struct syscore_ops msm_gpio_syscore_ops = {
+ .suspend = msm_gpio_suspend,
+ .resume = msm_gpio_resume,
+};
+
+static int __init msm_gpio_init(void)
+{
+ msm_gpio_probe();
+ register_syscore_ops(&msm_gpio_syscore_ops);
+ return 0;
+}
+
+static void __exit msm_gpio_exit(void)
+{
+ unregister_syscore_ops(&msm_gpio_syscore_ops);
+ msm_gpio_remove();
+}
+
+postcore_initcall(msm_gpio_init);
+module_exit(msm_gpio_exit);
+
+static void msm_tlmm_set_field(const struct tlmm_field_cfg *configs,
+ unsigned id, unsigned width, unsigned val)
+{
+ unsigned long irqflags;
+ u32 mask = (1 << width) - 1;
+ u32 __iomem *reg = MSM_TLMM_BASE + configs[id].reg;
+ u32 reg_val;
+
+ spin_lock_irqsave(&tlmm_lock, irqflags);
+ reg_val = __raw_readl(reg);
+ reg_val &= ~(mask << configs[id].off);
+ reg_val |= (val & mask) << configs[id].off;
+ __raw_writel(reg_val, reg);
+ mb();
+ spin_unlock_irqrestore(&tlmm_lock, irqflags);
+}
+
+void msm_tlmm_set_hdrive(enum msm_tlmm_hdrive_tgt tgt, int drv_str)
+{
+ msm_tlmm_set_field(tlmm_hdrv_cfgs, tgt, 3, drv_str);
+}
+EXPORT_SYMBOL(msm_tlmm_set_hdrive);
+
+void msm_tlmm_set_pull(enum msm_tlmm_pull_tgt tgt, int pull)
+{
+ msm_tlmm_set_field(tlmm_pull_cfgs, tgt, 2, pull);
+}
+EXPORT_SYMBOL(msm_tlmm_set_pull);
+
+int gpio_tlmm_config(unsigned config, unsigned disable)
+{
+ unsigned gpio = GPIO_PIN(config);
+
+ if (gpio > NR_MSM_GPIOS)
+ return -EINVAL;
+
+ __gpio_tlmm_config(config);
+ mb();
+
+ return 0;
+}
+EXPORT_SYMBOL(gpio_tlmm_config);
+
+int msm_gpio_install_direct_irq(unsigned gpio, unsigned irq,
+ unsigned int input_polarity)
+{
+ unsigned long irq_flags;
+
+ if (gpio >= NR_MSM_GPIOS || irq >= NR_TLMM_MSM_DIR_CONN_IRQ)
+ return -EINVAL;
+
+ spin_lock_irqsave(&tlmm_lock, irq_flags);
+ __msm_gpio_install_direct_irq(gpio, irq, input_polarity);
+ mb();
+ spin_unlock_irqrestore(&tlmm_lock, irq_flags);
+
+ return 0;
+}
+EXPORT_SYMBOL(msm_gpio_install_direct_irq);
+
+#ifdef CONFIG_OF
+static int msm_gpio_domain_dt_translate(struct irq_domain *d,
+ struct device_node *controller,
+ const u32 *intspec,
+ unsigned int intsize,
+ unsigned long *out_hwirq,
+ unsigned int *out_type)
+{
+ if (d->of_node != controller)
+ return -EINVAL;
+ if (intsize != 2)
+ return -EINVAL;
+
+ /* hwirq value */
+ *out_hwirq = intspec[0];
+
+ /* irq flags */
+ *out_type = intspec[1] & IRQ_TYPE_SENSE_MASK;
+ return 0;
+}
+
+static struct irq_domain_ops msm_gpio_irq_domain_ops = {
+ .dt_translate = msm_gpio_domain_dt_translate,
+};
+
+int __init msm_gpio_of_init(struct device_node *node,
+ struct device_node *parent)
+{
+ struct irq_domain *domain = &msm_gpio.domain;
+ int start;
+
+ start = irq_domain_find_free_range(0, NR_MSM_GPIOS);
+ domain->irq_base = irq_alloc_descs(start, 0, NR_MSM_GPIOS,
+ numa_node_id());
+ if (IS_ERR_VALUE(domain->irq_base)) {
+ WARN(1, "Cannot allocate irq_descs @ IRQ%d\n", start);
+ return domain->irq_base;
+ }
+
+ domain->nr_irq = NR_MSM_GPIOS;
+ domain->of_node = of_node_get(node);
+ domain->priv = &msm_gpio;
+ domain->ops = &msm_gpio_irq_domain_ops;
+ irq_domain_add(domain);
+ msm_gpio.gpio_chip.of_node = of_node_get(node);
+ pr_debug("%s: irq_base = %u\n", __func__, domain->irq_base);
+
+ return 0;
+}
+#endif
+
+MODULE_AUTHOR("Gregory Bean <gbean@codeaurora.org>");
+MODULE_DESCRIPTION("Driver for Qualcomm MSM TLMMv2 SoC GPIOs");
+MODULE_LICENSE("GPL v2");
+MODULE_ALIAS("sysdev:msmgpio");
diff --git a/drivers/gpio/gpio-msm-common.h b/drivers/gpio/gpio-msm-common.h
new file mode 100644
index 0000000..c9ea3da
--- /dev/null
+++ b/drivers/gpio/gpio-msm-common.h
@@ -0,0 +1,29 @@
+/* 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 __ARCH_ARM_MACH_MSM_GPIO_COMMON_H
+#define __ARCH_ARM_MACH_MSM_GPIO_COMMON_H
+
+extern int msm_show_resume_irq_mask;
+
+unsigned __msm_gpio_get_inout(unsigned gpio);
+void __msm_gpio_set_inout(unsigned gpio, unsigned val);
+void __msm_gpio_set_config_direction(unsigned gpio, int input, int val);
+void __msm_gpio_set_polarity(unsigned gpio, unsigned val);
+unsigned __msm_gpio_get_intr_status(unsigned gpio);
+void __msm_gpio_set_intr_status(unsigned gpio);
+unsigned __msm_gpio_get_intr_config(unsigned gpio);
+void __msm_gpio_set_intr_cfg_enable(unsigned gpio, unsigned val);
+void __msm_gpio_set_intr_cfg_type(unsigned gpio, unsigned type);
+void __gpio_tlmm_config(unsigned config);
+void __msm_gpio_install_direct_irq(unsigned gpio, unsigned irq,
+ unsigned int input_polarity);
+#endif
diff --git a/drivers/gpio/gpio-msm-v2.c b/drivers/gpio/gpio-msm-v2.c
index ad436e0..fb43562 100644
--- a/drivers/gpio/gpio-msm-v2.c
+++ b/drivers/gpio/gpio-msm-v2.c
@@ -14,21 +14,12 @@
#include <linux/bitops.h>
#include <linux/gpio.h>
#include <linux/init.h>
-#include <linux/interrupt.h>
-#include <linux/irq.h>
#include <linux/io.h>
-#include <linux/module.h>
-#include <linux/spinlock.h>
-#include <linux/syscore_ops.h>
-#include <linux/irqdomain.h>
-#include <linux/of.h>
-#include <linux/err.h>
-
-#include <asm/mach/irq.h>
+#include <linux/irq.h>
#include <mach/msm_iomap.h>
#include <mach/gpiomux.h>
-#include <mach/mpm.h>
+#include "gpio-msm-common.h"
/* Bits of interest in the GPIO_IN_OUT register.
*/
@@ -75,54 +66,6 @@
DC_IRQ_ENABLE = BIT(3),
};
-enum msm_tlmm_register {
- SDC4_HDRV_PULL_CTL = 0x20a0,
- SDC3_HDRV_PULL_CTL = 0x20a4,
- SDC1_HDRV_PULL_CTL = 0x20a0,
-};
-
-struct tlmm_field_cfg {
- enum msm_tlmm_register reg;
- u8 off;
-};
-
-static const struct tlmm_field_cfg tlmm_hdrv_cfgs[] = {
- {SDC4_HDRV_PULL_CTL, 6}, /* TLMM_HDRV_SDC4_CLK */
- {SDC4_HDRV_PULL_CTL, 3}, /* TLMM_HDRV_SDC4_CMD */
- {SDC4_HDRV_PULL_CTL, 0}, /* TLMM_HDRV_SDC4_DATA */
- {SDC3_HDRV_PULL_CTL, 6}, /* TLMM_HDRV_SDC3_CLK */
- {SDC3_HDRV_PULL_CTL, 3}, /* TLMM_HDRV_SDC3_CMD */
- {SDC3_HDRV_PULL_CTL, 0}, /* TLMM_HDRV_SDC3_DATA */
- {SDC1_HDRV_PULL_CTL, 6}, /* TLMM_HDRV_SDC1_CLK */
- {SDC1_HDRV_PULL_CTL, 3}, /* TLMM_HDRV_SDC1_CMD */
- {SDC1_HDRV_PULL_CTL, 0}, /* TLMM_HDRV_SDC1_DATA */
-};
-
-static const struct tlmm_field_cfg tlmm_pull_cfgs[] = {
- {SDC4_HDRV_PULL_CTL, 11}, /* TLMM_PULL_SDC4_CMD */
- {SDC4_HDRV_PULL_CTL, 9}, /* TLMM_PULL_SDC4_DATA */
- {SDC3_HDRV_PULL_CTL, 14}, /* TLMM_PULL_SDC3_CLK */
- {SDC3_HDRV_PULL_CTL, 11}, /* TLMM_PULL_SDC3_CMD */
- {SDC3_HDRV_PULL_CTL, 9}, /* TLMM_PULL_SDC3_DATA */
- {SDC1_HDRV_PULL_CTL, 13}, /* TLMM_PULL_SDC1_CLK */
- {SDC1_HDRV_PULL_CTL, 11}, /* TLMM_PULL_SDC1_CMD */
- {SDC1_HDRV_PULL_CTL, 9}, /* TLMM_PULL_SDC1_DATA */
-};
-
-/*
- * Supported arch specific irq extension.
- * Default make them NULL.
- */
-struct irq_chip msm_gpio_irq_extn = {
- .irq_eoi = NULL,
- .irq_mask = NULL,
- .irq_unmask = NULL,
- .irq_retrigger = NULL,
- .irq_set_type = NULL,
- .irq_set_wake = NULL,
- .irq_disable = NULL,
-};
-
/*
* When a GPIO triggers, two separate decisions are made, controlled
* by two separate flags.
@@ -147,37 +90,6 @@
#define GPIO_INTR_CFG(gpio) (MSM_TLMM_BASE + 0x1008 + (0x10 * (gpio)))
#define GPIO_INTR_STATUS(gpio) (MSM_TLMM_BASE + 0x100c + (0x10 * (gpio)))
-/**
- * struct msm_gpio_dev: the MSM8660 SoC GPIO device structure
- *
- * @enabled_irqs: a bitmap used to optimize the summary-irq handler. By
- * keeping track of which gpios are unmasked as irq sources, we avoid
- * having to do __raw_readl calls on hundreds of iomapped registers each time
- * the summary interrupt fires in order to locate the active interrupts.
- *
- * @wake_irqs: a bitmap for tracking which interrupt lines are enabled
- * as wakeup sources. When the device is suspended, interrupts which are
- * not wakeup sources are disabled.
- *
- * @dual_edge_irqs: a bitmap used to track which irqs are configured
- * as dual-edge, as this is not supported by the hardware and requires
- * some special handling in the driver.
- */
-struct msm_gpio_dev {
- struct gpio_chip gpio_chip;
- DECLARE_BITMAP(enabled_irqs, NR_MSM_GPIOS);
- DECLARE_BITMAP(wake_irqs, NR_MSM_GPIOS);
- DECLARE_BITMAP(dual_edge_irqs, NR_MSM_GPIOS);
- struct irq_domain domain;
-};
-
-static DEFINE_SPINLOCK(tlmm_lock);
-
-static inline struct msm_gpio_dev *to_msm_gpio_dev(struct gpio_chip *chip)
-{
- return container_of(chip, struct msm_gpio_dev, gpio_chip);
-}
-
static inline void set_gpio_bits(unsigned n, void __iomem *reg)
{
__raw_writel(__raw_readl(reg) | n, reg);
@@ -188,498 +100,99 @@
__raw_writel(__raw_readl(reg) & ~n, reg);
}
-static int msm_gpio_get(struct gpio_chip *chip, unsigned offset)
+unsigned __msm_gpio_get_inout(unsigned gpio)
{
- int rc;
- rc = __raw_readl(GPIO_IN_OUT(offset)) & BIT(GPIO_IN_BIT);
- mb();
- return rc;
+ return __raw_readl(GPIO_IN_OUT(gpio)) & BIT(GPIO_IN_BIT);
}
-static void msm_gpio_set(struct gpio_chip *chip, unsigned offset, int val)
+void __msm_gpio_set_inout(unsigned gpio, unsigned val)
{
- __raw_writel(val ? BIT(GPIO_OUT_BIT) : 0, GPIO_IN_OUT(offset));
- mb();
+ __raw_writel(val ? BIT(GPIO_OUT_BIT) : 0, GPIO_IN_OUT(gpio));
}
-static int msm_gpio_direction_input(struct gpio_chip *chip, unsigned offset)
+void __msm_gpio_set_config_direction(unsigned gpio, int input, int val)
{
- unsigned long irq_flags;
-
- spin_lock_irqsave(&tlmm_lock, irq_flags);
- clr_gpio_bits(BIT(GPIO_OE_BIT), GPIO_CONFIG(offset));
- mb();
- spin_unlock_irqrestore(&tlmm_lock, irq_flags);
- return 0;
+ if (input)
+ clr_gpio_bits(BIT(GPIO_OE_BIT), GPIO_CONFIG(gpio));
+ else {
+ __msm_gpio_set_inout(gpio, val);
+ set_gpio_bits(BIT(GPIO_OE_BIT), GPIO_CONFIG(gpio));
+ }
}
-static int msm_gpio_direction_output(struct gpio_chip *chip,
- unsigned offset,
- int val)
+void __msm_gpio_set_polarity(unsigned gpio, unsigned val)
{
- unsigned long irq_flags;
-
- spin_lock_irqsave(&tlmm_lock, irq_flags);
- msm_gpio_set(chip, offset, val);
- set_gpio_bits(BIT(GPIO_OE_BIT), GPIO_CONFIG(offset));
- mb();
- spin_unlock_irqrestore(&tlmm_lock, irq_flags);
- return 0;
-}
-
-#ifdef CONFIG_OF
-static int msm_gpio_to_irq(struct gpio_chip *chip, unsigned offset)
-{
- struct msm_gpio_dev *g_dev = to_msm_gpio_dev(chip);
- struct irq_domain *domain = &g_dev->domain;
- return domain->irq_base + (offset - chip->base);
-}
-
-static inline int msm_irq_to_gpio(struct gpio_chip *chip, unsigned irq)
-{
- struct msm_gpio_dev *g_dev = to_msm_gpio_dev(chip);
- struct irq_domain *domain = &g_dev->domain;
- return irq - domain->irq_base;
-}
-#else
-static int msm_gpio_to_irq(struct gpio_chip *chip, unsigned offset)
-{
- return MSM_GPIO_TO_INT(offset - chip->base);
-}
-
-static inline int msm_irq_to_gpio(struct gpio_chip *chip, unsigned irq)
-{
- return irq - MSM_GPIO_TO_INT(chip->base);
-}
-#endif
-
-static int msm_gpio_request(struct gpio_chip *chip, unsigned offset)
-{
- return msm_gpiomux_get(chip->base + offset);
-}
-
-static void msm_gpio_free(struct gpio_chip *chip, unsigned offset)
-{
- msm_gpiomux_put(chip->base + offset);
-}
-
-static struct msm_gpio_dev msm_gpio = {
- .gpio_chip = {
- .label = "msmgpio",
- .base = 0,
- .ngpio = NR_MSM_GPIOS,
- .direction_input = msm_gpio_direction_input,
- .direction_output = msm_gpio_direction_output,
- .get = msm_gpio_get,
- .set = msm_gpio_set,
- .to_irq = msm_gpio_to_irq,
- .request = msm_gpio_request,
- .free = msm_gpio_free,
- },
-};
-
-static void switch_mpm_config(struct irq_data *d, unsigned val)
-{
- /* switch the configuration in the mpm as well */
- if (!msm_gpio_irq_extn.irq_set_type)
- return;
-
if (val)
- msm_gpio_irq_extn.irq_set_type(d, IRQF_TRIGGER_FALLING);
+ clr_gpio_bits(INTR_POL_CTL_HI, GPIO_INTR_CFG(gpio));
else
- msm_gpio_irq_extn.irq_set_type(d, IRQF_TRIGGER_RISING);
+ set_gpio_bits(INTR_POL_CTL_HI, GPIO_INTR_CFG(gpio));
}
-/* For dual-edge interrupts in software, since the hardware has no
- * such support:
- *
- * At appropriate moments, this function may be called to flip the polarity
- * settings of both-edge irq lines to try and catch the next edge.
- *
- * The attempt is considered successful if:
- * - the status bit goes high, indicating that an edge was caught, or
- * - the input value of the gpio doesn't change during the attempt.
- * If the value changes twice during the process, that would cause the first
- * test to fail but would force the second, as two opposite
- * transitions would cause a detection no matter the polarity setting.
- *
- * The do-loop tries to sledge-hammer closed the timing hole between
- * the initial value-read and the polarity-write - if the line value changes
- * during that window, an interrupt is lost, the new polarity setting is
- * incorrect, and the first success test will fail, causing a retry.
- *
- * Algorithm comes from Google's msmgpio driver, see mach-msm/gpio.c.
- */
-static void msm_gpio_update_dual_edge_pos(struct irq_data *d, unsigned gpio)
+unsigned __msm_gpio_get_intr_status(unsigned gpio)
{
- int loop_limit = 100;
- unsigned val, val2, intstat;
-
- do {
- val = __raw_readl(GPIO_IN_OUT(gpio)) & BIT(GPIO_IN_BIT);
- if (val)
- clr_gpio_bits(INTR_POL_CTL_HI, GPIO_INTR_CFG(gpio));
- else
- set_gpio_bits(INTR_POL_CTL_HI, GPIO_INTR_CFG(gpio));
- val2 = __raw_readl(GPIO_IN_OUT(gpio)) & BIT(GPIO_IN_BIT);
- intstat = __raw_readl(GPIO_INTR_STATUS(gpio)) &
+ return __raw_readl(GPIO_INTR_STATUS(gpio)) &
BIT(INTR_STATUS_BIT);
- if (intstat || val == val2) {
- switch_mpm_config(d, val);
- return;
- }
- } while (loop_limit-- > 0);
- pr_err("%s: dual-edge irq failed to stabilize, "
- "interrupts dropped. %#08x != %#08x\n",
- __func__, val, val2);
}
-static void msm_gpio_irq_ack(struct irq_data *d)
+void __msm_gpio_set_intr_status(unsigned gpio)
{
- int gpio = msm_irq_to_gpio(&msm_gpio.gpio_chip, d->irq);
-
__raw_writel(BIT(INTR_STATUS_BIT), GPIO_INTR_STATUS(gpio));
- if (test_bit(gpio, msm_gpio.dual_edge_irqs))
- msm_gpio_update_dual_edge_pos(d, gpio);
- mb();
}
-static void __msm_gpio_irq_mask(unsigned int gpio)
+unsigned __msm_gpio_get_intr_config(unsigned gpio)
{
- __raw_writel(TARGET_PROC_NONE, GPIO_INTR_CFG_SU(gpio));
- clr_gpio_bits(INTR_RAW_STATUS_EN | INTR_ENABLE, GPIO_INTR_CFG(gpio));
+ return __raw_readl(GPIO_INTR_CFG(gpio));
}
-static void msm_gpio_irq_mask(struct irq_data *d)
+void __msm_gpio_set_intr_cfg_enable(unsigned gpio, unsigned val)
{
- int gpio = msm_irq_to_gpio(&msm_gpio.gpio_chip, d->irq);
- unsigned long irq_flags;
+ if (val) {
+ set_gpio_bits(INTR_RAW_STATUS_EN | INTR_ENABLE,
+ GPIO_INTR_CFG(gpio));
+ __raw_writel(TARGET_PROC_SCORPION, GPIO_INTR_CFG_SU(gpio));
- spin_lock_irqsave(&tlmm_lock, irq_flags);
- __msm_gpio_irq_mask(gpio);
- __clear_bit(gpio, msm_gpio.enabled_irqs);
- mb();
- spin_unlock_irqrestore(&tlmm_lock, irq_flags);
-
- if (msm_gpio_irq_extn.irq_mask)
- msm_gpio_irq_extn.irq_mask(d);
-
-}
-
-static void __msm_gpio_irq_unmask(unsigned int gpio)
-{
- set_gpio_bits(INTR_RAW_STATUS_EN | INTR_ENABLE, GPIO_INTR_CFG(gpio));
- __raw_writel(TARGET_PROC_SCORPION, GPIO_INTR_CFG_SU(gpio));
-}
-
-static void msm_gpio_irq_unmask(struct irq_data *d)
-{
- int gpio = msm_irq_to_gpio(&msm_gpio.gpio_chip, d->irq);
- unsigned long irq_flags;
-
- spin_lock_irqsave(&tlmm_lock, irq_flags);
- __set_bit(gpio, msm_gpio.enabled_irqs);
- __msm_gpio_irq_unmask(gpio);
- mb();
- spin_unlock_irqrestore(&tlmm_lock, irq_flags);
-
- if (msm_gpio_irq_extn.irq_mask)
- msm_gpio_irq_extn.irq_unmask(d);
-}
-
-static void msm_gpio_irq_disable(struct irq_data *d)
-{
- if (msm_gpio_irq_extn.irq_disable)
- msm_gpio_irq_extn.irq_disable(d);
-}
-
-static int msm_gpio_irq_set_type(struct irq_data *d, unsigned int flow_type)
-{
- int gpio = msm_irq_to_gpio(&msm_gpio.gpio_chip, d->irq);
- unsigned long irq_flags;
- uint32_t bits;
-
- spin_lock_irqsave(&tlmm_lock, irq_flags);
-
- bits = __raw_readl(GPIO_INTR_CFG(gpio));
-
- if (flow_type & IRQ_TYPE_EDGE_BOTH) {
- bits |= INTR_DECT_CTL_EDGE;
- __irq_set_handler_locked(d->irq, handle_edge_irq);
- if ((flow_type & IRQ_TYPE_EDGE_BOTH) == IRQ_TYPE_EDGE_BOTH)
- __set_bit(gpio, msm_gpio.dual_edge_irqs);
- else
- __clear_bit(gpio, msm_gpio.dual_edge_irqs);
} else {
- bits &= ~INTR_DECT_CTL_EDGE;
- __irq_set_handler_locked(d->irq, handle_level_irq);
- __clear_bit(gpio, msm_gpio.dual_edge_irqs);
+ __raw_writel(TARGET_PROC_NONE, GPIO_INTR_CFG_SU(gpio));
+ clr_gpio_bits(INTR_RAW_STATUS_EN | INTR_ENABLE,
+ GPIO_INTR_CFG(gpio));
}
+}
- if (flow_type & (IRQ_TYPE_EDGE_RISING | IRQ_TYPE_LEVEL_HIGH))
- bits |= INTR_POL_CTL_HI;
+void __msm_gpio_set_intr_cfg_type(unsigned gpio, unsigned type)
+{
+ unsigned cfg;
+
+ cfg = __msm_gpio_get_intr_config(gpio);
+ if (type & IRQ_TYPE_EDGE_BOTH)
+ cfg |= INTR_DECT_CTL_EDGE;
else
- bits &= ~INTR_POL_CTL_HI;
+ cfg &= ~INTR_DECT_CTL_EDGE;
- __raw_writel(bits, GPIO_INTR_CFG(gpio));
+ if (type & (IRQ_TYPE_EDGE_RISING | IRQ_TYPE_LEVEL_HIGH))
+ cfg |= INTR_POL_CTL_HI;
+ else
+ cfg &= ~INTR_POL_CTL_HI;
- if ((flow_type & IRQ_TYPE_EDGE_BOTH) == IRQ_TYPE_EDGE_BOTH)
- msm_gpio_update_dual_edge_pos(d, gpio);
-
- mb();
- spin_unlock_irqrestore(&tlmm_lock, irq_flags);
-
- if (msm_gpio_irq_extn.irq_set_type)
- msm_gpio_irq_extn.irq_set_type(d, flow_type);
-
- return 0;
+ __raw_writel(cfg, GPIO_INTR_CFG(gpio));
}
-/*
- * When the summary IRQ is raised, any number of GPIO lines may be high.
- * It is the job of the summary handler to find all those GPIO lines
- * which have been set as summary IRQ lines and which are triggered,
- * and to call their interrupt handlers.
- */
-static irqreturn_t msm_summary_irq_handler(int irq, void *data)
-{
- unsigned long i;
- struct irq_desc *desc = irq_to_desc(irq);
- struct irq_chip *chip = irq_desc_get_chip(desc);
-
- chained_irq_enter(chip, desc);
-
- for (i = find_first_bit(msm_gpio.enabled_irqs, NR_MSM_GPIOS);
- i < NR_MSM_GPIOS;
- i = find_next_bit(msm_gpio.enabled_irqs, NR_MSM_GPIOS, i + 1)) {
- if (__raw_readl(GPIO_INTR_STATUS(i)) & BIT(INTR_STATUS_BIT))
- generic_handle_irq(msm_gpio_to_irq(&msm_gpio.gpio_chip,
- i));
- }
-
- chained_irq_exit(chip, desc);
- return IRQ_HANDLED;
-}
-
-static int msm_gpio_irq_set_wake(struct irq_data *d, unsigned int on)
-{
- int gpio = msm_irq_to_gpio(&msm_gpio.gpio_chip, d->irq);
-
- if (on) {
- if (bitmap_empty(msm_gpio.wake_irqs, NR_MSM_GPIOS))
- irq_set_irq_wake(TLMM_MSM_SUMMARY_IRQ, 1);
- set_bit(gpio, msm_gpio.wake_irqs);
- } else {
- clear_bit(gpio, msm_gpio.wake_irqs);
- if (bitmap_empty(msm_gpio.wake_irqs, NR_MSM_GPIOS))
- irq_set_irq_wake(TLMM_MSM_SUMMARY_IRQ, 0);
- }
-
- if (msm_gpio_irq_extn.irq_set_wake)
- msm_gpio_irq_extn.irq_set_wake(d, on);
-
- return 0;
-}
-
-static struct irq_chip msm_gpio_irq_chip = {
- .name = "msmgpio",
- .irq_mask = msm_gpio_irq_mask,
- .irq_unmask = msm_gpio_irq_unmask,
- .irq_ack = msm_gpio_irq_ack,
- .irq_set_type = msm_gpio_irq_set_type,
- .irq_set_wake = msm_gpio_irq_set_wake,
- .irq_disable = msm_gpio_irq_disable,
-};
-
-/*
- * This lock class tells lockdep that GPIO irqs are in a different
- * category than their parent, so it won't report false recursion.
- */
-static struct lock_class_key msm_gpio_lock_class;
-
-static int __devinit msm_gpio_probe(void)
-{
- int i, irq, ret;
-
- spin_lock_init(&tlmm_lock);
- bitmap_zero(msm_gpio.enabled_irqs, NR_MSM_GPIOS);
- bitmap_zero(msm_gpio.wake_irqs, NR_MSM_GPIOS);
- bitmap_zero(msm_gpio.dual_edge_irqs, NR_MSM_GPIOS);
- ret = gpiochip_add(&msm_gpio.gpio_chip);
- if (ret < 0)
- return ret;
-
- for (i = 0; i < msm_gpio.gpio_chip.ngpio; ++i) {
- irq = msm_gpio_to_irq(&msm_gpio.gpio_chip, i);
- irq_set_lockdep_class(irq, &msm_gpio_lock_class);
- irq_set_chip_and_handler(irq, &msm_gpio_irq_chip,
- handle_level_irq);
- set_irq_flags(irq, IRQF_VALID);
- }
-
- ret = request_irq(TLMM_MSM_SUMMARY_IRQ, msm_summary_irq_handler,
- IRQF_TRIGGER_HIGH, "msmgpio", NULL);
- if (ret) {
- pr_err("Request_irq failed for TLMM_MSM_SUMMARY_IRQ - %d\n",
- ret);
- return ret;
- }
- return 0;
-}
-
-static int __devexit msm_gpio_remove(void)
-{
- int ret = gpiochip_remove(&msm_gpio.gpio_chip);
-
- if (ret < 0)
- return ret;
-
- irq_set_handler(TLMM_MSM_SUMMARY_IRQ, NULL);
-
- return 0;
-}
-
-#ifdef CONFIG_PM
-static int msm_gpio_suspend(void)
-{
- unsigned long irq_flags;
- unsigned long i;
-
- spin_lock_irqsave(&tlmm_lock, irq_flags);
- for_each_set_bit(i, msm_gpio.enabled_irqs, NR_MSM_GPIOS)
- __msm_gpio_irq_mask(i);
-
- for_each_set_bit(i, msm_gpio.wake_irqs, NR_MSM_GPIOS)
- __msm_gpio_irq_unmask(i);
- mb();
- spin_unlock_irqrestore(&tlmm_lock, irq_flags);
- return 0;
-}
-
-extern int msm_show_resume_irq_mask;
-
-void msm_gpio_show_resume_irq(void)
-{
- unsigned long irq_flags;
- int i, irq, intstat;
-
- if (!msm_show_resume_irq_mask)
- return;
-
- spin_lock_irqsave(&tlmm_lock, irq_flags);
- for_each_set_bit(i, msm_gpio.wake_irqs, NR_MSM_GPIOS) {
- intstat = __raw_readl(GPIO_INTR_STATUS(i)) &
- BIT(INTR_STATUS_BIT);
- if (intstat) {
- irq = msm_gpio_to_irq(&msm_gpio.gpio_chip, i);
- pr_warning("%s: %d triggered\n",
- __func__, irq);
- }
- }
- spin_unlock_irqrestore(&tlmm_lock, irq_flags);
-}
-
-static void msm_gpio_resume(void)
-{
- unsigned long irq_flags;
- unsigned long i;
-
- msm_gpio_show_resume_irq();
-
- spin_lock_irqsave(&tlmm_lock, irq_flags);
- for_each_set_bit(i, msm_gpio.wake_irqs, NR_MSM_GPIOS)
- __msm_gpio_irq_mask(i);
-
- for_each_set_bit(i, msm_gpio.enabled_irqs, NR_MSM_GPIOS)
- __msm_gpio_irq_unmask(i);
- mb();
- spin_unlock_irqrestore(&tlmm_lock, irq_flags);
-}
-#else
-#define msm_gpio_suspend NULL
-#define msm_gpio_resume NULL
-#endif
-
-static struct syscore_ops msm_gpio_syscore_ops = {
- .suspend = msm_gpio_suspend,
- .resume = msm_gpio_resume,
-};
-
-static int __init msm_gpio_init(void)
-{
- msm_gpio_probe();
- register_syscore_ops(&msm_gpio_syscore_ops);
- return 0;
-}
-
-static void __exit msm_gpio_exit(void)
-{
- unregister_syscore_ops(&msm_gpio_syscore_ops);
- msm_gpio_remove();
-}
-
-postcore_initcall(msm_gpio_init);
-module_exit(msm_gpio_exit);
-
-static void msm_tlmm_set_field(const struct tlmm_field_cfg *configs,
- unsigned id, unsigned width, unsigned val)
-{
- unsigned long irqflags;
- u32 mask = (1 << width) - 1;
- u32 __iomem *reg = MSM_TLMM_BASE + configs[id].reg;
- u32 reg_val;
-
- spin_lock_irqsave(&tlmm_lock, irqflags);
- reg_val = __raw_readl(reg);
- reg_val &= ~(mask << configs[id].off);
- reg_val |= (val & mask) << configs[id].off;
- __raw_writel(reg_val, reg);
- mb();
- spin_unlock_irqrestore(&tlmm_lock, irqflags);
-}
-
-void msm_tlmm_set_hdrive(enum msm_tlmm_hdrive_tgt tgt, int drv_str)
-{
- msm_tlmm_set_field(tlmm_hdrv_cfgs, tgt, 3, drv_str);
-}
-EXPORT_SYMBOL(msm_tlmm_set_hdrive);
-
-void msm_tlmm_set_pull(enum msm_tlmm_pull_tgt tgt, int pull)
-{
- msm_tlmm_set_field(tlmm_pull_cfgs, tgt, 2, pull);
-}
-EXPORT_SYMBOL(msm_tlmm_set_pull);
-
-int gpio_tlmm_config(unsigned config, unsigned disable)
+void __gpio_tlmm_config(unsigned config)
{
uint32_t flags;
unsigned gpio = GPIO_PIN(config);
- if (gpio > NR_MSM_GPIOS)
- return -EINVAL;
-
flags = ((GPIO_DIR(config) << 9) & (0x1 << 9)) |
((GPIO_DRVSTR(config) << 6) & (0x7 << 6)) |
((GPIO_FUNC(config) << 2) & (0xf << 2)) |
((GPIO_PULL(config) & 0x3));
__raw_writel(flags, GPIO_CONFIG(gpio));
- mb();
-
- return 0;
}
-EXPORT_SYMBOL(gpio_tlmm_config);
-int msm_gpio_install_direct_irq(unsigned gpio, unsigned irq,
+void __msm_gpio_install_direct_irq(unsigned gpio, unsigned irq,
unsigned int input_polarity)
{
- unsigned long irq_flags;
uint32_t bits;
- if (gpio >= NR_MSM_GPIOS || irq >= NR_TLMM_MSM_DIR_CONN_IRQ)
- return -EINVAL;
-
- spin_lock_irqsave(&tlmm_lock, irq_flags);
-
__raw_writel(__raw_readl(GPIO_CONFIG(gpio)) | BIT(GPIO_OE_BIT),
GPIO_CONFIG(gpio));
__raw_writel(__raw_readl(GPIO_INTR_CFG(gpio)) &
@@ -692,66 +205,4 @@
if (input_polarity)
bits |= DC_POLARITY_HI;
__raw_writel(bits, DIR_CONN_INTR_CFG_SU(irq));
-
- mb();
- spin_unlock_irqrestore(&tlmm_lock, irq_flags);
-
- return 0;
}
-EXPORT_SYMBOL(msm_gpio_install_direct_irq);
-
-#ifdef CONFIG_OF
-static int msm_gpio_domain_dt_translate(struct irq_domain *d,
- struct device_node *controller,
- const u32 *intspec,
- unsigned int intsize,
- unsigned long *out_hwirq,
- unsigned int *out_type)
-{
- if (d->of_node != controller)
- return -EINVAL;
- if (intsize != 2)
- return -EINVAL;
-
- /* hwirq value */
- *out_hwirq = intspec[0];
-
- /* irq flags */
- *out_type = intspec[1] & IRQ_TYPE_SENSE_MASK;
- return 0;
-}
-
-static struct irq_domain_ops msm_gpio_irq_domain_ops = {
- .dt_translate = msm_gpio_domain_dt_translate,
-};
-
-int __init msm_gpio_of_init(struct device_node *node,
- struct device_node *parent)
-{
- struct irq_domain *domain = &msm_gpio.domain;
- int start;
-
- start = irq_domain_find_free_range(0, NR_MSM_GPIOS);
- domain->irq_base = irq_alloc_descs(start, 0, NR_MSM_GPIOS,
- numa_node_id());
- if (IS_ERR_VALUE(domain->irq_base)) {
- WARN(1, "Cannot allocate irq_descs @ IRQ%d\n", start);
- return domain->irq_base;
- }
-
- domain->irq_base = irq_domain_find_free_range(0, NR_MSM_GPIOS);
- domain->nr_irq = NR_MSM_GPIOS;
- domain->of_node = of_node_get(node);
- domain->priv = &msm_gpio;
- domain->ops = &msm_gpio_irq_domain_ops;
- irq_domain_add(domain);
- pr_debug("%s: irq_base = %u\n", __func__, domain->irq_base);
-
- return 0;
-}
-#endif
-
-MODULE_AUTHOR("Gregory Bean <gbean@codeaurora.org>");
-MODULE_DESCRIPTION("Driver for Qualcomm MSM TLMMv2 SoC GPIOs");
-MODULE_LICENSE("GPL v2");
-MODULE_ALIAS("sysdev:msmgpio");
diff --git a/drivers/gpio/gpio-msm-v3.c b/drivers/gpio/gpio-msm-v3.c
new file mode 100644
index 0000000..49ad517
--- /dev/null
+++ b/drivers/gpio/gpio-msm-v3.c
@@ -0,0 +1,217 @@
+/* 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/bitmap.h>
+#include <linux/bitops.h>
+#include <linux/gpio.h>
+#include <linux/init.h>
+#include <linux/io.h>
+#include <linux/irq.h>
+
+#include <mach/msm_iomap.h>
+#include <mach/gpiomux.h>
+#include "gpio-msm-common.h"
+
+/* Bits of interest in the GPIO_IN_OUT register.
+ */
+enum {
+ GPIO_IN_BIT = 0,
+ GPIO_OUT_BIT = 1
+};
+
+/* Bits of interest in the GPIO_INTR_STATUS register.
+ */
+enum {
+ INTR_STATUS_BIT = 0,
+};
+
+/* Bits of interest in the GPIO_CFG register.
+ */
+enum {
+ GPIO_OE_BIT = 9,
+};
+
+/* Bits of interest in the GPIO_INTR_CFG register.
+ */
+enum {
+ INTR_ENABLE_BIT = 0,
+ INTR_POL_CTL_BIT = 1,
+ INTR_DECT_CTL_BIT = 2,
+ INTR_RAW_STATUS_EN_BIT = 4,
+ INTR_TARGET_PROC_BIT = 5,
+ INTR_DIR_CONN_EN_BIT = 8,
+};
+
+/*
+ * There is no 'DC_POLARITY_LO' because the GIC is incapable
+ * of asserting on falling edge or level-low conditions. Even though
+ * the registers allow for low-polarity inputs, the case can never arise.
+ */
+enum {
+ DC_GPIO_SEL_BIT = 0,
+ DC_POLARITY_BIT = 8,
+};
+
+/*
+ * When a GPIO triggers, two separate decisions are made, controlled
+ * by two separate flags.
+ *
+ * - First, INTR_RAW_STATUS_EN controls whether or not the GPIO_INTR_STATUS
+ * register for that GPIO will be updated to reflect the triggering of that
+ * gpio. If this bit is 0, this register will not be updated.
+ * - Second, INTR_ENABLE controls whether an interrupt is triggered.
+ *
+ * If INTR_ENABLE is set and INTR_RAW_STATUS_EN is NOT set, an interrupt
+ * can be triggered but the status register will not reflect it.
+ */
+#define INTR_RAW_STATUS_EN BIT(INTR_RAW_STATUS_EN_BIT)
+#define INTR_ENABLE BIT(INTR_ENABLE_BIT)
+#define INTR_POL_CTL_HI BIT(INTR_POL_CTL_BIT)
+#define INTR_DIR_CONN_EN BIT(INTR_DIR_CONN_EN_BIT)
+#define DC_POLARITY_HI BIT(DC_POLARITY_BIT)
+
+#define INTR_TARGET_PROC_APPS (4 << INTR_TARGET_PROC_BIT)
+#define INTR_TARGET_PROC_NONE (7 << INTR_TARGET_PROC_BIT)
+
+#define INTR_DECT_CTL_LEVEL (0 << INTR_DECT_CTL_BIT)
+#define INTR_DECT_CTL_POS_EDGE (1 << INTR_DECT_CTL_BIT)
+#define INTR_DECT_CTL_NEG_EDGE (2 << INTR_DECT_CTL_BIT)
+#define INTR_DECT_CTL_DUAL_EDGE (3 << INTR_DECT_CTL_BIT)
+#define INTR_DECT_CTL_MASK (3 << INTR_DECT_CTL_BIT)
+
+#define GPIO_CONFIG(gpio) (MSM_TLMM_BASE + 0x1000 + (0x10 * (gpio)))
+#define GPIO_IN_OUT(gpio) (MSM_TLMM_BASE + 0x1004 + (0x10 * (gpio)))
+#define GPIO_INTR_CFG(gpio) (MSM_TLMM_BASE + 0x1008 + (0x10 * (gpio)))
+#define GPIO_INTR_STATUS(gpio) (MSM_TLMM_BASE + 0x100c + (0x10 * (gpio)))
+#define GPIO_DIR_CONN_INTR(intr) (MSM_TLMM_BASE + 0x2800 + (0x04 * (intr)))
+
+static inline void set_gpio_bits(unsigned n, void __iomem *reg)
+{
+ __raw_writel(__raw_readl(reg) | n, reg);
+}
+
+static inline void clr_gpio_bits(unsigned n, void __iomem *reg)
+{
+ __raw_writel(__raw_readl(reg) & ~n, reg);
+}
+
+unsigned __msm_gpio_get_inout(unsigned gpio)
+{
+ return __raw_readl(GPIO_IN_OUT(gpio)) & BIT(GPIO_IN_BIT);
+}
+
+void __msm_gpio_set_inout(unsigned gpio, unsigned val)
+{
+ __raw_writel(val ? BIT(GPIO_OUT_BIT) : 0, GPIO_IN_OUT(gpio));
+}
+
+void __msm_gpio_set_config_direction(unsigned gpio, int input, int val)
+{
+ if (input) {
+ clr_gpio_bits(BIT(GPIO_OE_BIT), GPIO_CONFIG(gpio));
+ } else {
+ __msm_gpio_set_inout(gpio, val);
+ set_gpio_bits(BIT(GPIO_OE_BIT), GPIO_CONFIG(gpio));
+ }
+}
+
+void __msm_gpio_set_polarity(unsigned gpio, unsigned val)
+{
+ if (val)
+ clr_gpio_bits(INTR_POL_CTL_HI, GPIO_INTR_CFG(gpio));
+ else
+ set_gpio_bits(INTR_POL_CTL_HI, GPIO_INTR_CFG(gpio));
+}
+
+unsigned __msm_gpio_get_intr_status(unsigned gpio)
+{
+ return __raw_readl(GPIO_INTR_STATUS(gpio)) &
+ BIT(INTR_STATUS_BIT);
+}
+
+void __msm_gpio_set_intr_status(unsigned gpio)
+{
+ __raw_writel(BIT(INTR_STATUS_BIT), GPIO_INTR_STATUS(gpio));
+}
+
+unsigned __msm_gpio_get_intr_config(unsigned gpio)
+{
+ return __raw_readl(GPIO_INTR_CFG(gpio));
+}
+
+void __msm_gpio_set_intr_cfg_enable(unsigned gpio, unsigned val)
+{
+ unsigned cfg;
+
+ cfg = __raw_readl(GPIO_INTR_CFG(gpio));
+ if (val) {
+ cfg &= ~(INTR_TARGET_PROC_NONE | INTR_DIR_CONN_EN);
+ cfg |= INTR_RAW_STATUS_EN | INTR_ENABLE | INTR_TARGET_PROC_APPS;
+ } else {
+ cfg &= ~(INTR_TARGET_PROC_APPS | INTR_RAW_STATUS_EN |
+ INTR_ENABLE);
+ cfg |= INTR_TARGET_PROC_NONE;
+ }
+ __raw_writel(cfg, GPIO_INTR_CFG(gpio));
+}
+
+void __msm_gpio_set_intr_cfg_type(unsigned gpio, unsigned type)
+{
+ unsigned cfg;
+
+ cfg = __raw_readl(GPIO_INTR_CFG(gpio));
+ cfg &= ~INTR_DECT_CTL_MASK;
+ if (type == IRQ_TYPE_EDGE_RISING)
+ cfg |= INTR_DECT_CTL_POS_EDGE;
+ else if (type == IRQ_TYPE_EDGE_FALLING)
+ cfg |= INTR_DECT_CTL_NEG_EDGE;
+ else if (type == IRQ_TYPE_EDGE_BOTH)
+ cfg |= INTR_DECT_CTL_DUAL_EDGE;
+ else
+ cfg |= INTR_DECT_CTL_LEVEL;
+
+ if (type & (IRQ_TYPE_EDGE_RISING | IRQ_TYPE_LEVEL_HIGH))
+ cfg |= INTR_POL_CTL_HI;
+ else
+ cfg &= ~INTR_POL_CTL_HI;
+
+ __raw_writel(cfg, GPIO_INTR_CFG(gpio));
+}
+
+void __gpio_tlmm_config(unsigned config)
+{
+ unsigned flags;
+ unsigned gpio = GPIO_PIN(config);
+
+ flags = ((GPIO_DIR(config) << 9) & (0x1 << 9)) |
+ ((GPIO_DRVSTR(config) << 6) & (0x7 << 6)) |
+ ((GPIO_FUNC(config) << 2) & (0xf << 2)) |
+ ((GPIO_PULL(config) & 0x3));
+ __raw_writel(flags, GPIO_CONFIG(gpio));
+}
+
+void __msm_gpio_install_direct_irq(unsigned gpio, unsigned irq,
+ unsigned int input_polarity)
+{
+ unsigned cfg;
+
+ set_gpio_bits(BIT(GPIO_OE_BIT), GPIO_CONFIG(gpio));
+ cfg = __raw_readl(GPIO_INTR_CFG(gpio));
+ cfg &= ~(INTR_TARGET_PROC_NONE | INTR_RAW_STATUS_EN | INTR_ENABLE);
+ cfg |= INTR_TARGET_PROC_APPS | INTR_DIR_CONN_EN;
+ __raw_writel(cfg, GPIO_INTR_CFG(gpio));
+
+ cfg = gpio;
+ if (input_polarity)
+ cfg |= DC_POLARITY_HI;
+ __raw_writel(cfg, GPIO_DIR_CONN_INTR(irq));
+}
diff --git a/drivers/media/video/msm/sensors/s5k3l1yx.c b/drivers/media/video/msm/sensors/s5k3l1yx.c
index debda88..1d7da0d 100644
--- a/drivers/media/video/msm/sensors/s5k3l1yx.c
+++ b/drivers/media/video/msm/sensors/s5k3l1yx.c
@@ -80,7 +80,7 @@
{0x0202, 0x06}, /* coarse_integration_time */
{0x0203, 0x00}, /* coarse_integration_time */
{0x0340, 0x09}, /* frame_length_lines */
- {0x0341, 0x98}, /* frame_length_lines */
+ {0x0341, 0x6C}, /* frame_length_lines */
{0x0342, 0x11}, /* line_length_pck */
{0x0343, 0x80}, /* line_length_pck */
{0x0344, 0x00}, /* x_addr_start */
@@ -489,7 +489,7 @@
.x_output = 1984,
.y_output = 1508,
.line_length_pclk = 4480,
- .frame_length_lines = 2456,
+ .frame_length_lines = 2412,
.vt_pixel_clk = 330000000,
.op_pixel_clk = 320000000,
.binning_factor = 1,
diff --git a/drivers/mmc/card/block.c b/drivers/mmc/card/block.c
index 990faeb..5e0d669 100644
--- a/drivers/mmc/card/block.c
+++ b/drivers/mmc/card/block.c
@@ -918,9 +918,7 @@
goto retry;
if (!err)
mmc_blk_reset_success(md, type);
- spin_lock_irq(&md->lock);
- __blk_end_request(req, err, blk_rq_bytes(req));
- spin_unlock_irq(&md->lock);
+ blk_end_request(req, err, blk_rq_bytes(req));
return err ? 0 : 1;
}
@@ -989,9 +987,7 @@
if (!err)
mmc_blk_reset_success(md, type);
out:
- spin_lock_irq(&md->lock);
- __blk_end_request(req, err, blk_rq_bytes(req));
- spin_unlock_irq(&md->lock);
+ blk_end_request(req, err, blk_rq_bytes(req));
return err ? 0 : 1;
}
@@ -1030,9 +1026,7 @@
__func__);
out:
- spin_lock_irq(&md->lock);
- __blk_end_request(req, err, blk_rq_bytes(req));
- spin_unlock_irq(&md->lock);
+ blk_end_request(req, err, blk_rq_bytes(req));
return err ? 0 : 1;
}
@@ -1047,9 +1041,7 @@
if (ret)
ret = -EIO;
- spin_lock_irq(&md->lock);
- __blk_end_request_all(req, ret);
- spin_unlock_irq(&md->lock);
+ blk_end_request_all(req, ret);
return ret ? 0 : 1;
}
@@ -1672,15 +1664,11 @@
blocks = mmc_sd_num_wr_blocks(card);
if (blocks != (u32)-1) {
- spin_lock_irq(&md->lock);
- ret = __blk_end_request(req, 0, blocks << 9);
- spin_unlock_irq(&md->lock);
+ ret = blk_end_request(req, 0, blocks << 9);
}
} else {
if (mq_rq->packed_cmd == MMC_PACKED_NONE) {
- spin_lock_irq(&md->lock);
- ret = __blk_end_request(req, 0, brq->data.bytes_xfered);
- spin_unlock_irq(&md->lock);
+ ret = blk_end_request(req, 0, brq->data.bytes_xfered);
}
}
return ret;
@@ -1689,7 +1677,6 @@
static int mmc_blk_end_packed_req(struct mmc_queue *mq,
struct mmc_queue_req *mq_rq)
{
- struct mmc_blk_data *md = mq->data;
struct request *prq;
int idx = mq_rq->packed_fail_idx, i = 0;
int ret = 0;
@@ -1709,9 +1696,7 @@
return ret;
}
list_del_init(&prq->queuelist);
- spin_lock_irq(&md->lock);
- __blk_end_request(prq, 0, blk_rq_bytes(prq));
- spin_unlock_irq(&md->lock);
+ blk_end_request(prq, 0, blk_rq_bytes(prq));
i++;
}
@@ -1777,10 +1762,8 @@
ret = mmc_blk_end_packed_req(mq, mq_rq);
break;
} else {
- spin_lock_irq(&md->lock);
- ret = __blk_end_request(req, 0,
+ ret = blk_end_request(req, 0,
brq->data.bytes_xfered);
- spin_unlock_irq(&md->lock);
}
/*
@@ -1833,10 +1816,8 @@
* time, so we only reach here after trying to
* read a single sector.
*/
- spin_lock_irq(&md->lock);
- ret = __blk_end_request(req, -EIO,
+ ret = blk_end_request(req, -EIO,
brq->data.blksz);
- spin_unlock_irq(&md->lock);
if (!ret)
goto start_new_req;
break;
@@ -1866,20 +1847,16 @@
cmd_abort:
if (mq_rq->packed_cmd == MMC_PACKED_NONE) {
- spin_lock_irq(&md->lock);
if (mmc_card_removed(card))
req->cmd_flags |= REQ_QUIET;
while (ret)
- ret = __blk_end_request(req, -EIO,
+ ret = blk_end_request(req, -EIO,
blk_rq_cur_bytes(req));
- spin_unlock_irq(&md->lock);
} else {
while (!list_empty(&mq_rq->packed_list)) {
prq = list_entry_rq(mq_rq->packed_list.next);
list_del_init(&prq->queuelist);
- spin_lock_irq(&md->lock);
- __blk_end_request(prq, -EIO, blk_rq_bytes(prq));
- spin_unlock_irq(&md->lock);
+ blk_end_request(prq, -EIO, blk_rq_bytes(prq));
}
mmc_blk_clear_packed(mq_rq);
}
@@ -1932,9 +1909,7 @@
ret = mmc_blk_part_switch(card, md);
if (ret) {
if (req) {
- spin_lock_irq(&md->lock);
- __blk_end_request_all(req, -EIO);
- spin_unlock_irq(&md->lock);
+ blk_end_request_all(req, -EIO);
}
ret = 0;
goto out;
diff --git a/drivers/mmc/core/mmc.c b/drivers/mmc/core/mmc.c
index 3438bc91..a21b39d 100644
--- a/drivers/mmc/core/mmc.c
+++ b/drivers/mmc/core/mmc.c
@@ -235,6 +235,36 @@
return err;
}
+static void mmc_select_card_type(struct mmc_card *card)
+{
+ struct mmc_host *host = card->host;
+ u8 card_type = card->ext_csd.raw_card_type & EXT_CSD_CARD_TYPE_MASK;
+ unsigned int caps = host->caps, caps2 = host->caps2;
+ unsigned int hs_max_dtr = 0;
+
+ if (card_type & EXT_CSD_CARD_TYPE_26)
+ hs_max_dtr = MMC_HIGH_26_MAX_DTR;
+
+ if (caps & MMC_CAP_MMC_HIGHSPEED &&
+ card_type & EXT_CSD_CARD_TYPE_52)
+ hs_max_dtr = MMC_HIGH_52_MAX_DTR;
+
+ if ((caps & MMC_CAP_1_8V_DDR &&
+ card_type & EXT_CSD_CARD_TYPE_DDR_1_8V) ||
+ (caps & MMC_CAP_1_2V_DDR &&
+ card_type & EXT_CSD_CARD_TYPE_DDR_1_2V))
+ hs_max_dtr = MMC_HIGH_DDR_MAX_DTR;
+
+ if ((caps2 & MMC_CAP2_HS200_1_8V_SDR &&
+ card_type & EXT_CSD_CARD_TYPE_SDR_1_8V) ||
+ (caps2 & MMC_CAP2_HS200_1_2V_SDR &&
+ card_type & EXT_CSD_CARD_TYPE_SDR_1_2V))
+ hs_max_dtr = MMC_HS200_MAX_DTR;
+
+ card->ext_csd.hs_max_dtr = hs_max_dtr;
+ card->ext_csd.card_type = card_type;
+}
+
/*
* Decode extended CSD.
*/
@@ -284,56 +314,9 @@
if (card->ext_csd.sectors > (2u * 1024 * 1024 * 1024) / 512)
mmc_card_set_blockaddr(card);
}
+
card->ext_csd.raw_card_type = ext_csd[EXT_CSD_CARD_TYPE];
- switch (ext_csd[EXT_CSD_CARD_TYPE] & EXT_CSD_CARD_TYPE_MASK) {
- case EXT_CSD_CARD_TYPE_SDR_ALL:
- case EXT_CSD_CARD_TYPE_SDR_ALL_DDR_1_8V:
- case EXT_CSD_CARD_TYPE_SDR_ALL_DDR_1_2V:
- case EXT_CSD_CARD_TYPE_SDR_ALL_DDR_52:
- card->ext_csd.hs_max_dtr = 200000000;
- card->ext_csd.card_type = EXT_CSD_CARD_TYPE_SDR_200;
- break;
- case EXT_CSD_CARD_TYPE_SDR_1_2V_ALL:
- case EXT_CSD_CARD_TYPE_SDR_1_2V_DDR_1_8V:
- case EXT_CSD_CARD_TYPE_SDR_1_2V_DDR_1_2V:
- case EXT_CSD_CARD_TYPE_SDR_1_2V_DDR_52:
- card->ext_csd.hs_max_dtr = 200000000;
- card->ext_csd.card_type = EXT_CSD_CARD_TYPE_SDR_1_2V;
- break;
- case EXT_CSD_CARD_TYPE_SDR_1_8V_ALL:
- case EXT_CSD_CARD_TYPE_SDR_1_8V_DDR_1_8V:
- case EXT_CSD_CARD_TYPE_SDR_1_8V_DDR_1_2V:
- case EXT_CSD_CARD_TYPE_SDR_1_8V_DDR_52:
- card->ext_csd.hs_max_dtr = 200000000;
- card->ext_csd.card_type = EXT_CSD_CARD_TYPE_SDR_1_8V;
- break;
- case EXT_CSD_CARD_TYPE_DDR_52 | EXT_CSD_CARD_TYPE_52 |
- EXT_CSD_CARD_TYPE_26:
- card->ext_csd.hs_max_dtr = 52000000;
- card->ext_csd.card_type = EXT_CSD_CARD_TYPE_DDR_52;
- break;
- case EXT_CSD_CARD_TYPE_DDR_1_2V | EXT_CSD_CARD_TYPE_52 |
- EXT_CSD_CARD_TYPE_26:
- card->ext_csd.hs_max_dtr = 52000000;
- card->ext_csd.card_type = EXT_CSD_CARD_TYPE_DDR_1_2V;
- break;
- case EXT_CSD_CARD_TYPE_DDR_1_8V | EXT_CSD_CARD_TYPE_52 |
- EXT_CSD_CARD_TYPE_26:
- card->ext_csd.hs_max_dtr = 52000000;
- card->ext_csd.card_type = EXT_CSD_CARD_TYPE_DDR_1_8V;
- break;
- case EXT_CSD_CARD_TYPE_52 | EXT_CSD_CARD_TYPE_26:
- card->ext_csd.hs_max_dtr = 52000000;
- break;
- case EXT_CSD_CARD_TYPE_26:
- card->ext_csd.hs_max_dtr = 26000000;
- break;
- default:
- /* MMC v4 spec says this cannot happen */
- pr_warning("%s: card is mmc v4 but doesn't "
- "support any high-speed modes.\n",
- mmc_hostname(card->host));
- }
+ mmc_select_card_type(card);
card->ext_csd.raw_s_a_timeout = ext_csd[EXT_CSD_S_A_TIMEOUT];
card->ext_csd.raw_erase_timeout_mult =
diff --git a/drivers/mmc/host/msm_sdcc.c b/drivers/mmc/host/msm_sdcc.c
index ac8b164..02d1581 100644
--- a/drivers/mmc/host/msm_sdcc.c
+++ b/drivers/mmc/host/msm_sdcc.c
@@ -2136,7 +2136,7 @@
{
int rc = 0;
struct msm_mmc_slot_reg_data *curr_slot;
- struct msm_mmc_reg_data *curr_vdd_reg, *curr_vccq_reg, *curr_vddp_reg;
+ struct msm_mmc_reg_data *curr_vdd_reg, *curr_vdd_io_reg;
struct device *dev = mmc_dev(host->mmc);
curr_slot = host->plat->vreg_data;
@@ -2144,8 +2144,7 @@
goto out;
curr_vdd_reg = curr_slot->vdd_data;
- curr_vccq_reg = curr_slot->vccq_data;
- curr_vddp_reg = curr_slot->vddp_data;
+ curr_vdd_io_reg = curr_slot->vdd_io_data;
if (is_init) {
/*
@@ -2157,16 +2156,11 @@
if (rc)
goto out;
}
- if (curr_vccq_reg) {
- rc = msmsdcc_vreg_init_reg(curr_vccq_reg, dev);
+ if (curr_vdd_io_reg) {
+ rc = msmsdcc_vreg_init_reg(curr_vdd_io_reg, dev);
if (rc)
goto vdd_reg_deinit;
}
- if (curr_vddp_reg) {
- rc = msmsdcc_vreg_init_reg(curr_vddp_reg, dev);
- if (rc)
- goto vccq_reg_deinit;
- }
rc = msmsdcc_vreg_reset(host);
if (rc)
pr_err("msmsdcc.%d vreg reset failed (%d)\n",
@@ -2174,14 +2168,11 @@
goto out;
} else {
/* Deregister all regulators from regulator framework */
- goto vddp_reg_deinit;
+ goto vdd_io_reg_deinit;
}
-vddp_reg_deinit:
- if (curr_vddp_reg)
- msmsdcc_vreg_deinit_reg(curr_vddp_reg);
-vccq_reg_deinit:
- if (curr_vccq_reg)
- msmsdcc_vreg_deinit_reg(curr_vccq_reg);
+vdd_io_reg_deinit:
+ if (curr_vdd_io_reg)
+ msmsdcc_vreg_deinit_reg(curr_vdd_io_reg);
vdd_reg_deinit:
if (curr_vdd_reg)
msmsdcc_vreg_deinit_reg(curr_vdd_reg);
@@ -2254,16 +2245,14 @@
{
int rc = 0, i;
struct msm_mmc_slot_reg_data *curr_slot;
- struct msm_mmc_reg_data *curr_vdd_reg, *curr_vccq_reg, *curr_vddp_reg;
- struct msm_mmc_reg_data *vreg_table[3];
+ struct msm_mmc_reg_data *vreg_table[2];
curr_slot = host->plat->vreg_data;
if (!curr_slot)
goto out;
- curr_vdd_reg = vreg_table[0] = curr_slot->vdd_data;
- curr_vccq_reg = vreg_table[1] = curr_slot->vccq_data;
- curr_vddp_reg = vreg_table[2] = curr_slot->vddp_data;
+ vreg_table[0] = curr_slot->vdd_data;
+ vreg_table[1] = curr_slot->vdd_io_data;
for (i = 0; i < ARRAY_SIZE(vreg_table); i++) {
if (vreg_table[i]) {
@@ -2294,70 +2283,53 @@
return rc;
}
-static int msmsdcc_set_vddp_level(struct msmsdcc_host *host, int level)
+enum vdd_io_level {
+ /* set vdd_io_data->low_vol_level */
+ VDD_IO_LOW,
+ /* set vdd_io_data->high_vol_level */
+ VDD_IO_HIGH,
+ /*
+ * set whatever there in voltage_level (third argument) of
+ * msmsdcc_set_vdd_io_vol() function.
+ */
+ VDD_IO_SET_LEVEL,
+};
+
+static int msmsdcc_set_vdd_io_vol(struct msmsdcc_host *host,
+ enum vdd_io_level level,
+ unsigned int voltage_level)
{
int rc = 0;
+ int set_level;
if (host->plat->vreg_data) {
- struct msm_mmc_reg_data *vddp_reg =
- host->plat->vreg_data->vddp_data;
+ struct msm_mmc_reg_data *vdd_io_reg =
+ host->plat->vreg_data->vdd_io_data;
- if (vddp_reg && vddp_reg->is_enabled)
- rc = msmsdcc_vreg_set_voltage(vddp_reg, level, level);
+ if (vdd_io_reg && vdd_io_reg->is_enabled) {
+ switch (level) {
+ case VDD_IO_LOW:
+ set_level = vdd_io_reg->low_vol_level;
+ break;
+ case VDD_IO_HIGH:
+ set_level = vdd_io_reg->high_vol_level;
+ break;
+ case VDD_IO_SET_LEVEL:
+ set_level = voltage_level;
+ break;
+ default:
+ pr_err("%s: %s: invalid argument level = %d",
+ mmc_hostname(host->mmc), __func__,
+ level);
+ rc = -EINVAL;
+ goto out;
+ }
+ rc = msmsdcc_vreg_set_voltage(vdd_io_reg,
+ set_level, set_level);
+ }
}
- return rc;
-}
-
-static inline int msmsdcc_set_vddp_low_vol(struct msmsdcc_host *host)
-{
- struct msm_mmc_slot_reg_data *curr_slot = host->plat->vreg_data;
- int rc = 0;
-
- if (curr_slot && curr_slot->vddp_data) {
- rc = msmsdcc_set_vddp_level(host,
- curr_slot->vddp_data->low_vol_level);
-
- if (rc)
- pr_err("%s: %s: failed to change vddp level to %d",
- mmc_hostname(host->mmc), __func__,
- curr_slot->vddp_data->low_vol_level);
- }
-
- return rc;
-}
-
-static inline int msmsdcc_set_vddp_high_vol(struct msmsdcc_host *host)
-{
- struct msm_mmc_slot_reg_data *curr_slot = host->plat->vreg_data;
- int rc = 0;
-
- if (curr_slot && curr_slot->vddp_data) {
- rc = msmsdcc_set_vddp_level(host,
- curr_slot->vddp_data->high_vol_level);
-
- if (rc)
- pr_err("%s: %s: failed to change vddp level to %d",
- mmc_hostname(host->mmc), __func__,
- curr_slot->vddp_data->high_vol_level);
- }
-
- return rc;
-}
-
-static inline int msmsdcc_set_vccq_vol(struct msmsdcc_host *host, int level)
-{
- struct msm_mmc_slot_reg_data *curr_slot = host->plat->vreg_data;
- int rc = 0;
-
- if (curr_slot && curr_slot->vccq_data) {
- rc = msmsdcc_vreg_set_voltage(curr_slot->vccq_data,
- level, level);
- if (rc)
- pr_err("%s: %s: failed to change vccq level to %d",
- mmc_hostname(host->mmc), __func__, level);
- }
-
+out:
return rc;
}
@@ -2582,11 +2554,11 @@
pwr = MCI_PWR_OFF;
msmsdcc_cfg_mpm_sdiowakeup(host, SDC_DAT1_DISABLE);
/*
- * As VDD pad rail is always on, set low voltage for VDD
- * pad rail when slot is unused (when card is not present
- * or during system suspend).
+ * If VDD IO rail is always on, set low voltage for VDD
+ * IO rail when slot is not in use (like when card is not
+ * present or during system suspend).
*/
- msmsdcc_set_vddp_low_vol(host);
+ msmsdcc_set_vdd_io_vol(host, VDD_IO_LOW, 0);
msmsdcc_setup_pins(host, false);
break;
case MMC_POWER_UP:
@@ -2594,7 +2566,7 @@
pwr = MCI_PWR_UP;
msmsdcc_cfg_mpm_sdiowakeup(host, SDC_DAT1_ENABLE);
- msmsdcc_set_vddp_high_vol(host);
+ msmsdcc_set_vdd_io_vol(host, VDD_IO_HIGH, 0);
msmsdcc_setup_pins(host, true);
break;
case MMC_POWER_ON:
@@ -3298,8 +3270,8 @@
}
#endif
-static int msmsdcc_start_signal_voltage_switch(struct mmc_host *mmc,
- struct mmc_ios *ios)
+static int msmsdcc_switch_io_voltage(struct mmc_host *mmc,
+ struct mmc_ios *ios)
{
struct msmsdcc_host *host = mmc_priv(mmc);
unsigned long flags;
@@ -3309,31 +3281,32 @@
host->io_pad_pwr_switch = 0;
spin_unlock_irqrestore(&host->lock, flags);
- /*
- * For eMMC cards, VccQ voltage range must be changed
- * only if it operates in HS200 SDR 1.2V mode or in
- * DDR 1.2V mode.
- */
- if (ios->signal_voltage == MMC_SIGNAL_VOLTAGE_120) {
- rc = msmsdcc_set_vccq_vol(host, 1200000);
+ switch (ios->signal_voltage) {
+ case MMC_SIGNAL_VOLTAGE_330:
+ /* Set VDD IO to high voltage range (2.7v - 3.6v) */
+ rc = msmsdcc_set_vdd_io_vol(host, VDD_IO_HIGH, 0);
goto out;
- }
-
- if (ios->signal_voltage == MMC_SIGNAL_VOLTAGE_330) {
- /* Change voltage level of VDDPX to high voltage */
- rc = msmsdcc_set_vddp_high_vol(host);
+ case MMC_SIGNAL_VOLTAGE_180:
+ break;
+ case MMC_SIGNAL_VOLTAGE_120:
+ /*
+ * For eMMC cards, VDD_IO voltage range must be changed
+ * only if it operates in HS200 SDR 1.2V mode or in
+ * DDR 1.2V mode.
+ */
+ rc = msmsdcc_set_vdd_io_vol(host, VDD_IO_SET_LEVEL, 1200000);
goto out;
- } else if (ios->signal_voltage != MMC_SIGNAL_VOLTAGE_180) {
+ default:
/* invalid selection. don't do anything */
rc = -EINVAL;
goto out;
}
- spin_lock_irqsave(&host->lock, flags);
/*
* If we are here means voltage switch from high voltage to
* low voltage is required
*/
+ spin_lock_irqsave(&host->lock, flags);
/*
* Poll on MCIDATIN_3_0 and MCICMDIN bits of MCI_TEST_INPUT
@@ -3353,10 +3326,10 @@
spin_unlock_irqrestore(&host->lock, flags);
/*
- * Switch VDDPX from high voltage to low voltage
- * to change the VDD of the SD IO pads.
+ * Switch VDD Io from high voltage range (2.7v - 3.6v) to
+ * low voltage range (1.7v - 1.95v).
*/
- rc = msmsdcc_set_vddp_low_vol(host);
+ rc = msmsdcc_set_vdd_io_vol(host, VDD_IO_LOW, 0);
if (rc)
goto out;
@@ -3855,7 +3828,7 @@
.set_ios = msmsdcc_set_ios,
.get_ro = msmsdcc_get_ro,
.enable_sdio_irq = msmsdcc_enable_sdio_irq,
- .start_signal_voltage_switch = msmsdcc_start_signal_voltage_switch,
+ .start_signal_voltage_switch = msmsdcc_switch_io_voltage,
.execute_tuning = msmsdcc_execute_tuning
};
diff --git a/drivers/video/msm/vidc/1080p/ddl/vcd_ddl.c b/drivers/video/msm/vidc/1080p/ddl/vcd_ddl.c
index 81b1436..d5b195d 100644
--- a/drivers/video/msm/vidc/1080p/ddl/vcd_ddl.c
+++ b/drivers/video/msm/vidc/1080p/ddl/vcd_ddl.c
@@ -473,8 +473,7 @@
u32 vcd_status = VCD_S_SUCCESS;
struct vcd_transc *transc;
transc = (struct vcd_transc *)(ddl->client_data);
- DDL_MSG_LOW("%s: transc = 0x%x, in_use = %u",
- __func__, (u32)ddl->client_data, transc->in_use);
+ DDL_MSG_LOW("%s: transc = 0x%x", __func__, (u32)ddl->client_data);
if (encoder->slice_delivery_info.enable) {
return ddl_encode_frame_batch(ddl_handle,
input_frame,
diff --git a/drivers/video/msm/vidc/1080p/ddl/vcd_ddl.h b/drivers/video/msm/vidc/1080p/ddl/vcd_ddl.h
index ac1ff24..3c082e4 100644
--- a/drivers/video/msm/vidc/1080p/ddl/vcd_ddl.h
+++ b/drivers/video/msm/vidc/1080p/ddl/vcd_ddl.h
@@ -228,6 +228,7 @@
[DDL_MAX_NUM_BFRS_FOR_SLICE_BATCH];
u32 num_output_frames;
u32 out_frm_next_frmindex;
+ u32 first_output_frame_tag;
};
struct ddl_encoder_data{
struct ddl_codec_data_hdr hdr;
diff --git a/drivers/video/msm/vidc/1080p/ddl/vcd_ddl_interrupt_handler.c b/drivers/video/msm/vidc/1080p/ddl/vcd_ddl_interrupt_handler.c
index e2c0a2a..3487f53 100644
--- a/drivers/video/msm/vidc/1080p/ddl/vcd_ddl_interrupt_handler.c
+++ b/drivers/video/msm/vidc/1080p/ddl/vcd_ddl_interrupt_handler.c
@@ -1774,6 +1774,27 @@
vidc_sm_get_frame_tags(&ddl->shared_mem
[ddl->command_channel],
&output_frame->ip_frm_tag, &bottom_frame_tag);
+
+ if (start_bfr_idx == 0) {
+ encoder->batch_frame.first_output_frame_tag =
+ output_frame->ip_frm_tag;
+ DDL_MSG_LOW("%s: first_output_frame_tag[0x%x]",
+ __func__, output_frame->ip_frm_tag);
+ if (!output_frame->ip_frm_tag) {
+ DDL_MSG_ERROR("%s: first_output_frame_tag "\
+ "is zero", __func__);
+ }
+ }
+ if (output_frame->ip_frm_tag !=
+ encoder->batch_frame.first_output_frame_tag) {
+ DDL_MSG_ERROR("%s: output_frame->ip_frm_tag[0x%x] is "\
+ "not equal to the first_output_frame_tag[0x%x]\n",
+ __func__, output_frame->ip_frm_tag,
+ encoder->batch_frame.first_output_frame_tag);
+ output_frame->ip_frm_tag =
+ encoder->batch_frame.first_output_frame_tag;
+ }
+
ddl_get_encoded_frame(output_frame,
encoder->codec.codec,
encoder->enc_frame_info.enc_frame);
@@ -1856,6 +1877,27 @@
vidc_sm_get_frame_tags(&ddl->shared_mem
[ddl->command_channel],
&output_frame->ip_frm_tag, &bottom_frame_tag);
+
+ if (start_bfr_idx == 0) {
+ encoder->batch_frame.first_output_frame_tag =
+ output_frame->ip_frm_tag;
+ DDL_MSG_LOW("%s: first_output_frame_tag[0x%x]",
+ __func__, output_frame->ip_frm_tag);
+ if (!output_frame->ip_frm_tag) {
+ DDL_MSG_ERROR("%s: first_output_frame_tag "\
+ "is zero", __func__);
+ }
+ }
+ if (output_frame->ip_frm_tag !=
+ encoder->batch_frame.first_output_frame_tag) {
+ DDL_MSG_ERROR("%s: output_frame->ip_frm_tag[0x%x] is "\
+ "not equal to the first_output_frame_tag[0x%x]\n",
+ __func__, output_frame->ip_frm_tag,
+ encoder->batch_frame.first_output_frame_tag);
+ output_frame->ip_frm_tag =
+ encoder->batch_frame.first_output_frame_tag;
+ }
+
ddl_get_encoded_frame(output_frame,
encoder->codec.codec,
encoder->enc_frame_info.enc_frame);
@@ -1925,6 +1967,10 @@
&ddl->shared_mem[ddl->command_channel],
&output_frame->ip_frm_tag,
&bottom_frame_tag);
+ if (!output_frame->ip_frm_tag) {
+ DDL_MSG_ERROR("%s: output frame tag is zero",
+ __func__);
+ }
ddl_get_encoded_frame(
output_frame,
encoder->codec.codec,
diff --git a/drivers/video/msm/vidc/1080p/ddl/vcd_ddl_vidc.c b/drivers/video/msm/vidc/1080p/ddl/vcd_ddl_vidc.c
index d0cf4e8..14e1331 100644
--- a/drivers/video/msm/vidc/1080p/ddl/vcd_ddl_vidc.c
+++ b/drivers/video/msm/vidc/1080p/ddl/vcd_ddl_vidc.c
@@ -867,6 +867,7 @@
DDL_MEMSET(encoder->batch_frame.slice_batch_in.align_virtual_addr, 0,
sizeof(struct vidc_1080p_enc_slice_batch_in_param));
encoder->batch_frame.out_frm_next_frmindex = 0;
+ encoder->batch_frame.first_output_frame_tag = 0;
bitstream_size = encoder->batch_frame.output_frame[0].vcd_frm.alloc_len;
encoder->output_buf_req.sz = bitstream_size;
y_addr = DDL_OFFSET(ddl_context->dram_base_b.align_physical_addr,
diff --git a/drivers/video/msm/vidc/common/vcd/vcd_sub.c b/drivers/video/msm/vidc/common/vcd/vcd_sub.c
index 6ca4dbe..b71212c 100644
--- a/drivers/video/msm/vidc/common/vcd/vcd_sub.c
+++ b/drivers/video/msm/vidc/common/vcd/vcd_sub.c
@@ -2067,8 +2067,8 @@
rc = VCD_ERR_CLIENT_FATAL;
if (VCD_FAILED(rc)) {
- VCD_MSG_FATAL(
- "vcd_validate_io_done_pyld: invalid transaction");
+ VCD_MSG_FATAL("vcd_validate_io_done_pyld: "\
+ "invalid transaction 0x%x", (u32)transc);
} else if (!frame->vcd_frm.virtual &&
status != VCD_ERR_INTRLCD_FIELD_DROP)
rc = VCD_ERR_BAD_POINTER;
diff --git a/include/linux/mmc/card.h b/include/linux/mmc/card.h
index 3f6d994..19ca831 100644
--- a/include/linux/mmc/card.h
+++ b/include/linux/mmc/card.h
@@ -61,6 +61,10 @@
unsigned int generic_cmd6_time; /* Units: 10ms */
unsigned int power_off_longtime; /* Units: ms */
unsigned int hs_max_dtr;
+#define MMC_HIGH_26_MAX_DTR 26000000
+#define MMC_HIGH_52_MAX_DTR 52000000
+#define MMC_HIGH_DDR_MAX_DTR 52000000
+#define MMC_HS200_MAX_DTR 200000000
unsigned int sectors;
unsigned int card_type;
unsigned int hc_erase_size; /* In sectors */
diff --git a/include/linux/mmc/mmc.h b/include/linux/mmc/mmc.h
index 01f4991..b867c62 100644
--- a/include/linux/mmc/mmc.h
+++ b/include/linux/mmc/mmc.h
@@ -368,66 +368,6 @@
#define EXT_CSD_CARD_TYPE_SDR_1_2V (1<<5) /* Card can run at 200MHz */
/* SDR mode @1.2V I/O */
-#define EXT_CSD_CARD_TYPE_SDR_200 (EXT_CSD_CARD_TYPE_SDR_1_8V | \
- EXT_CSD_CARD_TYPE_SDR_1_2V)
-
-#define EXT_CSD_CARD_TYPE_SDR_ALL (EXT_CSD_CARD_TYPE_SDR_200 | \
- EXT_CSD_CARD_TYPE_52 | \
- EXT_CSD_CARD_TYPE_26)
-
-#define EXT_CSD_CARD_TYPE_SDR_1_2V_ALL (EXT_CSD_CARD_TYPE_SDR_1_2V | \
- EXT_CSD_CARD_TYPE_52 | \
- EXT_CSD_CARD_TYPE_26)
-
-#define EXT_CSD_CARD_TYPE_SDR_1_8V_ALL (EXT_CSD_CARD_TYPE_SDR_1_8V | \
- EXT_CSD_CARD_TYPE_52 | \
- EXT_CSD_CARD_TYPE_26)
-
-#define EXT_CSD_CARD_TYPE_SDR_1_2V_DDR_1_8V (EXT_CSD_CARD_TYPE_SDR_1_2V | \
- EXT_CSD_CARD_TYPE_DDR_1_8V | \
- EXT_CSD_CARD_TYPE_52 | \
- EXT_CSD_CARD_TYPE_26)
-
-#define EXT_CSD_CARD_TYPE_SDR_1_8V_DDR_1_8V (EXT_CSD_CARD_TYPE_SDR_1_8V | \
- EXT_CSD_CARD_TYPE_DDR_1_8V | \
- EXT_CSD_CARD_TYPE_52 | \
- EXT_CSD_CARD_TYPE_26)
-
-#define EXT_CSD_CARD_TYPE_SDR_1_2V_DDR_1_2V (EXT_CSD_CARD_TYPE_SDR_1_2V | \
- EXT_CSD_CARD_TYPE_DDR_1_2V | \
- EXT_CSD_CARD_TYPE_52 | \
- EXT_CSD_CARD_TYPE_26)
-
-#define EXT_CSD_CARD_TYPE_SDR_1_8V_DDR_1_2V (EXT_CSD_CARD_TYPE_SDR_1_8V | \
- EXT_CSD_CARD_TYPE_DDR_1_2V | \
- EXT_CSD_CARD_TYPE_52 | \
- EXT_CSD_CARD_TYPE_26)
-
-#define EXT_CSD_CARD_TYPE_SDR_1_2V_DDR_52 (EXT_CSD_CARD_TYPE_SDR_1_2V | \
- EXT_CSD_CARD_TYPE_DDR_52 | \
- EXT_CSD_CARD_TYPE_52 | \
- EXT_CSD_CARD_TYPE_26)
-
-#define EXT_CSD_CARD_TYPE_SDR_1_8V_DDR_52 (EXT_CSD_CARD_TYPE_SDR_1_8V | \
- EXT_CSD_CARD_TYPE_DDR_52 | \
- EXT_CSD_CARD_TYPE_52 | \
- EXT_CSD_CARD_TYPE_26)
-
-#define EXT_CSD_CARD_TYPE_SDR_ALL_DDR_1_8V (EXT_CSD_CARD_TYPE_SDR_200 | \
- EXT_CSD_CARD_TYPE_DDR_1_8V | \
- EXT_CSD_CARD_TYPE_52 | \
- EXT_CSD_CARD_TYPE_26)
-
-#define EXT_CSD_CARD_TYPE_SDR_ALL_DDR_1_2V (EXT_CSD_CARD_TYPE_SDR_200 | \
- EXT_CSD_CARD_TYPE_DDR_1_2V | \
- EXT_CSD_CARD_TYPE_52 | \
- EXT_CSD_CARD_TYPE_26)
-
-#define EXT_CSD_CARD_TYPE_SDR_ALL_DDR_52 (EXT_CSD_CARD_TYPE_SDR_200 | \
- EXT_CSD_CARD_TYPE_DDR_52 | \
- EXT_CSD_CARD_TYPE_52 | \
- EXT_CSD_CARD_TYPE_26)
-
#define EXT_CSD_BUS_WIDTH_1 0 /* Card is in 1 bit mode */
#define EXT_CSD_BUS_WIDTH_4 1 /* Card is in 4 bit mode */
#define EXT_CSD_BUS_WIDTH_8 2 /* Card is in 8 bit mode */
diff --git a/sound/soc/msm/msm-dai-q6.c b/sound/soc/msm/msm-dai-q6.c
index 284320d..e5bc922 100644
--- a/sound/soc/msm/msm-dai-q6.c
+++ b/sound/soc/msm/msm-dai-q6.c
@@ -1352,7 +1352,7 @@
};
static struct snd_soc_dai_driver msm_dai_q6_bt_sco_tx_dai = {
- .playback = {
+ .capture = {
.rates = SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_16000,
.formats = SNDRV_PCM_FMTBIT_S16_LE,
.channels_min = 1,
@@ -1381,7 +1381,7 @@
};
static struct snd_soc_dai_driver msm_dai_q6_fm_tx_dai = {
- .playback = {
+ .capture = {
.rates = SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_8000 |
SNDRV_PCM_RATE_16000,
.formats = SNDRV_PCM_FMTBIT_S16_LE,