Merge "radio-tavarua: Queue only the FM Shutdown work during FM Off" into msm-3.0
diff --git a/arch/arm/configs/msm8960_defconfig b/arch/arm/configs/msm8960_defconfig
index 064b787..c186be4 100644
--- a/arch/arm/configs/msm8960_defconfig
+++ b/arch/arm/configs/msm8960_defconfig
@@ -93,6 +93,7 @@
CONFIG_MSM_L1_ERR_PANIC=y
CONFIG_MSM_L2_ERP_1BIT_PANIC=y
CONFIG_MSM_L2_ERP_2BIT_PANIC=y
+CONFIG_MSM_CACHE_DUMP=y
CONFIG_STRICT_MEMORY_RWX=y
CONFIG_NO_HZ=y
CONFIG_HIGH_RES_TIMERS=y
diff --git a/arch/arm/mach-msm/Kconfig b/arch/arm/mach-msm/Kconfig
index 3c2d47a..2e37431 100644
--- a/arch/arm/mach-msm/Kconfig
+++ b/arch/arm/mach-msm/Kconfig
@@ -2221,4 +2221,12 @@
config HAVE_ARCH_HAS_CURRENT_TIMER
bool
+
+config MSM_CACHE_DUMP
+ bool "Cache dumping support"
+ help
+ Add infrastructure to dump the L1 and L2 caches to an allocated buffer.
+ This allows for analysis of the caches in case cache corruption is
+ suspected.
+
endif
diff --git a/arch/arm/mach-msm/Makefile b/arch/arm/mach-msm/Makefile
index c7943f4..4c40e3c 100644
--- a/arch/arm/mach-msm/Makefile
+++ b/arch/arm/mach-msm/Makefile
@@ -332,3 +332,4 @@
obj-$(CONFIG_ARCH_MSM8960) += mdm2.o mdm_common.o
obj-$(CONFIG_MSM_RTB) += msm_rtb.o
obj-$(CONFIG_MSM_CACHE_ERP) += cache_erp.o
+obj-$(CONFIG_MSM_CACHE_DUMP) += msm_cache_dump.o
diff --git a/arch/arm/mach-msm/board-8960.c b/arch/arm/mach-msm/board-8960.c
index 4ef7d6e..70a65d0 100644
--- a/arch/arm/mach-msm/board-8960.c
+++ b/arch/arm/mach-msm/board-8960.c
@@ -79,6 +79,8 @@
#include <mach/mdm2.h>
#include <mach/mdm-peripheral.h>
#include <mach/msm_rtb.h>
+#include <mach/msm_cache_dump.h>
+#include <mach/scm.h>
#include <linux/fmem.h>
@@ -590,6 +592,43 @@
msm8960_mdp_writeback(msm8960_reserve_table);
}
+#if defined(CONFIG_MSM_CACHE_DUMP)
+static struct msm_cache_dump_platform_data msm_cache_dump_pdata = {
+ .l2_size = L2_BUFFER_SIZE,
+};
+
+static struct platform_device msm_cache_dump_device = {
+ .name = "msm_cache_dump",
+ .id = -1,
+ .dev = {
+ .platform_data = &msm_cache_dump_pdata,
+ },
+};
+
+#endif
+
+static void reserve_cache_dump_memory(void)
+{
+#ifdef CONFIG_MSM_CACHE_DUMP
+ unsigned int spare;
+ unsigned int l1_size;
+ unsigned int total;
+ int ret;
+
+ ret = scm_call(L1C_SERVICE_ID, L1C_BUFFER_GET_SIZE_COMMAND_ID, &spare,
+ sizeof(spare), &l1_size, sizeof(l1_size));
+
+ if (ret)
+ /* Fall back to something reasonable here */
+ l1_size = L1_BUFFER_SIZE;
+
+ total = l1_size + L2_BUFFER_SIZE;
+
+ msm8960_reserve_table[MEMTYPE_EBI1].size += total;
+ msm_cache_dump_pdata.l1_size = l1_size;
+#endif
+}
+
static void __init msm8960_calculate_reserve_sizes(void)
{
size_pmem_devices();
@@ -597,6 +636,7 @@
reserve_ion_memory();
reserve_mdp_memory();
reserve_rtb_memory();
+ reserve_cache_dump_memory();
}
static struct reserve_info msm8960_reserve_info __initdata = {
@@ -2214,6 +2254,9 @@
&msm8960_cpu_idle_device,
&msm8960_msm_gov_device,
&msm8960_device_cache_erp,
+#ifdef CONFIG_MSM_CACHE_DUMP
+ &msm_cache_dump_device,
+#endif
};
static struct platform_device *sim_devices[] __initdata = {
diff --git a/arch/arm/mach-msm/board-qrd7627a.c b/arch/arm/mach-msm/board-qrd7627a.c
index 0b7b7de..44ba518 100644
--- a/arch/arm/mach-msm/board-qrd7627a.c
+++ b/arch/arm/mach-msm/board-qrd7627a.c
@@ -507,10 +507,8 @@
static void __init msm_pm_init(void)
{
- if (machine_is_msm8625_qrd7())
- return;
- if (!machine_is_msm8625_evb()) {
+ if (!cpu_is_msm8625()) {
msm_pm_set_platform_data(msm7627a_pm_data,
ARRAY_SIZE(msm7627a_pm_data));
BUG_ON(msm_pm_boot_init(&msm_pm_boot_pdata));
diff --git a/arch/arm/mach-msm/include/mach/msm_cache_dump.h b/arch/arm/mach-msm/include/mach/msm_cache_dump.h
new file mode 100644
index 0000000..a8d2987
--- /dev/null
+++ b/arch/arm/mach-msm/include/mach/msm_cache_dump.h
@@ -0,0 +1,69 @@
+/*
+ * 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 _MACH_MSM_CACHE_DUMP_
+#define _MACH_MSM_CACHE_DUMP_
+
+#include <asm-generic/sizes.h>
+
+
+struct l2_cache_line_dump {
+ unsigned int l2dcrtr0_val;
+ unsigned int l2dcrtr1_val;
+ unsigned int cache_line_data[32];
+ unsigned int ddr_data[32];
+} __packed;
+
+struct l2_cache_dump {
+ unsigned int magic_number;
+ unsigned int version;
+ unsigned int tag_size;
+ unsigned int line_size;
+ unsigned int total_lines;
+ struct l2_cache_line_dump cache[8*1024];
+ unsigned int l2esr;
+} __packed;
+
+
+struct l1_cache_dump {
+ unsigned int magic;
+ unsigned int version;
+ unsigned int flags;
+ unsigned int cpu_count;
+ unsigned int i_tag_size;
+ unsigned int i_line_size;
+ unsigned int i_num_sets;
+ unsigned int i_num_ways;
+ unsigned int d_tag_size;
+ unsigned int d_line_size;
+ unsigned int d_num_sets;
+ unsigned int d_num_ways;
+ unsigned int spare[32];
+ unsigned int lines[];
+} __packed;
+
+
+struct msm_cache_dump_platform_data {
+ unsigned int l1_size;
+ unsigned int l2_size;
+};
+
+#define L1_BUFFER_SIZE SZ_1M
+#define L2_BUFFER_SIZE (sizeof(struct l2_cache_dump))
+
+#define CACHE_BUFFER_DUMP_SIZE (L1_BUFFER_SIZE + L2_BUFFER_SIZE)
+
+#define L1C_SERVICE_ID 3
+#define L1C_BUFFER_SET_COMMAND_ID 4
+#define L1C_BUFFER_GET_SIZE_COMMAND_ID 6
+
+#endif
diff --git a/arch/arm/mach-msm/msm_cache_dump.c b/arch/arm/mach-msm/msm_cache_dump.c
new file mode 100644
index 0000000..40c358a
--- /dev/null
+++ b/arch/arm/mach-msm/msm_cache_dump.c
@@ -0,0 +1,100 @@
+/* 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/module.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/io.h>
+#include <linux/delay.h>
+#include <linux/workqueue.h>
+#include <linux/platform_device.h>
+#include <linux/pm.h>
+#include <linux/memory_alloc.h>
+#include <mach/scm.h>
+#include <mach/msm_cache_dump.h>
+#include <mach/memory.h>
+#include <mach/msm_iomap.h>
+
+#define L2C_IMEM_ADDR 0x2a03f014
+
+static unsigned long msm_cache_dump_addr;
+
+/*
+ * These are dummy pointers so the defintion of l1_cache_dump
+ * and l2_cache_dump don't get optimized away. If they aren't
+ * referenced, the structure definitions don't show up in the
+ * debugging information which is needed for post processing.
+ */
+static struct l1_cache_dump __used *l1_dump;
+static struct l2_cache_dump __used *l2_dump;
+
+static int msm_cache_dump_probe(struct platform_device *pdev)
+{
+ struct msm_cache_dump_platform_data *d = pdev->dev.platform_data;
+ int ret;
+ struct {
+ unsigned long buf;
+ unsigned long size;
+ } l1_cache_data;
+ unsigned int *imem_loc;
+ void *temp;
+ unsigned long total_size = d->l1_size + d->l2_size;
+
+ msm_cache_dump_addr = allocate_contiguous_ebi_nomap(total_size, SZ_4K);
+
+ if (!msm_cache_dump_addr) {
+ pr_err("%s: Could not get memory for cache dumping\n",
+ __func__);
+ return -ENOMEM;
+ }
+
+ temp = ioremap(msm_cache_dump_addr, total_size);
+ memset(temp, 0xFF, total_size);
+ iounmap(temp);
+
+ l1_cache_data.buf = msm_cache_dump_addr;
+ l1_cache_data.size = d->l1_size;
+
+ ret = scm_call(L1C_SERVICE_ID, L1C_BUFFER_SET_COMMAND_ID,
+ &l1_cache_data, sizeof(l1_cache_data), NULL, 0);
+
+ if (ret)
+ pr_err("%s: could not register L1 buffer ret = %d.\n",
+ __func__, ret);
+
+ imem_loc = ioremap(L2C_IMEM_ADDR, SZ_4K);
+ __raw_writel(msm_cache_dump_addr + d->l1_size, imem_loc);
+ iounmap(imem_loc);
+
+ return 0;
+}
+
+static struct platform_driver msm_cache_dump_driver = {
+ .driver = {
+ .name = "msm_cache_dump",
+ .owner = THIS_MODULE
+ },
+};
+
+static int __init msm_cache_dump_init(void)
+{
+ return platform_driver_probe(&msm_cache_dump_driver,
+ msm_cache_dump_probe);
+}
+
+static void __exit msm_cache_dump_exit(void)
+{
+ platform_driver_unregister(&msm_cache_dump_driver);
+}
+late_initcall(msm_cache_dump_init);
+module_exit(msm_cache_dump_exit)
diff --git a/arch/arm/mach-msm/pm-boot.c b/arch/arm/mach-msm/pm-boot.c
index 80e5a55..8d4ca8b 100644
--- a/arch/arm/mach-msm/pm-boot.c
+++ b/arch/arm/mach-msm/pm-boot.c
@@ -181,8 +181,6 @@
__raw_writel(readl_relaxed(pdata->v_addr +
MPA5_CFG_CTL_REG) | BIT(26),
pdata->v_addr + MPA5_CFG_CTL_REG);
-
- msm_pm_boot_before_pc = msm_pm_write_boot_vector;
}
break;
default:
diff --git a/arch/arm/mach-msm/smd.c b/arch/arm/mach-msm/smd.c
index bbfe702..3cf0550 100644
--- a/arch/arm/mach-msm/smd.c
+++ b/arch/arm/mach-msm/smd.c
@@ -2365,26 +2365,19 @@
return;
}
- /* queue state entries */
- for (n = 0; n < SMSM_NUM_ENTRIES; n++) {
- new_state = __raw_readl(SMSM_STATE_ADDR(n));
-
- ret = kfifo_in(&smsm_snapshot_fifo,
- &new_state, sizeof(new_state));
- if (ret != sizeof(new_state)) {
- pr_err("%s: SMSM snapshot failure %d\n", __func__, ret);
- return;
- }
- }
-
- /* queue wakelock usage flag */
- ret = kfifo_in(&smsm_snapshot_fifo,
- &use_wakelock, sizeof(use_wakelock));
- if (ret != sizeof(use_wakelock)) {
- pr_err("%s: SMSM snapshot failure %d\n", __func__, ret);
- return;
- }
-
+ /*
+ * To avoid a race condition with notify_smsm_cb_clients_worker, the
+ * following sequence must be followed:
+ * 1) increment snapshot count
+ * 2) insert data into FIFO
+ *
+ * Potentially in parallel, the worker:
+ * a) verifies >= 1 snapshots are in FIFO
+ * b) processes snapshot
+ * c) decrements reference count
+ *
+ * This order ensures that 1 will always occur before abc.
+ */
if (use_wakelock) {
spin_lock_irqsave(&smsm_snapshot_count_lock, flags);
if (smsm_snapshot_count == 0) {
@@ -2394,7 +2387,44 @@
++smsm_snapshot_count;
spin_unlock_irqrestore(&smsm_snapshot_count_lock, flags);
}
+
+ /* queue state entries */
+ for (n = 0; n < SMSM_NUM_ENTRIES; n++) {
+ new_state = __raw_readl(SMSM_STATE_ADDR(n));
+
+ ret = kfifo_in(&smsm_snapshot_fifo,
+ &new_state, sizeof(new_state));
+ if (ret != sizeof(new_state)) {
+ pr_err("%s: SMSM snapshot failure %d\n", __func__, ret);
+ goto restore_snapshot_count;
+ }
+ }
+
+ /* queue wakelock usage flag */
+ ret = kfifo_in(&smsm_snapshot_fifo,
+ &use_wakelock, sizeof(use_wakelock));
+ if (ret != sizeof(use_wakelock)) {
+ pr_err("%s: SMSM snapshot failure %d\n", __func__, ret);
+ goto restore_snapshot_count;
+ }
+
schedule_work(&smsm_cb_work);
+ return;
+
+restore_snapshot_count:
+ if (use_wakelock) {
+ spin_lock_irqsave(&smsm_snapshot_count_lock, flags);
+ if (smsm_snapshot_count) {
+ --smsm_snapshot_count;
+ if (smsm_snapshot_count == 0) {
+ SMx_POWER_INFO("SMSM snapshot wake unlock\n");
+ wake_unlock(&smsm_snapshot_wakelock);
+ }
+ } else {
+ pr_err("%s: invalid snapshot count\n", __func__);
+ }
+ spin_unlock_irqrestore(&smsm_snapshot_count_lock, flags);
+ }
}
static irqreturn_t smsm_irq_handler(int irq, void *data)
diff --git a/arch/arm/mach-msm/smem_log.c b/arch/arm/mach-msm/smem_log.c
index 98f9957..2e9a97c 100644
--- a/arch/arm/mach-msm/smem_log.c
+++ b/arch/arm/mach-msm/smem_log.c
@@ -59,10 +59,20 @@
#define D(x...) do {} while (0)
#endif
+/*
+ * Legacy targets use the 32KHz hardware timer and new targets will use
+ * the scheduler timer scaled to a 32KHz tick count.
+ *
+ * As testing on legacy targets permits, we will move them to use
+ * sched_clock() and eventually remove the conditiona compilation.
+ */
#if defined(CONFIG_ARCH_MSM7X30) || defined(CONFIG_ARCH_MSM8X60) \
|| defined(CONFIG_ARCH_FSM9XXX)
#define TIMESTAMP_ADDR (MSM_TMR_BASE + 0x08)
-#else
+#elif defined(CONFIG_ARCH_APQ8064) || defined(CONFIG_ARCH_MSM7X01A) || \
+ defined(CONFIG_ARCH_MSM7x25) || defined(CONFIG_ARCH_MSM7X27) || \
+ defined(CONFIG_ARCH_MSM7X27A) || defined(CONFIG_ARCH_MSM8960) || \
+ defined(CONFIG_ARCH_MSM9615) || defined(CONFIG_ARCH_QSD8X50)
#define TIMESTAMP_ADDR (MSM_TMR_BASE + 0x04)
#endif
@@ -623,6 +633,8 @@
static void init_syms(void) {}
#endif
+#ifdef TIMESTAMP_ADDR
+/* legacy timestamp using 32.768KHz clock */
static inline unsigned int read_timestamp(void)
{
unsigned int tick = 0;
@@ -637,6 +649,18 @@
return tick;
}
+#else
+static inline unsigned int read_timestamp(void)
+{
+ unsigned long long val;
+
+ /* SMEM LOG uses a 32.768KHz timestamp */
+ val = sched_clock() * 32768U;
+ do_div(val, 1000000000U);
+
+ return (unsigned int)val;
+}
+#endif
static void smem_log_event_from_user(struct smem_log_inst *inst,
const char __user *buf, int size, int num)
@@ -649,6 +673,11 @@
int first = 1;
int ret;
+ if (!inst->idx) {
+ pr_err("%s: invalid write index\n", __func__);
+ return;
+ }
+
remote_spin_lock_irqsave(inst->remote_spinlock, flags);
while (num--) {
@@ -898,6 +927,9 @@
local_inst = fp->private_data;
+ if (!local_inst->idx)
+ return -ENODEV;
+
remote_spin_lock_irqsave(local_inst->remote_spinlock, flags);
orig_idx = *local_inst->idx;
@@ -947,6 +979,8 @@
struct smem_log_inst *inst;
inst = fp->private_data;
+ if (!inst->idx)
+ return -ENODEV;
remote_spin_lock_irqsave(inst->remote_spinlock, flags);
@@ -1185,8 +1219,10 @@
int curr_read_avail;
unsigned long flags = 0;
- remote_spin_lock_irqsave(inst->remote_spinlock, flags);
+ if (!inst->idx)
+ return 0;
+ remote_spin_lock_irqsave(inst->remote_spinlock, flags);
curr_read_avail = (*inst->idx - inst->read_idx);
if (curr_read_avail < 0)
curr_read_avail = inst->num - inst->read_idx + *inst->idx;
@@ -1694,6 +1730,10 @@
static int debug_dump(char *buf, int max, uint32_t cont)
{
int r;
+
+ if (!inst[GEN].idx || !inst[GEN].events)
+ return -ENODEV;
+
while (cont) {
update_read_avail(&inst[GEN]);
r = wait_event_interruptible_timeout(inst[GEN].read_wait,
@@ -1714,6 +1754,10 @@
static int debug_dump_sym(char *buf, int max, uint32_t cont)
{
int r;
+
+ if (!inst[GEN].idx || !inst[GEN].events)
+ return -ENODEV;
+
while (cont) {
update_read_avail(&inst[GEN]);
r = wait_event_interruptible_timeout(inst[GEN].read_wait,
@@ -1734,6 +1778,10 @@
static int debug_dump_static(char *buf, int max, uint32_t cont)
{
int r;
+
+ if (!inst[STA].idx || !inst[STA].events)
+ return -ENODEV;
+
while (cont) {
update_read_avail(&inst[STA]);
r = wait_event_interruptible_timeout(inst[STA].read_wait,
@@ -1754,6 +1802,10 @@
static int debug_dump_static_sym(char *buf, int max, uint32_t cont)
{
int r;
+
+ if (!inst[STA].idx || !inst[STA].events)
+ return -ENODEV;
+
while (cont) {
update_read_avail(&inst[STA]);
r = wait_event_interruptible_timeout(inst[STA].read_wait,
@@ -1774,6 +1826,10 @@
static int debug_dump_power(char *buf, int max, uint32_t cont)
{
int r;
+
+ if (!inst[POW].idx || !inst[POW].events)
+ return -ENODEV;
+
while (cont) {
update_read_avail(&inst[POW]);
r = wait_event_interruptible_timeout(inst[POW].read_wait,
@@ -1794,6 +1850,10 @@
static int debug_dump_power_sym(char *buf, int max, uint32_t cont)
{
int r;
+
+ if (!inst[POW].idx || !inst[POW].events)
+ return -ENODEV;
+
while (cont) {
update_read_avail(&inst[POW]);
r = wait_event_interruptible_timeout(inst[POW].read_wait,
@@ -1822,10 +1882,15 @@
size_t count, loff_t *ppos)
{
int r;
- static int bsize;
+ int bsize = 0;
int (*fill)(char *, int, uint32_t) = file->private_data;
- if (!(*ppos))
+ if (!(*ppos)) {
bsize = fill(debug_buffer, EVENTS_PRINT_SIZE, 0);
+
+ if (bsize < 0)
+ bsize = scnprintf(debug_buffer,
+ EVENTS_PRINT_SIZE, "Log not available\n");
+ }
DBG("%s: count %d ppos %d\n", __func__, count, (unsigned int)*ppos);
r = simple_read_from_buffer(buf, count, ppos, debug_buffer,
bsize);
@@ -1840,12 +1905,21 @@
int bsize;
if (!buffer)
return -ENOMEM;
+
bsize = fill(buffer, count, 1);
+ if (bsize < 0) {
+ if (*ppos == 0)
+ bsize = scnprintf(buffer, count, "Log not available\n");
+ else
+ bsize = 0;
+ }
+
DBG("%s: count %d bsize %d\n", __func__, count, bsize);
if (copy_to_user(buf, buffer, bsize)) {
kfree(buffer);
return -EFAULT;
}
+ *ppos += bsize;
kfree(buffer);
return bsize;
}
diff --git a/arch/arm/mach-msm/timer.h b/arch/arm/mach-msm/timer.h
index caef19d..7da9e6a 100644
--- a/arch/arm/mach-msm/timer.h
+++ b/arch/arm/mach-msm/timer.h
@@ -17,9 +17,14 @@
extern struct sys_timer msm_timer;
void __iomem *msm_timer_get_timer0_base(void);
-int64_t msm_timer_enter_idle(void);
-void msm_timer_exit_idle(int low_power);
int64_t msm_timer_get_sclk_time(int64_t *period);
uint32_t msm_timer_get_sclk_ticks(void);
int msm_timer_init_time_sync(void (*timeout)(void));
+#ifndef CONFIG_ARM_ARCH_TIMER
+int64_t msm_timer_enter_idle(void);
+void msm_timer_exit_idle(int low_power);
+#else
+static inline int64_t msm_timer_enter_idle(void) { return 0; }
+static inline void msm_timer_exit_idle(int low_power) { return; }
+#endif
#endif
diff --git a/drivers/slimbus/slim-msm-ctrl.c b/drivers/slimbus/slim-msm-ctrl.c
index 8bd5bd8..fa9d1df 100644
--- a/drivers/slimbus/slim-msm-ctrl.c
+++ b/drivers/slimbus/slim-msm-ctrl.c
@@ -88,10 +88,80 @@
#define QC_DEVID_PGD 0x5
#define QC_MSM_DEVS 5
+#define PGD_THIS_EE(r, v) ((v) ? PGD_THIS_EE_V2(r) : PGD_THIS_EE_V1(r))
+#define PGD_PORT(r, p, v) ((v) ? PGD_PORT_V2(r, p) : PGD_PORT_V1(r, p))
+#define CFG_PORT(r, v) ((v) ? CFG_PORT_V2(r) : CFG_PORT_V1(r))
+
+#define PGD_THIS_EE_V2(r) (dev->base + (r ## _V2) + (dev->ee * 0x1000))
+#define PGD_PORT_V2(r, p) (dev->base + (r ## _V2) + ((p) * 0x1000))
+#define CFG_PORT_V2(r) ((r ## _V2))
/* Component registers */
-enum comp_reg {
- COMP_CFG = 0,
- COMP_TRUST_CFG = 0x14,
+enum comp_reg_v2 {
+ COMP_CFG_V2 = 4,
+ COMP_TRUST_CFG_V2 = 0x3000,
+};
+
+/* Manager PGD registers */
+enum pgd_reg_v2 {
+ PGD_CFG_V2 = 0x800,
+ PGD_STAT_V2 = 0x804,
+ PGD_INT_EN_V2 = 0x810,
+ PGD_INT_STAT_V2 = 0x814,
+ PGD_INT_CLR_V2 = 0x818,
+ PGD_OWN_EEn_V2 = 0x300C,
+ PGD_PORT_INT_EN_EEn_V2 = 0x5000,
+ PGD_PORT_INT_ST_EEn_V2 = 0x5004,
+ PGD_PORT_INT_CL_EEn_V2 = 0x5008,
+ PGD_PORT_CFGn_V2 = 0x14000,
+ PGD_PORT_STATn_V2 = 0x14004,
+ PGD_PORT_PARAMn_V2 = 0x14008,
+ PGD_PORT_BLKn_V2 = 0x1400C,
+ PGD_PORT_TRANn_V2 = 0x14010,
+ PGD_PORT_MCHANn_V2 = 0x14014,
+ PGD_PORT_PSHPLLn_V2 = 0x14018,
+ PGD_PORT_PC_CFGn_V2 = 0x8000,
+ PGD_PORT_PC_VALn_V2 = 0x8004,
+ PGD_PORT_PC_VFR_TSn_V2 = 0x8008,
+ PGD_PORT_PC_VFR_STn_V2 = 0x800C,
+ PGD_PORT_PC_VFR_CLn_V2 = 0x8010,
+ PGD_IE_STAT_V2 = 0x820,
+ PGD_VE_STAT_V2 = 0x830,
+};
+
+#define PGD_THIS_EE_V1(r) (dev->base + (r ## _V1) + (dev->ee * 16))
+#define PGD_PORT_V1(r, p) (dev->base + (r ## _V1) + ((p) * 32))
+#define CFG_PORT_V1(r) ((r ## _V1))
+/* Component registers */
+enum comp_reg_v1 {
+ COMP_CFG_V1 = 0,
+ COMP_TRUST_CFG_V1 = 0x14,
+};
+
+/* Manager PGD registers */
+enum pgd_reg_v1 {
+ PGD_CFG_V1 = 0x1000,
+ PGD_STAT_V1 = 0x1004,
+ PGD_INT_EN_V1 = 0x1010,
+ PGD_INT_STAT_V1 = 0x1014,
+ PGD_INT_CLR_V1 = 0x1018,
+ PGD_OWN_EEn_V1 = 0x1020,
+ PGD_PORT_INT_EN_EEn_V1 = 0x1030,
+ PGD_PORT_INT_ST_EEn_V1 = 0x1034,
+ PGD_PORT_INT_CL_EEn_V1 = 0x1038,
+ PGD_PORT_CFGn_V1 = 0x1080,
+ PGD_PORT_STATn_V1 = 0x1084,
+ PGD_PORT_PARAMn_V1 = 0x1088,
+ PGD_PORT_BLKn_V1 = 0x108C,
+ PGD_PORT_TRANn_V1 = 0x1090,
+ PGD_PORT_MCHANn_V1 = 0x1094,
+ PGD_PORT_PSHPLLn_V1 = 0x1098,
+ PGD_PORT_PC_CFGn_V1 = 0x1600,
+ PGD_PORT_PC_VALn_V1 = 0x1604,
+ PGD_PORT_PC_VFR_TSn_V1 = 0x1608,
+ PGD_PORT_PC_VFR_STn_V1 = 0x160C,
+ PGD_PORT_PC_VFR_CLn_V1 = 0x1610,
+ PGD_IE_STAT_V1 = 0x1700,
+ PGD_VE_STAT_V1 = 0x1710,
};
/* Manager registers */
@@ -143,33 +213,6 @@
INTF_VE_STAT = 0x640,
};
-/* Manager PGD registers */
-enum pgd_reg {
- PGD_CFG = 0x1000,
- PGD_STAT = 0x1004,
- PGD_INT_EN = 0x1010,
- PGD_INT_STAT = 0x1014,
- PGD_INT_CLR = 0x1018,
- PGD_OWN_EEn = 0x1020,
- PGD_PORT_INT_EN_EEn = 0x1030,
- PGD_PORT_INT_ST_EEn = 0x1034,
- PGD_PORT_INT_CL_EEn = 0x1038,
- PGD_PORT_CFGn = 0x1080,
- PGD_PORT_STATn = 0x1084,
- PGD_PORT_PARAMn = 0x1088,
- PGD_PORT_BLKn = 0x108C,
- PGD_PORT_TRANn = 0x1090,
- PGD_PORT_MCHANn = 0x1094,
- PGD_PORT_PSHPLLn = 0x1098,
- PGD_PORT_PC_CFGn = 0x1600,
- PGD_PORT_PC_VALn = 0x1604,
- PGD_PORT_PC_VFR_TSn = 0x1608,
- PGD_PORT_PC_VFR_STn = 0x160C,
- PGD_PORT_PC_VFR_CLn = 0x1610,
- PGD_IE_STAT = 0x1700,
- PGD_VE_STAT = 0x1710,
-};
-
enum rsc_grp {
EE_MGR_RSC_GRP = 1 << 10,
EE_NGD_2 = 2 << 6,
@@ -245,6 +288,7 @@
bool chan_active;
enum msm_ctrl_state state;
int nsats;
+ u32 ver;
};
struct msm_sat_chan {
@@ -509,13 +553,13 @@
mb();
complete(&dev->reconf);
}
- pstat = readl_relaxed(dev->base + PGD_PORT_INT_ST_EEn + (16 * dev->ee));
+ pstat = readl_relaxed(PGD_THIS_EE(PGD_PORT_INT_ST_EEn, dev->ver));
if (pstat != 0) {
int i = 0;
for (i = dev->pipe_b; i < MSM_SLIM_NPORTS; i++) {
if (pstat & 1 << i) {
- u32 val = readl_relaxed(dev->base +
- PGD_PORT_STATn + (i * 32));
+ u32 val = readl_relaxed(PGD_PORT(PGD_PORT_STATn,
+ i, dev->ver));
if (val & (1 << 19)) {
dev->ctrl.ports[i].err =
SLIM_P_DISCONNECT;
@@ -532,8 +576,8 @@
dev->ctrl.ports[i].err =
SLIM_P_UNDERFLOW;
}
- writel_relaxed(1, dev->base + PGD_PORT_INT_CL_EEn +
- (dev->ee * 16));
+ writel_relaxed(1, PGD_THIS_EE(PGD_PORT_INT_CL_EEn,
+ dev->ver));
}
/*
* Guarantee that port interrupt bit(s) clearing writes go
@@ -612,13 +656,13 @@
static void msm_hw_set_port(struct msm_slim_ctrl *dev, u8 pn)
{
u32 set_cfg = DEF_WATERMARK | DEF_ALIGN | DEF_PACK | ENABLE_PORT;
- u32 int_port = readl_relaxed(dev->base + PGD_PORT_INT_EN_EEn +
- (dev->ee * 16));
- writel_relaxed(set_cfg, dev->base + PGD_PORT_CFGn + (pn * 32));
- writel_relaxed(DEF_BLKSZ, dev->base + PGD_PORT_BLKn + (pn * 32));
- writel_relaxed(DEF_TRANSZ, dev->base + PGD_PORT_TRANn + (pn * 32));
- writel_relaxed((int_port | 1 << pn) , dev->base + PGD_PORT_INT_EN_EEn +
- (dev->ee * 16));
+ u32 int_port = readl_relaxed(PGD_THIS_EE(PGD_PORT_INT_EN_EEn,
+ dev->ver));
+ writel_relaxed(set_cfg, PGD_PORT(PGD_PORT_CFGn, pn, dev->ver));
+ writel_relaxed(DEF_BLKSZ, PGD_PORT(PGD_PORT_BLKn, pn, dev->ver));
+ writel_relaxed(DEF_TRANSZ, PGD_PORT(PGD_PORT_TRANn, pn, dev->ver));
+ writel_relaxed((int_port | 1 << pn) , PGD_THIS_EE(PGD_PORT_INT_EN_EEn,
+ dev->ver));
/* Make sure that port registers are updated before returning */
mb();
}
@@ -645,8 +689,8 @@
}
}
- stat = readl_relaxed(dev->base + PGD_PORT_STATn +
- (32 * (pn + dev->pipe_b)));
+ stat = readl_relaxed(PGD_PORT(PGD_PORT_STATn, (pn + dev->pipe_b),
+ dev->ver));
if (dev->ctrl.ports[pn].flow == SLIM_SRC) {
cfg->destination = dev->bam.hdl;
cfg->source = SPS_DEV_HANDLE_MEM;
@@ -1947,10 +1991,13 @@
clk_set_rate(dev->rclk, SLIM_ROOT_FREQ);
clk_prepare_enable(dev->rclk);
+ dev->ver = readl_relaxed(dev->base);
+ /* Version info in 16 MSbits */
+ dev->ver >>= 16;
/* Component register initialization */
- writel_relaxed(1, dev->base + COMP_CFG);
+ writel_relaxed(1, dev->base + CFG_PORT(COMP_CFG, dev->ver));
writel_relaxed((EE_MGR_RSC_GRP | EE_NGD_2 | EE_NGD_1),
- dev->base + COMP_TRUST_CFG);
+ dev->base + CFG_PORT(COMP_TRUST_CFG, dev->ver));
/*
* Manager register initialization
@@ -2001,15 +2048,16 @@
* ported generic device inside MSM manager
*/
mb();
- writel_relaxed(1, dev->base + PGD_CFG);
- writel_relaxed(0x3F<<17, dev->base + (PGD_OWN_EEn + (4 * dev->ee)));
+ writel_relaxed(1, dev->base + CFG_PORT(PGD_CFG, dev->ver));
+ writel_relaxed(0x3F<<17, dev->base + CFG_PORT(PGD_OWN_EEn, dev->ver) +
+ (4 * dev->ee));
/*
* Make sure that ported generic device is enabled and port-EE settings
* are written through before finally enabling the component
*/
mb();
- writel_relaxed(1, dev->base + COMP_CFG);
+ writel_relaxed(1, dev->base + CFG_PORT(COMP_CFG, dev->ver));
/*
* Make sure that all writes have gone through before exiting this
* function
@@ -2026,7 +2074,7 @@
return 0;
err_ctrl_failed:
- writel_relaxed(0, dev->base + COMP_CFG);
+ writel_relaxed(0, dev->base + CFG_PORT(COMP_CFG, dev->ver));
err_clk_get_failed:
kfree(dev->satd);
err_request_irq_failed:
diff --git a/drivers/staging/qcache/fmem.c b/drivers/staging/qcache/fmem.c
index acca6f1..4250ff5 100644
--- a/drivers/staging/qcache/fmem.c
+++ b/drivers/staging/qcache/fmem.c
@@ -223,6 +223,9 @@
{
int ret = 0;
+ if (fmem_state == FMEM_UNINITIALIZED)
+ return NOTIFY_OK;
+
switch (action) {
case MEM_ONLINE:
fmem_mem_online_callback(arg);
diff --git a/include/linux/msm_mdp.h b/include/linux/msm_mdp.h
index 56e8438..aa54b71 100644
--- a/include/linux/msm_mdp.h
+++ b/include/linux/msm_mdp.h
@@ -25,7 +25,7 @@
#define MSMFB_RESUME_SW_REFRESHER _IOW(MSMFB_IOCTL_MAGIC, 129, unsigned int)
#define MSMFB_CURSOR _IOW(MSMFB_IOCTL_MAGIC, 130, struct fb_cursor)
#define MSMFB_SET_LUT _IOW(MSMFB_IOCTL_MAGIC, 131, struct fb_cmap)
-#define MSMFB_HISTOGRAM _IOWR(MSMFB_IOCTL_MAGIC, 132, struct mdp_histogram)
+#define MSMFB_HISTOGRAM _IOWR(MSMFB_IOCTL_MAGIC, 132, struct mdp_histogram_data)
/* new ioctls's for set/get ccs matrix */
#define MSMFB_GET_CCS_MATRIX _IOWR(MSMFB_IOCTL_MAGIC, 133, struct mdp_ccs)
#define MSMFB_SET_CCS_MATRIX _IOW(MSMFB_IOCTL_MAGIC, 134, struct mdp_ccs)
@@ -44,8 +44,9 @@
#define MSMFB_OVERLAY_BLT _IOWR(MSMFB_IOCTL_MAGIC, 142, \
struct msmfb_overlay_blt)
#define MSMFB_OVERLAY_BLT_OFFSET _IOW(MSMFB_IOCTL_MAGIC, 143, unsigned int)
-#define MSMFB_HISTOGRAM_START _IO(MSMFB_IOCTL_MAGIC, 144)
-#define MSMFB_HISTOGRAM_STOP _IO(MSMFB_IOCTL_MAGIC, 145)
+#define MSMFB_HISTOGRAM_START _IOR(MSMFB_IOCTL_MAGIC, 144, \
+ struct mdp_histogram_start_req)
+#define MSMFB_HISTOGRAM_STOP _IOR(MSMFB_IOCTL_MAGIC, 145, unsigned int)
#define MSMFB_NOTIFY_UPDATE _IOW(MSMFB_IOCTL_MAGIC, 146, unsigned int)
#define MSMFB_OVERLAY_3D _IOWR(MSMFB_IOCTL_MAGIC, 147, \
@@ -328,6 +329,32 @@
MDP_BLOCK_MAX,
};
+/*
+ * mdp_histogram_start_req is used to provide the parameters for
+ * histogram start request
+ */
+
+struct mdp_histogram_start_req {
+ uint32_t block;
+ uint8_t frame_cnt;
+ uint8_t bit_mask;
+ uint8_t num_bins;
+};
+
+/*
+ * mdp_histogram_data is used to return the histogram data, once
+ * the histogram is done/stopped/cance
+ */
+
+struct mdp_histogram_data {
+ uint32_t block;
+ uint8_t bin_cnt;
+ uint32_t *c0;
+ uint32_t *c1;
+ uint32_t *c2;
+ uint32_t extra_info[2];
+};
+
struct mdp_pcc_coeff {
uint32_t c, r, g, b, rr, gg, bb, rg, gb, rb, rgb_0, rgb_1;
};