Merge "msm: clock-local: Set 'auto_off' ops for PLL clocks" into msm-3.0
diff --git a/arch/arm/configs/msm8960_defconfig b/arch/arm/configs/msm8960_defconfig
index c869beb..235db63 100755
--- a/arch/arm/configs/msm8960_defconfig
+++ b/arch/arm/configs/msm8960_defconfig
@@ -355,6 +355,7 @@
CONFIG_LEDS_PM8XXX=y
# CONFIG_LEDS_MSM_PMIC is not set
CONFIG_LEDS_TRIGGERS=y
+CONFIG_LEDS_TRIGGER_HEARTBEAT=y
CONFIG_SWITCH=y
CONFIG_RTC_CLASS=y
# CONFIG_RTC_DRV_MSM is not set
diff --git a/arch/arm/mach-msm/board-apq8064.c b/arch/arm/mach-msm/board-apq8064.c
index 88ce818..0e30aee 100644
--- a/arch/arm/mach-msm/board-apq8064.c
+++ b/arch/arm/mach-msm/board-apq8064.c
@@ -482,6 +482,7 @@
}
static struct platform_device *common_devices[] __initdata = {
+ &apq8064_device_dmov,
&apq8064_device_qup_i2c_gsbi4,
&apq8064_device_qup_spi_gsbi5,
&apq8064_slim_ctrl,
@@ -498,7 +499,6 @@
};
static struct platform_device *sim_devices[] __initdata = {
- &apq8064_device_dmov,
&apq8064_device_uart_gsbi3,
&msm_device_sps_apq8064,
};
diff --git a/arch/arm/mach-msm/board-msm8960.c b/arch/arm/mach-msm/board-msm8960.c
index c264011..7448cc6 100644
--- a/arch/arm/mach-msm/board-msm8960.c
+++ b/arch/arm/mach-msm/board-msm8960.c
@@ -206,7 +206,6 @@
}
}
-#define FPGA_CS_GPIO 14
#define KS8851_RST_GPIO 89
#define KS8851_IRQ_GPIO 90
@@ -241,6 +240,18 @@
.pull = GPIOMUX_PULL_DOWN,
};
+static struct gpiomux_setting spi_active_config2 = {
+ .func = GPIOMUX_FUNC_2,
+ .drv = GPIOMUX_DRV_8MA,
+ .pull = GPIOMUX_PULL_NONE,
+};
+
+static struct gpiomux_setting spi_suspended_config2 = {
+ .func = GPIOMUX_FUNC_GPIO,
+ .drv = GPIOMUX_DRV_2MA,
+ .pull = GPIOMUX_PULL_UP,
+};
+
static struct gpiomux_setting gsbi3_suspended_cfg = {
.func = GPIOMUX_FUNC_1,
.drv = GPIOMUX_DRV_2MA,
@@ -320,12 +331,6 @@
[GPIOMUX_SUSPENDED] = &gpio_eth_config,
}
},
- {
- .gpio = FPGA_CS_GPIO,
- .settings = {
- [GPIOMUX_SUSPENDED] = &gpio_eth_config,
- }
- },
#endif
};
@@ -359,6 +364,13 @@
},
},
{
+ .gpio = 14, /* GSBI1 SPI_CS_1 */
+ .settings = {
+ [GPIOMUX_SUSPENDED] = &spi_suspended_config2,
+ [GPIOMUX_ACTIVE] = &spi_active_config2,
+ },
+ },
+ {
.gpio = 16, /* GSBI3 I2C QUP SDA */
.settings = {
[GPIOMUX_SUSPENDED] = &gsbi3_suspended_cfg,
@@ -1969,6 +1981,7 @@
}
};
+#define FPGA_3D_GPIO_CONFIG_ADDR 0xB5
static int dsi2lvds_gpio[2] = {
0,/* Backlight PWM-ID=0 for PMIC-GPIO#24 */
0x1F08 /* DSI2LVDS Bridge GPIO Output, mask=0x1f, out=0x08 */
@@ -1994,6 +2007,8 @@
};
static struct mipi_dsi_panel_platform_data novatek_pdata = {
+ .fpga_3d_config_addr = FPGA_3D_GPIO_CONFIG_ADDR,
+ .fpga_ctrl_mode = FPGA_SPI_INTF,
.phy_ctrl_settings = &dsi_novatek_cmd_mode_phy_db,
};
@@ -3605,6 +3620,13 @@
.mode = SPI_MODE_0,
.platform_data = &spi_eth_pdata
},
+ {
+ .modalias = "dsi_novatek_3d_panel_spi",
+ .max_speed_hz = 10800000,
+ .bus_num = 0,
+ .chip_select = 1,
+ .mode = SPI_MODE_0,
+ },
};
static struct platform_device msm_device_saw_core0 = {
@@ -4226,30 +4248,6 @@
},
};
-#if defined(CONFIG_KS8851) || defined(CONFIG_KS8851_MODULE)
-static int fpga_init(void)
-{
- int ret;
-
- ret = gpio_request(FPGA_CS_GPIO, "fpga_cs");
- if (ret) {
- pr_err("FPGA CS gpio_request failed: %d\n", ret);
- goto fail;
- }
-
- gpio_direction_output(FPGA_CS_GPIO, 1);
-
- return 0;
-fail:
- return ret;
-}
-#else
-static int fpga_init(void)
-{
- return 0;
-}
-#endif
-
static struct msm_cpuidle_state msm_cstates[] __initdata = {
{0, 0, "C0", "WFI",
MSM_PM_SLEEP_MODE_WAIT_FOR_INTERRUPT},
@@ -4638,8 +4636,6 @@
#endif
msm_device_hsic_host.dev.platform_data = &msm_hsic_pdata;
gpiomux_init();
- if (machine_is_msm8960_cdp())
- fpga_init();
if (machine_is_msm8960_liquid())
pm8921_platform_data.keypad_pdata = &keypad_data_liquid;
msm8960_device_qup_spi_gsbi1.dev.platform_data =
diff --git a/arch/arm/mach-msm/clock-9615.c b/arch/arm/mach-msm/clock-9615.c
index dca8268..d2a1df1 100644
--- a/arch/arm/mach-msm/clock-9615.c
+++ b/arch/arm/mach-msm/clock-9615.c
@@ -194,11 +194,10 @@
static int set_vdd_dig(struct clk_vdd_class *vdd_class, int level)
{
- /* TODO: Update these voltages when info becomes available. */
static const int vdd_uv[] = {
- [VDD_DIG_NONE] = 1150000,
- [VDD_DIG_LOW] = 1150000,
- [VDD_DIG_NOMINAL] = 1150000,
+ [VDD_DIG_NONE] = 0,
+ [VDD_DIG_LOW] = 945000,
+ [VDD_DIG_NOMINAL] = 1050000,
[VDD_DIG_HIGH] = 1150000
};
diff --git a/arch/arm/mach-msm/clock-debug.c b/arch/arm/mach-msm/clock-debug.c
index ab4d8c1..78586a8 100644
--- a/arch/arm/mach-msm/clock-debug.c
+++ b/arch/arm/mach-msm/clock-debug.c
@@ -141,9 +141,24 @@
return ret;
}
+
+static int clock_debug_print_clock(struct clk *c)
+{
+ size_t ln = 0;
+ char s[128];
+
+ if (!c || !c->count)
+ return 0;
+
+ ln += snprintf(s, sizeof(s), "\t%s", c->dbg_name);
+ while (ln < sizeof(s) && (c = clk_get_parent(c)))
+ ln += snprintf(s + ln, sizeof(s) - ln, " -> %s", c->dbg_name);
+ pr_info("%s\n", s);
+ return 1;
+}
+
void clock_debug_print_enabled(void)
{
- struct clk *clk;
unsigned i;
int cnt = 0;
@@ -151,14 +166,8 @@
return;
pr_info("Enabled clocks:\n");
- for (i = 0; i < num_msm_clocks; i++) {
- clk = msm_clocks[i].clk;
-
- if (clk && clk->ops->is_enabled && clk->ops->is_enabled(clk)) {
- pr_info("\t%s\n", clk->dbg_name);
- cnt++;
- }
- }
+ for (i = 0; i < num_msm_clocks; i++)
+ cnt += clock_debug_print_clock(msm_clocks[i].clk);
if (cnt)
pr_info("Enabled clock count: %d\n", cnt);
diff --git a/arch/arm/mach-msm/clock.c b/arch/arm/mach-msm/clock.c
index de89382..4f3ad95 100644
--- a/arch/arm/mach-msm/clock.c
+++ b/arch/arm/mach-msm/clock.c
@@ -230,12 +230,13 @@
}
EXPORT_SYMBOL(clk_get_rate);
-int clk_set_rate(struct clk *clk, unsigned long rate)
+static int _clk_set_rate(struct clk *clk, unsigned long rate,
+ int (*set_fn)(struct clk *, unsigned))
{
unsigned long start_rate, flags;
int rc;
- if (!clk->ops->set_rate)
+ if (!set_fn)
return -ENOSYS;
spin_lock_irqsave(&clk->lock, flags);
@@ -245,13 +246,13 @@
rc = vote_rate_vdd(clk, rate);
if (rc)
goto err_vote_vdd;
- rc = clk->ops->set_rate(clk, rate);
+ rc = set_fn(clk, rate);
if (rc)
goto err_set_rate;
/* Release vdd requirements for starting frequency. */
unvote_rate_vdd(clk, start_rate);
} else {
- rc = clk->ops->set_rate(clk, rate);
+ rc = set_fn(clk, rate);
}
spin_unlock_irqrestore(&clk->lock, flags);
return rc;
@@ -262,7 +263,6 @@
spin_unlock_irqrestore(&clk->lock, flags);
return rc;
}
-EXPORT_SYMBOL(clk_set_rate);
long clk_round_rate(struct clk *clk, unsigned long rate)
{
@@ -273,12 +273,15 @@
}
EXPORT_SYMBOL(clk_round_rate);
+int clk_set_rate(struct clk *clk, unsigned long rate)
+{
+ return _clk_set_rate(clk, rate, clk->ops->set_rate);
+}
+EXPORT_SYMBOL(clk_set_rate);
+
int clk_set_min_rate(struct clk *clk, unsigned long rate)
{
- if (!clk->ops->set_min_rate)
- return -ENOSYS;
-
- return clk->ops->set_min_rate(clk, rate);
+ return _clk_set_rate(clk, rate, clk->ops->set_min_rate);
}
EXPORT_SYMBOL(clk_set_min_rate);
diff --git a/arch/arm/mach-msm/devices-8064.c b/arch/arm/mach-msm/devices-8064.c
index 35a69df..f1a0404 100644
--- a/arch/arm/mach-msm/devices-8064.c
+++ b/arch/arm/mach-msm/devices-8064.c
@@ -664,8 +664,8 @@
CLK_DUMMY("iface_clk", SDC2_P_CLK, NULL, OFF),
CLK_DUMMY("iface_clk", SDC3_P_CLK, NULL, OFF),
CLK_DUMMY("iface_clk", SDC4_P_CLK, NULL, OFF),
- CLK_DUMMY("core_clk", ADM0_CLK, NULL, OFF),
- CLK_DUMMY("iface_clk", ADM0_P_CLK, NULL, OFF),
+ CLK_DUMMY("core_clk", ADM0_CLK, "msm_dmov", OFF),
+ CLK_DUMMY("iface_clk", ADM0_P_CLK, "msm_dmov", OFF),
CLK_DUMMY("iface_clk", PMIC_ARB0_P_CLK, NULL, OFF),
CLK_DUMMY("iface_clk", PMIC_ARB1_P_CLK, NULL, OFF),
CLK_DUMMY("core_clk", PMIC_SSBI2_CLK, NULL, OFF),
@@ -760,6 +760,7 @@
CLK_DUMMY("bus_clk", DFAB_SDC4_CLK, NULL, 0),
CLK_DUMMY("dfab_clk", DFAB_CLK, NULL, 0),
CLK_DUMMY("dma_bam_pclk", DMA_BAM_P_CLK, NULL, 0),
+ CLK_DUMMY("mem_clk", EBI1_ADM_CLK, "msm_dmov", 0),
};
struct clock_init_data apq8064_dummy_clock_init_data __initdata = {
diff --git a/arch/arm/mach-msm/devices-8960.c b/arch/arm/mach-msm/devices-8960.c
index ba36f69..4e047c5 100644
--- a/arch/arm/mach-msm/devices-8960.c
+++ b/arch/arm/mach-msm/devices-8960.c
@@ -1134,6 +1134,12 @@
.flags = IORESOURCE_IO,
},
{
+ .name = "spi_cs1",
+ .start = 14,
+ .end = 14,
+ .flags = IORESOURCE_IO,
+ },
+ {
.name = "spi_miso",
.start = 7,
.end = 7,
diff --git a/arch/arm/mach-msm/include/mach/iommu_domains.h b/arch/arm/mach-msm/include/mach/iommu_domains.h
index 8ae3b72..28e98de 100644
--- a/arch/arm/mach-msm/include/mach/iommu_domains.h
+++ b/arch/arm/mach-msm/include/mach/iommu_domains.h
@@ -13,26 +13,67 @@
#ifndef _ARCH_IOMMU_DOMAINS_H
#define _ARCH_IOMMU_DOMAINS_H
-/*
- * Nothing in this file is to be used outside of the iommu wrappers.
- * Do NOT try and use anything here in a driver. Doing so is incorrect.
- */
+enum {
+ GLOBAL_DOMAIN,
+ MAX_DOMAINS
+};
-/*
- * These subsytem ids are NOT for public use. Please check the iommu
- * wrapper header for the properly abstracted id to pass in.
- */
+enum {
+ VIDEO_FIRMWARE_POOL,
+ LOW_256MB_POOL,
+ HIGH_POOL,
+};
+
#if defined(CONFIG_MSM_IOMMU)
-extern struct iommu_domain *msm_subsystem_get_domain(int subsys_id);
-extern struct mem_pool *msm_subsystem_get_pool(int subsys_id);
+extern struct iommu_domain *msm_get_iommu_domain(int domain_num);
+
+extern unsigned long msm_allocate_iova_address(unsigned int iommu_domain,
+ unsigned int partition_no,
+ unsigned long size,
+ unsigned long align);
+
+extern void msm_free_iova_address(unsigned long iova,
+ unsigned int iommu_domain,
+ unsigned int partition_no,
+ unsigned long size);
+
+extern unsigned long msm_subsystem_get_domain_no(int subsys_id);
+
+extern unsigned long msm_subsystem_get_partition_no(int subsys_id);
+
+extern int msm_use_iommu(void);
#else
static inline struct iommu_domain
- *msm_subsystem_get_domain(int subsys_id) { return NULL; }
+ *msm_get_iommu_domain(int subsys_id) { return NULL; }
-static inline struct mem_pool
- *msm_subsystem_get_pool(int subsys_id) { return NULL; }
+
+
+static inline unsigned long msm_allocate_iova_address(unsigned int iommu_domain,
+ unsigned int partition_no,
+ unsigned long size,
+ unsigned long align) { return 0; }
+
+static inline void msm_free_iova_address(unsigned long iova,
+ unsigned int iommu_domain,
+ unsigned int partition_no,
+ unsigned long size) { return; }
+
+static inline unsigned long msm_subsystem_get_domain_no(int subsys_id)
+{
+ return 0xFFFFFFFF;
+}
+
+static inline unsigned long msm_subsystem_get_partition_no(int subsys_id)
+{
+ return 0xFFFFFFFF;
+}
+
+static inline int msm_use_iommu(void)
+{
+ return 0;
+}
#endif
#endif
diff --git a/arch/arm/mach-msm/iommu_domains.c b/arch/arm/mach-msm/iommu_domains.c
index 290ba33..e849cdb 100644
--- a/arch/arm/mach-msm/iommu_domains.c
+++ b/arch/arm/mach-msm/iommu_domains.c
@@ -18,24 +18,23 @@
#include <linux/init.h>
#include <mach/iommu.h>
#include <mach/iommu_domains.h>
+#include <mach/socinfo.h>
struct msm_iommu_domain {
- int domain_idx;
- int iova_pool_idx;
+ /* iommu domain to map in */
+ struct iommu_domain *domain;
+ /* total number of allocations from this domain */
+ atomic_t allocation_cnt;
+ /* number of iova pools */
+ int npools;
+ /*
+ * array of gen_pools for allocating iovas.
+ * behavior is undefined if these overlap
+ */
+ struct mem_pool *iova_pools;
+
};
-enum {
- GLOBAL_DOMAIN,
- VIDEO_DOMAIN,
- EMPTY_DOMAIN,
- MAX_DOMAINS
-};
-
-enum {
- GLOBAL_MEMORY_POOL,
- VIDEO_FIRMWARE_POOL,
- VIDEO_ALLOC_POOL,
-};
struct {
char *name;
@@ -114,114 +113,175 @@
/* Video */
{
.name = "vcodec_a_mm1",
- .domain = VIDEO_DOMAIN,
+ .domain = GLOBAL_DOMAIN,
},
/* Video */
{
.name = "vcodec_b_mm2",
- .domain = VIDEO_DOMAIN,
+ .domain = GLOBAL_DOMAIN,
},
/* Video */
{
.name = "vcodec_a_stream",
- .domain = VIDEO_DOMAIN,
+ .domain = GLOBAL_DOMAIN,
},
};
-static struct iommu_domain *msm_iommu_domains[MAX_DOMAINS];
-
-static struct mem_pool msm_iommu_iova_pools[] = {
- [GLOBAL_MEMORY_POOL] = {
- .paddr = SZ_4K,
- .size = SZ_2G - SZ_4K,
- },
+static struct mem_pool global_pools[] = {
+ [VIDEO_FIRMWARE_POOL] =
+ /* Low addresses, intended for video firmware */
+ {
+ .paddr = SZ_128K,
+ .size = SZ_16M - SZ_128K,
+ },
+ [LOW_256MB_POOL] =
/*
- * The video hardware has several constraints:
- * 1) The start address for firmware must be 128K aligned
- * 2) The video firmware must exist at a lower address than
- * all other video allocations
- * 3) Video allocations cannot be more than 256MB away from the
- * firmware
- *
- * Splitting the video pools makes sure that firmware will
- * always be lower than regular allocations and the maximum
- * size of 256MB will be enforced.
+ * Video can only access first 256MB of memory
+ * dedicated pool for such allocations
*/
- [VIDEO_FIRMWARE_POOL] = {
- .paddr = SZ_128K,
- .size = SZ_16M - SZ_128K,
- },
- [VIDEO_ALLOC_POOL] = {
- .paddr = SZ_16M,
- .size = SZ_256M - SZ_16M - SZ_128K,
+ {
+ .paddr = SZ_16M,
+ .size = SZ_256M - SZ_16M,
+ },
+ [HIGH_POOL] =
+ /* Remaining address space up to 2G */
+ {
+ .paddr = SZ_256M,
+ .size = SZ_2G - SZ_256M,
+ }
+};
+
+
+static struct msm_iommu_domain msm_iommu_domains[] = {
+ [GLOBAL_DOMAIN] = {
+ .iova_pools = global_pools,
+ .npools = ARRAY_SIZE(global_pools),
}
};
-static struct msm_iommu_domain msm_iommu_subsystems[] = {
- [MSM_SUBSYSTEM_VIDEO] = {
- .domain_idx = VIDEO_DOMAIN,
- .iova_pool_idx = VIDEO_ALLOC_POOL,
- },
- [MSM_SUBSYSTEM_VIDEO_FWARE] = {
- .domain_idx = VIDEO_DOMAIN,
- .iova_pool_idx = VIDEO_FIRMWARE_POOL,
- },
- [MSM_SUBSYSTEM_CAMERA] = {
- .domain_idx = GLOBAL_DOMAIN,
- .iova_pool_idx = GLOBAL_MEMORY_POOL,
- },
- [MSM_SUBSYSTEM_DISPLAY] = {
- .domain_idx = GLOBAL_DOMAIN,
- .iova_pool_idx = GLOBAL_MEMORY_POOL,
- },
- [MSM_SUBSYSTEM_ROTATOR] = {
- .domain_idx = GLOBAL_DOMAIN,
- .iova_pool_idx = GLOBAL_MEMORY_POOL,
- },
-};
-
-struct iommu_domain *msm_subsystem_get_domain(int subsys_id)
+struct iommu_domain *msm_get_iommu_domain(int domain_num)
{
- int id = msm_iommu_subsystems[subsys_id].domain_idx;
-
- return msm_iommu_domains[id];
+ if (domain_num >= 0 && domain_num < MAX_DOMAINS)
+ return msm_iommu_domains[domain_num].domain;
+ else
+ return NULL;
}
-struct mem_pool *msm_subsystem_get_pool(int subsys_id)
+unsigned long msm_subsystem_get_domain_no(int subsys_id)
{
- int id = msm_iommu_subsystems[subsys_id].iova_pool_idx;
+ return GLOBAL_DOMAIN;
+}
- return &msm_iommu_iova_pools[id];
+unsigned long msm_subsystem_get_partition_no(int subsys_id)
+{
+ switch (subsys_id) {
+ case MSM_SUBSYSTEM_VIDEO_FWARE:
+ return VIDEO_FIRMWARE_POOL;
+ case MSM_SUBSYSTEM_VIDEO:
+ return LOW_256MB_POOL;
+ case MSM_SUBSYSTEM_CAMERA:
+ case MSM_SUBSYSTEM_DISPLAY:
+ case MSM_SUBSYSTEM_ROTATOR:
+ return HIGH_POOL;
+ default:
+ return 0xFFFFFFFF;
+ }
+}
+
+unsigned long msm_allocate_iova_address(unsigned int iommu_domain,
+ unsigned int partition_no,
+ unsigned long size,
+ unsigned long align)
+{
+ struct mem_pool *pool;
+ unsigned long iova;
+
+ if (iommu_domain >= MAX_DOMAINS)
+ return 0;
+
+ if (partition_no >= msm_iommu_domains[iommu_domain].npools)
+ return 0;
+
+ pool = &msm_iommu_domains[iommu_domain].iova_pools[partition_no];
+
+ if (!pool->gpool)
+ return 0;
+
+ iova = gen_pool_alloc_aligned(pool->gpool, size, ilog2(align));
+ if (iova)
+ pool->free -= size;
+
+ return iova;
+}
+
+void msm_free_iova_address(unsigned long iova,
+ unsigned int iommu_domain,
+ unsigned int partition_no,
+ unsigned long size)
+{
+ struct mem_pool *pool;
+
+ if (iommu_domain >= MAX_DOMAINS) {
+ WARN(1, "Invalid domain %d\n", iommu_domain);
+ return;
+ }
+
+ if (partition_no >= msm_iommu_domains[iommu_domain].npools) {
+ WARN(1, "Invalid partition %d for domain %d\n",
+ partition_no, iommu_domain);
+ return;
+ }
+
+ pool = &msm_iommu_domains[iommu_domain].iova_pools[partition_no];
+
+ if (!pool)
+ return;
+
+ pool->free += size;
+ gen_pool_free(pool->gpool, iova, size);
+}
+
+int msm_use_iommu()
+{
+ /*
+ * For now, just detect if the iommu is attached.
+ */
+ return iommu_found();
}
static int __init msm_subsystem_iommu_init(void)
{
- int i;
+ int i, j;
- for (i = 0; i < (ARRAY_SIZE(msm_iommu_domains) - 1); i++)
- msm_iommu_domains[i] = iommu_domain_alloc(0);
-
- for (i = 0; i < ARRAY_SIZE(msm_iommu_iova_pools); i++) {
- mutex_init(&msm_iommu_iova_pools[i].pool_mutex);
- msm_iommu_iova_pools[i].gpool = gen_pool_create(PAGE_SHIFT, -1);
-
- if (!msm_iommu_iova_pools[i].gpool) {
- pr_err("%s: could not allocate iova pool. iommu"
- " programming will not work with iova space"
- " %d\n", __func__, i);
+ for (i = 0; i < ARRAY_SIZE(msm_iommu_domains); i++) {
+ msm_iommu_domains[i].domain = iommu_domain_alloc(0);
+ if (!msm_iommu_domains[i].domain)
continue;
- }
- if (gen_pool_add(msm_iommu_iova_pools[i].gpool,
- msm_iommu_iova_pools[i].paddr,
- msm_iommu_iova_pools[i].size,
- -1)) {
- pr_err("%s: could not add memory to iova pool. iommu"
- " programming will not work with iova space"
- " %d\n", __func__, i);
- gen_pool_destroy(msm_iommu_iova_pools[i].gpool);
- msm_iommu_iova_pools[i].gpool = NULL;
- continue;
+ for (j = 0; j < msm_iommu_domains[i].npools; j++) {
+ struct mem_pool *pool = &msm_iommu_domains[i].
+ iova_pools[j];
+ mutex_init(&pool->pool_mutex);
+ pool->gpool = gen_pool_create(PAGE_SHIFT, -1);
+
+ if (!pool->gpool) {
+ pr_err("%s: domain %d: could not allocate iova"
+ " pool. iommu programming will not work"
+ " with iova space %d\n", __func__,
+ i, j);
+ continue;
+ }
+
+ if (gen_pool_add(pool->gpool, pool->paddr, pool->size,
+ -1)) {
+ pr_err("%s: domain %d: could not add memory to"
+ " iova pool. iommu programming will not"
+ " work with iova space %d\n", __func__,
+ i, j);
+ gen_pool_destroy(pool->gpool);
+ pool->gpool = NULL;
+ continue;
+ }
}
}
@@ -235,15 +295,15 @@
domain_idx = msm_iommu_ctx_names[i].domain;
- if (!msm_iommu_domains[domain_idx])
+ if (!msm_iommu_domains[domain_idx].domain)
continue;
- if (iommu_attach_device(msm_iommu_domains[domain_idx], ctx)) {
- pr_err("%s: could not attach domain %d to context %s."
+ if (iommu_attach_device(msm_iommu_domains[domain_idx].domain,
+ ctx)) {
+ WARN(1, "%s: could not attach domain %d to context %s."
" iommu programming will not occur.\n",
__func__, domain_idx,
msm_iommu_ctx_names[i].name);
- msm_iommu_subsystems[i].domain_idx = EMPTY_DOMAIN;
continue;
}
}
diff --git a/arch/arm/mach-msm/mdm.c b/arch/arm/mach-msm/mdm.c
index 9fa1a4a..01cc48a 100644
--- a/arch/arm/mach-msm/mdm.c
+++ b/arch/arm/mach-msm/mdm.c
@@ -119,6 +119,9 @@
CHARM_DBG("%s: setting AP2MDM_ERRFATAL high for a non graceful reset\n",
__func__);
+ if (get_restart_level() == RESET_SOC)
+ pm8058_stay_on();
+
charm_disable_irqs();
gpio_set_value(AP2MDM_ERRFATAL, 1);
gpio_set_value(AP2MDM_WAKEUP, 1);
diff --git a/arch/arm/mach-msm/msm_bus/msm_bus_arb.c b/arch/arm/mach-msm/msm_bus/msm_bus_arb.c
index 56bc71d..7b9a16e 100644
--- a/arch/arm/mach-msm/msm_bus/msm_bus_arb.c
+++ b/arch/arm/mach-msm/msm_bus/msm_bus_arb.c
@@ -412,8 +412,16 @@
struct msm_bus_client *client = NULL;
int i;
int src, dest, nfab;
+ struct msm_bus_fabric_device *deffab;
+
+ deffab = msm_bus_get_fabric_device(MSM_BUS_FAB_DEFAULT);
+ if (!deffab) {
+ MSM_BUS_ERR("Error finding default fabric\n");
+ return -ENXIO;
+ }
+
nfab = msm_bus_get_num_fab();
- if (nfab < NUM_FAB) {
+ if (nfab < deffab->board_algo->board_nfab) {
MSM_BUS_ERR("Can't register client!\n"
"Num of fabrics up: %d\n",
nfab);
diff --git a/arch/arm/mach-msm/msm_bus/msm_bus_board_8660.c b/arch/arm/mach-msm/msm_bus/msm_bus_board_8660.c
index fde2322..ff2876c 100644
--- a/arch/arm/mach-msm/msm_bus/msm_bus_board_8660.c
+++ b/arch/arm/mach-msm/msm_bus/msm_bus_board_8660.c
@@ -23,6 +23,7 @@
#define NMASTERS 39
#define NSLAVES 67
+#define NFAB_8660 5
enum msm_bus_fabric_tiered_slave_type {
MSM_BUS_SYSTEM_TIERED_SLAVE_FAB_APPSS = 1,
@@ -830,6 +831,7 @@
}
static struct msm_bus_board_algorithm msm_bus_board_algo = {
+ .board_nfab = NFAB_8660,
.get_iid = msm_bus_board_8660_get_iid,
.assign_iids = msm_bus_board_assign_iids,
};
diff --git a/arch/arm/mach-msm/msm_bus/msm_bus_board_8960.c b/arch/arm/mach-msm/msm_bus/msm_bus_board_8960.c
index 47f3c81..1dda082 100644
--- a/arch/arm/mach-msm/msm_bus/msm_bus_board_8960.c
+++ b/arch/arm/mach-msm/msm_bus/msm_bus_board_8960.c
@@ -23,6 +23,7 @@
#define NMASTERS 45
#define NSLAVES 75
+#define NFAB_8960 5
enum msm_bus_fabric_tiered_slave_type {
MSM_BUS_SYSTEM_TIERED_SLAVE_FAB_APPSS_0 = 1,
@@ -863,6 +864,7 @@
}
static struct msm_bus_board_algorithm msm_bus_board_algo = {
+ .board_nfab = NFAB_8960,
.get_iid = msm_bus_board_8960_get_iid,
.assign_iids = msm_bus_board_assign_iids,
};
diff --git a/arch/arm/mach-msm/msm_bus/msm_bus_core.h b/arch/arm/mach-msm/msm_bus/msm_bus_core.h
index 8a46026..c4c01e8 100644
--- a/arch/arm/mach-msm/msm_bus/msm_bus_core.h
+++ b/arch/arm/mach-msm/msm_bus/msm_bus_core.h
@@ -134,6 +134,7 @@
};
struct msm_bus_board_algorithm {
+ const int board_nfab;
void (*assign_iids)(struct msm_bus_fabric_registration *fabreg,
int fabid);
int (*get_iid)(int id);
diff --git a/arch/arm/mach-msm/qdsp6v2/pcm_out.c b/arch/arm/mach-msm/qdsp6v2/pcm_out.c
index 75975cc..a4a6b72 100644
--- a/arch/arm/mach-msm/qdsp6v2/pcm_out.c
+++ b/arch/arm/mach-msm/qdsp6v2/pcm_out.c
@@ -380,7 +380,7 @@
while (count > 0) {
rc = wait_event_timeout(pcm->write_wait,
(atomic_read(&pcm->out_count) ||
- atomic_read(&pcm->out_stopped)), 5 * HZ);
+ atomic_read(&pcm->out_stopped)), 1 * HZ);
if (!rc) {
pr_err("%s: wait_event_timeout failed for session %d\n",
__func__, pcm->ac->session);
diff --git a/arch/arm/mach-msm/subsystem_map.c b/arch/arm/mach-msm/subsystem_map.c
index 41d8072..11fe26c 100644
--- a/arch/arm/mach-msm/subsystem_map.c
+++ b/arch/arm/mach-msm/subsystem_map.c
@@ -208,58 +208,18 @@
return 0;
}
-static unsigned long allocate_iova_address(unsigned long size,
- int subsys_id,
- unsigned long align)
-{
- struct mem_pool *pool = msm_subsystem_get_pool(subsys_id);
- unsigned long iova;
-
- iova = gen_pool_alloc_aligned(pool->gpool, size, ilog2(align));
- if (iova)
- pool->free -= size;
-
- return iova;
-}
-
-static void free_iova_address(unsigned long iova,
- unsigned long size,
- int subsys_id)
-{
- struct mem_pool *pool = msm_subsystem_get_pool(subsys_id);
-
- pool->free += size;
- gen_pool_free(pool->gpool, iova, size);
-}
-
-static int subsys_validate(int subsys_id)
-{
- struct mem_pool *pool;
- struct iommu_domain *subsys_domain;
-
- if (!msm_subsystem_check_id(subsys_id)) {
- WARN(1, "subsystem id is not valid. Caller should check this.");
- return 0;
- }
-
- pool = msm_subsystem_get_pool(subsys_id);
- subsys_domain = msm_subsystem_get_domain(subsys_id);
-
- return subsys_domain && pool && pool->gpool;
-}
-
phys_addr_t msm_subsystem_check_iova_mapping(int subsys_id, unsigned long iova)
{
struct iommu_domain *subsys_domain;
- if (!subsys_validate(subsys_id))
+ if (!msm_use_iommu())
/*
- * If the subsystem is not valid, assume a phys = iova
- * mapping. Just return the iova in this case.
+ * If there is no iommu, Just return the iova in this case.
*/
return iova;
- subsys_domain = msm_subsystem_get_domain(subsys_id);
+ subsys_domain = msm_get_iommu_domain(msm_subsystem_get_domain_no
+ (subsys_id));
return iommu_iova_to_phys(subsys_domain, iova);
}
@@ -355,15 +315,29 @@
min_align = flags & ~(SZ_4K - 1);
for (i = 0; i < nsubsys; i++) {
- if (!subsys_validate(subsys_ids[i])) {
+ unsigned int domain_no, partition_no;
+
+ if (!msm_use_iommu()) {
buf->iova[i] = phys;
continue;
}
- d = msm_subsystem_get_domain(subsys_ids[i]);
+ d = msm_get_iommu_domain(
+ msm_subsystem_get_domain_no(subsys_ids[i]));
- iova_start = allocate_iova_address(length,
- subsys_ids[i],
+ if (!d) {
+ pr_err("%s: could not get domain for subsystem"
+ " %d\n", __func__, subsys_ids[i]);
+ continue;
+ }
+
+ domain_no = msm_subsystem_get_domain_no(subsys_ids[i]);
+ partition_no = msm_subsystem_get_partition_no(
+ subsys_ids[i]);
+
+ iova_start = msm_allocate_iova_address(domain_no,
+ partition_no,
+ length,
max(min_align, SZ_4K));
if (!iova_start) {
@@ -410,19 +384,26 @@
iommu_unmap(d, temp_va, get_order(SZ_4K));
outdomain:
if (flags & MSM_SUBSYSTEM_MAP_IOVA) {
+ /* Unmap the rest of the current domain, i */
for (j -= SZ_4K, temp_va -= SZ_4K;
j > 0; temp_va -= SZ_4K, j -= SZ_4K)
iommu_unmap(d, temp_va, get_order(SZ_4K));
+ /* Unmap all the other domains */
for (i--; i >= 0; i--) {
- if (!subsys_validate(subsys_ids[i]))
+ unsigned int domain_no, partition_no;
+ if (!msm_use_iommu())
continue;
+ domain_no = msm_subsystem_get_domain_no(subsys_ids[i]);
+ partition_no = msm_subsystem_get_partition_no(
+ subsys_ids[i]);
temp_va = buf->iova[i];
for (j = length; j > 0; j -= SZ_4K,
temp_va += SZ_4K)
iommu_unmap(d, temp_va, get_order(SZ_4K));
- free_iova_address(buf->iova[i], length, subsys_ids[i]);
+ msm_free_iova_address(buf->iova[i], domain_no,
+ partition_no, length);
}
kfree(buf->iova);
@@ -464,25 +445,32 @@
}
if (buf->iova) {
- for (i = 0; i < node->nsubsys; i++) {
- struct iommu_domain *subsys_domain;
+ if (msm_use_iommu())
+ for (i = 0; i < node->nsubsys; i++) {
+ struct iommu_domain *subsys_domain;
+ unsigned int domain_no, partition_no;
- if (!subsys_validate(node->subsystems[i]))
- continue;
+ subsys_domain = msm_get_iommu_domain(
+ msm_subsystem_get_domain_no(
+ node->subsystems[i]));
- subsys_domain = msm_subsystem_get_domain(
+ domain_no = msm_subsystem_get_domain_no(
node->subsystems[i]);
- temp_va = buf->iova[i];
- for (j = node->length; j > 0; j -= SZ_4K,
- temp_va += SZ_4K) {
- ret = iommu_unmap(subsys_domain, temp_va,
+ partition_no = msm_subsystem_get_partition_no(
+ node->subsystems[i]);
+
+ temp_va = buf->iova[i];
+ for (j = node->length; j > 0; j -= SZ_4K,
+ temp_va += SZ_4K) {
+ ret = iommu_unmap(subsys_domain,
+ temp_va,
get_order(SZ_4K));
- WARN(ret, "iommu_unmap returned a non-zero"
- " value.\n");
+ WARN(ret, "iommu_unmap returned a "
+ " non-zero value.\n");
+ }
+ msm_free_iova_address(buf->iova[i], domain_no,
+ partition_no, node->length);
}
- free_iova_address(buf->iova[i], node->length,
- node->subsystems[i]);
- }
kfree(buf->iova);
}
diff --git a/drivers/media/radio/radio-iris-transport.c b/drivers/media/radio/radio-iris-transport.c
index 6628c9d..50ca58c 100644
--- a/drivers/media/radio/radio-iris-transport.c
+++ b/drivers/media/radio/radio-iris-transport.c
@@ -51,13 +51,13 @@
len = smd_read_avail(hsmd->fm_channel);
while (len) {
- skb = alloc_skb(len, GFP_KERNEL);
+ skb = alloc_skb(len, GFP_ATOMIC);
if (!skb) {
FMDERR("Memory not allocated for the socket");
return;
}
- buf = kmalloc(len, GFP_KERNEL);
+ buf = kmalloc(len, GFP_ATOMIC);
if (!buf) {
kfree_skb(skb);
FMDERR("Error in allocating buffer memory");
diff --git a/drivers/mmc/host/msm_sdcc.c b/drivers/mmc/host/msm_sdcc.c
index 6181758..ce13d27 100644
--- a/drivers/mmc/host/msm_sdcc.c
+++ b/drivers/mmc/host/msm_sdcc.c
@@ -1024,8 +1024,6 @@
if (data->flags & MMC_DATA_READ)
datactrl |= (MCI_DPSM_DIRECTION | MCI_RX_DATA_PEND);
- else if (data->flags & MMC_DATA_WRITE)
- datactrl |= MCI_DATA_PEND;
clks = (unsigned long long)data->timeout_ns * host->clk_rate;
do_div(clks, 1000000000UL);
@@ -1364,6 +1362,9 @@
msmsdcc_start_command(host, host->curr.mrq->cmd, 0);
else
msmsdcc_request_start(host, host->curr.mrq);
+ } else if (cmd->data) {
+ if (!(cmd->data->flags & MMC_DATA_READ))
+ msmsdcc_start_data(host, cmd->data, NULL, 0);
}
}
@@ -1570,9 +1571,9 @@
static void
msmsdcc_request_start(struct msmsdcc_host *host, struct mmc_request *mrq)
{
- if (mrq->data) {
+ if (mrq->data && mrq->data->flags & MMC_DATA_READ) {
/* Queue/read data, daisy-chain command when data starts */
- if (mrq->sbc && (mrq->data->flags & MMC_DATA_READ))
+ if (mrq->sbc)
msmsdcc_start_data(host, mrq->data, mrq->sbc, 0);
else
msmsdcc_start_data(host, mrq->data, mrq->cmd, 0);
diff --git a/drivers/mmc/host/msm_sdcc.h b/drivers/mmc/host/msm_sdcc.h
index 590c293..12aa54b 100644
--- a/drivers/mmc/host/msm_sdcc.h
+++ b/drivers/mmc/host/msm_sdcc.h
@@ -77,7 +77,6 @@
#define MCI_DPSM_DIRECTION (1 << 1)
#define MCI_DPSM_MODE (1 << 2)
#define MCI_DPSM_DMAENABLE (1 << 3)
-#define MCI_DATA_PEND (1 << 17)
#define MCI_AUTO_PROG_DONE (1 << 19)
#define MCI_RX_DATA_PEND (1 << 20)
diff --git a/drivers/power/isl9519q.c b/drivers/power/isl9519q.c
index 733de45..e4729f2 100644
--- a/drivers/power/isl9519q.c
+++ b/drivers/power/isl9519q.c
@@ -60,6 +60,8 @@
bool trickle;
};
+static struct isl9519q_struct *the_isl_chg;
+
static int isl9519q_read_reg(struct i2c_client *client, int reg,
u16 *val)
{
@@ -485,6 +487,71 @@
return 0;
}
+static int set_reg(void *data, u64 val)
+{
+ int addr = (int)data;
+ int ret;
+ u16 temp;
+
+ temp = (u16) val;
+ ret = isl9519q_write_reg(the_isl_chg->client, addr, temp);
+
+ if (ret) {
+ pr_err("isl9519q_write_reg to %x value =%d errored = %d\n",
+ addr, temp, ret);
+ return -EAGAIN;
+ }
+ return 0;
+}
+static int get_reg(void *data, u64 *val)
+{
+ int addr = (int)data;
+ int ret;
+ u16 temp;
+
+ ret = isl9519q_read_reg(the_isl_chg->client, addr, &temp);
+ if (ret) {
+ pr_err("isl9519q_read_reg to %x value =%d errored = %d\n",
+ addr, temp, ret);
+ return -EAGAIN;
+ }
+
+ *val = temp;
+ return 0;
+}
+
+DEFINE_SIMPLE_ATTRIBUTE(reg_fops, get_reg, set_reg, "0x%02llx\n");
+
+static void create_debugfs_entries(struct isl9519q_struct *isl_chg)
+{
+ isl_chg->dent = debugfs_create_dir("isl9519q", NULL);
+
+ if (IS_ERR(isl_chg->dent)) {
+ pr_err("isl9519q driver couldn't create debugfs dir\n");
+ return;
+ }
+
+ debugfs_create_file("CHG_CURRENT_REG", 0644, isl_chg->dent,
+ (void *) CHG_CURRENT_REG, ®_fops);
+ debugfs_create_file("MAX_SYS_VOLTAGE_REG", 0644, isl_chg->dent,
+ (void *) MAX_SYS_VOLTAGE_REG, ®_fops);
+ debugfs_create_file("CONTROL_REG", 0644, isl_chg->dent,
+ (void *) CONTROL_REG, ®_fops);
+ debugfs_create_file("MIN_SYS_VOLTAGE_REG", 0644, isl_chg->dent,
+ (void *) MIN_SYS_VOLTAGE_REG, ®_fops);
+ debugfs_create_file("INPUT_CURRENT_REG", 0644, isl_chg->dent,
+ (void *) INPUT_CURRENT_REG, ®_fops);
+ debugfs_create_file("MANUFACTURER_ID_REG", 0644, isl_chg->dent,
+ (void *) MANUFACTURER_ID_REG, ®_fops);
+ debugfs_create_file("DEVICE_ID_REG", 0644, isl_chg->dent,
+ (void *) DEVICE_ID_REG, ®_fops);
+}
+
+static void remove_debugfs_entries(struct isl9519q_struct *isl_chg)
+{
+ if (isl_chg->dent)
+ debugfs_remove_recursive(isl_chg->dent);
+}
static int __devinit isl9519q_probe(struct i2c_client *client,
const struct i2c_device_id *id)
@@ -582,6 +649,9 @@
if (ret)
goto free_isl_chg;
+ the_isl_chg = isl_chg;
+ create_debugfs_entries(isl_chg);
+
pr_info("%s OK.\n", __func__);
return 0;
@@ -603,6 +673,9 @@
cancel_delayed_work_sync(&isl_chg->charge_work);
msm_charger_notify_event(&isl_chg->adapter_hw_chg, CHG_REMOVED_EVENT);
msm_charger_unregister(&isl_chg->adapter_hw_chg);
+ remove_debugfs_entries(isl_chg);
+ the_isl_chg = NULL;
+ kfree(isl_chg);
return 0;
}
diff --git a/drivers/usb/host/ehci-msm-hsic.c b/drivers/usb/host/ehci-msm-hsic.c
index 093a170..350f286 100644
--- a/drivers/usb/host/ehci-msm-hsic.c
+++ b/drivers/usb/host/ehci-msm-hsic.c
@@ -65,9 +65,10 @@
#define ULPI_IO_TIMEOUT_USEC (10 * 1000)
-#define USB_PHY_VDD_DIG_VOL_MIN 1000000 /* uV */
-#define USB_PHY_VDD_DIG_VOL_MAX 1320000 /* uV */
-#define USB_PHY_VDD_DIG_LOAD 49360 /* uA */
+#define USB_PHY_VDD_DIG_VOL_SUSP_MIN 500000 /* uV */
+#define USB_PHY_VDD_DIG_VOL_MIN 1000000 /* uV */
+#define USB_PHY_VDD_DIG_VOL_MAX 1320000 /* uV */
+#define USB_PHY_VDD_DIG_LOAD 49360 /* uA */
static int msm_hsic_init_vddcx(struct msm_hsic_hcd *mehci, int init)
{
@@ -431,6 +432,12 @@
"TCXO D1 buffer%d\n", __func__, ret);
}
+ ret = regulator_set_voltage(mehci->hsic_vddcx,
+ USB_PHY_VDD_DIG_VOL_SUSP_MIN,
+ USB_PHY_VDD_DIG_VOL_MAX);
+ if (ret < 0)
+ dev_err(mehci->dev, "unable to set vddcx voltage: min:0.5v max:1.3v\n");
+
atomic_set(&mehci->in_lpm, 1);
enable_irq(hcd->irq);
wake_unlock(&mehci->wlock);
@@ -454,6 +461,12 @@
wake_lock(&mehci->wlock);
+ ret = regulator_set_voltage(mehci->hsic_vddcx,
+ USB_PHY_VDD_DIG_VOL_MIN,
+ USB_PHY_VDD_DIG_VOL_MAX);
+ if (ret < 0)
+ dev_err(mehci->dev, "unable to set vddcx voltage: min:1v max:1.3v\n");
+
pdata = mehci->dev->platform_data;
if (pdata->hub_reset) {
ret = msm_xo_mode_vote(mehci->xo_handle, MSM_XO_MODE_ON);
diff --git a/drivers/usb/otg/msm_otg.c b/drivers/usb/otg/msm_otg.c
index 6c60cc9..7f1641f 100644
--- a/drivers/usb/otg/msm_otg.c
+++ b/drivers/usb/otg/msm_otg.c
@@ -600,6 +600,9 @@
if (motg->core_clk)
clk_disable(motg->core_clk);
+ if (!IS_ERR(motg->system_clk))
+ clk_disable(motg->system_clk);
+
if (!IS_ERR(motg->pclk_src))
clk_disable(motg->pclk_src);
@@ -642,6 +645,9 @@
if (!IS_ERR(motg->pclk_src))
clk_enable(motg->pclk_src);
+ if (!IS_ERR(motg->system_clk))
+ clk_enable(motg->system_clk);
+
clk_enable(motg->pclk);
if (motg->core_clk)
clk_enable(motg->core_clk);
@@ -2070,6 +2076,8 @@
clk_disable(motg->pclk);
if (motg->core_clk)
clk_disable(motg->core_clk);
+ if (!IS_ERR(motg->system_clk))
+ clk_disable(motg->system_clk);
if (!IS_ERR(motg->pclk_src)) {
clk_disable(motg->pclk_src);
clk_put(motg->pclk_src);