Merge "msm: pil-q6v5: Migrate to clock APIs" into msm-3.0
diff --git a/arch/arm/mach-msm/board-8064-pmic.c b/arch/arm/mach-msm/board-8064-pmic.c
index 91fd400..1a0a287 100644
--- a/arch/arm/mach-msm/board-8064-pmic.c
+++ b/arch/arm/mach-msm/board-8064-pmic.c
@@ -127,6 +127,7 @@
/* TABLA CODEC RESET */
PM8921_GPIO_OUTPUT(34, 1, MED),
PM8921_GPIO_INPUT(31, PM_GPIO_PULL_NO),
+ PM8921_GPIO_OUTPUT(13, 0, HIGH), /* PCIE_CLK_PWR_EN */
};
static struct pm8xxx_gpio_init pm8921_mtp_kp_gpios[] __initdata = {
@@ -146,6 +147,8 @@
PM8921_MPP_INIT(8, D_OUTPUT, PM8921_MPP_DIG_LEVEL_S4, DOUT_CTRL_LOW),
/*MPP9 is used to detect docking station connection/removal on Liquid*/
PM8921_MPP_INIT(9, D_INPUT, PM8921_MPP_DIG_LEVEL_S4, DIN_TO_INT),
+ /* PCIE_RESET_N */
+ PM8921_MPP_INIT(1, D_OUTPUT, PM8921_MPP_DIG_LEVEL_VPH, DOUT_CTRL_HIGH),
};
void __init apq8064_pm8xxx_gpio_mpp_init(void)
diff --git a/arch/arm/mach-msm/board-8064-regulator.c b/arch/arm/mach-msm/board-8064-regulator.c
index 58e83a0..3d2dbaa 100644
--- a/arch/arm/mach-msm/board-8064-regulator.c
+++ b/arch/arm/mach-msm/board-8064-regulator.c
@@ -157,6 +157,8 @@
REGULATOR_SUPPLY("HSUSB_VDDCX", "msm_ehci_host.1"),
REGULATOR_SUPPLY("HSIC_VDDCX", "msm_hsic_host"),
REGULATOR_SUPPLY("riva_vddcx", "wcnss_wlan.0"),
+ REGULATOR_SUPPLY("vp_pcie", "msm_pcie"),
+ REGULATOR_SUPPLY("vptx_pcie", "msm_pcie"),
};
VREG_CONSUMERS(S4) = {
REGULATOR_SUPPLY("8921_s4", NULL),
@@ -213,6 +215,7 @@
};
VREG_CONSUMERS(LVS6) = {
REGULATOR_SUPPLY("8921_lvs6", NULL),
+ REGULATOR_SUPPLY("vdd_pcie_vph", "msm_pcie"),
};
VREG_CONSUMERS(LVS7) = {
REGULATOR_SUPPLY("8921_lvs7", NULL),
@@ -256,6 +259,7 @@
REGULATOR_SUPPLY("lvds_vccs_3p3v", "lvds.0"),
REGULATOR_SUPPLY("dsi1_vccs_3p3v", "mipi_dsi.1"),
REGULATOR_SUPPLY("hdmi_mux_vdd", "hdmi_msm.0"),
+ REGULATOR_SUPPLY("pcie_ext_3p3v", "msm_pcie"),
};
VREG_CONSUMERS(EXT_TS_SW) = {
REGULATOR_SUPPLY("ext_ts_sw", NULL),
diff --git a/arch/arm/mach-msm/board-8064.c b/arch/arm/mach-msm/board-8064.c
index ed17cc4..c123138 100644
--- a/arch/arm/mach-msm/board-8064.c
+++ b/arch/arm/mach-msm/board-8064.c
@@ -69,6 +69,7 @@
#include <sound/cs8427.h>
#include <media/gpio-ir-recv.h>
#include <linux/fmem.h>
+#include <mach/msm_pcie.h>
#include "msm_watchdog.h"
#include "board-8064.h"
@@ -114,6 +115,10 @@
#define MSM_MM_FW_SIZE 0x200000
#define APQ8064_FW_START (APQ8064_FIXED_AREA_START - MSM_MM_FW_SIZE)
+/* PCIe power enable pmic gpio */
+#define PCIE_PWR_EN_PMIC_GPIO 13
+#define PCIE_RST_N_PMIC_MPP 1
+
#ifdef CONFIG_KERNEL_PMEM_EBI_REGION
static unsigned pmem_kernel_ebi1_size = MSM_PMEM_KERNEL_EBI1_SIZE;
static int __init pmem_kernel_ebi1_size_setup(char *p)
@@ -1998,6 +2003,22 @@
msm_bus_8064_cpss_fpb.dev.platform_data = &msm_bus_8064_cpss_fpb_pdata;
}
+/* PCIe gpios */
+static struct msm_pcie_gpio_info_t msm_pcie_gpio_info[MSM_PCIE_MAX_GPIO] = {
+ {"rst_n", PM8921_MPP_PM_TO_SYS(PCIE_RST_N_PMIC_MPP), 0},
+ {"pwr_en", PM8921_GPIO_PM_TO_SYS(PCIE_PWR_EN_PMIC_GPIO), 1},
+};
+
+static struct msm_pcie_platform msm_pcie_platform_data = {
+ .gpio = msm_pcie_gpio_info,
+};
+
+static void __init mpq8064_pcie_init(void)
+{
+ msm_device_pcie.dev.platform_data = &msm_pcie_platform_data;
+ platform_device_register(&msm_device_pcie);
+}
+
static struct platform_device apq8064_device_ext_5v_vreg __devinitdata = {
.name = GPIO_REGULATOR_DEV_NAME,
.id = PM8921_MPP_PM_TO_SYS(7),
@@ -2877,6 +2898,7 @@
machine_is_mpq8064_dtv()) {
enable_avc_i2c_bus();
platform_add_devices(mpq_devices, ARRAY_SIZE(mpq_devices));
+ mpq8064_pcie_init();
} else {
ethernet_init();
platform_add_devices(cdp_devices, ARRAY_SIZE(cdp_devices));
diff --git a/arch/arm/mach-msm/board-8930-gpu.c b/arch/arm/mach-msm/board-8930-gpu.c
index e23b76c..3c3843a 100644
--- a/arch/arm/mach-msm/board-8930-gpu.c
+++ b/arch/arm/mach-msm/board-8930-gpu.c
@@ -115,7 +115,7 @@
static struct kgsl_device_platform_data kgsl_3d0_pdata = {
.pwrlevel = {
{
- .gpu_freq = 400000000,
+ .gpu_freq = 450000000,
.bus_freq = 3,
.io_fraction = 0,
},
diff --git a/arch/arm/mach-msm/board-msm8x60.c b/arch/arm/mach-msm/board-msm8x60.c
index b0799c2..e172481 100644
--- a/arch/arm/mach-msm/board-msm8x60.c
+++ b/arch/arm/mach-msm/board-msm8x60.c
@@ -2639,7 +2639,11 @@
#define MSM_SMI_SIZE 0x4000000
#define KERNEL_SMI_BASE (MSM_SMI_BASE)
+#if defined(CONFIG_ION_MSM) && defined(CONFIG_MSM_MULTIMEDIA_USE_ION)
+#define KERNEL_SMI_SIZE 0x000000
+#else
#define KERNEL_SMI_SIZE 0x600000
+#endif
#define USER_SMI_BASE (KERNEL_SMI_BASE + KERNEL_SMI_SIZE)
#define USER_SMI_SIZE (MSM_SMI_SIZE - KERNEL_SMI_SIZE)
@@ -2648,7 +2652,7 @@
#define MSM_ION_SF_SIZE 0x4000000 /* 64MB */
#define MSM_ION_CAMERA_SIZE MSM_PMEM_ADSP_SIZE
#define MSM_ION_MM_FW_SIZE 0x200000 /* (2MB) */
-#define MSM_ION_MM_SIZE 0x3600000 /* (54MB) Must be a multiple of 64K */
+#define MSM_ION_MM_SIZE 0x3c00000 /* (60MB) Must be a multiple of 64K */
#define MSM_ION_MFC_SIZE SZ_8K
#ifdef CONFIG_FB_MSM_OVERLAY1_WRITEBACK
#define MSM_ION_WB_SIZE 0xC00000 /* 12MB */
diff --git a/arch/arm/mach-msm/clock-8960.c b/arch/arm/mach-msm/clock-8960.c
index 3a0b87e..1ebf597 100644
--- a/arch/arm/mach-msm/clock-8960.c
+++ b/arch/arm/mach-msm/clock-8960.c
@@ -4992,9 +4992,9 @@
CLK_LOOKUP("iface_clk", sdc2_p_clk.c, "msm_sdcc.2"),
CLK_LOOKUP("iface_clk", sdc3_p_clk.c, "msm_sdcc.3"),
CLK_LOOKUP("iface_clk", sdc4_p_clk.c, "msm_sdcc.4"),
- CLK_LOOKUP("iface_clk", pcie_p_clk.c, ""),
- CLK_LOOKUP("ref_clk", pcie_phy_ref_clk.c, ""),
- CLK_LOOKUP("bus_clk", pcie_a_clk.c, ""),
+ CLK_LOOKUP("iface_clk", pcie_p_clk.c, "msm_pcie"),
+ CLK_LOOKUP("ref_clk", pcie_phy_ref_clk.c, "msm_pcie"),
+ CLK_LOOKUP("bus_clk", pcie_a_clk.c, "msm_pcie"),
CLK_LOOKUP("core_clk", adm0_clk.c, "msm_dmov"),
CLK_LOOKUP("iface_clk", adm0_p_clk.c, "msm_dmov"),
CLK_LOOKUP("iface_clk", pmic_arb0_p_clk.c, ""),
diff --git a/arch/arm/mach-msm/devices-8064.c b/arch/arm/mach-msm/devices-8064.c
index f6eee76..29a90e4 100644
--- a/arch/arm/mach-msm/devices-8064.c
+++ b/arch/arm/mach-msm/devices-8064.c
@@ -82,6 +82,25 @@
#define MSM_HSUSB4_PHYS 0x12530000
#define MSM_HSUSB4_SIZE SZ_4K
+/* Address of PCIE20 PARF */
+#define PCIE20_PARF_PHYS 0x1b600000
+#define PCIE20_PARF_SIZE SZ_128
+
+/* Address of PCIE20 ELBI */
+#define PCIE20_ELBI_PHYS 0x1b502000
+#define PCIE20_ELBI_SIZE SZ_256
+
+/* Address of PCIE20 */
+#define PCIE20_PHYS 0x1b500000
+#define PCIE20_SIZE SZ_4K
+
+/* AXI address for PCIE device BAR resources */
+#define PCIE_AXI_BAR_PHYS 0x08000000
+#define PCIE_AXI_BAR_SIZE SZ_8M
+
+/* AXI address for PCIE device config space */
+#define PCIE_AXI_CONF_PHYS 0x08c00000
+#define PCIE_AXI_CONF_SIZE SZ_4K
static struct msm_watchdog_pdata msm_watchdog_pdata = {
.pet_time = 10000,
@@ -1518,6 +1537,46 @@
},
};
+static struct resource resources_msm_pcie[] = {
+ {
+ .name = "parf",
+ .start = PCIE20_PARF_PHYS,
+ .end = PCIE20_PARF_PHYS + PCIE20_PARF_SIZE - 1,
+ .flags = IORESOURCE_MEM,
+ },
+ {
+ .name = "elbi",
+ .start = PCIE20_ELBI_PHYS,
+ .end = PCIE20_ELBI_PHYS + PCIE20_ELBI_SIZE - 1,
+ .flags = IORESOURCE_MEM,
+ },
+ {
+ .name = "pcie20",
+ .start = PCIE20_PHYS,
+ .end = PCIE20_PHYS + PCIE20_SIZE - 1,
+ .flags = IORESOURCE_MEM,
+ },
+ {
+ .name = "axi_bar",
+ .start = PCIE_AXI_BAR_PHYS,
+ .end = PCIE_AXI_BAR_PHYS + PCIE_AXI_BAR_SIZE - 1,
+ .flags = IORESOURCE_MEM,
+ },
+ {
+ .name = "axi_conf",
+ .start = PCIE_AXI_CONF_PHYS,
+ .end = PCIE_AXI_CONF_PHYS + PCIE_AXI_CONF_SIZE - 1,
+ .flags = IORESOURCE_MEM,
+ },
+};
+
+struct platform_device msm_device_pcie = {
+ .name = "msm_pcie",
+ .id = -1,
+ .num_resources = ARRAY_SIZE(resources_msm_pcie),
+ .resource = resources_msm_pcie,
+};
+
#ifdef CONFIG_HW_RANDOM_MSM
/* PRNG device */
#define MSM_PRNG_PHYS 0x1A500000
diff --git a/arch/arm/mach-msm/devices.h b/arch/arm/mach-msm/devices.h
index 8f42ede..d01a229 100644
--- a/arch/arm/mach-msm/devices.h
+++ b/arch/arm/mach-msm/devices.h
@@ -167,6 +167,8 @@
extern struct platform_device msm_device_dmov_adm0;
extern struct platform_device msm_device_dmov_adm1;
+extern struct platform_device msm_device_pcie;
+
extern struct platform_device msm_device_nand;
extern struct platform_device msm_device_tssc;
diff --git a/arch/arm/mach-msm/include/mach/ocmem_priv.h b/arch/arm/mach-msm/include/mach/ocmem_priv.h
index 4b46c01..daf32a5 100644
--- a/arch/arm/mach-msm/include/mach/ocmem_priv.h
+++ b/arch/arm/mach-msm/include/mach/ocmem_priv.h
@@ -76,4 +76,6 @@
struct ocmem_zone *get_zone(unsigned);
unsigned long allocate_head(struct ocmem_zone *, unsigned long);
int free_head(struct ocmem_zone *, unsigned long, unsigned long);
+unsigned long allocate_tail(struct ocmem_zone *, unsigned long);
+int free_tail(struct ocmem_zone *, unsigned long, unsigned long);
#endif
diff --git a/arch/arm/mach-msm/ocmem.c b/arch/arm/mach-msm/ocmem.c
index 203b8d1..ed0b2f0 100644
--- a/arch/arm/mach-msm/ocmem.c
+++ b/arch/arm/mach-msm/ocmem.c
@@ -29,6 +29,7 @@
unsigned long p_start;
unsigned long p_size;
unsigned long p_min;
+ unsigned int p_tail;
};
struct ocmem_plat_data {
@@ -70,19 +71,20 @@
unsigned long start;
unsigned long size;
unsigned long min;
+ unsigned int tail;
};
/* This static table will go away with device tree support */
static struct ocmem_quota_table qt[OCMEM_CLIENT_MAX] = {
- /* name, id, start, size, min */
- { "graphics", OCMEM_GRAPHICS, 0x0, 0x100000, 0x80000},
- { "video", OCMEM_VIDEO, 0x100000, 0x80000, 0x55000},
- { "camera", OCMEM_CAMERA, 0x0, 0x0, 0x0},
- { "voice", OCMEM_VOICE, 0x0, 0x0, 0x0 },
- { "hp_audio", OCMEM_HP_AUDIO, 0x0, 0x0, 0x0},
- { "lp_audio", OCMEM_LP_AUDIO, 0x80000, 0xA0000, 0xA0000},
- { "blast", OCMEM_BLAST, 0x120000, 0x20000, 0x20000},
- { "sensors", OCMEM_SENSORS, 0x140000, 0x40000, 0x40000},
+ /* name, id, start, size, min, tail */
+ { "graphics", OCMEM_GRAPHICS, 0x0, 0x100000, 0x80000, 0},
+ { "video", OCMEM_VIDEO, 0x100000, 0x80000, 0x55000, 1},
+ { "camera", OCMEM_CAMERA, 0x0, 0x0, 0x0, 0},
+ { "voice", OCMEM_VOICE, 0x0, 0x0, 0x0, 0 },
+ { "hp_audio", OCMEM_HP_AUDIO, 0x0, 0x0, 0x0, 0},
+ { "lp_audio", OCMEM_LP_AUDIO, 0x80000, 0xA0000, 0xA0000, 0},
+ { "blast", OCMEM_BLAST, 0x120000, 0x20000, 0x20000, 0},
+ { "sensors", OCMEM_SENSORS, 0x140000, 0x40000, 0x40000, 0},
};
static inline int get_id(const char *name)
@@ -142,6 +144,7 @@
parts[j].p_size = qt[i].size;
parts[j].p_start = qt[i].start;
parts[j].p_min = qt[i].min;
+ parts[j].p_tail = qt[i].tail;
j++;
}
BUG_ON(j != nr_parts);
@@ -225,8 +228,13 @@
zone->max_regions = 0;
INIT_LIST_HEAD(&zone->region_list);
zone->z_ops = z_ops;
- z_ops->allocate = allocate_head;
- z_ops->free = free_head;
+ if (part->p_tail) {
+ z_ops->allocate = allocate_tail;
+ z_ops->free = free_tail;
+ } else {
+ z_ops->allocate = allocate_head;
+ z_ops->free = free_head;
+ }
active_zones++;
if (active_zones == 1)
diff --git a/arch/arm/mach-msm/ocmem_allocator.c b/arch/arm/mach-msm/ocmem_allocator.c
index 9f073fc..71cacda 100644
--- a/arch/arm/mach-msm/ocmem_allocator.c
+++ b/arch/arm/mach-msm/ocmem_allocator.c
@@ -15,6 +15,27 @@
#include <linux/genalloc.h>
/* All allocator operations are serialized by ocmem driver */
+
+/* The allocators work as follows:
+ Constraints:
+ 1) There is no IOMMU access to OCMEM hence successive allocations
+ in the zone must be physically contiguous
+ 2) Allocations must be freed in reverse order within a zone.
+
+ z->z_start: Fixed pointer to the start of a zone
+ z->z_end: Fixed pointer to the end of a zone
+
+ z->z_head: Movable pointer to the next free area when growing at head
+ Fixed on zones that grow from tail
+
+ z->z_tail: Movable pointer to the next free area when growing at tail
+ Fixed on zones that grow from head
+
+ z->z_free: Free space in a zone that is updated on an allocation/free
+
+ reserve: Enable libgenpool to simulate tail allocations
+*/
+
unsigned long allocate_head(struct ocmem_zone *z, unsigned long size)
{
@@ -30,6 +51,31 @@
return offset;
}
+unsigned long allocate_tail(struct ocmem_zone *z, unsigned long size)
+{
+ unsigned long offset;
+ unsigned long reserve;
+ unsigned long head;
+
+ if (z->z_tail < (z->z_head + size))
+ return -ENOMEM;
+
+ reserve = z->z_tail - z->z_head - size;
+ if (reserve) {
+ head = gen_pool_alloc(z->z_pool, reserve);
+ offset = gen_pool_alloc(z->z_pool, size);
+ gen_pool_free(z->z_pool, head, reserve);
+ } else
+ offset = gen_pool_alloc(z->z_pool, size);
+
+ if (!offset)
+ return -ENOMEM;
+
+ z->z_tail -= size;
+ z->z_free -= size;
+ return offset;
+}
+
int free_head(struct ocmem_zone *z, unsigned long offset,
unsigned long size)
{
@@ -43,3 +89,17 @@
z->z_free += size;
return 0;
}
+
+int free_tail(struct ocmem_zone *z, unsigned long offset,
+ unsigned long size)
+{
+ if (offset > z->z_tail) {
+ pr_err("ocmem: Detected out of order free "
+ "leading to fragmentation\n");
+ return -EINVAL;
+ }
+ gen_pool_free(z->z_pool, offset, size);
+ z->z_tail += size;
+ z->z_free += size;
+ return 0;
+}
diff --git a/drivers/gpu/msm/adreno.c b/drivers/gpu/msm/adreno.c
index 1432ccf..2f503ae 100644
--- a/drivers/gpu/msm/adreno.c
+++ b/drivers/gpu/msm/adreno.c
@@ -21,6 +21,7 @@
#include "kgsl_pwrscale.h"
#include "kgsl_cffdump.h"
#include "kgsl_sharedmem.h"
+#include "kgsl_iommu.h"
#include "adreno.h"
#include "adreno_pm4types.h"
@@ -243,7 +244,144 @@
return result;
}
-static void adreno_setstate(struct kgsl_device *device,
+static void adreno_iommu_setstate(struct kgsl_device *device,
+ uint32_t flags)
+{
+ unsigned int pt_val, reg_pt_val;
+ unsigned int link[200];
+ unsigned int *cmds = &link[0];
+ int sizedwords = 0;
+ struct adreno_device *adreno_dev = ADRENO_DEVICE(device);
+ struct kgsl_memdesc **reg_map_desc;
+ void *reg_map_array;
+ int num_iommu_units, i;
+
+ if (!adreno_dev->drawctxt_active)
+ return kgsl_mmu_device_setstate(&device->mmu, flags);
+ num_iommu_units = kgsl_mmu_get_reg_map_desc(&device->mmu,
+ ®_map_array);
+ reg_map_desc = reg_map_array;
+
+ if (kgsl_mmu_enable_clk(&device->mmu,
+ KGSL_IOMMU_CONTEXT_USER))
+ goto done;
+
+ if (adreno_is_a225(adreno_dev))
+ cmds += adreno_add_change_mh_phys_limit_cmds(cmds, 0xFFFFF000,
+ device->mmu.setstate_memory.gpuaddr +
+ KGSL_IOMMU_SETSTATE_NOP_OFFSET);
+ else
+ cmds += adreno_add_bank_change_cmds(cmds,
+ KGSL_IOMMU_CONTEXT_USER,
+ device->mmu.setstate_memory.gpuaddr +
+ KGSL_IOMMU_SETSTATE_NOP_OFFSET);
+
+ if (flags & KGSL_MMUFLAGS_PTUPDATE) {
+ pt_val = kgsl_mmu_pt_get_base_addr(device->mmu.hwpagetable);
+ /*
+ * We need to perfrom the following operations for all
+ * IOMMU units
+ */
+ for (i = 0; i < num_iommu_units; i++) {
+ reg_pt_val = (pt_val &
+ (KGSL_IOMMU_TTBR0_PA_MASK <<
+ KGSL_IOMMU_TTBR0_PA_SHIFT)) +
+ kgsl_mmu_get_pt_lsb(&device->mmu, i,
+ KGSL_IOMMU_CONTEXT_USER);
+ /*
+ * Set address of the new pagetable by writng to IOMMU
+ * TTBR0 register
+ */
+ *cmds++ = cp_type3_packet(CP_MEM_WRITE, 2);
+ *cmds++ = reg_map_desc[i]->gpuaddr +
+ (KGSL_IOMMU_CONTEXT_USER <<
+ KGSL_IOMMU_CTX_SHIFT) + KGSL_IOMMU_TTBR0;
+ *cmds++ = reg_pt_val;
+ *cmds++ = cp_type3_packet(CP_WAIT_FOR_IDLE, 1);
+ *cmds++ = 0x00000000;
+
+ /*
+ * Read back the ttbr0 register as a barrier to ensure
+ * above writes have completed
+ */
+ cmds += adreno_add_read_cmds(device, cmds,
+ reg_map_desc[i]->gpuaddr +
+ (KGSL_IOMMU_CONTEXT_USER <<
+ KGSL_IOMMU_CTX_SHIFT) + KGSL_IOMMU_TTBR0,
+ reg_pt_val,
+ device->mmu.setstate_memory.gpuaddr +
+ KGSL_IOMMU_SETSTATE_NOP_OFFSET);
+
+ /* set the asid */
+ *cmds++ = cp_type3_packet(CP_MEM_WRITE, 2);
+ *cmds++ = reg_map_desc[i]->gpuaddr +
+ (KGSL_IOMMU_CONTEXT_USER <<
+ KGSL_IOMMU_CTX_SHIFT) + KGSL_IOMMU_CONTEXTIDR;
+ *cmds++ = kgsl_mmu_get_hwpagetable_asid(&device->mmu);
+ *cmds++ = cp_type3_packet(CP_WAIT_FOR_IDLE, 1);
+ *cmds++ = 0x00000000;
+
+ /* Read back asid to ensure above write completes */
+ cmds += adreno_add_read_cmds(device, cmds,
+ reg_map_desc[i]->gpuaddr +
+ (KGSL_IOMMU_CONTEXT_USER <<
+ KGSL_IOMMU_CTX_SHIFT) + KGSL_IOMMU_CONTEXTIDR,
+ kgsl_mmu_get_hwpagetable_asid(&device->mmu),
+ device->mmu.setstate_memory.gpuaddr +
+ KGSL_IOMMU_SETSTATE_NOP_OFFSET);
+ }
+ /* invalidate all base pointers */
+ *cmds++ = cp_type3_packet(CP_INVALIDATE_STATE, 1);
+ *cmds++ = 0x7fff;
+
+ if (flags & KGSL_MMUFLAGS_TLBFLUSH)
+ cmds += __adreno_add_idle_indirect_cmds(cmds,
+ device->mmu.setstate_memory.gpuaddr +
+ KGSL_IOMMU_SETSTATE_NOP_OFFSET);
+ }
+ if (flags & KGSL_MMUFLAGS_TLBFLUSH) {
+ /*
+ * tlb flush based on asid, no need to flush entire tlb
+ */
+ for (i = 0; i < num_iommu_units; i++) {
+ *cmds++ = cp_type3_packet(CP_MEM_WRITE, 2);
+ *cmds++ = (reg_map_desc[i]->gpuaddr +
+ (KGSL_IOMMU_CONTEXT_USER <<
+ KGSL_IOMMU_CTX_SHIFT) +
+ KGSL_IOMMU_CTX_TLBIASID);
+ *cmds++ = kgsl_mmu_get_hwpagetable_asid(&device->mmu);
+ cmds += adreno_add_read_cmds(device, cmds,
+ reg_map_desc[i]->gpuaddr +
+ (KGSL_IOMMU_CONTEXT_USER <<
+ KGSL_IOMMU_CTX_SHIFT) +
+ KGSL_IOMMU_CONTEXTIDR,
+ kgsl_mmu_get_hwpagetable_asid(&device->mmu),
+ device->mmu.setstate_memory.gpuaddr +
+ KGSL_IOMMU_SETSTATE_NOP_OFFSET);
+ }
+ }
+
+ if (adreno_is_a225(adreno_dev))
+ cmds += adreno_add_change_mh_phys_limit_cmds(cmds,
+ reg_map_desc[num_iommu_units - 1]->gpuaddr - PAGE_SIZE,
+ device->mmu.setstate_memory.gpuaddr +
+ KGSL_IOMMU_SETSTATE_NOP_OFFSET);
+ else
+ cmds += adreno_add_bank_change_cmds(cmds,
+ KGSL_IOMMU_CONTEXT_PRIV,
+ device->mmu.setstate_memory.gpuaddr +
+ KGSL_IOMMU_SETSTATE_NOP_OFFSET);
+
+ sizedwords += (cmds - &link[0]);
+ if (sizedwords)
+ adreno_ringbuffer_issuecmds(device,
+ KGSL_CMD_FLAGS_PMODE, &link[0], sizedwords);
+done:
+ if (num_iommu_units)
+ kfree(reg_map_array);
+}
+
+static void adreno_gpummu_setstate(struct kgsl_device *device,
uint32_t flags)
{
struct adreno_device *adreno_dev = ADRENO_DEVICE(device);
@@ -253,16 +391,6 @@
unsigned int mh_mmu_invalidate = 0x00000003; /*invalidate all and tc */
/*
- * A3XX doesn't support the fast path (the registers don't even exist)
- * so just bail out early
- */
-
- if (adreno_is_a3xx(adreno_dev)) {
- kgsl_mmu_device_setstate(&device->mmu, flags);
- return;
- }
-
- /*
* If possible, then set the state via the command stream to avoid
* a CPU idle. Otherwise, use the default setstate which uses register
* writes For CFF dump we must idle and use the registers so that it is
@@ -348,6 +476,16 @@
}
}
+static void adreno_setstate(struct kgsl_device *device,
+ uint32_t flags)
+{
+ /* call the mmu specific handler */
+ if (KGSL_MMU_TYPE_GPU == kgsl_mmu_get_mmutype())
+ return adreno_gpummu_setstate(device, flags);
+ else if (KGSL_MMU_TYPE_IOMMU == kgsl_mmu_get_mmutype())
+ return adreno_iommu_setstate(device, flags);
+}
+
static unsigned int
a3xx_getchipid(struct kgsl_device *device)
{
diff --git a/drivers/gpu/msm/adreno.h b/drivers/gpu/msm/adreno.h
index a7ea20c..4ce56a4 100644
--- a/drivers/gpu/msm/adreno.h
+++ b/drivers/gpu/msm/adreno.h
@@ -16,6 +16,7 @@
#include "kgsl_device.h"
#include "adreno_drawctxt.h"
#include "adreno_ringbuffer.h"
+#include "kgsl_iommu.h"
#define DEVICE_3D_NAME "kgsl-3d"
#define DEVICE_3D0_NAME "kgsl-3d0"
@@ -223,4 +224,70 @@
return (ilog2(size) - 5) << 29;
}
+static inline int __adreno_add_idle_indirect_cmds(unsigned int *cmds,
+ unsigned int nop_gpuaddr)
+{
+ /* Adding an indirect buffer ensures that the prefetch stalls until
+ * the commands in indirect buffer have completed. We need to stall
+ * prefetch with a nop indirect buffer when updating pagetables
+ * because it provides stabler synchronization */
+ *cmds++ = CP_HDR_INDIRECT_BUFFER_PFD;
+ *cmds++ = nop_gpuaddr;
+ *cmds++ = 2;
+ *cmds++ = cp_type3_packet(CP_WAIT_FOR_IDLE, 1);
+ *cmds++ = 0x00000000;
+ return 5;
+}
+
+static inline int adreno_add_change_mh_phys_limit_cmds(unsigned int *cmds,
+ unsigned int new_phys_limit,
+ unsigned int nop_gpuaddr)
+{
+ unsigned int *start = cmds;
+
+ cmds += __adreno_add_idle_indirect_cmds(cmds, nop_gpuaddr);
+ *cmds++ = cp_type0_packet(MH_MMU_MPU_END, 1);
+ *cmds++ = new_phys_limit;
+ cmds += __adreno_add_idle_indirect_cmds(cmds, nop_gpuaddr);
+ return cmds - start;
+}
+
+static inline int adreno_add_bank_change_cmds(unsigned int *cmds,
+ int cur_ctx_bank,
+ unsigned int nop_gpuaddr)
+{
+ unsigned int *start = cmds;
+
+ cmds += __adreno_add_idle_indirect_cmds(cmds, nop_gpuaddr);
+ *cmds++ = cp_type0_packet(REG_CP_STATE_DEBUG_INDEX, 1);
+ *cmds++ = (cur_ctx_bank ? 0 : 0x20);
+ cmds += __adreno_add_idle_indirect_cmds(cmds, nop_gpuaddr);
+ return cmds - start;
+}
+
+/*
+ * adreno_read_cmds - Add pm4 packets to perform read
+ * @device - Pointer to device structure
+ * @cmds - Pointer to memory where read commands need to be added
+ * @addr - gpu address of the read
+ * @val - The GPU will wait until the data at address addr becomes
+ * equal to value
+ */
+static inline int adreno_add_read_cmds(struct kgsl_device *device,
+ unsigned int *cmds, unsigned int addr,
+ unsigned int val, unsigned int nop_gpuaddr)
+{
+ unsigned int *start = cmds;
+
+ *cmds++ = cp_type3_packet(CP_WAIT_REG_MEM, 5);
+ /* MEM SPACE = memory, FUNCTION = equals */
+ *cmds++ = 0x13;
+ *cmds++ = addr;
+ *cmds++ = val;
+ *cmds++ = 0xFFFFFFFF;
+ *cmds++ = 0xFFFFFFFF;
+ cmds += __adreno_add_idle_indirect_cmds(cmds, nop_gpuaddr);
+ return cmds - start;
+}
+
#endif /*__ADRENO_H */
diff --git a/drivers/gpu/msm/adreno_a2xx.c b/drivers/gpu/msm/adreno_a2xx.c
index eb936f8..ae846da 100644
--- a/drivers/gpu/msm/adreno_a2xx.c
+++ b/drivers/gpu/msm/adreno_a2xx.c
@@ -1848,8 +1848,13 @@
/* NQ and External Memory Swap */
GSL_RB_WRITE(cmds, cmds_gpu, 0x00000000);
- /* Protected mode error checking */
- GSL_RB_WRITE(cmds, cmds_gpu, GSL_RB_PROTECTED_MODE_CONTROL);
+ /* Protected mode error checking
+ * If iommu is used then protection needs to be turned off
+ * to enable context bank switching */
+ if (KGSL_MMU_TYPE_IOMMU == kgsl_mmu_get_mmutype())
+ GSL_RB_WRITE(cmds, cmds_gpu, 0);
+ else
+ GSL_RB_WRITE(cmds, cmds_gpu, GSL_RB_PROTECTED_MODE_CONTROL);
/* Disable header dumping and Header dump address */
GSL_RB_WRITE(cmds, cmds_gpu, 0x00000000);
/* Header dump size */
diff --git a/drivers/gpu/msm/kgsl_iommu.c b/drivers/gpu/msm/kgsl_iommu.c
index fdd4aa5..fb65565 100644
--- a/drivers/gpu/msm/kgsl_iommu.c
+++ b/drivers/gpu/msm/kgsl_iommu.c
@@ -595,7 +595,9 @@
kgsl_regwrite(mmu->device, MH_MMU_CONFIG, 0x00000001);
kgsl_regwrite(mmu->device, MH_MMU_MPU_END,
mh->mpu_base +
- iommu->iommu_units[0].reg_map.gpuaddr - PAGE_SIZE);
+ iommu->iommu_units
+ [iommu->unit_count - 1].reg_map.gpuaddr -
+ PAGE_SIZE);
} else {
kgsl_regwrite(mmu->device, MH_MMU_CONFIG, 0x00000000);
}
diff --git a/drivers/gpu/msm/kgsl_mmu.c b/drivers/gpu/msm/kgsl_mmu.c
index 663ba0f..b882807 100644
--- a/drivers/gpu/msm/kgsl_mmu.c
+++ b/drivers/gpu/msm/kgsl_mmu.c
@@ -545,8 +545,7 @@
struct kgsl_device *device = mmu->device;
if (KGSL_MMU_TYPE_NONE == kgsl_mmu_type)
return;
- else if (device->ftbl->setstate && (KGSL_MMU_TYPE_IOMMU !=
- kgsl_mmu_type))
+ else if (device->ftbl->setstate)
device->ftbl->setstate(device, flags);
else if (mmu->mmu_ops->mmu_device_setstate)
mmu->mmu_ops->mmu_device_setstate(mmu, flags);
diff --git a/drivers/gpu/msm/kgsl_pwrctrl.c b/drivers/gpu/msm/kgsl_pwrctrl.c
index 3a29d71..2aaefba 100644
--- a/drivers/gpu/msm/kgsl_pwrctrl.c
+++ b/drivers/gpu/msm/kgsl_pwrctrl.c
@@ -706,6 +706,7 @@
}
kgsl_pwrctrl_irq(device, KGSL_PWRFLAGS_OFF);
kgsl_pwrctrl_clk(device, KGSL_PWRFLAGS_OFF, KGSL_STATE_NAP);
+ kgsl_mmu_disable_clk(&device->mmu);
kgsl_pwrctrl_set_state(device, KGSL_STATE_NAP);
if (device->idle_wakelock.name)
wake_unlock(&device->idle_wakelock);
@@ -749,6 +750,7 @@
gpu_freq);
_sleep_accounting(device);
kgsl_pwrctrl_clk(device, KGSL_PWRFLAGS_OFF, KGSL_STATE_SLEEP);
+ kgsl_mmu_disable_clk(&device->mmu);
kgsl_pwrctrl_set_state(device, KGSL_STATE_SLEEP);
wake_unlock(&device->idle_wakelock);
pm_qos_update_request(&device->pm_qos_req_dma,
@@ -888,6 +890,7 @@
/* Order pwrrail/clk sequence based upon platform */
kgsl_pwrctrl_axi(device, KGSL_PWRFLAGS_OFF);
kgsl_pwrctrl_clk(device, KGSL_PWRFLAGS_OFF, KGSL_STATE_SLEEP);
+ kgsl_mmu_disable_clk(&device->mmu);
kgsl_pwrctrl_pwrrail(device, KGSL_PWRFLAGS_OFF);
}
EXPORT_SYMBOL(kgsl_pwrctrl_disable);
diff --git a/drivers/misc/qseecom.c b/drivers/misc/qseecom.c
index 2c42bc7..4c92ee5 100644
--- a/drivers/misc/qseecom.c
+++ b/drivers/misc/qseecom.c
@@ -1271,9 +1271,11 @@
{
struct ion_handle *ihandle; /* Ion handle */
struct qseecom_load_img_req load_img_req;
- int32_t ret;
+ int ret;
+ int set_cpu_ret = 0;
ion_phys_addr_t pa = 0;
uint32_t len;
+ struct cpumask mask;
struct qseecom_load_app_ireq load_req;
struct qseecom_command_scm_resp resp;
@@ -1302,14 +1304,25 @@
load_req.img_len = load_img_req.img_len;
load_req.phy_addr = pa;
+ /* SCM_CALL tied to Core0 */
+ mask = CPU_MASK_CPU0;
+ set_cpu_ret = set_cpus_allowed_ptr(current, &mask);
+ if (set_cpu_ret) {
+ pr_err("set_cpus_allowed_ptr failed : ret %d\n",
+ set_cpu_ret);
+ ret = -EFAULT;
+ goto qseecom_load_external_elf_set_cpu_err;
+ }
+
/* SCM_CALL to load the external elf */
ret = scm_call(SCM_SVC_TZSCHEDULER, 1, &load_req,
sizeof(struct qseecom_load_app_ireq),
&resp, sizeof(resp));
if (ret) {
- pr_err("scm_call to unload failed : ret %d\n",
+ pr_err("scm_call to load failed : ret %d\n",
ret);
ret = -EFAULT;
+ goto qseecom_load_external_elf_scm_err;
}
if (resp.result == QSEOS_RESULT_INCOMPLETE) {
@@ -1324,6 +1337,18 @@
ret = -EFAULT;
}
}
+
+qseecom_load_external_elf_scm_err:
+ /* Restore the CPU mask */
+ mask = CPU_MASK_ALL;
+ set_cpu_ret = set_cpus_allowed_ptr(current, &mask);
+ if (set_cpu_ret) {
+ pr_err("set_cpus_allowed_ptr failed to restore mask: ret %d\n",
+ set_cpu_ret);
+ ret = -EFAULT;
+ }
+
+qseecom_load_external_elf_set_cpu_err:
/* Deallocate the handle */
if (!IS_ERR_OR_NULL(ihandle))
ion_free(qseecom.ion_clnt, ihandle);
@@ -1334,11 +1359,23 @@
static int qseecom_unload_external_elf(struct qseecom_dev_handle *data)
{
int ret = 0;
+ int set_cpu_ret = 0;
struct qseecom_command_scm_resp resp;
struct qseecom_unload_app_ireq req;
+ struct cpumask mask;
/* Populate the structure for sending scm call to unload image */
req.qsee_cmd_id = QSEOS_UNLOAD_EXTERNAL_ELF_COMMAND;
+
+ /* SCM_CALL tied to Core0 */
+ mask = CPU_MASK_CPU0;
+ ret = set_cpus_allowed_ptr(current, &mask);
+ if (ret) {
+ pr_err("set_cpus_allowed_ptr failed : ret %d\n",
+ ret);
+ return -EFAULT;
+ }
+
/* SCM_CALL to unload the external elf */
ret = scm_call(SCM_SVC_TZSCHEDULER, 1, &req,
sizeof(struct qseecom_unload_app_ireq),
@@ -1346,7 +1383,8 @@
if (ret) {
pr_err("scm_call to unload failed : ret %d\n",
ret);
- return -EFAULT;
+ ret = -EFAULT;
+ goto qseecom_unload_external_elf_scm_err;
}
if (resp.result == QSEOS_RESULT_INCOMPLETE) {
ret = __qseecom_process_incomplete_cmd(data, &resp);
@@ -1360,6 +1398,17 @@
ret = -EFAULT;
}
}
+
+qseecom_unload_external_elf_scm_err:
+ /* Restore the CPU mask */
+ mask = CPU_MASK_ALL;
+ set_cpu_ret = set_cpus_allowed_ptr(current, &mask);
+ if (set_cpu_ret) {
+ pr_err("set_cpus_allowed_ptr failed to restore mask: ret %d\n",
+ set_cpu_ret);
+ ret = -EFAULT;
+ }
+
return ret;
}
diff --git a/drivers/usb/gadget/android.c b/drivers/usb/gadget/android.c
index d74959e..15fc0c1 100644
--- a/drivers/usb/gadget/android.c
+++ b/drivers/usb/gadget/android.c
@@ -223,6 +223,7 @@
char **uevent_envp = NULL;
static enum android_device_state last_uevent, next_state;
unsigned long flags;
+ int pm_qos_vote = -1;
spin_lock_irqsave(&cdev->lock, flags);
if (cdev->config) {
@@ -232,13 +233,16 @@
uevent_envp = dev->connected ? connected : disconnected;
next_state = dev->connected ? USB_CONNECTED : USB_DISCONNECTED;
if (dev->connected && strncmp(dev->pm_qos, "low", 3))
- android_pm_qos_update_latency(dev, 1);
+ pm_qos_vote = 1;
else if (!dev->connected || !strncmp(dev->pm_qos, "low", 3))
- android_pm_qos_update_latency(dev, 0);
+ pm_qos_vote = 0;
}
dev->sw_connected = dev->connected;
spin_unlock_irqrestore(&cdev->lock, flags);
+ if (pm_qos_vote != -1)
+ android_pm_qos_update_latency(dev, pm_qos_vote);
+
if (uevent_envp) {
/*
* Some userspace modules, e.g. MTP, work correctly only if
diff --git a/drivers/video/msm/mipi_dsi.c b/drivers/video/msm/mipi_dsi.c
index baad0a8..7564016 100644
--- a/drivers/video/msm/mipi_dsi.c
+++ b/drivers/video/msm/mipi_dsi.c
@@ -178,6 +178,17 @@
clk_rate = mfd->fbi->var.pixclock;
clk_rate = min(clk_rate, mfd->panel_info.clk_max);
+ mipi_dsi_phy_ctrl(1);
+
+ if (mdp_rev == MDP_REV_42 && mipi_dsi_pdata)
+ target_type = mipi_dsi_pdata->target_type;
+
+ mipi_dsi_phy_init(0, &(mfd->panel_info), target_type);
+
+ local_bh_disable();
+ mipi_dsi_clk_enable();
+ local_bh_enable();
+
MIPI_OUTP(MIPI_DSI_BASE + 0x114, 1);
MIPI_OUTP(MIPI_DSI_BASE + 0x114, 0);
@@ -190,17 +201,6 @@
width = mfd->panel_info.xres;
height = mfd->panel_info.yres;
- mipi_dsi_phy_ctrl(1);
-
- if (mdp_rev == MDP_REV_42 && mipi_dsi_pdata)
- target_type = mipi_dsi_pdata->target_type;
-
- mipi_dsi_phy_init(0, &(mfd->panel_info), target_type);
-
- local_bh_disable();
- mipi_dsi_clk_enable();
- local_bh_enable();
-
mipi = &mfd->panel_info.mipi;
if (mfd->panel_info.type == MIPI_VIDEO_PANEL) {
dummy_xres = mfd->panel_info.lcdc.xres_pad;
diff --git a/include/sound/snd_compress_params.h b/include/sound/snd_compress_params.h
index e9f6748..f1e3ea2 100644
--- a/include/sound/snd_compress_params.h
+++ b/include/sound/snd_compress_params.h
@@ -72,6 +72,7 @@
#define SND_AUDIOCODEC_AC3 ((__u32) 0x0000000E)
#define SND_AUDIOCODEC_DTS ((__u32) 0x0000000F)
#define SND_AUDIOCODEC_AC3_PASS_THROUGH ((__u32) 0x00000010)
+#define SND_AUDIOCODEC_WMA_PRO ((__u32) 0x000000011)
/*
* Profile and modes are listed with bit masks. This allows for a
* more compact representation of fields that will not evolve
diff --git a/sound/soc/msm/msm-compr-q6.c b/sound/soc/msm/msm-compr-q6.c
index 776337d..68f218f 100644
--- a/sound/soc/msm/msm-compr-q6.c
+++ b/sound/soc/msm/msm-compr-q6.c
@@ -192,6 +192,7 @@
struct msm_audio *prtd = &compr->prtd;
struct asm_aac_cfg aac_cfg;
struct asm_wma_cfg wma_cfg;
+ struct asm_wmapro_cfg wma_pro_cfg;
int ret;
pr_debug("compressed stream prepare\n");
@@ -250,6 +251,26 @@
if (ret < 0)
pr_err("%s: CMD Format block failed\n", __func__);
break;
+ case SND_AUDIOCODEC_WMA_PRO:
+ pr_debug("SND_AUDIOCODEC_WMA_PRO\n");
+ memset(&wma_pro_cfg, 0x0, sizeof(struct asm_wmapro_cfg));
+ wma_pro_cfg.format_tag = compr->info.codec_param.codec.format;
+ wma_pro_cfg.ch_cfg = compr->info.codec_param.codec.ch_in;
+ wma_pro_cfg.sample_rate = runtime->rate;
+ wma_pro_cfg.avg_bytes_per_sec =
+ compr->info.codec_param.codec.bit_rate/8;
+ wma_pro_cfg.block_align = compr->info.codec_param.codec.align;
+ wma_pro_cfg.valid_bits_per_sample =
+ compr->info.codec_param.codec.options.wma.bits_per_sample;
+ wma_pro_cfg.ch_mask =
+ compr->info.codec_param.codec.options.wma.channelmask;
+ wma_pro_cfg.encode_opt =
+ compr->info.codec_param.codec.options.wma.encodeopt;
+ ret = q6asm_media_format_block_wmapro(prtd->audio_client,
+ &wma_pro_cfg);
+ if (ret < 0)
+ pr_err("%s: CMD Format block failed\n", __func__);
+ break;
default:
return -EINVAL;
}
@@ -316,6 +337,7 @@
compr->info.compr_cap.codecs[1] = SND_AUDIOCODEC_AAC;
compr->info.compr_cap.codecs[2] = SND_AUDIOCODEC_AC3_PASS_THROUGH;
compr->info.compr_cap.codecs[3] = SND_AUDIOCODEC_WMA;
+ compr->info.compr_cap.codecs[4] = SND_AUDIOCODEC_WMA_PRO;
/* Add new codecs here */
}
@@ -638,6 +660,10 @@
pr_debug("SND_AUDIOCODEC_WMA\n");
compr->codec = FORMAT_WMA_V9;
break;
+ case SND_AUDIOCODEC_WMA_PRO:
+ pr_debug("SND_AUDIOCODEC_WMA_PRO\n");
+ compr->codec = FORMAT_WMA_V10PRO;
+ break;
default:
pr_debug("FORMAT_LINEAR_PCM\n");
compr->codec = FORMAT_LINEAR_PCM;