Merge "msm: smd_pkt: Register platform driver with the SMD channel name" into msm-3.4
diff --git a/arch/arm/boot/dts/msmcopper.dtsi b/arch/arm/boot/dts/msmcopper.dtsi
index 5fe99df..bc7c5f0 100644
--- a/arch/arm/boot/dts/msmcopper.dtsi
+++ b/arch/arm/boot/dts/msmcopper.dtsi
@@ -402,6 +402,7 @@
compatible = "qcom,mdss_mdp";
reg = <0xfd900000 0x22100>;
interrupts = <0 72 0>;
+ vdd-supply = <&gdsc_mdss>;
};
qcom,mdss_wb_panel {
diff --git a/arch/arm/configs/msm-copper_defconfig b/arch/arm/configs/msm-copper_defconfig
index 8b9fa0fe..57cd263 100644
--- a/arch/arm/configs/msm-copper_defconfig
+++ b/arch/arm/configs/msm-copper_defconfig
@@ -173,6 +173,7 @@
CONFIG_MMC=y
CONFIG_MMC_PERF_PROFILING=y
CONFIG_MMC_UNSAFE_RESUME=y
+CONFIG_MMC_CLKGATE=y
CONFIG_MMC_PARANOID_SD_INIT=y
CONFIG_MMC_BLOCK_MINORS=32
# CONFIG_MMC_BLOCK_BOUNCE is not set
diff --git a/arch/arm/kernel/perf_event.c b/arch/arm/kernel/perf_event.c
index e37b28b..778128b 100644
--- a/arch/arm/kernel/perf_event.c
+++ b/arch/arm/kernel/perf_event.c
@@ -616,16 +616,14 @@
atomic_set(&armpmu->active_events, 0);
mutex_init(&armpmu->reserve_mutex);
- armpmu->pmu = (struct pmu) {
- .pmu_enable = armpmu_enable,
- .pmu_disable = armpmu_disable,
- .event_init = armpmu_event_init,
- .add = armpmu_add,
- .del = armpmu_del,
- .start = armpmu_start,
- .stop = armpmu_stop,
- .read = armpmu_read,
- };
+ armpmu->pmu.pmu_enable = armpmu_enable;
+ armpmu->pmu.pmu_disable = armpmu_disable;
+ armpmu->pmu.event_init = armpmu_event_init;
+ armpmu->pmu.add = armpmu_add;
+ armpmu->pmu.del = armpmu_del;
+ armpmu->pmu.start = armpmu_start;
+ armpmu->pmu.stop = armpmu_stop;
+ armpmu->pmu.read = armpmu_read;
}
int armpmu_register(struct arm_pmu *armpmu, char *name, int type)
@@ -857,14 +855,12 @@
case 0x02D0: /* 8x60 */
// fabricmon_pmu_init();
cpu_pmu = armv7_scorpionmp_pmu_init();
-// scorpionmp_l2_pmu_init();
break;
case 0x0490: /* 8960 sim */
case 0x04D0: /* 8960 */
case 0x06F0: /* 8064 */
// fabricmon_pmu_init();
cpu_pmu = armv7_krait_pmu_init();
-// krait_l2_pmu_init();
break;
}
}
diff --git a/arch/arm/kernel/perf_event_msm.c b/arch/arm/kernel/perf_event_msm.c
index 46fa8fe..90c9c9e 100644
--- a/arch/arm/kernel/perf_event_msm.c
+++ b/arch/arm/kernel/perf_event_msm.c
@@ -720,6 +720,8 @@
.start = armv7pmu_start,
.stop = armv7pmu_stop,
.reset = scorpion_pmu_reset,
+ .test_set_event_constraints = msm_test_set_ev_constraint,
+ .clear_event_constraints = msm_clear_ev_constraint,
.max_period = (1LLU << 32) - 1,
};
@@ -728,6 +730,7 @@
scorpion_pmu.id = ARM_PERF_PMU_ID_SCORPION;
scorpion_pmu.name = "ARMv7 Scorpion";
scorpion_pmu.num_events = armv7_read_num_pmnc_events();
+ scorpion_pmu.pmu.attr_groups = msm_l1_pmu_attr_grps;
scorpion_clear_pmuregs();
return &scorpion_pmu;
}
@@ -737,6 +740,7 @@
scorpion_pmu.id = ARM_PERF_PMU_ID_SCORPIONMP;
scorpion_pmu.name = "ARMv7 Scorpion-MP";
scorpion_pmu.num_events = armv7_read_num_pmnc_events();
+ scorpion_pmu.pmu.attr_groups = msm_l1_pmu_attr_grps;
scorpion_clear_pmuregs();
return &scorpion_pmu;
}
diff --git a/arch/arm/kernel/perf_event_msm_krait.c b/arch/arm/kernel/perf_event_msm_krait.c
index 1b115b4..8d8f47a 100644
--- a/arch/arm/kernel/perf_event_msm_krait.c
+++ b/arch/arm/kernel/perf_event_msm_krait.c
@@ -573,10 +573,10 @@
*/
static int msm_test_set_ev_constraint(struct perf_event *event)
{
- u32 krait_evt_type = event->attr.config & KRAIT_EVENT_MASK;
- u8 prefix = (krait_evt_type & 0xF0000) >> 16;
- u8 reg = (krait_evt_type & 0x0F000) >> 12;
- u8 group = krait_evt_type & 0x0000F;
+ u32 evt_type = event->attr.config & KRAIT_EVENT_MASK;
+ u8 prefix = (evt_type & 0xF0000) >> 16;
+ u8 reg = (evt_type & 0x0F000) >> 12;
+ u8 group = evt_type & 0x0000F;
u64 cpu_pmu_bitmap = __get_cpu_var(pmu_bitmap);
u64 bitmap_t;
@@ -598,10 +598,10 @@
static int msm_clear_ev_constraint(struct perf_event *event)
{
- u32 krait_evt_type = event->attr.config & KRAIT_EVENT_MASK;
- u8 prefix = (krait_evt_type & 0xF0000) >> 16;
- u8 reg = (krait_evt_type & 0x0F000) >> 12;
- u8 group = krait_evt_type & 0x0000F;
+ u32 evt_type = event->attr.config & KRAIT_EVENT_MASK;
+ u8 prefix = (evt_type & 0xF0000) >> 16;
+ u8 reg = (evt_type & 0x0F000) >> 12;
+ u8 group = evt_type & 0x0000F;
u64 cpu_pmu_bitmap = __get_cpu_var(pmu_bitmap);
u64 bitmap_t;
@@ -636,6 +636,34 @@
.max_period = (1LLU << 32) - 1,
};
+/* NRCCG format for perf RAW codes. */
+PMU_FORMAT_ATTR(prefix, "config:16-19");
+PMU_FORMAT_ATTR(reg, "config:12-15");
+PMU_FORMAT_ATTR(code, "config:4-11");
+PMU_FORMAT_ATTR(grp, "config:0-3");
+
+static struct attribute *msm_l1_ev_formats[] = {
+ &format_attr_prefix.attr,
+ &format_attr_reg.attr,
+ &format_attr_code.attr,
+ &format_attr_grp.attr,
+ NULL,
+};
+
+/*
+ * Format group is essential to access PMU's from userspace
+ * via their .name field.
+ */
+static struct attribute_group msm_pmu_format_group = {
+ .name = "format",
+ .attrs = msm_l1_ev_formats,
+};
+
+static const struct attribute_group *msm_l1_pmu_attr_grps[] = {
+ &msm_pmu_format_group,
+ NULL,
+};
+
int get_krait_ver(void)
{
int ver = 0;
@@ -655,6 +683,7 @@
krait_pmu.name = "ARMv7 Krait";
krait_pmu.map_event = krait_8960_map_event;
krait_pmu.num_events = armv7_read_num_pmnc_events();
+ krait_pmu.pmu.attr_groups = msm_l1_pmu_attr_grps;
krait_clear_pmuregs();
krait_ver = get_krait_ver();
diff --git a/arch/arm/mach-msm/Kconfig b/arch/arm/mach-msm/Kconfig
index d1ab4dd..776bf40 100644
--- a/arch/arm/mach-msm/Kconfig
+++ b/arch/arm/mach-msm/Kconfig
@@ -347,12 +347,14 @@
select ARCH_MSM_SCORPION
select MSM_SMP
select HAVE_ARCH_HAS_CURRENT_TIMER
+ select MSM_JTAG if MSM_QDSS
bool
config ARCH_MSM_KRAITMP
select ARCH_MSM_KRAIT
select MSM_SMP
select HAVE_ARCH_HAS_CURRENT_TIMER
+ select MSM_JTAG if MSM_QDSS
bool
select HAVE_HW_BRKPT_RESERVED_RW_ACCESS
@@ -2074,9 +2076,15 @@
enabled via another mechanism.
config MSM_JTAG
- bool "JTAG debug and trace support"
+ bool "JTAG and kernel debug and trace support across power collapse"
help
- Add additional support for JTAG kernel debugging and tracing.
+ Enables support for kernel debugging (specifically breakpoints) and
+ processor tracing across power collapse both for JTag and OS hosted
+ software running on the target. Enabling this will ensure debug
+ and ETM registers are saved and restored across power collapse.
+
+ For production builds, you should probably say 'N' here to avoid
+ potential power, performance and memory penalty.
config MSM_ETM
tristate "Enable MSM ETM and ETB"
@@ -2085,30 +2093,6 @@
help
Enables embedded trace collection on MSM8660
-config MSM_QDSS
- bool "Qualcomm Debug Subsystem"
- select MSM_JTAG
- help
- Enables support for Qualcomm Debug Subsystem.
-
-config MSM_QDSS_STM_DEFAULT_ENABLE
- bool "Turn on QDSS STM Tracing by Default"
- depends on MSM_QDSS
- help
- Turns on QDSS STM tracing (hardware assisted software
- instrumentation based tracing) by default. Otherwise, tracing is
- disabled by default but can be enabled via sysfs.
-
- For production builds, you should probably say 'N' here to avoid
- potential power, performance and memory penalty.
-
-config MSM_QDSS_ETM_DEFAULT_ENABLE
- bool "Turn on QDSS ETM Tracing by Default"
- depends on MSM_QDSS
- help
- Turns on QDSS ETM tracing by default. Otherwise, tracing is
- disabled by default but can be enabled by other means.
-
config MSM_SLEEP_STATS
bool "Enable exporting of MSM sleep stats to userspace"
depends on CPU_IDLE
diff --git a/arch/arm/mach-msm/Makefile b/arch/arm/mach-msm/Makefile
index 8315d70..ec8de9f 100644
--- a/arch/arm/mach-msm/Makefile
+++ b/arch/arm/mach-msm/Makefile
@@ -55,7 +55,6 @@
msm-etm-objs := etm.o
obj-$(CONFIG_MSM_ETM) += msm-etm.o
-obj-$(CONFIG_MSM_QDSS) += qdss.o qdss-etb.o qdss-tpiu.o qdss-funnel.o qdss-stm.o qdss-etm.o
quiet_cmd_mkrpcsym = MKCAP $@
cmd_mkrpcsym = $(PERL) $(srctree)/$(src)/mkrpcsym.pl $< $@
diff --git a/arch/arm/mach-msm/acpuclock-8960.c b/arch/arm/mach-msm/acpuclock-8960.c
index d29fee6..6c14efa 100644
--- a/arch/arm/mach-msm/acpuclock-8960.c
+++ b/arch/arm/mach-msm/acpuclock-8960.c
@@ -735,10 +735,6 @@
{ 1, { 1080000, HFPLL, 1, 0, 0x28 }, L2(16), 1175000 },
{ 1, { 1134000, HFPLL, 1, 0, 0x2A }, L2(16), 1175000 },
{ 1, { 1188000, HFPLL, 1, 0, 0x2C }, L2(16), 1200000 },
- { 1, { 1242000, HFPLL, 1, 0, 0x2E }, L2(16), 1200000 },
- { 1, { 1296000, HFPLL, 1, 0, 0x30 }, L2(16), 1225000 },
- { 1, { 1350000, HFPLL, 1, 0, 0x32 }, L2(16), 1225000 },
- { 1, { 1404000, HFPLL, 1, 0, 0x34 }, L2(16), 1237500 },
{ 0, { 0 } }
};
@@ -760,10 +756,6 @@
{ 1, { 1080000, HFPLL, 1, 0, 0x28 }, L2(16), 1150000 },
{ 1, { 1134000, HFPLL, 1, 0, 0x2A }, L2(16), 1150000 },
{ 1, { 1188000, HFPLL, 1, 0, 0x2C }, L2(16), 1175000 },
- { 1, { 1242000, HFPLL, 1, 0, 0x2E }, L2(16), 1175000 },
- { 1, { 1296000, HFPLL, 1, 0, 0x30 }, L2(16), 1200000 },
- { 1, { 1350000, HFPLL, 1, 0, 0x32 }, L2(16), 1200000 },
- { 1, { 1404000, HFPLL, 1, 0, 0x34 }, L2(16), 1212500 },
{ 0, { 0 } }
};
@@ -785,10 +777,6 @@
{ 1, { 1080000, HFPLL, 1, 0, 0x28 }, L2(16), 1100000 },
{ 1, { 1134000, HFPLL, 1, 0, 0x2A }, L2(16), 1100000 },
{ 1, { 1188000, HFPLL, 1, 0, 0x2C }, L2(16), 1125000 },
- { 1, { 1242000, HFPLL, 1, 0, 0x2E }, L2(16), 1125000 },
- { 1, { 1296000, HFPLL, 1, 0, 0x30 }, L2(16), 1150000 },
- { 1, { 1350000, HFPLL, 1, 0, 0x32 }, L2(16), 1150000 },
- { 1, { 1404000, HFPLL, 1, 0, 0x34 }, L2(16), 1162500 },
{ 0, { 0 } }
};
/* TODO: Update vdd_dig, vdd_mem and bw when data is available. */
diff --git a/arch/arm/mach-msm/bam_dmux.c b/arch/arm/mach-msm/bam_dmux.c
index d53e471..3df566c 100644
--- a/arch/arm/mach-msm/bam_dmux.c
+++ b/arch/arm/mach-msm/bam_dmux.c
@@ -238,11 +238,12 @@
static DEFINE_SPINLOCK(wakelock_reference_lock);
static int wakelock_reference_count;
static int a2_pc_disabled_wakelock_skipped;
-static int disconnect_ack;
+static int disconnect_ack = 1;
static LIST_HEAD(bam_other_notify_funcs);
static DEFINE_MUTEX(smsm_cb_lock);
static DEFINE_MUTEX(delayed_ul_vote_lock);
static int need_delayed_ul_vote;
+static int power_management_only_mode;
struct outside_notify_func {
void (*notify)(void *, int, unsigned long);
@@ -561,9 +562,9 @@
bam_dmux_log("%s: opening cid %d PC enabled\n", __func__,
rx_hdr->ch_id);
handle_bam_mux_cmd_open(rx_hdr);
- if (rx_hdr->reserved & ENABLE_DISCONNECT_ACK) {
- bam_dmux_log("%s: activating disconnect ack\n");
- disconnect_ack = 1;
+ if (!(rx_hdr->reserved & ENABLE_DISCONNECT_ACK)) {
+ bam_dmux_log("%s: deactivating disconnect ack\n");
+ disconnect_ack = 0;
}
dev_kfree_skb_any(rx_skb);
break;
@@ -1688,21 +1689,28 @@
in_global_reset = 0;
vote_dfab();
- i = sps_device_reset(a2_device_handle);
- if (i)
- pr_err("%s: device reset failed rc = %d\n", __func__, i);
- i = sps_connect(bam_tx_pipe, &tx_connection);
- if (i)
- pr_err("%s: tx connection failed rc = %d\n", __func__, i);
- i = sps_connect(bam_rx_pipe, &rx_connection);
- if (i)
- pr_err("%s: rx connection failed rc = %d\n", __func__, i);
- i = sps_register_event(bam_tx_pipe, &tx_register_event);
- if (i)
- pr_err("%s: tx event reg failed rc = %d\n", __func__, i);
- i = sps_register_event(bam_rx_pipe, &rx_register_event);
- if (i)
- pr_err("%s: rx event reg failed rc = %d\n", __func__, i);
+ if (!power_management_only_mode) {
+ i = sps_device_reset(a2_device_handle);
+ if (i)
+ pr_err("%s: device reset failed rc = %d\n", __func__,
+ i);
+ i = sps_connect(bam_tx_pipe, &tx_connection);
+ if (i)
+ pr_err("%s: tx connection failed rc = %d\n", __func__,
+ i);
+ i = sps_connect(bam_rx_pipe, &rx_connection);
+ if (i)
+ pr_err("%s: rx connection failed rc = %d\n", __func__,
+ i);
+ i = sps_register_event(bam_tx_pipe, &tx_register_event);
+ if (i)
+ pr_err("%s: tx event reg failed rc = %d\n", __func__,
+ i);
+ i = sps_register_event(bam_rx_pipe, &rx_register_event);
+ if (i)
+ pr_err("%s: rx event reg failed rc = %d\n", __func__,
+ i);
+ }
bam_connection_is_active = 1;
@@ -1711,7 +1719,8 @@
toggle_apps_ack();
complete_all(&bam_connection_completion);
- queue_rx();
+ if (!power_management_only_mode)
+ queue_rx();
}
static void disconnect_to_bam(void)
@@ -1733,11 +1742,13 @@
/* tear down BAM connection */
INIT_COMPLETION(bam_connection_completion);
- sps_disconnect(bam_tx_pipe);
- sps_disconnect(bam_rx_pipe);
+ if (!power_management_only_mode) {
+ sps_disconnect(bam_tx_pipe);
+ sps_disconnect(bam_rx_pipe);
+ __memzero(rx_desc_mem_buf.base, rx_desc_mem_buf.size);
+ __memzero(tx_desc_mem_buf.base, tx_desc_mem_buf.size);
+ }
unvote_dfab();
- __memzero(rx_desc_mem_buf.base, rx_desc_mem_buf.size);
- __memzero(tx_desc_mem_buf.base, tx_desc_mem_buf.size);
mutex_lock(&bam_rx_pool_mutexlock);
while (!list_empty(&bam_rx_pool)) {
@@ -2081,7 +2092,6 @@
int ret;
void *a2_virt_addr;
- unvote_dfab();
/* init BAM */
a2_virt_addr = ioremap_nocache(A2_PHYS_BASE, A2_PHYS_SIZE);
if (!a2_virt_addr) {
@@ -2114,6 +2124,10 @@
mutex_unlock(&delayed_ul_vote_lock);
toggle_apps_ack();
+ power_management_only_mode = 1;
+ bam_connection_is_active = 1;
+ complete_all(&bam_connection_completion);
+
return 0;
register_bam_failed:
diff --git a/arch/arm/mach-msm/board-8064-regulator.c b/arch/arm/mach-msm/board-8064-regulator.c
index 622b213..7175123f 100644
--- a/arch/arm/mach-msm/board-8064-regulator.c
+++ b/arch/arm/mach-msm/board-8064-regulator.c
@@ -221,6 +221,7 @@
REGULATOR_SUPPLY("8921_lvs7", NULL),
REGULATOR_SUPPLY("pll_vdd", "pil_riva"),
REGULATOR_SUPPLY("lvds_vdda", "lvds.0"),
+ REGULATOR_SUPPLY("hdmi_pll_fs", "mdp.0"),
REGULATOR_SUPPLY("dsi1_vddio", "mipi_dsi.1"),
REGULATOR_SUPPLY("hdmi_vdda", "hdmi_msm.0"),
};
diff --git a/arch/arm/mach-msm/board-8930.c b/arch/arm/mach-msm/board-8930.c
index 1f5ea52..1a61dbb 100644
--- a/arch/arm/mach-msm/board-8930.c
+++ b/arch/arm/mach-msm/board-8930.c
@@ -78,6 +78,7 @@
#include <mach/mdm2.h>
#include <mach/msm_rtb.h>
#include <linux/fmem.h>
+#include <mach/msm_cache_dump.h>
#ifdef CONFIG_INPUT_MPU3050
#include <linux/input/mpu3050.h>
@@ -629,6 +630,19 @@
msm8930_mdp_writeback(msm8930_reserve_table);
}
+#ifdef CONFIG_MSM_CACHE_DUMP
+static void __init reserve_cache_dump_memory(void)
+{
+ unsigned int total;
+
+ total = msm8930_cache_dump_pdata.l1_size +
+ msm8930_cache_dump_pdata.l2_size;
+ msm8930_reserve_table[MEMTYPE_EBI1].size += total;
+}
+#else
+static void __init reserve_cache_dump_memory(void) { }
+#endif
+
static void __init msm8930_calculate_reserve_sizes(void)
{
size_pmem_devices();
@@ -636,6 +650,7 @@
reserve_ion_memory();
reserve_mdp_memory();
reserve_rtb_memory();
+ reserve_cache_dump_memory();
}
static struct reserve_info msm8930_reserve_info __initdata = {
@@ -2149,6 +2164,7 @@
&msm8960_device_cache_erp,
&msm8930_iommu_domain_device,
&msm_tsens_device,
+ &msm8930_cache_dump_device,
};
static struct platform_device *cdp_devices[] __initdata = {
diff --git a/arch/arm/mach-msm/board-8930.h b/arch/arm/mach-msm/board-8930.h
index 925de45..9f6276c 100644
--- a/arch/arm/mach-msm/board-8930.h
+++ b/arch/arm/mach-msm/board-8930.h
@@ -141,3 +141,4 @@
#define MSM_8930_GSBI12_QUP_I2C_BUS_ID 12
extern struct msm_rtb_platform_data msm8930_rtb_pdata;
+extern struct msm_cache_dump_platform_data msm8930_cache_dump_pdata;
diff --git a/arch/arm/mach-msm/board-8960-regulator.c b/arch/arm/mach-msm/board-8960-regulator.c
index bc5a892..6bd1b7d 100644
--- a/arch/arm/mach-msm/board-8960-regulator.c
+++ b/arch/arm/mach-msm/board-8960-regulator.c
@@ -116,6 +116,7 @@
REGULATOR_SUPPLY("8921_l23", NULL),
REGULATOR_SUPPLY("dsi_vddio", "mipi_dsi.1"),
REGULATOR_SUPPLY("hdmi_avdd", "hdmi_msm.0"),
+ REGULATOR_SUPPLY("hdmi_pll_fs", "mdp.0"),
REGULATOR_SUPPLY("pll_vdd", "pil_riva"),
REGULATOR_SUPPLY("pll_vdd", "pil_qdsp6v4.1"),
REGULATOR_SUPPLY("pll_vdd", "pil_qdsp6v4.2"),
diff --git a/arch/arm/mach-msm/board-8960.c b/arch/arm/mach-msm/board-8960.c
index 628a324..ec62388 100644
--- a/arch/arm/mach-msm/board-8960.c
+++ b/arch/arm/mach-msm/board-8960.c
@@ -1416,6 +1416,7 @@
static struct msm_spi_platform_data msm8960_qup_spi_gsbi1_pdata = {
.max_clock_speed = 15060000,
+ .infinite_mode = 1
};
#ifdef CONFIG_USB_MSM_OTG_72K
diff --git a/arch/arm/mach-msm/board-9615.c b/arch/arm/mach-msm/board-9615.c
index 568de46..7181990 100644
--- a/arch/arm/mach-msm/board-9615.c
+++ b/arch/arm/mach-msm/board-9615.c
@@ -194,7 +194,8 @@
/* Initial PM8018 GPIO configurations */
static struct pm8xxx_gpio_init pm8018_gpios[] __initdata = {
- PM8018_GPIO_OUTPUT(2, 0, HIGH) /* EXT_LDO_EN_WLAN */
+ PM8018_GPIO_OUTPUT(2, 0, HIGH), /* EXT_LDO_EN_WLAN */
+ PM8018_GPIO_OUTPUT(6, 0, LOW), /* WLAN_CLK_PWR_REQ */
};
/* Initial PM8018 MPP configurations */
diff --git a/arch/arm/mach-msm/board-copper.c b/arch/arm/mach-msm/board-copper.c
index 85241a4..59cb797 100644
--- a/arch/arm/mach-msm/board-copper.c
+++ b/arch/arm/mach-msm/board-copper.c
@@ -268,7 +268,7 @@
},
{
.irq_config_id = SMD_Q6,
- .subsys_name = "q6",
+ .subsys_name = "adsp",
.edge = SMD_APPS_QDSP,
.smd_int.irq_name = "adsp_smd_in",
diff --git a/arch/arm/mach-msm/board-fsm9xxx.c b/arch/arm/mach-msm/board-fsm9xxx.c
index b071353..0e2aa3b 100644
--- a/arch/arm/mach-msm/board-fsm9xxx.c
+++ b/arch/arm/mach-msm/board-fsm9xxx.c
@@ -89,6 +89,15 @@
#define GPIO_USER_FIRST 58
#define GPIO_USER_LAST 63
+#define GPIO_UIM_RESET 75
+#define GPIO_UIM_DATA_IO 76
+#define GPIO_UIM_CLOCK 77
+
+#define GPIO_PM_UIM_M_RST 26 /* UIM_RST input */
+#define GPIO_PM_UIM_RST 27 /* UIM_RST output */
+#define GPIO_PM_UIM_M_CLK 28 /* UIM_CLK input */
+#define GPIO_PM_UIM_CLK 29 /* UIM_CLK output */
+
#define FPGA_SDCC_STATUS 0x8E0001A8
/* Macros assume PMIC GPIOs start at 0 */
@@ -100,6 +109,8 @@
#define PMIC_GPIO_5V_PA_PWR 21 /* PMIC GPIO Number 22 */
#define PMIC_GPIO_4_2V_PA_PWR 22 /* PMIC GPIO Number 23 */
+#define PMIC_MPP_UIM_M_DATA 0 /* UIM_DATA input */
+#define PMIC_MPP_UIM_DATA 1 /* UIM_DATA output */
#define PMIC_MPP_3 2 /* PMIC MPP Number 3 */
#define PMIC_MPP_6 5 /* PMIC MPP Number 6 */
#define PMIC_MPP_7 6 /* PMIC MPP Number 7 */
@@ -181,6 +192,10 @@
PM8XXX_MPP_AOUT_LVL_1V25_2, AOUT_CTRL_ENABLE),
PM8XXX_MPP_INIT(PMIC_MPP_6, A_OUTPUT,
PM8XXX_MPP_AOUT_LVL_1V25_2, AOUT_CTRL_ENABLE),
+ PM8XXX_MPP_INIT(PMIC_MPP_UIM_M_DATA, D_BI_DIR,
+ PM8058_MPP_DIG_LEVEL_L3, BI_PULLUP_30KOHM),
+ PM8XXX_MPP_INIT(PMIC_MPP_UIM_DATA, D_BI_DIR,
+ PM8058_MPP_DIG_LEVEL_L3, BI_PULLUP_30KOHM),
};
for (i = 0; i < ARRAY_SIZE(pm8058_mpps); i++) {
@@ -597,6 +612,52 @@
}
#endif
+static struct msm_gpio uart3_uim_config_data[] = {
+ { GPIO_CFG(GPIO_UIM_RESET, 0, GPIO_CFG_OUTPUT,
+ GPIO_CFG_PULL_DOWN, GPIO_CFG_2MA), "UIM_Reset" },
+ { GPIO_CFG(GPIO_UIM_DATA_IO, 2, GPIO_CFG_OUTPUT,
+ GPIO_CFG_PULL_DOWN, GPIO_CFG_2MA), "UIM_Data" },
+ { GPIO_CFG(GPIO_UIM_CLOCK, 2, GPIO_CFG_OUTPUT,
+ GPIO_CFG_PULL_DOWN, GPIO_CFG_2MA), "UIM_Clock" },
+};
+
+static void fsm9xxx_init_uart3_uim(void)
+{
+ struct pm_gpio pmic_uim_gpio_in = {
+ .direction = PM_GPIO_DIR_IN,
+ .pull = PM_GPIO_PULL_NO,
+ .out_strength = PM_GPIO_STRENGTH_HIGH,
+ .function = PM_GPIO_FUNC_PAIRED,
+ .vin_sel = PM8058_GPIO_VIN_L3,
+ };
+ struct pm_gpio pmic_uim_gpio_out = {
+ .direction = PM_GPIO_DIR_OUT,
+ .pull = PM_GPIO_PULL_NO,
+ .out_strength = PM_GPIO_STRENGTH_HIGH,
+ .function = PM_GPIO_FUNC_PAIRED,
+ .vin_sel = PM8058_GPIO_VIN_L3,
+ };
+
+ /* TLMM */
+ msm_gpios_request_enable(uart3_uim_config_data,
+ ARRAY_SIZE(uart3_uim_config_data));
+
+ /* Put UIM to reset state */
+ gpio_direction_output(GPIO_UIM_RESET, 0);
+ gpio_set_value(GPIO_UIM_RESET, 0);
+ gpio_export(GPIO_UIM_RESET, false);
+
+ /* PMIC */
+ pm8xxx_gpio_config(PM8058_GPIO_PM_TO_SYS(GPIO_PM_UIM_M_RST),
+ &pmic_uim_gpio_in);
+ pm8xxx_gpio_config(PM8058_GPIO_PM_TO_SYS(GPIO_PM_UIM_RST),
+ &pmic_uim_gpio_out);
+ pm8xxx_gpio_config(PM8058_GPIO_PM_TO_SYS(GPIO_PM_UIM_M_CLK),
+ &pmic_uim_gpio_in);
+ pm8xxx_gpio_config(PM8058_GPIO_PM_TO_SYS(GPIO_PM_UIM_CLK),
+ &pmic_uim_gpio_out);
+}
+
/*
* SSBI
*/
@@ -833,6 +894,7 @@
#if defined(CONFIG_SERIAL_MSM) || defined(CONFIG_MSM_SERIAL_DEBUGGER)
&msm_device_uart1,
#endif
+ &msm_device_uart3,
#if defined(CONFIG_QFP_FUSE)
&fsm_qfp_fuse_device,
#endif
@@ -903,6 +965,7 @@
#ifdef CONFIG_SERIAL_MSM_CONSOLE
fsm9xxx_init_uart1();
#endif
+ fsm9xxx_init_uart3_uim();
#ifdef CONFIG_I2C_SSBI
msm_device_ssbi2.dev.platform_data = &msm_i2c_ssbi2_pdata;
msm_device_ssbi3.dev.platform_data = &msm_i2c_ssbi3_pdata;
diff --git a/arch/arm/mach-msm/board-msm7x27a.c b/arch/arm/mach-msm/board-msm7x27a.c
index dc473e6..7db4bda 100644
--- a/arch/arm/mach-msm/board-msm7x27a.c
+++ b/arch/arm/mach-msm/board-msm7x27a.c
@@ -50,6 +50,7 @@
#include <linux/atmel_maxtouch.h>
#include <linux/fmem.h>
#include <linux/msm_adc.h>
+#include <linux/ion.h>
#include "devices.h"
#include "timer.h"
#include "board-msm7x27a-regulator.h"
@@ -167,6 +168,15 @@
#endif
+#ifdef CONFIG_ION_MSM
+#define MSM_ION_HEAP_NUM 4
+static struct platform_device ion_dev;
+static int msm_ion_camera_size;
+static int msm_ion_audio_size;
+static int msm_ion_sf_size;
+#endif
+
+
static struct android_usb_platform_data android_usb_pdata = {
.update_pid_and_serial_num = usb_diag_update_pid_and_serial_num,
};
@@ -822,6 +832,9 @@
&asoc_msm_dai1,
&msm_batt_device,
&msm_adc_device,
+#ifdef CONFIG_ION_MSM
+ &ion_dev,
+#endif
};
static struct platform_device *msm8625_surf_devices[] __initdata = {
@@ -853,6 +866,81 @@
}
early_param("pmem_audio_size", pmem_audio_size_setup);
+static void fix_sizes(void)
+{
+ if (machine_is_msm7625a_surf() || machine_is_msm7625a_ffa()) {
+ pmem_mdp_size = MSM7x25A_MSM_PMEM_MDP_SIZE;
+ pmem_adsp_size = MSM7x25A_MSM_PMEM_ADSP_SIZE;
+ } else {
+ pmem_mdp_size = MSM_PMEM_MDP_SIZE;
+ pmem_adsp_size = MSM_PMEM_ADSP_SIZE;
+ }
+#ifdef CONFIG_ION_MSM
+ msm_ion_camera_size = pmem_adsp_size;
+ msm_ion_audio_size = (MSM_PMEM_AUDIO_SIZE + PMEM_KERNEL_EBI1_SIZE);
+ msm_ion_sf_size = pmem_mdp_size;
+#endif
+}
+
+#ifdef CONFIG_ION_MSM
+#ifdef CONFIG_MSM_MULTIMEDIA_USE_ION
+static struct ion_co_heap_pdata co_ion_pdata = {
+ .adjacent_mem_id = INVALID_HEAP_ID,
+ .align = PAGE_SIZE,
+};
+#endif
+
+/**
+ * These heaps are listed in the order they will be allocated.
+ * Don't swap the order unless you know what you are doing!
+ */
+static struct ion_platform_data ion_pdata = {
+ .nr = MSM_ION_HEAP_NUM,
+ .heaps = {
+ {
+ .id = ION_SYSTEM_HEAP_ID,
+ .type = ION_HEAP_TYPE_SYSTEM,
+ .name = ION_VMALLOC_HEAP_NAME,
+ },
+#ifdef CONFIG_MSM_MULTIMEDIA_USE_ION
+ /* PMEM_ADSP = CAMERA */
+ {
+ .id = ION_CAMERA_HEAP_ID,
+ .type = ION_HEAP_TYPE_CARVEOUT,
+ .name = ION_CAMERA_HEAP_NAME,
+ .memory_type = ION_EBI_TYPE,
+ .has_outer_cache = 1,
+ .extra_data = (void *)&co_ion_pdata,
+ },
+ /* PMEM_AUDIO */
+ {
+ .id = ION_AUDIO_HEAP_ID,
+ .type = ION_HEAP_TYPE_CARVEOUT,
+ .name = ION_AUDIO_HEAP_NAME,
+ .memory_type = ION_EBI_TYPE,
+ .has_outer_cache = 1,
+ .extra_data = (void *)&co_ion_pdata,
+ },
+ /* PMEM_MDP = SF */
+ {
+ .id = ION_SF_HEAP_ID,
+ .type = ION_HEAP_TYPE_CARVEOUT,
+ .name = ION_SF_HEAP_NAME,
+ .memory_type = ION_EBI_TYPE,
+ .has_outer_cache = 1,
+ .extra_data = (void *)&co_ion_pdata,
+ },
+#endif
+ }
+};
+
+static struct platform_device ion_dev = {
+ .name = "ion-msm",
+ .id = 1,
+ .dev = { .platform_data = &ion_pdata },
+};
+#endif
+
static struct memtype_reserve msm7x27a_reserve_table[] __initdata = {
[MEMTYPE_SMI] = {
},
@@ -865,27 +953,22 @@
};
#ifdef CONFIG_ANDROID_PMEM
+#ifndef CONFIG_MSM_MULTIMEDIA_USE_ION
static struct android_pmem_platform_data *pmem_pdata_array[] __initdata = {
&android_pmem_adsp_pdata,
&android_pmem_audio_pdata,
&android_pmem_pdata,
};
#endif
+#endif
static void __init size_pmem_devices(void)
{
#ifdef CONFIG_ANDROID_PMEM
+#ifndef CONFIG_MSM_MULTIMEDIA_USE_ION
unsigned int i;
unsigned int reusable_count = 0;
- if (machine_is_msm7625a_surf() || machine_is_msm7625a_ffa()) {
- pmem_mdp_size = MSM7x25A_MSM_PMEM_MDP_SIZE;
- pmem_adsp_size = MSM7x25A_MSM_PMEM_ADSP_SIZE;
- } else {
- pmem_mdp_size = MSM_PMEM_MDP_SIZE;
- pmem_adsp_size = MSM_PMEM_ADSP_SIZE;
- }
-
android_pmem_adsp_pdata.size = pmem_adsp_size;
android_pmem_pdata.size = pmem_mdp_size;
android_pmem_audio_pdata.size = pmem_audio_size;
@@ -910,29 +993,56 @@
}
}
#endif
-
+#endif
}
+#ifdef CONFIG_ANDROID_PMEM
+#ifndef CONFIG_MSM_MULTIMEDIA_USE_ION
static void __init reserve_memory_for(struct android_pmem_platform_data *p)
{
msm7x27a_reserve_table[p->memory_type].size += p->size;
}
+#endif
+#endif
static void __init reserve_pmem_memory(void)
{
#ifdef CONFIG_ANDROID_PMEM
+#ifndef CONFIG_MSM_MULTIMEDIA_USE_ION
unsigned int i;
for (i = 0; i < ARRAY_SIZE(pmem_pdata_array); ++i)
reserve_memory_for(pmem_pdata_array[i]);
msm7x27a_reserve_table[MEMTYPE_EBI1].size += pmem_kernel_ebi1_size;
#endif
+#endif
+}
+
+static void __init size_ion_devices(void)
+{
+#ifdef CONFIG_MSM_MULTIMEDIA_USE_ION
+ ion_pdata.heaps[1].size = msm_ion_camera_size;
+ ion_pdata.heaps[2].size = msm_ion_audio_size;
+ ion_pdata.heaps[3].size = msm_ion_sf_size;
+#endif
+}
+
+static void __init reserve_ion_memory(void)
+{
+#if defined(CONFIG_ION_MSM) && defined(CONFIG_MSM_MULTIMEDIA_USE_ION)
+ msm7x27a_reserve_table[MEMTYPE_EBI1].size += msm_ion_camera_size;
+ msm7x27a_reserve_table[MEMTYPE_EBI1].size += msm_ion_audio_size;
+ msm7x27a_reserve_table[MEMTYPE_EBI1].size += msm_ion_sf_size;
+#endif
}
static void __init msm7x27a_calculate_reserve_sizes(void)
{
+ fix_sizes();
size_pmem_devices();
reserve_pmem_memory();
+ size_ion_devices();
+ reserve_ion_memory();
}
static int msm7x27a_paddr_to_memtype(unsigned int paddr)
diff --git a/arch/arm/mach-msm/board-qrd7627a.c b/arch/arm/mach-msm/board-qrd7627a.c
index 9c80c8b..8eb961c 100644
--- a/arch/arm/mach-msm/board-qrd7627a.c
+++ b/arch/arm/mach-msm/board-qrd7627a.c
@@ -33,6 +33,7 @@
#include <linux/msm_adc.h>
#include <linux/fmem.h>
#include <linux/regulator/msm-gpio-regulator.h>
+#include <linux/ion.h>
#include <asm/mach/mmc.h>
#include <asm/mach-types.h>
#include <asm/mach/arch.h>
@@ -131,6 +132,14 @@
#ifdef CONFIG_ARCH_MSM7X27A
#define MSM_PMEM_MDP_SIZE 0x2300000
#define MSM_PMEM_ADSP_SIZE 0x1200000
+
+#define MSM_ION_AUDIO_SIZE (MSM_PMEM_AUDIO_SIZE + PMEM_KERNEL_EBI1_SIZE)
+#define MSM_ION_CAMERA_SIZE MSM_PMEM_ADSP_SIZE
+#define MSM_ION_SF_SIZE MSM_PMEM_MDP_SIZE
+#define MSM_ION_HEAP_NUM 4
+#ifdef CONFIG_ION_MSM
+static struct platform_device ion_dev;
+#endif
#endif
static struct android_usb_platform_data android_usb_pdata = {
@@ -708,6 +717,9 @@
&asoc_msm_dai1,
&msm_adc_device,
&fmem_device,
+#ifdef CONFIG_ION_MSM
+ &ion_dev,
+#endif
};
static struct platform_device *qrd7627a_devices[] __initdata = {
@@ -756,6 +768,68 @@
}
early_param("pmem_audio_size", pmem_audio_size_setup);
+#ifdef CONFIG_ION_MSM
+#ifdef CONFIG_MSM_MULTIMEDIA_USE_ION
+static struct ion_co_heap_pdata co_ion_pdata = {
+ .adjacent_mem_id = INVALID_HEAP_ID,
+ .align = PAGE_SIZE,
+};
+#endif
+
+/**
+ * These heaps are listed in the order they will be allocated.
+ * Don't swap the order unless you know what you are doing!
+ */
+static struct ion_platform_data ion_pdata = {
+ .nr = MSM_ION_HEAP_NUM,
+ .heaps = {
+ {
+ .id = ION_SYSTEM_HEAP_ID,
+ .type = ION_HEAP_TYPE_SYSTEM,
+ .name = ION_VMALLOC_HEAP_NAME,
+ },
+#ifdef CONFIG_MSM_MULTIMEDIA_USE_ION
+ /* PMEM_ADSP = CAMERA */
+ {
+ .id = ION_CAMERA_HEAP_ID,
+ .type = ION_HEAP_TYPE_CARVEOUT,
+ .name = ION_CAMERA_HEAP_NAME,
+ .size = MSM_ION_CAMERA_SIZE,
+ .memory_type = ION_EBI_TYPE,
+ .has_outer_cache = 1,
+ .extra_data = (void *)&co_ion_pdata,
+ },
+ /* PMEM_AUDIO */
+ {
+ .id = ION_AUDIO_HEAP_ID,
+ .type = ION_HEAP_TYPE_CARVEOUT,
+ .name = ION_AUDIO_HEAP_NAME,
+ .size = MSM_ION_AUDIO_SIZE,
+ .memory_type = ION_EBI_TYPE,
+ .has_outer_cache = 1,
+ .extra_data = (void *)&co_ion_pdata,
+ },
+ /* PMEM_MDP = SF */
+ {
+ .id = ION_SF_HEAP_ID,
+ .type = ION_HEAP_TYPE_CARVEOUT,
+ .name = ION_SF_HEAP_NAME,
+ .size = MSM_ION_SF_SIZE,
+ .memory_type = ION_EBI_TYPE,
+ .has_outer_cache = 1,
+ .extra_data = (void *)&co_ion_pdata,
+ },
+#endif
+ }
+};
+
+static struct platform_device ion_dev = {
+ .name = "ion-msm",
+ .id = 1,
+ .dev = { .platform_data = &ion_pdata },
+};
+#endif
+
static struct memtype_reserve msm7627a_reserve_table[] __initdata = {
[MEMTYPE_SMI] = {
},
@@ -768,16 +842,19 @@
};
#ifdef CONFIG_ANDROID_PMEM
+#ifndef CONFIG_MSM_MULTIMEDIA_USE_ION
static struct android_pmem_platform_data *pmem_pdata_array[] __initdata = {
&android_pmem_adsp_pdata,
&android_pmem_audio_pdata,
&android_pmem_pdata,
};
#endif
+#endif
static void __init size_pmem_devices(void)
{
#ifdef CONFIG_ANDROID_PMEM
+#ifndef CONFIG_MSM_MULTIMEDIA_USE_ION
unsigned int i;
unsigned int reusable_count = 0;
@@ -804,30 +881,46 @@
pdata->reusable = 0;
}
}
-
+#endif
#endif
}
+#ifdef CONFIG_ANDROID_PMEM
+#ifndef CONFIG_MSM_MULTIMEDIA_USE_ION
static void __init reserve_memory_for(struct android_pmem_platform_data *p)
{
msm7627a_reserve_table[p->memory_type].size += p->size;
}
+#endif
+#endif
static void __init reserve_pmem_memory(void)
{
#ifdef CONFIG_ANDROID_PMEM
+#ifndef CONFIG_MSM_MULTIMEDIA_USE_ION
unsigned int i;
for (i = 0; i < ARRAY_SIZE(pmem_pdata_array); ++i)
reserve_memory_for(pmem_pdata_array[i]);
msm7627a_reserve_table[MEMTYPE_EBI1].size += pmem_kernel_ebi1_size;
#endif
+#endif
+}
+
+static void __init reserve_ion_memory(void)
+{
+#if defined(CONFIG_ION_MSM) && defined(CONFIG_MSM_MULTIMEDIA_USE_ION)
+ msm7627a_reserve_table[MEMTYPE_EBI1].size += MSM_ION_CAMERA_SIZE;
+ msm7627a_reserve_table[MEMTYPE_EBI1].size += MSM_ION_AUDIO_SIZE;
+ msm7627a_reserve_table[MEMTYPE_EBI1].size += MSM_ION_SF_SIZE;
+#endif
}
static void __init msm7627a_calculate_reserve_sizes(void)
{
size_pmem_devices();
reserve_pmem_memory();
+ reserve_ion_memory();
}
static int msm7627a_paddr_to_memtype(unsigned int paddr)
diff --git a/arch/arm/mach-msm/clock-7x30.c b/arch/arm/mach-msm/clock-7x30.c
index aa94be6..225ea2b 100644
--- a/arch/arm/mach-msm/clock-7x30.c
+++ b/arch/arm/mach-msm/clock-7x30.c
@@ -200,7 +200,7 @@
#define PCOM_XO_TCXO 0
#define PCOM_XO_LPXO 1
-static bool pcom_is_local(struct clk *clk)
+static bool pcom_is_local(struct clk *c)
{
return false;
}
@@ -2441,7 +2441,7 @@
struct measure_sel {
u32 test_vector;
- struct clk *clk;
+ struct clk *c;
};
static struct measure_sel measure_mux[] = {
@@ -2538,17 +2538,17 @@
{ CLK_TEST_LS(0x3F), &usb_hs_clk.c },
};
-static struct measure_sel *find_measure_sel(struct clk *clk)
+static struct measure_sel *find_measure_sel(struct clk *c)
{
int i;
for (i = 0; i < ARRAY_SIZE(measure_mux); i++)
- if (measure_mux[i].clk == clk)
+ if (measure_mux[i].c == c)
return &measure_mux[i];
return NULL;
}
-static int measure_clk_set_parent(struct clk *clk, struct clk *parent)
+static int measure_clk_set_parent(struct clk *c, struct clk *parent)
{
struct measure_sel *p;
unsigned long flags;
@@ -2599,7 +2599,7 @@
/* Perform a hardware rate measurement for a given clock.
FOR DEBUG USE ONLY: Measurements take ~15 ms! */
-static unsigned long measure_clk_get_rate(struct clk *clk)
+static unsigned long measure_clk_get_rate(struct clk *c)
{
unsigned long flags;
u32 regval, prph_web_reg_old;
@@ -2647,12 +2647,12 @@
return ret;
}
#else /* !CONFIG_DEBUG_FS */
-static int measure_clk_set_parent(struct clk *clk, struct clk *parent)
+static int measure_clk_set_parent(struct clk *c, struct clk *parent)
{
return -EINVAL;
}
-static unsigned long measure_clk_get_rate(struct clk *clk)
+static unsigned long measure_clk_get_rate(struct clk *c)
{
return 0;
}
@@ -2670,14 +2670,14 @@
};
/* Implementation for clk_set_flags(). */
-int soc_clk_set_flags(struct clk *clk, unsigned clk_flags)
+int soc_clk_set_flags(struct clk *c, unsigned clk_flags)
{
uint32_t regval, ret = 0;
unsigned long flags;
spin_lock_irqsave(&local_clock_reg_lock, flags);
- if (clk == &vfe_clk.c) {
+ if (c == &vfe_clk.c) {
regval = readl_relaxed(CAM_VFE_NS_REG);
/* Flag values chosen for backward compatibility
* with proc_comm remote clock control. */
@@ -2701,17 +2701,15 @@
return ret;
}
-static int msm7x30_clk_reset(struct clk *clk, enum clk_reset_action action)
+static int msm7x30_clk_reset(struct clk *c, enum clk_reset_action action)
{
/* reset_mask is actually a proc_comm id */
- unsigned id = to_rcg_clk(clk)->b.reset_mask;
- return pc_clk_reset(id, action);
+ return pc_clk_reset(to_rcg_clk(c)->b.reset_mask, action);
}
-static int soc_branch_clk_reset(struct clk *clk, enum clk_reset_action action)
+static int soc_branch_clk_reset(struct clk *c, enum clk_reset_action action)
{
- unsigned id = to_branch_clk(clk)->b.reset_mask;
- return pc_clk_reset(id, action);
+ return pc_clk_reset(to_branch_clk(c)->b.reset_mask, action);
}
/*
diff --git a/arch/arm/mach-msm/clock-8960.c b/arch/arm/mach-msm/clock-8960.c
index 7866fc7..fa91249 100644
--- a/arch/arm/mach-msm/clock-8960.c
+++ b/arch/arm/mach-msm/clock-8960.c
@@ -2858,9 +2858,9 @@
struct clk c;
};
-static inline struct pix_rdi_clk *to_pix_rdi_clk(struct clk *clk)
+static inline struct pix_rdi_clk *to_pix_rdi_clk(struct clk *c)
{
- return container_of(clk, struct pix_rdi_clk, c);
+ return container_of(c, struct pix_rdi_clk, c);
}
static int pix_rdi_clk_set_rate(struct clk *c, unsigned long rate)
@@ -2868,7 +2868,7 @@
int ret, i;
u32 reg;
unsigned long flags;
- struct pix_rdi_clk *clk = to_pix_rdi_clk(c);
+ struct pix_rdi_clk *rdi = to_pix_rdi_clk(c);
struct clk **mux_map = pix_rdi_mux_map;
/*
@@ -2889,32 +2889,32 @@
goto err;
}
/* Keep the new source on when switching inputs of an enabled clock */
- if (clk->enabled) {
- clk_disable(mux_map[clk->cur_rate]);
+ if (rdi->enabled) {
+ clk_disable(mux_map[rdi->cur_rate]);
clk_enable(mux_map[rate]);
}
spin_lock_irqsave(&local_clock_reg_lock, flags);
- reg = readl_relaxed(clk->s2_reg);
- reg &= ~clk->s2_mask;
- reg |= rate == 2 ? clk->s2_mask : 0;
- writel_relaxed(reg, clk->s2_reg);
+ reg = readl_relaxed(rdi->s2_reg);
+ reg &= ~rdi->s2_mask;
+ reg |= rate == 2 ? rdi->s2_mask : 0;
+ writel_relaxed(reg, rdi->s2_reg);
/*
* Wait at least 6 cycles of slowest clock
* for the glitch-free MUX to fully switch sources.
*/
mb();
udelay(1);
- reg = readl_relaxed(clk->s_reg);
- reg &= ~clk->s_mask;
- reg |= rate == 1 ? clk->s_mask : 0;
- writel_relaxed(reg, clk->s_reg);
+ reg = readl_relaxed(rdi->s_reg);
+ reg &= ~rdi->s_mask;
+ reg |= rate == 1 ? rdi->s_mask : 0;
+ writel_relaxed(reg, rdi->s_reg);
/*
* Wait at least 6 cycles of slowest clock
* for the glitch-free MUX to fully switch sources.
*/
mb();
udelay(1);
- clk->cur_rate = rate;
+ rdi->cur_rate = rate;
spin_unlock_irqrestore(&local_clock_reg_lock, flags);
err:
for (i--; i >= 0; i--)
@@ -2931,12 +2931,12 @@
static int pix_rdi_clk_enable(struct clk *c)
{
unsigned long flags;
- struct pix_rdi_clk *clk = to_pix_rdi_clk(c);
+ struct pix_rdi_clk *rdi = to_pix_rdi_clk(c);
spin_lock_irqsave(&local_clock_reg_lock, flags);
- __branch_clk_enable_reg(&clk->b, clk->c.dbg_name);
+ __branch_enable_reg(&rdi->b, rdi->c.dbg_name);
spin_unlock_irqrestore(&local_clock_reg_lock, flags);
- clk->enabled = true;
+ rdi->enabled = true;
return 0;
}
@@ -2944,24 +2944,22 @@
static void pix_rdi_clk_disable(struct clk *c)
{
unsigned long flags;
- struct pix_rdi_clk *clk = to_pix_rdi_clk(c);
+ struct pix_rdi_clk *rdi = to_pix_rdi_clk(c);
spin_lock_irqsave(&local_clock_reg_lock, flags);
- __branch_clk_disable_reg(&clk->b, clk->c.dbg_name);
+ __branch_disable_reg(&rdi->b, rdi->c.dbg_name);
spin_unlock_irqrestore(&local_clock_reg_lock, flags);
- clk->enabled = false;
+ rdi->enabled = false;
}
-static int pix_rdi_clk_reset(struct clk *clk, enum clk_reset_action action)
+static int pix_rdi_clk_reset(struct clk *c, enum clk_reset_action action)
{
- return branch_reset(&to_pix_rdi_clk(clk)->b, action);
+ return branch_reset(&to_pix_rdi_clk(c)->b, action);
}
static struct clk *pix_rdi_clk_get_parent(struct clk *c)
{
- struct pix_rdi_clk *clk = to_pix_rdi_clk(c);
-
- return pix_rdi_mux_map[clk->cur_rate];
+ return pix_rdi_mux_map[to_pix_rdi_clk(c)->cur_rate];
}
static int pix_rdi_clk_list_rate(struct clk *c, unsigned n)
@@ -2974,17 +2972,17 @@
static enum handoff pix_rdi_clk_handoff(struct clk *c)
{
u32 reg;
- struct pix_rdi_clk *clk = to_pix_rdi_clk(c);
+ struct pix_rdi_clk *rdi = to_pix_rdi_clk(c);
enum handoff ret;
- ret = branch_handoff(&clk->b, &clk->c);
+ ret = branch_handoff(&rdi->b, &rdi->c);
if (ret == HANDOFF_DISABLED_CLK)
return ret;
- reg = readl_relaxed(clk->s_reg);
- clk->cur_rate = reg & clk->s_mask ? 1 : 0;
- reg = readl_relaxed(clk->s2_reg);
- clk->cur_rate = reg & clk->s2_mask ? 2 : clk->cur_rate;
+ reg = readl_relaxed(rdi->s_reg);
+ rdi->cur_rate = reg & rdi->s_mask ? 1 : 0;
+ reg = readl_relaxed(rdi->s2_reg);
+ rdi->cur_rate = reg & rdi->s2_mask ? 2 : rdi->cur_rate;
return HANDOFF_ENABLED_CLK;
}
@@ -3897,7 +3895,7 @@
},
};
-static int hdmi_pll_clk_enable(struct clk *clk)
+static int hdmi_pll_clk_enable(struct clk *c)
{
int ret;
unsigned long flags;
@@ -3907,7 +3905,7 @@
return ret;
}
-static void hdmi_pll_clk_disable(struct clk *clk)
+static void hdmi_pll_clk_disable(struct clk *c)
{
unsigned long flags;
spin_lock_irqsave(&local_clock_reg_lock, flags);
@@ -3915,12 +3913,12 @@
spin_unlock_irqrestore(&local_clock_reg_lock, flags);
}
-static unsigned long hdmi_pll_clk_get_rate(struct clk *clk)
+static unsigned long hdmi_pll_clk_get_rate(struct clk *c)
{
return hdmi_pll_get_rate();
}
-static struct clk *hdmi_pll_clk_get_parent(struct clk *clk)
+static struct clk *hdmi_pll_clk_get_parent(struct clk *c)
{
return &pxo_clk.c;
}
@@ -3975,12 +3973,12 @@
* Unlike other clocks, the TV rate is adjusted through PLL
* re-programming. It is also routed through an MND divider.
*/
-void set_rate_tv(struct rcg_clk *clk, struct clk_freq_tbl *nf)
+void set_rate_tv(struct rcg_clk *rcg, struct clk_freq_tbl *nf)
{
unsigned long pll_rate = (unsigned long)nf->extra_freq_data;
if (pll_rate)
hdmi_pll_set_rate(pll_rate);
- set_rate_mnd(clk, nf);
+ set_rate_mnd(rcg, nf);
}
static struct rcg_clk tv_src_clk = {
@@ -4585,6 +4583,7 @@
DEFINE_CLK_RPM(mmfpb_clk, mmfpb_a_clk, MMFPB, NULL);
DEFINE_CLK_RPM(sfab_clk, sfab_a_clk, SYSTEM_FABRIC, NULL);
DEFINE_CLK_RPM(sfpb_clk, sfpb_a_clk, SFPB, NULL);
+DEFINE_CLK_RPM_QDSS(qdss_clk, qdss_a_clk);
static DEFINE_CLK_VOTER(sfab_msmbus_a_clk, &sfab_a_clk.c, 0);
static DEFINE_CLK_VOTER(sfab_tmr_a_clk, &sfab_a_clk.c, 0);
@@ -4616,7 +4615,7 @@
#ifdef CONFIG_DEBUG_FS
struct measure_sel {
u32 test_vector;
- struct clk *clk;
+ struct clk *c;
};
static DEFINE_CLK_MEASURE(l2_m_clk);
@@ -4840,12 +4839,12 @@
{ TEST_CPUL2(0x5), &krait3_m_clk },
};
-static struct measure_sel *find_measure_sel(struct clk *clk)
+static struct measure_sel *find_measure_sel(struct clk *c)
{
int i;
for (i = 0; i < ARRAY_SIZE(measure_mux); i++)
- if (measure_mux[i].clk == clk)
+ if (measure_mux[i].c == c)
return &measure_mux[i];
return NULL;
}
@@ -4855,7 +4854,7 @@
int ret = 0;
u32 clk_sel;
struct measure_sel *p;
- struct measure_clk *clk = to_measure_clk(c);
+ struct measure_clk *measure = to_measure_clk(c);
unsigned long flags;
if (!parent)
@@ -4871,9 +4870,9 @@
* Program the test vector, measurement period (sample_ticks)
* and scaling multiplier.
*/
- clk->sample_ticks = 0x10000;
+ measure->sample_ticks = 0x10000;
clk_sel = p->test_vector & TEST_CLK_SEL_MASK;
- clk->multiplier = 1;
+ measure->multiplier = 1;
switch (p->test_vector >> TEST_TYPE_SHIFT) {
case TEST_TYPE_PER_LS:
writel_relaxed(0x4030D00|BVAL(7, 0, clk_sel), CLK_TEST_REG);
@@ -4902,8 +4901,8 @@
case TEST_TYPE_CPUL2:
writel_relaxed(0x4030400, CLK_TEST_REG);
writel_relaxed(0x80|BVAL(5, 3, clk_sel), GCC_APCS_CLK_DIAG);
- clk->sample_ticks = 0x4000;
- clk->multiplier = 2;
+ measure->sample_ticks = 0x4000;
+ measure->multiplier = 2;
break;
default:
ret = -EPERM;
@@ -4946,7 +4945,7 @@
unsigned long flags;
u32 pdm_reg_backup, ringosc_reg_backup;
u64 raw_count_short, raw_count_full;
- struct measure_clk *clk = to_measure_clk(c);
+ struct measure_clk *measure = to_measure_clk(c);
unsigned ret;
ret = clk_prepare_enable(&cxo_clk.c);
@@ -4973,7 +4972,7 @@
/* Run a short measurement. (~1 ms) */
raw_count_short = run_measurement(0x1000);
/* Run a full measurement. (~14 ms) */
- raw_count_full = run_measurement(clk->sample_ticks);
+ raw_count_full = run_measurement(measure->sample_ticks);
writel_relaxed(ringosc_reg_backup, RINGOSC_NS_REG);
writel_relaxed(pdm_reg_backup, PDM_CLK_NS_REG);
@@ -4984,8 +4983,8 @@
else {
/* Compute rate in Hz. */
raw_count_full = ((raw_count_full * 10) + 15) * 4800000;
- do_div(raw_count_full, ((clk->sample_ticks * 10) + 35));
- ret = (raw_count_full * clk->multiplier);
+ do_div(raw_count_full, ((measure->sample_ticks * 10) + 35));
+ ret = (raw_count_full * measure->multiplier);
}
/* Route dbg_hs_clk to PLLTEST. 300mV single-ended amplitude. */
@@ -4997,12 +4996,12 @@
return ret;
}
#else /* !CONFIG_DEBUG_FS */
-static int measure_clk_set_parent(struct clk *clk, struct clk *parent)
+static int measure_clk_set_parent(struct clk *c, struct clk *parent)
{
return -EINVAL;
}
-static unsigned long measure_clk_get_rate(struct clk *clk)
+static unsigned long measure_clk_get_rate(struct clk *c)
{
return 0;
}
@@ -5070,6 +5069,12 @@
CLK_LOOKUP("mem_a_clk", ebi1_msmbus_a_clk.c, "msm_bus"),
CLK_LOOKUP("dfab_clk", dfab_msmbus_clk.c, "msm_bus"),
CLK_LOOKUP("dfab_a_clk", dfab_msmbus_a_clk.c, "msm_bus"),
+ CLK_LOOKUP("core_a_clk", qdss_a_clk.c, ""),
+ CLK_LOOKUP("core_clk", qdss_clk.c, "msm_etb.0"),
+ CLK_LOOKUP("core_clk", qdss_clk.c, "msm_tpiu.0"),
+ CLK_LOOKUP("core_clk", qdss_clk.c, "msm_funnel.0"),
+ CLK_LOOKUP("core_clk", qdss_clk.c, "msm_stm.0"),
+ CLK_LOOKUP("core_clk", qdss_clk.c, "msm_etm.0"),
CLK_LOOKUP("ebi1_clk", ebi1_clk.c, ""),
CLK_LOOKUP("mmfpb_clk", mmfpb_clk.c, ""),
@@ -5394,6 +5399,12 @@
CLK_LOOKUP("mem_a_clk", ebi1_msmbus_a_clk.c, "msm_bus"),
CLK_LOOKUP("dfab_clk", dfab_msmbus_clk.c, "msm_bus"),
CLK_LOOKUP("dfab_a_clk", dfab_msmbus_a_clk.c, "msm_bus"),
+ CLK_LOOKUP("core_a_clk", qdss_a_clk.c, ""),
+ CLK_LOOKUP("core_clk", qdss_clk.c, "msm_etb.0"),
+ CLK_LOOKUP("core_clk", qdss_clk.c, "msm_tpiu.0"),
+ CLK_LOOKUP("core_clk", qdss_clk.c, "msm_funnel.0"),
+ CLK_LOOKUP("core_clk", qdss_clk.c, "msm_stm.0"),
+ CLK_LOOKUP("core_clk", qdss_clk.c, "msm_etm.0"),
CLK_LOOKUP("ebi1_clk", ebi1_clk.c, NULL),
CLK_LOOKUP("mmfpb_clk", mmfpb_clk.c, NULL),
@@ -5710,6 +5721,12 @@
CLK_LOOKUP("mem_a_clk", ebi1_msmbus_a_clk.c, "msm_bus"),
CLK_LOOKUP("dfab_clk", dfab_msmbus_clk.c, "msm_bus"),
CLK_LOOKUP("dfab_a_clk", dfab_msmbus_a_clk.c, "msm_bus"),
+ CLK_LOOKUP("core_a_clk", qdss_a_clk.c, ""),
+ CLK_LOOKUP("core_clk", qdss_clk.c, "msm_etb.0"),
+ CLK_LOOKUP("core_clk", qdss_clk.c, "msm_tpiu.0"),
+ CLK_LOOKUP("core_clk", qdss_clk.c, "msm_funnel.0"),
+ CLK_LOOKUP("core_clk", qdss_clk.c, "msm_stm.0"),
+ CLK_LOOKUP("core_clk", qdss_clk.c, "msm_etm.0"),
CLK_LOOKUP("ebi1_clk", ebi1_clk.c, NULL),
CLK_LOOKUP("mmfpb_clk", mmfpb_clk.c, NULL),
diff --git a/arch/arm/mach-msm/clock-8x60.c b/arch/arm/mach-msm/clock-8x60.c
index 74d71a2..da7dca7 100644
--- a/arch/arm/mach-msm/clock-8x60.c
+++ b/arch/arm/mach-msm/clock-8x60.c
@@ -341,24 +341,24 @@
},
};
-static int pll4_clk_enable(struct clk *clk)
+static int pll4_clk_enable(struct clk *c)
{
struct msm_rpm_iv_pair iv = { MSM_RPM_ID_PLL_4, 1 };
return msm_rpm_set_noirq(MSM_RPM_CTX_SET_0, &iv, 1);
}
-static void pll4_clk_disable(struct clk *clk)
+static void pll4_clk_disable(struct clk *c)
{
struct msm_rpm_iv_pair iv = { MSM_RPM_ID_PLL_4, 0 };
msm_rpm_set_noirq(MSM_RPM_CTX_SET_0, &iv, 1);
}
-static struct clk *pll4_clk_get_parent(struct clk *clk)
+static struct clk *pll4_clk_get_parent(struct clk *c)
{
return &pxo_clk.c;
}
-static bool pll4_clk_is_local(struct clk *clk)
+static bool pll4_clk_is_local(struct clk *c)
{
return false;
}
@@ -397,7 +397,7 @@
/* Unlike other clocks, the TV rate is adjusted through PLL
* re-programming. It is also routed through an MND divider. */
-static void set_rate_tv(struct rcg_clk *clk, struct clk_freq_tbl *nf)
+static void set_rate_tv(struct rcg_clk *rcg, struct clk_freq_tbl *nf)
{
struct pll_rate *rate = nf->extra_freq_data;
uint32_t pll_mode, pll_config, misc_cc2;
@@ -426,7 +426,7 @@
writel_relaxed(pll_config, MM_PLL2_CONFIG_REG);
/* Configure MND. */
- set_rate_mnd(clk, nf);
+ set_rate_mnd(rcg, nf);
/* Configure hdmi_ref_clk to be equal to the TV clock rate. */
misc_cc2 = readl_relaxed(MISC_CC2_REG);
@@ -3133,7 +3133,7 @@
#ifdef CONFIG_DEBUG_FS
struct measure_sel {
u32 test_vector;
- struct clk *clk;
+ struct clk *c;
};
static struct measure_sel measure_mux[] = {
@@ -3308,12 +3308,12 @@
{ TEST_SC(0x42), &l2_m_clk },
};
-static struct measure_sel *find_measure_sel(struct clk *clk)
+static struct measure_sel *find_measure_sel(struct clk *c)
{
int i;
for (i = 0; i < ARRAY_SIZE(measure_mux); i++)
- if (measure_mux[i].clk == clk)
+ if (measure_mux[i].c == c)
return &measure_mux[i];
return NULL;
}
@@ -3323,7 +3323,7 @@
int ret = 0;
u32 clk_sel;
struct measure_sel *p;
- struct measure_clk *clk = to_measure_clk(c);
+ struct measure_clk *measure = to_measure_clk(c);
unsigned long flags;
if (!parent)
@@ -3340,9 +3340,9 @@
* and scaling factors (multiplier, divider).
*/
clk_sel = p->test_vector & TEST_CLK_SEL_MASK;
- clk->sample_ticks = 0x10000;
- clk->multiplier = 1;
- clk->divider = 1;
+ measure->sample_ticks = 0x10000;
+ measure->multiplier = 1;
+ measure->divider = 1;
switch (p->test_vector >> TEST_TYPE_SHIFT) {
case TEST_TYPE_PER_LS:
writel_relaxed(0x4030D00|BVAL(7, 0, clk_sel), CLK_TEST_REG);
@@ -3355,7 +3355,7 @@
writel_relaxed(BVAL(6, 1, clk_sel)|BIT(0), DBG_CFG_REG_LS_REG);
break;
case TEST_TYPE_MM_HS2X:
- clk->divider = 2;
+ measure->divider = 2;
case TEST_TYPE_MM_HS:
writel_relaxed(0x402B800, CLK_TEST_REG);
writel_relaxed(BVAL(6, 1, clk_sel)|BIT(0), DBG_CFG_REG_HS_REG);
@@ -3367,8 +3367,8 @@
break;
case TEST_TYPE_SC:
writel_relaxed(0x5020000|BVAL(16, 10, clk_sel), CLK_TEST_REG);
- clk->sample_ticks = 0x4000;
- clk->multiplier = 2;
+ measure->sample_ticks = 0x4000;
+ measure->multiplier = 2;
break;
default:
ret = -EPERM;
@@ -3410,7 +3410,7 @@
unsigned long flags;
u32 pdm_reg_backup, ringosc_reg_backup;
u64 raw_count_short, raw_count_full;
- struct measure_clk *clk = to_measure_clk(c);
+ struct measure_clk *measure = to_measure_clk(c);
unsigned ret;
spin_lock_irqsave(&local_clock_reg_lock, flags);
@@ -3431,7 +3431,7 @@
/* Run a short measurement. (~1 ms) */
raw_count_short = run_measurement(0x1000);
/* Run a full measurement. (~14 ms) */
- raw_count_full = run_measurement(clk->sample_ticks);
+ raw_count_full = run_measurement(measure->sample_ticks);
writel_relaxed(ringosc_reg_backup, RINGOSC_NS_REG);
writel_relaxed(pdm_reg_backup, PDM_CLK_NS_REG);
@@ -3442,9 +3442,9 @@
else {
/* Compute rate in Hz. */
raw_count_full = ((raw_count_full * 10) + 15) * 4800000;
- do_div(raw_count_full,
- (((clk->sample_ticks * 10) + 35) * clk->divider));
- ret = (raw_count_full * clk->multiplier);
+ do_div(raw_count_full, (((measure->sample_ticks * 10) + 35)
+ * measure->divider));
+ ret = (raw_count_full * measure->multiplier);
}
/* Route dbg_hs_clk to PLLTEST. 300mV single-ended amplitude. */
@@ -3454,12 +3454,12 @@
return ret;
}
#else /* !CONFIG_DEBUG_FS */
-static int measure_clk_set_parent(struct clk *clk, struct clk *parent)
+static int measure_clk_set_parent(struct clk *c, struct clk *parent)
{
return -EINVAL;
}
-static unsigned long measure_clk_get_rate(struct clk *clk)
+static unsigned long measure_clk_get_rate(struct clk *c)
{
return 0;
}
diff --git a/arch/arm/mach-msm/clock-9615.c b/arch/arm/mach-msm/clock-9615.c
index a2e0bc9..f7ccb35 100644
--- a/arch/arm/mach-msm/clock-9615.c
+++ b/arch/arm/mach-msm/clock-9615.c
@@ -216,33 +216,33 @@
static DEFINE_SPINLOCK(soft_vote_lock);
-static int pll_acpu_vote_clk_enable(struct clk *clk)
+static int pll_acpu_vote_clk_enable(struct clk *c)
{
int ret = 0;
unsigned long flags;
- struct pll_vote_clk *pll = to_pll_vote_clk(clk);
+ struct pll_vote_clk *pllv = to_pll_vote_clk(c);
spin_lock_irqsave(&soft_vote_lock, flags);
- if (!*pll->soft_vote)
- ret = pll_vote_clk_enable(clk);
+ if (!*pllv->soft_vote)
+ ret = pll_vote_clk_enable(c);
if (ret == 0)
- *pll->soft_vote |= (pll->soft_vote_mask);
+ *pllv->soft_vote |= (pllv->soft_vote_mask);
spin_unlock_irqrestore(&soft_vote_lock, flags);
return ret;
}
-static void pll_acpu_vote_clk_disable(struct clk *clk)
+static void pll_acpu_vote_clk_disable(struct clk *c)
{
unsigned long flags;
- struct pll_vote_clk *pll = to_pll_vote_clk(clk);
+ struct pll_vote_clk *pllv = to_pll_vote_clk(c);
spin_lock_irqsave(&soft_vote_lock, flags);
- *pll->soft_vote &= ~(pll->soft_vote_mask);
- if (!*pll->soft_vote)
- pll_vote_clk_disable(clk);
+ *pllv->soft_vote &= ~(pllv->soft_vote_mask);
+ if (!*pllv->soft_vote)
+ pll_vote_clk_disable(c);
spin_unlock_irqrestore(&soft_vote_lock, flags);
}
@@ -1376,7 +1376,7 @@
#ifdef CONFIG_DEBUG_FS
struct measure_sel {
u32 test_vector;
- struct clk *clk;
+ struct clk *c;
};
static DEFINE_CLK_MEASURE(q6sw_clk);
@@ -1447,12 +1447,12 @@
{ TEST_LPA_HS(0x00), &q6_func_clk },
};
-static struct measure_sel *find_measure_sel(struct clk *clk)
+static struct measure_sel *find_measure_sel(struct clk *c)
{
int i;
for (i = 0; i < ARRAY_SIZE(measure_mux); i++)
- if (measure_mux[i].clk == clk)
+ if (measure_mux[i].c == c)
return &measure_mux[i];
return NULL;
}
@@ -1462,7 +1462,7 @@
int ret = 0;
u32 clk_sel;
struct measure_sel *p;
- struct measure_clk *clk = to_measure_clk(c);
+ struct measure_clk *measure = to_measure_clk(c);
unsigned long flags;
if (!parent)
@@ -1478,9 +1478,9 @@
* Program the test vector, measurement period (sample_ticks)
* and scaling multiplier.
*/
- clk->sample_ticks = 0x10000;
+ measure->sample_ticks = 0x10000;
clk_sel = p->test_vector & TEST_CLK_SEL_MASK;
- clk->multiplier = 1;
+ measure->multiplier = 1;
switch (p->test_vector >> TEST_TYPE_SHIFT) {
case TEST_TYPE_PER_LS:
writel_relaxed(0x4030D00|BVAL(7, 0, clk_sel), CLK_TEST_REG);
@@ -1539,7 +1539,7 @@
unsigned long flags;
u32 pdm_reg_backup, ringosc_reg_backup;
u64 raw_count_short, raw_count_full;
- struct measure_clk *clk = to_measure_clk(c);
+ struct measure_clk *measure = to_measure_clk(c);
unsigned ret;
spin_lock_irqsave(&local_clock_reg_lock, flags);
@@ -1560,7 +1560,7 @@
/* Run a short measurement. (~1 ms) */
raw_count_short = run_measurement(0x1000);
/* Run a full measurement. (~14 ms) */
- raw_count_full = run_measurement(clk->sample_ticks);
+ raw_count_full = run_measurement(measure->sample_ticks);
writel_relaxed(ringosc_reg_backup, RINGOSC_NS_REG);
writel_relaxed(pdm_reg_backup, PDM_CLK_NS_REG);
@@ -1571,8 +1571,8 @@
else {
/* Compute rate in Hz. */
raw_count_full = ((raw_count_full * 10) + 15) * 4800000;
- do_div(raw_count_full, ((clk->sample_ticks * 10) + 35));
- ret = (raw_count_full * clk->multiplier);
+ do_div(raw_count_full, ((measure->sample_ticks * 10) + 35));
+ ret = (raw_count_full * measure->multiplier);
}
/* Route dbg_hs_clk to PLLTEST. 300mV single-ended amplitude. */
@@ -1582,12 +1582,12 @@
return ret;
}
#else /* !CONFIG_DEBUG_FS */
-static int measure_clk_set_parent(struct clk *clk, struct clk *parent)
+static int measure_clk_set_parent(struct clk *c, struct clk *parent)
{
return -EINVAL;
}
-static unsigned long measure_clk_get_rate(struct clk *clk)
+static unsigned long measure_clk_get_rate(struct clk *c)
{
return 0;
}
diff --git a/arch/arm/mach-msm/clock-copper.c b/arch/arm/mach-msm/clock-copper.c
index 2dadc4c..fcb69f0 100644
--- a/arch/arm/mach-msm/clock-copper.c
+++ b/arch/arm/mach-msm/clock-copper.c
@@ -5017,6 +5017,7 @@
static void __init msmcopper_clock_post_init(void)
{
clk_set_rate(&axi_clk_src.c, 333330000);
+ clk_set_rate(&ocmemnoc_clk_src.c, 333330000);
/* Set rates for single-rate clocks. */
clk_set_rate(&usb30_master_clk_src.c,
diff --git a/arch/arm/mach-msm/clock-fsm9xxx.c b/arch/arm/mach-msm/clock-fsm9xxx.c
index 13a5b65..c188ba6 100644
--- a/arch/arm/mach-msm/clock-fsm9xxx.c
+++ b/arch/arm/mach-msm/clock-fsm9xxx.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
@@ -24,6 +24,7 @@
static struct clk_lookup msm_clocks_fsm9xxx[] = {
CLK_DUMMY("core_clk", ADM0_CLK, "msm_dmov", OFF),
CLK_DUMMY("core_clk", UART1_CLK, "msm_serial.0", OFF),
+ CLK_DUMMY("core_clk", UART3_CLK, "msm_uim.2", OFF),
CLK_DUMMY("core_clk", CE_CLK, "qce.0", OFF),
CLK_DUMMY("core_clk", CE_CLK, "qcota.0", OFF),
CLK_DUMMY("core_clk", CE_CLK, "qcrypto.0", OFF),
diff --git a/arch/arm/mach-msm/clock-local.c b/arch/arm/mach-msm/clock-local.c
index b5ae4ab..0f9404b 100644
--- a/arch/arm/mach-msm/clock-local.c
+++ b/arch/arm/mach-msm/clock-local.c
@@ -53,32 +53,32 @@
*/
/* For clocks with MND dividers. */
-void set_rate_mnd(struct rcg_clk *clk, struct clk_freq_tbl *nf)
+void set_rate_mnd(struct rcg_clk *rcg, struct clk_freq_tbl *nf)
{
uint32_t ns_reg_val, ctl_reg_val;
/* Assert MND reset. */
- ns_reg_val = readl_relaxed(clk->ns_reg);
+ ns_reg_val = readl_relaxed(rcg->ns_reg);
ns_reg_val |= BIT(7);
- writel_relaxed(ns_reg_val, clk->ns_reg);
+ writel_relaxed(ns_reg_val, rcg->ns_reg);
/* Program M and D values. */
- writel_relaxed(nf->md_val, clk->md_reg);
+ writel_relaxed(nf->md_val, rcg->md_reg);
/* If the clock has a separate CC register, program it. */
- if (clk->ns_reg != clk->b.ctl_reg) {
- ctl_reg_val = readl_relaxed(clk->b.ctl_reg);
- ctl_reg_val &= ~(clk->ctl_mask);
+ if (rcg->ns_reg != rcg->b.ctl_reg) {
+ ctl_reg_val = readl_relaxed(rcg->b.ctl_reg);
+ ctl_reg_val &= ~(rcg->ctl_mask);
ctl_reg_val |= nf->ctl_val;
- writel_relaxed(ctl_reg_val, clk->b.ctl_reg);
+ writel_relaxed(ctl_reg_val, rcg->b.ctl_reg);
}
/* Deassert MND reset. */
ns_reg_val &= ~BIT(7);
- writel_relaxed(ns_reg_val, clk->ns_reg);
+ writel_relaxed(ns_reg_val, rcg->ns_reg);
}
-void set_rate_nop(struct rcg_clk *clk, struct clk_freq_tbl *nf)
+void set_rate_nop(struct rcg_clk *rcg, struct clk_freq_tbl *nf)
{
/*
* Nothing to do for fixed-rate or integer-divider clocks. Any settings
@@ -88,31 +88,31 @@
*/
}
-void set_rate_mnd_8(struct rcg_clk *clk, struct clk_freq_tbl *nf)
+void set_rate_mnd_8(struct rcg_clk *rcg, struct clk_freq_tbl *nf)
{
uint32_t ctl_reg_val;
/* Assert MND reset. */
- ctl_reg_val = readl_relaxed(clk->b.ctl_reg);
+ ctl_reg_val = readl_relaxed(rcg->b.ctl_reg);
ctl_reg_val |= BIT(8);
- writel_relaxed(ctl_reg_val, clk->b.ctl_reg);
+ writel_relaxed(ctl_reg_val, rcg->b.ctl_reg);
/* Program M and D values. */
- writel_relaxed(nf->md_val, clk->md_reg);
+ writel_relaxed(nf->md_val, rcg->md_reg);
/* Program MN counter Enable and Mode. */
- ctl_reg_val &= ~(clk->ctl_mask);
+ ctl_reg_val &= ~(rcg->ctl_mask);
ctl_reg_val |= nf->ctl_val;
- writel_relaxed(ctl_reg_val, clk->b.ctl_reg);
+ writel_relaxed(ctl_reg_val, rcg->b.ctl_reg);
/* Deassert MND reset. */
ctl_reg_val &= ~BIT(8);
- writel_relaxed(ctl_reg_val, clk->b.ctl_reg);
+ writel_relaxed(ctl_reg_val, rcg->b.ctl_reg);
}
-void set_rate_mnd_banked(struct rcg_clk *clk, struct clk_freq_tbl *nf)
+void set_rate_mnd_banked(struct rcg_clk *rcg, struct clk_freq_tbl *nf)
{
- struct bank_masks *banks = clk->bank_info;
+ struct bank_masks *banks = rcg->bank_info;
const struct bank_mask_info *new_bank_masks;
const struct bank_mask_info *old_bank_masks;
uint32_t ns_reg_val, ctl_reg_val;
@@ -123,10 +123,10 @@
* off, program the active bank since bank switching won't work if
* both banks aren't running.
*/
- ctl_reg_val = readl_relaxed(clk->b.ctl_reg);
+ ctl_reg_val = readl_relaxed(rcg->b.ctl_reg);
bank_sel = !!(ctl_reg_val & banks->bank_sel_mask);
/* If clock isn't running, don't switch banks. */
- bank_sel ^= (!clk->enabled || clk->current_freq->freq_hz == 0);
+ bank_sel ^= (!rcg->enabled || rcg->current_freq->freq_hz == 0);
if (bank_sel == 0) {
new_bank_masks = &banks->bank1_mask;
old_bank_masks = &banks->bank0_mask;
@@ -135,46 +135,46 @@
old_bank_masks = &banks->bank1_mask;
}
- ns_reg_val = readl_relaxed(clk->ns_reg);
+ ns_reg_val = readl_relaxed(rcg->ns_reg);
/* Assert bank MND reset. */
ns_reg_val |= new_bank_masks->rst_mask;
- writel_relaxed(ns_reg_val, clk->ns_reg);
+ writel_relaxed(ns_reg_val, rcg->ns_reg);
/*
* Program NS only if the clock is enabled, since the NS will be set
* as part of the enable procedure and should remain with a low-power
* MUX input selected until then.
*/
- if (clk->enabled) {
+ if (rcg->enabled) {
ns_reg_val &= ~(new_bank_masks->ns_mask);
ns_reg_val |= (nf->ns_val & new_bank_masks->ns_mask);
- writel_relaxed(ns_reg_val, clk->ns_reg);
+ writel_relaxed(ns_reg_val, rcg->ns_reg);
}
writel_relaxed(nf->md_val, new_bank_masks->md_reg);
/* Enable counter only if clock is enabled. */
- if (clk->enabled)
+ if (rcg->enabled)
ctl_reg_val |= new_bank_masks->mnd_en_mask;
else
ctl_reg_val &= ~(new_bank_masks->mnd_en_mask);
ctl_reg_val &= ~(new_bank_masks->mode_mask);
ctl_reg_val |= (nf->ctl_val & new_bank_masks->mode_mask);
- writel_relaxed(ctl_reg_val, clk->b.ctl_reg);
+ writel_relaxed(ctl_reg_val, rcg->b.ctl_reg);
/* Deassert bank MND reset. */
ns_reg_val &= ~(new_bank_masks->rst_mask);
- writel_relaxed(ns_reg_val, clk->ns_reg);
+ writel_relaxed(ns_reg_val, rcg->ns_reg);
/*
* Switch to the new bank if clock is running. If it isn't, then
* no switch is necessary since we programmed the active bank.
*/
- if (clk->enabled && clk->current_freq->freq_hz) {
+ if (rcg->enabled && rcg->current_freq->freq_hz) {
ctl_reg_val ^= banks->bank_sel_mask;
- writel_relaxed(ctl_reg_val, clk->b.ctl_reg);
+ writel_relaxed(ctl_reg_val, rcg->b.ctl_reg);
/*
* Wait at least 6 cycles of slowest bank's clock
* for the glitch-free MUX to fully switch sources.
@@ -184,22 +184,22 @@
/* Disable old bank's MN counter. */
ctl_reg_val &= ~(old_bank_masks->mnd_en_mask);
- writel_relaxed(ctl_reg_val, clk->b.ctl_reg);
+ writel_relaxed(ctl_reg_val, rcg->b.ctl_reg);
/* Program old bank to a low-power source and divider. */
ns_reg_val &= ~(old_bank_masks->ns_mask);
- ns_reg_val |= (clk->freq_tbl->ns_val & old_bank_masks->ns_mask);
- writel_relaxed(ns_reg_val, clk->ns_reg);
+ ns_reg_val |= (rcg->freq_tbl->ns_val & old_bank_masks->ns_mask);
+ writel_relaxed(ns_reg_val, rcg->ns_reg);
}
/* Update the MND_EN and NS masks to match the current bank. */
- clk->mnd_en_mask = new_bank_masks->mnd_en_mask;
- clk->ns_mask = new_bank_masks->ns_mask;
+ rcg->mnd_en_mask = new_bank_masks->mnd_en_mask;
+ rcg->ns_mask = new_bank_masks->ns_mask;
}
-void set_rate_div_banked(struct rcg_clk *clk, struct clk_freq_tbl *nf)
+void set_rate_div_banked(struct rcg_clk *rcg, struct clk_freq_tbl *nf)
{
- struct bank_masks *banks = clk->bank_info;
+ struct bank_masks *banks = rcg->bank_info;
const struct bank_mask_info *new_bank_masks;
const struct bank_mask_info *old_bank_masks;
uint32_t ns_reg_val, bank_sel;
@@ -209,10 +209,10 @@
* off, program the active bank since bank switching won't work if
* both banks aren't running.
*/
- ns_reg_val = readl_relaxed(clk->ns_reg);
+ ns_reg_val = readl_relaxed(rcg->ns_reg);
bank_sel = !!(ns_reg_val & banks->bank_sel_mask);
/* If clock isn't running, don't switch banks. */
- bank_sel ^= (!clk->enabled || clk->current_freq->freq_hz == 0);
+ bank_sel ^= (!rcg->enabled || rcg->current_freq->freq_hz == 0);
if (bank_sel == 0) {
new_bank_masks = &banks->bank1_mask;
old_bank_masks = &banks->bank0_mask;
@@ -226,19 +226,19 @@
* as part of the enable procedure and should remain with a low-power
* MUX input selected until then.
*/
- if (clk->enabled) {
+ if (rcg->enabled) {
ns_reg_val &= ~(new_bank_masks->ns_mask);
ns_reg_val |= (nf->ns_val & new_bank_masks->ns_mask);
- writel_relaxed(ns_reg_val, clk->ns_reg);
+ writel_relaxed(ns_reg_val, rcg->ns_reg);
}
/*
* Switch to the new bank if clock is running. If it isn't, then
* no switch is necessary since we programmed the active bank.
*/
- if (clk->enabled && clk->current_freq->freq_hz) {
+ if (rcg->enabled && rcg->current_freq->freq_hz) {
ns_reg_val ^= banks->bank_sel_mask;
- writel_relaxed(ns_reg_val, clk->ns_reg);
+ writel_relaxed(ns_reg_val, rcg->ns_reg);
/*
* Wait at least 6 cycles of slowest bank's clock
* for the glitch-free MUX to fully switch sources.
@@ -248,12 +248,12 @@
/* Program old bank to a low-power source and divider. */
ns_reg_val &= ~(old_bank_masks->ns_mask);
- ns_reg_val |= (clk->freq_tbl->ns_val & old_bank_masks->ns_mask);
- writel_relaxed(ns_reg_val, clk->ns_reg);
+ ns_reg_val |= (rcg->freq_tbl->ns_val & old_bank_masks->ns_mask);
+ writel_relaxed(ns_reg_val, rcg->ns_reg);
}
/* Update the NS mask to match the current bank. */
- clk->ns_mask = new_bank_masks->ns_mask;
+ rcg->ns_mask = new_bank_masks->ns_mask;
}
/*
@@ -261,10 +261,10 @@
*/
/* Return non-zero if a clock status registers shows the clock is halted. */
-static int branch_clk_is_halted(const struct branch *clk)
+static int branch_clk_is_halted(const struct branch *b)
{
- int invert = (clk->halt_check == ENABLE);
- int status_bit = readl_relaxed(clk->halt_reg) & BIT(clk->halt_bit);
+ int invert = (b->halt_check == ENABLE);
+ int status_bit = readl_relaxed(b->halt_reg) & BIT(b->halt_bit);
return invert ? !status_bit : status_bit;
}
@@ -276,14 +276,14 @@
return !!(readl_relaxed(b->hwcg_reg) & b->hwcg_mask);
}
-void __branch_clk_enable_reg(const struct branch *clk, const char *name)
+void __branch_enable_reg(const struct branch *b, const char *name)
{
u32 reg_val;
- if (clk->en_mask) {
- reg_val = readl_relaxed(clk->ctl_reg);
- reg_val |= clk->en_mask;
- writel_relaxed(reg_val, clk->ctl_reg);
+ if (b->en_mask) {
+ reg_val = readl_relaxed(b->ctl_reg);
+ reg_val |= b->en_mask;
+ writel_relaxed(reg_val, b->ctl_reg);
}
/*
@@ -295,19 +295,19 @@
mb();
/* Skip checking halt bit if the clock is in hardware gated mode */
- if (branch_in_hwcg_mode(clk))
+ if (branch_in_hwcg_mode(b))
return;
/* Wait for clock to enable before returning. */
- if (clk->halt_check == DELAY)
+ if (b->halt_check == DELAY) {
udelay(HALT_CHECK_DELAY_US);
- else if (clk->halt_check == ENABLE || clk->halt_check == HALT
- || clk->halt_check == ENABLE_VOTED
- || clk->halt_check == HALT_VOTED) {
+ } else if (b->halt_check == ENABLE || b->halt_check == HALT
+ || b->halt_check == ENABLE_VOTED
+ || b->halt_check == HALT_VOTED) {
int count;
/* Wait up to HALT_CHECK_MAX_LOOPS for clock to enable. */
- for (count = HALT_CHECK_MAX_LOOPS; branch_clk_is_halted(clk)
+ for (count = HALT_CHECK_MAX_LOOPS; branch_clk_is_halted(b)
&& count > 0; count--)
udelay(1);
WARN(count == 0, "%s status stuck at 'off'", name);
@@ -315,50 +315,50 @@
}
/* Perform any register operations required to enable the clock. */
-static void __rcg_clk_enable_reg(struct rcg_clk *clk)
+static void __rcg_clk_enable_reg(struct rcg_clk *rcg)
{
u32 reg_val;
- void __iomem *const reg = clk->b.ctl_reg;
+ void __iomem *const reg = rcg->b.ctl_reg;
- WARN(clk->current_freq == &rcg_dummy_freq,
+ WARN(rcg->current_freq == &rcg_dummy_freq,
"Attempting to enable %s before setting its rate. "
- "Set the rate first!\n", clk->c.dbg_name);
+ "Set the rate first!\n", rcg->c.dbg_name);
/*
* Program the NS register, if applicable. NS registers are not
* set in the set_rate path because power can be saved by deferring
* the selection of a clocked source until the clock is enabled.
*/
- if (clk->ns_mask) {
- reg_val = readl_relaxed(clk->ns_reg);
- reg_val &= ~(clk->ns_mask);
- reg_val |= (clk->current_freq->ns_val & clk->ns_mask);
- writel_relaxed(reg_val, clk->ns_reg);
+ if (rcg->ns_mask) {
+ reg_val = readl_relaxed(rcg->ns_reg);
+ reg_val &= ~(rcg->ns_mask);
+ reg_val |= (rcg->current_freq->ns_val & rcg->ns_mask);
+ writel_relaxed(reg_val, rcg->ns_reg);
}
/* Enable MN counter, if applicable. */
reg_val = readl_relaxed(reg);
- if (clk->current_freq->md_val) {
- reg_val |= clk->mnd_en_mask;
+ if (rcg->current_freq->md_val) {
+ reg_val |= rcg->mnd_en_mask;
writel_relaxed(reg_val, reg);
}
/* Enable root. */
- if (clk->root_en_mask) {
- reg_val |= clk->root_en_mask;
+ if (rcg->root_en_mask) {
+ reg_val |= rcg->root_en_mask;
writel_relaxed(reg_val, reg);
}
- __branch_clk_enable_reg(&clk->b, clk->c.dbg_name);
+ __branch_enable_reg(&rcg->b, rcg->c.dbg_name);
}
/* Perform any register operations required to disable the branch. */
-u32 __branch_clk_disable_reg(const struct branch *clk, const char *name)
+u32 __branch_disable_reg(const struct branch *b, const char *name)
{
u32 reg_val;
- reg_val = readl_relaxed(clk->ctl_reg);
- if (clk->en_mask) {
- reg_val &= ~(clk->en_mask);
- writel_relaxed(reg_val, clk->ctl_reg);
+ reg_val = readl_relaxed(b->ctl_reg);
+ if (b->en_mask) {
+ reg_val &= ~(b->en_mask);
+ writel_relaxed(reg_val, b->ctl_reg);
}
/*
@@ -370,18 +370,18 @@
mb();
/* Skip checking halt bit if the clock is in hardware gated mode */
- if (branch_in_hwcg_mode(clk))
+ if (branch_in_hwcg_mode(b))
return reg_val;
/* Wait for clock to disable before continuing. */
- if (clk->halt_check == DELAY || clk->halt_check == ENABLE_VOTED
- || clk->halt_check == HALT_VOTED)
+ if (b->halt_check == DELAY || b->halt_check == ENABLE_VOTED
+ || b->halt_check == HALT_VOTED) {
udelay(HALT_CHECK_DELAY_US);
- else if (clk->halt_check == ENABLE || clk->halt_check == HALT) {
+ } else if (b->halt_check == ENABLE || b->halt_check == HALT) {
int count;
/* Wait up to HALT_CHECK_MAX_LOOPS for clock to disable. */
- for (count = HALT_CHECK_MAX_LOOPS; !branch_clk_is_halted(clk)
+ for (count = HALT_CHECK_MAX_LOOPS; !branch_clk_is_halted(b)
&& count > 0; count--)
udelay(1);
WARN(count == 0, "%s status stuck at 'on'", name);
@@ -391,31 +391,31 @@
}
/* Perform any register operations required to disable the generator. */
-static void __rcg_clk_disable_reg(struct rcg_clk *clk)
+static void __rcg_clk_disable_reg(struct rcg_clk *rcg)
{
- void __iomem *const reg = clk->b.ctl_reg;
+ void __iomem *const reg = rcg->b.ctl_reg;
uint32_t reg_val;
- reg_val = __branch_clk_disable_reg(&clk->b, clk->c.dbg_name);
+ reg_val = __branch_disable_reg(&rcg->b, rcg->c.dbg_name);
/* Disable root. */
- if (clk->root_en_mask) {
- reg_val &= ~(clk->root_en_mask);
+ if (rcg->root_en_mask) {
+ reg_val &= ~(rcg->root_en_mask);
writel_relaxed(reg_val, reg);
}
/* Disable MN counter, if applicable. */
- if (clk->current_freq->md_val) {
- reg_val &= ~(clk->mnd_en_mask);
+ if (rcg->current_freq->md_val) {
+ reg_val &= ~(rcg->mnd_en_mask);
writel_relaxed(reg_val, reg);
}
/*
* Program NS register to low-power value with an un-clocked or
* slowly-clocked source selected.
*/
- if (clk->ns_mask) {
- reg_val = readl_relaxed(clk->ns_reg);
- reg_val &= ~(clk->ns_mask);
- reg_val |= (clk->freq_tbl->ns_val & clk->ns_mask);
- writel_relaxed(reg_val, clk->ns_reg);
+ if (rcg->ns_mask) {
+ reg_val = readl_relaxed(rcg->ns_reg);
+ reg_val &= ~(rcg->ns_mask);
+ reg_val |= (rcg->freq_tbl->ns_val & rcg->ns_mask);
+ writel_relaxed(reg_val, rcg->ns_reg);
}
}
@@ -423,11 +423,11 @@
static int rcg_clk_enable(struct clk *c)
{
unsigned long flags;
- struct rcg_clk *clk = to_rcg_clk(c);
+ struct rcg_clk *rcg = to_rcg_clk(c);
spin_lock_irqsave(&local_clock_reg_lock, flags);
- __rcg_clk_enable_reg(clk);
- clk->enabled = true;
+ __rcg_clk_enable_reg(rcg);
+ rcg->enabled = true;
spin_unlock_irqrestore(&local_clock_reg_lock, flags);
return 0;
@@ -437,11 +437,11 @@
static void rcg_clk_disable(struct clk *c)
{
unsigned long flags;
- struct rcg_clk *clk = to_rcg_clk(c);
+ struct rcg_clk *rcg = to_rcg_clk(c);
spin_lock_irqsave(&local_clock_reg_lock, flags);
- __rcg_clk_disable_reg(clk);
- clk->enabled = false;
+ __rcg_clk_disable_reg(rcg);
+ rcg->enabled = false;
spin_unlock_irqrestore(&local_clock_reg_lock, flags);
}
@@ -452,21 +452,21 @@
/* Set a clock to an exact rate. */
static int rcg_clk_set_rate(struct clk *c, unsigned long rate)
{
- struct rcg_clk *clk = to_rcg_clk(c);
+ struct rcg_clk *rcg = to_rcg_clk(c);
struct clk_freq_tbl *nf, *cf;
struct clk *chld;
int rc = 0;
- for (nf = clk->freq_tbl; nf->freq_hz != FREQ_END
+ for (nf = rcg->freq_tbl; nf->freq_hz != FREQ_END
&& nf->freq_hz != rate; nf++)
;
if (nf->freq_hz == FREQ_END)
return -EINVAL;
- cf = clk->current_freq;
+ cf = rcg->current_freq;
- if (clk->enabled) {
+ if (rcg->enabled) {
/* Enable source clock dependency for the new freq. */
rc = clk_enable(nf->src_clk);
if (rc)
@@ -476,9 +476,9 @@
spin_lock(&local_clock_reg_lock);
/* Disable branch if clock isn't dual-banked with a glitch-free MUX. */
- if (!clk->bank_info) {
+ if (!rcg->bank_info) {
/* Disable all branches to prevent glitches. */
- list_for_each_entry(chld, &clk->c.children, siblings) {
+ list_for_each_entry(chld, &rcg->c.children, siblings) {
struct branch_clk *x = to_branch_clk(chld);
/*
* We don't need to grab the child's lock because
@@ -486,56 +486,56 @@
* only modified within lock.
*/
if (x->enabled)
- __branch_clk_disable_reg(&x->b, x->c.dbg_name);
+ __branch_disable_reg(&x->b, x->c.dbg_name);
}
- if (clk->enabled)
- __rcg_clk_disable_reg(clk);
+ if (rcg->enabled)
+ __rcg_clk_disable_reg(rcg);
}
/* Perform clock-specific frequency switch operations. */
- BUG_ON(!clk->set_rate);
- clk->set_rate(clk, nf);
+ BUG_ON(!rcg->set_rate);
+ rcg->set_rate(rcg, nf);
/*
* Current freq must be updated before __rcg_clk_enable_reg()
* is called to make sure the MNCNTR_EN bit is set correctly.
*/
- clk->current_freq = nf;
+ rcg->current_freq = nf;
/* Enable any clocks that were disabled. */
- if (!clk->bank_info) {
- if (clk->enabled)
- __rcg_clk_enable_reg(clk);
+ if (!rcg->bank_info) {
+ if (rcg->enabled)
+ __rcg_clk_enable_reg(rcg);
/* Enable only branches that were ON before. */
- list_for_each_entry(chld, &clk->c.children, siblings) {
+ list_for_each_entry(chld, &rcg->c.children, siblings) {
struct branch_clk *x = to_branch_clk(chld);
if (x->enabled)
- __branch_clk_enable_reg(&x->b, x->c.dbg_name);
+ __branch_enable_reg(&x->b, x->c.dbg_name);
}
}
spin_unlock(&local_clock_reg_lock);
/* Release source requirements of the old freq. */
- if (clk->enabled)
+ if (rcg->enabled)
clk_disable(cf->src_clk);
return rc;
}
/* Check if a clock is currently enabled. */
-static int rcg_clk_is_enabled(struct clk *clk)
+static int rcg_clk_is_enabled(struct clk *c)
{
- return to_rcg_clk(clk)->enabled;
+ return to_rcg_clk(c)->enabled;
}
/* Return a supported rate that's at least the specified rate. */
static long rcg_clk_round_rate(struct clk *c, unsigned long rate)
{
- struct rcg_clk *clk = to_rcg_clk(c);
+ struct rcg_clk *rcg = to_rcg_clk(c);
struct clk_freq_tbl *f;
- for (f = clk->freq_tbl; f->freq_hz != FREQ_END; f++)
+ for (f = rcg->freq_tbl; f->freq_hz != FREQ_END; f++)
if (f->freq_hz >= rate)
return f->freq_hz;
@@ -545,26 +545,26 @@
/* Return the nth supported frequency for a given clock. */
static int rcg_clk_list_rate(struct clk *c, unsigned n)
{
- struct rcg_clk *clk = to_rcg_clk(c);
+ struct rcg_clk *rcg = to_rcg_clk(c);
- if (!clk->freq_tbl || clk->freq_tbl->freq_hz == FREQ_END)
+ if (!rcg->freq_tbl || rcg->freq_tbl->freq_hz == FREQ_END)
return -ENXIO;
- return (clk->freq_tbl + n)->freq_hz;
+ return (rcg->freq_tbl + n)->freq_hz;
}
-static struct clk *rcg_clk_get_parent(struct clk *clk)
+static struct clk *rcg_clk_get_parent(struct clk *c)
{
- return to_rcg_clk(clk)->current_freq->src_clk;
+ return to_rcg_clk(c)->current_freq->src_clk;
}
/* Disable hw clock gating if not set at boot */
-enum handoff branch_handoff(struct branch *clk, struct clk *c)
+enum handoff branch_handoff(struct branch *b, struct clk *c)
{
- if (!branch_in_hwcg_mode(clk)) {
- clk->hwcg_mask = 0;
+ if (!branch_in_hwcg_mode(b)) {
+ b->hwcg_mask = 0;
c->flags &= ~CLKFLAG_HWCG;
- if (readl_relaxed(clk->ctl_reg) & clk->en_mask)
+ if (readl_relaxed(b->ctl_reg) & b->en_mask)
return HANDOFF_ENABLED_CLK;
} else {
c->flags |= CLKFLAG_HWCG;
@@ -574,24 +574,24 @@
static enum handoff branch_clk_handoff(struct clk *c)
{
- struct branch_clk *clk = to_branch_clk(c);
- return branch_handoff(&clk->b, &clk->c);
+ struct branch_clk *br = to_branch_clk(c);
+ return branch_handoff(&br->b, &br->c);
}
static enum handoff rcg_clk_handoff(struct clk *c)
{
- struct rcg_clk *clk = to_rcg_clk(c);
+ struct rcg_clk *rcg = to_rcg_clk(c);
uint32_t ctl_val, ns_val, md_val, ns_mask;
struct clk_freq_tbl *freq;
enum handoff ret;
- ctl_val = readl_relaxed(clk->b.ctl_reg);
- ret = branch_handoff(&clk->b, &clk->c);
+ ctl_val = readl_relaxed(rcg->b.ctl_reg);
+ ret = branch_handoff(&rcg->b, &rcg->c);
if (ret == HANDOFF_DISABLED_CLK)
return HANDOFF_DISABLED_CLK;
- if (clk->bank_info) {
- const struct bank_masks *bank_masks = clk->bank_info;
+ if (rcg->bank_info) {
+ const struct bank_masks *bank_masks = rcg->bank_info;
const struct bank_mask_info *bank_info;
if (!(ctl_val & bank_masks->bank_sel_mask))
bank_info = &bank_masks->bank0_mask;
@@ -602,13 +602,13 @@
md_val = bank_info->md_reg ?
readl_relaxed(bank_info->md_reg) : 0;
} else {
- ns_mask = clk->ns_mask;
- md_val = clk->md_reg ? readl_relaxed(clk->md_reg) : 0;
+ ns_mask = rcg->ns_mask;
+ md_val = rcg->md_reg ? readl_relaxed(rcg->md_reg) : 0;
}
if (!ns_mask)
return HANDOFF_UNKNOWN_RATE;
- ns_val = readl_relaxed(clk->ns_reg) & ns_mask;
- for (freq = clk->freq_tbl; freq->freq_hz != FREQ_END; freq++) {
+ ns_val = readl_relaxed(rcg->ns_reg) & ns_mask;
+ for (freq = rcg->freq_tbl; freq->freq_hz != FREQ_END; freq++) {
if ((freq->ns_val & ns_mask) == ns_val &&
(!freq->md_val || freq->md_val == md_val))
break;
@@ -616,7 +616,7 @@
if (freq->freq_hz == FREQ_END)
return HANDOFF_UNKNOWN_RATE;
- clk->current_freq = freq;
+ rcg->current_freq = freq;
c->rate = freq->freq_hz;
return HANDOFF_ENABLED_CLK;
@@ -632,40 +632,38 @@
},
};
-static int branch_clk_enable(struct clk *clk)
+static int branch_clk_enable(struct clk *c)
{
unsigned long flags;
- struct branch_clk *branch = to_branch_clk(clk);
+ struct branch_clk *br = to_branch_clk(c);
spin_lock_irqsave(&local_clock_reg_lock, flags);
- __branch_clk_enable_reg(&branch->b, branch->c.dbg_name);
- branch->enabled = true;
+ __branch_enable_reg(&br->b, br->c.dbg_name);
+ br->enabled = true;
spin_unlock_irqrestore(&local_clock_reg_lock, flags);
return 0;
}
-static void branch_clk_disable(struct clk *clk)
+static void branch_clk_disable(struct clk *c)
{
unsigned long flags;
- struct branch_clk *branch = to_branch_clk(clk);
+ struct branch_clk *br = to_branch_clk(c);
spin_lock_irqsave(&local_clock_reg_lock, flags);
- __branch_clk_disable_reg(&branch->b, branch->c.dbg_name);
- branch->enabled = false;
+ __branch_disable_reg(&br->b, br->c.dbg_name);
+ br->enabled = false;
spin_unlock_irqrestore(&local_clock_reg_lock, flags);
}
-static struct clk *branch_clk_get_parent(struct clk *clk)
+static struct clk *branch_clk_get_parent(struct clk *c)
{
- struct branch_clk *branch = to_branch_clk(clk);
- return branch->parent;
+ return to_branch_clk(c)->parent;
}
-static int branch_clk_is_enabled(struct clk *clk)
+static int branch_clk_is_enabled(struct clk *c)
{
- struct branch_clk *branch = to_branch_clk(clk);
- return branch->enabled;
+ return to_branch_clk(c)->enabled;
}
static void branch_enable_hwcg(struct branch *b)
@@ -692,16 +690,14 @@
spin_unlock_irqrestore(&local_clock_reg_lock, flags);
}
-static void branch_clk_enable_hwcg(struct clk *clk)
+static void branch_clk_enable_hwcg(struct clk *c)
{
- struct branch_clk *branch = to_branch_clk(clk);
- branch_enable_hwcg(&branch->b);
+ branch_enable_hwcg(&to_branch_clk(c)->b);
}
-static void branch_clk_disable_hwcg(struct clk *clk)
+static void branch_clk_disable_hwcg(struct clk *c)
{
- struct branch_clk *branch = to_branch_clk(clk);
- branch_disable_hwcg(&branch->b);
+ branch_disable_hwcg(&to_branch_clk(c)->b);
}
static int branch_set_flags(struct branch *b, unsigned flags)
@@ -738,26 +734,22 @@
static int branch_clk_in_hwcg_mode(struct clk *c)
{
- struct branch_clk *clk = to_branch_clk(c);
- return branch_in_hwcg_mode(&clk->b);
+ return branch_in_hwcg_mode(&to_branch_clk(c)->b);
}
-static void rcg_clk_enable_hwcg(struct clk *clk)
+static void rcg_clk_enable_hwcg(struct clk *c)
{
- struct rcg_clk *rcg = to_rcg_clk(clk);
- branch_enable_hwcg(&rcg->b);
+ branch_enable_hwcg(&to_rcg_clk(c)->b);
}
-static void rcg_clk_disable_hwcg(struct clk *clk)
+static void rcg_clk_disable_hwcg(struct clk *c)
{
- struct rcg_clk *rcg = to_rcg_clk(clk);
- branch_disable_hwcg(&rcg->b);
+ branch_disable_hwcg(&to_rcg_clk(c)->b);
}
static int rcg_clk_in_hwcg_mode(struct clk *c)
{
- struct rcg_clk *clk = to_rcg_clk(c);
- return branch_in_hwcg_mode(&clk->b);
+ return branch_in_hwcg_mode(&to_rcg_clk(c)->b);
}
static int rcg_clk_set_flags(struct clk *clk, unsigned flags)
@@ -802,9 +794,9 @@
return ret;
}
-static int branch_clk_reset(struct clk *clk, enum clk_reset_action action)
+static int branch_clk_reset(struct clk *c, enum clk_reset_action action)
{
- return branch_reset(&to_branch_clk(clk)->b, action);
+ return branch_reset(&to_branch_clk(c)->b, action);
}
struct clk_ops clk_ops_branch = {
@@ -825,9 +817,9 @@
.reset = branch_clk_reset,
};
-static int rcg_clk_reset(struct clk *clk, enum clk_reset_action action)
+static int rcg_clk_reset(struct clk *c, enum clk_reset_action action)
{
- return branch_reset(&to_rcg_clk(clk)->b, action);
+ return branch_reset(&to_rcg_clk(c)->b, action);
}
struct clk_ops clk_ops_rcg = {
@@ -850,10 +842,10 @@
static int cdiv_clk_enable(struct clk *c)
{
unsigned long flags;
- struct cdiv_clk *clk = to_cdiv_clk(c);
+ struct cdiv_clk *cdiv = to_cdiv_clk(c);
spin_lock_irqsave(&local_clock_reg_lock, flags);
- __branch_clk_enable_reg(&clk->b, clk->c.dbg_name);
+ __branch_enable_reg(&cdiv->b, cdiv->c.dbg_name);
spin_unlock_irqrestore(&local_clock_reg_lock, flags);
return 0;
@@ -862,70 +854,67 @@
static void cdiv_clk_disable(struct clk *c)
{
unsigned long flags;
- struct cdiv_clk *clk = to_cdiv_clk(c);
+ struct cdiv_clk *cdiv = to_cdiv_clk(c);
spin_lock_irqsave(&local_clock_reg_lock, flags);
- __branch_clk_disable_reg(&clk->b, clk->c.dbg_name);
+ __branch_disable_reg(&cdiv->b, cdiv->c.dbg_name);
spin_unlock_irqrestore(&local_clock_reg_lock, flags);
}
static int cdiv_clk_set_rate(struct clk *c, unsigned long rate)
{
- struct cdiv_clk *clk = to_cdiv_clk(c);
+ struct cdiv_clk *cdiv = to_cdiv_clk(c);
u32 reg_val;
- if (rate > clk->max_div)
+ if (rate > cdiv->max_div)
return -EINVAL;
spin_lock(&local_clock_reg_lock);
- reg_val = readl_relaxed(clk->ns_reg);
- reg_val &= ~(clk->ext_mask | (clk->max_div - 1) << clk->div_offset);
+ reg_val = readl_relaxed(cdiv->ns_reg);
+ reg_val &= ~(cdiv->ext_mask | (cdiv->max_div - 1) << cdiv->div_offset);
/* Non-zero rates mean set a divider, zero means use external input */
if (rate)
- reg_val |= (rate - 1) << clk->div_offset;
+ reg_val |= (rate - 1) << cdiv->div_offset;
else
- reg_val |= clk->ext_mask;
- writel_relaxed(reg_val, clk->ns_reg);
+ reg_val |= cdiv->ext_mask;
+ writel_relaxed(reg_val, cdiv->ns_reg);
spin_unlock(&local_clock_reg_lock);
- clk->cur_div = rate;
+ cdiv->cur_div = rate;
return 0;
}
static unsigned long cdiv_clk_get_rate(struct clk *c)
{
- struct cdiv_clk *clk = to_cdiv_clk(c);
- return clk->cur_div;
+ return to_cdiv_clk(c)->cur_div;
}
static long cdiv_clk_round_rate(struct clk *c, unsigned long rate)
{
- struct cdiv_clk *clk = to_cdiv_clk(c);
- return rate > clk->max_div ? -EPERM : rate;
+ return rate > to_cdiv_clk(c)->max_div ? -EPERM : rate;
}
static int cdiv_clk_list_rate(struct clk *c, unsigned n)
{
- struct cdiv_clk *clk = to_cdiv_clk(c);
- return n > clk->max_div ? -ENXIO : n;
+ return n > to_cdiv_clk(c)->max_div ? -ENXIO : n;
}
static enum handoff cdiv_clk_handoff(struct clk *c)
{
- struct cdiv_clk *clk = to_cdiv_clk(c);
+ struct cdiv_clk *cdiv = to_cdiv_clk(c);
enum handoff ret;
u32 reg_val;
- ret = branch_handoff(&clk->b, &clk->c);
+ ret = branch_handoff(&cdiv->b, &cdiv->c);
if (ret == HANDOFF_DISABLED_CLK)
return ret;
- reg_val = readl_relaxed(clk->ns_reg);
- if (reg_val & clk->ext_mask) {
- clk->cur_div = 0;
+ reg_val = readl_relaxed(cdiv->ns_reg);
+ if (reg_val & cdiv->ext_mask) {
+ cdiv->cur_div = 0;
} else {
- reg_val >>= clk->div_offset;
- clk->cur_div = (reg_val & (clk->max_div - 1)) + 1;
+ reg_val >>= cdiv->div_offset;
+ cdiv->cur_div = (reg_val & (cdiv->max_div - 1)) + 1;
}
return HANDOFF_ENABLED_CLK;
@@ -933,20 +922,17 @@
static void cdiv_clk_enable_hwcg(struct clk *c)
{
- struct cdiv_clk *clk = to_cdiv_clk(c);
- branch_enable_hwcg(&clk->b);
+ branch_enable_hwcg(&to_cdiv_clk(c)->b);
}
static void cdiv_clk_disable_hwcg(struct clk *c)
{
- struct cdiv_clk *clk = to_cdiv_clk(c);
- branch_disable_hwcg(&clk->b);
+ branch_disable_hwcg(&to_cdiv_clk(c)->b);
}
static int cdiv_clk_in_hwcg_mode(struct clk *c)
{
- struct cdiv_clk *clk = to_cdiv_clk(c);
- return branch_in_hwcg_mode(&clk->b);
+ return branch_in_hwcg_mode(&to_cdiv_clk(c)->b);
}
struct clk_ops clk_ops_cdiv = {
diff --git a/arch/arm/mach-msm/clock-local.h b/arch/arm/mach-msm/clock-local.h
index ffc7057..034e09c 100644
--- a/arch/arm/mach-msm/clock-local.h
+++ b/arch/arm/mach-msm/clock-local.h
@@ -156,9 +156,9 @@
extern struct clk_ops clk_ops_reset;
int branch_reset(struct branch *b, enum clk_reset_action action);
-void __branch_clk_enable_reg(const struct branch *clk, const char *name);
-u32 __branch_clk_disable_reg(const struct branch *clk, const char *name);
-enum handoff branch_handoff(struct branch *clk, struct clk *c);
+void __branch_enable_reg(const struct branch *b, const char *name);
+u32 __branch_disable_reg(const struct branch *b, const char *name);
+enum handoff branch_handoff(struct branch *b, struct clk *c);
/*
* Generic clock-definition struct and macros
@@ -183,9 +183,9 @@
struct clk c;
};
-static inline struct rcg_clk *to_rcg_clk(struct clk *clk)
+static inline struct rcg_clk *to_rcg_clk(struct clk *c)
{
- return container_of(clk, struct rcg_clk, c);
+ return container_of(c, struct rcg_clk, c);
}
extern struct clk_ops clk_ops_rcg;
@@ -214,9 +214,9 @@
struct clk c;
};
-static inline struct cdiv_clk *to_cdiv_clk(struct clk *clk)
+static inline struct cdiv_clk *to_cdiv_clk(struct clk *c)
{
- return container_of(clk, struct cdiv_clk, c);
+ return container_of(c, struct cdiv_clk, c);
}
extern struct clk_ops clk_ops_cdiv;
@@ -234,7 +234,7 @@
* @enabled: true if clock is on, false otherwise
* @b: branch
* @parent: clock source
- * @c: clk
+ * @c: clock
*
* An on/off switch with a rate derived from the parent.
*/
@@ -245,9 +245,9 @@
struct clk c;
};
-static inline struct branch_clk *to_branch_clk(struct clk *clk)
+static inline struct branch_clk *to_branch_clk(struct clk *c)
{
- return container_of(clk, struct branch_clk, c);
+ return container_of(c, struct branch_clk, c);
}
/**
@@ -255,7 +255,7 @@
* @sample_ticks: sample period in reference clock ticks
* @multiplier: measurement scale-up factor
* @divider: measurement scale-down factor
- * @c: clk
+ * @c: clock
*/
struct measure_clk {
u64 sample_ticks;
@@ -266,9 +266,9 @@
extern struct clk_ops clk_ops_empty;
-static inline struct measure_clk *to_measure_clk(struct clk *clk)
+static inline struct measure_clk *to_measure_clk(struct clk *c)
{
- return container_of(clk, struct measure_clk, c);
+ return container_of(c, struct measure_clk, c);
}
/*
@@ -280,11 +280,11 @@
/*
* Generic set-rate implementations
*/
-void set_rate_mnd(struct rcg_clk *clk, struct clk_freq_tbl *nf);
-void set_rate_nop(struct rcg_clk *clk, struct clk_freq_tbl *nf);
-void set_rate_mnd_8(struct rcg_clk *clk, struct clk_freq_tbl *nf);
-void set_rate_mnd_banked(struct rcg_clk *clk, struct clk_freq_tbl *nf);
-void set_rate_div_banked(struct rcg_clk *clk, struct clk_freq_tbl *nf);
+void set_rate_mnd(struct rcg_clk *rcg, struct clk_freq_tbl *nf);
+void set_rate_nop(struct rcg_clk *rcg, struct clk_freq_tbl *nf);
+void set_rate_mnd_8(struct rcg_clk *rcg, struct clk_freq_tbl *nf);
+void set_rate_mnd_banked(struct rcg_clk *rcg, struct clk_freq_tbl *nf);
+void set_rate_div_banked(struct rcg_clk *rcg, struct clk_freq_tbl *nf);
#endif /* __ARCH_ARM_MACH_MSM_CLOCK_LOCAL_H */
diff --git a/arch/arm/mach-msm/clock-pll.c b/arch/arm/mach-msm/clock-pll.c
index d839911..49bb063 100644
--- a/arch/arm/mach-msm/clock-pll.c
+++ b/arch/arm/mach-msm/clock-pll.c
@@ -55,16 +55,16 @@
#define ENABLE_WAIT_MAX_LOOPS 200
-int pll_vote_clk_enable(struct clk *clk)
+int pll_vote_clk_enable(struct clk *c)
{
u32 ena, count;
unsigned long flags;
- struct pll_vote_clk *pll = to_pll_vote_clk(clk);
+ struct pll_vote_clk *pllv = to_pll_vote_clk(c);
spin_lock_irqsave(&pll_reg_lock, flags);
- ena = readl_relaxed(PLL_EN_REG(pll));
- ena |= pll->en_mask;
- writel_relaxed(ena, PLL_EN_REG(pll));
+ ena = readl_relaxed(PLL_EN_REG(pllv));
+ ena |= pllv->en_mask;
+ writel_relaxed(ena, PLL_EN_REG(pllv));
spin_unlock_irqrestore(&pll_reg_lock, flags);
/*
@@ -75,45 +75,44 @@
/* Wait for pll to enable. */
for (count = ENABLE_WAIT_MAX_LOOPS; count > 0; count--) {
- if (readl_relaxed(PLL_STATUS_REG(pll)) & pll->status_mask)
+ if (readl_relaxed(PLL_STATUS_REG(pllv)) & pllv->status_mask)
return 0;
udelay(1);
}
- WARN("PLL %s didn't enable after voting for it!\n", clk->dbg_name);
+ WARN("PLL %s didn't enable after voting for it!\n", c->dbg_name);
return -ETIMEDOUT;
}
-void pll_vote_clk_disable(struct clk *clk)
+void pll_vote_clk_disable(struct clk *c)
{
u32 ena;
unsigned long flags;
- struct pll_vote_clk *pll = to_pll_vote_clk(clk);
+ struct pll_vote_clk *pllv = to_pll_vote_clk(c);
spin_lock_irqsave(&pll_reg_lock, flags);
- ena = readl_relaxed(PLL_EN_REG(pll));
- ena &= ~(pll->en_mask);
- writel_relaxed(ena, PLL_EN_REG(pll));
+ ena = readl_relaxed(PLL_EN_REG(pllv));
+ ena &= ~(pllv->en_mask);
+ writel_relaxed(ena, PLL_EN_REG(pllv));
spin_unlock_irqrestore(&pll_reg_lock, flags);
}
-struct clk *pll_vote_clk_get_parent(struct clk *clk)
+struct clk *pll_vote_clk_get_parent(struct clk *c)
{
- struct pll_vote_clk *pll = to_pll_vote_clk(clk);
- return pll->parent;
+ return to_pll_vote_clk(c)->parent;
}
-int pll_vote_clk_is_enabled(struct clk *clk)
+int pll_vote_clk_is_enabled(struct clk *c)
{
- struct pll_vote_clk *pll = to_pll_vote_clk(clk);
- return !!(readl_relaxed(PLL_STATUS_REG(pll)) & pll->status_mask);
+ struct pll_vote_clk *pllv = to_pll_vote_clk(c);
+ return !!(readl_relaxed(PLL_STATUS_REG(pllv)) & pllv->status_mask);
}
-static enum handoff pll_vote_clk_handoff(struct clk *clk)
+static enum handoff pll_vote_clk_handoff(struct clk *c)
{
- struct pll_vote_clk *pll = to_pll_vote_clk(clk);
- if (readl_relaxed(PLL_EN_REG(pll)) & pll->en_mask)
+ struct pll_vote_clk *pllv = to_pll_vote_clk(c);
+ if (readl_relaxed(PLL_EN_REG(pllv)) & pllv->en_mask)
return HANDOFF_ENABLED_CLK;
return HANDOFF_DISABLED_CLK;
@@ -158,10 +157,10 @@
mb();
}
-static int local_pll_clk_enable(struct clk *clk)
+static int local_pll_clk_enable(struct clk *c)
{
unsigned long flags;
- struct pll_clk *pll = to_pll_clk(clk);
+ struct pll_clk *pll = to_pll_clk(c);
spin_lock_irqsave(&pll_reg_lock, flags);
__pll_clk_enable_reg(PLL_MODE_REG(pll));
@@ -177,10 +176,10 @@
writel_relaxed(mode, mode_reg);
}
-static void local_pll_clk_disable(struct clk *clk)
+static void local_pll_clk_disable(struct clk *c)
{
unsigned long flags;
- struct pll_clk *pll = to_pll_clk(clk);
+ struct pll_clk *pll = to_pll_clk(c);
/*
* Disable the PLL output, disable test mode, enable
@@ -191,9 +190,9 @@
spin_unlock_irqrestore(&pll_reg_lock, flags);
}
-static enum handoff local_pll_clk_handoff(struct clk *clk)
+static enum handoff local_pll_clk_handoff(struct clk *c)
{
- struct pll_clk *pll = to_pll_clk(clk);
+ struct pll_clk *pll = to_pll_clk(c);
u32 mode = readl_relaxed(PLL_MODE_REG(pll));
u32 mask = PLL_BYPASSNL | PLL_RESET_N | PLL_OUTCTRL;
@@ -203,17 +202,16 @@
return HANDOFF_DISABLED_CLK;
}
-static struct clk *local_pll_clk_get_parent(struct clk *clk)
+static struct clk *local_pll_clk_get_parent(struct clk *c)
{
- struct pll_clk *pll = to_pll_clk(clk);
- return pll->parent;
+ return to_pll_clk(c)->parent;
}
-int sr_pll_clk_enable(struct clk *clk)
+int sr_pll_clk_enable(struct clk *c)
{
u32 mode;
unsigned long flags;
- struct pll_clk *pll = to_pll_clk(clk);
+ struct pll_clk *pll = to_pll_clk(c);
spin_lock_irqsave(&pll_reg_lock, flags);
mode = readl_relaxed(PLL_MODE_REG(pll));
@@ -250,10 +248,10 @@
#define PLL_LOCKED_BIT BIT(16)
-int copper_pll_clk_enable(struct clk *clk)
+int copper_pll_clk_enable(struct clk *c)
{
unsigned long flags;
- struct pll_clk *pll = to_pll_clk(clk);
+ struct pll_clk *pll = to_pll_clk(c);
u32 count, mode;
int ret = 0;
@@ -282,7 +280,7 @@
}
if (!(readl_relaxed(PLL_STATUS_REG(pll)) & PLL_LOCKED_BIT)) {
- WARN("PLL %s didn't lock after enabling it!\n", clk->dbg_name);
+ WARN("PLL %s didn't lock after enabling it!\n", c->dbg_name);
ret = -ETIMEDOUT;
goto out;
}
@@ -379,9 +377,9 @@
}
-static int pll_clk_enable(struct clk *clk)
+static int pll_clk_enable(struct clk *c)
{
- struct pll_shared_clk *pll = to_pll_shared_clk(clk);
+ struct pll_shared_clk *pll = to_pll_shared_clk(c);
unsigned int pll_id = pll->id;
remote_spin_lock(&pll_lock);
@@ -396,9 +394,9 @@
return 0;
}
-static void pll_clk_disable(struct clk *clk)
+static void pll_clk_disable(struct clk *c)
{
- struct pll_shared_clk *pll = to_pll_shared_clk(clk);
+ struct pll_shared_clk *pll = to_pll_shared_clk(c);
unsigned int pll_id = pll->id;
remote_spin_lock(&pll_lock);
@@ -413,16 +411,14 @@
remote_spin_unlock(&pll_lock);
}
-static int pll_clk_is_enabled(struct clk *clk)
+static int pll_clk_is_enabled(struct clk *c)
{
- struct pll_shared_clk *pll = to_pll_shared_clk(clk);
-
- return readl_relaxed(PLL_MODE_REG(pll)) & BIT(0);
+ return readl_relaxed(PLL_MODE_REG(to_pll_shared_clk(c))) & BIT(0);
}
-static enum handoff pll_clk_handoff(struct clk *clk)
+static enum handoff pll_clk_handoff(struct clk *c)
{
- struct pll_shared_clk *pll = to_pll_shared_clk(clk);
+ struct pll_shared_clk *pll = to_pll_shared_clk(c);
unsigned int pll_lval;
struct pll_rate *l;
@@ -438,12 +434,12 @@
/* Convert PLL L values to PLL Output rate */
for (l = pll_l_rate; l->rate != 0; l++) {
if (l->lvalue == pll_lval) {
- clk->rate = l->rate;
+ c->rate = l->rate;
break;
}
}
- if (!clk->rate) {
+ if (!c->rate) {
pr_crit("Unknown PLL's L value!\n");
BUG();
}
diff --git a/arch/arm/mach-msm/clock-pll.h b/arch/arm/mach-msm/clock-pll.h
index a8c642f..f24b066 100644
--- a/arch/arm/mach-msm/clock-pll.h
+++ b/arch/arm/mach-msm/clock-pll.h
@@ -34,7 +34,7 @@
* @id: PLL ID
* @mode_reg: enable register
* @parent: clock source
- * @c: clk
+ * @c: clock
*/
struct pll_shared_clk {
unsigned int id;
@@ -45,9 +45,9 @@
extern struct clk_ops clk_ops_pll;
-static inline struct pll_shared_clk *to_pll_shared_clk(struct clk *clk)
+static inline struct pll_shared_clk *to_pll_shared_clk(struct clk *c)
{
- return container_of(clk, struct pll_shared_clk, c);
+ return container_of(c, struct pll_shared_clk, c);
}
/**
@@ -64,7 +64,7 @@
* @status_mask: ANDed with @status_reg to determine if PLL is active.
* @status_reg: status register
* @parent: clock source
- * @c: clk
+ * @c: clock
*/
struct pll_vote_clk {
u32 *soft_vote;
@@ -81,9 +81,9 @@
extern struct clk_ops clk_ops_pll_vote;
-static inline struct pll_vote_clk *to_pll_vote_clk(struct clk *clk)
+static inline struct pll_vote_clk *to_pll_vote_clk(struct clk *c)
{
- return container_of(clk, struct pll_vote_clk, c);
+ return container_of(c, struct pll_vote_clk, c);
}
/**
@@ -105,21 +105,21 @@
extern struct clk_ops clk_ops_local_pll;
-static inline struct pll_clk *to_pll_clk(struct clk *clk)
+static inline struct pll_clk *to_pll_clk(struct clk *c)
{
- return container_of(clk, struct pll_clk, c);
+ return container_of(c, struct pll_clk, c);
}
-int sr_pll_clk_enable(struct clk *clk);
-int copper_pll_clk_enable(struct clk *clk);
+int sr_pll_clk_enable(struct clk *c);
+int copper_pll_clk_enable(struct clk *c);
/*
* PLL vote clock APIs
*/
-int pll_vote_clk_enable(struct clk *clk);
-void pll_vote_clk_disable(struct clk *clk);
-struct clk *pll_vote_clk_get_parent(struct clk *clk);
-int pll_vote_clk_is_enabled(struct clk *clk);
+int pll_vote_clk_enable(struct clk *c);
+void pll_vote_clk_disable(struct clk *c);
+struct clk *pll_vote_clk_get_parent(struct clk *c);
+int pll_vote_clk_is_enabled(struct clk *c);
struct pll_config {
u32 l;
diff --git a/arch/arm/mach-msm/clock-rpm.c b/arch/arm/mach-msm/clock-rpm.c
index e35e8d4..8096c10 100644
--- a/arch/arm/mach-msm/clock-rpm.c
+++ b/arch/arm/mach-msm/clock-rpm.c
@@ -51,7 +51,7 @@
int rc;
struct msm_rpm_iv_pair iv = { .id = r->rpm_status_id, };
rc = msm_rpm_get_status(&iv, 1);
- return (rc < 0) ? rc : iv.value * 1000;
+ return (rc < 0) ? rc : iv.value * r->factor;
}
#define RPM_SMD_KEY_RATE 0x007A484B
@@ -192,7 +192,7 @@
unsigned long this_khz, this_sleep_khz;
int rc = 0;
- this_khz = DIV_ROUND_UP(rate, 1000);
+ this_khz = DIV_ROUND_UP(rate, r->factor);
spin_lock_irqsave(&rpm_clock_lock, flags);
@@ -277,7 +277,7 @@
if (!r->branch) {
r->last_set_khz = iv.value;
r->last_set_sleep_khz = iv.value;
- clk->rate = iv.value * 1000;
+ clk->rate = iv.value * r->factor;
}
return HANDOFF_ENABLED_CLK;
diff --git a/arch/arm/mach-msm/clock-rpm.h b/arch/arm/mach-msm/clock-rpm.h
index b2358bc..107fb02 100644
--- a/arch/arm/mach-msm/clock-rpm.h
+++ b/arch/arm/mach-msm/clock-rpm.h
@@ -32,6 +32,7 @@
unsigned last_set_sleep_khz;
bool enabled;
bool branch; /* true: RPM only accepts 1 for ON and 0 for OFF */
+ unsigned factor;
struct clk_rpmrs_data *rpmrs_data;
struct rpm_clk *peer;
@@ -53,6 +54,7 @@
.rpm_clk_id = (r_id), \
.rpm_status_id = (stat_id), \
.peer = &active, \
+ .factor = 1000, \
.rpmrs_data = (rpmrsdata),\
.c = { \
.ops = &clk_ops_rpm, \
@@ -68,6 +70,7 @@
.rpm_status_id = (stat_id), \
.peer = &name, \
.active_only = true, \
+ .factor = 1000, \
.rpmrs_data = (rpmrsdata),\
.c = { \
.ops = &clk_ops_rpm, \
@@ -88,6 +91,7 @@
.peer = &active, \
.last_set_khz = ((r) / 1000), \
.last_set_sleep_khz = ((r) / 1000), \
+ .factor = 1000, \
.branch = true, \
.rpmrs_data = (rpmrsdata),\
.c = { \
@@ -106,6 +110,7 @@
.peer = &name, \
.last_set_khz = ((r) / 1000), \
.active_only = true, \
+ .factor = 1000, \
.branch = true, \
.rpmrs_data = (rpmrsdata),\
.c = { \
@@ -118,10 +123,48 @@
}, \
};
+#define __DEFINE_CLK_RPM_QDSS(name, active, type, r_id, stat_id, rpmrsdata) \
+ static struct rpm_clk active; \
+ static struct rpm_clk name = { \
+ .rpm_res_type = (type), \
+ .rpm_clk_id = (r_id), \
+ .rpm_status_id = (stat_id), \
+ .peer = &active, \
+ .factor = 1, \
+ .rpmrs_data = (rpmrsdata),\
+ .c = { \
+ .ops = &clk_ops_rpm, \
+ .flags = CLKFLAG_SKIP_AUTO_OFF, \
+ .dbg_name = #name, \
+ CLK_INIT(name.c), \
+ .warned = true, \
+ }, \
+ }; \
+ static struct rpm_clk active = { \
+ .rpm_res_type = (type), \
+ .rpm_clk_id = (r_id), \
+ .rpm_status_id = (stat_id), \
+ .peer = &name, \
+ .active_only = true, \
+ .factor = 1, \
+ .rpmrs_data = (rpmrsdata),\
+ .c = { \
+ .ops = &clk_ops_rpm, \
+ .flags = CLKFLAG_SKIP_AUTO_OFF, \
+ .dbg_name = #active, \
+ CLK_INIT(active.c), \
+ .warned = true, \
+ }, \
+ };
+
#define DEFINE_CLK_RPM(name, active, r_id, dep) \
__DEFINE_CLK_RPM(name, active, 0, MSM_RPM_ID_##r_id##_CLK, \
MSM_RPM_STATUS_ID_##r_id##_CLK, dep, &clk_rpmrs_data)
+#define DEFINE_CLK_RPM_QDSS(name, active) \
+ __DEFINE_CLK_RPM_QDSS(name, active, 0, MSM_RPM_ID_QDSS_CLK, \
+ MSM_RPM_STATUS_ID_QDSS_CLK, &clk_rpmrs_data)
+
#define DEFINE_CLK_RPM_BRANCH(name, active, r_id, r) \
__DEFINE_CLK_RPM_BRANCH(name, active, 0, MSM_RPM_ID_##r_id##_CLK, \
MSM_RPM_STATUS_ID_##r_id##_CLK, r, &clk_rpmrs_data)
diff --git a/arch/arm/mach-msm/devices-8064.c b/arch/arm/mach-msm/devices-8064.c
index cc3c6db..472a87e 100644
--- a/arch/arm/mach-msm/devices-8064.c
+++ b/arch/arm/mach-msm/devices-8064.c
@@ -17,6 +17,7 @@
#include <linux/msm_rotator.h>
#include <linux/clkdev.h>
#include <linux/dma-mapping.h>
+#include <linux/coresight.h>
#include <mach/irqs-8064.h>
#include <mach/board.h>
#include <mach/msm_iomap.h>
@@ -32,7 +33,6 @@
#include <mach/msm_smd.h>
#include <mach/msm_dcvs.h>
#include <mach/msm_rtb.h>
-#include <mach/qdss.h>
#include <linux/ion.h>
#include "clock.h"
#include "devices.h"
diff --git a/arch/arm/mach-msm/devices-8930.c b/arch/arm/mach-msm/devices-8930.c
index c480bba..6ea8d7b 100644
--- a/arch/arm/mach-msm/devices-8930.c
+++ b/arch/arm/mach-msm/devices-8930.c
@@ -25,6 +25,7 @@
#include <mach/socinfo.h>
#include <mach/iommu_domains.h>
#include <mach/msm_rtb.h>
+#include <mach/msm_cache_dump.h>
#include "devices.h"
#include "rpm_log.h"
@@ -901,3 +902,23 @@
.platform_data = &msm8930_rtb_pdata,
},
};
+
+#define MSM8930_L1_SIZE SZ_1M
+/*
+ * The actual L2 size is smaller but we need a larger buffer
+ * size to store other dump information
+ */
+#define MSM8930_L2_SIZE SZ_4M
+
+struct msm_cache_dump_platform_data msm8930_cache_dump_pdata = {
+ .l2_size = MSM8930_L2_SIZE,
+ .l1_size = MSM8930_L1_SIZE,
+};
+
+struct platform_device msm8930_cache_dump_device = {
+ .name = "msm_cache_dump",
+ .id = -1,
+ .dev = {
+ .platform_data = &msm8930_cache_dump_pdata,
+ },
+};
diff --git a/arch/arm/mach-msm/devices-8960.c b/arch/arm/mach-msm/devices-8960.c
index 550a283..3522e80 100644
--- a/arch/arm/mach-msm/devices-8960.c
+++ b/arch/arm/mach-msm/devices-8960.c
@@ -17,6 +17,7 @@
#include <linux/msm_rotator.h>
#include <linux/ion.h>
#include <linux/gpio.h>
+#include <linux/coresight.h>
#include <asm/clkdev.h>
#include <linux/msm_kgsl.h>
#include <linux/android_pmem.h>
@@ -37,7 +38,6 @@
#include <sound/msm-dai-q6.h>
#include <sound/apr_audio.h>
#include <mach/msm_tsif.h>
-#include <mach/qdss.h>
#include <mach/msm_serial_hs_lite.h>
#include "clock.h"
#include "devices.h"
diff --git a/arch/arm/mach-msm/devices-fsm9xxx.c b/arch/arm/mach-msm/devices-fsm9xxx.c
index 777b6d6..5f4d940 100644
--- a/arch/arm/mach-msm/devices-fsm9xxx.c
+++ b/arch/arm/mach-msm/devices-fsm9xxx.c
@@ -71,6 +71,26 @@
.resource = resources_uart2,
};
+static struct resource resources_uart3[] = {
+ {
+ .start = INT_UART3,
+ .end = INT_UART3,
+ .flags = IORESOURCE_IRQ,
+ },
+ {
+ .start = MSM_UART3_PHYS,
+ .end = MSM_UART3_PHYS + MSM_UART3_SIZE - 1,
+ .flags = IORESOURCE_MEM,
+ },
+};
+
+struct platform_device msm_device_uart3 = {
+ .name = "msm_uim",
+ .id = 2,
+ .num_resources = ARRAY_SIZE(resources_uart3),
+ .resource = resources_uart3,
+};
+
/*
* SSBIs
*/
diff --git a/arch/arm/mach-msm/devices-msm7x27a.c b/arch/arm/mach-msm/devices-msm7x27a.c
index 553f52f..1c58490 100644
--- a/arch/arm/mach-msm/devices-msm7x27a.c
+++ b/arch/arm/mach-msm/devices-msm7x27a.c
@@ -558,8 +558,8 @@
},
{
.name = "sdcc_dma_chnl",
- .start = DMOV_SDC3_CHAN,
- .end = DMOV_SDC3_CHAN,
+ .start = DMOV_NAND_CHAN,
+ .end = DMOV_NAND_CHAN,
.flags = IORESOURCE_DMA,
},
{
diff --git a/arch/arm/mach-msm/devices-msm7x30.c b/arch/arm/mach-msm/devices-msm7x30.c
index ff747e2..722575d 100644
--- a/arch/arm/mach-msm/devices-msm7x30.c
+++ b/arch/arm/mach-msm/devices-msm7x30.c
@@ -820,8 +820,8 @@
},
{
.name = "sdcc_dma_chnl",
- .start = DMOV_SDC2_CHAN,
- .end = DMOV_SDC2_CHAN,
+ .start = DMOV_NAND_CHAN,
+ .end = DMOV_NAND_CHAN,
.flags = IORESOURCE_DMA,
},
{
diff --git a/arch/arm/mach-msm/devices.h b/arch/arm/mach-msm/devices.h
index ea47727..152ca5b 100644
--- a/arch/arm/mach-msm/devices.h
+++ b/arch/arm/mach-msm/devices.h
@@ -406,6 +406,7 @@
extern struct platform_device msm8960_cache_dump_device;
extern struct platform_device apq8064_cache_dump_device;
+extern struct platform_device msm8930_cache_dump_device;
extern struct platform_device copper_device_tz_log;
diff --git a/arch/arm/mach-msm/footswitch-pcom.c b/arch/arm/mach-msm/footswitch-pcom.c
index 07d7118..8903859 100644
--- a/arch/arm/mach-msm/footswitch-pcom.c
+++ b/arch/arm/mach-msm/footswitch-pcom.c
@@ -42,7 +42,6 @@
* @init_data: Regulator platform data
* @pcom_id: Proc-comm ID of the footswitch
* @is_enabled: Flag set when footswitch is enabled
- * @is_manual: Flag set when footswitch is in manual proc-comm mode
* @has_ahb_clk: Flag set if footswitched core has an ahb_clk
* @has_src_clk: Flag set if footswitched core has a src_clk
* @src_clk: Controls the core clock's rate
@@ -57,7 +56,6 @@
struct regulator_init_data init_data;
unsigned pcom_id;
bool is_enabled;
- bool is_manual;
struct clk *src_clk;
struct clk *core_clk;
struct clk *ahb_clk;
@@ -256,12 +254,19 @@
if (pdev->id >= MAX_FS)
return -ENODEV;
- fs = &footswitches[pdev->id];
- if (!fs->is_manual) {
- pr_err("%s is not in manual mode\n", fs->desc.name);
- return -EINVAL;
- }
init_data = pdev->dev.platform_data;
+ fs = &footswitches[pdev->id];
+
+ /*
+ * Enable footswitch in manual mode (ie. not controlled along
+ * with pcom clocks).
+ */
+ rc = set_rail_state(fs->pcom_id, PCOM_CLKCTL_RPC_RAIL_ENABLE);
+ if (rc)
+ return rc;
+ rc = set_rail_mode(fs->pcom_id, PCOM_RAIL_MODE_MANUAL);
+ if (rc)
+ return rc;
rc = get_clocks(&pdev->dev, fs);
if (rc)
@@ -305,21 +310,6 @@
static int __init footswitch_init(void)
{
- struct footswitch *fs;
- int ret;
-
- /*
- * Enable all footswitches in manual mode (ie. not controlled along
- * with pcom clocks).
- */
- for (fs = footswitches; fs < footswitches + ARRAY_SIZE(footswitches);
- fs++) {
- set_rail_state(fs->pcom_id, PCOM_CLKCTL_RPC_RAIL_ENABLE);
- ret = set_rail_mode(fs->pcom_id, PCOM_RAIL_MODE_MANUAL);
- if (!ret)
- fs->is_manual = 1;
- }
-
return platform_driver_register(&footswitch_driver);
}
subsys_initcall(footswitch_init);
diff --git a/arch/arm/mach-msm/gdsc.c b/arch/arm/mach-msm/gdsc.c
index df3a92d..f91e3dc 100644
--- a/arch/arm/mach-msm/gdsc.c
+++ b/arch/arm/mach-msm/gdsc.c
@@ -63,10 +63,18 @@
ret = readl_tight_poll_timeout(sc->gdscr, regval, regval & PWR_ON_MASK,
TIMEOUT_US);
- if (ret)
+ if (ret) {
dev_err(&rdev->dev, "%s enable timed out\n", sc->rdesc.name);
+ return ret;
+ }
- return ret;
+ /*
+ * If clocks to this power domain were already on, they will take an
+ * additional 4 clock cycles to re-enable after the rail is enabled.
+ */
+ udelay(1);
+
+ return 0;
}
static int gdsc_disable(struct regulator_dev *rdev)
diff --git a/arch/arm/mach-msm/gss-8064.c b/arch/arm/mach-msm/gss-8064.c
index 126f8e0..e65f2d2 100644
--- a/arch/arm/mach-msm/gss-8064.c
+++ b/arch/arm/mach-msm/gss-8064.c
@@ -69,40 +69,12 @@
wmb();
}
-static void gss_fatal_fn(struct work_struct *work)
+static void restart_gss(void)
{
- uint32_t panic_smsm_states = SMSM_RESET | SMSM_SYSTEM_DOWNLOAD;
- uint32_t reset_smsm_states = SMSM_SYSTEM_REBOOT_USR |
- SMSM_SYSTEM_PWRDWN_USR;
- uint32_t gss_state;
-
- pr_err("Watchdog bite received from GSS!\n");
-
- gss_state = smsm_get_state(SMSM_MODEM_STATE);
-
- if (gss_state & panic_smsm_states) {
-
- pr_err("GSS SMSM state changed to SMSM_RESET.\n"
- "Probable err_fatal on the GSS. "
- "Calling subsystem restart...\n");
- log_gss_sfr();
- subsystem_restart("gss");
-
- } else if (gss_state & reset_smsm_states) {
-
- pr_err("%s: User-invoked system reset/powerdown. "
- "Resetting the SoC now.\n",
- __func__);
- kernel_restart(NULL);
- } else {
- /* TODO: Bus unlock code/sequence goes _here_ */
- log_gss_sfr();
- subsystem_restart("gss");
- }
+ log_gss_sfr();
+ subsystem_restart("gss");
}
-static DECLARE_WORK(gss_fatal_work, gss_fatal_fn);
-
static void smsm_state_cb(void *data, uint32_t old_state, uint32_t new_state)
{
/* Ignore if we're the one that set SMSM_RESET */
@@ -113,8 +85,7 @@
pr_err("GSS SMSM state changed to SMSM_RESET.\n"
"Probable err_fatal on the GSS. "
"Calling subsystem restart...\n");
- log_gss_sfr();
- subsystem_restart("gss");
+ restart_gss();
}
}
@@ -180,8 +151,8 @@
static irqreturn_t gss_wdog_bite_irq(int irq, void *dev_id)
{
- schedule_work(&gss_fatal_work);
- disable_irq_nosync(GSS_A5_WDOG_EXPIRED);
+ pr_err("Watchdog bite received from GSS!\n");
+ restart_gss();
return IRQ_HANDLED;
}
diff --git a/arch/arm/mach-msm/hotplug.c b/arch/arm/mach-msm/hotplug.c
index 46e835f..f8324ce 100644
--- a/arch/arm/mach-msm/hotplug.c
+++ b/arch/arm/mach-msm/hotplug.c
@@ -16,7 +16,7 @@
#include <asm/smp_plat.h>
#include <asm/vfp.h>
-#include <mach/qdss.h>
+#include <mach/jtag.h>
#include <mach/msm_rtb.h>
#include "pm.h"
diff --git a/arch/arm/mach-msm/include/mach/jtag.h b/arch/arm/mach-msm/include/mach/jtag.h
new file mode 100644
index 0000000..3850eff
--- /dev/null
+++ b/arch/arm/mach-msm/include/mach/jtag.h
@@ -0,0 +1,24 @@
+/* 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_JTAG_H
+#define __MACH_JTAG_H
+
+#ifdef CONFIG_MSM_JTAG
+extern void msm_jtag_save_state(void);
+extern void msm_jtag_restore_state(void);
+#else
+static inline void msm_jtag_save_state(void) {}
+static inline void msm_jtag_restore_state(void) {}
+#endif
+
+#endif
diff --git a/arch/arm/mach-msm/include/mach/mdm2.h b/arch/arm/mach-msm/include/mach/mdm2.h
index 09839b2..2bcdf07 100644
--- a/arch/arm/mach-msm/include/mach/mdm2.h
+++ b/arch/arm/mach-msm/include/mach/mdm2.h
@@ -27,6 +27,7 @@
int soft_reset_inverted;
int early_power_on;
int sfr_query;
+ int no_powerdown_after_ramdumps;
struct mdm_vddmin_resource *vddmin_resource;
struct platform_device *peripheral_platform_device;
};
diff --git a/arch/arm/mach-msm/include/mach/msm_iomap-fsm9xxx.h b/arch/arm/mach-msm/include/mach/msm_iomap-fsm9xxx.h
index c30c9e4..a99f1f7 100644
--- a/arch/arm/mach-msm/include/mach/msm_iomap-fsm9xxx.h
+++ b/arch/arm/mach-msm/include/mach/msm_iomap-fsm9xxx.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
+/* Copyright (c) 2010-2012, Code Aurora Forum. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -78,7 +78,10 @@
#define MSM_UART1_PHYS 0x94000000
#define MSM_UART1_SIZE SZ_4K
-#define MSM_UART2_PHYS 0x94100000
+#define MSM_UART2_PHYS 0x94010000
#define MSM_UART2_SIZE SZ_4K
+#define MSM_UART3_PHYS 0x94100000
+#define MSM_UART3_SIZE SZ_4K
+
#endif
diff --git a/arch/arm/mach-msm/include/mach/msm_spi.h b/arch/arm/mach-msm/include/mach/msm_spi.h
index 51081b6..11d3014 100644
--- a/arch/arm/mach-msm/include/mach/msm_spi.h
+++ b/arch/arm/mach-msm/include/mach/msm_spi.h
@@ -21,4 +21,5 @@
int (*dma_config)(void);
const char *rsl_id;
uint32_t pm_lat;
+ uint32_t infinite_mode;
};
diff --git a/arch/arm/mach-msm/include/mach/qdss.h b/arch/arm/mach-msm/include/mach/qdss.h
deleted file mode 100644
index 05d8577..0000000
--- a/arch/arm/mach-msm/include/mach/qdss.h
+++ /dev/null
@@ -1,54 +0,0 @@
-/* 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_QDSS_H
-#define __MACH_QDSS_H
-
-struct qdss_source {
- struct list_head link;
- const char *name;
- uint32_t fport_mask;
-};
-
-struct msm_qdss_platform_data {
- struct qdss_source *src_table;
- size_t size;
- uint8_t afamily;
-};
-
-#ifdef CONFIG_MSM_QDSS
-extern struct qdss_source *qdss_get(const char *name);
-extern void qdss_put(struct qdss_source *src);
-extern int qdss_enable(struct qdss_source *src);
-extern void qdss_disable(struct qdss_source *src);
-extern void qdss_disable_sink(void);
-extern int qdss_clk_enable(void);
-extern void qdss_clk_disable(void);
-#else
-static inline struct qdss_source *qdss_get(const char *name) { return NULL; }
-static inline void qdss_put(struct qdss_source *src) {}
-static inline int qdss_enable(struct qdss_source *src) { return -ENOSYS; }
-static inline void qdss_disable(struct qdss_source *src) {}
-static inline void qdss_disable_sink(void) {}
-static inline int qdss_clk_enable(void) { return -ENOSYS; }
-static inline void qdss_clk_disable(void) {}
-#endif
-
-#ifdef CONFIG_MSM_JTAG
-extern void msm_jtag_save_state(void);
-extern void msm_jtag_restore_state(void);
-#else
-static inline void msm_jtag_save_state(void) {}
-static inline void msm_jtag_restore_state(void) {}
-#endif
-
-#endif
diff --git a/arch/arm/mach-msm/jtag.c b/arch/arm/mach-msm/jtag.c
index 8dae9c6..bf5857c 100644
--- a/arch/arm/mach-msm/jtag.c
+++ b/arch/arm/mach-msm/jtag.c
@@ -19,11 +19,16 @@
#include <linux/export.h>
#include <linux/printk.h>
#include <linux/ratelimit.h>
+#include <linux/coresight.h>
#include <mach/scm.h>
+#include <mach/jtag.h>
-#include "qdss-priv.h"
#include "cp14.h"
+#define BM(lsb, msb) ((BIT(msb) - BIT(lsb)) + BIT(msb))
+#define BMVAL(val, lsb, msb) ((val & BM(lsb, msb)) >> lsb)
+#define BVAL(val, n) ((val & BIT(n)) >> n)
+
/* no of dbg regs + 1 (for storing the reg count) */
#define MAX_DBG_REGS (90)
#define MAX_DBG_STATE_SIZE (MAX_DBG_REGS * num_possible_cpus())
diff --git a/arch/arm/mach-msm/mdm2.c b/arch/arm/mach-msm/mdm2.c
index 4791955..f851545 100644
--- a/arch/arm/mach-msm/mdm2.c
+++ b/arch/arm/mach-msm/mdm2.c
@@ -42,9 +42,6 @@
#include "clock.h"
#include "mdm_private.h"
-#define MDM_MODEM_TIMEOUT 6000
-#define MDM_HOLD_TIME 4000
-#define MDM_MODEM_DELTA 100
#define MDM_PBLRDY_CNT 20
static int mdm_debug_on;
@@ -80,20 +77,52 @@
mutex_unlock(&hsic_status_lock);
}
+static void mdm_toggle_soft_reset(struct mdm_modem_drv *mdm_drv)
+{
+ int soft_reset_direction_assert = 0,
+ soft_reset_direction_de_assert = 1;
+
+ if (mdm_drv->pdata->soft_reset_inverted) {
+ soft_reset_direction_assert = 1;
+ soft_reset_direction_de_assert = 0;
+ }
+ gpio_direction_output(mdm_drv->ap2mdm_soft_reset_gpio,
+ soft_reset_direction_assert);
+ usleep_range(5000, 10000);
+ gpio_direction_output(mdm_drv->ap2mdm_soft_reset_gpio,
+ soft_reset_direction_de_assert);
+}
+
static void mdm_power_down_common(struct mdm_modem_drv *mdm_drv)
{
+ int i;
int soft_reset_direction =
mdm_drv->pdata->soft_reset_inverted ? 1 : 0;
- gpio_direction_output(mdm_drv->ap2mdm_soft_reset_gpio,
- soft_reset_direction);
+ /* Wait for the modem to complete its power down actions. */
+ for (i = 20; i > 0; i--) {
+ if (gpio_get_value(mdm_drv->mdm2ap_status_gpio) == 0)
+ break;
+ msleep(100);
+ }
+ if (i == 0) {
+ pr_err("%s: MDM2AP_STATUS never went low. Doing a hard reset\n",
+ __func__);
+ gpio_direction_output(mdm_drv->ap2mdm_soft_reset_gpio,
+ soft_reset_direction);
+ /*
+ * Currently, there is a debounce timer on the charm PMIC. It is
+ * necessary to hold the PMIC RESET low for ~3.5 seconds
+ * for the reset to fully take place. Sleep here to ensure the
+ * reset has occured before the function exits.
+ */
+ msleep(4000);
+ }
mdm_peripheral_disconnect(mdm_drv);
}
static void mdm_do_first_power_on(struct mdm_modem_drv *mdm_drv)
{
- int soft_reset_direction =
- mdm_drv->pdata->soft_reset_inverted ? 0 : 1;
int i;
int pblrdy;
@@ -106,6 +135,13 @@
pr_err("%s: Powering on modem for the first time\n", __func__);
mdm_peripheral_disconnect(mdm_drv);
+ /* If this is the first power-up after a panic, the modem may still
+ * be in a power-on state, in which case we need to toggle the gpio
+ * instead of just de-asserting it. No harm done if the modem was
+ * powered down.
+ */
+ mdm_toggle_soft_reset(mdm_drv);
+
/* If the device has a kpd pwr gpio then toggle it. */
if (mdm_drv->ap2mdm_kpdpwr_n_gpio > 0) {
/* Pull AP2MDM_KPDPWR gpio high and wait for PS_HOLD to settle,
@@ -117,10 +153,6 @@
gpio_direction_output(mdm_drv->ap2mdm_kpdpwr_n_gpio, 0);
}
- /* De-assert the soft reset line. */
- pr_debug("%s: De-asserting soft reset gpio\n", __func__);
- gpio_direction_output(mdm_drv->ap2mdm_soft_reset_gpio,
- soft_reset_direction);
if (!mdm_drv->mdm2ap_pblrdy)
goto start_mdm_peripheral;
@@ -140,21 +172,12 @@
static void mdm_do_soft_power_on(struct mdm_modem_drv *mdm_drv)
{
- int soft_reset_direction =
- mdm_drv->pdata->soft_reset_inverted ? 0 : 1;
int i;
int pblrdy;
- /* De-assert the soft reset line. */
pr_err("%s: soft resetting mdm modem\n", __func__);
-
mdm_peripheral_disconnect(mdm_drv);
-
- gpio_direction_output(mdm_drv->ap2mdm_soft_reset_gpio,
- soft_reset_direction == 1 ? 0 : 1);
- usleep_range(5000, 10000);
- gpio_direction_output(mdm_drv->ap2mdm_soft_reset_gpio,
- soft_reset_direction == 1 ? 1 : 0);
+ mdm_toggle_soft_reset(mdm_drv);
if (!mdm_drv->mdm2ap_pblrdy)
goto start_mdm_peripheral;
diff --git a/arch/arm/mach-msm/mdm_common.c b/arch/arm/mach-msm/mdm_common.c
index c961731..04ce49f 100644
--- a/arch/arm/mach-msm/mdm_common.c
+++ b/arch/arm/mach-msm/mdm_common.c
@@ -45,7 +45,7 @@
#define MDM_MODEM_TIMEOUT 6000
#define MDM_MODEM_DELTA 100
#define MDM_BOOT_TIMEOUT 60000L
-#define MDM_RDUMP_TIMEOUT 60000L
+#define MDM_RDUMP_TIMEOUT 120000L
#define MDM2AP_STATUS_TIMEOUT_MS 60000L
static int mdm_debug_on;
@@ -403,7 +403,8 @@
pr_info("%s: mdm modem ramdumps completed.\n",
__func__);
INIT_COMPLETION(mdm_ram_dumps);
- mdm_drv->ops->power_down_mdm_cb(mdm_drv);
+ if (!mdm_drv->pdata->no_powerdown_after_ramdumps)
+ mdm_drv->ops->power_down_mdm_cb(mdm_drv);
}
return mdm_drv->mdm_ram_dump_status;
}
diff --git a/arch/arm/mach-msm/memory.c b/arch/arm/mach-msm/memory.c
index 40845d7..a1b21c5 100644
--- a/arch/arm/mach-msm/memory.c
+++ b/arch/arm/mach-msm/memory.c
@@ -363,64 +363,6 @@
}
EXPORT_SYMBOL(allocate_contiguous_ebi_nomap);
-/* emulation of the deprecated pmem_kalloc and pmem_kfree */
-int32_t pmem_kalloc(const size_t size, const uint32_t flags)
-{
- int pmem_memtype;
- int memtype = MEMTYPE_NONE;
- int ebi1_memtype = MEMTYPE_EBI1;
- unsigned int align;
- int32_t paddr;
-
- switch (flags & PMEM_ALIGNMENT_MASK) {
- case PMEM_ALIGNMENT_4K:
- align = SZ_4K;
- break;
- case PMEM_ALIGNMENT_1M:
- align = SZ_1M;
- break;
- default:
- pr_alert("Invalid alignment %x\n",
- (flags & PMEM_ALIGNMENT_MASK));
- return -EINVAL;
- }
-
- /* on 7x30 and 8x55 "EBI1 kernel PMEM" is really on EBI0 */
- if (cpu_is_msm7x30() || cpu_is_msm8x55())
- ebi1_memtype = MEMTYPE_EBI0;
-
- pmem_memtype = flags & PMEM_MEMTYPE_MASK;
- if (pmem_memtype == PMEM_MEMTYPE_EBI1)
- memtype = ebi1_memtype;
- else if (pmem_memtype == PMEM_MEMTYPE_SMI)
- memtype = MEMTYPE_SMI_KERNEL;
- else {
- pr_alert("Invalid memory type %x\n",
- flags & PMEM_MEMTYPE_MASK);
- return -EINVAL;
- }
-
- paddr = _allocate_contiguous_memory_nomap(size, memtype, align,
- __builtin_return_address(0));
-
- if (!paddr && pmem_memtype == PMEM_MEMTYPE_SMI)
- paddr = _allocate_contiguous_memory_nomap(size,
- ebi1_memtype, align, __builtin_return_address(0));
-
- if (!paddr)
- return -ENOMEM;
- return paddr;
-}
-EXPORT_SYMBOL(pmem_kalloc);
-
-int pmem_kfree(const int32_t physaddr)
-{
- free_contiguous_memory_by_paddr(physaddr);
-
- return 0;
-}
-EXPORT_SYMBOL(pmem_kfree);
-
unsigned int msm_ttbr0;
void store_ttbr0(void)
diff --git a/arch/arm/mach-msm/perf_event_msm_krait_l2.c b/arch/arm/mach-msm/perf_event_msm_krait_l2.c
index d82f4dd..5f76a92 100644
--- a/arch/arm/mach-msm/perf_event_msm_krait_l2.c
+++ b/arch/arm/mach-msm/perf_event_msm_krait_l2.c
@@ -14,12 +14,17 @@
#include <linux/irq.h>
#include <asm/pmu.h>
#include <linux/platform_device.h>
+#include <linux/spinlock.h>
#include <mach/msm-krait-l2-accessors.h>
#define MAX_L2_PERIOD ((1ULL << 32) - 1)
#define MAX_KRAIT_L2_CTRS 5
+#define L2_EVT_MASK 0xfffff
+
+#define L2_SLAVE_EV_PREFIX 4
+
#define L2PMCCNTR 0x409
#define L2PMCCNTCR 0x408
#define L2PMCCNTSR 0x40A
@@ -48,16 +53,62 @@
/* event format is -e rsRCCG See get_event_desc() */
-#define EVENT_REG_MASK 0xf000
-#define EVENT_GROUPSEL_MASK 0x000f
-#define EVENT_GROUPCODE_MASK 0x0ff0
+#define EVENT_PREFIX_MASK 0xf0000
+#define EVENT_REG_MASK 0x0f000
+#define EVENT_GROUPSEL_MASK 0x0000f
+#define EVENT_GROUPCODE_MASK 0x00ff0
+
+#define EVENT_PREFIX_SHIFT 16
#define EVENT_REG_SHIFT 12
#define EVENT_GROUPCODE_SHIFT 4
#define RESRX_VALUE_EN 0x80000000
+/*
+ * The L2 PMU is shared between all CPU's, so protect
+ * its bitmap access.
+ */
+struct pmu_constraints {
+ u64 pmu_bitmap;
+ raw_spinlock_t lock;
+} l2_pmu_constraints = {
+ .pmu_bitmap = 0,
+ .lock = __RAW_SPIN_LOCK_UNLOCKED(l2_pmu_constraints.lock),
+};
+
+/* NRCCG format for perf RAW codes. */
+PMU_FORMAT_ATTR(l2_prefix, "config:16-19");
+PMU_FORMAT_ATTR(l2_reg, "config:12-15");
+PMU_FORMAT_ATTR(l2_code, "config:4-11");
+PMU_FORMAT_ATTR(l2_grp, "config:0-3");
+
+static struct attribute *msm_l2_ev_formats[] = {
+ &format_attr_l2_prefix.attr,
+ &format_attr_l2_reg.attr,
+ &format_attr_l2_code.attr,
+ &format_attr_l2_grp.attr,
+ NULL,
+};
+
+/*
+ * Format group is essential to access PMU's from userspace
+ * via their .name field.
+ */
+static struct attribute_group msm_l2_pmu_format_group = {
+ .name = "format",
+ .attrs = msm_l2_ev_formats,
+};
+
+static const struct attribute_group *msm_l2_pmu_attr_grps[] = {
+ &msm_l2_pmu_format_group,
+ NULL,
+};
+
static u32 l2_orig_filter_prefix = 0x000f0030;
+/* L2 slave port traffic filtering */
+static u32 l2_slv_filter_prefix = 0x000f0010;
+
static u32 pmu_type;
static struct arm_pmu krait_l2_pmu;
@@ -128,19 +179,25 @@
set_l2_indirect_reg(group_reg, resr_val);
}
-static void set_evfilter_task_mode(int ctr)
+static void set_evfilter_task_mode(int ctr, unsigned int is_slv)
{
u32 filter_reg = (ctr * 16) + IA_L2PMXEVFILTER_BASE;
u32 filter_val = l2_orig_filter_prefix | 1 << smp_processor_id();
+ if (is_slv)
+ filter_val = l2_slv_filter_prefix;
+
set_l2_indirect_reg(filter_reg, filter_val);
}
-static void set_evfilter_sys_mode(int ctr)
+static void set_evfilter_sys_mode(int ctr, unsigned int is_slv)
{
u32 filter_reg = (ctr * 16) + IA_L2PMXEVFILTER_BASE;
u32 filter_val = l2_orig_filter_prefix | 0xf;
+ if (is_slv)
+ filter_val = l2_slv_filter_prefix;
+
set_l2_indirect_reg(filter_reg, filter_val);
}
@@ -212,12 +269,21 @@
{
struct event_desc evdesc;
unsigned long iflags;
+ unsigned int is_slv = 0;
+ unsigned int evt_prefix;
raw_spin_lock_irqsave(&krait_l2_pmu_hw_events.pmu_lock, iflags);
if (hwc->config_base == L2CYCLE_CTR_RAW_CODE)
goto out;
+ /* Check if user requested any special origin filtering. */
+ evt_prefix = (hwc->config_base &
+ EVENT_PREFIX_MASK) >> EVENT_PREFIX_SHIFT;
+
+ if (evt_prefix == L2_SLAVE_EV_PREFIX)
+ is_slv = 1;
+
set_evcntcr(idx);
memset(&evdesc, 0, sizeof(evdesc));
@@ -230,9 +296,9 @@
evdesc.event_group_code);
if (cpu < 0)
- set_evfilter_task_mode(idx);
+ set_evfilter_task_mode(idx, is_slv);
else
- set_evfilter_sys_mode(idx);
+ set_evfilter_sys_mode(idx, is_slv);
out:
enable_intenset(idx);
@@ -358,7 +424,7 @@
static int krait_l2_map_event(struct perf_event *event)
{
if (pmu_type > 0 && pmu_type == event->attr.type)
- return event->attr.config & 0xfffff;
+ return event->attr.config & L2_EVT_MASK;
else
return -ENOENT;
}
@@ -378,6 +444,50 @@
free_irq(irq, NULL);
}
+static int msm_l2_test_set_ev_constraint(struct perf_event *event)
+{
+ u32 evt_type = event->attr.config & L2_EVT_MASK;
+ u8 reg = (evt_type & 0x0F000) >> 12;
+ u8 group = evt_type & 0x0000F;
+ unsigned long flags;
+ u32 err = 0;
+ u64 bitmap_t;
+
+ raw_spin_lock_irqsave(&l2_pmu_constraints.lock, flags);
+
+ bitmap_t = 1 << ((reg * 4) + group);
+
+ if (!(l2_pmu_constraints.pmu_bitmap & bitmap_t)) {
+ l2_pmu_constraints.pmu_bitmap |= bitmap_t;
+ goto out;
+ }
+
+ /* Bit is already set. Constraint failed. */
+ err = -EPERM;
+out:
+ raw_spin_unlock_irqrestore(&l2_pmu_constraints.lock, flags);
+ return err;
+}
+
+static int msm_l2_clear_ev_constraint(struct perf_event *event)
+{
+ u32 evt_type = event->attr.config & L2_EVT_MASK;
+ u8 reg = (evt_type & 0x0F000) >> 12;
+ u8 group = evt_type & 0x0000F;
+ unsigned long flags;
+ u64 bitmap_t;
+
+ raw_spin_lock_irqsave(&l2_pmu_constraints.lock, flags);
+
+ bitmap_t = 1 << ((reg * 4) + group);
+
+ /* Clear constraint bit. */
+ l2_pmu_constraints.pmu_bitmap &= ~bitmap_t;
+
+ raw_spin_unlock_irqrestore(&l2_pmu_constraints.lock, flags);
+ return 1;
+}
+
static struct arm_pmu krait_l2_pmu = {
.id = ARM_PERF_PMU_ID_KRAIT_L2,
.type = ARM_PMU_DEVICE_L2CC,
@@ -393,16 +503,19 @@
.read_counter = krait_l2_read_counter,
.write_counter = krait_l2_write_counter,
.map_event = krait_l2_map_event,
- .max_period = (1LLU << 32) - 1,
+ .max_period = MAX_L2_PERIOD,
.get_hw_events = krait_l2_get_hw_events,
.num_events = MAX_KRAIT_L2_CTRS,
+ .test_set_event_constraints = msm_l2_test_set_ev_constraint,
+ .clear_event_constraints = msm_l2_clear_ev_constraint,
+ .pmu.attr_groups = msm_l2_pmu_attr_grps,
};
static int __devinit krait_l2_pmu_device_probe(struct platform_device *pdev)
{
krait_l2_pmu.plat_device = pdev;
- if (!armpmu_register(&krait_l2_pmu, "krait-l2", -1))
+ if (!armpmu_register(&krait_l2_pmu, "kraitl2", -1))
pmu_type = krait_l2_pmu.pmu.type;
return 0;
diff --git a/arch/arm/mach-msm/perf_event_msm_l2.c b/arch/arm/mach-msm/perf_event_msm_l2.c
index 3310d92..5a5bf57 100644
--- a/arch/arm/mach-msm/perf_event_msm_l2.c
+++ b/arch/arm/mach-msm/perf_event_msm_l2.c
@@ -13,6 +13,7 @@
#include <linux/irq.h>
#include <asm/pmu.h>
#include <linux/platform_device.h>
+#include <linux/spinlock.h>
#define MAX_SCORPION_L2_CTRS 5
@@ -23,10 +24,61 @@
#define SCORPION_L2_EVT_PREFIX 3
#define SCORPION_MAX_L2_REG 4
+#define L2_EVT_MASK 0xfffff
+#define L2_EVT_PREFIX_MASK 0xf0000
+#define L2_EVT_PREFIX_SHIFT 16
+#define L2_SLAVE_EVT_PREFIX 4
+
+
+/*
+ * The L2 PMU is shared between all CPU's, so protect
+ * its bitmap access.
+ */
+struct pmu_constraints {
+ u64 pmu_bitmap;
+ raw_spinlock_t lock;
+} l2_pmu_constraints = {
+ .pmu_bitmap = 0,
+ .lock = __RAW_SPIN_LOCK_UNLOCKED(l2_pmu_constraints.lock),
+};
+
+/* NRCCG format for perf RAW codes. */
+PMU_FORMAT_ATTR(l2_prefix, "config:16-19");
+PMU_FORMAT_ATTR(l2_reg, "config:12-15");
+PMU_FORMAT_ATTR(l2_code, "config:4-11");
+PMU_FORMAT_ATTR(l2_grp, "config:0-3");
+
+static struct attribute *msm_l2_ev_formats[] = {
+ &format_attr_l2_prefix.attr,
+ &format_attr_l2_reg.attr,
+ &format_attr_l2_code.attr,
+ &format_attr_l2_grp.attr,
+ NULL,
+};
+
+/*
+ * Format group is essential to access PMU's from userspace
+ * via their .name field.
+ */
+static struct attribute_group msm_l2_pmu_format_group = {
+ .name = "format",
+ .attrs = msm_l2_ev_formats,
+};
+
+static const struct attribute_group *msm_l2_pmu_attr_grps[] = {
+ &msm_l2_pmu_format_group,
+ NULL,
+};
+
static u32 pmu_type;
static struct arm_pmu scorpion_l2_pmu;
+static u32 l2_orig_filter_prefix = 0x000f0030;
+
+/* L2 slave port traffic filtering */
+static u32 l2_slv_filter_prefix = 0x000f0010;
+
static struct perf_event *l2_events[MAX_SCORPION_L2_CTRS];
static unsigned long l2_used_mask[BITS_TO_LONGS(MAX_SCORPION_L2_CTRS)];
@@ -376,7 +428,8 @@
u8 group;
prefix = (evt_type & 0xF0000) >> 16;
- if (prefix == SCORPION_L2_EVT_PREFIX) {
+ if (prefix == SCORPION_L2_EVT_PREFIX ||
+ prefix == L2_SLAVE_EVT_PREFIX) {
reg = (evt_type & 0x0F000) >> 12;
code = (evt_type & 0x00FF0) >> 4;
group = evt_type & 0x0000F;
@@ -433,16 +486,22 @@
asm volatile ("mcr p15, 3, %0, c15, c6, 7" : : "r" (val));
}
-static void scorpion_l2_set_evfilter_task_mode(void)
+static void scorpion_l2_set_evfilter_task_mode(unsigned int is_slv)
{
- u32 filter_val = 0x000f0030 | 1 << smp_processor_id();
+ u32 filter_val = l2_orig_filter_prefix | 1 << smp_processor_id();
+
+ if (is_slv)
+ filter_val = l2_slv_filter_prefix;
asm volatile ("mcr p15, 3, %0, c15, c6, 3" : : "r" (filter_val));
}
-static void scorpion_l2_set_evfilter_sys_mode(void)
+static void scorpion_l2_set_evfilter_sys_mode(unsigned int is_slv)
{
- u32 filter_val = 0x000f003f;
+ u32 filter_val = l2_orig_filter_prefix | 0xf;
+
+ if (is_slv)
+ filter_val = l2_slv_filter_prefix;
asm volatile ("mcr p15, 3, %0, c15, c6, 3" : : "r" (filter_val));
}
@@ -542,12 +601,21 @@
int evtype = hwc->config_base;
int ev_typer;
unsigned long iflags;
+ unsigned int is_slv = 0;
+ unsigned int evt_prefix;
raw_spin_lock_irqsave(&scorpion_l2_pmu_hw_events.pmu_lock, iflags);
if (hwc->config_base == SCORPION_L2CYCLE_CTR_RAW_CODE)
goto out;
+ /* Check if user requested any special origin filtering. */
+ evt_prefix = (hwc->config_base &
+ L2_EVT_PREFIX_MASK) >> L2_EVT_PREFIX_SHIFT;
+
+ if (evt_prefix == L2_SLAVE_EVT_PREFIX)
+ is_slv = 1;
+
memset(&evtinfo, 0, sizeof(evtinfo));
ev_typer = get_scorpion_l2_evtinfo(evtype, &evtinfo);
@@ -557,9 +625,9 @@
scorpion_l2_set_evcntcr();
if (cpu < 0)
- scorpion_l2_set_evfilter_task_mode();
+ scorpion_l2_set_evfilter_task_mode(is_slv);
else
- scorpion_l2_set_evfilter_sys_mode();
+ scorpion_l2_set_evfilter_sys_mode(is_slv);
scorpion_l2_evt_setup(evtinfo.grp, evtinfo.val);
@@ -693,7 +761,7 @@
static int scorpion_l2_map_event(struct perf_event *event)
{
if (pmu_type > 0 && pmu_type == event->attr.type)
- return event->attr.config & 0xfffff;
+ return event->attr.config & L2_EVT_MASK;
else
return -ENOENT;
}
@@ -713,6 +781,59 @@
free_irq(irq, NULL);
}
+static int msm_l2_test_set_ev_constraint(struct perf_event *event)
+{
+ u32 evt_type = event->attr.config & L2_EVT_MASK;
+ u8 prefix = (evt_type & 0xF0000) >> 16;
+ u8 reg = (evt_type & 0x0F000) >> 12;
+ u8 group = evt_type & 0x0000F;
+ unsigned long flags;
+ u32 err = 0;
+ u64 bitmap_t;
+
+ if (!prefix)
+ return 0;
+
+ raw_spin_lock_irqsave(&l2_pmu_constraints.lock, flags);
+
+ bitmap_t = 1 << ((reg * 4) + group);
+
+ if (!(l2_pmu_constraints.pmu_bitmap & bitmap_t)) {
+ l2_pmu_constraints.pmu_bitmap |= bitmap_t;
+ goto out;
+ }
+
+ /* Bit is already set. Constraint failed. */
+ err = -EPERM;
+
+out:
+ raw_spin_unlock_irqrestore(&l2_pmu_constraints.lock, flags);
+ return err;
+}
+
+static int msm_l2_clear_ev_constraint(struct perf_event *event)
+{
+ u32 evt_type = event->attr.config & L2_EVT_MASK;
+ u8 prefix = (evt_type & 0xF0000) >> 16;
+ u8 reg = (evt_type & 0x0F000) >> 12;
+ u8 group = evt_type & 0x0000F;
+ unsigned long flags;
+ u64 bitmap_t;
+
+ if (!prefix)
+ return 0;
+
+ raw_spin_lock_irqsave(&l2_pmu_constraints.lock, flags);
+
+ bitmap_t = 1 << ((reg * 4) + group);
+
+ /* Clear constraint bit. */
+ l2_pmu_constraints.pmu_bitmap &= ~bitmap_t;
+
+ raw_spin_unlock_irqrestore(&l2_pmu_constraints.lock, flags);
+ return 1;
+}
+
static struct arm_pmu scorpion_l2_pmu = {
.id = ARM_PERF_PMU_ID_SCORPIONMP_L2,
.type = ARM_PMU_DEVICE_L2CC,
@@ -731,13 +852,16 @@
.max_period = (1LLU << 32) - 1,
.get_hw_events = scorpion_l2_get_hw_events,
.num_events = MAX_SCORPION_L2_CTRS,
+ .test_set_event_constraints = msm_l2_test_set_ev_constraint,
+ .clear_event_constraints = msm_l2_clear_ev_constraint,
+ .pmu.attr_groups = msm_l2_pmu_attr_grps,
};
static int __devinit scorpion_l2_pmu_device_probe(struct platform_device *pdev)
{
scorpion_l2_pmu.plat_device = pdev;
- if (!armpmu_register(&scorpion_l2_pmu, "scorpion-l2", -1))
+ if (!armpmu_register(&scorpion_l2_pmu, "scorpionl2", -1))
pmu_type = scorpion_l2_pmu.pmu.type;
return 0;
diff --git a/arch/arm/mach-msm/qdsp5v2/audio_lpa.c b/arch/arm/mach-msm/qdsp5v2/audio_lpa.c
index d5fb2e9..60f43b9 100644
--- a/arch/arm/mach-msm/qdsp5v2/audio_lpa.c
+++ b/arch/arm/mach-msm/qdsp5v2/audio_lpa.c
@@ -34,6 +34,7 @@
#include <linux/slab.h>
#include <linux/msm_audio.h>
#include <mach/qdsp5v2/audio_dev_ctl.h>
+#include <linux/memory_alloc.h>
#include <mach/qdsp5v2/qdsp5audppmsg.h>
#include <mach/qdsp5v2/qdsp5audplaycmdi.h>
@@ -1410,7 +1411,7 @@
wake_up(&audio->event_wait);
audlpa_reset_event_queue(audio);
iounmap(audio->data);
- pmem_kfree(audio->phys);
+ free_contiguous_memory_by_paddr(audio->phys);
mutex_unlock(&audio->lock);
#ifdef CONFIG_DEBUG_FS
if (audio->dentry)
@@ -1655,7 +1656,7 @@
msm_adsp_put(audio->audplay);
err:
iounmap(audio->data);
- pmem_kfree(audio->phys);
+ free_contiguous_memory_by_paddr(audio->phys);
audpp_adec_free(audio->dec_id);
MM_INFO("audio instance 0x%08x freeing\n", (int)audio);
kfree(audio);
diff --git a/arch/arm/mach-msm/qdsp5v2/audio_mvs.c b/arch/arm/mach-msm/qdsp5v2/audio_mvs.c
index 99da836..1884b3c 100644
--- a/arch/arm/mach-msm/qdsp5v2/audio_mvs.c
+++ b/arch/arm/mach-msm/qdsp5v2/audio_mvs.c
@@ -304,6 +304,7 @@
uint32_t buf_free_cnt;
uint32_t rate_type;
uint32_t dtx_mode;
+ struct min_max_rate min_max_rate;
struct msm_rpc_endpoint *rpc_endpt;
uint32_t rpc_prog;
@@ -416,8 +417,10 @@
/* Set EVRC mode. */
memset(&set_voc_mode_msg, 0, sizeof(set_voc_mode_msg));
- set_voc_mode_msg.min_rate = cpu_to_be32(audio->rate_type);
- set_voc_mode_msg.max_rate = cpu_to_be32(audio->rate_type);
+ set_voc_mode_msg.min_rate =
+ cpu_to_be32(audio->min_max_rate.min_rate);
+ set_voc_mode_msg.max_rate =
+ cpu_to_be32(audio->min_max_rate.max_rate);
msm_rpc_setup_req(&set_voc_mode_msg.rpc_hdr,
audio->rpc_prog,
@@ -1555,6 +1558,8 @@
mutex_lock(&audio->lock);
config.mvs_mode = audio->mvs_mode;
config.rate_type = audio->rate_type;
+ config.min_max_rate.min_rate = audio->min_max_rate.min_rate;
+ config.min_max_rate.max_rate = audio->min_max_rate.max_rate;
mutex_unlock(&audio->lock);
rc = copy_to_user((void *)arg, &config, sizeof(config));
@@ -1579,6 +1584,10 @@
audio->mvs_mode = config.mvs_mode;
audio->rate_type = config.rate_type;
audio->dtx_mode = config.dtx_mode;
+ audio->min_max_rate.min_rate =
+ config.min_max_rate.min_rate;
+ audio->min_max_rate.max_rate =
+ config.min_max_rate.max_rate;
} else {
pr_err("%s: Set confg called in state %d\n",
__func__, audio->state);
diff --git a/arch/arm/mach-msm/qdss-etb.c b/arch/arm/mach-msm/qdss-etb.c
deleted file mode 100644
index ccea2fa..0000000
--- a/arch/arm/mach-msm/qdss-etb.c
+++ /dev/null
@@ -1,419 +0,0 @@
-/* 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
- * only version 2 as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- */
-
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/init.h>
-#include <linux/types.h>
-#include <linux/device.h>
-#include <linux/platform_device.h>
-#include <linux/io.h>
-#include <linux/err.h>
-#include <linux/fs.h>
-#include <linux/miscdevice.h>
-#include <linux/uaccess.h>
-#include <linux/slab.h>
-#include <linux/delay.h>
-#include <linux/mutex.h>
-
-#include "qdss-priv.h"
-
-#define etb_writel(etb, val, off) __raw_writel((val), etb.base + off)
-#define etb_readl(etb, off) __raw_readl(etb.base + off)
-
-#define ETB_RAM_DEPTH_REG (0x004)
-#define ETB_STATUS_REG (0x00C)
-#define ETB_RAM_READ_DATA_REG (0x010)
-#define ETB_RAM_READ_POINTER (0x014)
-#define ETB_RAM_WRITE_POINTER (0x018)
-#define ETB_TRG (0x01C)
-#define ETB_CTL_REG (0x020)
-#define ETB_RWD_REG (0x024)
-#define ETB_FFSR (0x300)
-#define ETB_FFCR (0x304)
-#define ETB_ITMISCOP0 (0xEE0)
-#define ETB_ITTRFLINACK (0xEE4)
-#define ETB_ITTRFLIN (0xEE8)
-#define ETB_ITATBDATA0 (0xEEC)
-#define ETB_ITATBCTR2 (0xEF0)
-#define ETB_ITATBCTR1 (0xEF4)
-#define ETB_ITATBCTR0 (0xEF8)
-
-
-#define BYTES_PER_WORD 4
-#define ETB_SIZE_WORDS 4096
-#define FRAME_SIZE_WORDS 4
-
-#define ETB_LOCK() \
-do { \
- mb(); \
- etb_writel(etb, 0x0, CS_LAR); \
-} while (0)
-#define ETB_UNLOCK() \
-do { \
- etb_writel(etb, CS_UNLOCK_MAGIC, CS_LAR); \
- mb(); \
-} while (0)
-
-struct etb_ctx {
- uint8_t *buf;
- void __iomem *base;
- bool enabled;
- bool reading;
- spinlock_t spinlock;
- atomic_t in_use;
- struct device *dev;
- struct kobject *kobj;
- uint32_t trigger_cntr;
-};
-
-static struct etb_ctx etb;
-
-static void __etb_enable(void)
-{
- int i;
-
- ETB_UNLOCK();
-
- etb_writel(etb, 0x0, ETB_RAM_WRITE_POINTER);
- for (i = 0; i < ETB_SIZE_WORDS; i++)
- etb_writel(etb, 0x0, ETB_RWD_REG);
-
- etb_writel(etb, 0x0, ETB_RAM_WRITE_POINTER);
- etb_writel(etb, 0x0, ETB_RAM_READ_POINTER);
-
- etb_writel(etb, etb.trigger_cntr, ETB_TRG);
- etb_writel(etb, BIT(13) | BIT(0), ETB_FFCR);
- etb_writel(etb, BIT(0), ETB_CTL_REG);
-
- ETB_LOCK();
-}
-
-void etb_enable(void)
-{
- unsigned long flags;
-
- spin_lock_irqsave(&etb.spinlock, flags);
- __etb_enable();
- etb.enabled = true;
- dev_info(etb.dev, "ETB enabled\n");
- spin_unlock_irqrestore(&etb.spinlock, flags);
-}
-
-static void __etb_disable(void)
-{
- int count;
- uint32_t ffcr;
-
- ETB_UNLOCK();
-
- ffcr = etb_readl(etb, ETB_FFCR);
- ffcr |= (BIT(12) | BIT(6));
- etb_writel(etb, ffcr, ETB_FFCR);
-
- for (count = TIMEOUT_US; BVAL(etb_readl(etb, ETB_FFCR), 6) != 0
- && count > 0; count--)
- udelay(1);
- WARN(count == 0, "timeout while flushing ETB, ETB_FFCR: %#x\n",
- etb_readl(etb, ETB_FFCR));
-
- etb_writel(etb, 0x0, ETB_CTL_REG);
-
- for (count = TIMEOUT_US; BVAL(etb_readl(etb, ETB_FFSR), 1) != 1
- && count > 0; count--)
- udelay(1);
- WARN(count == 0, "timeout while disabling ETB, ETB_FFSR: %#x\n",
- etb_readl(etb, ETB_FFSR));
-
- ETB_LOCK();
-}
-
-void etb_disable(void)
-{
- unsigned long flags;
-
- spin_lock_irqsave(&etb.spinlock, flags);
- __etb_disable();
- etb.enabled = false;
- dev_info(etb.dev, "ETB disabled\n");
- spin_unlock_irqrestore(&etb.spinlock, flags);
-}
-
-static void __etb_dump(void)
-{
- int i;
- uint8_t *buf_ptr;
- uint32_t read_data;
- uint32_t read_ptr;
- uint32_t write_ptr;
- uint32_t frame_off;
- uint32_t frame_endoff;
-
- ETB_UNLOCK();
-
- read_ptr = etb_readl(etb, ETB_RAM_READ_POINTER);
- write_ptr = etb_readl(etb, ETB_RAM_WRITE_POINTER);
-
- frame_off = write_ptr % FRAME_SIZE_WORDS;
- frame_endoff = FRAME_SIZE_WORDS - frame_off;
- if (frame_off) {
- dev_err(etb.dev, "write_ptr: %lu not aligned to formatter "
- "frame size\n", (unsigned long)write_ptr);
- dev_err(etb.dev, "frameoff: %lu, frame_endoff: %lu\n",
- (unsigned long)frame_off, (unsigned long)frame_endoff);
- write_ptr += frame_endoff;
- }
-
- if ((etb_readl(etb, ETB_STATUS_REG) & BIT(0)) == 0)
- etb_writel(etb, 0x0, ETB_RAM_READ_POINTER);
- else
- etb_writel(etb, write_ptr, ETB_RAM_READ_POINTER);
-
- buf_ptr = etb.buf;
- for (i = 0; i < ETB_SIZE_WORDS; i++) {
- read_data = etb_readl(etb, ETB_RAM_READ_DATA_REG);
- *buf_ptr++ = read_data >> 0;
- *buf_ptr++ = read_data >> 8;
- *buf_ptr++ = read_data >> 16;
- *buf_ptr++ = read_data >> 24;
- }
-
- if (frame_off) {
- buf_ptr -= (frame_endoff * BYTES_PER_WORD);
- for (i = 0; i < frame_endoff; i++) {
- *buf_ptr++ = 0x0;
- *buf_ptr++ = 0x0;
- *buf_ptr++ = 0x0;
- *buf_ptr++ = 0x0;
- }
- }
-
- etb_writel(etb, read_ptr, ETB_RAM_READ_POINTER);
-
- ETB_LOCK();
-}
-
-void etb_dump(void)
-{
- unsigned long flags;
-
- spin_lock_irqsave(&etb.spinlock, flags);
- if (etb.enabled) {
- __etb_disable();
- __etb_dump();
- __etb_enable();
-
- dev_info(etb.dev, "ETB dumped\n");
- }
- spin_unlock_irqrestore(&etb.spinlock, flags);
-}
-
-static int etb_open(struct inode *inode, struct file *file)
-{
- if (atomic_cmpxchg(&etb.in_use, 0, 1))
- return -EBUSY;
-
- dev_dbg(etb.dev, "%s: successfully opened\n", __func__);
- return 0;
-}
-
-static ssize_t etb_read(struct file *file, char __user *data,
- size_t len, loff_t *ppos)
-{
- if (etb.reading == false) {
- etb_dump();
- etb.reading = true;
- }
-
- if (*ppos + len > ETB_SIZE_WORDS * BYTES_PER_WORD)
- len = ETB_SIZE_WORDS * BYTES_PER_WORD - *ppos;
-
- if (copy_to_user(data, etb.buf + *ppos, len)) {
- dev_dbg(etb.dev, "%s: copy_to_user failed\n", __func__);
- return -EFAULT;
- }
-
- *ppos += len;
-
- dev_dbg(etb.dev, "%s: %d bytes copied, %d bytes left\n",
- __func__, len, (int) (ETB_SIZE_WORDS * BYTES_PER_WORD - *ppos));
-
- return len;
-}
-
-static int etb_release(struct inode *inode, struct file *file)
-{
- etb.reading = false;
-
- atomic_set(&etb.in_use, 0);
-
- dev_dbg(etb.dev, "%s: released\n", __func__);
-
- return 0;
-}
-
-static const struct file_operations etb_fops = {
- .owner = THIS_MODULE,
- .open = etb_open,
- .read = etb_read,
- .release = etb_release,
-};
-
-static struct miscdevice etb_misc = {
- .name = "msm_etb",
- .minor = MISC_DYNAMIC_MINOR,
- .fops = &etb_fops,
-};
-
-#define ETB_ATTR(__name) \
-static struct kobj_attribute __name##_attr = \
- __ATTR(__name, S_IRUGO | S_IWUSR, __name##_show, __name##_store)
-
-static ssize_t trigger_cntr_store(struct kobject *kobj,
- struct kobj_attribute *attr,
- const char *buf, size_t n)
-{
- unsigned long val;
-
- if (sscanf(buf, "%lx", &val) != 1)
- return -EINVAL;
-
- etb.trigger_cntr = val;
- return n;
-}
-static ssize_t trigger_cntr_show(struct kobject *kobj,
- struct kobj_attribute *attr,
- char *buf)
-{
- unsigned long val = etb.trigger_cntr;
- return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
-}
-ETB_ATTR(trigger_cntr);
-
-static int __devinit etb_sysfs_init(void)
-{
- int ret;
-
- etb.kobj = kobject_create_and_add("etb", qdss_get_modulekobj());
- if (!etb.kobj) {
- dev_err(etb.dev, "failed to create ETB sysfs kobject\n");
- ret = -ENOMEM;
- goto err_create;
- }
-
- ret = sysfs_create_file(etb.kobj, &trigger_cntr_attr.attr);
- if (ret) {
- dev_err(etb.dev, "failed to create ETB sysfs trigger_cntr"
- " attribute\n");
- goto err_file;
- }
-
- return 0;
-err_file:
- kobject_put(etb.kobj);
-err_create:
- return ret;
-}
-
-static void __devexit etb_sysfs_exit(void)
-{
- sysfs_remove_file(etb.kobj, &trigger_cntr_attr.attr);
- kobject_put(etb.kobj);
-}
-
-static int __devinit etb_probe(struct platform_device *pdev)
-{
- int ret;
- struct resource *res;
-
- res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
- if (!res) {
- ret = -EINVAL;
- goto err_res;
- }
-
- etb.base = ioremap_nocache(res->start, resource_size(res));
- if (!etb.base) {
- ret = -EINVAL;
- goto err_ioremap;
- }
-
- etb.dev = &pdev->dev;
-
- spin_lock_init(&etb.spinlock);
-
- ret = misc_register(&etb_misc);
- if (ret)
- goto err_misc;
-
- etb.buf = kzalloc(ETB_SIZE_WORDS * BYTES_PER_WORD, GFP_KERNEL);
- if (!etb.buf) {
- ret = -ENOMEM;
- goto err_alloc;
- }
-
- etb_sysfs_init();
-
- dev_info(etb.dev, "ETB initialized\n");
- return 0;
-
-err_alloc:
- misc_deregister(&etb_misc);
-err_misc:
- iounmap(etb.base);
-err_ioremap:
-err_res:
- dev_err(etb.dev, "ETB init failed\n");
- return ret;
-}
-
-static int __devexit etb_remove(struct platform_device *pdev)
-{
- if (etb.enabled)
- etb_disable();
- etb_sysfs_exit();
- kfree(etb.buf);
- misc_deregister(&etb_misc);
- iounmap(etb.base);
-
- return 0;
-}
-
-static struct of_device_id etb_match[] = {
- {.compatible = "qcom,msm-etb"},
- {}
-};
-
-static struct platform_driver etb_driver = {
- .probe = etb_probe,
- .remove = __devexit_p(etb_remove),
- .driver = {
- .name = "msm_etb",
- .owner = THIS_MODULE,
- .of_match_table = etb_match,
- },
-};
-
-static int __init etb_init(void)
-{
- return platform_driver_register(&etb_driver);
-}
-module_init(etb_init);
-
-static void __exit etb_exit(void)
-{
- platform_driver_unregister(&etb_driver);
-}
-module_exit(etb_exit);
-
-MODULE_LICENSE("GPL v2");
-MODULE_DESCRIPTION("CoreSight Embedded Trace Buffer driver");
diff --git a/arch/arm/mach-msm/qdss-etm.c b/arch/arm/mach-msm/qdss-etm.c
deleted file mode 100644
index e2a38de..0000000
--- a/arch/arm/mach-msm/qdss-etm.c
+++ /dev/null
@@ -1,1336 +0,0 @@
-/* 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
- * only version 2 as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- */
-
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/init.h>
-#include <linux/types.h>
-#include <linux/device.h>
-#include <linux/platform_device.h>
-#include <linux/io.h>
-#include <linux/err.h>
-#include <linux/fs.h>
-#include <linux/slab.h>
-#include <linux/delay.h>
-#include <linux/smp.h>
-#include <linux/wakelock.h>
-#include <linux/pm_qos.h>
-#include <linux/sysfs.h>
-#include <linux/stat.h>
-#include <asm/sections.h>
-#include <mach/socinfo.h>
-
-#include "qdss-priv.h"
-
-#define etm_writel(etm, cpu, val, off) \
- __raw_writel((val), etm.base + (SZ_4K * cpu) + off)
-#define etm_readl(etm, cpu, off) \
- __raw_readl(etm.base + (SZ_4K * cpu) + off)
-
-/*
- * Device registers:
- * 0x000 - 0x2FC: Trace registers
- * 0x300 - 0x314: Management registers
- * 0x318 - 0xEFC: Trace registers
- *
- * Coresight registers
- * 0xF00 - 0xF9C: Management registers
- * 0xFA0 - 0xFA4: Management registers in PFTv1.0
- * Trace registers in PFTv1.1
- * 0xFA8 - 0xFFC: Management registers
- */
-
-/* Trace registers (0x000-0x2FC) */
-#define ETMCR (0x000)
-#define ETMCCR (0x004)
-#define ETMTRIGGER (0x008)
-#define ETMSR (0x010)
-#define ETMSCR (0x014)
-#define ETMTSSCR (0x018)
-#define ETMTEEVR (0x020)
-#define ETMTECR1 (0x024)
-#define ETMFFLR (0x02C)
-#define ETMACVRn(n) (0x040 + (n * 4))
-#define ETMACTRn(n) (0x080 + (n * 4))
-#define ETMCNTRLDVRn(n) (0x140 + (n * 4))
-#define ETMCNTENRn(n) (0x150 + (n * 4))
-#define ETMCNTRLDEVRn(n) (0x160 + (n * 4))
-#define ETMCNTVRn(n) (0x170 + (n * 4))
-#define ETMSQ12EVR (0x180)
-#define ETMSQ21EVR (0x184)
-#define ETMSQ23EVR (0x188)
-#define ETMSQ31EVR (0x18C)
-#define ETMSQ32EVR (0x190)
-#define ETMSQ13EVR (0x194)
-#define ETMSQR (0x19C)
-#define ETMEXTOUTEVRn(n) (0x1A0 + (n * 4))
-#define ETMCIDCVRn(n) (0x1B0 + (n * 4))
-#define ETMCIDCMR (0x1BC)
-#define ETMIMPSPEC0 (0x1C0)
-#define ETMIMPSPEC1 (0x1C4)
-#define ETMIMPSPEC2 (0x1C8)
-#define ETMIMPSPEC3 (0x1CC)
-#define ETMIMPSPEC4 (0x1D0)
-#define ETMIMPSPEC5 (0x1D4)
-#define ETMIMPSPEC6 (0x1D8)
-#define ETMIMPSPEC7 (0x1DC)
-#define ETMSYNCFR (0x1E0)
-#define ETMIDR (0x1E4)
-#define ETMCCER (0x1E8)
-#define ETMEXTINSELR (0x1EC)
-#define ETMTESSEICR (0x1F0)
-#define ETMEIBCR (0x1F4)
-#define ETMTSEVR (0x1F8)
-#define ETMAUXCR (0x1FC)
-#define ETMTRACEIDR (0x200)
-#define ETMVMIDCVR (0x240)
-/* Management registers (0x300-0x314) */
-#define ETMOSLAR (0x300)
-#define ETMOSLSR (0x304)
-#define ETMOSSRR (0x308)
-#define ETMPDCR (0x310)
-#define ETMPDSR (0x314)
-
-#define ETM_MAX_ADDR_CMP (16)
-#define ETM_MAX_CNTR (4)
-#define ETM_MAX_CTXID_CMP (3)
-
-#define ETM_MODE_EXCLUDE BIT(0)
-#define ETM_MODE_CYCACC BIT(1)
-#define ETM_MODE_STALL BIT(2)
-#define ETM_MODE_TIMESTAMP BIT(3)
-#define ETM_MODE_CTXID BIT(4)
-#define ETM_MODE_ALL (0x1F)
-
-#define ETM_EVENT_MASK (0x1FFFF)
-#define ETM_SYNC_MASK (0xFFF)
-#define ETM_ALL_MASK (0xFFFFFFFF)
-
-#define ETM_SEQ_STATE_MAX_VAL (0x2)
-
-enum {
- ETM_ADDR_TYPE_NONE,
- ETM_ADDR_TYPE_SINGLE,
- ETM_ADDR_TYPE_RANGE,
- ETM_ADDR_TYPE_START,
- ETM_ADDR_TYPE_STOP,
-};
-
-#define ETM_LOCK(cpu) \
-do { \
- mb(); \
- etm_writel(etm, cpu, 0x0, CS_LAR); \
-} while (0)
-#define ETM_UNLOCK(cpu) \
-do { \
- etm_writel(etm, cpu, CS_UNLOCK_MAGIC, CS_LAR); \
- mb(); \
-} while (0)
-
-
-#ifdef MODULE_PARAM_PREFIX
-#undef MODULE_PARAM_PREFIX
-#endif
-#define MODULE_PARAM_PREFIX "qdss."
-
-#ifdef CONFIG_MSM_QDSS_ETM_DEFAULT_ENABLE
-static int etm_boot_enable = 1;
-#else
-static int etm_boot_enable;
-#endif
-module_param_named(
- etm_boot_enable, etm_boot_enable, int, S_IRUGO
-);
-
-struct etm_ctx {
- void __iomem *base;
- bool enabled;
- struct wake_lock wake_lock;
- struct pm_qos_request qos_req;
- struct qdss_source *src;
- struct mutex mutex;
- struct device *dev;
- struct kobject *kobj;
- uint8_t arch;
- uint8_t nr_addr_cmp;
- uint8_t nr_cntr;
- uint8_t nr_ext_inp;
- uint8_t nr_ext_out;
- uint8_t nr_ctxid_cmp;
- uint8_t reset;
- uint32_t mode;
- uint32_t ctrl;
- uint32_t trigger_event;
- uint32_t startstop_ctrl;
- uint32_t enable_event;
- uint32_t enable_ctrl1;
- uint32_t fifofull_level;
- uint8_t addr_idx;
- uint32_t addr_val[ETM_MAX_ADDR_CMP];
- uint32_t addr_acctype[ETM_MAX_ADDR_CMP];
- uint32_t addr_type[ETM_MAX_ADDR_CMP];
- uint8_t cntr_idx;
- uint32_t cntr_rld_val[ETM_MAX_CNTR];
- uint32_t cntr_event[ETM_MAX_CNTR];
- uint32_t cntr_rld_event[ETM_MAX_CNTR];
- uint32_t cntr_val[ETM_MAX_CNTR];
- uint32_t seq_12_event;
- uint32_t seq_21_event;
- uint32_t seq_23_event;
- uint32_t seq_31_event;
- uint32_t seq_32_event;
- uint32_t seq_13_event;
- uint32_t seq_curr_state;
- uint8_t ctxid_idx;
- uint32_t ctxid_val[ETM_MAX_CTXID_CMP];
- uint32_t ctxid_mask;
- uint32_t sync_freq;
- uint32_t timestamp_event;
-};
-
-static struct etm_ctx etm = {
- .trigger_event = 0x406F,
- .enable_event = 0x6F,
- .enable_ctrl1 = 0x1,
- .fifofull_level = 0x28,
- .addr_val = {(uint32_t) _stext, (uint32_t) _etext},
- .addr_type = {ETM_ADDR_TYPE_RANGE, ETM_ADDR_TYPE_RANGE},
- .cntr_event = {[0 ... (ETM_MAX_CNTR - 1)] = 0x406F},
- .cntr_rld_event = {[0 ... (ETM_MAX_CNTR - 1)] = 0x406F},
- .seq_12_event = 0x406F,
- .seq_21_event = 0x406F,
- .seq_23_event = 0x406F,
- .seq_31_event = 0x406F,
- .seq_32_event = 0x406F,
- .seq_13_event = 0x406F,
- .sync_freq = 0x80,
- .timestamp_event = 0x406F,
-};
-
-
-/* ETM clock is derived from the processor clock and gets enabled on a
- * logical OR of below items on Krait (pass2 onwards):
- * 1.CPMR[ETMCLKEN] is 1
- * 2.ETMCR[PD] is 0
- * 3.ETMPDCR[PU] is 1
- * 4.Reset is asserted (core or debug)
- * 5.APB memory mapped requests (eg. EDAP access)
- *
- * 1., 2. and 3. above are permanent enables whereas 4. and 5. are temporary
- * enables
- *
- * We rely on 5. to be able to access ETMCR and then use 2. above for ETM
- * clock vote in the driver and the save-restore code uses 1. above
- * for its vote
- */
-static void etm_set_pwrdwn(int cpu)
-{
- uint32_t etmcr;
-
- etmcr = etm_readl(etm, cpu, ETMCR);
- etmcr |= BIT(0);
- etm_writel(etm, cpu, etmcr, ETMCR);
-}
-
-static void etm_clr_pwrdwn(int cpu)
-{
- uint32_t etmcr;
-
- etmcr = etm_readl(etm, cpu, ETMCR);
- etmcr &= ~BIT(0);
- etm_writel(etm, cpu, etmcr, ETMCR);
-}
-
-static void etm_set_prog(int cpu)
-{
- uint32_t etmcr;
- int count;
-
- etmcr = etm_readl(etm, cpu, ETMCR);
- etmcr |= BIT(10);
- etm_writel(etm, cpu, etmcr, ETMCR);
-
- for (count = TIMEOUT_US; BVAL(etm_readl(etm, cpu, ETMSR), 1) != 1
- && count > 0; count--)
- udelay(1);
- WARN(count == 0, "timeout while setting prog bit, ETMSR: %#x\n",
- etm_readl(etm, cpu, ETMSR));
-}
-
-static void etm_clr_prog(int cpu)
-{
- uint32_t etmcr;
- int count;
-
- etmcr = etm_readl(etm, cpu, ETMCR);
- etmcr &= ~BIT(10);
- etm_writel(etm, cpu, etmcr, ETMCR);
-
- for (count = TIMEOUT_US; BVAL(etm_readl(etm, cpu, ETMSR), 1) != 0
- && count > 0; count--)
- udelay(1);
- WARN(count == 0, "timeout while clearing prog bit, ETMSR: %#x\n",
- etm_readl(etm, cpu, ETMSR));
-}
-
-static void __etm_enable(int cpu)
-{
- int i;
-
- ETM_UNLOCK(cpu);
- /* Vote for ETM power/clock enable */
- etm_clr_pwrdwn(cpu);
- etm_set_prog(cpu);
-
- etm_writel(etm, cpu, etm.ctrl | BIT(10), ETMCR);
- etm_writel(etm, cpu, etm.trigger_event, ETMTRIGGER);
- etm_writel(etm, cpu, etm.startstop_ctrl, ETMTSSCR);
- etm_writel(etm, cpu, etm.enable_event, ETMTEEVR);
- etm_writel(etm, cpu, etm.enable_ctrl1, ETMTECR1);
- etm_writel(etm, cpu, etm.fifofull_level, ETMFFLR);
- for (i = 0; i < etm.nr_addr_cmp; i++) {
- etm_writel(etm, cpu, etm.addr_val[i], ETMACVRn(i));
- etm_writel(etm, cpu, etm.addr_acctype[i], ETMACTRn(i));
- }
- for (i = 0; i < etm.nr_cntr; i++) {
- etm_writel(etm, cpu, etm.cntr_rld_val[i], ETMCNTRLDVRn(i));
- etm_writel(etm, cpu, etm.cntr_event[i], ETMCNTENRn(i));
- etm_writel(etm, cpu, etm.cntr_rld_event[i], ETMCNTRLDEVRn(i));
- etm_writel(etm, cpu, etm.cntr_val[i], ETMCNTVRn(i));
- }
- etm_writel(etm, cpu, etm.seq_12_event, ETMSQ12EVR);
- etm_writel(etm, cpu, etm.seq_21_event, ETMSQ21EVR);
- etm_writel(etm, cpu, etm.seq_23_event, ETMSQ23EVR);
- etm_writel(etm, cpu, etm.seq_31_event, ETMSQ31EVR);
- etm_writel(etm, cpu, etm.seq_32_event, ETMSQ32EVR);
- etm_writel(etm, cpu, etm.seq_13_event, ETMSQ13EVR);
- etm_writel(etm, cpu, etm.seq_curr_state, ETMSQR);
- for (i = 0; i < etm.nr_ext_out; i++)
- etm_writel(etm, cpu, 0x0000406F, ETMEXTOUTEVRn(i));
- for (i = 0; i < etm.nr_ctxid_cmp; i++)
- etm_writel(etm, cpu, etm.ctxid_val[i], ETMCIDCVRn(i));
- etm_writel(etm, cpu, etm.ctxid_mask, ETMCIDCMR);
- etm_writel(etm, cpu, etm.sync_freq, ETMSYNCFR);
- etm_writel(etm, cpu, 0x00000000, ETMEXTINSELR);
- etm_writel(etm, cpu, etm.timestamp_event, ETMTSEVR);
- etm_writel(etm, cpu, 0x00000000, ETMAUXCR);
- etm_writel(etm, cpu, cpu+1, ETMTRACEIDR);
- etm_writel(etm, cpu, 0x00000000, ETMVMIDCVR);
-
- etm_clr_prog(cpu);
- ETM_LOCK(cpu);
-}
-
-static int etm_enable(void)
-{
- int ret, cpu;
-
- if (etm.enabled) {
- dev_err(etm.dev, "ETM tracing already enabled\n");
- ret = -EPERM;
- goto err;
- }
-
- wake_lock(&etm.wake_lock);
- /* 1. causes all online cpus to come out of idle PC
- * 2. prevents idle PC until save restore flag is enabled atomically
- *
- * we rely on the user to prevent hotplug on/off racing with this
- * operation and to ensure cores where trace is expected to be turned
- * on are already hotplugged on
- */
- pm_qos_update_request(&etm.qos_req, 0);
-
- ret = qdss_enable(etm.src);
- if (ret)
- goto err_qdss;
-
- for_each_online_cpu(cpu)
- __etm_enable(cpu);
-
- etm.enabled = true;
-
- pm_qos_update_request(&etm.qos_req, PM_QOS_DEFAULT_VALUE);
- wake_unlock(&etm.wake_lock);
-
- dev_info(etm.dev, "ETM tracing enabled\n");
- return 0;
-
-err_qdss:
- pm_qos_update_request(&etm.qos_req, PM_QOS_DEFAULT_VALUE);
- wake_unlock(&etm.wake_lock);
-err:
- return ret;
-}
-
-static void __etm_disable(int cpu)
-{
- ETM_UNLOCK(cpu);
- etm_set_prog(cpu);
-
- /* program trace enable to low by using always false event */
- etm_writel(etm, cpu, 0x6F | BIT(14), ETMTEEVR);
-
- /* Vote for ETM power/clock disable */
- etm_set_pwrdwn(cpu);
- ETM_LOCK(cpu);
-}
-
-static int etm_disable(void)
-{
- int ret, cpu;
-
- if (!etm.enabled) {
- dev_err(etm.dev, "ETM tracing already disabled\n");
- ret = -EPERM;
- goto err;
- }
-
- wake_lock(&etm.wake_lock);
- /* 1. causes all online cpus to come out of idle PC
- * 2. prevents idle PC until save restore flag is disabled atomically
- *
- * we rely on the user to prevent hotplug on/off racing with this
- * operation and to ensure cores where trace is expected to be turned
- * off are already hotplugged on
- */
- pm_qos_update_request(&etm.qos_req, 0);
-
- for_each_online_cpu(cpu)
- __etm_disable(cpu);
-
- qdss_disable(etm.src);
-
- etm.enabled = false;
-
- pm_qos_update_request(&etm.qos_req, PM_QOS_DEFAULT_VALUE);
- wake_unlock(&etm.wake_lock);
-
- dev_info(etm.dev, "ETM tracing disabled\n");
- return 0;
-err:
- return ret;
-}
-
-/* Memory mapped writes to clear os lock not supported */
-static void etm_os_unlock(void *unused)
-{
- unsigned long value = 0x0;
-
- asm("mcr p14, 1, %0, c1, c0, 4\n\t" : : "r" (value));
- asm("isb\n\t");
-}
-
-#define ETM_STORE(__name, mask) \
-static ssize_t __name##_store(struct kobject *kobj, \
- struct kobj_attribute *attr, \
- const char *buf, size_t n) \
-{ \
- unsigned long val; \
- \
- if (sscanf(buf, "%lx", &val) != 1) \
- return -EINVAL; \
- \
- etm.__name = val & mask; \
- return n; \
-}
-
-#define ETM_SHOW(__name) \
-static ssize_t __name##_show(struct kobject *kobj, \
- struct kobj_attribute *attr, \
- char *buf) \
-{ \
- unsigned long val = etm.__name; \
- return scnprintf(buf, PAGE_SIZE, "%#lx\n", val); \
-}
-
-#define ETM_ATTR(__name) \
-static struct kobj_attribute __name##_attr = \
- __ATTR(__name, S_IRUGO | S_IWUSR, __name##_show, __name##_store)
-#define ETM_ATTR_RO(__name) \
-static struct kobj_attribute __name##_attr = \
- __ATTR(__name, S_IRUGO, __name##_show, NULL)
-
-static ssize_t enabled_store(struct kobject *kobj,
- struct kobj_attribute *attr,
- const char *buf, size_t n)
-{
- int ret = 0;
- unsigned long val;
-
- if (sscanf(buf, "%lx", &val) != 1)
- return -EINVAL;
-
- mutex_lock(&etm.mutex);
- if (val)
- ret = etm_enable();
- else
- ret = etm_disable();
- mutex_unlock(&etm.mutex);
-
- if (ret)
- return ret;
- return n;
-}
-ETM_SHOW(enabled);
-ETM_ATTR(enabled);
-
-ETM_SHOW(nr_addr_cmp);
-ETM_ATTR_RO(nr_addr_cmp);
-ETM_SHOW(nr_cntr);
-ETM_ATTR_RO(nr_cntr);
-ETM_SHOW(nr_ctxid_cmp);
-ETM_ATTR_RO(nr_ctxid_cmp);
-
-/* Reset to trace everything i.e. exclude nothing. */
-static ssize_t reset_store(struct kobject *kobj,
- struct kobj_attribute *attr,
- const char *buf, size_t n)
-{
- int i;
- unsigned long val;
-
- if (sscanf(buf, "%lx", &val) != 1)
- return -EINVAL;
-
- mutex_lock(&etm.mutex);
- if (val) {
- etm.mode = ETM_MODE_EXCLUDE;
- etm.ctrl = 0x0;
- if (cpu_is_krait_v1()) {
- etm.mode |= ETM_MODE_CYCACC;
- etm.ctrl |= BIT(12);
- }
- etm.trigger_event = 0x406F;
- etm.startstop_ctrl = 0x0;
- etm.enable_event = 0x6F;
- etm.enable_ctrl1 = 0x1000000;
- etm.fifofull_level = 0x28;
- etm.addr_idx = 0x0;
- for (i = 0; i < etm.nr_addr_cmp; i++) {
- etm.addr_val[i] = 0x0;
- etm.addr_acctype[i] = 0x0;
- etm.addr_type[i] = ETM_ADDR_TYPE_NONE;
- }
- etm.cntr_idx = 0x0;
- for (i = 0; i < etm.nr_cntr; i++) {
- etm.cntr_rld_val[i] = 0x0;
- etm.cntr_event[i] = 0x406F;
- etm.cntr_rld_event[i] = 0x406F;
- etm.cntr_val[i] = 0x0;
- }
- etm.seq_12_event = 0x406F;
- etm.seq_21_event = 0x406F;
- etm.seq_23_event = 0x406F;
- etm.seq_31_event = 0x406F;
- etm.seq_32_event = 0x406F;
- etm.seq_13_event = 0x406F;
- etm.seq_curr_state = 0x0;
- etm.ctxid_idx = 0x0;
- for (i = 0; i < etm.nr_ctxid_cmp; i++)
- etm.ctxid_val[i] = 0x0;
- etm.ctxid_mask = 0x0;
- etm.sync_freq = 0x80;
- etm.timestamp_event = 0x406F;
- }
- mutex_unlock(&etm.mutex);
- return n;
-}
-ETM_SHOW(reset);
-ETM_ATTR(reset);
-
-static ssize_t mode_store(struct kobject *kobj,
- struct kobj_attribute *attr,
- const char *buf, size_t n)
-{
- unsigned long val;
-
- if (sscanf(buf, "%lx", &val) != 1)
- return -EINVAL;
-
- mutex_lock(&etm.mutex);
- etm.mode = val & ETM_MODE_ALL;
-
- if (etm.mode & ETM_MODE_EXCLUDE)
- etm.enable_ctrl1 |= BIT(24);
- else
- etm.enable_ctrl1 &= ~BIT(24);
-
- if (etm.mode & ETM_MODE_CYCACC)
- etm.ctrl |= BIT(12);
- else
- etm.ctrl &= ~BIT(12);
-
- if (etm.mode & ETM_MODE_STALL)
- etm.ctrl |= BIT(7);
- else
- etm.ctrl &= ~BIT(7);
-
- if (etm.mode & ETM_MODE_TIMESTAMP)
- etm.ctrl |= BIT(28);
- else
- etm.ctrl &= ~BIT(28);
- if (etm.mode & ETM_MODE_CTXID)
- etm.ctrl |= (BIT(14) | BIT(15));
- else
- etm.ctrl &= ~(BIT(14) | BIT(15));
- mutex_unlock(&etm.mutex);
-
- return n;
-}
-ETM_SHOW(mode);
-ETM_ATTR(mode);
-
-ETM_STORE(trigger_event, ETM_EVENT_MASK);
-ETM_SHOW(trigger_event);
-ETM_ATTR(trigger_event);
-
-ETM_STORE(enable_event, ETM_EVENT_MASK);
-ETM_SHOW(enable_event);
-ETM_ATTR(enable_event);
-
-ETM_STORE(fifofull_level, ETM_ALL_MASK);
-ETM_SHOW(fifofull_level);
-ETM_ATTR(fifofull_level);
-
-static ssize_t addr_idx_store(struct kobject *kobj,
- struct kobj_attribute *attr,
- const char *buf, size_t n)
-{
- unsigned long val;
-
- if (sscanf(buf, "%lx", &val) != 1)
- return -EINVAL;
- if (val >= etm.nr_addr_cmp)
- return -EINVAL;
-
- /* Use mutex to ensure index doesn't change while it gets dereferenced
- * multiple times within a mutex block elsewhere.
- */
- mutex_lock(&etm.mutex);
- etm.addr_idx = val;
- mutex_unlock(&etm.mutex);
- return n;
-}
-ETM_SHOW(addr_idx);
-ETM_ATTR(addr_idx);
-
-static ssize_t addr_single_store(struct kobject *kobj,
- struct kobj_attribute *attr,
- const char *buf, size_t n)
-{
- unsigned long val;
- uint8_t idx;
-
- if (sscanf(buf, "%lx", &val) != 1)
- return -EINVAL;
-
- mutex_lock(&etm.mutex);
- idx = etm.addr_idx;
- if (!(etm.addr_type[idx] == ETM_ADDR_TYPE_NONE ||
- etm.addr_type[idx] == ETM_ADDR_TYPE_SINGLE)) {
- mutex_unlock(&etm.mutex);
- return -EPERM;
- }
-
- etm.addr_val[idx] = val;
- etm.addr_type[idx] = ETM_ADDR_TYPE_SINGLE;
- mutex_unlock(&etm.mutex);
- return n;
-}
-static ssize_t addr_single_show(struct kobject *kobj,
- struct kobj_attribute *attr,
- char *buf)
-{
- unsigned long val;
- uint8_t idx;
-
- mutex_lock(&etm.mutex);
- idx = etm.addr_idx;
- if (!(etm.addr_type[idx] == ETM_ADDR_TYPE_NONE ||
- etm.addr_type[idx] == ETM_ADDR_TYPE_SINGLE)) {
- mutex_unlock(&etm.mutex);
- return -EPERM;
- }
-
- val = etm.addr_val[idx];
- mutex_unlock(&etm.mutex);
- return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
-}
-ETM_ATTR(addr_single);
-
-static ssize_t addr_range_store(struct kobject *kobj,
- struct kobj_attribute *attr,
- const char *buf, size_t n)
-{
- unsigned long val1, val2;
- uint8_t idx;
-
- if (sscanf(buf, "%lx %lx", &val1, &val2) != 2)
- return -EINVAL;
- /* lower address comparator cannot have a higher address value */
- if (val1 > val2)
- return -EINVAL;
-
- mutex_lock(&etm.mutex);
- idx = etm.addr_idx;
- if (idx % 2 != 0) {
- mutex_unlock(&etm.mutex);
- return -EPERM;
- }
- if (!((etm.addr_type[idx] == ETM_ADDR_TYPE_NONE &&
- etm.addr_type[idx + 1] == ETM_ADDR_TYPE_NONE) ||
- (etm.addr_type[idx] == ETM_ADDR_TYPE_RANGE &&
- etm.addr_type[idx + 1] == ETM_ADDR_TYPE_RANGE))) {
- mutex_unlock(&etm.mutex);
- return -EPERM;
- }
-
- etm.addr_val[idx] = val1;
- etm.addr_type[idx] = ETM_ADDR_TYPE_RANGE;
- etm.addr_val[idx + 1] = val2;
- etm.addr_type[idx + 1] = ETM_ADDR_TYPE_RANGE;
- etm.enable_ctrl1 |= (1 << (idx/2));
- mutex_unlock(&etm.mutex);
- return n;
-}
-static ssize_t addr_range_show(struct kobject *kobj,
- struct kobj_attribute *attr,
- char *buf)
-{
- unsigned long val1, val2;
- uint8_t idx;
-
- mutex_lock(&etm.mutex);
- idx = etm.addr_idx;
- if (idx % 2 != 0) {
- mutex_unlock(&etm.mutex);
- return -EPERM;
- }
- if (!((etm.addr_type[idx] == ETM_ADDR_TYPE_NONE &&
- etm.addr_type[idx + 1] == ETM_ADDR_TYPE_NONE) ||
- (etm.addr_type[idx] == ETM_ADDR_TYPE_RANGE &&
- etm.addr_type[idx + 1] == ETM_ADDR_TYPE_RANGE))) {
- mutex_unlock(&etm.mutex);
- return -EPERM;
- }
-
- val1 = etm.addr_val[idx];
- val2 = etm.addr_val[idx + 1];
- mutex_unlock(&etm.mutex);
- return scnprintf(buf, PAGE_SIZE, "%#lx %#lx\n", val1, val2);
-}
-ETM_ATTR(addr_range);
-
-static ssize_t addr_start_store(struct kobject *kobj,
- struct kobj_attribute *attr,
- const char *buf, size_t n)
-{
- unsigned long val;
- uint8_t idx;
-
- if (sscanf(buf, "%lx", &val) != 1)
- return -EINVAL;
-
- mutex_lock(&etm.mutex);
- idx = etm.addr_idx;
- if (!(etm.addr_type[idx] == ETM_ADDR_TYPE_NONE ||
- etm.addr_type[idx] == ETM_ADDR_TYPE_START)) {
- mutex_unlock(&etm.mutex);
- return -EPERM;
- }
-
- etm.addr_val[idx] = val;
- etm.addr_type[idx] = ETM_ADDR_TYPE_START;
- etm.startstop_ctrl |= (1 << idx);
- etm.enable_ctrl1 |= BIT(25);
- mutex_unlock(&etm.mutex);
- return n;
-}
-static ssize_t addr_start_show(struct kobject *kobj,
- struct kobj_attribute *attr,
- char *buf)
-{
- unsigned long val;
- uint8_t idx;
-
- mutex_lock(&etm.mutex);
- idx = etm.addr_idx;
- if (!(etm.addr_type[idx] == ETM_ADDR_TYPE_NONE ||
- etm.addr_type[idx] == ETM_ADDR_TYPE_START)) {
- mutex_unlock(&etm.mutex);
- return -EPERM;
- }
-
- val = etm.addr_val[idx];
- mutex_unlock(&etm.mutex);
- return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
-}
-ETM_ATTR(addr_start);
-
-static ssize_t addr_stop_store(struct kobject *kobj,
- struct kobj_attribute *attr,
- const char *buf, size_t n)
-{
- unsigned long val;
- uint8_t idx;
-
- if (sscanf(buf, "%lx", &val) != 1)
- return -EINVAL;
-
- mutex_lock(&etm.mutex);
- idx = etm.addr_idx;
- if (!(etm.addr_type[idx] == ETM_ADDR_TYPE_NONE ||
- etm.addr_type[idx] == ETM_ADDR_TYPE_STOP)) {
- mutex_unlock(&etm.mutex);
- return -EPERM;
- }
-
- etm.addr_val[idx] = val;
- etm.addr_type[idx] = ETM_ADDR_TYPE_STOP;
- etm.startstop_ctrl |= (1 << (idx + 16));
- etm.enable_ctrl1 |= BIT(25);
- mutex_unlock(&etm.mutex);
- return n;
-}
-static ssize_t addr_stop_show(struct kobject *kobj,
- struct kobj_attribute *attr,
- char *buf)
-{
- unsigned long val;
- uint8_t idx;
-
- mutex_lock(&etm.mutex);
- idx = etm.addr_idx;
- if (!(etm.addr_type[idx] == ETM_ADDR_TYPE_NONE ||
- etm.addr_type[idx] == ETM_ADDR_TYPE_STOP)) {
- mutex_unlock(&etm.mutex);
- return -EPERM;
- }
-
- val = etm.addr_val[idx];
- mutex_unlock(&etm.mutex);
- return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
-}
-ETM_ATTR(addr_stop);
-
-static ssize_t addr_acctype_store(struct kobject *kobj,
- struct kobj_attribute *attr,
- const char *buf, size_t n)
-{
- unsigned long val;
-
- if (sscanf(buf, "%lx", &val) != 1)
- return -EINVAL;
-
- mutex_lock(&etm.mutex);
- etm.addr_acctype[etm.addr_idx] = val;
- mutex_unlock(&etm.mutex);
- return n;
-}
-static ssize_t addr_acctype_show(struct kobject *kobj,
- struct kobj_attribute *attr,
- char *buf)
-{
- unsigned long val;
-
- mutex_lock(&etm.mutex);
- val = etm.addr_acctype[etm.addr_idx];
- mutex_unlock(&etm.mutex);
- return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
-}
-ETM_ATTR(addr_acctype);
-
-static ssize_t cntr_idx_store(struct kobject *kobj,
- struct kobj_attribute *attr,
- const char *buf, size_t n)
-{
- unsigned long val;
-
- if (sscanf(buf, "%lx", &val) != 1)
- return -EINVAL;
- if (val >= etm.nr_cntr)
- return -EINVAL;
-
- /* Use mutex to ensure index doesn't change while it gets dereferenced
- * multiple times within a mutex block elsewhere.
- */
- mutex_lock(&etm.mutex);
- etm.cntr_idx = val;
- mutex_unlock(&etm.mutex);
- return n;
-}
-ETM_SHOW(cntr_idx);
-ETM_ATTR(cntr_idx);
-
-static ssize_t cntr_rld_val_store(struct kobject *kobj,
- struct kobj_attribute *attr,
- const char *buf, size_t n)
-{
- unsigned long val;
-
- if (sscanf(buf, "%lx", &val) != 1)
- return -EINVAL;
-
- mutex_lock(&etm.mutex);
- etm.cntr_rld_val[etm.cntr_idx] = val;
- mutex_unlock(&etm.mutex);
- return n;
-}
-static ssize_t cntr_rld_val_show(struct kobject *kobj,
- struct kobj_attribute *attr,
- char *buf)
-{
- unsigned long val;
- mutex_lock(&etm.mutex);
- val = etm.cntr_rld_val[etm.cntr_idx];
- mutex_unlock(&etm.mutex);
- return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
-}
-ETM_ATTR(cntr_rld_val);
-
-static ssize_t cntr_event_store(struct kobject *kobj,
- struct kobj_attribute *attr,
- const char *buf, size_t n)
-{
- unsigned long val;
-
- if (sscanf(buf, "%lx", &val) != 1)
- return -EINVAL;
-
- mutex_lock(&etm.mutex);
- etm.cntr_event[etm.cntr_idx] = val & ETM_EVENT_MASK;
- mutex_unlock(&etm.mutex);
- return n;
-}
-static ssize_t cntr_event_show(struct kobject *kobj,
- struct kobj_attribute *attr,
- char *buf)
-{
- unsigned long val;
-
- mutex_lock(&etm.mutex);
- val = etm.cntr_event[etm.cntr_idx];
- mutex_unlock(&etm.mutex);
- return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
-}
-ETM_ATTR(cntr_event);
-
-static ssize_t cntr_rld_event_store(struct kobject *kobj,
- struct kobj_attribute *attr,
- const char *buf, size_t n)
-{
- unsigned long val;
-
- if (sscanf(buf, "%lx", &val) != 1)
- return -EINVAL;
-
- mutex_lock(&etm.mutex);
- etm.cntr_rld_event[etm.cntr_idx] = val & ETM_EVENT_MASK;
- mutex_unlock(&etm.mutex);
- return n;
-}
-static ssize_t cntr_rld_event_show(struct kobject *kobj,
- struct kobj_attribute *attr,
- char *buf)
-{
- unsigned long val;
-
- mutex_lock(&etm.mutex);
- val = etm.cntr_rld_event[etm.cntr_idx];
- mutex_unlock(&etm.mutex);
- return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
-}
-ETM_ATTR(cntr_rld_event);
-
-static ssize_t cntr_val_store(struct kobject *kobj,
- struct kobj_attribute *attr,
- const char *buf, size_t n)
-{
- unsigned long val;
-
- if (sscanf(buf, "%lx", &val) != 1)
- return -EINVAL;
-
- mutex_lock(&etm.mutex);
- etm.cntr_val[etm.cntr_idx] = val;
- mutex_unlock(&etm.mutex);
- return n;
-}
-static ssize_t cntr_val_show(struct kobject *kobj,
- struct kobj_attribute *attr,
- char *buf)
-{
- unsigned long val;
-
- mutex_lock(&etm.mutex);
- val = etm.cntr_val[etm.cntr_idx];
- mutex_unlock(&etm.mutex);
- return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
-}
-ETM_ATTR(cntr_val);
-
-ETM_STORE(seq_12_event, ETM_EVENT_MASK);
-ETM_SHOW(seq_12_event);
-ETM_ATTR(seq_12_event);
-
-ETM_STORE(seq_21_event, ETM_EVENT_MASK);
-ETM_SHOW(seq_21_event);
-ETM_ATTR(seq_21_event);
-
-ETM_STORE(seq_23_event, ETM_EVENT_MASK);
-ETM_SHOW(seq_23_event);
-ETM_ATTR(seq_23_event);
-
-ETM_STORE(seq_31_event, ETM_EVENT_MASK);
-ETM_SHOW(seq_31_event);
-ETM_ATTR(seq_31_event);
-
-ETM_STORE(seq_32_event, ETM_EVENT_MASK);
-ETM_SHOW(seq_32_event);
-ETM_ATTR(seq_32_event);
-
-ETM_STORE(seq_13_event, ETM_EVENT_MASK);
-ETM_SHOW(seq_13_event);
-ETM_ATTR(seq_13_event);
-
-static ssize_t seq_curr_state_store(struct kobject *kobj,
- struct kobj_attribute *attr,
- const char *buf, size_t n)
-{
- unsigned long val;
-
- if (sscanf(buf, "%lx", &val) != 1)
- return -EINVAL;
- if (val > ETM_SEQ_STATE_MAX_VAL)
- return -EINVAL;
-
- etm.seq_curr_state = val;
- return n;
-}
-ETM_SHOW(seq_curr_state);
-ETM_ATTR(seq_curr_state);
-
-static ssize_t ctxid_idx_store(struct kobject *kobj,
- struct kobj_attribute *attr,
- const char *buf, size_t n)
-{
- unsigned long val;
-
- if (sscanf(buf, "%lx", &val) != 1)
- return -EINVAL;
- if (val >= etm.nr_ctxid_cmp)
- return -EINVAL;
-
- /* Use mutex to ensure index doesn't change while it gets dereferenced
- * multiple times within a mutex block elsewhere.
- */
- mutex_lock(&etm.mutex);
- etm.ctxid_idx = val;
- mutex_unlock(&etm.mutex);
- return n;
-}
-ETM_SHOW(ctxid_idx);
-ETM_ATTR(ctxid_idx);
-
-static ssize_t ctxid_val_store(struct kobject *kobj,
- struct kobj_attribute *attr,
- const char *buf, size_t n)
-{
- unsigned long val;
-
- if (sscanf(buf, "%lx", &val) != 1)
- return -EINVAL;
-
- mutex_lock(&etm.mutex);
- etm.ctxid_val[etm.ctxid_idx] = val;
- mutex_unlock(&etm.mutex);
- return n;
-}
-static ssize_t ctxid_val_show(struct kobject *kobj,
- struct kobj_attribute *attr,
- char *buf)
-{
- unsigned long val;
-
- mutex_lock(&etm.mutex);
- val = etm.ctxid_val[etm.ctxid_idx];
- mutex_unlock(&etm.mutex);
- return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
-}
-ETM_ATTR(ctxid_val);
-
-ETM_STORE(ctxid_mask, ETM_ALL_MASK);
-ETM_SHOW(ctxid_mask);
-ETM_ATTR(ctxid_mask);
-
-ETM_STORE(sync_freq, ETM_SYNC_MASK);
-ETM_SHOW(sync_freq);
-ETM_ATTR(sync_freq);
-
-ETM_STORE(timestamp_event, ETM_EVENT_MASK);
-ETM_SHOW(timestamp_event);
-ETM_ATTR(timestamp_event);
-
-static struct attribute *etm_attrs[] = {
- &nr_addr_cmp_attr.attr,
- &nr_cntr_attr.attr,
- &nr_ctxid_cmp_attr.attr,
- &reset_attr.attr,
- &mode_attr.attr,
- &trigger_event_attr.attr,
- &enable_event_attr.attr,
- &fifofull_level_attr.attr,
- &addr_idx_attr.attr,
- &addr_single_attr.attr,
- &addr_range_attr.attr,
- &addr_start_attr.attr,
- &addr_stop_attr.attr,
- &addr_acctype_attr.attr,
- &cntr_idx_attr.attr,
- &cntr_rld_val_attr.attr,
- &cntr_event_attr.attr,
- &cntr_rld_event_attr.attr,
- &cntr_val_attr.attr,
- &seq_12_event_attr.attr,
- &seq_21_event_attr.attr,
- &seq_23_event_attr.attr,
- &seq_31_event_attr.attr,
- &seq_32_event_attr.attr,
- &seq_13_event_attr.attr,
- &seq_curr_state_attr.attr,
- &ctxid_idx_attr.attr,
- &ctxid_val_attr.attr,
- &ctxid_mask_attr.attr,
- &sync_freq_attr.attr,
- ×tamp_event_attr.attr,
- NULL,
-};
-
-static struct attribute_group etm_attr_grp = {
- .attrs = etm_attrs,
-};
-
-static int __devinit etm_sysfs_init(void)
-{
- int ret;
-
- etm.kobj = kobject_create_and_add("etm", qdss_get_modulekobj());
- if (!etm.kobj) {
- dev_err(etm.dev, "failed to create ETM sysfs kobject\n");
- ret = -ENOMEM;
- goto err_create;
- }
-
- ret = sysfs_create_file(etm.kobj, &enabled_attr.attr);
- if (ret) {
- dev_err(etm.dev, "failed to create ETM sysfs enabled"
- " attribute\n");
- goto err_file;
- }
-
- if (sysfs_create_group(etm.kobj, &etm_attr_grp))
- dev_err(etm.dev, "failed to create ETM sysfs group\n");
-
- return 0;
-err_file:
- kobject_put(etm.kobj);
-err_create:
- return ret;
-}
-
-static void __devexit etm_sysfs_exit(void)
-{
- sysfs_remove_group(etm.kobj, &etm_attr_grp);
- sysfs_remove_file(etm.kobj, &enabled_attr.attr);
- kobject_put(etm.kobj);
-}
-
-static bool __devinit etm_arch_supported(uint8_t arch)
-{
- switch (arch) {
- case PFT_ARCH_V1_1:
- break;
- default:
- return false;
- }
- return true;
-}
-
-static int __devinit etm_arch_init(void)
-{
- int ret, i;
- /* use cpu 0 for setup */
- int cpu = 0;
- uint32_t etmidr;
- uint32_t etmccr;
-
- /* Unlock OS lock first to allow memory mapped reads and writes */
- etm_os_unlock(NULL);
- smp_call_function(etm_os_unlock, NULL, 1);
- ETM_UNLOCK(cpu);
- /* Vote for ETM power/clock enable */
- etm_clr_pwrdwn(cpu);
- /* Set prog bit. It will be set from reset but this is included to
- * ensure it is set
- */
- etm_set_prog(cpu);
-
- /* find all capabilities */
- etmidr = etm_readl(etm, cpu, ETMIDR);
- etm.arch = BMVAL(etmidr, 4, 11);
- if (etm_arch_supported(etm.arch) == false) {
- ret = -EINVAL;
- goto err;
- }
-
- etmccr = etm_readl(etm, cpu, ETMCCR);
- etm.nr_addr_cmp = BMVAL(etmccr, 0, 3) * 2;
- etm.nr_cntr = BMVAL(etmccr, 13, 15);
- etm.nr_ext_inp = BMVAL(etmccr, 17, 19);
- etm.nr_ext_out = BMVAL(etmccr, 20, 22);
- etm.nr_ctxid_cmp = BMVAL(etmccr, 24, 25);
-
- if (cpu_is_krait_v1()) {
- /* Krait pass1 doesn't support include filtering and non-cycle
- * accurate tracing
- */
- etm.mode = (ETM_MODE_EXCLUDE | ETM_MODE_CYCACC);
- etm.ctrl = 0x1000;
- etm.enable_ctrl1 = 0x1000000;
- for (i = 0; i < etm.nr_addr_cmp; i++) {
- etm.addr_val[i] = 0x0;
- etm.addr_acctype[i] = 0x0;
- etm.addr_type[i] = ETM_ADDR_TYPE_NONE;
- }
- }
-
- /* Vote for ETM power/clock disable */
- etm_set_pwrdwn(cpu);
- ETM_LOCK(cpu);
-
- return 0;
-err:
- return ret;
-}
-
-static int __devinit etm_probe(struct platform_device *pdev)
-{
- int ret;
- struct resource *res;
-
- res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
- if (!res) {
- ret = -EINVAL;
- goto err_res;
- }
-
- etm.base = ioremap_nocache(res->start, resource_size(res));
- if (!etm.base) {
- ret = -EINVAL;
- goto err_ioremap;
- }
-
- etm.dev = &pdev->dev;
-
- mutex_init(&etm.mutex);
- wake_lock_init(&etm.wake_lock, WAKE_LOCK_SUSPEND, "msm_etm");
- pm_qos_add_request(&etm.qos_req, PM_QOS_CPU_DMA_LATENCY,
- PM_QOS_DEFAULT_VALUE);
- etm.src = qdss_get("msm_etm");
- if (IS_ERR(etm.src)) {
- ret = PTR_ERR(etm.src);
- goto err_qdssget;
- }
-
- ret = qdss_clk_enable();
- if (ret)
- goto err_clk;
-
- ret = etm_arch_init();
- if (ret)
- goto err_arch;
-
- ret = etm_sysfs_init();
- if (ret)
- goto err_sysfs;
-
- etm.enabled = false;
-
- qdss_clk_disable();
-
- dev_info(etm.dev, "ETM initialized\n");
-
- if (etm_boot_enable)
- etm_enable();
-
- return 0;
-
-err_sysfs:
-err_arch:
- qdss_clk_disable();
-err_clk:
- qdss_put(etm.src);
-err_qdssget:
- pm_qos_remove_request(&etm.qos_req);
- wake_lock_destroy(&etm.wake_lock);
- mutex_destroy(&etm.mutex);
- iounmap(etm.base);
-err_ioremap:
-err_res:
- dev_err(etm.dev, "ETM init failed\n");
- return ret;
-}
-
-static int __devexit etm_remove(struct platform_device *pdev)
-{
- if (etm.enabled)
- etm_disable();
- etm_sysfs_exit();
- qdss_put(etm.src);
- pm_qos_remove_request(&etm.qos_req);
- wake_lock_destroy(&etm.wake_lock);
- mutex_destroy(&etm.mutex);
- iounmap(etm.base);
-
- return 0;
-}
-
-static struct of_device_id etm_match[] = {
- {.compatible = "qcom,msm-etm"},
- {}
-};
-
-static struct platform_driver etm_driver = {
- .probe = etm_probe,
- .remove = __devexit_p(etm_remove),
- .driver = {
- .name = "msm_etm",
- .owner = THIS_MODULE,
- .of_match_table = etm_match,
- },
-};
-
-int __init etm_init(void)
-{
- return platform_driver_register(&etm_driver);
-}
-module_init(etm_init);
-
-void __exit etm_exit(void)
-{
- platform_driver_unregister(&etm_driver);
-}
-module_exit(etm_exit);
-
-MODULE_LICENSE("GPL v2");
-MODULE_DESCRIPTION("CoreSight Program Flow Trace driver");
diff --git a/arch/arm/mach-msm/qdss-funnel.c b/arch/arm/mach-msm/qdss-funnel.c
deleted file mode 100644
index 1c19ebd..0000000
--- a/arch/arm/mach-msm/qdss-funnel.c
+++ /dev/null
@@ -1,239 +0,0 @@
-/* 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
- * only version 2 as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- */
-
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/init.h>
-#include <linux/types.h>
-#include <linux/device.h>
-#include <linux/platform_device.h>
-#include <linux/io.h>
-#include <linux/err.h>
-
-#include "qdss-priv.h"
-
-#define funnel_writel(funnel, id, val, off) \
- __raw_writel((val), funnel.base + (SZ_4K * id) + off)
-#define funnel_readl(funnel, id, off) \
- __raw_readl(funnel.base + (SZ_4K * id) + off)
-
-#define FUNNEL_FUNCTL (0x000)
-#define FUNNEL_PRICTL (0x004)
-#define FUNNEL_ITATBDATA0 (0xEEC)
-#define FUNNEL_ITATBCTR2 (0xEF0)
-#define FUNNEL_ITATBCTR1 (0xEF4)
-#define FUNNEL_ITATBCTR0 (0xEF8)
-
-
-#define FUNNEL_LOCK(id) \
-do { \
- mb(); \
- funnel_writel(funnel, id, 0x0, CS_LAR); \
-} while (0)
-#define FUNNEL_UNLOCK(id) \
-do { \
- funnel_writel(funnel, id, CS_UNLOCK_MAGIC, CS_LAR); \
- mb(); \
-} while (0)
-
-#define FUNNEL_HOLDTIME_MASK (0xF00)
-#define FUNNEL_HOLDTIME_SHFT (0x8)
-#define FUNNEL_HOLDTIME (0x7 << FUNNEL_HOLDTIME_SHFT)
-
-struct funnel_ctx {
- void __iomem *base;
- bool enabled;
- struct mutex mutex;
- struct device *dev;
- struct kobject *kobj;
- uint32_t priority;
-};
-
-static struct funnel_ctx funnel;
-
-static void __funnel_enable(uint8_t id, uint32_t port_mask)
-{
- uint32_t functl;
-
- FUNNEL_UNLOCK(id);
-
- functl = funnel_readl(funnel, id, FUNNEL_FUNCTL);
- functl &= ~FUNNEL_HOLDTIME_MASK;
- functl |= FUNNEL_HOLDTIME;
- functl |= port_mask;
- funnel_writel(funnel, id, functl, FUNNEL_FUNCTL);
- funnel_writel(funnel, id, funnel.priority, FUNNEL_PRICTL);
-
- FUNNEL_LOCK(id);
-}
-
-void funnel_enable(uint8_t id, uint32_t port_mask)
-{
- mutex_lock(&funnel.mutex);
- __funnel_enable(id, port_mask);
- funnel.enabled = true;
- dev_info(funnel.dev, "FUNNEL port mask 0x%lx enabled\n",
- (unsigned long) port_mask);
- mutex_unlock(&funnel.mutex);
-}
-
-static void __funnel_disable(uint8_t id, uint32_t port_mask)
-{
- uint32_t functl;
-
- FUNNEL_UNLOCK(id);
-
- functl = funnel_readl(funnel, id, FUNNEL_FUNCTL);
- functl &= ~port_mask;
- funnel_writel(funnel, id, functl, FUNNEL_FUNCTL);
-
- FUNNEL_LOCK(id);
-}
-
-void funnel_disable(uint8_t id, uint32_t port_mask)
-{
- mutex_lock(&funnel.mutex);
- __funnel_disable(id, port_mask);
- funnel.enabled = false;
- dev_info(funnel.dev, "FUNNEL port mask 0x%lx disabled\n",
- (unsigned long) port_mask);
- mutex_unlock(&funnel.mutex);
-}
-
-#define FUNNEL_ATTR(__name) \
-static struct kobj_attribute __name##_attr = \
- __ATTR(__name, S_IRUGO | S_IWUSR, __name##_show, __name##_store)
-
-static ssize_t priority_store(struct kobject *kobj,
- struct kobj_attribute *attr,
- const char *buf, size_t n)
-{
- unsigned long val;
-
- if (sscanf(buf, "%lx", &val) != 1)
- return -EINVAL;
-
- funnel.priority = val;
- return n;
-}
-static ssize_t priority_show(struct kobject *kobj,
- struct kobj_attribute *attr,
- char *buf)
-{
- unsigned long val = funnel.priority;
- return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
-}
-FUNNEL_ATTR(priority);
-
-static int __devinit funnel_sysfs_init(void)
-{
- int ret;
-
- funnel.kobj = kobject_create_and_add("funnel", qdss_get_modulekobj());
- if (!funnel.kobj) {
- dev_err(funnel.dev, "failed to create FUNNEL sysfs kobject\n");
- ret = -ENOMEM;
- goto err_create;
- }
-
- ret = sysfs_create_file(funnel.kobj, &priority_attr.attr);
- if (ret) {
- dev_err(funnel.dev, "failed to create FUNNEL sysfs priority"
- " attribute\n");
- goto err_file;
- }
-
- return 0;
-err_file:
- kobject_put(funnel.kobj);
-err_create:
- return ret;
-}
-
-static void __devexit funnel_sysfs_exit(void)
-{
- sysfs_remove_file(funnel.kobj, &priority_attr.attr);
- kobject_put(funnel.kobj);
-}
-
-static int __devinit funnel_probe(struct platform_device *pdev)
-{
- int ret;
- struct resource *res;
-
- res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
- if (!res) {
- ret = -EINVAL;
- goto err_res;
- }
-
- funnel.base = ioremap_nocache(res->start, resource_size(res));
- if (!funnel.base) {
- ret = -EINVAL;
- goto err_ioremap;
- }
-
- funnel.dev = &pdev->dev;
-
- mutex_init(&funnel.mutex);
-
- funnel_sysfs_init();
-
- dev_info(funnel.dev, "FUNNEL initialized\n");
- return 0;
-
-err_ioremap:
-err_res:
- dev_err(funnel.dev, "FUNNEL init failed\n");
- return ret;
-}
-
-static int __devexit funnel_remove(struct platform_device *pdev)
-{
- if (funnel.enabled)
- funnel_disable(0x0, 0xFF);
- funnel_sysfs_exit();
- mutex_destroy(&funnel.mutex);
- iounmap(funnel.base);
-
- return 0;
-}
-
-static struct of_device_id funnel_match[] = {
- {.compatible = "qcom,msm-funnel"},
- {}
-};
-
-static struct platform_driver funnel_driver = {
- .probe = funnel_probe,
- .remove = __devexit_p(funnel_remove),
- .driver = {
- .name = "msm_funnel",
- .owner = THIS_MODULE,
- .of_match_table = funnel_match,
- },
-};
-
-static int __init funnel_init(void)
-{
- return platform_driver_register(&funnel_driver);
-}
-module_init(funnel_init);
-
-static void __exit funnel_exit(void)
-{
- platform_driver_unregister(&funnel_driver);
-}
-module_exit(funnel_exit);
-
-MODULE_LICENSE("GPL v2");
-MODULE_DESCRIPTION("CoreSight Funnel driver");
diff --git a/arch/arm/mach-msm/qdss-priv.h b/arch/arm/mach-msm/qdss-priv.h
deleted file mode 100644
index f39bc52..0000000
--- a/arch/arm/mach-msm/qdss-priv.h
+++ /dev/null
@@ -1,70 +0,0 @@
-/* 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
- * 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_QDSS_H_
-#define _ARCH_ARM_MACH_MSM_QDSS_H_
-
-#include <linux/bitops.h>
-#include <mach/qdss.h>
-
-/* Coresight management registers (0xF00-0xFCC)
- * 0xFA0 - 0xFA4: Management registers in PFTv1.0
- * Trace registers in PFTv1.1
- */
-#define CS_ITCTRL (0xF00)
-#define CS_CLAIMSET (0xFA0)
-#define CS_CLAIMCLR (0xFA4)
-#define CS_LAR (0xFB0)
-#define CS_LSR (0xFB4)
-#define CS_AUTHSTATUS (0xFB8)
-#define CS_DEVID (0xFC8)
-#define CS_DEVTYPE (0xFCC)
-/* Peripheral id registers (0xFD0-0xFEC) */
-#define CS_PIDR4 (0xFD0)
-#define CS_PIDR5 (0xFD4)
-#define CS_PIDR6 (0xFD8)
-#define CS_PIDR7 (0xFDC)
-#define CS_PIDR0 (0xFE0)
-#define CS_PIDR1 (0xFE4)
-#define CS_PIDR2 (0xFE8)
-#define CS_PIDR3 (0xFEC)
-/* Component id registers (0xFF0-0xFFC) */
-#define CS_CIDR0 (0xFF0)
-#define CS_CIDR1 (0xFF4)
-#define CS_CIDR2 (0xFF8)
-#define CS_CIDR3 (0xFFC)
-
-/* DBGv7 with baseline CP14 registers implemented */
-#define ARM_DEBUG_ARCH_V7B (0x3)
-/* DBGv7 with all CP14 registers implemented */
-#define ARM_DEBUG_ARCH_V7 (0x4)
-#define ARM_DEBUG_ARCH_V7_1 (0x5)
-#define ETM_ARCH_V3_3 (0x23)
-#define PFT_ARCH_V1_1 (0x31)
-
-#define TIMEOUT_US (100)
-#define CS_UNLOCK_MAGIC (0xC5ACCE55)
-
-#define BM(lsb, msb) ((BIT(msb) - BIT(lsb)) + BIT(msb))
-#define BMVAL(val, lsb, msb) ((val & BM(lsb, msb)) >> lsb)
-#define BVAL(val, n) ((val & BIT(n)) >> n)
-
-void etb_enable(void);
-void etb_disable(void);
-void etb_dump(void);
-void tpiu_disable(void);
-void funnel_enable(uint8_t id, uint32_t port_mask);
-void funnel_disable(uint8_t id, uint32_t port_mask);
-
-struct kobject *qdss_get_modulekobj(void);
-
-#endif
diff --git a/arch/arm/mach-msm/qdss.c b/arch/arm/mach-msm/qdss.c
deleted file mode 100644
index 83a6a36..0000000
--- a/arch/arm/mach-msm/qdss.c
+++ /dev/null
@@ -1,411 +0,0 @@
-/* Copyright (c) 2012, Code Aurora Forum. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 and
- * only version 2 as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- */
-
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/init.h>
-#include <linux/types.h>
-#include <linux/device.h>
-#include <linux/platform_device.h>
-#include <linux/io.h>
-#include <linux/err.h>
-#include <linux/export.h>
-#include <mach/rpm.h>
-
-#include "rpm_resources.h"
-#include "qdss-priv.h"
-
-#define MAX_STR_LEN (65535)
-
-enum {
- QDSS_CLK_OFF,
- QDSS_CLK_ON_DBG,
- QDSS_CLK_ON_HSDBG,
-};
-
-/*
- * Exclusion rules for structure fields.
- *
- * S: qdss.sources_mutex protected.
- * I: qdss.sink_mutex protected.
- * C: qdss.clk_mutex protected.
- */
-struct qdss_ctx {
- struct kobject *modulekobj;
- uint8_t afamily;
- struct list_head sources; /* S: sources list */
- struct mutex sources_mutex;
- uint8_t sink_count; /* I: sink count */
- struct mutex sink_mutex;
- uint8_t max_clk;
- uint8_t clk_count; /* C: clk count */
- struct mutex clk_mutex;
-};
-
-static struct qdss_ctx qdss;
-
-/**
- * qdss_get - get the qdss source handle
- * @name: name of the qdss source
- *
- * Searches the sources list to get the qdss source handle for this source.
- *
- * CONTEXT:
- * Typically called from init or probe functions
- *
- * RETURNS:
- * pointer to struct qdss_source on success, %NULL on failure
- */
-struct qdss_source *qdss_get(const char *name)
-{
- struct qdss_source *src, *source = NULL;
-
- mutex_lock(&qdss.sources_mutex);
- list_for_each_entry(src, &qdss.sources, link) {
- if (src->name) {
- if (strncmp(src->name, name, MAX_STR_LEN))
- continue;
- source = src;
- break;
- }
- }
- mutex_unlock(&qdss.sources_mutex);
-
- return source ? source : ERR_PTR(-ENOENT);
-}
-EXPORT_SYMBOL(qdss_get);
-
-/**
- * qdss_put - release the qdss source handle
- * @name: name of the qdss source
- *
- * CONTEXT:
- * Typically called from driver remove or exit functions
- */
-void qdss_put(struct qdss_source *src)
-{
-}
-EXPORT_SYMBOL(qdss_put);
-
-/**
- * qdss_enable - enable qdss for the source
- * @src: handle for the source making the call
- *
- * Enables qdss block (relevant funnel ports and sink) if not already
- * enabled, otherwise increments the reference count
- *
- * CONTEXT:
- * Might sleep. Uses a mutex lock. Should be called from a non-atomic context.
- *
- * RETURNS:
- * 0 on success, non-zero on failure
- */
-int qdss_enable(struct qdss_source *src)
-{
- int ret;
-
- if (!src)
- return -EINVAL;
-
- ret = qdss_clk_enable();
- if (ret)
- goto err;
-
- if (qdss.afamily) {
- mutex_lock(&qdss.sink_mutex);
- if (qdss.sink_count == 0) {
- etb_disable();
- tpiu_disable();
- /* enable ETB first to avoid losing any trace data */
- etb_enable();
- }
- qdss.sink_count++;
- mutex_unlock(&qdss.sink_mutex);
- }
-
- funnel_enable(0x0, src->fport_mask);
- return 0;
-err:
- return ret;
-}
-EXPORT_SYMBOL(qdss_enable);
-
-/**
- * qdss_disable - disable qdss for the source
- * @src: handle for the source making the call
- *
- * Disables qdss block (relevant funnel ports and sink) if the reference count
- * is one, otherwise decrements the reference count
- *
- * CONTEXT:
- * Might sleep. Uses a mutex lock. Should be called from a non-atomic context.
- */
-void qdss_disable(struct qdss_source *src)
-{
- if (!src)
- return;
-
- if (qdss.afamily) {
- mutex_lock(&qdss.sink_mutex);
- if (WARN(qdss.sink_count == 0, "qdss is unbalanced\n"))
- goto out;
- if (qdss.sink_count == 1) {
- etb_dump();
- etb_disable();
- }
- qdss.sink_count--;
- mutex_unlock(&qdss.sink_mutex);
- }
-
- funnel_disable(0x0, src->fport_mask);
- qdss_clk_disable();
- return;
-out:
- mutex_unlock(&qdss.sink_mutex);
-}
-EXPORT_SYMBOL(qdss_disable);
-
-/**
- * qdss_disable_sink - force disable the current qdss sink(s)
- *
- * Force disable the current qdss sink(s) to stop the sink from accepting any
- * trace generated subsequent to this call. This function should only be used
- * as a way to stop the sink from getting polluted with trace data that is
- * uninteresting after an event of interest has occured.
- *
- * CONTEXT:
- * Can be called from atomic or non-atomic context.
- */
-void qdss_disable_sink(void)
-{
- if (qdss.afamily) {
- etb_dump();
- etb_disable();
- }
-}
-EXPORT_SYMBOL(qdss_disable_sink);
-
-/**
- * qdss_clk_enable - enable qdss clocks
- *
- * Enables qdss clocks via RPM if they aren't already enabled, otherwise
- * increments the reference count.
- *
- * CONTEXT:
- * Might sleep. Uses a mutex lock. Should be called from a non-atomic context.
- *
- * RETURNS:
- * 0 on success, non-zero on failure
- */
-int qdss_clk_enable(void)
-{
- int ret;
- struct msm_rpm_iv_pair iv;
-
- mutex_lock(&qdss.clk_mutex);
- if (qdss.clk_count == 0) {
- iv.id = MSM_RPM_ID_QDSS_CLK;
- if (qdss.max_clk)
- iv.value = QDSS_CLK_ON_HSDBG;
- else
- iv.value = QDSS_CLK_ON_DBG;
- ret = msm_rpmrs_set(MSM_RPM_CTX_SET_0, &iv, 1);
- if (WARN(ret, "qdss clks not enabled (%d)\n", ret))
- goto err_clk;
- }
- qdss.clk_count++;
- mutex_unlock(&qdss.clk_mutex);
- return 0;
-err_clk:
- mutex_unlock(&qdss.clk_mutex);
- return ret;
-}
-EXPORT_SYMBOL(qdss_clk_enable);
-
-/**
- * qdss_clk_disable - disable qdss clocks
- *
- * Disables qdss clocks via RPM if the reference count is one, otherwise
- * decrements the reference count.
- *
- * CONTEXT:
- * Might sleep. Uses a mutex lock. Should be called from a non-atomic context.
- */
-void qdss_clk_disable(void)
-{
- int ret;
- struct msm_rpm_iv_pair iv;
-
- mutex_lock(&qdss.clk_mutex);
- if (WARN(qdss.clk_count == 0, "qdss clks are unbalanced\n"))
- goto out;
- if (qdss.clk_count == 1) {
- iv.id = MSM_RPM_ID_QDSS_CLK;
- iv.value = QDSS_CLK_OFF;
- ret = msm_rpmrs_set(MSM_RPM_CTX_SET_0, &iv, 1);
- WARN(ret, "qdss clks not disabled (%d)\n", ret);
- }
- qdss.clk_count--;
-out:
- mutex_unlock(&qdss.clk_mutex);
-}
-EXPORT_SYMBOL(qdss_clk_disable);
-
-struct kobject *qdss_get_modulekobj(void)
-{
- return qdss.modulekobj;
-}
-
-#define QDSS_ATTR(name) \
-static struct kobj_attribute name##_attr = \
- __ATTR(name, S_IRUGO | S_IWUSR, name##_show, name##_store)
-
-static ssize_t max_clk_store(struct kobject *kobj,
- struct kobj_attribute *attr,
- const char *buf, size_t n)
-{
- unsigned long val;
-
- if (sscanf(buf, "%lx", &val) != 1)
- return -EINVAL;
-
- qdss.max_clk = val;
- return n;
-}
-static ssize_t max_clk_show(struct kobject *kobj,
- struct kobj_attribute *attr,
- char *buf)
-{
- unsigned long val = qdss.max_clk;
- return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
-}
-QDSS_ATTR(max_clk);
-
-static void __devinit qdss_add_sources(struct qdss_source *srcs, size_t num)
-{
- mutex_lock(&qdss.sources_mutex);
- while (num--) {
- list_add_tail(&srcs->link, &qdss.sources);
- srcs++;
- }
- mutex_unlock(&qdss.sources_mutex);
-}
-
-static int __init qdss_sysfs_init(void)
-{
- int ret;
-
- qdss.modulekobj = kset_find_obj(module_kset, KBUILD_MODNAME);
- if (!qdss.modulekobj) {
- pr_err("failed to find QDSS sysfs module kobject\n");
- ret = -ENOENT;
- goto err;
- }
-
- ret = sysfs_create_file(qdss.modulekobj, &max_clk_attr.attr);
- if (ret) {
- pr_err("failed to create QDSS sysfs max_clk attribute\n");
- goto err;
- }
-
- return 0;
-err:
- return ret;
-}
-
-static void __devexit qdss_sysfs_exit(void)
-{
- sysfs_remove_file(qdss.modulekobj, &max_clk_attr.attr);
-}
-
-static int __devinit qdss_probe(struct platform_device *pdev)
-{
- int ret;
- struct msm_qdss_platform_data *pdata;
-
- mutex_init(&qdss.sources_mutex);
- mutex_init(&qdss.clk_mutex);
- mutex_init(&qdss.sink_mutex);
-
- INIT_LIST_HEAD(&qdss.sources);
-
- pdata = pdev->dev.platform_data;
- if (!pdata)
- goto err_pdata;
-
- qdss.afamily = pdata->afamily;
- qdss_add_sources(pdata->src_table, pdata->size);
-
- pr_info("QDSS arch initialized\n");
- return 0;
-err_pdata:
- mutex_destroy(&qdss.sink_mutex);
- mutex_destroy(&qdss.clk_mutex);
- mutex_destroy(&qdss.sources_mutex);
- pr_err("QDSS init failed\n");
- return ret;
-}
-
-static int __devexit qdss_remove(struct platform_device *pdev)
-{
- qdss_sysfs_exit();
- mutex_destroy(&qdss.sink_mutex);
- mutex_destroy(&qdss.clk_mutex);
- mutex_destroy(&qdss.sources_mutex);
-
- return 0;
-}
-
-static struct of_device_id qdss_match[] = {
- {.compatible = "qcom,msm-qdss"},
- {}
-};
-
-static struct platform_driver qdss_driver = {
- .probe = qdss_probe,
- .remove = __devexit_p(qdss_remove),
- .driver = {
- .name = "msm_qdss",
- .owner = THIS_MODULE,
- .of_match_table = qdss_match,
- },
-};
-
-static int __init qdss_init(void)
-{
- return platform_driver_register(&qdss_driver);
-}
-arch_initcall(qdss_init);
-
-static int __init qdss_module_init(void)
-{
- int ret;
-
- ret = qdss_sysfs_init();
- if (ret)
- goto err_sysfs;
-
- pr_info("QDSS module initialized\n");
- return 0;
-err_sysfs:
- return ret;
-}
-module_init(qdss_module_init);
-
-static void __exit qdss_exit(void)
-{
- platform_driver_unregister(&qdss_driver);
-}
-module_exit(qdss_exit);
-
-MODULE_LICENSE("GPL v2");
-MODULE_DESCRIPTION("Qualcomm Debug SubSystem Driver");
diff --git a/arch/arm/mach-msm/sdio_ctl.c b/arch/arm/mach-msm/sdio_ctl.c
index 586e890..ac16e77 100644
--- a/arch/arm/mach-msm/sdio_ctl.c
+++ b/arch/arm/mach-msm/sdio_ctl.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
+/* Copyright (c) 2010-2012, Code Aurora Forum. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -25,6 +25,7 @@
#include <linux/mutex.h>
#include <linux/uaccess.h>
#include <linux/workqueue.h>
+#include <linux/poll.h>
#include <asm/ioctls.h>
#include <linux/platform_device.h>
#include <mach/msm_smd.h>
@@ -206,6 +207,34 @@
return ret;
}
+static unsigned int sdio_ctl_poll(struct file *file, poll_table *wait)
+{
+ struct sdio_ctl_dev *sdio_ctl_devp;
+ unsigned int mask = 0;
+
+ sdio_ctl_devp = file->private_data;
+ if (!sdio_ctl_devp) {
+ pr_err("%s: on a NULL device\n", __func__);
+ return POLLERR;
+ }
+
+ poll_wait(file, &sdio_ctl_devp->read_wait_queue, wait);
+ mutex_lock(&sdio_ctl_devp->rx_lock);
+ if (sdio_cmux_is_channel_reset(sdio_ctl_devp->id)) {
+ mutex_unlock(&sdio_ctl_devp->rx_lock);
+ pr_err("%s notifying reset for sdio_ctl_dev id:%d\n",
+ __func__, sdio_ctl_devp->id);
+ return POLLERR;
+ }
+
+ if (sdio_ctl_devp->read_avail > 0)
+ mask |= POLLIN | POLLRDNORM;
+
+ mutex_unlock(&sdio_ctl_devp->rx_lock);
+
+ return mask;
+}
+
ssize_t sdio_ctl_read(struct file *file,
char __user *buf,
size_t count,
@@ -417,6 +446,7 @@
.release = sdio_ctl_release,
.read = sdio_ctl_read,
.write = sdio_ctl_write,
+ .poll = sdio_ctl_poll,
.unlocked_ioctl = sdio_ctl_ioctl,
};
diff --git a/arch/arm/mach-msm/socinfo.c b/arch/arm/mach-msm/socinfo.c
index b047cf4..533e6cd 100644
--- a/arch/arm/mach-msm/socinfo.c
+++ b/arch/arm/mach-msm/socinfo.c
@@ -189,12 +189,14 @@
[88] = MSM_CPU_7X25A,
[89] = MSM_CPU_7X25A,
[96] = MSM_CPU_7X25A,
+ [135] = MSM_CPU_7X25A,
/* 7x27A IDs */
[90] = MSM_CPU_7X27A,
[91] = MSM_CPU_7X27A,
[92] = MSM_CPU_7X27A,
[97] = MSM_CPU_7X27A,
+ [136] = MSM_CPU_7X27A,
/* FSM9xxx ID */
[94] = FSM_CPU_9XXX,
diff --git a/drivers/Kconfig b/drivers/Kconfig
index 286a4d4..a73d713 100644
--- a/drivers/Kconfig
+++ b/drivers/Kconfig
@@ -148,4 +148,6 @@
source "drivers/gud/Kconfig"
+source "drivers/coresight/Kconfig"
+
endmenu
diff --git a/drivers/Makefile b/drivers/Makefile
index bea505c..bd18a62 100644
--- a/drivers/Makefile
+++ b/drivers/Makefile
@@ -140,3 +140,5 @@
#MobiCore
obj-$(CONFIG_MOBICORE_SUPPORT) += gud/
+
+obj-$(CONFIG_MSM_QDSS) += coresight/
diff --git a/drivers/coresight/Kconfig b/drivers/coresight/Kconfig
new file mode 100644
index 0000000..1219af1
--- /dev/null
+++ b/drivers/coresight/Kconfig
@@ -0,0 +1,32 @@
+config MSM_QDSS
+ bool "CoreSight tracing"
+ help
+ Enables support for CoreSight tracing. This uses CoreSight trace
+ components and buses to support both hardware (eg. processor ETM)
+ and hardware assisted software instrumentation based (eg. STM)
+ tracing.
+
+ For production builds, you should probably say 'N' here to avoid
+ potential power, performance and memory penalty.
+
+config MSM_QDSS_STM_DEFAULT_ENABLE
+ bool "Turn on CoreSight STM tracing by default"
+ depends on MSM_QDSS
+ help
+ Turns on CoreSight STM tracing (hardware assisted software
+ instrumentation based tracing) by default. Otherwise, tracing is
+ disabled by default but can be enabled via sysfs.
+
+ For production builds, you should probably say 'N' here to avoid
+ potential power, performance and memory penalty.
+
+config MSM_QDSS_ETM_DEFAULT_ENABLE
+ bool "Turn on CoreSight ETM tracing by default"
+ depends on MSM_QDSS
+ help
+ Turns on CoreSight ETM tracing (processor tracing) by default.
+ Otherwise, tracing is disabled by default but can be enabled via
+ sysfs.
+
+ For production builds, you should probably say 'N' here to avoid
+ potential power, performance and memory penalty.
diff --git a/drivers/coresight/Makefile b/drivers/coresight/Makefile
new file mode 100644
index 0000000..2ee2093
--- /dev/null
+++ b/drivers/coresight/Makefile
@@ -0,0 +1,2 @@
+
+obj-$(CONFIG_MSM_QDSS) += coresight.o coresight-etb.o coresight-tpiu.o coresight-funnel.o coresight-stm.o coresight-etm.o
diff --git a/drivers/coresight/coresight-etb.c b/drivers/coresight/coresight-etb.c
new file mode 100644
index 0000000..2bffae5
--- /dev/null
+++ b/drivers/coresight/coresight-etb.c
@@ -0,0 +1,451 @@
+/* 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
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/types.h>
+#include <linux/device.h>
+#include <linux/platform_device.h>
+#include <linux/io.h>
+#include <linux/err.h>
+#include <linux/fs.h>
+#include <linux/miscdevice.h>
+#include <linux/uaccess.h>
+#include <linux/slab.h>
+#include <linux/delay.h>
+#include <linux/mutex.h>
+#include <linux/clk.h>
+#include <linux/coresight.h>
+
+#include "coresight-priv.h"
+
+#define etb_writel(drvdata, val, off) __raw_writel((val), drvdata->base + off)
+#define etb_readl(drvdata, off) __raw_readl(drvdata->base + off)
+
+#define ETB_RAM_DEPTH_REG (0x004)
+#define ETB_STATUS_REG (0x00C)
+#define ETB_RAM_READ_DATA_REG (0x010)
+#define ETB_RAM_READ_POINTER (0x014)
+#define ETB_RAM_WRITE_POINTER (0x018)
+#define ETB_TRG (0x01C)
+#define ETB_CTL_REG (0x020)
+#define ETB_RWD_REG (0x024)
+#define ETB_FFSR (0x300)
+#define ETB_FFCR (0x304)
+#define ETB_ITMISCOP0 (0xEE0)
+#define ETB_ITTRFLINACK (0xEE4)
+#define ETB_ITTRFLIN (0xEE8)
+#define ETB_ITATBDATA0 (0xEEC)
+#define ETB_ITATBCTR2 (0xEF0)
+#define ETB_ITATBCTR1 (0xEF4)
+#define ETB_ITATBCTR0 (0xEF8)
+
+
+#define BYTES_PER_WORD 4
+#define ETB_SIZE_WORDS 4096
+#define FRAME_SIZE_WORDS 4
+
+#define ETB_LOCK() \
+do { \
+ mb(); \
+ etb_writel(drvdata, 0x0, CORESIGHT_LAR); \
+} while (0)
+#define ETB_UNLOCK() \
+do { \
+ etb_writel(drvdata, CORESIGHT_UNLOCK, CORESIGHT_LAR); \
+ mb(); \
+} while (0)
+
+struct etb_drvdata {
+ uint8_t *buf;
+ void __iomem *base;
+ bool enabled;
+ bool reading;
+ spinlock_t spinlock;
+ atomic_t in_use;
+ struct device *dev;
+ struct kobject *kobj;
+ struct clk *clk;
+ uint32_t trigger_cntr;
+};
+
+static struct etb_drvdata *drvdata;
+
+static void __etb_enable(void)
+{
+ int i;
+
+ ETB_UNLOCK();
+
+ etb_writel(drvdata, 0x0, ETB_RAM_WRITE_POINTER);
+ for (i = 0; i < ETB_SIZE_WORDS; i++)
+ etb_writel(drvdata, 0x0, ETB_RWD_REG);
+
+ etb_writel(drvdata, 0x0, ETB_RAM_WRITE_POINTER);
+ etb_writel(drvdata, 0x0, ETB_RAM_READ_POINTER);
+
+ etb_writel(drvdata, drvdata->trigger_cntr, ETB_TRG);
+ etb_writel(drvdata, BIT(13) | BIT(0), ETB_FFCR);
+ etb_writel(drvdata, BIT(0), ETB_CTL_REG);
+
+ ETB_LOCK();
+}
+
+int etb_enable(void)
+{
+ int ret;
+ unsigned long flags;
+
+ ret = clk_prepare_enable(drvdata->clk);
+ if (ret)
+ return ret;
+
+ spin_lock_irqsave(&drvdata->spinlock, flags);
+ __etb_enable();
+ drvdata->enabled = true;
+ dev_info(drvdata->dev, "ETB enabled\n");
+ spin_unlock_irqrestore(&drvdata->spinlock, flags);
+
+ return 0;
+}
+
+static void __etb_disable(void)
+{
+ int count;
+ uint32_t ffcr;
+
+ ETB_UNLOCK();
+
+ ffcr = etb_readl(drvdata, ETB_FFCR);
+ ffcr |= (BIT(12) | BIT(6));
+ etb_writel(drvdata, ffcr, ETB_FFCR);
+
+ for (count = TIMEOUT_US; BVAL(etb_readl(drvdata, ETB_FFCR), 6) != 0
+ && count > 0; count--)
+ udelay(1);
+ WARN(count == 0, "timeout while flushing DRVDATA, ETB_FFCR: %#x\n",
+ etb_readl(drvdata, ETB_FFCR));
+
+ etb_writel(drvdata, 0x0, ETB_CTL_REG);
+
+ for (count = TIMEOUT_US; BVAL(etb_readl(drvdata, ETB_FFSR), 1) != 1
+ && count > 0; count--)
+ udelay(1);
+ WARN(count == 0, "timeout while disabling DRVDATA, ETB_FFSR: %#x\n",
+ etb_readl(drvdata, ETB_FFSR));
+
+ ETB_LOCK();
+}
+
+void etb_disable(void)
+{
+ unsigned long flags;
+
+ spin_lock_irqsave(&drvdata->spinlock, flags);
+ __etb_disable();
+ drvdata->enabled = false;
+ dev_info(drvdata->dev, "ETB disabled\n");
+ spin_unlock_irqrestore(&drvdata->spinlock, flags);
+
+ clk_disable_unprepare(drvdata->clk);
+}
+
+static void __etb_dump(void)
+{
+ int i;
+ uint8_t *buf_ptr;
+ uint32_t read_data;
+ uint32_t read_ptr;
+ uint32_t write_ptr;
+ uint32_t frame_off;
+ uint32_t frame_endoff;
+
+ ETB_UNLOCK();
+
+ read_ptr = etb_readl(drvdata, ETB_RAM_READ_POINTER);
+ write_ptr = etb_readl(drvdata, ETB_RAM_WRITE_POINTER);
+
+ frame_off = write_ptr % FRAME_SIZE_WORDS;
+ frame_endoff = FRAME_SIZE_WORDS - frame_off;
+ if (frame_off) {
+ dev_err(drvdata->dev, "write_ptr: %lu not aligned to formatter "
+ "frame size\n", (unsigned long)write_ptr);
+ dev_err(drvdata->dev, "frameoff: %lu, frame_endoff: %lu\n",
+ (unsigned long)frame_off, (unsigned long)frame_endoff);
+ write_ptr += frame_endoff;
+ }
+
+ if ((etb_readl(drvdata, ETB_STATUS_REG) & BIT(0)) == 0)
+ etb_writel(drvdata, 0x0, ETB_RAM_READ_POINTER);
+ else
+ etb_writel(drvdata, write_ptr, ETB_RAM_READ_POINTER);
+
+ buf_ptr = drvdata->buf;
+ for (i = 0; i < ETB_SIZE_WORDS; i++) {
+ read_data = etb_readl(drvdata, ETB_RAM_READ_DATA_REG);
+ *buf_ptr++ = read_data >> 0;
+ *buf_ptr++ = read_data >> 8;
+ *buf_ptr++ = read_data >> 16;
+ *buf_ptr++ = read_data >> 24;
+ }
+
+ if (frame_off) {
+ buf_ptr -= (frame_endoff * BYTES_PER_WORD);
+ for (i = 0; i < frame_endoff; i++) {
+ *buf_ptr++ = 0x0;
+ *buf_ptr++ = 0x0;
+ *buf_ptr++ = 0x0;
+ *buf_ptr++ = 0x0;
+ }
+ }
+
+ etb_writel(drvdata, read_ptr, ETB_RAM_READ_POINTER);
+
+ ETB_LOCK();
+}
+
+void etb_dump(void)
+{
+ unsigned long flags;
+
+ spin_lock_irqsave(&drvdata->spinlock, flags);
+ if (drvdata->enabled) {
+ __etb_disable();
+ __etb_dump();
+ __etb_enable();
+
+ dev_info(drvdata->dev, "ETB dumped\n");
+ }
+ spin_unlock_irqrestore(&drvdata->spinlock, flags);
+}
+
+static int etb_open(struct inode *inode, struct file *file)
+{
+ if (atomic_cmpxchg(&drvdata->in_use, 0, 1))
+ return -EBUSY;
+
+ dev_dbg(drvdata->dev, "%s: successfully opened\n", __func__);
+ return 0;
+}
+
+static ssize_t etb_read(struct file *file, char __user *data,
+ size_t len, loff_t *ppos)
+{
+ if (drvdata->reading == false) {
+ etb_dump();
+ drvdata->reading = true;
+ }
+
+ if (*ppos + len > ETB_SIZE_WORDS * BYTES_PER_WORD)
+ len = ETB_SIZE_WORDS * BYTES_PER_WORD - *ppos;
+
+ if (copy_to_user(data, drvdata->buf + *ppos, len)) {
+ dev_dbg(drvdata->dev, "%s: copy_to_user failed\n", __func__);
+ return -EFAULT;
+ }
+
+ *ppos += len;
+
+ dev_dbg(drvdata->dev, "%s: %d bytes copied, %d bytes left\n",
+ __func__, len, (int) (ETB_SIZE_WORDS * BYTES_PER_WORD - *ppos));
+
+ return len;
+}
+
+static int etb_release(struct inode *inode, struct file *file)
+{
+ drvdata->reading = false;
+
+ atomic_set(&drvdata->in_use, 0);
+
+ dev_dbg(drvdata->dev, "%s: released\n", __func__);
+
+ return 0;
+}
+
+static const struct file_operations etb_fops = {
+ .owner = THIS_MODULE,
+ .open = etb_open,
+ .read = etb_read,
+ .release = etb_release,
+};
+
+static struct miscdevice etb_misc = {
+ .name = "msm_etb",
+ .minor = MISC_DYNAMIC_MINOR,
+ .fops = &etb_fops,
+};
+
+static ssize_t etb_show_trigger_cntr(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ unsigned long val = drvdata->trigger_cntr;
+ return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
+}
+
+static ssize_t etb_store_trigger_cntr(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t size)
+{
+ unsigned long val;
+
+ if (sscanf(buf, "%lx", &val) != 1)
+ return -EINVAL;
+
+ drvdata->trigger_cntr = val;
+ return size;
+}
+static DEVICE_ATTR(trigger_cntr, S_IRUGO | S_IWUSR, etb_show_trigger_cntr,
+ etb_store_trigger_cntr);
+
+static int __devinit etb_sysfs_init(void)
+{
+ int ret;
+
+ drvdata->kobj = kobject_create_and_add("etb", qdss_get_modulekobj());
+ if (!drvdata->kobj) {
+ dev_err(drvdata->dev, "failed to create ETB sysfs kobject\n");
+ ret = -ENOMEM;
+ goto err_create;
+ }
+
+ ret = sysfs_create_file(drvdata->kobj, &dev_attr_trigger_cntr.attr);
+ if (ret) {
+ dev_err(drvdata->dev, "failed to create ETB sysfs trigger_cntr"
+ " attribute\n");
+ goto err_file;
+ }
+
+ return 0;
+err_file:
+ kobject_put(drvdata->kobj);
+err_create:
+ return ret;
+}
+
+static void __devexit etb_sysfs_exit(void)
+{
+ sysfs_remove_file(drvdata->kobj, &dev_attr_trigger_cntr.attr);
+ kobject_put(drvdata->kobj);
+}
+
+static int __devinit etb_probe(struct platform_device *pdev)
+{
+ int ret;
+ struct resource *res;
+
+ drvdata = kzalloc(sizeof(*drvdata), GFP_KERNEL);
+ if (!drvdata) {
+ ret = -ENOMEM;
+ goto err_kzalloc_drvdata;
+ }
+
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ if (!res) {
+ ret = -EINVAL;
+ goto err_res;
+ }
+
+ drvdata->base = ioremap_nocache(res->start, resource_size(res));
+ if (!drvdata->base) {
+ ret = -EINVAL;
+ goto err_ioremap;
+ }
+
+ drvdata->dev = &pdev->dev;
+
+ spin_lock_init(&drvdata->spinlock);
+
+ drvdata->clk = clk_get(drvdata->dev, "core_clk");
+ if (IS_ERR(drvdata->clk)) {
+ ret = PTR_ERR(drvdata->clk);
+ goto err_clk_get;
+ }
+
+ ret = clk_set_rate(drvdata->clk, CORESIGHT_CLK_RATE_TRACE);
+ if (ret)
+ goto err_clk_rate;
+
+ ret = misc_register(&etb_misc);
+ if (ret)
+ goto err_misc;
+
+ drvdata->buf = kzalloc(ETB_SIZE_WORDS * BYTES_PER_WORD, GFP_KERNEL);
+ if (!drvdata->buf) {
+ ret = -ENOMEM;
+ goto err_alloc;
+ }
+
+ etb_sysfs_init();
+
+ dev_info(drvdata->dev, "ETB initialized\n");
+ return 0;
+
+err_alloc:
+ misc_deregister(&etb_misc);
+err_misc:
+err_clk_rate:
+ clk_put(drvdata->clk);
+err_clk_get:
+ iounmap(drvdata->base);
+err_ioremap:
+err_res:
+ kfree(drvdata);
+err_kzalloc_drvdata:
+ dev_err(drvdata->dev, "ETB init failed\n");
+ return ret;
+}
+
+static int __devexit etb_remove(struct platform_device *pdev)
+{
+ if (drvdata->enabled)
+ etb_disable();
+ etb_sysfs_exit();
+ kfree(drvdata->buf);
+ misc_deregister(&etb_misc);
+ clk_put(drvdata->clk);
+ iounmap(drvdata->base);
+ kfree(drvdata);
+
+ return 0;
+}
+
+static struct of_device_id etb_match[] = {
+ {.compatible = "qcom,msm-etb"},
+ {}
+};
+
+static struct platform_driver etb_driver = {
+ .probe = etb_probe,
+ .remove = __devexit_p(etb_remove),
+ .driver = {
+ .name = "msm_etb",
+ .owner = THIS_MODULE,
+ .of_match_table = etb_match,
+ },
+};
+
+static int __init etb_init(void)
+{
+ return platform_driver_register(&etb_driver);
+}
+module_init(etb_init);
+
+static void __exit etb_exit(void)
+{
+ platform_driver_unregister(&etb_driver);
+}
+module_exit(etb_exit);
+
+MODULE_LICENSE("GPL v2");
+MODULE_DESCRIPTION("CoreSight Embedded Trace Buffer driver");
diff --git a/drivers/coresight/coresight-etm.c b/drivers/coresight/coresight-etm.c
new file mode 100644
index 0000000..b3d2a16
--- /dev/null
+++ b/drivers/coresight/coresight-etm.c
@@ -0,0 +1,1646 @@
+/* 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
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/types.h>
+#include <linux/device.h>
+#include <linux/platform_device.h>
+#include <linux/io.h>
+#include <linux/err.h>
+#include <linux/fs.h>
+#include <linux/slab.h>
+#include <linux/delay.h>
+#include <linux/smp.h>
+#include <linux/wakelock.h>
+#include <linux/pm_qos.h>
+#include <linux/sysfs.h>
+#include <linux/stat.h>
+#include <linux/clk.h>
+#include <linux/coresight.h>
+#include <asm/sections.h>
+#include <mach/socinfo.h>
+
+#include "coresight-priv.h"
+
+#define etm_writel(drvdata, cpu, val, off) \
+ __raw_writel((val), drvdata->base + (SZ_4K * cpu) + off)
+#define etm_readl(drvdata, cpu, off) \
+ __raw_readl(drvdata->base + (SZ_4K * cpu) + off)
+
+/*
+ * Device registers:
+ * 0x000 - 0x2FC: Trace registers
+ * 0x300 - 0x314: Management registers
+ * 0x318 - 0xEFC: Trace registers
+ *
+ * Coresight registers
+ * 0xF00 - 0xF9C: Management registers
+ * 0xFA0 - 0xFA4: Management registers in PFTv1.0
+ * Trace registers in PFTv1.1
+ * 0xFA8 - 0xFFC: Management registers
+ */
+
+/* Trace registers (0x000-0x2FC) */
+#define ETMCR (0x000)
+#define ETMCCR (0x004)
+#define ETMTRIGGER (0x008)
+#define ETMSR (0x010)
+#define ETMSCR (0x014)
+#define ETMTSSCR (0x018)
+#define ETMTEEVR (0x020)
+#define ETMTECR1 (0x024)
+#define ETMFFLR (0x02C)
+#define ETMACVRn(n) (0x040 + (n * 4))
+#define ETMACTRn(n) (0x080 + (n * 4))
+#define ETMCNTRLDVRn(n) (0x140 + (n * 4))
+#define ETMCNTENRn(n) (0x150 + (n * 4))
+#define ETMCNTRLDEVRn(n) (0x160 + (n * 4))
+#define ETMCNTVRn(n) (0x170 + (n * 4))
+#define ETMSQ12EVR (0x180)
+#define ETMSQ21EVR (0x184)
+#define ETMSQ23EVR (0x188)
+#define ETMSQ31EVR (0x18C)
+#define ETMSQ32EVR (0x190)
+#define ETMSQ13EVR (0x194)
+#define ETMSQR (0x19C)
+#define ETMEXTOUTEVRn(n) (0x1A0 + (n * 4))
+#define ETMCIDCVRn(n) (0x1B0 + (n * 4))
+#define ETMCIDCMR (0x1BC)
+#define ETMIMPSPEC0 (0x1C0)
+#define ETMIMPSPEC1 (0x1C4)
+#define ETMIMPSPEC2 (0x1C8)
+#define ETMIMPSPEC3 (0x1CC)
+#define ETMIMPSPEC4 (0x1D0)
+#define ETMIMPSPEC5 (0x1D4)
+#define ETMIMPSPEC6 (0x1D8)
+#define ETMIMPSPEC7 (0x1DC)
+#define ETMSYNCFR (0x1E0)
+#define ETMIDR (0x1E4)
+#define ETMCCER (0x1E8)
+#define ETMEXTINSELR (0x1EC)
+#define ETMTESSEICR (0x1F0)
+#define ETMEIBCR (0x1F4)
+#define ETMTSEVR (0x1F8)
+#define ETMAUXCR (0x1FC)
+#define ETMTRACEIDR (0x200)
+#define ETMVMIDCVR (0x240)
+/* Management registers (0x300-0x314) */
+#define ETMOSLAR (0x300)
+#define ETMOSLSR (0x304)
+#define ETMOSSRR (0x308)
+#define ETMPDCR (0x310)
+#define ETMPDSR (0x314)
+
+#define ETM_MAX_ADDR_CMP (16)
+#define ETM_MAX_CNTR (4)
+#define ETM_MAX_CTXID_CMP (3)
+
+#define ETM_MODE_EXCLUDE BIT(0)
+#define ETM_MODE_CYCACC BIT(1)
+#define ETM_MODE_STALL BIT(2)
+#define ETM_MODE_TIMESTAMP BIT(3)
+#define ETM_MODE_CTXID BIT(4)
+#define ETM_MODE_ALL (0x1F)
+
+#define ETM_EVENT_MASK (0x1FFFF)
+#define ETM_SYNC_MASK (0xFFF)
+#define ETM_ALL_MASK (0xFFFFFFFF)
+
+#define ETM_SEQ_STATE_MAX_VAL (0x2)
+
+enum {
+ ETM_ADDR_TYPE_NONE,
+ ETM_ADDR_TYPE_SINGLE,
+ ETM_ADDR_TYPE_RANGE,
+ ETM_ADDR_TYPE_START,
+ ETM_ADDR_TYPE_STOP,
+};
+
+#define ETM_LOCK(cpu) \
+do { \
+ mb(); \
+ etm_writel(drvdata, cpu, 0x0, CORESIGHT_LAR); \
+} while (0)
+#define ETM_UNLOCK(cpu) \
+do { \
+ etm_writel(drvdata, cpu, CORESIGHT_UNLOCK, CORESIGHT_LAR); \
+ mb(); \
+} while (0)
+
+
+#ifdef MODULE_PARAM_PREFIX
+#undef MODULE_PARAM_PREFIX
+#endif
+#define MODULE_PARAM_PREFIX "coresight."
+
+#ifdef CONFIG_MSM_QDSS_ETM_DEFAULT_ENABLE
+static int etm_boot_enable = 1;
+#else
+static int etm_boot_enable;
+#endif
+module_param_named(
+ etm_boot_enable, etm_boot_enable, int, S_IRUGO
+);
+
+struct etm_drvdata {
+ void __iomem *base;
+ bool enabled;
+ struct wake_lock wake_lock;
+ struct pm_qos_request qos_req;
+ struct qdss_source *src;
+ struct mutex mutex;
+ struct device *dev;
+ struct kobject *kobj;
+ struct clk *clk;
+ uint8_t arch;
+ uint8_t nr_addr_cmp;
+ uint8_t nr_cntr;
+ uint8_t nr_ext_inp;
+ uint8_t nr_ext_out;
+ uint8_t nr_ctxid_cmp;
+ uint8_t reset;
+ uint32_t mode;
+ uint32_t ctrl;
+ uint32_t trigger_event;
+ uint32_t startstop_ctrl;
+ uint32_t enable_event;
+ uint32_t enable_ctrl1;
+ uint32_t fifofull_level;
+ uint8_t addr_idx;
+ uint32_t addr_val[ETM_MAX_ADDR_CMP];
+ uint32_t addr_acctype[ETM_MAX_ADDR_CMP];
+ uint32_t addr_type[ETM_MAX_ADDR_CMP];
+ uint8_t cntr_idx;
+ uint32_t cntr_rld_val[ETM_MAX_CNTR];
+ uint32_t cntr_event[ETM_MAX_CNTR];
+ uint32_t cntr_rld_event[ETM_MAX_CNTR];
+ uint32_t cntr_val[ETM_MAX_CNTR];
+ uint32_t seq_12_event;
+ uint32_t seq_21_event;
+ uint32_t seq_23_event;
+ uint32_t seq_31_event;
+ uint32_t seq_32_event;
+ uint32_t seq_13_event;
+ uint32_t seq_curr_state;
+ uint8_t ctxid_idx;
+ uint32_t ctxid_val[ETM_MAX_CTXID_CMP];
+ uint32_t ctxid_mask;
+ uint32_t sync_freq;
+ uint32_t timestamp_event;
+};
+
+static struct etm_drvdata *drvdata;
+
+
+/* ETM clock is derived from the processor clock and gets enabled on a
+ * logical OR of below items on Krait (pass2 onwards):
+ * 1.CPMR[ETMCLKEN] is 1
+ * 2.ETMCR[PD] is 0
+ * 3.ETMPDCR[PU] is 1
+ * 4.Reset is asserted (core or debug)
+ * 5.APB memory mapped requests (eg. EDAP access)
+ *
+ * 1., 2. and 3. above are permanent enables whereas 4. and 5. are temporary
+ * enables
+ *
+ * We rely on 5. to be able to access ETMCR and then use 2. above for ETM
+ * clock vote in the driver and the save-restore code uses 1. above
+ * for its vote
+ */
+static void etm_set_pwrdwn(int cpu)
+{
+ uint32_t etmcr;
+
+ etmcr = etm_readl(drvdata, cpu, ETMCR);
+ etmcr |= BIT(0);
+ etm_writel(drvdata, cpu, etmcr, ETMCR);
+}
+
+static void etm_clr_pwrdwn(int cpu)
+{
+ uint32_t etmcr;
+
+ etmcr = etm_readl(drvdata, cpu, ETMCR);
+ etmcr &= ~BIT(0);
+ etm_writel(drvdata, cpu, etmcr, ETMCR);
+}
+
+static void etm_set_prog(int cpu)
+{
+ uint32_t etmcr;
+ int count;
+
+ etmcr = etm_readl(drvdata, cpu, ETMCR);
+ etmcr |= BIT(10);
+ etm_writel(drvdata, cpu, etmcr, ETMCR);
+
+ for (count = TIMEOUT_US; BVAL(etm_readl(drvdata, cpu, ETMSR), 1) != 1
+ && count > 0; count--)
+ udelay(1);
+ WARN(count == 0, "timeout while setting prog bit, ETMSR: %#x\n",
+ etm_readl(drvdata, cpu, ETMSR));
+}
+
+static void etm_clr_prog(int cpu)
+{
+ uint32_t etmcr;
+ int count;
+
+ etmcr = etm_readl(drvdata, cpu, ETMCR);
+ etmcr &= ~BIT(10);
+ etm_writel(drvdata, cpu, etmcr, ETMCR);
+
+ for (count = TIMEOUT_US; BVAL(etm_readl(drvdata, cpu, ETMSR), 1) != 0
+ && count > 0; count--)
+ udelay(1);
+ WARN(count == 0, "timeout while clearing prog bit, ETMSR: %#x\n",
+ etm_readl(drvdata, cpu, ETMSR));
+}
+
+static void __etm_enable(int cpu)
+{
+ int i;
+
+ ETM_UNLOCK(cpu);
+ /* Vote for ETM power/clock enable */
+ etm_clr_pwrdwn(cpu);
+ etm_set_prog(cpu);
+
+ etm_writel(drvdata, cpu, drvdata->ctrl | BIT(10), ETMCR);
+ etm_writel(drvdata, cpu, drvdata->trigger_event, ETMTRIGGER);
+ etm_writel(drvdata, cpu, drvdata->startstop_ctrl, ETMTSSCR);
+ etm_writel(drvdata, cpu, drvdata->enable_event, ETMTEEVR);
+ etm_writel(drvdata, cpu, drvdata->enable_ctrl1, ETMTECR1);
+ etm_writel(drvdata, cpu, drvdata->fifofull_level, ETMFFLR);
+ for (i = 0; i < drvdata->nr_addr_cmp; i++) {
+ etm_writel(drvdata, cpu, drvdata->addr_val[i], ETMACVRn(i));
+ etm_writel(drvdata, cpu, drvdata->addr_acctype[i], ETMACTRn(i));
+ }
+ for (i = 0; i < drvdata->nr_cntr; i++) {
+ etm_writel(drvdata, cpu, drvdata->cntr_rld_val[i],
+ ETMCNTRLDVRn(i));
+ etm_writel(drvdata, cpu, drvdata->cntr_event[i], ETMCNTENRn(i));
+ etm_writel(drvdata, cpu, drvdata->cntr_rld_event[i],
+ ETMCNTRLDEVRn(i));
+ etm_writel(drvdata, cpu, drvdata->cntr_val[i], ETMCNTVRn(i));
+ }
+ etm_writel(drvdata, cpu, drvdata->seq_12_event, ETMSQ12EVR);
+ etm_writel(drvdata, cpu, drvdata->seq_21_event, ETMSQ21EVR);
+ etm_writel(drvdata, cpu, drvdata->seq_23_event, ETMSQ23EVR);
+ etm_writel(drvdata, cpu, drvdata->seq_31_event, ETMSQ31EVR);
+ etm_writel(drvdata, cpu, drvdata->seq_32_event, ETMSQ32EVR);
+ etm_writel(drvdata, cpu, drvdata->seq_13_event, ETMSQ13EVR);
+ etm_writel(drvdata, cpu, drvdata->seq_curr_state, ETMSQR);
+ for (i = 0; i < drvdata->nr_ext_out; i++)
+ etm_writel(drvdata, cpu, 0x0000406F, ETMEXTOUTEVRn(i));
+ for (i = 0; i < drvdata->nr_ctxid_cmp; i++)
+ etm_writel(drvdata, cpu, drvdata->ctxid_val[i], ETMCIDCVRn(i));
+ etm_writel(drvdata, cpu, drvdata->ctxid_mask, ETMCIDCMR);
+ etm_writel(drvdata, cpu, drvdata->sync_freq, ETMSYNCFR);
+ etm_writel(drvdata, cpu, 0x00000000, ETMEXTINSELR);
+ etm_writel(drvdata, cpu, drvdata->timestamp_event, ETMTSEVR);
+ etm_writel(drvdata, cpu, 0x00000000, ETMAUXCR);
+ etm_writel(drvdata, cpu, cpu+1, ETMTRACEIDR);
+ etm_writel(drvdata, cpu, 0x00000000, ETMVMIDCVR);
+
+ etm_clr_prog(cpu);
+ ETM_LOCK(cpu);
+}
+
+static int etm_enable(void)
+{
+ int ret, cpu;
+
+ if (drvdata->enabled) {
+ dev_err(drvdata->dev, "ETM tracing already enabled\n");
+ ret = -EPERM;
+ goto err;
+ }
+
+ wake_lock(&drvdata->wake_lock);
+ /* 1. causes all online cpus to come out of idle PC
+ * 2. prevents idle PC until save restore flag is enabled atomically
+ *
+ * we rely on the user to prevent hotplug on/off racing with this
+ * operation and to ensure cores where trace is expected to be turned
+ * on are already hotplugged on
+ */
+ pm_qos_update_request(&drvdata->qos_req, 0);
+
+ ret = clk_prepare_enable(drvdata->clk);
+ if (ret)
+ goto err_clk;
+
+ ret = qdss_enable(drvdata->src);
+ if (ret)
+ goto err_qdss;
+
+ for_each_online_cpu(cpu)
+ __etm_enable(cpu);
+
+ drvdata->enabled = true;
+
+ pm_qos_update_request(&drvdata->qos_req, PM_QOS_DEFAULT_VALUE);
+ wake_unlock(&drvdata->wake_lock);
+
+ dev_info(drvdata->dev, "ETM tracing enabled\n");
+ return 0;
+
+err_qdss:
+ clk_disable_unprepare(drvdata->clk);
+err_clk:
+ pm_qos_update_request(&drvdata->qos_req, PM_QOS_DEFAULT_VALUE);
+ wake_unlock(&drvdata->wake_lock);
+err:
+ return ret;
+}
+
+static void __etm_disable(int cpu)
+{
+ ETM_UNLOCK(cpu);
+ etm_set_prog(cpu);
+
+ /* program trace enable to low by using always false event */
+ etm_writel(drvdata, cpu, 0x6F | BIT(14), ETMTEEVR);
+
+ /* Vote for ETM power/clock disable */
+ etm_set_pwrdwn(cpu);
+ ETM_LOCK(cpu);
+}
+
+static int etm_disable(void)
+{
+ int ret, cpu;
+
+ if (!drvdata->enabled) {
+ dev_err(drvdata->dev, "ETM tracing already disabled\n");
+ ret = -EPERM;
+ goto err;
+ }
+
+ wake_lock(&drvdata->wake_lock);
+ /* 1. causes all online cpus to come out of idle PC
+ * 2. prevents idle PC until save restore flag is disabled atomically
+ *
+ * we rely on the user to prevent hotplug on/off racing with this
+ * operation and to ensure cores where trace is expected to be turned
+ * off are already hotplugged on
+ */
+ pm_qos_update_request(&drvdata->qos_req, 0);
+
+ for_each_online_cpu(cpu)
+ __etm_disable(cpu);
+
+ drvdata->enabled = false;
+
+ qdss_disable(drvdata->src);
+
+ clk_disable_unprepare(drvdata->clk);
+
+ pm_qos_update_request(&drvdata->qos_req, PM_QOS_DEFAULT_VALUE);
+ wake_unlock(&drvdata->wake_lock);
+
+ dev_info(drvdata->dev, "ETM tracing disabled\n");
+ return 0;
+err:
+ return ret;
+}
+
+/* Memory mapped writes to clear os lock not supported */
+static void etm_os_unlock(void *unused)
+{
+ unsigned long value = 0x0;
+
+ asm("mcr p14, 1, %0, c1, c0, 4\n\t" : : "r" (value));
+ asm("isb\n\t");
+}
+
+static ssize_t etm_show_enabled(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ unsigned long val = drvdata->enabled;
+ return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
+}
+
+static ssize_t etm_store_enabled(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t size)
+{
+ int ret = 0;
+ unsigned long val;
+
+ if (sscanf(buf, "%lx", &val) != 1)
+ return -EINVAL;
+
+ mutex_lock(&drvdata->mutex);
+ if (val)
+ ret = etm_enable();
+ else
+ ret = etm_disable();
+ mutex_unlock(&drvdata->mutex);
+
+ if (ret)
+ return ret;
+ return size;
+}
+static DEVICE_ATTR(enabled, S_IRUGO | S_IWUSR, etm_show_enabled,
+ etm_store_enabled);
+
+static ssize_t etm_show_nr_addr_cmp(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ unsigned long val = drvdata->nr_addr_cmp;
+ return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
+}
+static DEVICE_ATTR(nr_addr_cmp, S_IRUGO, etm_show_nr_addr_cmp, NULL);
+
+static ssize_t etm_show_nr_cntr(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ unsigned long val = drvdata->nr_cntr;
+ return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
+}
+static DEVICE_ATTR(nr_cntr, S_IRUGO, etm_show_nr_cntr, NULL);
+
+static ssize_t etm_show_nr_ctxid_cmp(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ unsigned long val = drvdata->nr_ctxid_cmp;
+ return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
+}
+static DEVICE_ATTR(nr_ctxid_cmp, S_IRUGO, etm_show_nr_ctxid_cmp, NULL);
+
+static ssize_t etm_show_reset(struct device *dev, struct device_attribute *attr,
+ char *buf)
+{
+ unsigned long val = drvdata->reset;
+ return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
+}
+
+/* Reset to trace everything i.e. exclude nothing. */
+static ssize_t etm_store_reset(struct device *dev,
+ struct device_attribute *attr, const char *buf,
+ size_t size)
+{
+ int i;
+ unsigned long val;
+
+ if (sscanf(buf, "%lx", &val) != 1)
+ return -EINVAL;
+
+ mutex_lock(&drvdata->mutex);
+ if (val) {
+ drvdata->mode = ETM_MODE_EXCLUDE;
+ drvdata->ctrl = 0x0;
+ if (cpu_is_krait_v1()) {
+ drvdata->mode |= ETM_MODE_CYCACC;
+ drvdata->ctrl |= BIT(12);
+ }
+ drvdata->trigger_event = 0x406F;
+ drvdata->startstop_ctrl = 0x0;
+ drvdata->enable_event = 0x6F;
+ drvdata->enable_ctrl1 = 0x1000000;
+ drvdata->fifofull_level = 0x28;
+ drvdata->addr_idx = 0x0;
+ for (i = 0; i < drvdata->nr_addr_cmp; i++) {
+ drvdata->addr_val[i] = 0x0;
+ drvdata->addr_acctype[i] = 0x0;
+ drvdata->addr_type[i] = ETM_ADDR_TYPE_NONE;
+ }
+ drvdata->cntr_idx = 0x0;
+ for (i = 0; i < drvdata->nr_cntr; i++) {
+ drvdata->cntr_rld_val[i] = 0x0;
+ drvdata->cntr_event[i] = 0x406F;
+ drvdata->cntr_rld_event[i] = 0x406F;
+ drvdata->cntr_val[i] = 0x0;
+ }
+ drvdata->seq_12_event = 0x406F;
+ drvdata->seq_21_event = 0x406F;
+ drvdata->seq_23_event = 0x406F;
+ drvdata->seq_31_event = 0x406F;
+ drvdata->seq_32_event = 0x406F;
+ drvdata->seq_13_event = 0x406F;
+ drvdata->seq_curr_state = 0x0;
+ drvdata->ctxid_idx = 0x0;
+ for (i = 0; i < drvdata->nr_ctxid_cmp; i++)
+ drvdata->ctxid_val[i] = 0x0;
+ drvdata->ctxid_mask = 0x0;
+ drvdata->sync_freq = 0x80;
+ drvdata->timestamp_event = 0x406F;
+ }
+ mutex_unlock(&drvdata->mutex);
+ return size;
+}
+static DEVICE_ATTR(reset, S_IRUGO | S_IWUSR, etm_show_reset, etm_store_reset);
+
+static ssize_t etm_show_mode(struct device *dev, struct device_attribute *attr,
+ char *buf)
+{
+ unsigned long val = drvdata->mode;
+ return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
+}
+
+static ssize_t etm_store_mode(struct device *dev, struct device_attribute *attr,
+ const char *buf, size_t size)
+{
+ unsigned long val;
+
+ if (sscanf(buf, "%lx", &val) != 1)
+ return -EINVAL;
+
+ mutex_lock(&drvdata->mutex);
+ drvdata->mode = val & ETM_MODE_ALL;
+
+ if (drvdata->mode & ETM_MODE_EXCLUDE)
+ drvdata->enable_ctrl1 |= BIT(24);
+ else
+ drvdata->enable_ctrl1 &= ~BIT(24);
+
+ if (drvdata->mode & ETM_MODE_CYCACC)
+ drvdata->ctrl |= BIT(12);
+ else
+ drvdata->ctrl &= ~BIT(12);
+
+ if (drvdata->mode & ETM_MODE_STALL)
+ drvdata->ctrl |= BIT(7);
+ else
+ drvdata->ctrl &= ~BIT(7);
+
+ if (drvdata->mode & ETM_MODE_TIMESTAMP)
+ drvdata->ctrl |= BIT(28);
+ else
+ drvdata->ctrl &= ~BIT(28);
+ if (drvdata->mode & ETM_MODE_CTXID)
+ drvdata->ctrl |= (BIT(14) | BIT(15));
+ else
+ drvdata->ctrl &= ~(BIT(14) | BIT(15));
+ mutex_unlock(&drvdata->mutex);
+
+ return size;
+}
+static DEVICE_ATTR(mode, S_IRUGO | S_IWUSR, etm_show_mode, etm_store_mode);
+
+static ssize_t etm_show_trigger_event(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ unsigned long val = drvdata->trigger_event;
+ return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
+}
+
+static ssize_t etm_store_trigger_event(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t size)
+{
+ unsigned long val;
+
+ if (sscanf(buf, "%lx", &val) != 1)
+ return -EINVAL;
+
+ drvdata->trigger_event = val & ETM_EVENT_MASK;
+ return size;
+}
+static DEVICE_ATTR(trigger_event, S_IRUGO | S_IWUSR, etm_show_trigger_event,
+ etm_store_trigger_event);
+
+static ssize_t etm_show_enable_event(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ unsigned long val = drvdata->enable_event;
+ return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
+}
+
+static ssize_t etm_store_enable_event(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t size)
+{
+ unsigned long val;
+
+ if (sscanf(buf, "%lx", &val) != 1)
+ return -EINVAL;
+
+ drvdata->enable_event = val & ETM_EVENT_MASK;
+ return size;
+}
+static DEVICE_ATTR(enable_event, S_IRUGO | S_IWUSR, etm_show_enable_event,
+ etm_store_enable_event);
+
+static ssize_t etm_show_fifofull_level(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ unsigned long val = drvdata->fifofull_level;
+ return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
+}
+
+static ssize_t etm_store_fifofull_level(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t size)
+{
+ unsigned long val;
+
+ if (sscanf(buf, "%lx", &val) != 1)
+ return -EINVAL;
+
+ drvdata->fifofull_level = val;
+ return size;
+}
+static DEVICE_ATTR(fifofull_level, S_IRUGO | S_IWUSR, etm_show_fifofull_level,
+ etm_store_fifofull_level);
+
+static ssize_t etm_show_addr_idx(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ unsigned long val = drvdata->addr_idx;
+ return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
+}
+
+static ssize_t etm_store_addr_idx(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t size)
+{
+ unsigned long val;
+
+ if (sscanf(buf, "%lx", &val) != 1)
+ return -EINVAL;
+ if (val >= drvdata->nr_addr_cmp)
+ return -EINVAL;
+
+ /* Use mutex to ensure index doesn't change while it gets dereferenced
+ * multiple times within a mutex block elsewhere.
+ */
+ mutex_lock(&drvdata->mutex);
+ drvdata->addr_idx = val;
+ mutex_unlock(&drvdata->mutex);
+ return size;
+}
+static DEVICE_ATTR(addr_idx, S_IRUGO | S_IWUSR, etm_show_addr_idx,
+ etm_store_addr_idx);
+
+static ssize_t etm_show_addr_single(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ unsigned long val;
+ uint8_t idx;
+
+ mutex_lock(&drvdata->mutex);
+ idx = drvdata->addr_idx;
+ if (!(drvdata->addr_type[idx] == ETM_ADDR_TYPE_NONE ||
+ drvdata->addr_type[idx] == ETM_ADDR_TYPE_SINGLE)) {
+ mutex_unlock(&drvdata->mutex);
+ return -EPERM;
+ }
+
+ val = drvdata->addr_val[idx];
+ mutex_unlock(&drvdata->mutex);
+ return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
+}
+
+static ssize_t etm_store_addr_single(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t size)
+{
+ unsigned long val;
+ uint8_t idx;
+
+ if (sscanf(buf, "%lx", &val) != 1)
+ return -EINVAL;
+
+ mutex_lock(&drvdata->mutex);
+ idx = drvdata->addr_idx;
+ if (!(drvdata->addr_type[idx] == ETM_ADDR_TYPE_NONE ||
+ drvdata->addr_type[idx] == ETM_ADDR_TYPE_SINGLE)) {
+ mutex_unlock(&drvdata->mutex);
+ return -EPERM;
+ }
+
+ drvdata->addr_val[idx] = val;
+ drvdata->addr_type[idx] = ETM_ADDR_TYPE_SINGLE;
+ mutex_unlock(&drvdata->mutex);
+ return size;
+}
+static DEVICE_ATTR(addr_single, S_IRUGO | S_IWUSR, etm_show_addr_single,
+ etm_store_addr_single);
+
+static ssize_t etm_show_addr_range(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ unsigned long val1, val2;
+ uint8_t idx;
+
+ mutex_lock(&drvdata->mutex);
+ idx = drvdata->addr_idx;
+ if (idx % 2 != 0) {
+ mutex_unlock(&drvdata->mutex);
+ return -EPERM;
+ }
+ if (!((drvdata->addr_type[idx] == ETM_ADDR_TYPE_NONE &&
+ drvdata->addr_type[idx + 1] == ETM_ADDR_TYPE_NONE) ||
+ (drvdata->addr_type[idx] == ETM_ADDR_TYPE_RANGE &&
+ drvdata->addr_type[idx + 1] == ETM_ADDR_TYPE_RANGE))) {
+ mutex_unlock(&drvdata->mutex);
+ return -EPERM;
+ }
+
+ val1 = drvdata->addr_val[idx];
+ val2 = drvdata->addr_val[idx + 1];
+ mutex_unlock(&drvdata->mutex);
+ return scnprintf(buf, PAGE_SIZE, "%#lx %#lx\n", val1, val2);
+}
+
+static ssize_t etm_store_addr_range(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t size)
+{
+ unsigned long val1, val2;
+ uint8_t idx;
+
+ if (sscanf(buf, "%lx %lx", &val1, &val2) != 2)
+ return -EINVAL;
+ /* lower address comparator cannot have a higher address value */
+ if (val1 > val2)
+ return -EINVAL;
+
+ mutex_lock(&drvdata->mutex);
+ idx = drvdata->addr_idx;
+ if (idx % 2 != 0) {
+ mutex_unlock(&drvdata->mutex);
+ return -EPERM;
+ }
+ if (!((drvdata->addr_type[idx] == ETM_ADDR_TYPE_NONE &&
+ drvdata->addr_type[idx + 1] == ETM_ADDR_TYPE_NONE) ||
+ (drvdata->addr_type[idx] == ETM_ADDR_TYPE_RANGE &&
+ drvdata->addr_type[idx + 1] == ETM_ADDR_TYPE_RANGE))) {
+ mutex_unlock(&drvdata->mutex);
+ return -EPERM;
+ }
+
+ drvdata->addr_val[idx] = val1;
+ drvdata->addr_type[idx] = ETM_ADDR_TYPE_RANGE;
+ drvdata->addr_val[idx + 1] = val2;
+ drvdata->addr_type[idx + 1] = ETM_ADDR_TYPE_RANGE;
+ drvdata->enable_ctrl1 |= (1 << (idx/2));
+ mutex_unlock(&drvdata->mutex);
+ return size;
+}
+static DEVICE_ATTR(addr_range, S_IRUGO | S_IWUSR, etm_show_addr_range,
+ etm_store_addr_range);
+
+static ssize_t etm_show_addr_start(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ unsigned long val;
+ uint8_t idx;
+
+ mutex_lock(&drvdata->mutex);
+ idx = drvdata->addr_idx;
+ if (!(drvdata->addr_type[idx] == ETM_ADDR_TYPE_NONE ||
+ drvdata->addr_type[idx] == ETM_ADDR_TYPE_START)) {
+ mutex_unlock(&drvdata->mutex);
+ return -EPERM;
+ }
+
+ val = drvdata->addr_val[idx];
+ mutex_unlock(&drvdata->mutex);
+ return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
+}
+
+static ssize_t etm_store_addr_start(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t size)
+{
+ unsigned long val;
+ uint8_t idx;
+
+ if (sscanf(buf, "%lx", &val) != 1)
+ return -EINVAL;
+
+ mutex_lock(&drvdata->mutex);
+ idx = drvdata->addr_idx;
+ if (!(drvdata->addr_type[idx] == ETM_ADDR_TYPE_NONE ||
+ drvdata->addr_type[idx] == ETM_ADDR_TYPE_START)) {
+ mutex_unlock(&drvdata->mutex);
+ return -EPERM;
+ }
+
+ drvdata->addr_val[idx] = val;
+ drvdata->addr_type[idx] = ETM_ADDR_TYPE_START;
+ drvdata->startstop_ctrl |= (1 << idx);
+ drvdata->enable_ctrl1 |= BIT(25);
+ mutex_unlock(&drvdata->mutex);
+ return size;
+}
+static DEVICE_ATTR(addr_start, S_IRUGO | S_IWUSR, etm_show_addr_start,
+ etm_store_addr_start);
+
+static ssize_t etm_show_addr_stop(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ unsigned long val;
+ uint8_t idx;
+
+ mutex_lock(&drvdata->mutex);
+ idx = drvdata->addr_idx;
+ if (!(drvdata->addr_type[idx] == ETM_ADDR_TYPE_NONE ||
+ drvdata->addr_type[idx] == ETM_ADDR_TYPE_STOP)) {
+ mutex_unlock(&drvdata->mutex);
+ return -EPERM;
+ }
+
+ val = drvdata->addr_val[idx];
+ mutex_unlock(&drvdata->mutex);
+ return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
+}
+
+static ssize_t etm_store_addr_stop(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t size)
+{
+ unsigned long val;
+ uint8_t idx;
+
+ if (sscanf(buf, "%lx", &val) != 1)
+ return -EINVAL;
+
+ mutex_lock(&drvdata->mutex);
+ idx = drvdata->addr_idx;
+ if (!(drvdata->addr_type[idx] == ETM_ADDR_TYPE_NONE ||
+ drvdata->addr_type[idx] == ETM_ADDR_TYPE_STOP)) {
+ mutex_unlock(&drvdata->mutex);
+ return -EPERM;
+ }
+
+ drvdata->addr_val[idx] = val;
+ drvdata->addr_type[idx] = ETM_ADDR_TYPE_STOP;
+ drvdata->startstop_ctrl |= (1 << (idx + 16));
+ drvdata->enable_ctrl1 |= BIT(25);
+ mutex_unlock(&drvdata->mutex);
+ return size;
+}
+static DEVICE_ATTR(addr_stop, S_IRUGO | S_IWUSR, etm_show_addr_stop,
+ etm_store_addr_stop);
+
+static ssize_t etm_show_addr_acctype(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ unsigned long val;
+
+ mutex_lock(&drvdata->mutex);
+ val = drvdata->addr_acctype[drvdata->addr_idx];
+ mutex_unlock(&drvdata->mutex);
+ return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
+}
+
+static ssize_t etm_store_addr_acctype(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t size)
+{
+ unsigned long val;
+
+ if (sscanf(buf, "%lx", &val) != 1)
+ return -EINVAL;
+
+ mutex_lock(&drvdata->mutex);
+ drvdata->addr_acctype[drvdata->addr_idx] = val;
+ mutex_unlock(&drvdata->mutex);
+ return size;
+}
+static DEVICE_ATTR(addr_acctype, S_IRUGO | S_IWUSR, etm_show_addr_acctype,
+ etm_store_addr_acctype);
+
+static ssize_t etm_show_cntr_idx(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ unsigned long val = drvdata->addr_idx;
+ return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
+}
+
+static ssize_t etm_store_cntr_idx(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t size)
+{
+ unsigned long val;
+
+ if (sscanf(buf, "%lx", &val) != 1)
+ return -EINVAL;
+ if (val >= drvdata->nr_cntr)
+ return -EINVAL;
+
+ /* Use mutex to ensure index doesn't change while it gets dereferenced
+ * multiple times within a mutex block elsewhere.
+ */
+ mutex_lock(&drvdata->mutex);
+ drvdata->cntr_idx = val;
+ mutex_unlock(&drvdata->mutex);
+ return size;
+}
+static DEVICE_ATTR(cntr_idx, S_IRUGO | S_IWUSR, etm_show_cntr_idx,
+ etm_store_cntr_idx);
+
+static ssize_t etm_show_cntr_rld_val(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ unsigned long val;
+ mutex_lock(&drvdata->mutex);
+ val = drvdata->cntr_rld_val[drvdata->cntr_idx];
+ mutex_unlock(&drvdata->mutex);
+ return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
+}
+
+static ssize_t etm_store_cntr_rld_val(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t size)
+{
+ unsigned long val;
+
+ if (sscanf(buf, "%lx", &val) != 1)
+ return -EINVAL;
+
+ mutex_lock(&drvdata->mutex);
+ drvdata->cntr_rld_val[drvdata->cntr_idx] = val;
+ mutex_unlock(&drvdata->mutex);
+ return size;
+}
+static DEVICE_ATTR(cntr_rld_val, S_IRUGO | S_IWUSR, etm_show_cntr_rld_val,
+ etm_store_cntr_rld_val);
+
+static ssize_t etm_show_cntr_event(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ unsigned long val;
+
+ mutex_lock(&drvdata->mutex);
+ val = drvdata->cntr_event[drvdata->cntr_idx];
+ mutex_unlock(&drvdata->mutex);
+ return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
+}
+
+static ssize_t etm_store_cntr_event(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t size)
+{
+ unsigned long val;
+
+ if (sscanf(buf, "%lx", &val) != 1)
+ return -EINVAL;
+
+ mutex_lock(&drvdata->mutex);
+ drvdata->cntr_event[drvdata->cntr_idx] = val & ETM_EVENT_MASK;
+ mutex_unlock(&drvdata->mutex);
+ return size;
+}
+static DEVICE_ATTR(cntr_event, S_IRUGO | S_IWUSR, etm_show_cntr_event,
+ etm_store_cntr_event);
+
+static ssize_t etm_show_cntr_rld_event(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ unsigned long val;
+
+ mutex_lock(&drvdata->mutex);
+ val = drvdata->cntr_rld_event[drvdata->cntr_idx];
+ mutex_unlock(&drvdata->mutex);
+ return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
+}
+
+static ssize_t etm_store_cntr_rld_event(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t size)
+{
+ unsigned long val;
+
+ if (sscanf(buf, "%lx", &val) != 1)
+ return -EINVAL;
+
+ mutex_lock(&drvdata->mutex);
+ drvdata->cntr_rld_event[drvdata->cntr_idx] = val & ETM_EVENT_MASK;
+ mutex_unlock(&drvdata->mutex);
+ return size;
+}
+static DEVICE_ATTR(cntr_rld_event, S_IRUGO | S_IWUSR, etm_show_cntr_rld_event,
+ etm_store_cntr_rld_event);
+
+static ssize_t etm_show_cntr_val(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ unsigned long val;
+
+ mutex_lock(&drvdata->mutex);
+ val = drvdata->cntr_val[drvdata->cntr_idx];
+ mutex_unlock(&drvdata->mutex);
+ return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
+}
+
+static ssize_t etm_store_cntr_val(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t size)
+{
+ unsigned long val;
+
+ if (sscanf(buf, "%lx", &val) != 1)
+ return -EINVAL;
+
+ mutex_lock(&drvdata->mutex);
+ drvdata->cntr_val[drvdata->cntr_idx] = val;
+ mutex_unlock(&drvdata->mutex);
+ return size;
+}
+static DEVICE_ATTR(cntr_val, S_IRUGO | S_IWUSR, etm_show_cntr_val,
+ etm_store_cntr_val);
+
+static ssize_t etm_show_seq_12_event(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ unsigned long val = drvdata->seq_12_event;
+ return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
+}
+
+static ssize_t etm_store_seq_12_event(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t size)
+{
+ unsigned long val;
+
+ if (sscanf(buf, "%lx", &val) != 1)
+ return -EINVAL;
+
+ drvdata->seq_12_event = val & ETM_EVENT_MASK;
+ return size;
+}
+static DEVICE_ATTR(seq_12_event, S_IRUGO | S_IWUSR, etm_show_seq_12_event,
+ etm_store_seq_12_event);
+
+static ssize_t etm_show_seq_21_event(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ unsigned long val = drvdata->seq_21_event;
+ return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
+}
+
+static ssize_t etm_store_seq_21_event(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t size)
+{
+ unsigned long val;
+
+ if (sscanf(buf, "%lx", &val) != 1)
+ return -EINVAL;
+
+ drvdata->seq_21_event = val & ETM_EVENT_MASK;
+ return size;
+}
+static DEVICE_ATTR(seq_21_event, S_IRUGO | S_IWUSR, etm_show_seq_21_event,
+ etm_store_seq_21_event);
+
+static ssize_t etm_show_seq_23_event(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ unsigned long val = drvdata->seq_23_event;
+ return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
+}
+
+static ssize_t etm_store_seq_23_event(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t size)
+{
+ unsigned long val;
+
+ if (sscanf(buf, "%lx", &val) != 1)
+ return -EINVAL;
+
+ drvdata->seq_23_event = val & ETM_EVENT_MASK;
+ return size;
+}
+static DEVICE_ATTR(seq_23_event, S_IRUGO | S_IWUSR, etm_show_seq_23_event,
+ etm_store_seq_23_event);
+
+static ssize_t etm_show_seq_31_event(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ unsigned long val = drvdata->seq_31_event;
+ return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
+}
+
+static ssize_t etm_store_seq_31_event(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t size)
+{
+ unsigned long val;
+
+ if (sscanf(buf, "%lx", &val) != 1)
+ return -EINVAL;
+
+ drvdata->seq_31_event = val & ETM_EVENT_MASK;
+ return size;
+}
+static DEVICE_ATTR(seq_31_event, S_IRUGO | S_IWUSR, etm_show_seq_31_event,
+ etm_store_seq_31_event);
+
+static ssize_t etm_show_seq_32_event(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ unsigned long val = drvdata->seq_32_event;
+ return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
+}
+
+static ssize_t etm_store_seq_32_event(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t size)
+{
+ unsigned long val;
+
+ if (sscanf(buf, "%lx", &val) != 1)
+ return -EINVAL;
+
+ drvdata->seq_32_event = val & ETM_EVENT_MASK;
+ return size;
+}
+static DEVICE_ATTR(seq_32_event, S_IRUGO | S_IWUSR, etm_show_seq_32_event,
+ etm_store_seq_32_event);
+
+static ssize_t etm_show_seq_13_event(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ unsigned long val = drvdata->seq_13_event;
+ return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
+}
+
+static ssize_t etm_store_seq_13_event(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t size)
+{
+ unsigned long val;
+
+ if (sscanf(buf, "%lx", &val) != 1)
+ return -EINVAL;
+
+ drvdata->seq_13_event = val & ETM_EVENT_MASK;
+ return size;
+}
+static DEVICE_ATTR(seq_13_event, S_IRUGO | S_IWUSR, etm_show_seq_13_event,
+ etm_store_seq_13_event);
+
+static ssize_t etm_show_seq_curr_state(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ unsigned long val = drvdata->seq_curr_state;
+ return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
+}
+
+static ssize_t etm_store_seq_curr_state(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t size)
+{
+ unsigned long val;
+
+ if (sscanf(buf, "%lx", &val) != 1)
+ return -EINVAL;
+ if (val > ETM_SEQ_STATE_MAX_VAL)
+ return -EINVAL;
+
+ drvdata->seq_curr_state = val;
+ return size;
+}
+static DEVICE_ATTR(seq_curr_state, S_IRUGO | S_IWUSR, etm_show_seq_curr_state,
+ etm_store_seq_curr_state);
+
+static ssize_t etm_show_ctxid_idx(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ unsigned long val = drvdata->ctxid_idx;
+ return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
+}
+
+static ssize_t etm_store_ctxid_idx(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t size)
+{
+ unsigned long val;
+
+ if (sscanf(buf, "%lx", &val) != 1)
+ return -EINVAL;
+ if (val >= drvdata->nr_ctxid_cmp)
+ return -EINVAL;
+
+ /* Use mutex to ensure index doesn't change while it gets dereferenced
+ * multiple times within a mutex block elsewhere.
+ */
+ mutex_lock(&drvdata->mutex);
+ drvdata->ctxid_idx = val;
+ mutex_unlock(&drvdata->mutex);
+ return size;
+}
+static DEVICE_ATTR(ctxid_idx, S_IRUGO | S_IWUSR, etm_show_ctxid_idx,
+ etm_store_ctxid_idx);
+
+static ssize_t etm_show_ctxid_val(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ unsigned long val;
+
+ mutex_lock(&drvdata->mutex);
+ val = drvdata->ctxid_val[drvdata->ctxid_idx];
+ mutex_unlock(&drvdata->mutex);
+ return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
+}
+
+static ssize_t etm_store_ctxid_val(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t size)
+{
+ unsigned long val;
+
+ if (sscanf(buf, "%lx", &val) != 1)
+ return -EINVAL;
+
+ mutex_lock(&drvdata->mutex);
+ drvdata->ctxid_val[drvdata->ctxid_idx] = val;
+ mutex_unlock(&drvdata->mutex);
+ return size;
+}
+static DEVICE_ATTR(ctxid_val, S_IRUGO | S_IWUSR, etm_show_ctxid_val,
+ etm_store_ctxid_val);
+
+static ssize_t etm_show_ctxid_mask(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ unsigned long val = drvdata->ctxid_mask;
+ return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
+}
+
+static ssize_t etm_store_ctxid_mask(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t size)
+{
+ unsigned long val;
+
+ if (sscanf(buf, "%lx", &val) != 1)
+ return -EINVAL;
+
+ drvdata->ctxid_mask = val;
+ return size;
+}
+static DEVICE_ATTR(ctxid_mask, S_IRUGO | S_IWUSR, etm_show_ctxid_mask,
+ etm_store_ctxid_mask);
+
+static ssize_t etm_show_sync_freq(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ unsigned long val = drvdata->sync_freq;
+ return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
+}
+
+static ssize_t etm_store_sync_freq(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t size)
+{
+ unsigned long val;
+
+ if (sscanf(buf, "%lx", &val) != 1)
+ return -EINVAL;
+
+ drvdata->sync_freq = val & ETM_SYNC_MASK;
+ return size;
+}
+static DEVICE_ATTR(sync_freq, S_IRUGO | S_IWUSR, etm_show_sync_freq,
+ etm_store_sync_freq);
+
+static ssize_t etm_show_timestamp_event(struct device *dev,
+ struct device_attribute *attr,
+ char *buf)
+{
+ unsigned long val = drvdata->timestamp_event;
+ return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
+}
+
+static ssize_t etm_store_timestamp_event(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t size)
+{
+ unsigned long val;
+
+ if (sscanf(buf, "%lx", &val) != 1)
+ return -EINVAL;
+
+ drvdata->timestamp_event = val & ETM_EVENT_MASK;
+ return size;
+}
+static DEVICE_ATTR(timestamp_event, S_IRUGO | S_IWUSR, etm_show_timestamp_event,
+ etm_store_timestamp_event);
+
+static struct attribute *etm_attrs[] = {
+ &dev_attr_nr_addr_cmp.attr,
+ &dev_attr_nr_cntr.attr,
+ &dev_attr_nr_ctxid_cmp.attr,
+ &dev_attr_reset.attr,
+ &dev_attr_mode.attr,
+ &dev_attr_trigger_event.attr,
+ &dev_attr_enable_event.attr,
+ &dev_attr_fifofull_level.attr,
+ &dev_attr_addr_idx.attr,
+ &dev_attr_addr_single.attr,
+ &dev_attr_addr_range.attr,
+ &dev_attr_addr_start.attr,
+ &dev_attr_addr_stop.attr,
+ &dev_attr_addr_acctype.attr,
+ &dev_attr_cntr_idx.attr,
+ &dev_attr_cntr_rld_val.attr,
+ &dev_attr_cntr_event.attr,
+ &dev_attr_cntr_rld_event.attr,
+ &dev_attr_cntr_val.attr,
+ &dev_attr_seq_12_event.attr,
+ &dev_attr_seq_21_event.attr,
+ &dev_attr_seq_23_event.attr,
+ &dev_attr_seq_31_event.attr,
+ &dev_attr_seq_32_event.attr,
+ &dev_attr_seq_13_event.attr,
+ &dev_attr_seq_curr_state.attr,
+ &dev_attr_ctxid_idx.attr,
+ &dev_attr_ctxid_val.attr,
+ &dev_attr_ctxid_mask.attr,
+ &dev_attr_sync_freq.attr,
+ &dev_attr_timestamp_event.attr,
+ NULL,
+};
+
+static struct attribute_group etm_attr_grp = {
+ .attrs = etm_attrs,
+};
+
+static int __devinit etm_sysfs_init(void)
+{
+ int ret;
+
+ drvdata->kobj = kobject_create_and_add("etm", qdss_get_modulekobj());
+ if (!drvdata->kobj) {
+ dev_err(drvdata->dev, "failed to create ETM sysfs kobject\n");
+ ret = -ENOMEM;
+ goto err_create;
+ }
+
+ ret = sysfs_create_file(drvdata->kobj, &dev_attr_enabled.attr);
+ if (ret) {
+ dev_err(drvdata->dev, "failed to create ETM sysfs enabled"
+ " attribute\n");
+ goto err_file;
+ }
+
+ if (sysfs_create_group(drvdata->kobj, &etm_attr_grp))
+ dev_err(drvdata->dev, "failed to create ETM sysfs group\n");
+
+ return 0;
+err_file:
+ kobject_put(drvdata->kobj);
+err_create:
+ return ret;
+}
+
+static void __devexit etm_sysfs_exit(void)
+{
+ sysfs_remove_group(drvdata->kobj, &etm_attr_grp);
+ sysfs_remove_file(drvdata->kobj, &dev_attr_enabled.attr);
+ kobject_put(drvdata->kobj);
+}
+
+static bool __devinit etm_arch_supported(uint8_t arch)
+{
+ switch (arch) {
+ case PFT_ARCH_V1_1:
+ break;
+ default:
+ return false;
+ }
+ return true;
+}
+
+static int __devinit etm_init_arch_data(void)
+{
+ int ret;
+ /* use cpu 0 for setup */
+ int cpu = 0;
+ uint32_t etmidr;
+ uint32_t etmccr;
+
+ /* Unlock OS lock first to allow memory mapped reads and writes */
+ etm_os_unlock(NULL);
+ smp_call_function(etm_os_unlock, NULL, 1);
+ ETM_UNLOCK(cpu);
+ /* Vote for ETM power/clock enable */
+ etm_clr_pwrdwn(cpu);
+ /* Set prog bit. It will be set from reset but this is included to
+ * ensure it is set
+ */
+ etm_set_prog(cpu);
+
+ /* find all capabilities */
+ etmidr = etm_readl(drvdata, cpu, ETMIDR);
+ drvdata->arch = BMVAL(etmidr, 4, 11);
+ if (etm_arch_supported(drvdata->arch) == false) {
+ ret = -EINVAL;
+ goto err;
+ }
+
+ etmccr = etm_readl(drvdata, cpu, ETMCCR);
+ drvdata->nr_addr_cmp = BMVAL(etmccr, 0, 3) * 2;
+ drvdata->nr_cntr = BMVAL(etmccr, 13, 15);
+ drvdata->nr_ext_inp = BMVAL(etmccr, 17, 19);
+ drvdata->nr_ext_out = BMVAL(etmccr, 20, 22);
+ drvdata->nr_ctxid_cmp = BMVAL(etmccr, 24, 25);
+
+ /* Vote for ETM power/clock disable */
+ etm_set_pwrdwn(cpu);
+ ETM_LOCK(cpu);
+
+ return 0;
+err:
+ return ret;
+}
+
+static void __devinit etm_init_default_data(void)
+{
+ int i;
+
+ drvdata->trigger_event = 0x406F;
+ drvdata->enable_event = 0x6F;
+ drvdata->enable_ctrl1 = 0x1;
+ drvdata->fifofull_level = 0x28;
+ if (drvdata->nr_addr_cmp >= 2) {
+ drvdata->addr_val[0] = (uint32_t) _stext;
+ drvdata->addr_val[1] = (uint32_t) _etext;
+ drvdata->addr_type[0] = ETM_ADDR_TYPE_RANGE;
+ drvdata->addr_type[1] = ETM_ADDR_TYPE_RANGE;
+ }
+ for (i = 0; i < drvdata->nr_cntr; i++) {
+ drvdata->cntr_event[i] = 0x406F;
+ drvdata->cntr_rld_event[i] = 0x406F;
+ }
+ drvdata->seq_12_event = 0x406F;
+ drvdata->seq_21_event = 0x406F;
+ drvdata->seq_23_event = 0x406F;
+ drvdata->seq_31_event = 0x406F;
+ drvdata->seq_32_event = 0x406F;
+ drvdata->seq_13_event = 0x406F;
+ drvdata->sync_freq = 0x80;
+ drvdata->timestamp_event = 0x406F;
+
+ /* Overrides for Krait pass1 */
+ if (cpu_is_krait_v1()) {
+ /* Krait pass1 doesn't support include filtering and non-cycle
+ * accurate tracing
+ */
+ drvdata->mode = (ETM_MODE_EXCLUDE | ETM_MODE_CYCACC);
+ drvdata->ctrl = 0x1000;
+ drvdata->enable_ctrl1 = 0x1000000;
+ for (i = 0; i < drvdata->nr_addr_cmp; i++) {
+ drvdata->addr_val[i] = 0x0;
+ drvdata->addr_acctype[i] = 0x0;
+ drvdata->addr_type[i] = ETM_ADDR_TYPE_NONE;
+ }
+ }
+}
+
+static int __devinit etm_probe(struct platform_device *pdev)
+{
+ int ret;
+ struct resource *res;
+
+ drvdata = kzalloc(sizeof(*drvdata), GFP_KERNEL);
+ if (!drvdata) {
+ ret = -ENOMEM;
+ goto err_kzalloc_drvdata;
+ }
+
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ if (!res) {
+ ret = -EINVAL;
+ goto err_res;
+ }
+
+ drvdata->base = ioremap_nocache(res->start, resource_size(res));
+ if (!drvdata->base) {
+ ret = -EINVAL;
+ goto err_ioremap;
+ }
+
+ drvdata->dev = &pdev->dev;
+
+ mutex_init(&drvdata->mutex);
+ wake_lock_init(&drvdata->wake_lock, WAKE_LOCK_SUSPEND, "msm_etm");
+ pm_qos_add_request(&drvdata->qos_req, PM_QOS_CPU_DMA_LATENCY,
+ PM_QOS_DEFAULT_VALUE);
+ drvdata->src = qdss_get("msm_etm");
+ if (IS_ERR(drvdata->src)) {
+ ret = PTR_ERR(drvdata->src);
+ goto err_qdssget;
+ }
+
+ drvdata->clk = clk_get(drvdata->dev, "core_clk");
+ if (IS_ERR(drvdata->clk)) {
+ ret = PTR_ERR(drvdata->clk);
+ goto err_clk_get;
+ }
+
+ ret = clk_set_rate(drvdata->clk, CORESIGHT_CLK_RATE_TRACE);
+ if (ret)
+ goto err_clk_rate;
+
+ ret = clk_prepare_enable(drvdata->clk);
+ if (ret)
+ goto err_clk_enable;
+
+ ret = etm_init_arch_data();
+ if (ret)
+ goto err_arch;
+
+ etm_init_default_data();
+
+ ret = etm_sysfs_init();
+ if (ret)
+ goto err_sysfs;
+
+ drvdata->enabled = false;
+
+ clk_disable_unprepare(drvdata->clk);
+
+ dev_info(drvdata->dev, "ETM initialized\n");
+
+ if (etm_boot_enable)
+ etm_enable();
+
+ return 0;
+
+err_sysfs:
+err_arch:
+ clk_disable_unprepare(drvdata->clk);
+err_clk_enable:
+err_clk_rate:
+ clk_put(drvdata->clk);
+err_clk_get:
+ qdss_put(drvdata->src);
+err_qdssget:
+ pm_qos_remove_request(&drvdata->qos_req);
+ wake_lock_destroy(&drvdata->wake_lock);
+ mutex_destroy(&drvdata->mutex);
+ iounmap(drvdata->base);
+err_ioremap:
+err_res:
+ kfree(drvdata);
+err_kzalloc_drvdata:
+ dev_err(drvdata->dev, "ETM init failed\n");
+ return ret;
+}
+
+static int __devexit etm_remove(struct platform_device *pdev)
+{
+ if (drvdata->enabled)
+ etm_disable();
+ etm_sysfs_exit();
+ clk_put(drvdata->clk);
+ qdss_put(drvdata->src);
+ pm_qos_remove_request(&drvdata->qos_req);
+ wake_lock_destroy(&drvdata->wake_lock);
+ mutex_destroy(&drvdata->mutex);
+ iounmap(drvdata->base);
+ kfree(drvdata);
+
+ return 0;
+}
+
+static struct of_device_id etm_match[] = {
+ {.compatible = "qcom,msm-etm"},
+ {}
+};
+
+static struct platform_driver etm_driver = {
+ .probe = etm_probe,
+ .remove = __devexit_p(etm_remove),
+ .driver = {
+ .name = "msm_etm",
+ .owner = THIS_MODULE,
+ .of_match_table = etm_match,
+ },
+};
+
+int __init etm_init(void)
+{
+ return platform_driver_register(&etm_driver);
+}
+module_init(etm_init);
+
+void __exit etm_exit(void)
+{
+ platform_driver_unregister(&etm_driver);
+}
+module_exit(etm_exit);
+
+MODULE_LICENSE("GPL v2");
+MODULE_DESCRIPTION("CoreSight Program Flow Trace driver");
diff --git a/drivers/coresight/coresight-funnel.c b/drivers/coresight/coresight-funnel.c
new file mode 100644
index 0000000..79a27f4
--- /dev/null
+++ b/drivers/coresight/coresight-funnel.c
@@ -0,0 +1,275 @@
+/* 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
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/types.h>
+#include <linux/device.h>
+#include <linux/platform_device.h>
+#include <linux/io.h>
+#include <linux/err.h>
+#include <linux/slab.h>
+#include <linux/clk.h>
+#include <linux/coresight.h>
+
+#include "coresight-priv.h"
+
+#define funnel_writel(drvdata, id, val, off) \
+ __raw_writel((val), drvdata->base + (SZ_4K * id) + off)
+#define funnel_readl(drvdata, id, off) \
+ __raw_readl(drvdata->base + (SZ_4K * id) + off)
+
+#define FUNNEL_FUNCTL (0x000)
+#define FUNNEL_PRICTL (0x004)
+#define FUNNEL_ITATBDATA0 (0xEEC)
+#define FUNNEL_ITATBCTR2 (0xEF0)
+#define FUNNEL_ITATBCTR1 (0xEF4)
+#define FUNNEL_ITATBCTR0 (0xEF8)
+
+
+#define FUNNEL_LOCK(id) \
+do { \
+ mb(); \
+ funnel_writel(drvdata, id, 0x0, CORESIGHT_LAR); \
+} while (0)
+#define FUNNEL_UNLOCK(id) \
+do { \
+ funnel_writel(drvdata, id, CORESIGHT_UNLOCK, CORESIGHT_LAR); \
+ mb(); \
+} while (0)
+
+#define FUNNEL_HOLDTIME_MASK (0xF00)
+#define FUNNEL_HOLDTIME_SHFT (0x8)
+#define FUNNEL_HOLDTIME (0x7 << FUNNEL_HOLDTIME_SHFT)
+
+struct funnel_drvdata {
+ void __iomem *base;
+ bool enabled;
+ struct mutex mutex;
+ struct device *dev;
+ struct kobject *kobj;
+ struct clk *clk;
+ uint32_t priority;
+};
+
+static struct funnel_drvdata *drvdata;
+
+static void __funnel_enable(uint8_t id, uint32_t port_mask)
+{
+ uint32_t functl;
+
+ FUNNEL_UNLOCK(id);
+
+ functl = funnel_readl(drvdata, id, FUNNEL_FUNCTL);
+ functl &= ~FUNNEL_HOLDTIME_MASK;
+ functl |= FUNNEL_HOLDTIME;
+ functl |= port_mask;
+ funnel_writel(drvdata, id, functl, FUNNEL_FUNCTL);
+ funnel_writel(drvdata, id, drvdata->priority, FUNNEL_PRICTL);
+
+ FUNNEL_LOCK(id);
+}
+
+int funnel_enable(uint8_t id, uint32_t port_mask)
+{
+ int ret;
+
+ ret = clk_prepare_enable(drvdata->clk);
+ if (ret)
+ return ret;
+
+ mutex_lock(&drvdata->mutex);
+ __funnel_enable(id, port_mask);
+ drvdata->enabled = true;
+ dev_info(drvdata->dev, "FUNNEL port mask 0x%lx enabled\n",
+ (unsigned long) port_mask);
+ mutex_unlock(&drvdata->mutex);
+
+ return 0;
+}
+
+static void __funnel_disable(uint8_t id, uint32_t port_mask)
+{
+ uint32_t functl;
+
+ FUNNEL_UNLOCK(id);
+
+ functl = funnel_readl(drvdata, id, FUNNEL_FUNCTL);
+ functl &= ~port_mask;
+ funnel_writel(drvdata, id, functl, FUNNEL_FUNCTL);
+
+ FUNNEL_LOCK(id);
+}
+
+void funnel_disable(uint8_t id, uint32_t port_mask)
+{
+ mutex_lock(&drvdata->mutex);
+ __funnel_disable(id, port_mask);
+ drvdata->enabled = false;
+ dev_info(drvdata->dev, "FUNNEL port mask 0x%lx disabled\n",
+ (unsigned long) port_mask);
+ mutex_unlock(&drvdata->mutex);
+
+ clk_disable_unprepare(drvdata->clk);
+}
+
+static ssize_t funnel_show_priority(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ unsigned long val = drvdata->priority;
+ return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
+}
+
+static ssize_t funnel_store_priority(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t size)
+{
+ unsigned long val;
+
+ if (sscanf(buf, "%lx", &val) != 1)
+ return -EINVAL;
+
+ drvdata->priority = val;
+ return size;
+}
+static DEVICE_ATTR(priority, S_IRUGO | S_IWUSR, funnel_show_priority,
+ funnel_store_priority);
+
+static int __devinit funnel_sysfs_init(void)
+{
+ int ret;
+
+ drvdata->kobj = kobject_create_and_add("funnel", qdss_get_modulekobj());
+ if (!drvdata->kobj) {
+ dev_err(drvdata->dev, "failed to create FUNNEL sysfs kobject\n");
+ ret = -ENOMEM;
+ goto err_create;
+ }
+
+ ret = sysfs_create_file(drvdata->kobj, &dev_attr_priority.attr);
+ if (ret) {
+ dev_err(drvdata->dev, "failed to create FUNNEL sysfs priority"
+ " attribute\n");
+ goto err_file;
+ }
+
+ return 0;
+err_file:
+ kobject_put(drvdata->kobj);
+err_create:
+ return ret;
+}
+
+static void __devexit funnel_sysfs_exit(void)
+{
+ sysfs_remove_file(drvdata->kobj, &dev_attr_priority.attr);
+ kobject_put(drvdata->kobj);
+}
+
+static int __devinit funnel_probe(struct platform_device *pdev)
+{
+ int ret;
+ struct resource *res;
+
+ drvdata = kzalloc(sizeof(*drvdata), GFP_KERNEL);
+ if (!drvdata) {
+ ret = -ENOMEM;
+ goto err_kzalloc_drvdata;
+ }
+
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ if (!res) {
+ ret = -EINVAL;
+ goto err_res;
+ }
+
+ drvdata->base = ioremap_nocache(res->start, resource_size(res));
+ if (!drvdata->base) {
+ ret = -EINVAL;
+ goto err_ioremap;
+ }
+
+ drvdata->dev = &pdev->dev;
+
+ mutex_init(&drvdata->mutex);
+
+ drvdata->clk = clk_get(drvdata->dev, "core_clk");
+ if (IS_ERR(drvdata->clk)) {
+ ret = PTR_ERR(drvdata->clk);
+ goto err_clk_get;
+ }
+
+ ret = clk_set_rate(drvdata->clk, CORESIGHT_CLK_RATE_TRACE);
+ if (ret)
+ goto err_clk_rate;
+
+ funnel_sysfs_init();
+
+ dev_info(drvdata->dev, "FUNNEL initialized\n");
+ return 0;
+
+err_clk_rate:
+ clk_put(drvdata->clk);
+err_clk_get:
+ mutex_destroy(&drvdata->mutex);
+ iounmap(drvdata->base);
+err_ioremap:
+err_res:
+ kfree(drvdata);
+err_kzalloc_drvdata:
+ dev_err(drvdata->dev, "FUNNEL init failed\n");
+ return ret;
+}
+
+static int __devexit funnel_remove(struct platform_device *pdev)
+{
+ if (drvdata->enabled)
+ funnel_disable(0x0, 0xFF);
+ funnel_sysfs_exit();
+ clk_put(drvdata->clk);
+ mutex_destroy(&drvdata->mutex);
+ iounmap(drvdata->base);
+ kfree(drvdata);
+
+ return 0;
+}
+
+static struct of_device_id funnel_match[] = {
+ {.compatible = "qcom,msm-funnel"},
+ {}
+};
+
+static struct platform_driver funnel_driver = {
+ .probe = funnel_probe,
+ .remove = __devexit_p(funnel_remove),
+ .driver = {
+ .name = "msm_funnel",
+ .owner = THIS_MODULE,
+ .of_match_table = funnel_match,
+ },
+};
+
+static int __init funnel_init(void)
+{
+ return platform_driver_register(&funnel_driver);
+}
+module_init(funnel_init);
+
+static void __exit funnel_exit(void)
+{
+ platform_driver_unregister(&funnel_driver);
+}
+module_exit(funnel_exit);
+
+MODULE_LICENSE("GPL v2");
+MODULE_DESCRIPTION("CoreSight Funnel driver");
diff --git a/drivers/coresight/coresight-priv.h b/drivers/coresight/coresight-priv.h
new file mode 100644
index 0000000..dab854c
--- /dev/null
+++ b/drivers/coresight/coresight-priv.h
@@ -0,0 +1,48 @@
+/* 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
+ * 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 _CORESIGHT_PRIV_H
+#define _CORESIGHT_PRIV_H
+
+#include <linux/bitops.h>
+
+/* Coresight management registers (0xF00-0xFCC)
+ * 0xFA0 - 0xFA4: Management registers in PFTv1.0
+ * Trace registers in PFTv1.1
+ */
+#define CORESIGHT_ITCTRL (0xF00)
+#define CORESIGHT_CLAIMSET (0xFA0)
+#define CORESIGHT_CLAIMCLR (0xFA4)
+#define CORESIGHT_LAR (0xFB0)
+#define CORESIGHT_LSR (0xFB4)
+#define CORESIGHT_AUTHSTATUS (0xFB8)
+#define CORESIGHT_DEVID (0xFC8)
+#define CORESIGHT_DEVTYPE (0xFCC)
+
+#define CORESIGHT_UNLOCK (0xC5ACCE55)
+
+#define TIMEOUT_US (100)
+
+#define BM(lsb, msb) ((BIT(msb) - BIT(lsb)) + BIT(msb))
+#define BMVAL(val, lsb, msb) ((val & BM(lsb, msb)) >> lsb)
+#define BVAL(val, n) ((val & BIT(n)) >> n)
+
+int etb_enable(void);
+void etb_disable(void);
+void etb_dump(void);
+void tpiu_disable(void);
+int funnel_enable(uint8_t id, uint32_t port_mask);
+void funnel_disable(uint8_t id, uint32_t port_mask);
+
+struct kobject *qdss_get_modulekobj(void);
+
+#endif
diff --git a/arch/arm/mach-msm/qdss-stm.c b/drivers/coresight/coresight-stm.c
similarity index 67%
rename from arch/arm/mach-msm/qdss-stm.c
rename to drivers/coresight/coresight-stm.c
index 0d44c1a..6387947 100644
--- a/arch/arm/mach-msm/qdss-stm.c
+++ b/drivers/coresight/coresight-stm.c
@@ -22,15 +22,17 @@
#include <linux/miscdevice.h>
#include <linux/uaccess.h>
#include <linux/slab.h>
+#include <linux/clk.h>
+#include <linux/coresight.h>
+#include <linux/coresight-stm.h>
#include <asm/unaligned.h>
-#include <mach/stm.h>
-#include "qdss-priv.h"
+#include "coresight-priv.h"
-#define stm_writel(stm, val, off) \
- __raw_writel((val), stm.base + off)
-#define stm_readl(stm, val, off) \
- __raw_readl(stm.base + off)
+#define stm_writel(drvdata, val, off) \
+ __raw_writel((val), drvdata->base + off)
+#define stm_readl(drvdata, val, off) \
+ __raw_readl(drvdata->base + off)
#define NR_STM_CHANNEL (32)
#define BYTES_PER_CHANNEL (256)
@@ -51,17 +53,17 @@
#define OST_VERSION (0x1)
#define stm_channel_addr(ch) \
- (stm.chs.base + (ch * BYTES_PER_CHANNEL))
+ (drvdata->chs.base + (ch * BYTES_PER_CHANNEL))
#define stm_channel_off(type, opts) (type & ~opts)
#define STM_LOCK() \
do { \
mb(); \
- stm_writel(stm, 0x0, CS_LAR); \
+ stm_writel(drvdata, 0x0, CORESIGHT_LAR); \
} while (0)
#define STM_UNLOCK() \
do { \
- stm_writel(stm, CS_UNLOCK_MAGIC, CS_LAR); \
+ stm_writel(drvdata, CORESIGHT_UNLOCK, CORESIGHT_LAR); \
mb(); \
} while (0)
@@ -91,29 +93,27 @@
unsigned long *bitmap;
};
-struct stm_ctx {
+struct stm_drvdata {
void __iomem *base;
bool enabled;
struct qdss_source *src;
struct device *dev;
struct kobject *kobj;
+ struct clk *clk;
uint32_t entity;
struct channel_space chs;
};
-static struct stm_ctx stm = {
- .entity = OST_ENTITY_ALL,
-};
-
+static struct stm_drvdata *drvdata;
static void __stm_enable(void)
{
STM_UNLOCK();
- stm_writel(stm, 0x80, STMSYNCR);
- stm_writel(stm, 0xFFFFFFFF, STMSPTER);
- stm_writel(stm, 0xFFFFFFFF, STMSPER);
- stm_writel(stm, 0x30003, STMTCSR);
+ stm_writel(drvdata, 0x80, STMSYNCR);
+ stm_writel(drvdata, 0xFFFFFFFF, STMSPTER);
+ stm_writel(drvdata, 0xFFFFFFFF, STMSPER);
+ stm_writel(drvdata, 0x30003, STMTCSR);
STM_LOCK();
}
@@ -122,23 +122,30 @@
{
int ret;
- if (stm.enabled) {
- dev_err(stm.dev, "STM tracing already enabled\n");
+ if (drvdata->enabled) {
+ dev_err(drvdata->dev, "STM tracing already enabled\n");
ret = -EINVAL;
goto err;
}
- ret = qdss_enable(stm.src);
+ ret = clk_prepare_enable(drvdata->clk);
if (ret)
- goto err;
+ goto err_clk;
+
+ ret = qdss_enable(drvdata->src);
+ if (ret)
+ goto err_qdss;
__stm_enable();
- stm.enabled = true;
+ drvdata->enabled = true;
- dev_info(stm.dev, "STM tracing enabled\n");
+ dev_info(drvdata->dev, "STM tracing enabled\n");
return 0;
+err_qdss:
+ clk_disable_unprepare(drvdata->clk);
+err_clk:
err:
return ret;
}
@@ -147,9 +154,9 @@
{
STM_UNLOCK();
- stm_writel(stm, 0x30000, STMTCSR);
- stm_writel(stm, 0x0, STMSPER);
- stm_writel(stm, 0x0, STMSPTER);
+ stm_writel(drvdata, 0x30000, STMTCSR);
+ stm_writel(drvdata, 0x0, STMSPER);
+ stm_writel(drvdata, 0x0, STMSPTER);
STM_LOCK();
}
@@ -158,19 +165,21 @@
{
int ret;
- if (!stm.enabled) {
- dev_err(stm.dev, "STM tracing already disabled\n");
+ if (!drvdata->enabled) {
+ dev_err(drvdata->dev, "STM tracing already disabled\n");
ret = -EINVAL;
goto err;
}
__stm_disable();
- qdss_disable(stm.src);
+ drvdata->enabled = false;
- stm.enabled = false;
+ qdss_disable(drvdata->src);
- dev_info(stm.dev, "STM tracing disabled\n");
+ clk_disable_unprepare(drvdata->clk);
+
+ dev_info(drvdata->dev, "STM tracing disabled\n");
return 0;
err:
@@ -182,15 +191,17 @@
uint32_t ch;
do {
- ch = find_next_zero_bit(stm.chs.bitmap, NR_STM_CHANNEL, off);
- } while ((ch < NR_STM_CHANNEL) && test_and_set_bit(ch, stm.chs.bitmap));
+ ch = find_next_zero_bit(drvdata->chs.bitmap,
+ NR_STM_CHANNEL, off);
+ } while ((ch < NR_STM_CHANNEL) &&
+ test_and_set_bit(ch, drvdata->chs.bitmap));
return ch;
}
static void stm_channel_free(uint32_t ch)
{
- clear_bit(ch, stm.chs.bitmap);
+ clear_bit(ch, drvdata->chs.bitmap);
}
static int stm_send(void *addr, const void *data, uint32_t size)
@@ -331,10 +342,10 @@
* number of bytes transfered over STM
*/
int stm_trace(uint32_t options, uint8_t entity_id, uint8_t proto_id,
- const void *data, uint32_t size)
+ const void *data, uint32_t size)
{
/* we don't support sizes more than 24bits (0 to 23) */
- if (!(stm.enabled && (stm.entity & entity_id) &&
+ if (!(drvdata->enabled && (drvdata->entity & entity_id) &&
(size < 0x1000000)))
return 0;
@@ -347,10 +358,10 @@
{
char *buf;
- if (!stm.enabled)
+ if (!drvdata->enabled)
return -EINVAL;
- if (!(stm.entity & OST_ENTITY_DEV_NODE))
+ if (!(drvdata->entity & OST_ENTITY_DEV_NODE))
return size;
if (size > STM_TRACE_BUF_SIZE)
@@ -362,7 +373,7 @@
if (copy_from_user(buf, data, size)) {
kfree(buf);
- dev_dbg(stm.dev, "%s: copy_from_user failed\n", __func__);
+ dev_dbg(drvdata->dev, "%s: copy_from_user failed\n", __func__);
return -EFAULT;
}
@@ -385,13 +396,16 @@
.fops = &stm_fops,
};
-#define STM_ATTR(__name) \
-static struct kobj_attribute __name##_attr = \
- __ATTR(__name, S_IRUGO | S_IWUSR, __name##_show, __name##_store)
+static ssize_t stm_show_enabled(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ unsigned long val = drvdata->enabled;
+ return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
+}
-static ssize_t enabled_store(struct kobject *kobj,
- struct kobj_attribute *attr,
- const char *buf, size_t n)
+static ssize_t stm_store_enabled(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t size)
{
int ret = 0;
unsigned long val;
@@ -406,70 +420,65 @@
if (ret)
return ret;
- return n;
+ return size;
}
-static ssize_t enabled_show(struct kobject *kobj,
- struct kobj_attribute *attr,
- char *buf)
+static DEVICE_ATTR(enabled, S_IRUGO | S_IWUSR, stm_show_enabled,
+ stm_store_enabled);
+
+static ssize_t stm_show_entity(struct device *dev,
+ struct device_attribute *attr, char *buf)
{
- unsigned long val = stm.enabled;
+ unsigned long val = drvdata->entity;
return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
}
-STM_ATTR(enabled);
-static ssize_t entity_store(struct kobject *kobj,
- struct kobj_attribute *attr,
- const char *buf, size_t n)
+static ssize_t stm_store_entity(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t size)
{
unsigned long val;
if (sscanf(buf, "%lx", &val) != 1)
return -EINVAL;
- stm.entity = val;
- return n;
+ drvdata->entity = val;
+ return size;
}
-static ssize_t entity_show(struct kobject *kobj,
- struct kobj_attribute *attr,
- char *buf)
-{
- unsigned long val = stm.entity;
- return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
-}
-STM_ATTR(entity);
+static DEVICE_ATTR(entity, S_IRUGO | S_IWUSR, stm_show_entity,
+ stm_store_entity);
static int __devinit stm_sysfs_init(void)
{
int ret;
- stm.kobj = kobject_create_and_add("stm", qdss_get_modulekobj());
- if (!stm.kobj) {
- dev_err(stm.dev, "failed to create STM sysfs kobject\n");
+ drvdata->kobj = kobject_create_and_add("stm", qdss_get_modulekobj());
+ if (!drvdata->kobj) {
+ dev_err(drvdata->dev, "failed to create STM sysfs kobject\n");
ret = -ENOMEM;
goto err_create;
}
- ret = sysfs_create_file(stm.kobj, &enabled_attr.attr);
+ ret = sysfs_create_file(drvdata->kobj, &dev_attr_enabled.attr);
if (ret) {
- dev_err(stm.dev, "failed to create STM sysfs enabled attr\n");
+ dev_err(drvdata->dev, "failed to create STM sysfs enabled attr\n");
goto err_file;
}
- if (sysfs_create_file(stm.kobj, &entity_attr.attr))
- dev_err(stm.dev, "failed to create STM sysfs entity attr\n");
+ if (sysfs_create_file(drvdata->kobj, &dev_attr_entity.attr))
+ dev_err(drvdata->dev, "failed to create STM sysfs entity attr\n");
return 0;
err_file:
- kobject_put(stm.kobj);
+ kobject_put(drvdata->kobj);
err_create:
return ret;
}
static void __devexit stm_sysfs_exit(void)
{
- sysfs_remove_file(stm.kobj, &entity_attr.attr);
- sysfs_remove_file(stm.kobj, &enabled_attr.attr);
- kobject_put(stm.kobj);
+ sysfs_remove_file(drvdata->kobj, &dev_attr_entity.attr);
+ sysfs_remove_file(drvdata->kobj, &dev_attr_enabled.attr);
+ kobject_put(drvdata->kobj);
}
static int __devinit stm_probe(struct platform_device *pdev)
@@ -478,14 +487,20 @@
struct resource *res;
size_t res_size, bitmap_size;
+ drvdata = kzalloc(sizeof(*drvdata), GFP_KERNEL);
+ if (!drvdata) {
+ ret = -ENOMEM;
+ goto err_kzalloc_drvdata;
+ }
+
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
if (!res) {
ret = -EINVAL;
goto err_res0;
}
- stm.base = ioremap_nocache(res->start, resource_size(res));
- if (!stm.base) {
+ drvdata->base = ioremap_nocache(res->start, resource_size(res));
+ if (!drvdata->base) {
ret = -EINVAL;
goto err_ioremap0;
}
@@ -506,30 +521,42 @@
bitmap_size = NR_STM_CHANNEL * sizeof(long);
}
- stm.chs.bitmap = kzalloc(bitmap_size, GFP_KERNEL);
- if (!stm.chs.bitmap) {
+ drvdata->chs.bitmap = kzalloc(bitmap_size, GFP_KERNEL);
+ if (!drvdata->chs.bitmap) {
ret = -ENOMEM;
goto err_bitmap;
}
- stm.chs.base = ioremap_nocache(res->start, res_size);
- if (!stm.chs.base) {
+ drvdata->chs.base = ioremap_nocache(res->start, res_size);
+ if (!drvdata->chs.base) {
ret = -EINVAL;
goto err_ioremap1;
}
- stm.dev = &pdev->dev;
+ drvdata->dev = &pdev->dev;
ret = misc_register(&stm_misc);
if (ret)
goto err_misc;
- stm.src = qdss_get("msm_stm");
- if (IS_ERR(stm.src)) {
- ret = PTR_ERR(stm.src);
+ drvdata->src = qdss_get("msm_stm");
+ if (IS_ERR(drvdata->src)) {
+ ret = PTR_ERR(drvdata->src);
goto err_qdssget;
}
+ drvdata->clk = clk_get(drvdata->dev, "core_clk");
+ if (IS_ERR(drvdata->clk)) {
+ ret = PTR_ERR(drvdata->clk);
+ goto err_clk_get;
+ }
+
+ ret = clk_set_rate(drvdata->clk, CORESIGHT_CLK_RATE_TRACE);
+ if (ret)
+ goto err_clk_rate;
+
+ drvdata->entity = OST_ENTITY_ALL;
+
ret = stm_sysfs_init();
if (ret)
goto err_sysfs;
@@ -537,36 +564,44 @@
if (stm_boot_enable)
stm_enable();
- dev_info(stm.dev, "STM initialized\n");
+ dev_info(drvdata->dev, "STM initialized\n");
return 0;
err_sysfs:
- qdss_put(stm.src);
+err_clk_rate:
+ clk_put(drvdata->clk);
+err_clk_get:
+ qdss_put(drvdata->src);
err_qdssget:
misc_deregister(&stm_misc);
err_misc:
- iounmap(stm.chs.base);
+ iounmap(drvdata->chs.base);
err_ioremap1:
- kfree(stm.chs.bitmap);
+ kfree(drvdata->chs.bitmap);
err_bitmap:
err_res1:
- iounmap(stm.base);
+ iounmap(drvdata->base);
err_ioremap0:
err_res0:
- dev_err(stm.dev, "STM init failed\n");
+ kfree(drvdata);
+err_kzalloc_drvdata:
+
+ dev_err(drvdata->dev, "STM init failed\n");
return ret;
}
static int __devexit stm_remove(struct platform_device *pdev)
{
- if (stm.enabled)
+ if (drvdata->enabled)
stm_disable();
stm_sysfs_exit();
- qdss_put(stm.src);
+ clk_put(drvdata->clk);
+ qdss_put(drvdata->src);
misc_deregister(&stm_misc);
- iounmap(stm.chs.base);
- kfree(stm.chs.bitmap);
- iounmap(stm.base);
+ iounmap(drvdata->chs.base);
+ kfree(drvdata->chs.bitmap);
+ iounmap(drvdata->base);
+ kfree(drvdata);
return 0;
}
diff --git a/arch/arm/mach-msm/qdss-tpiu.c b/drivers/coresight/coresight-tpiu.c
similarity index 66%
rename from arch/arm/mach-msm/qdss-tpiu.c
rename to drivers/coresight/coresight-tpiu.c
index 23905f0..4b52c4d 100644
--- a/arch/arm/mach-msm/qdss-tpiu.c
+++ b/drivers/coresight/coresight-tpiu.c
@@ -17,11 +17,14 @@
#include <linux/platform_device.h>
#include <linux/io.h>
#include <linux/err.h>
+#include <linux/slab.h>
+#include <linux/clk.h>
+#include <linux/coresight.h>
-#include "qdss-priv.h"
+#include "coresight-priv.h"
-#define tpiu_writel(tpiu, val, off) __raw_writel((val), tpiu.base + off)
-#define tpiu_readl(tpiu, off) __raw_readl(tpiu.base + off)
+#define tpiu_writel(drvdata, val, off) __raw_writel((val), drvdata->base + off)
+#define tpiu_readl(drvdata, off) __raw_readl(drvdata->base + off)
#define TPIU_SUPP_PORTSZ (0x000)
#define TPIU_CURR_PORTSZ (0x004)
@@ -47,28 +50,29 @@
#define TPIU_LOCK() \
do { \
mb(); \
- tpiu_writel(tpiu, 0x0, CS_LAR); \
+ tpiu_writel(drvdata, 0x0, CORESIGHT_LAR); \
} while (0)
#define TPIU_UNLOCK() \
do { \
- tpiu_writel(tpiu, CS_UNLOCK_MAGIC, CS_LAR); \
+ tpiu_writel(drvdata, CORESIGHT_UNLOCK, CORESIGHT_LAR); \
mb(); \
} while (0)
-struct tpiu_ctx {
+struct tpiu_drvdata {
void __iomem *base;
bool enabled;
struct device *dev;
+ struct clk *clk;
};
-static struct tpiu_ctx tpiu;
+static struct tpiu_drvdata *drvdata;
static void __tpiu_disable(void)
{
TPIU_UNLOCK();
- tpiu_writel(tpiu, 0x3000, TPIU_FFCR);
- tpiu_writel(tpiu, 0x3040, TPIU_FFCR);
+ tpiu_writel(drvdata, 0x3000, TPIU_FFCR);
+ tpiu_writel(drvdata, 0x3040, TPIU_FFCR);
TPIU_LOCK();
}
@@ -76,8 +80,8 @@
void tpiu_disable(void)
{
__tpiu_disable();
- tpiu.enabled = false;
- dev_info(tpiu.dev, "TPIU disabled\n");
+ drvdata->enabled = false;
+ dev_info(drvdata->dev, "TPIU disabled\n");
}
static int __devinit tpiu_probe(struct platform_device *pdev)
@@ -85,34 +89,58 @@
int ret;
struct resource *res;
+ drvdata = kzalloc(sizeof(*drvdata), GFP_KERNEL);
+ if (!drvdata) {
+ ret = -ENOMEM;
+ goto err_kzalloc_drvdata;
+ }
+
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
if (!res) {
ret = -EINVAL;
goto err_res;
}
- tpiu.base = ioremap_nocache(res->start, resource_size(res));
- if (!tpiu.base) {
+ drvdata->base = ioremap_nocache(res->start, resource_size(res));
+ if (!drvdata->base) {
ret = -EINVAL;
goto err_ioremap;
}
- tpiu.dev = &pdev->dev;
+ drvdata->dev = &pdev->dev;
- dev_info(tpiu.dev, "TPIU initialized\n");
+ drvdata->clk = clk_get(drvdata->dev, "core_clk");
+ if (IS_ERR(drvdata->clk)) {
+ ret = PTR_ERR(drvdata->clk);
+ goto err_clk_get;
+ }
+
+ ret = clk_set_rate(drvdata->clk, CORESIGHT_CLK_RATE_TRACE);
+ if (ret)
+ goto err_clk_rate;
+
+ dev_info(drvdata->dev, "TPIU initialized\n");
return 0;
+err_clk_rate:
+ clk_put(drvdata->clk);
+err_clk_get:
+ iounmap(drvdata->base);
err_ioremap:
err_res:
- dev_err(tpiu.dev, "TPIU init failed\n");
+ kfree(drvdata);
+err_kzalloc_drvdata:
+ dev_err(drvdata->dev, "TPIU init failed\n");
return ret;
}
static int __devexit tpiu_remove(struct platform_device *pdev)
{
- if (tpiu.enabled)
+ if (drvdata->enabled)
tpiu_disable();
- iounmap(tpiu.base);
+ clk_put(drvdata->clk);
+ iounmap(drvdata->base);
+ kfree(drvdata);
return 0;
}
diff --git a/drivers/coresight/coresight.c b/drivers/coresight/coresight.c
new file mode 100644
index 0000000..055ef55
--- /dev/null
+++ b/drivers/coresight/coresight.c
@@ -0,0 +1,606 @@
+/* Copyright (c) 2012, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/types.h>
+#include <linux/device.h>
+#include <linux/platform_device.h>
+#include <linux/io.h>
+#include <linux/err.h>
+#include <linux/export.h>
+#include <linux/slab.h>
+#include <linux/mutex.h>
+#include <linux/clk.h>
+#include <linux/coresight.h>
+
+#include "coresight-priv.h"
+
+#define MAX_STR_LEN (65535)
+
+
+static LIST_HEAD(coresight_orph_conns);
+static DEFINE_MUTEX(coresight_conns_mutex);
+static LIST_HEAD(coresight_devs);
+static DEFINE_MUTEX(coresight_devs_mutex);
+
+
+int coresight_enable(struct coresight_device *csdev, int port)
+{
+ int i;
+ int ret;
+ struct coresight_connection *conn;
+
+ mutex_lock(&csdev->mutex);
+ if (csdev->refcnt[port] == 0) {
+ for (i = 0; i < csdev->nr_conns; i++) {
+ conn = &csdev->conns[i];
+ ret = coresight_enable(conn->child_dev,
+ conn->child_port);
+ if (ret)
+ goto err_enable_child;
+ }
+ if (csdev->ops->enable)
+ ret = csdev->ops->enable(csdev, port);
+ if (ret)
+ goto err_enable;
+ }
+ csdev->refcnt[port]++;
+ mutex_unlock(&csdev->mutex);
+ return 0;
+err_enable_child:
+ while (i) {
+ conn = &csdev->conns[--i];
+ coresight_disable(conn->child_dev, conn->child_port);
+ }
+err_enable:
+ mutex_unlock(&csdev->mutex);
+ return ret;
+}
+EXPORT_SYMBOL(coresight_enable);
+
+void coresight_disable(struct coresight_device *csdev, int port)
+{
+ int i;
+ struct coresight_connection *conn;
+
+ mutex_lock(&csdev->mutex);
+ if (csdev->refcnt[port] == 1) {
+ if (csdev->ops->disable)
+ csdev->ops->disable(csdev, port);
+ for (i = 0; i < csdev->nr_conns; i++) {
+ conn = &csdev->conns[i];
+ coresight_disable(conn->child_dev, conn->child_port);
+ }
+ }
+ csdev->refcnt[port]--;
+ mutex_unlock(&csdev->mutex);
+}
+EXPORT_SYMBOL(coresight_disable);
+
+static ssize_t coresight_show_type(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ return snprintf(buf, PAGE_SIZE, "%s\n", dev->type->name);
+}
+
+static struct device_attribute coresight_dev_attrs[] = {
+ __ATTR(type, S_IRUGO, coresight_show_type, NULL),
+ { },
+};
+
+struct bus_type coresight_bus_type = {
+ .name = "coresight",
+ .dev_attrs = coresight_dev_attrs,
+};
+
+static ssize_t coresight_show_enable(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct coresight_device *csdev = to_coresight_device(dev);
+
+ return scnprintf(buf, PAGE_SIZE, "%u\n", (unsigned)csdev->enable);
+}
+
+static ssize_t coresight_store_enable(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t size)
+{
+ int ret = 0;
+ unsigned long val;
+ struct coresight_device *csdev = to_coresight_device(dev);
+
+ if (sscanf(buf, "%lx", &val) != 1)
+ return -EINVAL;
+
+ if (val)
+ ret = coresight_enable(csdev, 0);
+ else
+ coresight_disable(csdev, 0);
+
+ if (ret)
+ return ret;
+ return size;
+}
+static DEVICE_ATTR(enable, S_IRUGO | S_IWUSR, coresight_show_enable,
+ coresight_store_enable);
+
+static struct attribute *coresight_attrs[] = {
+ &dev_attr_enable.attr,
+ NULL,
+};
+
+static struct attribute_group coresight_attr_grp = {
+ .attrs = coresight_attrs,
+};
+
+static const struct attribute_group *coresight_attr_grps[] = {
+ &coresight_attr_grp,
+ NULL,
+};
+
+static struct device_type coresight_dev_type[CORESIGHT_DEV_TYPE_MAX] = {
+ {
+ .name = "source",
+ .groups = coresight_attr_grps,
+ },
+ {
+ .name = "link",
+ },
+ {
+ .name = "sink",
+ .groups = coresight_attr_grps,
+ },
+};
+
+static void coresight_device_release(struct device *dev)
+{
+ struct coresight_device *csdev = to_coresight_device(dev);
+ mutex_destroy(&csdev->mutex);
+ kfree(csdev);
+}
+
+static void coresight_fixup_orphan_conns(struct coresight_device *csdev)
+{
+ struct coresight_connection *conn, *temp;
+
+ mutex_lock(&coresight_conns_mutex);
+ list_for_each_entry_safe(conn, temp, &coresight_orph_conns, link) {
+ if (conn->child_id == csdev->id) {
+ conn->child_dev = csdev;
+ list_del(&conn->link);
+ }
+ }
+ mutex_unlock(&coresight_conns_mutex);
+}
+
+static void coresight_fixup_device_conns(struct coresight_device *csdev)
+{
+ int i;
+ struct coresight_device *cd;
+ bool found;
+
+ for (i = 0; i < csdev->nr_conns; i++) {
+ found = false;
+ mutex_lock(&coresight_devs_mutex);
+ list_for_each_entry(cd, &coresight_devs, link) {
+ if (csdev->conns[i].child_id == cd->id) {
+ csdev->conns[i].child_dev = cd;
+ found = true;
+ break;
+ }
+ }
+ mutex_unlock(&coresight_devs_mutex);
+ if (!found) {
+ mutex_lock(&coresight_conns_mutex);
+ list_add_tail(&csdev->conns[i].link,
+ &coresight_orph_conns);
+ mutex_unlock(&coresight_conns_mutex);
+ }
+ }
+}
+
+struct coresight_device *coresight_register(struct coresight_desc *desc)
+{
+ int i;
+ int ret;
+ int *refcnt;
+ struct coresight_device *csdev;
+ struct coresight_connection *conns;
+
+ csdev = kzalloc(sizeof(*csdev), GFP_KERNEL);
+ if (!csdev) {
+ ret = -ENOMEM;
+ goto err_kzalloc_csdev;
+ }
+
+ mutex_init(&csdev->mutex);
+ csdev->id = desc->pdata->id;
+
+ refcnt = kzalloc(sizeof(*refcnt) * desc->pdata->nr_ports, GFP_KERNEL);
+ if (!refcnt) {
+ ret = -ENOMEM;
+ goto err_kzalloc_refcnt;
+ }
+ csdev->refcnt = refcnt;
+
+ csdev->nr_conns = desc->pdata->nr_children;
+ conns = kzalloc(sizeof(*conns) * csdev->nr_conns, GFP_KERNEL);
+ if (!conns) {
+ ret = -ENOMEM;
+ goto err_kzalloc_conns;
+ }
+ for (i = 0; i < csdev->nr_conns; i++) {
+ conns[i].child_id = desc->pdata->child_ids[i];
+ conns[i].child_port = desc->pdata->child_ports[i];
+ }
+ csdev->conns = conns;
+
+ csdev->ops = desc->ops;
+ csdev->owner = desc->owner;
+
+ csdev->dev.type = &coresight_dev_type[desc->type];
+ csdev->dev.groups = desc->groups;
+ csdev->dev.parent = desc->dev;
+ csdev->dev.bus = &coresight_bus_type;
+ csdev->dev.release = coresight_device_release;
+ dev_set_name(&csdev->dev, "%s", desc->pdata->name);
+
+ coresight_fixup_device_conns(csdev);
+ ret = device_register(&csdev->dev);
+ if (ret)
+ goto err_dev_reg;
+ coresight_fixup_orphan_conns(csdev);
+
+ mutex_lock(&coresight_devs_mutex);
+ list_add_tail(&csdev->link, &coresight_devs);
+ mutex_unlock(&coresight_devs_mutex);
+
+ return csdev;
+err_dev_reg:
+ put_device(&csdev->dev);
+ kfree(conns);
+err_kzalloc_conns:
+ kfree(refcnt);
+err_kzalloc_refcnt:
+ mutex_destroy(&csdev->mutex);
+ kfree(csdev);
+err_kzalloc_csdev:
+ return ERR_PTR(ret);
+}
+EXPORT_SYMBOL(coresight_register);
+
+void coresight_unregister(struct coresight_device *csdev)
+{
+ if (IS_ERR_OR_NULL(csdev))
+ return;
+
+ if (get_device(&csdev->dev)) {
+ mutex_lock(&csdev->mutex);
+ device_unregister(&csdev->dev);
+ mutex_unlock(&csdev->mutex);
+ put_device(&csdev->dev);
+ }
+}
+EXPORT_SYMBOL(coresight_unregister);
+
+static int __init coresight_init(void)
+{
+ return bus_register(&coresight_bus_type);
+}
+subsys_initcall(coresight_init);
+
+static void __exit coresight_exit(void)
+{
+ bus_unregister(&coresight_bus_type);
+}
+module_exit(coresight_exit);
+
+MODULE_LICENSE("GPL v2");
+/*
+ * Exclusion rules for structure fields.
+ *
+ * S: qdss.sources_mutex protected.
+ * I: qdss.sink_mutex protected.
+ * C: qdss.clk_mutex protected.
+ */
+struct qdss_ctx {
+ struct kobject *modulekobj;
+ uint8_t afamily;
+ struct list_head sources; /* S: sources list */
+ struct mutex sources_mutex;
+ uint8_t sink_count; /* I: sink count */
+ struct mutex sink_mutex;
+ uint8_t max_clk;
+ struct clk *clk;
+};
+
+static struct qdss_ctx qdss;
+
+/**
+ * qdss_get - get the qdss source handle
+ * @name: name of the qdss source
+ *
+ * Searches the sources list to get the qdss source handle for this source.
+ *
+ * CONTEXT:
+ * Typically called from init or probe functions
+ *
+ * RETURNS:
+ * pointer to struct qdss_source on success, %NULL on failure
+ */
+struct qdss_source *qdss_get(const char *name)
+{
+ struct qdss_source *src, *source = NULL;
+
+ mutex_lock(&qdss.sources_mutex);
+ list_for_each_entry(src, &qdss.sources, link) {
+ if (src->name) {
+ if (strncmp(src->name, name, MAX_STR_LEN))
+ continue;
+ source = src;
+ break;
+ }
+ }
+ mutex_unlock(&qdss.sources_mutex);
+
+ return source ? source : ERR_PTR(-ENOENT);
+}
+EXPORT_SYMBOL(qdss_get);
+
+/**
+ * qdss_put - release the qdss source handle
+ * @name: name of the qdss source
+ *
+ * CONTEXT:
+ * Typically called from driver remove or exit functions
+ */
+void qdss_put(struct qdss_source *src)
+{
+}
+EXPORT_SYMBOL(qdss_put);
+
+/**
+ * qdss_enable - enable qdss for the source
+ * @src: handle for the source making the call
+ *
+ * Enables qdss block (relevant funnel ports and sink) if not already
+ * enabled, otherwise increments the reference count
+ *
+ * CONTEXT:
+ * Might sleep. Uses a mutex lock. Should be called from a non-atomic context.
+ *
+ * RETURNS:
+ * 0 on success, non-zero on failure
+ */
+int qdss_enable(struct qdss_source *src)
+{
+ if (!src)
+ return -EINVAL;
+
+ if (qdss.afamily) {
+ mutex_lock(&qdss.sink_mutex);
+ if (qdss.sink_count == 0) {
+ tpiu_disable();
+ /* enable ETB first to avoid losing any trace data */
+ etb_enable();
+ }
+ qdss.sink_count++;
+ mutex_unlock(&qdss.sink_mutex);
+ }
+
+ funnel_enable(0x0, src->fport_mask);
+ return 0;
+}
+EXPORT_SYMBOL(qdss_enable);
+
+/**
+ * qdss_disable - disable qdss for the source
+ * @src: handle for the source making the call
+ *
+ * Disables qdss block (relevant funnel ports and sink) if the reference count
+ * is one, otherwise decrements the reference count
+ *
+ * CONTEXT:
+ * Might sleep. Uses a mutex lock. Should be called from a non-atomic context.
+ */
+void qdss_disable(struct qdss_source *src)
+{
+ if (!src)
+ return;
+
+ if (qdss.afamily) {
+ mutex_lock(&qdss.sink_mutex);
+ if (WARN(qdss.sink_count == 0, "qdss is unbalanced\n"))
+ goto out;
+ if (qdss.sink_count == 1) {
+ etb_dump();
+ etb_disable();
+ }
+ qdss.sink_count--;
+ mutex_unlock(&qdss.sink_mutex);
+ }
+
+ funnel_disable(0x0, src->fport_mask);
+ return;
+out:
+ mutex_unlock(&qdss.sink_mutex);
+}
+EXPORT_SYMBOL(qdss_disable);
+
+/**
+ * qdss_disable_sink - force disable the current qdss sink(s)
+ *
+ * Force disable the current qdss sink(s) to stop the sink from accepting any
+ * trace generated subsequent to this call. This function should only be used
+ * as a way to stop the sink from getting polluted with trace data that is
+ * uninteresting after an event of interest has occured.
+ *
+ * CONTEXT:
+ * Can be called from atomic or non-atomic context.
+ */
+void qdss_disable_sink(void)
+{
+ if (qdss.afamily) {
+ etb_dump();
+ etb_disable();
+ }
+}
+EXPORT_SYMBOL(qdss_disable_sink);
+
+struct kobject *qdss_get_modulekobj(void)
+{
+ return qdss.modulekobj;
+}
+
+#define QDSS_ATTR(name) \
+static struct kobj_attribute name##_attr = \
+ __ATTR(name, S_IRUGO | S_IWUSR, name##_show, name##_store)
+
+static ssize_t max_clk_store(struct kobject *kobj,
+ struct kobj_attribute *attr,
+ const char *buf, size_t n)
+{
+ unsigned long val;
+
+ if (sscanf(buf, "%lx", &val) != 1)
+ return -EINVAL;
+
+ qdss.max_clk = val;
+ return n;
+}
+static ssize_t max_clk_show(struct kobject *kobj,
+ struct kobj_attribute *attr,
+ char *buf)
+{
+ unsigned long val = qdss.max_clk;
+ return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
+}
+QDSS_ATTR(max_clk);
+
+static void __devinit qdss_add_sources(struct qdss_source *srcs, size_t num)
+{
+ mutex_lock(&qdss.sources_mutex);
+ while (num--) {
+ list_add_tail(&srcs->link, &qdss.sources);
+ srcs++;
+ }
+ mutex_unlock(&qdss.sources_mutex);
+}
+
+static int __init qdss_sysfs_init(void)
+{
+ int ret;
+
+ qdss.modulekobj = kset_find_obj(module_kset, KBUILD_MODNAME);
+ if (!qdss.modulekobj) {
+ pr_err("failed to find QDSS sysfs module kobject\n");
+ ret = -ENOENT;
+ goto err;
+ }
+
+ ret = sysfs_create_file(qdss.modulekobj, &max_clk_attr.attr);
+ if (ret) {
+ pr_err("failed to create QDSS sysfs max_clk attribute\n");
+ goto err;
+ }
+
+ return 0;
+err:
+ return ret;
+}
+
+static void __devexit qdss_sysfs_exit(void)
+{
+ sysfs_remove_file(qdss.modulekobj, &max_clk_attr.attr);
+}
+
+static int __devinit qdss_probe(struct platform_device *pdev)
+{
+ int ret = 0;
+ struct msm_qdss_platform_data *pdata;
+
+ mutex_init(&qdss.sources_mutex);
+ mutex_init(&qdss.sink_mutex);
+
+ INIT_LIST_HEAD(&qdss.sources);
+
+ pdata = pdev->dev.platform_data;
+ if (!pdata)
+ goto err_pdata;
+
+ qdss.afamily = pdata->afamily;
+ qdss_add_sources(pdata->src_table, pdata->size);
+
+ pr_info("QDSS arch initialized\n");
+ return 0;
+err_pdata:
+ mutex_destroy(&qdss.sink_mutex);
+ mutex_destroy(&qdss.sources_mutex);
+ pr_err("QDSS init failed\n");
+ return ret;
+}
+
+static int __devexit qdss_remove(struct platform_device *pdev)
+{
+ qdss_sysfs_exit();
+ mutex_destroy(&qdss.sink_mutex);
+ mutex_destroy(&qdss.sources_mutex);
+
+ return 0;
+}
+
+static struct of_device_id qdss_match[] = {
+ {.compatible = "qcom,msm-qdss"},
+ {}
+};
+
+static struct platform_driver qdss_driver = {
+ .probe = qdss_probe,
+ .remove = __devexit_p(qdss_remove),
+ .driver = {
+ .name = "msm_qdss",
+ .owner = THIS_MODULE,
+ .of_match_table = qdss_match,
+ },
+};
+
+static int __init qdss_init(void)
+{
+ return platform_driver_register(&qdss_driver);
+}
+arch_initcall(qdss_init);
+
+static int __init qdss_module_init(void)
+{
+ int ret;
+
+ ret = qdss_sysfs_init();
+ if (ret)
+ goto err_sysfs;
+
+ pr_info("QDSS module initialized\n");
+ return 0;
+err_sysfs:
+ return ret;
+}
+module_init(qdss_module_init);
+
+static void __exit qdss_exit(void)
+{
+ platform_driver_unregister(&qdss_driver);
+}
+module_exit(qdss_exit);
+
+MODULE_LICENSE("GPL v2");
+MODULE_DESCRIPTION("Qualcomm Debug SubSystem Driver");
diff --git a/drivers/gpu/msm/kgsl_drm.c b/drivers/gpu/msm/kgsl_drm.c
index 66ac08f..870a7d7 100644
--- a/drivers/gpu/msm/kgsl_drm.c
+++ b/drivers/gpu/msm/kgsl_drm.c
@@ -238,11 +238,8 @@
}
if (TYPE_IS_PMEM(priv->type)) {
- int type;
-
if (priv->type == DRM_KGSL_GEM_TYPE_EBI ||
priv->type & DRM_KGSL_GEM_PMEM_EBI) {
- type = PMEM_MEMTYPE_EBI1;
result = kgsl_sharedmem_ebimem_user(
&priv->memdesc,
priv->pagetable,
diff --git a/drivers/media/radio/radio-tavarua.c b/drivers/media/radio/radio-tavarua.c
index a2993ce..116b7f9 100644
--- a/drivers/media/radio/radio-tavarua.c
+++ b/drivers/media/radio/radio-tavarua.c
@@ -3453,9 +3453,17 @@
if (retval < 0)
FMDBG("write failed");
} break;
+ case V4L2_CID_PRIVATE_SOFT_MUTE:
+ radio->registers[IOCTRL] &= ~(IOC_SFT_MUTE);
+ if (ctrl->value)
+ radio->registers[IOCTRL] |= IOC_SFT_MUTE;
+ retval = tavarua_write_register(radio, IOCTRL,
+ radio->registers[IOCTRL]);
+ if (retval < 0)
+ FMDERR("Failed to enable/disable SMute\n");
+ break;
/*These IOCTL's are place holders to keep the
driver compatible with change in frame works for IRIS */
- case V4L2_CID_PRIVATE_SOFT_MUTE:
case V4L2_CID_PRIVATE_RIVA_ACCS_ADDR:
case V4L2_CID_PRIVATE_RIVA_ACCS_LEN:
case V4L2_CID_PRIVATE_RIVA_PEEK:
diff --git a/drivers/media/video/msm/Kconfig b/drivers/media/video/msm/Kconfig
index 5ffc133..9c791e4 100644
--- a/drivers/media/video/msm/Kconfig
+++ b/drivers/media/video/msm/Kconfig
@@ -271,6 +271,15 @@
cores and composite them into a single
interrupt to the MSM.
+config MSM_CPP
+ bool "Qualcomm MSM Camera Post Processing Engine support"
+ depends on MSM_CAMERA && MSM_CAMERA_V4L2
+ ---help---
+ Enable support for Camera Post-processing Engine
+ The Post processing engine is capable of scaling
+ and cropping image. The driver support V4L2 subdev
+ APIs.
+
config QUP_EXCLUSIVE_TO_CAMERA
bool "QUP exclusive to camera"
depends on MSM_CAMERA
diff --git a/drivers/media/video/msm/Makefile b/drivers/media/video/msm/Makefile
index 431da2e..63120da 100644
--- a/drivers/media/video/msm/Makefile
+++ b/drivers/media/video/msm/Makefile
@@ -13,6 +13,7 @@
EXTRA_CFLAGS += -Idrivers/media/video/msm/server
obj-$(CONFIG_MSM_CAMERA) += msm_isp.o msm.o msm_mem.o msm_mctl.o msm_mctl_buf.o msm_mctl_pp.o
obj-$(CONFIG_MSM_CAMERA) += server/ eeprom/ sensors/ actuators/ csi/
+ obj-$(CONFIG_MSM_CPP) += cpp/
obj-$(CONFIG_MSM_CAMERA) += msm_gesture.o
obj-$(CONFIG_MSM_CAM_IRQ_ROUTER) += msm_camirq_router.o
else
diff --git a/drivers/media/video/msm/actuators/msm_actuator.c b/drivers/media/video/msm/actuators/msm_actuator.c
index 774a46d..554cddc 100644
--- a/drivers/media/video/msm/actuators/msm_actuator.c
+++ b/drivers/media/video/msm/actuators/msm_actuator.c
@@ -14,55 +14,42 @@
#include "msm_actuator.h"
static struct msm_actuator_ctrl_t msm_actuator_t;
-
-static struct msm_actuator msm_vcm_actuator_table = {
- .act_type = ACTUATOR_VCM,
- .func_tbl = {
- .actuator_init_step_table = msm_actuator_init_step_table,
- .actuator_move_focus = msm_actuator_move_focus,
- .actuator_write_focus = msm_actuator_write_focus,
- .actuator_set_default_focus = msm_actuator_set_default_focus,
- .actuator_init_focus = msm_actuator_init_focus,
- .actuator_i2c_write = msm_actuator_i2c_write,
- },
-};
-
-static struct msm_actuator msm_piezo_actuator_table = {
- .act_type = ACTUATOR_PIEZO,
- .func_tbl = {
- .actuator_init_step_table = NULL,
- .actuator_move_focus = msm_actuator_piezo_move_focus,
- .actuator_write_focus = NULL,
- .actuator_set_default_focus =
- msm_actuator_piezo_set_default_focus,
- .actuator_init_focus = msm_actuator_init_focus,
- .actuator_i2c_write = msm_actuator_i2c_write,
- },
-};
+static struct msm_actuator msm_vcm_actuator_table;
+static struct msm_actuator msm_piezo_actuator_table;
static struct msm_actuator *actuators[] = {
&msm_vcm_actuator_table,
&msm_piezo_actuator_table,
};
-int32_t msm_actuator_piezo_set_default_focus(
+static int32_t msm_actuator_piezo_set_default_focus(
struct msm_actuator_ctrl_t *a_ctrl,
struct msm_actuator_move_params_t *move_params)
{
int32_t rc = 0;
if (a_ctrl->curr_step_pos != 0) {
- rc = a_ctrl->func_tbl->actuator_i2c_write(a_ctrl,
- a_ctrl->initial_code, 0);
- rc = a_ctrl->func_tbl->actuator_i2c_write(a_ctrl,
- a_ctrl->initial_code, 0);
+ a_ctrl->i2c_tbl_index = 0;
+ rc = a_ctrl->func_tbl->actuator_parse_i2c_params(a_ctrl,
+ a_ctrl->initial_code, 0, 0);
+ rc = a_ctrl->func_tbl->actuator_parse_i2c_params(a_ctrl,
+ a_ctrl->initial_code, 0, 0);
+ rc = msm_camera_i2c_write_table_w_microdelay(
+ &a_ctrl->i2c_client, a_ctrl->i2c_reg_tbl,
+ a_ctrl->i2c_tbl_index, a_ctrl->i2c_data_type);
+ if (rc < 0) {
+ pr_err("%s: i2c write error:%d\n",
+ __func__, rc);
+ return rc;
+ }
+ a_ctrl->i2c_tbl_index = 0;
a_ctrl->curr_step_pos = 0;
}
return rc;
}
-int32_t msm_actuator_i2c_write(struct msm_actuator_ctrl_t *a_ctrl,
- int16_t next_lens_position, uint32_t hw_params)
+static int32_t msm_actuator_parse_i2c_params(struct msm_actuator_ctrl_t *a_ctrl,
+ int16_t next_lens_position, uint32_t hw_params, uint16_t delay)
{
struct msm_actuator_reg_params_t *write_arr = a_ctrl->reg_tbl;
uint32_t hw_dword = hw_params;
@@ -70,6 +57,7 @@
uint16_t value = 0;
uint32_t size = a_ctrl->reg_tbl_size, i = 0;
int32_t rc = 0;
+ struct msm_camera_i2c_reg_tbl *i2c_tbl = a_ctrl->i2c_reg_tbl;
CDBG("%s: IN\n", __func__);
for (i = 0; i < size; i++) {
if (write_arr[i].reg_write_type == MSM_ACTUATOR_WRITE_DAC) {
@@ -85,16 +73,13 @@
i2c_byte2 = value & 0xFF;
CDBG("%s: byte1:0x%x, byte2:0x%x\n",
__func__, i2c_byte1, i2c_byte2);
- rc = msm_camera_i2c_write(
- &a_ctrl->i2c_client,
- i2c_byte1, i2c_byte2,
- a_ctrl->i2c_data_type);
- if (rc < 0) {
- pr_err("%s: i2c write error:%d\n",
- __func__, rc);
- return rc;
- }
-
+ i2c_tbl[a_ctrl->i2c_tbl_index].
+ reg_addr = i2c_byte1;
+ i2c_tbl[a_ctrl->i2c_tbl_index].
+ reg_data = i2c_byte2;
+ i2c_tbl[a_ctrl->i2c_tbl_index].
+ delay = 0;
+ a_ctrl->i2c_tbl_index++;
i++;
i2c_byte1 = write_arr[i].reg_addr;
i2c_byte2 = (value & 0xFF00) >> 8;
@@ -110,14 +95,16 @@
}
CDBG("%s: i2c_byte1:0x%x, i2c_byte2:0x%x\n", __func__,
i2c_byte1, i2c_byte2);
- rc = msm_camera_i2c_write(&a_ctrl->i2c_client,
- i2c_byte1, i2c_byte2, a_ctrl->i2c_data_type);
+ i2c_tbl[a_ctrl->i2c_tbl_index].reg_addr = i2c_byte1;
+ i2c_tbl[a_ctrl->i2c_tbl_index].reg_data = i2c_byte2;
+ i2c_tbl[a_ctrl->i2c_tbl_index].delay = delay;
+ a_ctrl->i2c_tbl_index++;
}
CDBG("%s: OUT\n", __func__);
return rc;
}
-int32_t msm_actuator_init_focus(struct msm_actuator_ctrl_t *a_ctrl,
+static int32_t msm_actuator_init_focus(struct msm_actuator_ctrl_t *a_ctrl,
uint16_t size, enum msm_actuator_data_type type,
struct reg_settings_t *settings)
{
@@ -153,7 +140,7 @@
return rc;
}
-int32_t msm_actuator_write_focus(
+static int32_t msm_actuator_write_focus(
struct msm_actuator_ctrl_t *a_ctrl,
uint16_t curr_lens_pos,
struct damping_params_t *damping_params,
@@ -177,27 +164,25 @@
(next_lens_pos +
(sign_direction * damping_code_step))) {
rc = a_ctrl->func_tbl->
- actuator_i2c_write(a_ctrl, next_lens_pos,
- damping_params->hw_params);
+ actuator_parse_i2c_params(a_ctrl, next_lens_pos,
+ damping_params->hw_params, wait_time);
if (rc < 0) {
pr_err("%s: error:%d\n",
__func__, rc);
return rc;
}
curr_lens_pos = next_lens_pos;
- usleep(wait_time);
}
if (curr_lens_pos != code_boundary) {
rc = a_ctrl->func_tbl->
- actuator_i2c_write(a_ctrl, code_boundary,
- damping_params->hw_params);
- usleep(wait_time);
+ actuator_parse_i2c_params(a_ctrl, code_boundary,
+ damping_params->hw_params, wait_time);
}
return rc;
}
-int32_t msm_actuator_piezo_move_focus(
+static int32_t msm_actuator_piezo_move_focus(
struct msm_actuator_ctrl_t *a_ctrl,
struct msm_actuator_move_params_t *move_params)
{
@@ -208,17 +193,27 @@
if (num_steps == 0)
return rc;
+ a_ctrl->i2c_tbl_index = 0;
rc = a_ctrl->func_tbl->
- actuator_i2c_write(a_ctrl,
+ actuator_parse_i2c_params(a_ctrl,
(num_steps *
a_ctrl->region_params[0].code_per_step),
- move_params->ringing_params[0].hw_params);
+ move_params->ringing_params[0].hw_params, 0);
+ rc = msm_camera_i2c_write_table_w_microdelay(&a_ctrl->i2c_client,
+ a_ctrl->i2c_reg_tbl, a_ctrl->i2c_tbl_index,
+ a_ctrl->i2c_data_type);
+ if (rc < 0) {
+ pr_err("%s: i2c write error:%d\n",
+ __func__, rc);
+ return rc;
+ }
+ a_ctrl->i2c_tbl_index = 0;
a_ctrl->curr_step_pos = dest_step_position;
return rc;
}
-int32_t msm_actuator_move_focus(
+static int32_t msm_actuator_move_focus(
struct msm_actuator_ctrl_t *a_ctrl,
struct msm_actuator_move_params_t *move_params)
{
@@ -241,6 +236,7 @@
return rc;
curr_lens_pos = a_ctrl->step_position_table[a_ctrl->curr_step_pos];
+ a_ctrl->i2c_tbl_index = 0;
CDBG("curr_step_pos =%d dest_step_pos =%d curr_lens_pos=%d\n",
a_ctrl->curr_step_pos, dest_step_pos, curr_lens_pos);
@@ -299,10 +295,20 @@
a_ctrl->curr_step_pos = target_step_pos;
}
+ rc = msm_camera_i2c_write_table_w_microdelay(&a_ctrl->i2c_client,
+ a_ctrl->i2c_reg_tbl, a_ctrl->i2c_tbl_index,
+ a_ctrl->i2c_data_type);
+ if (rc < 0) {
+ pr_err("%s: i2c write error:%d\n",
+ __func__, rc);
+ return rc;
+ }
+ a_ctrl->i2c_tbl_index = 0;
+
return rc;
}
-int32_t msm_actuator_init_step_table(struct msm_actuator_ctrl_t *a_ctrl,
+static int32_t msm_actuator_init_step_table(struct msm_actuator_ctrl_t *a_ctrl,
struct msm_actuator_set_info_t *set_info)
{
int16_t code_per_step = 0;
@@ -361,7 +367,7 @@
return rc;
}
-int32_t msm_actuator_set_default_focus(
+static int32_t msm_actuator_set_default_focus(
struct msm_actuator_ctrl_t *a_ctrl,
struct msm_actuator_move_params_t *move_params)
{
@@ -373,7 +379,7 @@
return rc;
}
-int32_t msm_actuator_power_down(struct msm_actuator_ctrl_t *a_ctrl)
+static int32_t msm_actuator_power_down(struct msm_actuator_ctrl_t *a_ctrl)
{
int32_t rc = 0;
if (a_ctrl->vcm_enable) {
@@ -384,10 +390,13 @@
kfree(a_ctrl->step_position_table);
a_ctrl->step_position_table = NULL;
+ kfree(a_ctrl->i2c_reg_tbl);
+ a_ctrl->i2c_reg_tbl = NULL;
+ a_ctrl->i2c_tbl_index = 0;
return rc;
}
-int32_t msm_actuator_init(struct msm_actuator_ctrl_t *a_ctrl,
+static int32_t msm_actuator_init(struct msm_actuator_ctrl_t *a_ctrl,
struct msm_actuator_set_info_t *set_info) {
struct reg_settings_t *init_settings = NULL;
int32_t rc = -EFAULT;
@@ -412,7 +421,6 @@
pr_err("%s: MAX_ACTUATOR_REGION is exceeded.\n", __func__);
return -EFAULT;
}
- a_ctrl->total_steps = set_info->af_tuning_params.total_steps;
a_ctrl->pwd_step = set_info->af_tuning_params.pwd_step;
a_ctrl->total_steps = set_info->af_tuning_params.total_steps;
@@ -430,11 +438,22 @@
__func__);
return -EFAULT;
}
+
+ a_ctrl->i2c_reg_tbl =
+ kmalloc(sizeof(struct msm_camera_i2c_reg_tbl) *
+ (set_info->af_tuning_params.total_steps + 1), GFP_KERNEL);
+ if (!a_ctrl->i2c_reg_tbl) {
+ pr_err("%s kmalloc fail\n", __func__);
+ return -EFAULT;
+ }
+
if (copy_from_user(&a_ctrl->reg_tbl,
(void *)set_info->actuator_params.reg_tbl_params,
a_ctrl->reg_tbl_size *
- sizeof(struct msm_actuator_reg_params_t)))
+ sizeof(struct msm_actuator_reg_params_t))) {
+ kfree(a_ctrl->i2c_reg_tbl);
return -EFAULT;
+ }
if (set_info->actuator_params.init_setting_size) {
if (a_ctrl->func_tbl->actuator_init_focus) {
@@ -442,6 +461,7 @@
(set_info->actuator_params.init_setting_size),
GFP_KERNEL);
if (init_settings == NULL) {
+ kfree(a_ctrl->i2c_reg_tbl);
pr_err("%s Error allocating memory for init_settings\n",
__func__);
return -EFAULT;
@@ -451,6 +471,7 @@
set_info->actuator_params.init_setting_size *
sizeof(struct reg_settings_t))) {
kfree(init_settings);
+ kfree(a_ctrl->i2c_reg_tbl);
pr_err("%s Error copying init_settings\n",
__func__);
return -EFAULT;
@@ -461,6 +482,7 @@
init_settings);
kfree(init_settings);
if (rc < 0) {
+ kfree(a_ctrl->i2c_reg_tbl);
pr_err("%s Error actuator_init_focus\n",
__func__);
return -EFAULT;
@@ -480,7 +502,7 @@
}
-int32_t msm_actuator_config(struct msm_actuator_ctrl_t *a_ctrl,
+static int32_t msm_actuator_config(struct msm_actuator_ctrl_t *a_ctrl,
void __user *argp)
{
struct msm_actuator_cfg_data cdata;
@@ -519,7 +541,7 @@
return rc;
}
-int32_t msm_actuator_i2c_probe(
+static int32_t msm_actuator_i2c_probe(
struct i2c_client *client,
const struct i2c_device_id *id)
{
@@ -554,7 +576,7 @@
return rc;
}
-int32_t msm_actuator_power_up(struct msm_actuator_ctrl_t *a_ctrl)
+static int32_t msm_actuator_power_up(struct msm_actuator_ctrl_t *a_ctrl)
{
int rc = 0;
CDBG("%s called\n", __func__);
@@ -594,7 +616,7 @@
return i2c_add_driver(msm_actuator_t.i2c_driver);
}
-long msm_actuator_subdev_ioctl(struct v4l2_subdev *sd,
+static long msm_actuator_subdev_ioctl(struct v4l2_subdev *sd,
unsigned int cmd, void *arg)
{
struct msm_actuator_ctrl_t *a_ctrl = get_actrl(sd);
@@ -607,7 +629,7 @@
}
}
-int32_t msm_actuator_power(struct v4l2_subdev *sd, int on)
+static int32_t msm_actuator_power(struct v4l2_subdev *sd, int on)
{
int rc = 0;
struct msm_actuator_ctrl_t *a_ctrl = get_actrl(sd);
@@ -644,6 +666,31 @@
};
+static struct msm_actuator msm_vcm_actuator_table = {
+ .act_type = ACTUATOR_VCM,
+ .func_tbl = {
+ .actuator_init_step_table = msm_actuator_init_step_table,
+ .actuator_move_focus = msm_actuator_move_focus,
+ .actuator_write_focus = msm_actuator_write_focus,
+ .actuator_set_default_focus = msm_actuator_set_default_focus,
+ .actuator_init_focus = msm_actuator_init_focus,
+ .actuator_parse_i2c_params = msm_actuator_parse_i2c_params,
+ },
+};
+
+static struct msm_actuator msm_piezo_actuator_table = {
+ .act_type = ACTUATOR_PIEZO,
+ .func_tbl = {
+ .actuator_init_step_table = NULL,
+ .actuator_move_focus = msm_actuator_piezo_move_focus,
+ .actuator_write_focus = NULL,
+ .actuator_set_default_focus =
+ msm_actuator_piezo_set_default_focus,
+ .actuator_init_focus = msm_actuator_init_focus,
+ .actuator_parse_i2c_params = msm_actuator_parse_i2c_params,
+ },
+};
+
subsys_initcall(msm_actuator_i2c_add_driver);
MODULE_DESCRIPTION("MSM ACTUATOR");
MODULE_LICENSE("GPL v2");
diff --git a/drivers/media/video/msm/actuators/msm_actuator.h b/drivers/media/video/msm/actuators/msm_actuator.h
index 4f936e7..82157e8 100644
--- a/drivers/media/video/msm/actuators/msm_actuator.h
+++ b/drivers/media/video/msm/actuators/msm_actuator.h
@@ -51,8 +51,8 @@
struct msm_actuator_move_params_t *);
int32_t (*actuator_move_focus) (struct msm_actuator_ctrl_t *,
struct msm_actuator_move_params_t *);
- int32_t (*actuator_i2c_write)(struct msm_actuator_ctrl_t *,
- int16_t, uint32_t);
+ int32_t (*actuator_parse_i2c_params)(struct msm_actuator_ctrl_t *,
+ int16_t, uint32_t, uint16_t);
int32_t (*actuator_write_focus)(struct msm_actuator_ctrl_t *,
uint16_t,
struct damping_params_t *,
@@ -87,40 +87,11 @@
uint32_t total_steps;
uint16_t pwd_step;
uint16_t initial_code;
+ struct msm_camera_i2c_reg_tbl *i2c_reg_tbl;
+ uint16_t i2c_tbl_index;
};
struct msm_actuator_ctrl_t *get_actrl(struct v4l2_subdev *sd);
-int32_t msm_actuator_i2c_write(struct msm_actuator_ctrl_t *a_ctrl,
- int16_t next_lens_position, uint32_t hw_params);
-int32_t msm_actuator_init_focus(struct msm_actuator_ctrl_t *a_ctrl,
- uint16_t size, enum msm_actuator_data_type type,
- struct reg_settings_t *settings);
-int32_t msm_actuator_i2c_write_b_af(struct msm_actuator_ctrl_t *a_ctrl,
- uint8_t msb,
- uint8_t lsb);
-int32_t msm_actuator_move_focus(struct msm_actuator_ctrl_t *a_ctrl,
- struct msm_actuator_move_params_t *move_params);
-int32_t msm_actuator_piezo_move_focus(
- struct msm_actuator_ctrl_t *a_ctrl,
- struct msm_actuator_move_params_t *move_params);
-int32_t msm_actuator_init_step_table(struct msm_actuator_ctrl_t *a_ctrl,
- struct msm_actuator_set_info_t *set_info);
-int32_t msm_actuator_set_default_focus(struct msm_actuator_ctrl_t *a_ctrl,
- struct msm_actuator_move_params_t *move_params);
-int32_t msm_actuator_piezo_set_default_focus(
- struct msm_actuator_ctrl_t *a_ctrl,
- struct msm_actuator_move_params_t *move_params);
-int32_t msm_actuator_i2c_probe(struct i2c_client *client,
- const struct i2c_device_id *id);
-int32_t msm_actuator_write_focus(struct msm_actuator_ctrl_t *a_ctrl,
- uint16_t curr_lens_pos, struct damping_params_t *damping_params,
- int8_t sign_direction, int16_t code_boundary);
-int32_t msm_actuator_write_focus2(struct msm_actuator_ctrl_t *a_ctrl,
- uint16_t curr_lens_pos, struct damping_params_t *damping_params,
- int8_t sign_direction, int16_t code_boundary);
-long msm_actuator_subdev_ioctl(struct v4l2_subdev *sd,
- unsigned int cmd, void *arg);
-int32_t msm_actuator_power(struct v4l2_subdev *sd, int on);
#define VIDIOC_MSM_ACTUATOR_CFG \
_IOWR('V', BASE_VIDIOC_PRIVATE + 11, void __user *)
diff --git a/drivers/media/video/msm/cpp/Makefile b/drivers/media/video/msm/cpp/Makefile
new file mode 100644
index 0000000..b4f1fdf
--- /dev/null
+++ b/drivers/media/video/msm/cpp/Makefile
@@ -0,0 +1,5 @@
+GCC_VERSION := $(shell $(CONFIG_SHELL) $(PWD)/scripts/gcc-version.sh $(CROSS_COMPILE)gcc)
+ccflags-y += -Idrivers/media/video/msm
+ccflags-y += -Idrivers/media/video/msm/io
+obj-$(CONFIG_MSM_CPP) += msm_cpp.o
+
diff --git a/drivers/media/video/msm/cpp/msm_cpp.c b/drivers/media/video/msm/cpp/msm_cpp.c
new file mode 100644
index 0000000..e569388
--- /dev/null
+++ b/drivers/media/video/msm/cpp/msm_cpp.c
@@ -0,0 +1,412 @@
+/* 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/delay.h>
+#include <linux/clk.h>
+#include <linux/io.h>
+#include <linux/module.h>
+#include <mach/board.h>
+#include <mach/camera.h>
+#include <mach/vreg.h>
+#include <media/msm_isp.h>
+#include <linux/proc_fs.h>
+#include <linux/debugfs.h>
+
+#include "msm_cpp.h"
+#include "msm.h"
+
+#define CONFIG_MSM_CPP_DBG 0
+
+#if CONFIG_MSM_CPP_DBG
+#define CPP_DBG(fmt, args...) pr_info(fmt, ##args)
+#else
+#define CPP_DBG(fmt, args...) pr_debug(fmt, ##args)
+#endif
+
+static int cpp_open_node(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh)
+{
+ uint32_t i;
+ struct cpp_device *cpp_dev = v4l2_get_subdevdata(sd);
+ CPP_DBG("%s\n", __func__);
+
+ mutex_lock(&cpp_dev->mutex);
+ if (cpp_dev->cpp_open_cnt == MAX_ACTIVE_CPP_INSTANCE) {
+ pr_err("No free CPP instance\n");
+ mutex_unlock(&cpp_dev->mutex);
+ return -ENODEV;
+ }
+
+ for (i = 0; i < MAX_ACTIVE_CPP_INSTANCE; i++) {
+ if (cpp_dev->cpp_subscribe_list[i].active == 0) {
+ cpp_dev->cpp_subscribe_list[i].active = 1;
+ cpp_dev->cpp_subscribe_list[i].vfh = &fh->vfh;
+ break;
+ }
+ }
+ if (i == MAX_ACTIVE_CPP_INSTANCE) {
+ pr_err("No free instance\n");
+ mutex_unlock(&cpp_dev->mutex);
+ return -ENODEV;
+ }
+
+ CPP_DBG("open %d %p\n", i, &fh->vfh);
+ cpp_dev->cpp_open_cnt++;
+ mutex_unlock(&cpp_dev->mutex);
+ return 0;
+}
+
+static int cpp_close_node(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh)
+{
+ uint32_t i;
+ struct cpp_device *cpp_dev = v4l2_get_subdevdata(sd);
+ mutex_lock(&cpp_dev->mutex);
+ for (i = 0; i < MAX_ACTIVE_CPP_INSTANCE; i++) {
+ if (cpp_dev->cpp_subscribe_list[i].vfh == &fh->vfh) {
+ cpp_dev->cpp_subscribe_list[i].active = 0;
+ cpp_dev->cpp_subscribe_list[i].vfh = NULL;
+ break;
+ }
+ }
+ if (i == MAX_ACTIVE_CPP_INSTANCE) {
+ pr_err("Invalid close\n");
+ mutex_unlock(&cpp_dev->mutex);
+ return -ENODEV;
+ }
+
+ CPP_DBG("close %d %p\n", i, &fh->vfh);
+ cpp_dev->cpp_open_cnt--;
+ mutex_unlock(&cpp_dev->mutex);
+ return 0;
+}
+
+static const struct v4l2_subdev_internal_ops msm_cpp_internal_ops = {
+ .open = cpp_open_node,
+ .close = cpp_close_node,
+};
+
+static int msm_cpp_notify_frame_done(struct cpp_device *cpp_dev)
+{
+ struct v4l2_event v4l2_evt;
+ struct msm_queue_cmd *frame_qcmd;
+ struct msm_queue_cmd *event_qcmd;
+ struct msm_cpp_frame_info_t *processed_frame;
+ struct msm_device_queue *queue = &cpp_dev->processing_q;
+
+ if (queue->len > 0) {
+ frame_qcmd = msm_dequeue(queue, list_frame);
+ processed_frame = frame_qcmd->command;
+
+ event_qcmd = kzalloc(sizeof(struct msm_queue_cmd), GFP_KERNEL);
+ if (!event_qcmd) {
+ pr_err("%s Insufficient memory. return", __func__);
+ return -ENOMEM;
+ }
+ atomic_set(&event_qcmd->on_heap, 1);
+ event_qcmd->command = processed_frame;
+ CPP_DBG("fid %d\n", processed_frame->frame_id);
+ msm_enqueue(&cpp_dev->eventData_q, &event_qcmd->list_eventdata);
+
+ v4l2_evt.id = processed_frame->inst_id;
+ v4l2_evt.type = V4L2_EVENT_CPP_FRAME_DONE;
+ v4l2_event_queue(cpp_dev->subdev.devnode, &v4l2_evt);
+ }
+ return 0;
+}
+
+static int msm_cpp_send_frame_to_hardware(struct cpp_device *cpp_dev)
+{
+ struct msm_queue_cmd *frame_qcmd;
+ struct msm_cpp_frame_info_t *process_frame;
+ struct msm_device_queue *queue;
+
+ if (cpp_dev->processing_q.len < MAX_CPP_PROCESSING_FRAME) {
+ while (cpp_dev->processing_q.len < MAX_CPP_PROCESSING_FRAME) {
+ if (cpp_dev->realtime_q.len != 0) {
+ queue = &cpp_dev->realtime_q;
+ } else if (cpp_dev->offline_q.len != 0) {
+ queue = &cpp_dev->offline_q;
+ } else {
+ pr_debug("%s: All frames queued\n", __func__);
+ break;
+ }
+ frame_qcmd = msm_dequeue(queue, list_frame);
+ /*TBD Code to actually sending to harware*/
+ process_frame = frame_qcmd->command;
+
+ msm_enqueue(&cpp_dev->processing_q,
+ &frame_qcmd->list_frame);
+ }
+ }
+ return 0;
+}
+
+long msm_cpp_subdev_ioctl(struct v4l2_subdev *sd,
+ unsigned int cmd, void *arg)
+{
+ struct cpp_device *cpp_dev = v4l2_get_subdevdata(sd);
+ struct msm_camera_v4l2_ioctl_t *ioctl_ptr = arg;
+ int rc = 0;
+
+ CPP_DBG("%s: %d\n", __func__, __LINE__);
+ mutex_lock(&cpp_dev->mutex);
+ CPP_DBG("%s cmd: %d\n", __func__, cmd);
+ switch (cmd) {
+ case VIDIOC_MSM_CPP_CFG: {
+ struct msm_queue_cmd *frame_qcmd;
+ struct msm_cpp_frame_info_t *new_frame =
+ kzalloc(sizeof(struct msm_cpp_frame_info_t),
+ GFP_KERNEL);
+ if (!new_frame) {
+ pr_err("%s Insufficient memory. return", __func__);
+ mutex_unlock(&cpp_dev->mutex);
+ return -ENOMEM;
+ }
+
+ COPY_FROM_USER(rc, new_frame,
+ (void __user *)ioctl_ptr->ioctl_ptr,
+ sizeof(struct msm_cpp_frame_info_t));
+ if (rc) {
+ ERR_COPY_FROM_USER();
+ kfree(new_frame);
+ mutex_unlock(&cpp_dev->mutex);
+ return -EINVAL;
+ }
+
+ frame_qcmd = kzalloc(sizeof(struct msm_queue_cmd), GFP_KERNEL);
+ if (!frame_qcmd) {
+ pr_err("%s Insufficient memory. return", __func__);
+ kfree(new_frame);
+ mutex_unlock(&cpp_dev->mutex);
+ return -ENOMEM;
+ }
+
+ atomic_set(&frame_qcmd->on_heap, 1);
+ frame_qcmd->command = new_frame;
+ if (new_frame->frame_type == MSM_CPP_REALTIME_FRAME) {
+ msm_enqueue(&cpp_dev->realtime_q,
+ &frame_qcmd->list_frame);
+ } else if (new_frame->frame_type == MSM_CPP_OFFLINE_FRAME) {
+ msm_enqueue(&cpp_dev->offline_q,
+ &frame_qcmd->list_frame);
+ } else {
+ pr_err("%s: Invalid frame type\n", __func__);
+ kfree(new_frame);
+ kfree(frame_qcmd);
+ mutex_unlock(&cpp_dev->mutex);
+ return -EINVAL;
+ }
+ break;
+ }
+ case VIDIOC_MSM_CPP_GET_EVENTPAYLOAD: {
+ struct msm_device_queue *queue = &cpp_dev->eventData_q;
+ struct msm_queue_cmd *event_qcmd;
+ struct msm_cpp_frame_info_t *process_frame;
+ event_qcmd = msm_dequeue(queue, list_eventdata);
+ process_frame = event_qcmd->command;
+ CPP_DBG("fid %d\n", process_frame->frame_id);
+ if (copy_to_user((void __user *)ioctl_ptr->ioctl_ptr,
+ process_frame,
+ sizeof(struct msm_cpp_frame_info_t))) {
+ mutex_unlock(&cpp_dev->mutex);
+ return -EINVAL;
+ }
+ kfree(process_frame);
+ kfree(event_qcmd);
+ break;
+ }
+ }
+ mutex_unlock(&cpp_dev->mutex);
+ CPP_DBG("%s: %d\n", __func__, __LINE__);
+ return 0;
+}
+
+int msm_cpp_subscribe_event(struct v4l2_subdev *sd, struct v4l2_fh *fh,
+ struct v4l2_event_subscription *sub)
+{
+ CPP_DBG("%s\n", __func__);
+ return v4l2_event_subscribe(fh, sub, MAX_CPP_V4l2_EVENTS);
+}
+
+int msm_cpp_unsubscribe_event(struct v4l2_subdev *sd, struct v4l2_fh *fh,
+ struct v4l2_event_subscription *sub)
+{
+ CPP_DBG("%s\n", __func__);
+ return v4l2_event_unsubscribe(fh, sub);
+}
+
+static struct v4l2_subdev_core_ops msm_cpp_subdev_core_ops = {
+ .ioctl = msm_cpp_subdev_ioctl,
+ .subscribe_event = msm_cpp_subscribe_event,
+ .unsubscribe_event = msm_cpp_unsubscribe_event,
+};
+
+static const struct v4l2_subdev_ops msm_cpp_subdev_ops = {
+ .core = &msm_cpp_subdev_core_ops,
+};
+
+static int msm_cpp_enable_debugfs(struct cpp_device *cpp_dev);
+
+static struct v4l2_file_operations msm_cpp_v4l2_subdev_fops;
+
+static long msm_cpp_subdev_do_ioctl(
+ struct file *file, unsigned int cmd, void *arg)
+{
+ struct video_device *vdev = video_devdata(file);
+ struct v4l2_subdev *sd = vdev_to_v4l2_subdev(vdev);
+ struct v4l2_fh *vfh = file->private_data;
+
+ switch (cmd) {
+ case VIDIOC_DQEVENT:
+ if (!(sd->flags & V4L2_SUBDEV_FL_HAS_EVENTS))
+ return -ENOIOCTLCMD;
+
+ return v4l2_event_dequeue(vfh, arg, file->f_flags & O_NONBLOCK);
+
+ case VIDIOC_SUBSCRIBE_EVENT:
+ return v4l2_subdev_call(sd, core, subscribe_event, vfh, arg);
+
+ case VIDIOC_UNSUBSCRIBE_EVENT:
+ return v4l2_subdev_call(sd, core, unsubscribe_event, vfh, arg);
+
+ case VIDIOC_MSM_CPP_GET_INST_INFO: {
+ uint32_t i;
+ struct cpp_device *cpp_dev = v4l2_get_subdevdata(sd);
+ struct msm_camera_v4l2_ioctl_t *ioctl_ptr = arg;
+ struct msm_cpp_frame_info_t inst_info;
+ for (i = 0; i < MAX_ACTIVE_CPP_INSTANCE; i++) {
+ if (cpp_dev->cpp_subscribe_list[i].vfh == vfh) {
+ inst_info.inst_id = i;
+ break;
+ }
+ }
+ if (copy_to_user(
+ (void __user *)ioctl_ptr->ioctl_ptr, &inst_info,
+ sizeof(struct msm_cpp_frame_info_t))) {
+ return -EINVAL;
+ }
+ }
+ break;
+ default:
+ return v4l2_subdev_call(sd, core, ioctl, cmd, arg);
+ }
+
+ return 0;
+}
+
+static long msm_cpp_subdev_fops_ioctl(struct file *file, unsigned int cmd,
+ unsigned long arg)
+{
+ return video_usercopy(file, cmd, arg, msm_cpp_subdev_do_ioctl);
+}
+
+static int __devinit cpp_probe(struct platform_device *pdev)
+{
+ struct cpp_device *cpp_dev;
+ struct msm_cam_subdev_info sd_info;
+ int rc = 0;
+ CDBG("%s: device id = %d\n", __func__, pdev->id);
+ cpp_dev = kzalloc(sizeof(struct cpp_device), GFP_KERNEL);
+ if (!cpp_dev) {
+ pr_err("%s: no enough memory\n", __func__);
+ return -ENOMEM;
+ }
+ v4l2_subdev_init(&cpp_dev->subdev, &msm_cpp_subdev_ops);
+ cpp_dev->subdev.internal_ops = &msm_cpp_internal_ops;
+ snprintf(cpp_dev->subdev.name, ARRAY_SIZE(cpp_dev->subdev.name),
+ "cpp");
+ cpp_dev->subdev.flags |= V4L2_SUBDEV_FL_HAS_DEVNODE;
+ cpp_dev->subdev.flags |= V4L2_SUBDEV_FL_HAS_EVENTS;
+ v4l2_set_subdevdata(&cpp_dev->subdev, cpp_dev);
+ platform_set_drvdata(pdev, &cpp_dev->subdev);
+ mutex_init(&cpp_dev->mutex);
+
+ cpp_dev->pdev = pdev;
+
+ media_entity_init(&cpp_dev->subdev.entity, 0, NULL, 0);
+ cpp_dev->subdev.entity.type = MEDIA_ENT_T_DEVNODE_V4L;
+ cpp_dev->subdev.entity.group_id = CPP_DEV;
+ cpp_dev->subdev.entity.name = pdev->name;
+ sd_info.sdev_type = CPP_DEV;
+ sd_info.sd_index = pdev->id;
+ msm_cam_register_subdev_node(&cpp_dev->subdev, &sd_info);
+ msm_cpp_v4l2_subdev_fops.owner = v4l2_subdev_fops.owner;
+ msm_cpp_v4l2_subdev_fops.open = v4l2_subdev_fops.open;
+ msm_cpp_v4l2_subdev_fops.unlocked_ioctl = msm_cpp_subdev_fops_ioctl;
+ msm_cpp_v4l2_subdev_fops.release = v4l2_subdev_fops.release;
+ msm_cpp_v4l2_subdev_fops.poll = v4l2_subdev_fops.poll;
+
+ cpp_dev->subdev.devnode->fops = &msm_cpp_v4l2_subdev_fops;
+ cpp_dev->subdev.entity.revision = cpp_dev->subdev.devnode->num;
+ msm_cpp_enable_debugfs(cpp_dev);
+ msm_queue_init(&cpp_dev->eventData_q, "eventdata");
+ msm_queue_init(&cpp_dev->offline_q, "frame");
+ msm_queue_init(&cpp_dev->realtime_q, "frame");
+ msm_queue_init(&cpp_dev->processing_q, "frame");
+ cpp_dev->cpp_open_cnt = 0;
+
+ return rc;
+}
+
+static struct platform_driver cpp_driver = {
+ .probe = cpp_probe,
+ .driver = {
+ .name = MSM_CPP_DRV_NAME,
+ .owner = THIS_MODULE,
+ },
+};
+
+static int __init msm_cpp_init_module(void)
+{
+ return platform_driver_register(&cpp_driver);
+}
+
+static void __exit msm_cpp_exit_module(void)
+{
+ platform_driver_unregister(&cpp_driver);
+}
+
+static int msm_cpp_debugfs_stream_s(void *data, u64 val)
+{
+ struct cpp_device *cpp_dev = data;
+ CPP_DBG("CPP processing frame E\n");
+ while (1) {
+ mutex_lock(&cpp_dev->mutex);
+ msm_cpp_notify_frame_done(cpp_dev);
+ msm_cpp_send_frame_to_hardware(cpp_dev);
+ mutex_unlock(&cpp_dev->mutex);
+ msleep(20);
+ }
+ CPP_DBG("CPP processing frame X\n");
+ return 0;
+}
+
+DEFINE_SIMPLE_ATTRIBUTE(cpp_debugfs_stream, NULL,
+ msm_cpp_debugfs_stream_s, "%llu\n");
+
+static int msm_cpp_enable_debugfs(struct cpp_device *cpp_dev)
+{
+ struct dentry *debugfs_base;
+ debugfs_base = debugfs_create_dir("msm_camera", NULL);
+ if (!debugfs_base)
+ return -ENOMEM;
+
+ if (!debugfs_create_file("test", S_IRUGO | S_IWUSR, debugfs_base,
+ (void *)cpp_dev, &cpp_debugfs_stream))
+ return -ENOMEM;
+
+ return 0;
+}
+
+module_init(msm_cpp_init_module);
+module_exit(msm_cpp_exit_module);
+MODULE_DESCRIPTION("MSM CPP driver");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/media/video/msm/cpp/msm_cpp.h b/drivers/media/video/msm/cpp/msm_cpp.h
new file mode 100644
index 0000000..8c10cac
--- /dev/null
+++ b/drivers/media/video/msm/cpp/msm_cpp.h
@@ -0,0 +1,65 @@
+/* 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/clk.h>
+#include <linux/io.h>
+#include <linux/list.h>
+#include <media/v4l2-subdev.h>
+
+#define MAX_ACTIVE_CPP_INSTANCE 8
+#define MAX_CPP_PROCESSING_FRAME 2
+#define MAX_CPP_V4l2_EVENTS 30
+
+#define MSM_CPP_MICRO_BASE 0x4000
+#define MSM_CPP_MICRO_HW_VERSION 0x0000
+#define MSM_CPP_MICRO_IRQGEN_STAT 0x0004
+#define MSM_CPP_MICRO_IRQGEN_CLR 0x0008
+#define MSM_CPP_MICRO_IRQGEN_MASK 0x000C
+#define MSM_CPP_MICRO_FIFO_TX_DATA 0x0010
+#define MSM_CPP_MICRO_FIFO_TX_STAT 0x0014
+#define MSM_CPP_MICRO_FIFO_RX_DATA 0x0018
+#define MSM_CPP_MICRO_FIFO_RX_STAT 0x001C
+#define MSM_CPP_MICRO_BOOT_START 0x0020
+#define MSM_CPP_MICRO_BOOT_LDORG 0x0024
+#define MSM_CPP_MICRO_CLKEN_CTL 0x0030
+
+struct cpp_subscribe_info {
+ struct v4l2_fh *vfh;
+ uint32_t active;
+};
+
+struct cpp_device {
+ struct platform_device *pdev;
+ struct v4l2_subdev subdev;
+ struct resource *mem;
+ struct resource *irq;
+ struct resource *io;
+ void __iomem *base;
+ struct clk *cpp_clk[2];
+ struct mutex mutex;
+
+ struct cpp_subscribe_info cpp_subscribe_list[MAX_ACTIVE_CPP_INSTANCE];
+ uint32_t cpp_open_cnt;
+
+ struct msm_device_queue eventData_q; /*V4L2 Event Payload Queue*/
+
+ /*Offline Frame Queue
+ process when realtime queue is empty*/
+ struct msm_device_queue offline_q;
+ /*Realtime Frame Queue
+ process with highest priority*/
+ struct msm_device_queue realtime_q;
+ /*Processing Queue
+ store frame info for frames sent to microcontroller*/
+ struct msm_device_queue processing_q;
+};
+
diff --git a/drivers/media/video/msm/io/msm_camera_i2c.c b/drivers/media/video/msm/io/msm_camera_i2c.c
index cecf9b0..e946569 100644
--- a/drivers/media/video/msm/io/msm_camera_i2c.c
+++ b/drivers/media/video/msm/io/msm_camera_i2c.c
@@ -267,6 +267,35 @@
return rc;
}
+int32_t msm_camera_i2c_write_table_w_microdelay(
+ struct msm_camera_i2c_client *client,
+ struct msm_camera_i2c_reg_tbl *reg_tbl, uint16_t size,
+ enum msm_camera_i2c_data_type data_type)
+{
+ int i;
+ int32_t rc = -EFAULT;
+
+ if (!client || !reg_tbl)
+ return rc;
+
+ if ((client->addr_type != MSM_CAMERA_I2C_BYTE_ADDR
+ && client->addr_type != MSM_CAMERA_I2C_WORD_ADDR)
+ || (data_type != MSM_CAMERA_I2C_BYTE_DATA
+ && data_type != MSM_CAMERA_I2C_WORD_DATA))
+ return rc;
+
+ for (i = 0; i < size; i++) {
+ rc = msm_camera_i2c_write(client, reg_tbl->reg_addr,
+ reg_tbl->reg_data, data_type);
+ if (rc < 0)
+ break;
+ if (reg_tbl->delay)
+ usleep_range(reg_tbl->delay, reg_tbl->delay + 1000);
+ reg_tbl++;
+ }
+ return rc;
+}
+
int32_t msm_camera_i2c_write_tbl(struct msm_camera_i2c_client *client,
struct msm_camera_i2c_reg_conf *reg_conf_tbl, uint16_t size,
enum msm_camera_i2c_data_type data_type)
diff --git a/drivers/media/video/msm/io/msm_camera_i2c.h b/drivers/media/video/msm/io/msm_camera_i2c.h
index 01c8259..a0cdd77 100644
--- a/drivers/media/video/msm/io/msm_camera_i2c.h
+++ b/drivers/media/video/msm/io/msm_camera_i2c.h
@@ -58,6 +58,12 @@
enum msm_camera_i2c_cmd_type cmd_type;
};
+struct msm_camera_i2c_reg_tbl {
+ uint16_t reg_addr;
+ uint16_t reg_data;
+ uint16_t delay;
+};
+
struct msm_camera_i2c_conf_array {
struct msm_camera_i2c_reg_conf *conf;
uint16_t size;
@@ -107,6 +113,11 @@
uint16_t addr, uint16_t data,
enum msm_camera_i2c_data_type data_type);
+int32_t msm_camera_i2c_write_table_w_microdelay(
+ struct msm_camera_i2c_client *client,
+ struct msm_camera_i2c_reg_tbl *reg_tbl, uint16_t size,
+ enum msm_camera_i2c_data_type data_type);
+
int32_t msm_camera_i2c_write_tbl(struct msm_camera_i2c_client *client,
struct msm_camera_i2c_reg_conf *reg_conf_tbl, uint16_t size,
enum msm_camera_i2c_data_type data_type);
diff --git a/drivers/media/video/msm/mercury/msm_mercury_platform.c b/drivers/media/video/msm/mercury/msm_mercury_platform.c
index 9366ef3..67ce82d 100644
--- a/drivers/media/video/msm/mercury/msm_mercury_platform.c
+++ b/drivers/media/video/msm/mercury/msm_mercury_platform.c
@@ -11,7 +11,6 @@
*/
#include <linux/module.h>
-#include <linux/pm_qos_params.h>
#include <linux/clk.h>
#include <linux/io.h>
#include <linux/android_pmem.h>
diff --git a/drivers/media/video/msm/msm.c b/drivers/media/video/msm/msm.c
index d34b8e1..c6fadc0 100644
--- a/drivers/media/video/msm/msm.c
+++ b/drivers/media/video/msm/msm.c
@@ -166,17 +166,22 @@
struct msm_cam_v4l2_dev_inst, eventHandle);
D("%s\n", __func__);
WARN_ON(pctx != f->private_data);
+
+ mutex_lock(&pcam_inst->inst_lock);
rc = vb2_reqbufs(&pcam_inst->vid_bufq, pb);
if (rc < 0) {
pr_err("%s reqbufs failed %d ", __func__, rc);
+ mutex_unlock(&pcam_inst->inst_lock);
return rc;
}
if (!pb->count) {
/* Deallocation. free buf_offset array */
D("%s Inst %p freeing buffer offsets array",
__func__, pcam_inst);
- for (j = 0 ; j < pcam_inst->buf_count ; j++)
+ for (j = 0 ; j < pcam_inst->buf_count ; j++) {
kfree(pcam_inst->buf_offset[j]);
+ pcam_inst->buf_offset[j] = NULL;
+ }
kfree(pcam_inst->buf_offset);
pcam_inst->buf_offset = NULL;
/* If the userspace has deallocated all the
@@ -194,6 +199,7 @@
GFP_KERNEL);
if (!pcam_inst->buf_offset) {
pr_err("%s out of memory ", __func__);
+ mutex_unlock(&pcam_inst->inst_lock);
return -ENOMEM;
}
for (i = 0; i < pb->count; i++) {
@@ -202,15 +208,19 @@
pcam_inst->plane_info.num_planes, GFP_KERNEL);
if (!pcam_inst->buf_offset[i]) {
pr_err("%s out of memory ", __func__);
- for (j = i-1 ; j >= 0; j--)
+ for (j = i-1 ; j >= 0; j--) {
kfree(pcam_inst->buf_offset[j]);
+ pcam_inst->buf_offset[j] = NULL;
+ }
kfree(pcam_inst->buf_offset);
pcam_inst->buf_offset = NULL;
+ mutex_unlock(&pcam_inst->inst_lock);
return -ENOMEM;
}
}
}
pcam_inst->buf_count = pb->count;
+ mutex_unlock(&pcam_inst->inst_lock);
return rc;
}
@@ -218,13 +228,17 @@
struct v4l2_buffer *pb)
{
/* get the video device */
+ int rc = 0;
struct msm_cam_v4l2_dev_inst *pcam_inst;
pcam_inst = container_of(f->private_data,
struct msm_cam_v4l2_dev_inst, eventHandle);
D("%s\n", __func__);
WARN_ON(pctx != f->private_data);
- return vb2_querybuf(&pcam_inst->vid_bufq, pb);
+ mutex_lock(&pcam_inst->inst_lock);
+ rc = vb2_querybuf(&pcam_inst->vid_bufq, pb);
+ mutex_unlock(&pcam_inst->inst_lock);
+ return rc;
}
static int msm_camera_v4l2_qbuf(struct file *f, void *pctx,
@@ -240,8 +254,10 @@
pcam_inst->image_mode, pb->index);
WARN_ON(pctx != f->private_data);
+ mutex_lock(&pcam_inst->inst_lock);
if (!pcam_inst->buf_offset) {
pr_err("%s Buffer is already released. Returning.\n", __func__);
+ mutex_unlock(&pcam_inst->inst_lock);
return -EINVAL;
}
@@ -249,6 +265,7 @@
/* Reject the buffer if planes array was not allocated */
if (pb->m.planes == NULL) {
pr_err("%s Planes array is null\n", __func__);
+ mutex_unlock(&pcam_inst->inst_lock);
return -EINVAL;
}
for (i = 0; i < pcam_inst->plane_info.num_planes; i++) {
@@ -269,7 +286,7 @@
rc = vb2_qbuf(&pcam_inst->vid_bufq, pb);
D("%s, videobuf_qbuf mode %d and idx %d returns %d\n", __func__,
pcam_inst->image_mode, pb->index, rc);
-
+ mutex_unlock(&pcam_inst->inst_lock);
return rc;
}
@@ -285,6 +302,11 @@
D("%s\n", __func__);
WARN_ON(pctx != f->private_data);
+ mutex_lock(&pcam_inst->inst_lock);
+ if (0 == pcam_inst->streamon) {
+ mutex_unlock(&pcam_inst->inst_lock);
+ return -EACCES;
+ }
rc = vb2_dqbuf(&pcam_inst->vid_bufq, pb, f->f_flags & O_NONBLOCK);
D("%s, videobuf_dqbuf returns %d\n", __func__, rc);
@@ -292,6 +314,7 @@
/* Reject the buffer if planes array was not allocated */
if (pb->m.planes == NULL) {
pr_err("%s Planes array is null\n", __func__);
+ mutex_unlock(&pcam_inst->inst_lock);
return -EINVAL;
}
for (i = 0; i < pcam_inst->plane_info.num_planes; i++) {
@@ -309,6 +332,7 @@
pb->reserved = pcam_inst->buf_offset[pb->index][0].addr_offset;
}
+ mutex_unlock(&pcam_inst->inst_lock);
return rc;
}
@@ -325,9 +349,13 @@
D("%s Inst %p\n", __func__, pcam_inst);
WARN_ON(pctx != f->private_data);
+ mutex_lock(&pcam->vid_lock);
+ mutex_lock(&pcam_inst->inst_lock);
if ((buf_type != V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) &&
(buf_type != V4L2_BUF_TYPE_VIDEO_CAPTURE)) {
pr_err("%s Invalid buffer type ", __func__);
+ mutex_unlock(&pcam_inst->inst_lock);
+ mutex_unlock(&pcam->vid_lock);
return -EINVAL;
}
@@ -336,10 +364,10 @@
rc = vb2_streamon(&pcam_inst->vid_bufq, buf_type);
D("%s, videobuf_streamon returns %d\n", __func__, rc);
- mutex_lock(&pcam->vid_lock);
/* turn HW (VFE/sensor) streaming */
pcam_inst->streamon = 1;
rc = msm_server_streamon(pcam, pcam_inst->my_index);
+ mutex_unlock(&pcam_inst->inst_lock);
mutex_unlock(&pcam->vid_lock);
D("%s rc = %d\n", __func__, rc);
return rc;
@@ -367,16 +395,20 @@
/* first turn of HW (VFE/sensor) streaming so that buffers are
not in use when we free the buffers */
mutex_lock(&pcam->vid_lock);
+ mutex_lock(&pcam_inst->inst_lock);
pcam_inst->streamon = 0;
if (msm_server_get_usecount() > 0)
rc = msm_server_streamoff(pcam, pcam_inst->my_index);
- mutex_unlock(&pcam->vid_lock);
+
if (rc < 0)
pr_err("%s: hw failed to stop streaming\n", __func__);
/* stop buffer streaming */
rc = vb2_streamoff(&pcam_inst->vid_bufq, buf_type);
D("%s, videobuf_streamoff returns %d\n", __func__, rc);
+
+ mutex_unlock(&pcam_inst->inst_lock);
+ mutex_unlock(&pcam->vid_lock);
return rc;
}
@@ -466,11 +498,13 @@
D("%s\n", __func__);
WARN_ON(pctx != f->private_data);
+ mutex_lock(&pcam->vid_lock);
rc = msm_server_try_fmt(pcam, pfmt);
if (rc)
pr_err("Format %x not found, rc = %d\n",
pfmt->fmt.pix.pixelformat, rc);
+ mutex_unlock(&pcam->vid_lock);
return rc;
}
@@ -484,11 +518,13 @@
D("%s\n", __func__);
WARN_ON(pctx != f->private_data);
+ mutex_lock(&pcam->vid_lock);
rc = msm_server_try_fmt_mplane(pcam, pfmt);
if (rc)
pr_err("Format %x not found, rc = %d\n",
pfmt->fmt.pix_mp.pixelformat, rc);
+ mutex_unlock(&pcam->vid_lock);
return rc;
}
@@ -795,6 +831,7 @@
mutex_unlock(&pcam->vid_lock);
return rc;
}
+ mutex_init(&pcam_inst->inst_lock);
pcam_inst->sensor_pxlcode = pcam->usr_fmts[0].pxlcode;
pcam_inst->my_index = i;
pcam_inst->pcam = pcam;
@@ -887,7 +924,9 @@
pcam->dev_inst[i] = NULL;
pcam->use_count = 0;
}
+ pcam->dev_inst[i] = NULL;
mutex_unlock(&pcam->vid_lock);
+ mutex_destroy(&pcam_inst->inst_lock);
kfree(pcam_inst);
pr_err("%s: error end", __func__);
return rc;
@@ -986,6 +1025,7 @@
}
mutex_lock(&pcam->vid_lock);
+ mutex_lock(&pcam_inst->inst_lock);
if (pcam_inst->streamon) {
/*something went wrong since instance
@@ -1011,6 +1051,8 @@
v4l2_fh_del(&pcam_inst->eventHandle);
v4l2_fh_exit(&pcam_inst->eventHandle);
}
+ mutex_unlock(&pcam_inst->inst_lock);
+ mutex_destroy(&pcam_inst->inst_lock);
kfree(pcam_inst);
f->private_data = NULL;
diff --git a/drivers/media/video/msm/msm.h b/drivers/media/video/msm/msm.h
index d0322d1..7d07e7b 100644
--- a/drivers/media/video/msm/msm.h
+++ b/drivers/media/video/msm/msm.h
@@ -59,6 +59,7 @@
#define MSM_MERCURY_DRV_NAME "msm_mercury"
#define MSM_I2C_MUX_DRV_NAME "msm_cam_i2c_mux"
#define MSM_IRQ_ROUTER_DRV_NAME "msm_cam_irq_router"
+#define MSM_CPP_DRV_NAME "msm_cpp"
#define MAX_NUM_CSIPHY_DEV 3
#define MAX_NUM_CSID_DEV 4
@@ -68,6 +69,7 @@
#define MAX_NUM_AXI_DEV 2
#define MAX_NUM_VPE_DEV 1
#define MAX_NUM_JPEG_DEV 3
+#define MAX_NUM_CPP_DEV 1
enum msm_cam_subdev_type {
CSIPHY_DEV,
@@ -82,6 +84,7 @@
EEPROM_DEV,
GESTURE_DEV,
IRQ_ROUTER_DEV,
+ CPP_DEV,
};
/* msm queue management APIs*/
@@ -261,6 +264,7 @@
struct v4l2_subdev *vpe_sdev; /* vpe sub device */
struct v4l2_subdev *axi_sdev; /* axi sub device */
struct v4l2_subdev *eeprom_sdev; /* eeprom sub device */
+ struct v4l2_subdev *cpp_sdev;/*cpp sub device*/
struct msm_isp_ops *isp_sdev; /* isp sub device : camif/VFE */
struct msm_cam_config_dev *config_device;
@@ -343,6 +347,7 @@
int is_mem_map_inst;
struct img_plane_info plane_info;
int vbqueue_initialized;
+ struct mutex inst_lock;
};
struct msm_cam_mctl_node {
@@ -540,6 +545,7 @@
struct v4l2_subdev *axi_device[MAX_NUM_AXI_DEV];
struct v4l2_subdev *vpe_device[MAX_NUM_VPE_DEV];
struct v4l2_subdev *gesture_device;
+ struct v4l2_subdev *cpp_device[MAX_NUM_CPP_DEV];
struct v4l2_subdev *irqr_device;
spinlock_t intr_table_lock;
diff --git a/drivers/media/video/msm/msm_mctl.c b/drivers/media/video/msm/msm_mctl.c
index cdfad3b..1359792 100644
--- a/drivers/media/video/msm/msm_mctl.c
+++ b/drivers/media/video/msm/msm_mctl.c
@@ -1123,17 +1123,22 @@
struct msm_cam_v4l2_dev_inst, eventHandle);
D("%s\n", __func__);
WARN_ON(pctx != f->private_data);
+
+ mutex_lock(&pcam_inst->inst_lock);
rc = vb2_reqbufs(&pcam_inst->vid_bufq, pb);
if (rc < 0) {
pr_err("%s reqbufs failed %d ", __func__, rc);
+ mutex_unlock(&pcam_inst->inst_lock);
return rc;
}
if (!pb->count) {
/* Deallocation. free buf_offset array */
D("%s Inst %p freeing buffer offsets array",
__func__, pcam_inst);
- for (j = 0 ; j < pcam_inst->buf_count ; j++)
+ for (j = 0 ; j < pcam_inst->buf_count ; j++) {
kfree(pcam_inst->buf_offset[j]);
+ pcam_inst->buf_offset[j] = NULL;
+ }
kfree(pcam_inst->buf_offset);
pcam_inst->buf_offset = NULL;
/* If the userspace has deallocated all the
@@ -1151,6 +1156,7 @@
GFP_KERNEL);
if (!pcam_inst->buf_offset) {
pr_err("%s out of memory ", __func__);
+ mutex_unlock(&pcam_inst->inst_lock);
return -ENOMEM;
}
for (i = 0; i < pb->count; i++) {
@@ -1159,10 +1165,13 @@
pcam_inst->plane_info.num_planes, GFP_KERNEL);
if (!pcam_inst->buf_offset[i]) {
pr_err("%s out of memory ", __func__);
- for (j = i-1 ; j >= 0; j--)
+ for (j = i-1 ; j >= 0; j--) {
kfree(pcam_inst->buf_offset[j]);
+ pcam_inst->buf_offset[j] = NULL;
+ }
kfree(pcam_inst->buf_offset);
pcam_inst->buf_offset = NULL;
+ mutex_unlock(&pcam_inst->inst_lock);
return -ENOMEM;
}
}
@@ -1170,6 +1179,7 @@
pcam_inst->buf_count = pb->count;
D("%s inst %p, buf count %d ", __func__,
pcam_inst, pcam_inst->buf_count);
+ mutex_unlock(&pcam_inst->inst_lock);
return rc;
}
@@ -1177,13 +1187,17 @@
struct v4l2_buffer *pb)
{
/* get the video device */
+ int rc = 0;
struct msm_cam_v4l2_dev_inst *pcam_inst;
pcam_inst = container_of(f->private_data,
struct msm_cam_v4l2_dev_inst, eventHandle);
D("%s\n", __func__);
WARN_ON(pctx != f->private_data);
- return vb2_querybuf(&pcam_inst->vid_bufq, pb);
+ mutex_lock(&pcam_inst->inst_lock);
+ rc = vb2_querybuf(&pcam_inst->vid_bufq, pb);
+ mutex_unlock(&pcam_inst->inst_lock);
+ return rc;
}
static int msm_mctl_v4l2_qbuf(struct file *f, void *pctx,
@@ -1198,8 +1212,10 @@
D("%s Inst = %p\n", __func__, pcam_inst);
WARN_ON(pctx != f->private_data);
+ mutex_lock(&pcam_inst->inst_lock);
if (!pcam_inst->buf_offset) {
pr_err("%s Buffer is already released. Returning. ", __func__);
+ mutex_unlock(&pcam_inst->inst_lock);
return -EINVAL;
}
@@ -1207,6 +1223,7 @@
/* Reject the buffer if planes array was not allocated */
if (pb->m.planes == NULL) {
pr_err("%s Planes array is null ", __func__);
+ mutex_unlock(&pcam_inst->inst_lock);
return -EINVAL;
}
for (i = 0; i < pcam_inst->plane_info.num_planes; i++) {
@@ -1232,6 +1249,7 @@
rc = vb2_qbuf(&pcam_inst->vid_bufq, pb);
D("%s, videobuf_qbuf returns %d\n", __func__, rc);
+ mutex_unlock(&pcam_inst->inst_lock);
return rc;
}
@@ -1246,10 +1264,16 @@
D("%s\n", __func__);
WARN_ON(pctx != f->private_data);
+ mutex_lock(&pcam_inst->inst_lock);
+ if (0 == pcam_inst->streamon) {
+ mutex_unlock(&pcam_inst->inst_lock);
+ return -EACCES;
+ }
rc = vb2_dqbuf(&pcam_inst->vid_bufq, pb, f->f_flags & O_NONBLOCK);
D("%s, videobuf_dqbuf returns %d\n", __func__, rc);
+ mutex_unlock(&pcam_inst->inst_lock);
return rc;
}
@@ -1266,9 +1290,13 @@
D("%s Inst %p\n", __func__, pcam_inst);
WARN_ON(pctx != f->private_data);
+ mutex_lock(&pcam->mctl_node.dev_lock);
+ mutex_lock(&pcam_inst->inst_lock);
if ((buf_type != V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) &&
(buf_type != V4L2_BUF_TYPE_VIDEO_CAPTURE)) {
pr_err("%s Invalid buffer type ", __func__);
+ mutex_unlock(&pcam_inst->inst_lock);
+ mutex_unlock(&pcam->mctl_node.dev_lock);
return -EINVAL;
}
@@ -1277,9 +1305,9 @@
rc = vb2_streamon(&pcam_inst->vid_bufq, buf_type);
D("%s, videobuf_streamon returns %d\n", __func__, rc);
- mutex_lock(&pcam->mctl_node.dev_lock);
/* turn HW (VFE/sensor) streaming */
pcam_inst->streamon = 1;
+ mutex_unlock(&pcam_inst->inst_lock);
mutex_unlock(&pcam->mctl_node.dev_lock);
D("%s rc = %d\n", __func__, rc);
return rc;
@@ -1307,14 +1335,16 @@
/* first turn of HW (VFE/sensor) streaming so that buffers are
not in use when we free the buffers */
mutex_lock(&pcam->mctl_node.dev_lock);
+ mutex_lock(&pcam_inst->inst_lock);
pcam_inst->streamon = 0;
- mutex_unlock(&pcam->mctl_node.dev_lock);
if (rc < 0)
pr_err("%s: hw failed to stop streaming\n", __func__);
/* stop buffer streaming */
rc = vb2_streamoff(&pcam_inst->vid_bufq, buf_type);
D("%s, videobuf_streamoff returns %d\n", __func__, rc);
+ mutex_unlock(&pcam_inst->inst_lock);
+ mutex_unlock(&pcam->mctl_node.dev_lock);
return rc;
}
diff --git a/drivers/media/video/msm/sensors/imx074_v4l2.c b/drivers/media/video/msm/sensors/imx074_v4l2.c
index 3d23337..ddf0754 100644
--- a/drivers/media/video/msm/sensors/imx074_v4l2.c
+++ b/drivers/media/video/msm/sensors/imx074_v4l2.c
@@ -276,7 +276,7 @@
.sensor_config = msm_sensor_config,
.sensor_power_up = msm_sensor_power_up,
.sensor_power_down = msm_sensor_power_down,
- .sensor_adjust_frame_lines = msm_sensor_adjust_frame_lines,
+ .sensor_adjust_frame_lines = msm_sensor_adjust_frame_lines1,
.sensor_get_csi_params = msm_sensor_get_csi_params,
};
diff --git a/drivers/media/video/msm/sensors/imx091.c b/drivers/media/video/msm/sensors/imx091.c
index 49442e9..7fda037 100644
--- a/drivers/media/video/msm/sensors/imx091.c
+++ b/drivers/media/video/msm/sensors/imx091.c
@@ -303,7 +303,7 @@
.sensor_config = msm_sensor_config,
.sensor_power_up = msm_sensor_power_up,
.sensor_power_down = msm_sensor_power_down,
- .sensor_adjust_frame_lines = msm_sensor_adjust_frame_lines,
+ .sensor_adjust_frame_lines = msm_sensor_adjust_frame_lines1,
.sensor_get_csi_params = msm_sensor_get_csi_params,
};
diff --git a/drivers/media/video/msm/sensors/msm_sensor.c b/drivers/media/video/msm/sensors/msm_sensor.c
index 8ab3963..be1efe0 100644
--- a/drivers/media/video/msm/sensors/msm_sensor.c
+++ b/drivers/media/video/msm/sensors/msm_sensor.c
@@ -16,7 +16,7 @@
#include "msm_camera_i2c_mux.h"
/*=============================================================*/
-int32_t msm_sensor_adjust_frame_lines(struct msm_sensor_ctrl_t *s_ctrl,
+int32_t msm_sensor_adjust_frame_lines1(struct msm_sensor_ctrl_t *s_ctrl,
uint16_t res)
{
uint16_t cur_line = 0;
@@ -50,6 +50,45 @@
return 0;
}
+int32_t msm_sensor_adjust_frame_lines2(struct msm_sensor_ctrl_t *s_ctrl,
+ uint16_t res)
+{
+ uint16_t cur_line = 0;
+ uint16_t exp_fl_lines = 0;
+ uint8_t int_time[3];
+ if (s_ctrl->sensor_exp_gain_info) {
+ if (s_ctrl->prev_gain && s_ctrl->prev_line &&
+ s_ctrl->func_tbl->sensor_write_exp_gain)
+ s_ctrl->func_tbl->sensor_write_exp_gain(
+ s_ctrl,
+ s_ctrl->prev_gain,
+ s_ctrl->prev_line);
+
+ msm_camera_i2c_read_seq(s_ctrl->sensor_i2c_client,
+ s_ctrl->sensor_exp_gain_info->coarse_int_time_addr-1,
+ &int_time[0], 3);
+ cur_line |= int_time[0] << 12;
+ cur_line |= int_time[1] << 4;
+ cur_line |= int_time[2] >> 4;
+ exp_fl_lines = cur_line +
+ s_ctrl->sensor_exp_gain_info->vert_offset;
+ if (exp_fl_lines > s_ctrl->msm_sensor_reg->
+ output_settings[res].frame_length_lines)
+ msm_camera_i2c_write(s_ctrl->sensor_i2c_client,
+ s_ctrl->sensor_output_reg_addr->
+ frame_length_lines,
+ exp_fl_lines,
+ MSM_CAMERA_I2C_WORD_DATA);
+ CDBG("%s cur_line %x cur_fl_lines %x, exp_fl_lines %x\n",
+ __func__,
+ cur_line,
+ s_ctrl->msm_sensor_reg->
+ output_settings[res].frame_length_lines,
+ exp_fl_lines);
+ }
+ return 0;
+}
+
int32_t msm_sensor_write_init_settings(struct msm_sensor_ctrl_t *s_ctrl)
{
int32_t rc;
diff --git a/drivers/media/video/msm/sensors/msm_sensor.h b/drivers/media/video/msm/sensors/msm_sensor.h
index b1e584d..a3ddaa7 100644
--- a/drivers/media/video/msm/sensors/msm_sensor.h
+++ b/drivers/media/video/msm/sensors/msm_sensor.h
@@ -236,7 +236,10 @@
int32_t msm_sensor_write_output_settings(struct msm_sensor_ctrl_t *s_ctrl,
uint16_t res);
-int32_t msm_sensor_adjust_frame_lines(struct msm_sensor_ctrl_t *s_ctrl,
+int32_t msm_sensor_adjust_frame_lines1(struct msm_sensor_ctrl_t *s_ctrl,
+ uint16_t res);
+
+int32_t msm_sensor_adjust_frame_lines2(struct msm_sensor_ctrl_t *s_ctrl,
uint16_t res);
int32_t msm_sensor_setting(struct msm_sensor_ctrl_t *s_ctrl,
diff --git a/drivers/media/video/msm/sensors/ov2720.c b/drivers/media/video/msm/sensors/ov2720.c
index 03f1af1..e4c5061 100644
--- a/drivers/media/video/msm/sensors/ov2720.c
+++ b/drivers/media/video/msm/sensors/ov2720.c
@@ -783,7 +783,7 @@
.sensor_config = msm_sensor_config,
.sensor_power_up = msm_sensor_power_up,
.sensor_power_down = msm_sensor_power_down,
- .sensor_adjust_frame_lines = msm_sensor_adjust_frame_lines,
+ .sensor_adjust_frame_lines = msm_sensor_adjust_frame_lines2,
.sensor_get_csi_params = msm_sensor_get_csi_params,
};
diff --git a/drivers/media/video/msm/sensors/s5k3l1yx.c b/drivers/media/video/msm/sensors/s5k3l1yx.c
index d7aeb74..c24da00 100644
--- a/drivers/media/video/msm/sensors/s5k3l1yx.c
+++ b/drivers/media/video/msm/sensors/s5k3l1yx.c
@@ -652,7 +652,7 @@
.sensor_config = msm_sensor_config,
.sensor_power_up = msm_sensor_power_up,
.sensor_power_down = msm_sensor_power_down,
- .sensor_adjust_frame_lines = msm_sensor_adjust_frame_lines,
+ .sensor_adjust_frame_lines = msm_sensor_adjust_frame_lines1,
.sensor_get_csi_params = msm_sensor_get_csi_params,
};
diff --git a/drivers/media/video/msm/server/msm_cam_server.c b/drivers/media/video/msm/server/msm_cam_server.c
index f2bb65f..e21de29 100644
--- a/drivers/media/video/msm/server/msm_cam_server.c
+++ b/drivers/media/video/msm/server/msm_cam_server.c
@@ -637,6 +637,7 @@
__func__, tmp_cmd.type, (uint32_t)tmp_cmd.value,
tmp_cmd.length, tmp_cmd.status, rc);
kfree(ctrl_data);
+ ctrl_data = NULL;
return rc;
}
@@ -1894,8 +1895,17 @@
case GESTURE_DEV:
g_server_dev.gesture_device = sd;
break;
+
case IRQ_ROUTER_DEV:
g_server_dev.irqr_device = sd;
+
+ case CPP_DEV:
+ if (index >= MAX_NUM_CPP_DEV) {
+ pr_err("%s Invalid CPP idx %d", __func__, index);
+ err = -EINVAL;
+ break;
+ }
+ g_server_dev.cpp_device[index] = sd;
break;
default:
break;
@@ -2396,6 +2406,7 @@
/* Next, copy the userspace event ctrl structure */
if (copy_from_user((void *)&u_isp_event, user_ptr,
sizeof(struct msm_isp_event_ctrl))) {
+ rc = -EFAULT;
break;
}
/* Save the pointer of the user allocated command buffer*/
@@ -2407,6 +2418,7 @@
&ev, fp->f_flags & O_NONBLOCK);
if (rc < 0) {
pr_err("no pending events?");
+ rc = -EFAULT;
break;
}
/* Use k_isp_event to point to the event_ctrl structure
@@ -2436,6 +2448,7 @@
break;
}
kfree(k_msg_value);
+ k_msg_value = NULL;
}
}
}
@@ -2448,6 +2461,7 @@
break;
}
kfree(k_isp_event);
+ k_isp_event = NULL;
/* Copy the v4l2_event structure back to the user*/
if (copy_to_user((void __user *)arg, &ev,
diff --git a/drivers/misc/tsif.c b/drivers/misc/tsif.c
index 2b09d7c..aeda38c 100644
--- a/drivers/misc/tsif.c
+++ b/drivers/misc/tsif.c
@@ -304,7 +304,9 @@
for (i = size-1; i >= 0; i--) {
int tmp;
g = table + i;
- tmp = gpio_tlmm_config(g->gpio_cfg, GPIO_CFG_DISABLE);
+ tmp = gpio_tlmm_config(GPIO_CFG(GPIO_PIN(g->gpio_cfg),
+ 0, GPIO_CFG_INPUT, GPIO_CFG_PULL_DOWN, GPIO_CFG_2MA),
+ GPIO_CFG_DISABLE);
if (tmp) {
pr_err("gpio_tlmm_config(0x%08x, GPIO_CFG_DISABLE)"
" <%s> failed: %d\n",
@@ -681,7 +683,7 @@
while (tsif_device->xfer[0].busy ||
tsif_device->xfer[1].busy) {
msm_dmov_flush(tsif_device->dma, 1);
- msleep(10);
+ usleep(10000);
}
}
tsif_device->state = tsif_state_stopped;
@@ -1031,6 +1033,15 @@
return rc;
}
tsif_device->state = tsif_state_running;
+
+ /* make sure the GPIO's are set up */
+ rc = tsif_start_gpios(tsif_device);
+ if (rc) {
+ dev_err(&tsif_device->pdev->dev, "failed to start GPIOs\n");
+ tsif_dma_exit(tsif_device);
+ return rc;
+ }
+
/*
* DMA should be scheduled prior to TSIF hardware initialization,
* otherwise "bus error" will be reported by Data Mover
@@ -1046,6 +1057,7 @@
rc = tsif_start_hw(tsif_device);
if (rc) {
dev_err(&tsif_device->pdev->dev, "Unable to start HW\n");
+ tsif_stop_gpios(tsif_device);
tsif_dma_exit(tsif_device);
tsif_clock(tsif_device, 0);
return rc;
@@ -1067,10 +1079,19 @@
{
dev_info(&tsif_device->pdev->dev, "%s, state %d\n", __func__,
(int)tsif_device->state);
- /*
- * DMA should be flushed/stopped prior to TSIF hardware stop,
- * otherwise "bus error" will be reported by Data Mover
+
+ /* turn off the GPIO's to prevent new data from entering */
+ tsif_stop_gpios(tsif_device);
+
+ /* we unfortunately must sleep here to give the ADM time to
+ * complete any outstanding reads after the GPIO's are turned
+ * off. There is no indication from the ADM hardware that
+ * there are any outstanding reads on the bus, and if we
+ * stop the TSIF too quickly, it can cause a bus error.
*/
+ msleep(100);
+
+ /* now we can stop the core */
tsif_stop_hw(tsif_device);
tsif_dma_exit(tsif_device);
tsif_clock(tsif_device, 0);
@@ -1317,9 +1338,6 @@
}
dev_info(&pdev->dev, "remapped phys 0x%08x => virt %p\n",
tsif_device->memres->start, tsif_device->base);
- rc = tsif_start_gpios(tsif_device);
- if (rc)
- goto err_gpio;
pm_runtime_set_active(&pdev->dev);
pm_runtime_enable(&pdev->dev);
@@ -1355,8 +1373,6 @@
free_irq(tsif_device->irq, tsif_device);
err_irq:
tsif_debugfs_exit(tsif_device);
- tsif_stop_gpios(tsif_device);
-err_gpio:
iounmap(tsif_device->base);
err_ioremap:
err_rgn:
diff --git a/drivers/misc/tspp.c b/drivers/misc/tspp.c
index 81c6b65..4d7553e 100644
--- a/drivers/misc/tspp.c
+++ b/drivers/misc/tspp.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
@@ -1687,7 +1687,7 @@
/* map clocks */
if (data->tsif_pclk) {
- device->tsif_pclk = clk_get(NULL, data->tsif_pclk);
+ device->tsif_pclk = clk_get(&pdev->dev, data->tsif_pclk);
if (IS_ERR(device->tsif_pclk)) {
pr_err("tspp: failed to get %s",
data->tsif_pclk);
@@ -1697,7 +1697,7 @@
}
}
if (data->tsif_ref_clk) {
- device->tsif_ref_clk = clk_get(NULL, data->tsif_ref_clk);
+ device->tsif_ref_clk = clk_get(&pdev->dev, data->tsif_ref_clk);
if (IS_ERR(device->tsif_ref_clk)) {
pr_err("tspp: failed to get %s",
data->tsif_ref_clk);
diff --git a/drivers/net/usb/rmnet_usb_ctrl.c b/drivers/net/usb/rmnet_usb_ctrl.c
index a153de1..2972af0 100644
--- a/drivers/net/usb/rmnet_usb_ctrl.c
+++ b/drivers/net/usb/rmnet_usb_ctrl.c
@@ -521,8 +521,6 @@
dev->is_opened = 0;
mutex_unlock(&dev->dev_lock);
- rmnet_usb_ctrl_stop_rx(dev);
-
if (is_dev_connected(dev))
usb_kill_anchored_urbs(&dev->tx_submitted);
diff --git a/drivers/net/usb/rmnet_usb_data.c b/drivers/net/usb/rmnet_usb_data.c
index 9e1e252..55020a1 100644
--- a/drivers/net/usb/rmnet_usb_data.c
+++ b/drivers/net/usb/rmnet_usb_data.c
@@ -604,6 +604,7 @@
static const struct driver_info rmnet_info_pid9034 = {
.description = "RmNET net device",
+ .flags = FLAG_SEND_ZLP,
.bind = rmnet_usb_bind,
.tx_fixup = rmnet_usb_tx_fixup,
.rx_fixup = rmnet_usb_rx_fixup,
@@ -613,6 +614,7 @@
static const struct driver_info rmnet_info_pid9048 = {
.description = "RmNET net device",
+ .flags = FLAG_SEND_ZLP,
.bind = rmnet_usb_bind,
.tx_fixup = rmnet_usb_tx_fixup,
.rx_fixup = rmnet_usb_rx_fixup,
@@ -622,6 +624,7 @@
static const struct driver_info rmnet_info_pid904c = {
.description = "RmNET net device",
+ .flags = FLAG_SEND_ZLP,
.bind = rmnet_usb_bind,
.tx_fixup = rmnet_usb_tx_fixup,
.rx_fixup = rmnet_usb_rx_fixup,
diff --git a/drivers/power/power_supply_core.c b/drivers/power/power_supply_core.c
index be6ba04..e87b4bd 100644
--- a/drivers/power/power_supply_core.c
+++ b/drivers/power/power_supply_core.c
@@ -64,6 +64,24 @@
EXPORT_SYMBOL_GPL(power_supply_set_online);
/**
+ * power_supply_set_scope - set scope of the power supply
+ * @psy: the power supply to control
+ * @scope: value to set the scope property to, should be from
+ * the SCOPE enum in power_supply.h
+ */
+int power_supply_set_scope(struct power_supply *psy, int scope)
+{
+ const union power_supply_propval ret = {scope, };
+
+ if (psy->set_property)
+ return psy->set_property(psy, POWER_SUPPLY_PROP_SCOPE,
+ &ret);
+
+ return -ENXIO;
+}
+EXPORT_SYMBOL_GPL(power_supply_set_scope);
+
+/**
* power_supply_set_charge_type - set charge type of the power supply
* @psy: the power supply to control
* @enable: sets charge type property of power supply
diff --git a/drivers/slimbus/slimbus.c b/drivers/slimbus/slimbus.c
index 24da4d1..36414e0 100644
--- a/drivers/slimbus/slimbus.c
+++ b/drivers/slimbus/slimbus.c
@@ -1979,7 +1979,7 @@
}
}
/* Leave some slots for messaging space */
- if (opensl1[1] == 0 && opensl1[0] == 0)
+ if (opensl1[1] <= 0 && opensl1[0] <= 0)
return -EXFULL;
if (opensl1[1] > opensl1[0]) {
int temp = opensl1[0];
@@ -2184,7 +2184,7 @@
}
}
/* Leave some slots for messaging space */
- if (opensl3[1] == 0 && opensl3[0] == 0)
+ if (opensl3[1] <= 0 && opensl3[0] <= 0)
return -EXFULL;
/* swap 1st and 2nd bucket if 2nd bucket has more open slots */
if (opensl3[1] > opensl3[0]) {
diff --git a/drivers/spi/spi_qsd.c b/drivers/spi/spi_qsd.c
index 2c86e83..f2c881d 100644
--- a/drivers/spi/spi_qsd.c
+++ b/drivers/spi/spi_qsd.c
@@ -405,9 +405,17 @@
bytes_sent = 0;
}
- /* We'll send in chunks of SPI_MAX_LEN if larger */
- bytes_to_send = dd->tx_bytes_remaining / SPI_MAX_LEN ?
- SPI_MAX_LEN : dd->tx_bytes_remaining;
+ /* We'll send in chunks of SPI_MAX_LEN if larger than
+ * 4K bytes for targets that doesn't support infinite
+ * mode. Make sure this doesn't happen on targets that
+ * support infinite mode.
+ */
+ if (!dd->pdata->infinite_mode)
+ bytes_to_send = dd->tx_bytes_remaining / SPI_MAX_LEN ?
+ SPI_MAX_LEN : dd->tx_bytes_remaining;
+ else
+ bytes_to_send = dd->tx_bytes_remaining;
+
num_transfers = DIV_ROUND_UP(bytes_to_send, dd->bytes_per_word);
dd->unaligned_len = bytes_to_send % dd->burst_size;
num_rows = bytes_to_send / dd->burst_size;
@@ -512,12 +520,11 @@
msm_dmov_enqueue_cmd(dd->rx_dma_chan, &dd->rx_hdr);
}
-/* SPI core can send maximum of 4K transfers, because there is HW problem
- with infinite mode.
- Therefore, we are sending several chunks of 3K or less (depending on how
- much is left).
- Upon completion we send the next chunk, or complete the transfer if
- everything is finished.
+/* SPI core on targets that does not support infinite mode can send maximum of
+ 4K transfers, Therefore, we are sending several chunks of 3K or less
+ (depending on how much is left). Upon completion we send the next chunk,
+ or complete the transfer if everything is finished. On targets that support
+ infinite mode, we send all the bytes in as single chunk.
*/
static int msm_spi_dm_send_next(struct msm_spi *dd)
{
@@ -527,8 +534,10 @@
if (dd->mode != SPI_DMOV_MODE)
return 0;
- /* We need to send more chunks, if we sent max last time */
- if (dd->tx_bytes_remaining > SPI_MAX_LEN) {
+ /* On targets which does not support infinite mode,
+ We need to send more chunks, if we sent max last time */
+ if ((!dd->pdata->infinite_mode) &&
+ (dd->tx_bytes_remaining > SPI_MAX_LEN)) {
dd->tx_bytes_remaining -= SPI_MAX_LEN;
if (msm_spi_set_state(dd, SPI_OP_STATE_RESET))
return 0;
@@ -1766,6 +1775,8 @@
of_property_read_u32(node, "spi-max-frequency",
&pdata->max_clock_speed);
+ of_property_read_u32(node, "infinite_mode",
+ &pdata->infinite_mode);
return pdata;
}
diff --git a/drivers/tty/serial/msm_serial.c b/drivers/tty/serial/msm_serial.c
index 72bc8de..c483bb45 100644
--- a/drivers/tty/serial/msm_serial.c
+++ b/drivers/tty/serial/msm_serial.c
@@ -73,6 +73,7 @@
#ifdef CONFIG_SERIAL_MSM_RX_WAKEUP
struct msm_wakeup wakeup;
#endif
+ int uim;
};
#define UART_TO_MSM(uart_port) ((struct msm_port *) uart_port)
@@ -500,7 +501,22 @@
msm_port->clk_state = MSM_CLK_ON;
#endif
- if (port->uartclk == 19200000) {
+ if (msm_port->uim) {
+ msm_write(port,
+ UART_SIM_CFG_UIM_TX_MODE |
+ UART_SIM_CFG_UIM_RX_MODE |
+ UART_SIM_CFG_STOP_BIT_LEN_N(1) |
+ UART_SIM_CFG_SIM_CLK_ON |
+ UART_SIM_CFG_SIM_CLK_STOP_HIGH |
+ UART_SIM_CFG_SIM_SEL,
+ UART_SIM_CFG);
+
+ /* (TCXO * 16) / (5 * 372) = TCXO * 16 / 1860 */
+ msm_write(port, 0x08, UART_MREG);
+ msm_write(port, 0x19, UART_NREG);
+ msm_write(port, 0xe8, UART_DREG);
+ msm_write(port, 0x0e, UART_MNDREG);
+ } else if (port->uartclk == 19200000) {
/* clock is TCXO (19.2MHz) */
msm_write(port, 0x06, UART_MREG);
msm_write(port, 0xF1, UART_NREG);
@@ -603,6 +619,11 @@
{
struct msm_port *msm_port = UART_TO_MSM(port);
+ if (msm_port->uim)
+ msm_write(port,
+ UART_SIM_CFG_SIM_CLK_STOP_HIGH,
+ UART_SIM_CFG);
+
msm_port->imr = 0;
msm_write(port, 0, UART_IMR); /* disable interrupts */
@@ -1040,6 +1061,39 @@
return uart_add_one_port(&msm_uart_driver, port);
}
+static int __init msm_uim_probe(struct platform_device *pdev)
+{
+ struct msm_port *msm_port;
+ struct resource *resource;
+ struct uart_port *port;
+ int irq;
+
+ if (unlikely(pdev->id < 0 || pdev->id >= UART_NR))
+ return -ENXIO;
+
+ pr_info("msm_uim: detected port #%d\n", pdev->id);
+
+ port = get_port_from_line(pdev->id);
+ port->dev = &pdev->dev;
+ msm_port = UART_TO_MSM(port);
+
+ msm_port->uim = true;
+
+ resource = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ if (unlikely(!resource))
+ return -ENXIO;
+ port->mapbase = resource->start;
+
+ irq = platform_get_irq(pdev, 0);
+ if (unlikely(irq < 0))
+ return -ENXIO;
+ port->irq = irq;
+
+ platform_set_drvdata(pdev, port);
+
+ return uart_add_one_port(&msm_uart_driver, port);
+}
+
static int __devexit msm_serial_remove(struct platform_device *pdev)
{
struct msm_port *msm_port = platform_get_drvdata(pdev);
@@ -1125,6 +1179,14 @@
},
};
+static struct platform_driver msm_platform_uim_driver = {
+ .remove = msm_serial_remove,
+ .driver = {
+ .name = "msm_uim",
+ .owner = THIS_MODULE,
+ },
+};
+
static int __init msm_serial_init(void)
{
int ret;
@@ -1137,6 +1199,8 @@
if (unlikely(ret))
uart_unregister_driver(&msm_uart_driver);
+ platform_driver_probe(&msm_platform_uim_driver, msm_uim_probe);
+
printk(KERN_INFO "msm_serial: driver initialized\n");
return ret;
diff --git a/drivers/tty/serial/msm_serial.h b/drivers/tty/serial/msm_serial.h
index 65d0e30..a769825 100644
--- a/drivers/tty/serial/msm_serial.h
+++ b/drivers/tty/serial/msm_serial.h
@@ -1,7 +1,7 @@
/*
* Copyright (C) 2007 Google, Inc.
* Author: Robert Love <rlove@google.com>
- * Copyright (c) 2011, Code Aurora Forum. All rights reserved.
+ * Copyright (c) 2011-2012, Code Aurora Forum. All rights reserved.
*
* This software is licensed under the terms of the GNU General Public
* License version 2, as published by the Free Software Foundation, and
@@ -100,6 +100,16 @@
#define UART_DREG 0x0030
#define UART_MNDREG 0x0034
#define UART_IRDA 0x0038
+
+#define UART_SIM_CFG 0x003c
+#define UART_SIM_CFG_UIM_TX_MODE (1 << 17)
+#define UART_SIM_CFG_UIM_RX_MODE (1 << 16)
+#define UART_SIM_CFG_STOP_BIT_LEN_N(n) ((n) << 8)
+#define UART_SIM_CFG_SIM_CLK_ON (1 << 7)
+#define UART_SIM_CFG_SIM_CLK_TD8_SEL (1 << 6)
+#define UART_SIM_CFG_SIM_CLK_STOP_HIGH (1 << 5)
+#define UART_SIM_CFG_SIM_SEL (1 << 0)
+
#define UART_MISR_MODE 0x0040
#define UART_MISR_RESET 0x0044
#define UART_MISR_EXPORT 0x0048
diff --git a/drivers/tty/serial/msm_serial_hs_lite.c b/drivers/tty/serial/msm_serial_hs_lite.c
index 5735534..ce197be 100644
--- a/drivers/tty/serial/msm_serial_hs_lite.c
+++ b/drivers/tty/serial/msm_serial_hs_lite.c
@@ -122,9 +122,15 @@
},
{}
};
+
+#ifdef CONFIG_SERIAL_MSM_HSL_CONSOLE
+static int get_console_state(struct uart_port *port);
+#else
+static inline int get_console_state(struct uart_port *port) { return -ENODEV; };
+#endif
+
static struct dentry *debug_base;
static inline void wait_for_xmitr(struct uart_port *port);
-static int get_console_state(struct uart_port *port);
static inline void msm_hsl_write(struct uart_port *port,
unsigned int val, unsigned int off)
{
diff --git a/drivers/usb/gadget/u_sdio.c b/drivers/usb/gadget/u_sdio.c
index 8c4b4c7..5e9b0ec 100644
--- a/drivers/usb/gadget/u_sdio.c
+++ b/drivers/usb/gadget/u_sdio.c
@@ -1140,18 +1140,6 @@
goto free_sdio_ports;
}
-#ifdef DEBUG
- /* REVISIT: create one file per port
- * or do not create any file
- */
- if (i == 0) {
- ret = device_create_file(&g->dev, &dev_attr_input);
- if (ret)
- pr_err("%s: unable to create device file\n",
- __func__);
- }
-#endif
-
}
gsdio_debugfs_init();
diff --git a/drivers/usb/host/ehci-hub.c b/drivers/usb/host/ehci-hub.c
index 3098fbe..fff9465 100644
--- a/drivers/usb/host/ehci-hub.c
+++ b/drivers/usb/host/ehci-hub.c
@@ -380,6 +380,9 @@
ehci_writel(ehci, ehci->periodic_dma, &ehci->regs->frame_list);
ehci_writel(ehci, (u32) ehci->async->qh_dma, &ehci->regs->async_next);
+ /*CMD_RUN will be set after, PORT_RESUME gets cleared*/
+ if (ehci->resume_sof_bug)
+ ehci->command &= ~CMD_RUN;
/* restore CMD_RUN, framelist size, and irq threshold */
ehci_writel(ehci, ehci->command, &ehci->regs->command);
ehci->rh_state = EHCI_RH_RUNNING;
@@ -422,6 +425,17 @@
ehci_writel(ehci, temp, &ehci->regs->port_status [i]);
}
+ if (ehci->resume_sof_bug && resume_needed) {
+ /* root hub has only one port.
+ * PORT_RESUME gets cleared automatically. */
+ handshake(ehci, &ehci->regs->port_status[0], PORT_RESUME, 0,
+ 20000);
+ ehci_writel(ehci, ehci_readl(ehci,
+ &ehci->regs->command) | CMD_RUN,
+ &ehci->regs->command);
+ goto skip_clear_resume;
+ }
+
/* msleep for 20ms only if code is trying to resume port */
if (resume_needed) {
spin_unlock_irq(&ehci->lock);
@@ -438,6 +452,8 @@
ehci_vdbg (ehci, "resumed port %d\n", i + 1);
}
}
+
+skip_clear_resume:
(void) ehci_readl(ehci, &ehci->regs->command);
/* maybe re-activate the schedule(s) */
diff --git a/drivers/usb/host/ehci-msm-hsic.c b/drivers/usb/host/ehci-msm-hsic.c
index a95198c..874c728 100644
--- a/drivers/usb/host/ehci-msm-hsic.c
+++ b/drivers/usb/host/ehci-msm-hsic.c
@@ -730,13 +730,6 @@
skip_phy_resume:
- if (!(readl_relaxed(USB_USBCMD) & CMD_RUN) &&
- (readl_relaxed(USB_PORTSC) & PORT_SUSPEND)) {
- writel_relaxed(readl_relaxed(USB_USBCMD) | CMD_RUN ,
- USB_USBCMD);
- dbg_log_event(NULL, "Set RS", readl_relaxed(USB_USBCMD));
- }
-
usb_hcd_resume_root_hub(hcd);
atomic_set(&mehci->in_lpm, 0);
@@ -1246,6 +1239,8 @@
mehci->ehci.susp_sof_bug = 1;
mehci->ehci.reset_sof_bug = 1;
+ mehci->ehci.resume_sof_bug = 1;
+
mehci->ehci.max_log2_irq_thresh = 6;
res = platform_get_resource_byname(pdev,
diff --git a/drivers/usb/host/ehci.h b/drivers/usb/host/ehci.h
index 5754170..a0f995c 100644
--- a/drivers/usb/host/ehci.h
+++ b/drivers/usb/host/ehci.h
@@ -152,6 +152,7 @@
unsigned has_synopsys_hc_bug:1; /* Synopsys HC */
unsigned frame_index_bug:1; /* MosChip (AKA NetMos) */
unsigned susp_sof_bug:1; /*Chip Idea HC*/
+ unsigned resume_sof_bug:1;/*Chip Idea HC*/
unsigned reset_sof_bug:1; /*Chip Idea HC*/
/* required for usb32 quirk */
diff --git a/drivers/usb/misc/diag_bridge.c b/drivers/usb/misc/diag_bridge.c
index 8b762a2..6d5544a 100644
--- a/drivers/usb/misc/diag_bridge.c
+++ b/drivers/usb/misc/diag_bridge.c
@@ -255,6 +255,7 @@
pipe = usb_sndbulkpipe(dev->udev, dev->out_epAddr);
usb_fill_bulk_urb(urb, dev->udev, pipe, data, size,
diag_bridge_write_cb, dev);
+ urb->transfer_flags |= URB_ZERO_PACKET;
usb_anchor_urb(urb, &dev->submitted);
dev->pending_writes++;
diff --git a/drivers/usb/misc/mdm_data_bridge.c b/drivers/usb/misc/mdm_data_bridge.c
index db2f40a..1c9de07 100644
--- a/drivers/usb/misc/mdm_data_bridge.c
+++ b/drivers/usb/misc/mdm_data_bridge.c
@@ -497,6 +497,8 @@
usb_fill_bulk_urb(txurb, dev->udev, dev->bulk_out,
skb->data, skb->len, data_bridge_write_cb, skb);
+ txurb->transfer_flags |= URB_ZERO_PACKET;
+
if (test_bit(SUSPENDED, &dev->flags)) {
usb_anchor_urb(txurb, &dev->delayed);
goto free_urb;
diff --git a/drivers/video/msm/mdp.c b/drivers/video/msm/mdp.c
index 79bbce4..2bc7f5b 100644
--- a/drivers/video/msm/mdp.c
+++ b/drivers/video/msm/mdp.c
@@ -51,7 +51,7 @@
int mdp_rev;
static struct platform_device *mdp_init_pdev;
-static struct regulator *footswitch;
+static struct regulator *footswitch, *hdmi_pll_fs;
static unsigned int mdp_footswitch_on;
struct completion mdp_ppp_comp;
@@ -2122,10 +2122,16 @@
}
disable_irq(mdp_irq);
+ hdmi_pll_fs = regulator_get(&pdev->dev, "hdmi_pll_fs");
+ if (IS_ERR(hdmi_pll_fs))
+ hdmi_pll_fs = NULL;
+
footswitch = regulator_get(&pdev->dev, "vdd");
if (IS_ERR(footswitch))
footswitch = NULL;
else {
+ if (hdmi_pll_fs)
+ regulator_enable(hdmi_pll_fs);
regulator_enable(footswitch);
mdp_footswitch_on = 1;
@@ -2134,6 +2140,8 @@
msleep(20);
regulator_enable(footswitch);
}
+ if (hdmi_pll_fs)
+ regulator_disable(hdmi_pll_fs);
}
mdp_clk = clk_get(&pdev->dev, "core_clk");
@@ -2625,6 +2633,9 @@
return;
}
+ if (hdmi_pll_fs)
+ regulator_enable(hdmi_pll_fs);
+
if (on && !mdp_footswitch_on) {
pr_debug("Enable MDP FS\n");
regulator_enable(footswitch);
@@ -2635,6 +2646,9 @@
mdp_footswitch_on = 0;
}
+ if (hdmi_pll_fs)
+ regulator_disable(hdmi_pll_fs);
+
mutex_unlock(&mdp_suspend_mutex);
}
diff --git a/drivers/video/msm/mdp4_overlay_dtv.c b/drivers/video/msm/mdp4_overlay_dtv.c
index 9174bc5..03b22f1 100644
--- a/drivers/video/msm/mdp4_overlay_dtv.c
+++ b/drivers/video/msm/mdp4_overlay_dtv.c
@@ -520,7 +520,7 @@
}
wait_for_completion_timeout(&dtv_pipe->comp,
- msecs_to_jiffies(VSYNC_PERIOD*2));
+ msecs_to_jiffies(VSYNC_PERIOD * 3));
mdp_disable_irq(MDP_OVERLAY1_TERM);
if (dtv_pipe->blt_addr)
diff --git a/drivers/video/msm/mdp4_overlay_writeback.c b/drivers/video/msm/mdp4_overlay_writeback.c
index f1a2ada..8dccf78 100644
--- a/drivers/video/msm/mdp4_overlay_writeback.c
+++ b/drivers/video/msm/mdp4_overlay_writeback.c
@@ -21,7 +21,7 @@
#include <linux/delay.h>
#include <mach/hardware.h>
#include <linux/io.h>
-
+#include <mach/iommu_domains.h>
#include <asm/system.h>
#include <asm/mach-types.h>
#include <linux/semaphore.h>
@@ -407,11 +407,10 @@
pr_err("%s: out of memory\n", __func__);
goto register_alloc_fail;
}
-
+ temp->ihdl = NULL;
if (data->iova)
temp->addr = (void *)(data->iova + data->offset);
-#ifdef CONFIG_MSM_MULTIMEDIA_USE_ION
- else {
+ else if (mfd->iclient) {
struct ion_handle *srcp_ihdl;
ulong len;
srcp_ihdl = ion_import_fd(mfd->iclient,
@@ -420,22 +419,30 @@
pr_err("%s: ion import fd failed\n", __func__);
goto register_ion_fail;
}
- if (ion_phys(mfd->iclient,
- srcp_ihdl,
- (ulong *)&temp->addr,
- (size_t *)&len)) {
- pr_err("%s: unable to get ion phys\n",
+
+ if (ion_map_iommu(mfd->iclient,
+ srcp_ihdl,
+ DISPLAY_DOMAIN,
+ GEN_POOL,
+ SZ_4K,
+ 0,
+ (ulong *)&temp->addr,
+ (ulong *)&len,
+ 0,
+ ION_IOMMU_UNMAP_DELAYED)) {
+ ion_free(mfd->iclient, srcp_ihdl);
+ pr_err("%s: unable to get ion mapping addr\n",
__func__);
goto register_ion_fail;
}
temp->addr += data->offset;
+ temp->ihdl = srcp_ihdl;
}
-#else
else {
pr_err("%s: only support ion memory\n", __func__);
goto register_ion_fail;
}
-#endif
+
memcpy(&temp->buf_info, data, sizeof(struct msmfb_data));
if (mdp4_overlay_writeback_register_buffer(mfd, temp)) {
pr_err("%s: error registering node\n", __func__);
@@ -514,6 +521,15 @@
list_del(&node->active_entry);
node->state = WITH_CLIENT;
memcpy(data, &node->buf_info, sizeof(struct msmfb_data));
+ if (!data->iova)
+ if (mfd->iclient && node->ihdl) {
+ ion_unmap_iommu(mfd->iclient,
+ node->ihdl,
+ DISPLAY_DOMAIN,
+ GEN_POOL);
+ ion_free(mfd->iclient,
+ node->ihdl);
+ }
} else {
pr_err("node is NULL. Somebody else dequeued?\n");
rc = -ENOBUFS;
diff --git a/drivers/video/msm/mdss/mdss_mdp.c b/drivers/video/msm/mdss/mdss_mdp.c
index 41e0c18..46e49da 100644
--- a/drivers/video/msm/mdss/mdss_mdp.c
+++ b/drivers/video/msm/mdss/mdss_mdp.c
@@ -554,10 +554,10 @@
}
disable_irq(mdss_res->irq);
- mdss_res->fs = regulator_get(NULL, "gdsc_mdss");
+ mdss_res->fs = regulator_get(&pdev->dev, "vdd");
if (IS_ERR_OR_NULL(mdss_res->fs)) {
mdss_res->fs = NULL;
- pr_err("unable to get gdsc_mdss regulator\n");
+ pr_err("unable to get gdsc regulator\n");
goto error;
}
regulator_enable(mdss_res->fs);
diff --git a/drivers/video/msm/msm_fb.h b/drivers/video/msm/msm_fb.h
index c9eb7dd..0658365 100644
--- a/drivers/video/msm/msm_fb.h
+++ b/drivers/video/msm/msm_fb.h
@@ -60,6 +60,7 @@
struct list_head registered_entry;
struct list_head active_entry;
void *addr;
+ struct ion_handle *ihdl;
struct file *pmem_file;
struct msmfb_data buf_info;
struct msmfb_img img;
diff --git a/drivers/video/msm/vidc/1080p/ddl/vcd_ddl_helper.c b/drivers/video/msm/vidc/1080p/ddl/vcd_ddl_helper.c
index 6fd5656..d7ebd54 100644
--- a/drivers/video/msm/vidc/1080p/ddl/vcd_ddl_helper.c
+++ b/drivers/video/msm/vidc/1080p/ddl/vcd_ddl_helper.c
@@ -168,6 +168,28 @@
} else if (operation == DDL_DPB_OP_MARK_FREE) {
dpb_mask->client_mask |= (0x1 << loopc);
*found_frame = *in_out_frame;
+ if ((decoder->meta_data_enable_flag) &&
+ (in_out_frame->vcd_frm.buff_ion_handle)) {
+ struct ddl_context *ddl_context =
+ ddl_get_context();
+ unsigned long *vaddr =
+ (unsigned long *)((u32)
+ in_out_frame->vcd_frm.virtual +
+ decoder->meta_data_offset);
+ DDL_MSG_LOW("%s: Cache clean: vaddr"\
+ " (%p), offset %u, size %u",
+ __func__,
+ in_out_frame->vcd_frm.virtual,
+ decoder->meta_data_offset,
+ decoder->suffix);
+ msm_ion_do_cache_op(
+ ddl_context->video_ion_client,
+ in_out_frame->vcd_frm.\
+ buff_ion_handle,
+ vaddr,
+ (unsigned long)decoder->suffix,
+ ION_IOC_CLEAN_CACHES);
+ }
}
} else {
in_out_frame->vcd_frm.physical = NULL;
diff --git a/drivers/video/msm/vidc/common/dec/vdec.c b/drivers/video/msm/vidc/common/dec/vdec.c
index 3076aa1..ed8b452 100644
--- a/drivers/video/msm/vidc/common/dec/vdec.c
+++ b/drivers/video/msm/vidc/common/dec/vdec.c
@@ -348,10 +348,15 @@
pmem_fd, kernel_vaddr, buffer_index,
&buff_handle);
if (ion_flag == CACHED && buff_handle) {
+ DBG("%s: Cache invalidate: vaddr (%p), "\
+ "size %u\n", __func__,
+ (void *)kernel_vaddr,
+ vcd_frame_data->alloc_len);
msm_ion_do_cache_op(client_ctx->user_ion_client,
buff_handle,
(unsigned long *) kernel_vaddr,
- (unsigned long)vcd_frame_data->data_len,
+ (unsigned long)vcd_frame_data->\
+ alloc_len,
ION_IOC_INV_CACHES);
}
}
diff --git a/include/linux/android_pmem.h b/include/linux/android_pmem.h
index ab96379..cfca491 100644
--- a/include/linux/android_pmem.h
+++ b/include/linux/android_pmem.h
@@ -108,26 +108,6 @@
PMEM_ALLOCATORTYPE_MAX,
};
-#define PMEM_MEMTYPE_MASK 0x7
-#define PMEM_INVALID_MEMTYPE 0x0
-#define PMEM_MEMTYPE_EBI1 0x1
-#define PMEM_MEMTYPE_SMI 0x2
-#define PMEM_MEMTYPE_RESERVED_INVALID2 0x3
-#define PMEM_MEMTYPE_RESERVED_INVALID3 0x4
-#define PMEM_MEMTYPE_RESERVED_INVALID4 0x5
-#define PMEM_MEMTYPE_RESERVED_INVALID5 0x6
-#define PMEM_MEMTYPE_RESERVED_INVALID6 0x7
-
-#define PMEM_ALIGNMENT_MASK 0x18
-#define PMEM_ALIGNMENT_RESERVED_INVALID1 0x0
-#define PMEM_ALIGNMENT_4K 0x8 /* the default */
-#define PMEM_ALIGNMENT_1M 0x10
-#define PMEM_ALIGNMENT_RESERVED_INVALID2 0x18
-
-/* flags in the following function defined as above. */
-int32_t pmem_kalloc(const size_t size, const uint32_t flags);
-int32_t pmem_kfree(const int32_t physaddr);
-
/* kernel api names for board specific data structures */
#define PMEM_KERNEL_EBI1_DATA_NAME "pmem_kernel_ebi1"
#define PMEM_KERNEL_SMI_DATA_NAME "pmem_kernel_smi"
diff --git a/arch/arm/mach-msm/include/mach/stm.h b/include/linux/coresight-stm.h
similarity index 100%
rename from arch/arm/mach-msm/include/mach/stm.h
rename to include/linux/coresight-stm.h
diff --git a/include/linux/coresight.h b/include/linux/coresight.h
new file mode 100644
index 0000000..f03a493
--- /dev/null
+++ b/include/linux/coresight.h
@@ -0,0 +1,132 @@
+/* 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 _LINUX_CORESIGHT_H
+#define _LINUX_CORESIGHT_H
+
+#include <linux/device.h>
+
+/* Peripheral id registers (0xFD0-0xFEC) */
+#define CORESIGHT_PERIPHIDR4 (0xFD0)
+#define CORESIGHT_PERIPHIDR5 (0xFD4)
+#define CORESIGHT_PERIPHIDR6 (0xFD8)
+#define CORESIGHT_PERIPHIDR7 (0xFDC)
+#define CORESIGHT_PERIPHIDR0 (0xFE0)
+#define CORESIGHT_PERIPHIDR1 (0xFE4)
+#define CORESIGHT_PERIPHIDR2 (0xFE8)
+#define CORESIGHT_PERIPHIDR3 (0xFEC)
+/* Component id registers (0xFF0-0xFFC) */
+#define CORESIGHT_COMPIDR0 (0xFF0)
+#define CORESIGHT_COMPIDR1 (0xFF4)
+#define CORESIGHT_COMPIDR2 (0xFF8)
+#define CORESIGHT_COMPIDR3 (0xFFC)
+
+/* DBGv7 with baseline CP14 registers implemented */
+#define ARM_DEBUG_ARCH_V7B (0x3)
+/* DBGv7 with all CP14 registers implemented */
+#define ARM_DEBUG_ARCH_V7 (0x4)
+#define ARM_DEBUG_ARCH_V7_1 (0x5)
+#define ETM_ARCH_V3_3 (0x23)
+#define PFT_ARCH_V1_1 (0x31)
+
+enum coresight_clk_rate {
+ CORESIGHT_CLK_RATE_OFF,
+ CORESIGHT_CLK_RATE_TRACE,
+ CORESIGHT_CLK_RATE_HSTRACE,
+};
+
+enum coresight_dev_type {
+ CORESIGHT_DEV_TYPE_SINK,
+ CORESIGHT_DEV_TYPE_LINK,
+ CORESIGHT_DEV_TYPE_SOURCE,
+ CORESIGHT_DEV_TYPE_MAX,
+};
+
+struct coresight_connection {
+ int child_id;
+ int child_port;
+ struct coresight_device *child_dev;
+ struct list_head link;
+};
+
+struct coresight_device {
+ int id;
+ struct coresight_connection *conns;
+ int nr_conns;
+ const struct coresight_ops *ops;
+ struct device dev;
+ struct mutex mutex;
+ int *refcnt;
+ struct list_head link;
+ struct module *owner;
+ bool enable;
+};
+
+#define to_coresight_device(d) container_of(d, struct coresight_device, dev)
+
+struct coresight_ops {
+ int (*enable)(struct coresight_device *csdev, int port);
+ void (*disable)(struct coresight_device *csdev, int port);
+};
+
+struct coresight_platform_data {
+ int id;
+ const char *name;
+ int nr_ports;
+ int *child_ids;
+ int *child_ports;
+ int nr_children;
+};
+
+struct coresight_desc {
+ enum coresight_dev_type type;
+ const struct coresight_ops *ops;
+ struct coresight_platform_data *pdata;
+ struct device *dev;
+ const struct attribute_group **groups;
+ struct module *owner;
+};
+
+struct qdss_source {
+ struct list_head link;
+ const char *name;
+ uint32_t fport_mask;
+};
+
+struct msm_qdss_platform_data {
+ struct qdss_source *src_table;
+ size_t size;
+ uint8_t afamily;
+};
+
+
+extern struct coresight_device *
+coresight_register(struct coresight_desc *desc);
+extern void coresight_unregister(struct coresight_device *csdev);
+extern int coresight_enable(struct coresight_device *csdev, int port);
+extern void coresight_disable(struct coresight_device *csdev, int port);
+
+#ifdef CONFIG_MSM_QDSS
+extern struct qdss_source *qdss_get(const char *name);
+extern void qdss_put(struct qdss_source *src);
+extern int qdss_enable(struct qdss_source *src);
+extern void qdss_disable(struct qdss_source *src);
+extern void qdss_disable_sink(void);
+#else
+static inline struct qdss_source *qdss_get(const char *name) { return NULL; }
+static inline void qdss_put(struct qdss_source *src) {}
+static inline int qdss_enable(struct qdss_source *src) { return -ENOSYS; }
+static inline void qdss_disable(struct qdss_source *src) {}
+static inline void qdss_disable_sink(void) {}
+#endif
+
+#endif
diff --git a/include/linux/power_supply.h b/include/linux/power_supply.h
index 643c80e..32d8ec2 100644
--- a/include/linux/power_supply.h
+++ b/include/linux/power_supply.h
@@ -216,6 +216,7 @@
extern int power_supply_set_battery_charged(struct power_supply *psy);
extern int power_supply_set_current_limit(struct power_supply *psy, int limit);
extern int power_supply_set_online(struct power_supply *psy, bool enable);
+extern int power_supply_set_scope(struct power_supply *psy, int scope);
extern int power_supply_set_charge_type(struct power_supply *psy, int type);
#if defined(CONFIG_POWER_SUPPLY) || defined(CONFIG_POWER_SUPPLY_MODULE)
diff --git a/include/media/msm_camera.h b/include/media/msm_camera.h
index 3308243..da450fc 100644
--- a/include/media/msm_camera.h
+++ b/include/media/msm_camera.h
@@ -1659,4 +1659,86 @@
#define MSM_IRQROUTER_CFG_COMPIRQ \
_IOWR('V', BASE_VIDIOC_PRIVATE, void __user *)
+#define MAX_NUM_CPP_STRIPS 8
+
+enum msm_cpp_frame_type {
+ MSM_CPP_OFFLINE_FRAME,
+ MSM_CPP_REALTIME_FRAME,
+};
+
+struct msm_cpp_frame_strip_info {
+ int scale_v_en;
+ int scale_h_en;
+
+ int upscale_v_en;
+ int upscale_h_en;
+
+ int src_start_x;
+ int src_end_x;
+ int src_start_y;
+ int src_end_y;
+
+ /* Padding is required for upscaler because it does not
+ * pad internally like other blocks, also needed for rotation
+ * rotation expects all the blocks in the stripe to be the same size
+ * Padding is done such that all the extra padded pixels
+ * are on the right and bottom
+ */
+ int pad_bottom;
+ int pad_top;
+ int pad_right;
+ int pad_left;
+
+ int v_init_phase;
+ int h_init_phase;
+ int h_phase_step;
+ int v_phase_step;
+
+ int prescale_crop_width_first_pixel;
+ int prescale_crop_width_last_pixel;
+ int prescale_crop_height_first_line;
+ int prescale_crop_height_last_line;
+
+ int postscale_crop_height_first_line;
+ int postscale_crop_height_last_line;
+ int postscale_crop_width_first_pixel;
+ int postscale_crop_width_last_pixel;
+
+ int dst_start_x;
+ int dst_end_x;
+ int dst_start_y;
+ int dst_end_y;
+
+ int bytes_per_pixel;
+ unsigned int source_address;
+ unsigned int destination_address;
+ unsigned int src_stride;
+ unsigned int dst_stride;
+ int rotate_270;
+ int horizontal_flip;
+ int vertical_flip;
+ int scale_output_width;
+ int scale_output_height;
+};
+
+struct msm_cpp_frame_info_t {
+ int32_t frame_id;
+ uint32_t inst_id;
+ uint32_t client_id;
+ enum msm_cpp_frame_type frame_type;
+ uint32_t num_strips;
+ struct msm_cpp_frame_strip_info *strip_info;
+};
+
+#define VIDIOC_MSM_CPP_CFG \
+ _IOWR('V', BASE_VIDIOC_PRIVATE, struct msm_camera_v4l2_ioctl_t)
+
+#define VIDIOC_MSM_CPP_GET_EVENTPAYLOAD \
+ _IOWR('V', BASE_VIDIOC_PRIVATE + 1, struct msm_camera_v4l2_ioctl_t)
+
+#define VIDIOC_MSM_CPP_GET_INST_INFO \
+ _IOWR('V', BASE_VIDIOC_PRIVATE + 2, struct msm_camera_v4l2_ioctl_t)
+
+#define V4L2_EVENT_CPP_FRAME_DONE (V4L2_EVENT_PRIVATE_START + 0)
+
#endif /* __LINUX_MSM_CAMERA_H */
diff --git a/include/sound/apr_audio.h b/include/sound/apr_audio.h
index 431dedf..c770f13 100644
--- a/include/sound/apr_audio.h
+++ b/include/sound/apr_audio.h
@@ -1127,6 +1127,7 @@
#define AC3_DECODER 0x00010BF6
#define EAC3_DECODER 0x00010C3C
#define DTS 0x00010D88
+#define DTS_LBR 0x00010DBB
#define ATRAC 0x00010D89
#define MAT 0x00010D8A
#define G711_ALAW_FS 0x00010BF7
@@ -1145,6 +1146,13 @@
#define ASM_ENCDEC_IMMDIATE_DECODE 0x00010C14
#define ASM_ENCDEC_CFG_BLK 0x00010C2C
+#define ASM_STREAM_CMD_OPEN_READ_COMPRESSED 0x00010D95
+struct asm_stream_cmd_open_read_compressed {
+ struct apr_hdr hdr;
+ u32 uMode;
+ u32 frame_per_buf;
+} __packed;
+
#define ASM_STREAM_CMD_OPEN_WRITE 0x00010BCA
struct asm_stream_cmd_open_write {
struct apr_hdr hdr;
@@ -1185,6 +1193,17 @@
u16 afe_port_id;
} __packed;
+#define ADM_CMD_CONNECT_AFE_PORT_V2 0x00010332
+
+struct adm_cmd_connect_afe_port_v2 {
+ struct apr_hdr hdr;
+ u8 mode; /*mode represent the interface is for RX or TX*/
+ u8 session_id; /*ASM session ID*/
+ u16 afe_port_id;
+ u32 num_channels;
+ u32 sampleing_rate;
+} __packed;
+
#define ASM_STREAM_CMD_SET_ENCDEC_PARAM 0x00010C10
#define ASM_STREAM_CMD_GET_ENCDEC_PARAM 0x00010C11
#define ASM_ENCDEC_CFG_BLK_ID 0x00010C2C
diff --git a/include/sound/compress_offload.h b/include/sound/compress_offload.h
index 9769dea..e59d29c 100644
--- a/include/sound/compress_offload.h
+++ b/include/sound/compress_offload.h
@@ -123,6 +123,16 @@
};
/**
+ * struct snd_compr_audio_info: compressed input audio information
+ * @frame_size: legth of the encoded frame with valid data
+ * @reserved: reserved for furture use
+ */
+struct snd_compr_audio_info {
+ uint32_t frame_size;
+ uint32_t reserved[15];
+};
+
+/**
* compress path ioctl definitions
* SNDRV_COMPRESS_GET_CAPS: Query capability of DSP
* SNDRV_COMPRESS_GET_CODEC_CAPS: Query capability of a codec
diff --git a/include/sound/compress_params.h b/include/sound/compress_params.h
index 9c7a1ea..75558bf 100644
--- a/include/sound/compress_params.h
+++ b/include/sound/compress_params.h
@@ -70,10 +70,14 @@
#define SND_AUDIOCODEC_IEC61937 ((__u32) 0x0000000B)
#define SND_AUDIOCODEC_G723_1 ((__u32) 0x0000000C)
#define SND_AUDIOCODEC_G729 ((__u32) 0x0000000D)
-#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) 0x00000011)
+#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) 0x00000011)
+#define SND_AUDIOCODEC_DTS_PASS_THROUGH ((__u32) 0x00000012)
+#define SND_AUDIOCODEC_DTS_LBR ((__u32) 0x00000013)
+#define SND_AUDIOCODEC_DTS_TRANSCODE_LOOPBACK ((__u32) 0x00000014)
+
/*
* Profile and modes are listed with bit masks. This allows for a
* more compact representation of fields that will not evolve
diff --git a/include/sound/q6asm.h b/include/sound/q6asm.h
index 1e647a2..84e3150 100644
--- a/include/sound/q6asm.h
+++ b/include/sound/q6asm.h
@@ -48,6 +48,7 @@
#define FORMAT_ATRAC 0x0016
#define FORMAT_MAT 0x0017
#define FORMAT_AAC 0x0018
+#define FORMAT_DTS_LBR 0x0019
#define ENCDEC_SBCBITRATE 0x0001
#define ENCDEC_IMMEDIATE_DECODE 0x0002
@@ -180,6 +181,8 @@
int q6asm_open_read(struct audio_client *ac, uint32_t format);
+int q6asm_open_read_compressed(struct audio_client *ac, uint32_t format);
+
int q6asm_open_write(struct audio_client *ac, uint32_t format);
int q6asm_open_write_compressed(struct audio_client *ac, uint32_t format);
diff --git a/kernel/panic.c b/kernel/panic.c
index b47ca87..8c6babc 100644
--- a/kernel/panic.c
+++ b/kernel/panic.c
@@ -81,6 +81,14 @@
int state = 0;
/*
+ * Disable local interrupts. This will prevent panic_smp_self_stop
+ * from deadlocking the first cpu that invokes the panic, since
+ * there is nothing to prevent an interrupt handler (that runs
+ * after the panic_lock is acquired) from invoking panic again.
+ */
+ local_irq_disable();
+
+ /*
* It's possible to come here directly from a panic-assertion and
* not have preempt disabled. Some functions called from here want
* preempt to be disabled. No point enabling it later though...
diff --git a/sound/soc/codecs/wcd9310.c b/sound/soc/codecs/wcd9310.c
index e85e9f5..a34b294 100644
--- a/sound/soc/codecs/wcd9310.c
+++ b/sound/soc/codecs/wcd9310.c
@@ -114,6 +114,11 @@
static const DECLARE_TLV_DB_SCALE(analog_gain, 0, 25, 1);
static struct snd_soc_dai_driver tabla_dai[];
static const DECLARE_TLV_DB_SCALE(aux_pga_gain, 0, 2, 0);
+static int tabla_codec_enable_slimrx(struct snd_soc_dapm_widget *w,
+ struct snd_kcontrol *kcontrol, int event);
+static int tabla_codec_enable_slimtx(struct snd_soc_dapm_widget *w,
+ struct snd_kcontrol *kcontrol, int event);
+
enum tabla_bandgap_type {
TABLA_BANDGAP_OFF = 0,
@@ -3931,50 +3936,277 @@
return 0;
}
+
+static struct snd_soc_dapm_widget tabla_dapm_aif_in_widgets[] = {
+
+ SND_SOC_DAPM_AIF_IN_E("SLIM RX1", "AIF1 Playback", 0, SND_SOC_NOPM, 1,
+ 0, tabla_codec_enable_slimrx,
+ SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
+
+ SND_SOC_DAPM_AIF_IN_E("SLIM RX2", "AIF1 Playback", 0, SND_SOC_NOPM, 2,
+ 0, tabla_codec_enable_slimrx,
+ SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
+
+ SND_SOC_DAPM_AIF_IN_E("SLIM RX3", "AIF1 Playback", 0, SND_SOC_NOPM, 3,
+ 0, tabla_codec_enable_slimrx,
+ SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
+
+ SND_SOC_DAPM_AIF_IN_E("SLIM RX4", "AIF3 Playback", 0, SND_SOC_NOPM, 4,
+ 0, tabla_codec_enable_slimrx,
+ SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
+
+ SND_SOC_DAPM_AIF_IN_E("SLIM RX5", "AIF3 Playback", 0, SND_SOC_NOPM, 5,
+ 0, tabla_codec_enable_slimrx,
+ SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
+
+ SND_SOC_DAPM_AIF_IN_E("SLIM RX6", "AIF2 Playback", 0, SND_SOC_NOPM, 6,
+ 0, tabla_codec_enable_slimrx,
+ SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
+
+ SND_SOC_DAPM_AIF_IN_E("SLIM RX7", "AIF2 Playback", 0, SND_SOC_NOPM, 7,
+ 0, tabla_codec_enable_slimrx,
+ SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
+};
+
+static struct snd_soc_dapm_widget tabla_dapm_aif_out_widgets[] = {
+
+ SND_SOC_DAPM_AIF_OUT_E("SLIM TX1", "AIF2 Capture", 0, SND_SOC_NOPM, 1,
+ 0, tabla_codec_enable_slimtx,
+ SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
+
+ SND_SOC_DAPM_AIF_OUT_E("SLIM TX2", "AIF2 Capture", 0, SND_SOC_NOPM, 2,
+ 0, tabla_codec_enable_slimtx,
+ SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
+
+ SND_SOC_DAPM_AIF_OUT_E("SLIM TX3", "AIF3 Capture", 0, SND_SOC_NOPM, 3,
+ 0, tabla_codec_enable_slimtx,
+ SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
+
+ SND_SOC_DAPM_AIF_OUT_E("SLIM TX4", "AIF2 Capture", 0, SND_SOC_NOPM, 4,
+ 0, tabla_codec_enable_slimtx,
+ SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
+
+ SND_SOC_DAPM_AIF_OUT_E("SLIM TX5", "AIF3 Capture", 0, SND_SOC_NOPM, 5,
+ 0, tabla_codec_enable_slimtx,
+ SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
+
+ SND_SOC_DAPM_AIF_OUT_E("SLIM TX6", "AIF2 Capture", 0, SND_SOC_NOPM, 6,
+ 0, tabla_codec_enable_slimtx,
+ SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
+
+ SND_SOC_DAPM_AIF_OUT_E("SLIM TX7", "AIF1 Capture", 0, SND_SOC_NOPM, 7,
+ 0, tabla_codec_enable_slimtx,
+ SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
+
+ SND_SOC_DAPM_AIF_OUT_E("SLIM TX8", "AIF1 Capture", 0, SND_SOC_NOPM, 8,
+ 0, tabla_codec_enable_slimtx,
+ SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
+
+ SND_SOC_DAPM_AIF_OUT_E("SLIM TX9", "AIF1 Capture", 0, SND_SOC_NOPM, 9,
+ 0, tabla_codec_enable_slimtx,
+ SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
+
+ SND_SOC_DAPM_AIF_OUT_E("SLIM TX10", "AIF1 Capture", 0, SND_SOC_NOPM, 10,
+ 0, tabla_codec_enable_slimtx,
+ SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
+};
+
+static int tabla_set_interpolator_rate(struct snd_soc_dai *dai,
+ u8 rx_fs_rate_reg_val, u32 compander_fs, u32 sample_rate)
+{
+ u32 i, j;
+ u8 rx_mix1_inp;
+ u16 rx_mix_1_reg_1, rx_mix_1_reg_2;
+ u16 rx_fs_reg;
+ u8 rx_mix_1_reg_1_val, rx_mix_1_reg_2_val;
+ struct snd_soc_codec *codec = dai->codec;
+ struct tabla_priv *tabla = snd_soc_codec_get_drvdata(codec);
+ struct snd_soc_dapm_widget *w = tabla_dapm_aif_in_widgets;
+
+ for (i = 0; i < ARRAY_SIZE(tabla_dapm_aif_in_widgets); i++) {
+
+ if (strncmp(dai->driver->playback.stream_name, w[i].sname, 13))
+ continue;
+
+ rx_mix1_inp = w[i].shift + 4;
+
+ if ((rx_mix1_inp < 0x5) || (rx_mix1_inp > 0xB)) {
+
+ pr_err("%s: Invalid SLIM RX%u port. widget = %s\n",
+ __func__, rx_mix1_inp - 4 , w[i].name);
+ return -EINVAL;
+ }
+
+ rx_mix_1_reg_1 = TABLA_A_CDC_CONN_RX1_B1_CTL;
+
+ for (j = 0; j < NUM_INTERPOLATORS; j++) {
+
+ rx_mix_1_reg_2 = rx_mix_1_reg_1 + 1;
+
+ rx_mix_1_reg_1_val = snd_soc_read(codec,
+ rx_mix_1_reg_1);
+ rx_mix_1_reg_2_val = snd_soc_read(codec,
+ rx_mix_1_reg_2);
+
+ if (((rx_mix_1_reg_1_val & 0x0F) == rx_mix1_inp) ||
+ (((rx_mix_1_reg_1_val >> 4) & 0x0F) == rx_mix1_inp)
+ || ((rx_mix_1_reg_2_val & 0x0F) == rx_mix1_inp)) {
+
+ rx_fs_reg = TABLA_A_CDC_RX1_B5_CTL + 8 * j;
+
+ pr_debug("%s: %s connected to RX%u\n", __func__,
+ w[i].name, j + 1);
+
+ pr_debug("%s: set RX%u sample rate to %u\n",
+ __func__, j + 1, sample_rate);
+
+ snd_soc_update_bits(codec, rx_fs_reg,
+ 0xE0, rx_fs_rate_reg_val);
+
+ if (comp_rx_path[j] < COMPANDER_MAX)
+ tabla->comp_fs[comp_rx_path[j]]
+ = compander_fs;
+ }
+ if (j <= 2)
+ rx_mix_1_reg_1 += 3;
+ else
+ rx_mix_1_reg_1 += 2;
+ }
+ }
+ return 0;
+}
+
+static int tabla_set_decimator_rate(struct snd_soc_dai *dai,
+ u8 tx_fs_rate_reg_val, u32 sample_rate)
+{
+ struct snd_soc_codec *codec = dai->codec;
+ struct snd_soc_dapm_widget *w = tabla_dapm_aif_out_widgets;
+
+ u32 i, tx_port;
+ u16 tx_port_reg, tx_fs_reg;
+ u8 tx_port_reg_val;
+ s8 decimator;
+
+ for (i = 0; i < ARRAY_SIZE(tabla_dapm_aif_out_widgets); i++) {
+
+ if (strncmp(dai->driver->capture.stream_name, w[i].sname, 12))
+ continue;
+
+ tx_port = w[i].shift;
+
+ if ((tx_port < 1) || (tx_port > NUM_DECIMATORS)) {
+ pr_err("%s: Invalid SLIM TX%u port. widget = %s\n",
+ __func__, tx_port, w[i].name);
+ return -EINVAL;
+ }
+
+ tx_port_reg = TABLA_A_CDC_CONN_TX_SB_B1_CTL + (tx_port - 1);
+ tx_port_reg_val = snd_soc_read(codec, tx_port_reg);
+
+ decimator = 0;
+
+ if ((tx_port >= 1) && (tx_port <= 6)) {
+
+ tx_port_reg_val = tx_port_reg_val & 0x0F;
+ if (tx_port_reg_val == 0x8)
+ decimator = tx_port;
+
+ } else if ((tx_port >= 7) && (tx_port <= NUM_DECIMATORS)) {
+
+ tx_port_reg_val = tx_port_reg_val & 0x1F;
+
+ if ((tx_port_reg_val >= 0x8) &&
+ (tx_port_reg_val <= 0x11)) {
+
+ decimator = (tx_port_reg_val - 0x8) + 1;
+ }
+ }
+
+ if (decimator) { /* SLIM_TX port has a DEC as input */
+
+ tx_fs_reg = TABLA_A_CDC_TX1_CLK_FS_CTL +
+ 8 * (decimator - 1);
+
+ pr_debug("%s: set DEC%u (-> SLIM_TX%u) rate to %u\n",
+ __func__, decimator, tx_port, sample_rate);
+
+ snd_soc_update_bits(codec, tx_fs_reg, 0x07,
+ tx_fs_rate_reg_val);
+
+ } else {
+ if ((tx_port_reg_val >= 0x1) &&
+ (tx_port_reg_val <= 0x7)) {
+
+ pr_debug("%s: RMIX%u going to SLIM TX%u\n",
+ __func__, tx_port_reg_val, tx_port);
+
+ } else if ((tx_port_reg_val >= 0x8) &&
+ (tx_port_reg_val <= 0x11)) {
+
+ pr_err("%s: ERROR: Should not be here\n",
+ __func__);
+ pr_err("%s: ERROR: DEC connected to SLIM TX%u\n"
+ , __func__, tx_port);
+ return -EINVAL;
+
+ } else if (tx_port_reg_val == 0) {
+ pr_debug("%s: no signal to SLIM TX%u\n",
+ __func__, tx_port);
+ } else {
+ pr_err("%s: ERROR: wrong signal to SLIM TX%u\n"
+ , __func__, tx_port);
+ pr_err("%s: ERROR: wrong signal = %u\n"
+ , __func__, tx_port_reg_val);
+ return -EINVAL;
+ }
+ }
+ }
+ return 0;
+}
+
static int tabla_hw_params(struct snd_pcm_substream *substream,
- struct snd_pcm_hw_params *params,
- struct snd_soc_dai *dai)
+ struct snd_pcm_hw_params *params,
+ struct snd_soc_dai *dai)
{
struct snd_soc_codec *codec = dai->codec;
struct tabla_priv *tabla = snd_soc_codec_get_drvdata(dai->codec);
- u8 path, shift;
- u16 tx_fs_reg, rx_fs_reg;
- u8 tx_fs_rate, rx_fs_rate, rx_state, tx_state;
+ u8 tx_fs_rate_reg_val, rx_fs_rate_reg_val;
u32 compander_fs;
+ int ret;
pr_debug("%s: dai_name = %s DAI-ID %x rate %d num_ch %d\n", __func__,
- dai->name, dai->id, params_rate(params),
- params_channels(params));
+ dai->name, dai->id, params_rate(params),
+ params_channels(params));
switch (params_rate(params)) {
case 8000:
- tx_fs_rate = 0x00;
- rx_fs_rate = 0x00;
+ tx_fs_rate_reg_val = 0x00;
+ rx_fs_rate_reg_val = 0x00;
compander_fs = COMPANDER_FS_8KHZ;
break;
case 16000:
- tx_fs_rate = 0x01;
- rx_fs_rate = 0x20;
+ tx_fs_rate_reg_val = 0x01;
+ rx_fs_rate_reg_val = 0x20;
compander_fs = COMPANDER_FS_16KHZ;
break;
case 32000:
- tx_fs_rate = 0x02;
- rx_fs_rate = 0x40;
+ tx_fs_rate_reg_val = 0x02;
+ rx_fs_rate_reg_val = 0x40;
compander_fs = COMPANDER_FS_32KHZ;
break;
case 48000:
- tx_fs_rate = 0x03;
- rx_fs_rate = 0x60;
+ tx_fs_rate_reg_val = 0x03;
+ rx_fs_rate_reg_val = 0x60;
compander_fs = COMPANDER_FS_48KHZ;
break;
case 96000:
- tx_fs_rate = 0x04;
- rx_fs_rate = 0x80;
+ tx_fs_rate_reg_val = 0x04;
+ rx_fs_rate_reg_val = 0x80;
compander_fs = COMPANDER_FS_96KHZ;
break;
case 192000:
- tx_fs_rate = 0x05;
- rx_fs_rate = 0xA0;
+ tx_fs_rate_reg_val = 0x05;
+ rx_fs_rate_reg_val = 0xA0;
compander_fs = COMPANDER_FS_192KHZ;
break;
default:
@@ -3983,105 +4215,76 @@
return -EINVAL;
}
+ switch (substream->stream) {
+ case SNDRV_PCM_STREAM_CAPTURE:
- /**
- * If current dai is a tx dai, set sample rate to
- * all the txfe paths that are currently not active
- */
- if ((dai->id == AIF1_CAP) || (dai->id == AIF2_CAP) ||
- (dai->id == AIF3_CAP)) {
-
- tx_state = snd_soc_read(codec,
- TABLA_A_CDC_CLK_TX_CLK_EN_B1_CTL);
-
- for (path = 1, shift = 0;
- path <= NUM_DECIMATORS; path++, shift++) {
-
- if (path == BITS_PER_REG + 1) {
- shift = 0;
- tx_state = snd_soc_read(codec,
- TABLA_A_CDC_CLK_TX_CLK_EN_B2_CTL);
- }
-
- if (!(tx_state & (1 << shift))) {
- tx_fs_reg = TABLA_A_CDC_TX1_CLK_FS_CTL
- + (BITS_PER_REG*(path-1));
- snd_soc_update_bits(codec, tx_fs_reg,
- 0x07, tx_fs_rate);
- }
+ ret = tabla_set_decimator_rate(dai, tx_fs_rate_reg_val,
+ params_rate(params));
+ if (ret < 0) {
+ pr_err("%s: set decimator rate failed %d\n", __func__,
+ ret);
+ return ret;
}
+
if (tabla->intf_type == WCD9XXX_INTERFACE_TYPE_I2C) {
switch (params_format(params)) {
case SNDRV_PCM_FORMAT_S16_LE:
snd_soc_update_bits(codec,
- TABLA_A_CDC_CLK_TX_I2S_CTL,
- 0x20, 0x20);
+ TABLA_A_CDC_CLK_TX_I2S_CTL, 0x20, 0x20);
break;
case SNDRV_PCM_FORMAT_S32_LE:
snd_soc_update_bits(codec,
- TABLA_A_CDC_CLK_TX_I2S_CTL,
- 0x20, 0x00);
+ TABLA_A_CDC_CLK_TX_I2S_CTL, 0x20, 0x00);
break;
default:
- pr_err("invalid format\n");
- break;
+ pr_err("%s: invalid TX format %u\n", __func__,
+ params_format(params));
+ return -EINVAL;
}
snd_soc_update_bits(codec, TABLA_A_CDC_CLK_TX_I2S_CTL,
- 0x07, tx_fs_rate);
+ 0x07, tx_fs_rate_reg_val);
} else {
tabla->dai[dai->id - 1].rate = params_rate(params);
}
- }
- /**
- * TODO: Need to handle case where same RX chain takes 2 or more inputs
- * with varying sample rates
- */
+ break;
- /**
- * If current dai is a rx dai, set sample rate to
- * all the rx paths that are currently not active
- */
- if (dai->id == AIF1_PB || dai->id == AIF2_PB || dai->id == AIF3_PB) {
+ case SNDRV_PCM_STREAM_PLAYBACK:
- rx_state = snd_soc_read(codec,
- TABLA_A_CDC_CLK_RX_B1_CTL);
-
- for (path = 1, shift = 0;
- path <= NUM_INTERPOLATORS; path++, shift++) {
-
- if (!(rx_state & (1 << shift))) {
- rx_fs_reg = TABLA_A_CDC_RX1_B5_CTL
- + (BITS_PER_REG*(path-1));
- snd_soc_update_bits(codec, rx_fs_reg,
- 0xE0, rx_fs_rate);
- if (comp_rx_path[shift] < COMPANDER_MAX)
- tabla->comp_fs[comp_rx_path[shift]]
- = compander_fs;
- }
+ ret = tabla_set_interpolator_rate(dai, rx_fs_rate_reg_val,
+ compander_fs, params_rate(params));
+ if (ret < 0) {
+ pr_err("%s: set decimator rate failed %d\n", __func__,
+ ret);
+ return ret;
}
+
if (tabla->intf_type == WCD9XXX_INTERFACE_TYPE_I2C) {
switch (params_format(params)) {
case SNDRV_PCM_FORMAT_S16_LE:
snd_soc_update_bits(codec,
- TABLA_A_CDC_CLK_RX_I2S_CTL,
- 0x20, 0x20);
+ TABLA_A_CDC_CLK_RX_I2S_CTL, 0x20, 0x20);
break;
case SNDRV_PCM_FORMAT_S32_LE:
snd_soc_update_bits(codec,
- TABLA_A_CDC_CLK_RX_I2S_CTL,
- 0x20, 0x00);
+ TABLA_A_CDC_CLK_RX_I2S_CTL, 0x20, 0x00);
break;
default:
- pr_err("invalid format\n");
- break;
+ pr_err("%s: invalid RX format %u\n", __func__,
+ params_format(params));
+ return -EINVAL;
}
snd_soc_update_bits(codec, TABLA_A_CDC_CLK_RX_I2S_CTL,
- 0x03, (rx_fs_rate >> 0x05));
+ 0x03, (rx_fs_rate_reg_val >> 0x05));
} else {
tabla->dai[dai->id - 1].rate = params_rate(params);
}
- }
+ break;
+ default:
+ pr_err("%s: Invalid stream type %d\n", __func__,
+ substream->stream);
+ return -EINVAL;
+ }
return 0;
}
@@ -4350,30 +4553,6 @@
SND_SOC_DAPM_MIXER("DAC1", TABLA_A_RX_EAR_EN, 6, 0, dac1_switch,
ARRAY_SIZE(dac1_switch)),
- SND_SOC_DAPM_AIF_IN_E("SLIM RX1", "AIF1 Playback", 0, SND_SOC_NOPM, 0,
- 0, tabla_codec_enable_slimrx,
- SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
- SND_SOC_DAPM_AIF_IN_E("SLIM RX2", "AIF1 Playback", 0, SND_SOC_NOPM, 0,
- 0, tabla_codec_enable_slimrx,
- SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
- SND_SOC_DAPM_AIF_IN_E("SLIM RX3", "AIF1 Playback", 0, SND_SOC_NOPM, 0,
- 0, tabla_codec_enable_slimrx,
- SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
-
- SND_SOC_DAPM_AIF_IN_E("SLIM RX4", "AIF3 Playback", 0, SND_SOC_NOPM, 0,
- 0, tabla_codec_enable_slimrx,
- SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
- SND_SOC_DAPM_AIF_IN_E("SLIM RX5", "AIF3 Playback", 0, SND_SOC_NOPM, 0,
- 0, tabla_codec_enable_slimrx,
- SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
-
- SND_SOC_DAPM_AIF_IN_E("SLIM RX6", "AIF2 Playback", 0, SND_SOC_NOPM, 0,
- 0, tabla_codec_enable_slimrx,
- SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
- SND_SOC_DAPM_AIF_IN_E("SLIM RX7", "AIF2 Playback", 0, SND_SOC_NOPM, 0,
- 0, tabla_codec_enable_slimrx,
- SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
-
/* Headphone */
SND_SOC_DAPM_OUTPUT("HEADPHONE"),
SND_SOC_DAPM_PGA_E("HPHL", TABLA_A_RX_HPH_CNP_EN, 5, 0, NULL, 0,
@@ -4654,54 +4833,15 @@
SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
SND_SOC_DAPM_MUX("SLIM TX1 MUX", SND_SOC_NOPM, 0, 0, &sb_tx1_mux),
- SND_SOC_DAPM_AIF_OUT_E("SLIM TX1", "AIF2 Capture", 0, SND_SOC_NOPM, 0,
- 0, tabla_codec_enable_slimtx,
- SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
-
SND_SOC_DAPM_MUX("SLIM TX2 MUX", SND_SOC_NOPM, 0, 0, &sb_tx2_mux),
- SND_SOC_DAPM_AIF_OUT_E("SLIM TX2", "AIF2 Capture", 0, SND_SOC_NOPM, 0,
- 0, tabla_codec_enable_slimtx,
- SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
-
SND_SOC_DAPM_MUX("SLIM TX3 MUX", SND_SOC_NOPM, 0, 0, &sb_tx3_mux),
- SND_SOC_DAPM_AIF_OUT_E("SLIM TX3", "AIF3 Capture", 0, SND_SOC_NOPM, 0,
- 0, tabla_codec_enable_slimtx,
- SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
-
SND_SOC_DAPM_MUX("SLIM TX4 MUX", SND_SOC_NOPM, 0, 0, &sb_tx4_mux),
- SND_SOC_DAPM_AIF_OUT_E("SLIM TX4", "AIF2 Capture", 0, SND_SOC_NOPM, 0,
- 0, tabla_codec_enable_slimtx,
- SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
-
SND_SOC_DAPM_MUX("SLIM TX5 MUX", SND_SOC_NOPM, 0, 0, &sb_tx5_mux),
- SND_SOC_DAPM_AIF_OUT_E("SLIM TX5", "AIF3 Capture", 0, SND_SOC_NOPM, 0,
- 0, tabla_codec_enable_slimtx,
- SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
-
SND_SOC_DAPM_MUX("SLIM TX6 MUX", SND_SOC_NOPM, 0, 0, &sb_tx6_mux),
- SND_SOC_DAPM_AIF_OUT_E("SLIM TX6", "AIF2 Capture", 0, SND_SOC_NOPM, 0,
- 0, tabla_codec_enable_slimtx,
- SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
-
SND_SOC_DAPM_MUX("SLIM TX7 MUX", SND_SOC_NOPM, 0, 0, &sb_tx7_mux),
- SND_SOC_DAPM_AIF_OUT_E("SLIM TX7", "AIF1 Capture", 0, SND_SOC_NOPM, 0,
- 0, tabla_codec_enable_slimtx,
- SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
-
SND_SOC_DAPM_MUX("SLIM TX8 MUX", SND_SOC_NOPM, 0, 0, &sb_tx8_mux),
- SND_SOC_DAPM_AIF_OUT_E("SLIM TX8", "AIF1 Capture", 0, SND_SOC_NOPM, 0,
- 0, tabla_codec_enable_slimtx,
- SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
-
SND_SOC_DAPM_MUX("SLIM TX9 MUX", SND_SOC_NOPM, 0, 0, &sb_tx9_mux),
- SND_SOC_DAPM_AIF_OUT_E("SLIM TX9", "AIF1 Capture", NULL, SND_SOC_NOPM,
- 0, 0, tabla_codec_enable_slimtx,
- SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
-
SND_SOC_DAPM_MUX("SLIM TX10 MUX", SND_SOC_NOPM, 0, 0, &sb_tx10_mux),
- SND_SOC_DAPM_AIF_OUT_E("SLIM TX10", "AIF1 Capture", NULL, SND_SOC_NOPM,
- 0, 0, tabla_codec_enable_slimtx,
- SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
/* Digital Mic Inputs */
SND_SOC_DAPM_ADC_E("DMIC1", NULL, SND_SOC_NOPM, 0, 0,
@@ -7560,6 +7700,13 @@
// snd_soc_dapm_new_controls(dapm, tabla_dapm_widgets,
// ARRAY_SIZE(tabla_dapm_widgets));
+
+ snd_soc_dapm_new_controls(dapm, tabla_dapm_aif_in_widgets,
+ ARRAY_SIZE(tabla_dapm_aif_in_widgets));
+
+ snd_soc_dapm_new_controls(dapm, tabla_dapm_aif_out_widgets,
+ ARRAY_SIZE(tabla_dapm_aif_out_widgets));
+
if (TABLA_IS_1_X(control->version))
snd_soc_dapm_new_controls(dapm, tabla_1_x_dapm_widgets,
ARRAY_SIZE(tabla_1_x_dapm_widgets));
diff --git a/sound/soc/msm/mpq8064.c b/sound/soc/msm/mpq8064.c
index 391c5f3..6685ce5 100644
--- a/sound/soc/msm/mpq8064.c
+++ b/sound/soc/msm/mpq8064.c
@@ -850,7 +850,7 @@
static void msm_mi2s_shutdown(struct snd_pcm_substream *substream)
{
if (mi2s_bit_clk) {
- clk_disable(mi2s_bit_clk);
+ clk_disable_unprepare(mi2s_bit_clk);
clk_put(mi2s_bit_clk);
mi2s_bit_clk = NULL;
}
@@ -892,7 +892,7 @@
if (IS_ERR(mi2s_bit_clk))
return PTR_ERR(mi2s_bit_clk);
clk_set_rate(mi2s_bit_clk, 0);
- ret = clk_enable(mi2s_bit_clk);
+ ret = clk_prepare_enable(mi2s_bit_clk);
if (IS_ERR_VALUE(ret)) {
pr_err("Unable to enable mi2s_bit_clk\n");
clk_put(mi2s_bit_clk);
diff --git a/sound/soc/msm/msm-compr-q6.c b/sound/soc/msm/msm-compr-q6.c
index 2455128..c894921 100644
--- a/sound/soc/msm/msm-compr-q6.c
+++ b/sound/soc/msm/msm-compr-q6.c
@@ -34,6 +34,13 @@
#include "msm-compr-q6.h"
#include "msm-pcm-routing.h"
+#define COMPRE_CAPTURE_NUM_PERIODS 16
+/* Allocate the worst case frame size for compressed audio */
+#define COMPRE_CAPTURE_HEADER_SIZE (sizeof(struct snd_compr_audio_info))
+#define COMPRE_CAPTURE_MAX_FRAME_SIZE (6144)
+#define COMPRE_CAPTURE_PERIOD_SIZE (COMPRE_CAPTURE_MAX_FRAME_SIZE + \
+ COMPRE_CAPTURE_HEADER_SIZE)
+
struct snd_msm {
struct msm_audio *prtd;
unsigned volume;
@@ -42,6 +49,27 @@
static struct audio_locks the_locks;
+static struct snd_pcm_hardware msm_compr_hardware_capture = {
+ .info = (SNDRV_PCM_INFO_MMAP |
+ SNDRV_PCM_INFO_BLOCK_TRANSFER |
+ SNDRV_PCM_INFO_MMAP_VALID |
+ SNDRV_PCM_INFO_INTERLEAVED |
+ SNDRV_PCM_INFO_PAUSE | SNDRV_PCM_INFO_RESUME),
+ .formats = SNDRV_PCM_FMTBIT_S16_LE,
+ .rates = SNDRV_PCM_RATE_8000_48000,
+ .rate_min = 8000,
+ .rate_max = 48000,
+ .channels_min = 1,
+ .channels_max = 8,
+ .buffer_bytes_max =
+ COMPRE_CAPTURE_PERIOD_SIZE * COMPRE_CAPTURE_NUM_PERIODS ,
+ .period_bytes_min = COMPRE_CAPTURE_PERIOD_SIZE,
+ .period_bytes_max = COMPRE_CAPTURE_PERIOD_SIZE,
+ .periods_min = COMPRE_CAPTURE_NUM_PERIODS,
+ .periods_max = COMPRE_CAPTURE_NUM_PERIODS,
+ .fifo_size = 0,
+};
+
static struct snd_pcm_hardware msm_compr_hardware_playback = {
.info = (SNDRV_PCM_INFO_MMAP |
SNDRV_PCM_INFO_BLOCK_TRANSFER |
@@ -81,7 +109,9 @@
struct snd_pcm_substream *substream = prtd->substream;
struct snd_pcm_runtime *runtime = substream->runtime;
struct audio_aio_write_param param;
+ struct audio_aio_read_param read_param;
struct audio_buffer *buf = NULL;
+ uint32_t *ptrmem = (uint32_t *)payload;
int i = 0;
pr_debug("%s opcode =%08x\n", __func__, opcode);
@@ -138,9 +168,53 @@
prtd->cmd_ack = 1;
wake_up(&the_locks.eos_wait);
break;
+ case ASM_DATA_EVENT_READ_DONE: {
+ pr_debug("ASM_DATA_EVENT_READ_DONE\n");
+ pr_debug("buf = %p, data = 0x%X, *data = %p,\n"
+ "prtd->pcm_irq_pos = %d\n",
+ prtd->audio_client->port[OUT].buf,
+ *(uint32_t *)prtd->audio_client->port[OUT].buf->data,
+ prtd->audio_client->port[OUT].buf->data,
+ prtd->pcm_irq_pos);
+
+ memcpy(prtd->audio_client->port[OUT].buf->data +
+ prtd->pcm_irq_pos, (ptrmem + 2),
+ COMPRE_CAPTURE_HEADER_SIZE);
+ pr_debug("buf = %p, updated data = 0x%X, *data = %p\n",
+ prtd->audio_client->port[OUT].buf,
+ *(uint32_t *)(prtd->audio_client->port[OUT].buf->data +
+ prtd->pcm_irq_pos),
+ prtd->audio_client->port[OUT].buf->data);
+ if (!atomic_read(&prtd->start))
+ break;
+ pr_debug("frame size=%d, buffer = 0x%X\n", ptrmem[2],
+ ptrmem[1]);
+ if (ptrmem[2] > COMPRE_CAPTURE_MAX_FRAME_SIZE) {
+ pr_err("Frame length exceeded the max length");
+ break;
+ }
+ buf = prtd->audio_client->port[OUT].buf;
+ pr_debug("pcm_irq_pos=%d, buf[0].phys = 0x%X\n",
+ prtd->pcm_irq_pos, (uint32_t)buf[0].phys);
+ read_param.len = prtd->pcm_count - COMPRE_CAPTURE_HEADER_SIZE ;
+ read_param.paddr = (unsigned long)(buf[0].phys) +
+ prtd->pcm_irq_pos + COMPRE_CAPTURE_HEADER_SIZE;
+ prtd->pcm_irq_pos += prtd->pcm_count;
+
+ if (atomic_read(&prtd->start))
+ snd_pcm_period_elapsed(substream);
+
+ q6asm_async_read(prtd->audio_client, &read_param);
+ break;
+ }
case APR_BASIC_RSP_RESULT: {
switch (payload[0]) {
case ASM_SESSION_CMD_RUN: {
+ if (substream->stream
+ != SNDRV_PCM_STREAM_PLAYBACK) {
+ atomic_set(&prtd->start, 1);
+ break;
+ }
if (!atomic_read(&prtd->pending_buffer))
break;
pr_debug("%s:writing %d bytes"
@@ -230,6 +304,9 @@
pr_debug("compressd playback, no need to send"
" the decoder params\n");
break;
+ case SND_AUDIOCODEC_DTS_PASS_THROUGH:
+ pr_debug("compressd DTS playback,dont send the decoder params\n");
+ break;
case SND_AUDIOCODEC_WMA:
pr_debug("SND_AUDIOCODEC_WMA\n");
memset(&wma_cfg, 0x0, sizeof(struct asm_wma_cfg));
@@ -276,6 +353,16 @@
if (ret < 0)
pr_err("%s: CMD Format block failed\n", __func__);
break;
+ case SND_AUDIOCODEC_DTS:
+ case SND_AUDIOCODEC_DTS_LBR:
+ pr_debug("SND_AUDIOCODEC_DTS\n");
+ ret = q6asm_media_format_block(prtd->audio_client,
+ compr->codec);
+ if (ret < 0) {
+ pr_err("%s: CMD Format block failed\n", __func__);
+ return ret;
+ }
+ break;
default:
return -EINVAL;
}
@@ -286,6 +373,44 @@
return 0;
}
+static int msm_compr_capture_prepare(struct snd_pcm_substream *substream)
+{
+ struct snd_pcm_runtime *runtime = substream->runtime;
+ struct compr_audio *compr = runtime->private_data;
+ struct msm_audio *prtd = &compr->prtd;
+ struct audio_buffer *buf = prtd->audio_client->port[OUT].buf;
+ struct audio_aio_read_param read_param;
+ int ret = 0;
+ int i;
+ prtd->pcm_size = snd_pcm_lib_buffer_bytes(substream);
+ prtd->pcm_count = snd_pcm_lib_period_bytes(substream);
+ prtd->pcm_irq_pos = 0;
+
+ /* rate and channels are sent to audio driver */
+ prtd->samp_rate = runtime->rate;
+ prtd->channel_mode = runtime->channels;
+
+ if (prtd->enabled)
+ return ret;
+ read_param.len = prtd->pcm_count - COMPRE_CAPTURE_HEADER_SIZE;
+ pr_debug("%s: Samp_rate = %d, Channel = %d, pcm_size = %d,\n"
+ "pcm_count = %d, periods = %d\n",
+ __func__, prtd->samp_rate, prtd->channel_mode,
+ prtd->pcm_size, prtd->pcm_count, runtime->periods);
+
+ for (i = 0; i < runtime->periods; i++) {
+ read_param.uid = i;
+ read_param.paddr = ((unsigned long)(buf[i].phys) +
+ COMPRE_CAPTURE_HEADER_SIZE);
+ q6asm_async_read(prtd->audio_client, &read_param);
+ }
+ prtd->periods = runtime->periods;
+
+ prtd->enabled = 1;
+
+ return ret;
+}
+
static int msm_compr_trigger(struct snd_pcm_substream *substream, int cmd)
{
int ret = 0;
@@ -298,8 +423,17 @@
switch (cmd) {
case SNDRV_PCM_TRIGGER_START:
prtd->pcm_irq_pos = 0;
- if (compr->info.codec_param.codec.id ==
- SND_AUDIOCODEC_AC3_PASS_THROUGH) {
+ if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
+ if (compr->info.codec_param.codec.id ==
+ SND_AUDIOCODEC_AC3_PASS_THROUGH ||
+ compr->info.codec_param.codec.id ==
+ SND_AUDIOCODEC_DTS_PASS_THROUGH) {
+ msm_pcm_routing_reg_psthr_stream(
+ soc_prtd->dai_link->be_id,
+ prtd->session_id, substream->stream,
+ 1);
+ }
+ } else if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) {
msm_pcm_routing_reg_psthr_stream(
soc_prtd->dai_link->be_id,
prtd->session_id, substream->stream, 1);
@@ -312,11 +446,19 @@
break;
case SNDRV_PCM_TRIGGER_STOP:
pr_debug("SNDRV_PCM_TRIGGER_STOP\n");
- if (compr->info.codec_param.codec.id ==
- SND_AUDIOCODEC_AC3_PASS_THROUGH) {
+ if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
+ if (compr->info.codec_param.codec.id ==
+ SND_AUDIOCODEC_AC3_PASS_THROUGH) {
+ msm_pcm_routing_reg_psthr_stream(
+ soc_prtd->dai_link->be_id,
+ prtd->session_id, substream->stream,
+ 0);
+ }
+ } else if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) {
msm_pcm_routing_reg_psthr_stream(
soc_prtd->dai_link->be_id,
- prtd->session_id, substream->stream, 0);
+ prtd->session_id, substream->stream,
+ 0);
}
atomic_set(&prtd->start, 0);
break;
@@ -349,6 +491,9 @@
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;
+ compr->info.compr_cap.codecs[5] = SND_AUDIOCODEC_DTS;
+ compr->info.compr_cap.codecs[6] = SND_AUDIOCODEC_DTS_LBR;
+ compr->info.compr_cap.codecs[7] = SND_AUDIOCODEC_DTS_PASS_THROUGH;
/* Add new codecs here */
}
@@ -370,10 +515,6 @@
.rampingcurve = SOFT_VOLUME_CURVE_LINEAR,
};
- /* Capture path */
- if (substream->stream == SNDRV_PCM_STREAM_CAPTURE)
- return -EINVAL;
-
pr_debug("%s\n", __func__);
compr = kzalloc(sizeof(struct compr_audio), GFP_KERNEL);
if (compr == NULL) {
@@ -389,13 +530,18 @@
kfree(prtd);
return -ENOMEM;
}
- runtime->hw = msm_compr_hardware_playback;
pr_info("%s: session ID %d\n", __func__, prtd->audio_client->session);
prtd->session_id = prtd->audio_client->session;
- prtd->cmd_ack = 1;
+ if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
+ runtime->hw = msm_compr_hardware_playback;
+ prtd->cmd_ack = 1;
+ } else {
+ runtime->hw = msm_compr_hardware_capture;
+ }
+
ret = snd_pcm_hw_constraint_list(runtime, 0,
SNDRV_PCM_HW_PARAM_RATE,
@@ -410,7 +556,8 @@
prtd->dsp_cnt = 0;
atomic_set(&prtd->pending_buffer, 1);
- compr->codec = FORMAT_MP3;
+ if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
+ compr->codec = FORMAT_MP3;
populate_codec_list(compr, runtime);
runtime->private_data = compr;
compressed_audio.prtd = &compr->prtd;
@@ -473,6 +620,27 @@
return 0;
}
+static int msm_compr_capture_close(struct snd_pcm_substream *substream)
+{
+ struct snd_pcm_runtime *runtime = substream->runtime;
+ struct snd_soc_pcm_runtime *soc_prtd = substream->private_data;
+ struct compr_audio *compr = runtime->private_data;
+ struct msm_audio *prtd = &compr->prtd;
+ int dir = OUT;
+
+ pr_debug("%s\n", __func__);
+ atomic_set(&prtd->pending_buffer, 0);
+ q6asm_cmd(prtd->audio_client, CMD_CLOSE);
+ q6asm_audio_client_buf_free_contiguous(dir,
+ prtd->audio_client);
+ msm_pcm_routing_dereg_phy_stream(soc_prtd->dai_link->be_id,
+ SNDRV_PCM_STREAM_CAPTURE);
+ q6asm_audio_client_free(prtd->audio_client);
+ kfree(prtd);
+
+ return 0;
+}
+
static int msm_compr_close(struct snd_pcm_substream *substream)
{
int ret = 0;
@@ -480,7 +648,7 @@
if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
ret = msm_compr_playback_close(substream);
else if (substream->stream == SNDRV_PCM_STREAM_CAPTURE)
- ret = EINVAL;
+ ret = msm_compr_capture_close(substream);
return ret;
}
static int msm_compr_prepare(struct snd_pcm_substream *substream)
@@ -490,7 +658,7 @@
if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
ret = msm_compr_playback_prepare(substream);
else if (substream->stream == SNDRV_PCM_STREAM_CAPTURE)
- ret = EINVAL;
+ ret = msm_compr_capture_prepare(substream);
return ret;
}
@@ -504,7 +672,10 @@
if (prtd->pcm_irq_pos >= prtd->pcm_size)
prtd->pcm_irq_pos = 0;
- pr_debug("pcm_irq_pos = %d\n", prtd->pcm_irq_pos);
+ pr_debug("%s: pcm_irq_pos = %d, pcm_size = %d, sample_bits = %d,\n"
+ "frame_bits = %d\n", __func__, prtd->pcm_irq_pos,
+ prtd->pcm_size, runtime->sample_bits,
+ runtime->frame_bits);
return bytes_to_frames(runtime, (prtd->pcm_irq_pos));
}
@@ -546,28 +717,45 @@
if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
dir = IN;
else
- return -EINVAL;
+ dir = OUT;
- switch (compr->info.codec_param.codec.id) {
- case SND_AUDIOCODEC_AC3_PASS_THROUGH:
- ret = q6asm_open_write_compressed(prtd->audio_client,
+
+ if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
+ switch (compr->info.codec_param.codec.id) {
+ case SND_AUDIOCODEC_AC3_PASS_THROUGH:
+ case SND_AUDIOCODEC_DTS_PASS_THROUGH:
+ ret = q6asm_open_write_compressed(prtd->audio_client,
compr->codec);
+
+ if (ret < 0) {
+ pr_err("%s: Session out open failed\n",
+ __func__);
+ return -ENOMEM;
+ }
+ break;
+ default:
+ ret = q6asm_open_write(prtd->audio_client,
+ compr->codec);
+ if (ret < 0) {
+ pr_err("%s: Session out open failed\n",
+ __func__);
+ return -ENOMEM;
+ }
+ msm_pcm_routing_reg_phy_stream(
+ soc_prtd->dai_link->be_id,
+ prtd->session_id, substream->stream);
+
+ break;
+ }
+ } else if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) {
+ ret = q6asm_open_read_compressed(prtd->audio_client,
+ compr->codec);
+
if (ret < 0) {
pr_err("%s: compressed Session out open failed\n",
- __func__);
+ __func__);
return -ENOMEM;
}
- break;
- default:
- ret = q6asm_open_write(prtd->audio_client, compr->codec);
- if (ret < 0) {
- pr_err("%s: Session out open failed\n", __func__);
- return -ENOMEM;
- }
- msm_pcm_routing_reg_phy_stream(soc_prtd->dai_link->be_id,
- prtd->session_id, substream->stream);
-
- break;
}
ret = q6asm_set_io_mode(prtd->audio_client, ASYNC_IO_MODE);
if (ret < 0) {
@@ -586,13 +774,17 @@
}
buf = prtd->audio_client->port[dir].buf;
- pr_debug("%s:buf = %p\n", __func__, buf);
dma_buf->dev.type = SNDRV_DMA_TYPE_DEV;
dma_buf->dev.dev = substream->pcm->card->dev;
dma_buf->private_data = NULL;
dma_buf->area = buf[0].data;
dma_buf->addr = buf[0].phys;
dma_buf->bytes = runtime->hw.buffer_bytes_max;
+
+ pr_debug("%s: buf[%p]dma_buf->area[%p]dma_buf->addr[%p]\n"
+ "dma_buf->bytes[%d]\n", __func__,
+ (void *)buf, (void *)dma_buf->area,
+ (void *)dma_buf->addr, dma_buf->bytes);
if (!dma_buf->area)
return -ENOMEM;
@@ -674,6 +866,18 @@
pr_debug("SND_AUDIOCODEC_WMA_PRO\n");
compr->codec = FORMAT_WMA_V10PRO;
break;
+ case SND_AUDIOCODEC_DTS_PASS_THROUGH:
+ pr_debug("SND_AUDIOCODEC_DTS_PASS_THROUGH\n");
+ compr->codec = FORMAT_DTS;
+ break;
+ case SND_AUDIOCODEC_DTS:
+ pr_debug("SND_AUDIOCODEC_DTS\n");
+ compr->codec = FORMAT_DTS;
+ break;
+ case SND_AUDIOCODEC_DTS_LBR:
+ pr_debug("SND_AUDIOCODEC_DTS\n");
+ compr->codec = FORMAT_DTS_LBR;
+ break;
default:
pr_debug("FORMAT_LINEAR_PCM\n");
compr->codec = FORMAT_LINEAR_PCM;
diff --git a/sound/soc/msm/msm-dai-fe.c b/sound/soc/msm/msm-dai-fe.c
index 8a49f1b..be0951c 100644
--- a/sound/soc/msm/msm-dai-fe.c
+++ b/sound/soc/msm/msm-dai-fe.c
@@ -176,6 +176,17 @@
.rate_min = 8000,
.rate_max = 48000,
},
+ .capture = {
+ .stream_name = "MultiMedia4 Capture",
+ .aif_name = "MM_UL4",
+ .rates = (SNDRV_PCM_RATE_8000_48000|
+ SNDRV_PCM_RATE_KNOT),
+ .formats = SNDRV_PCM_FMTBIT_S16_LE,
+ .channels_min = 1,
+ .channels_max = 8,
+ .rate_min = 8000,
+ .rate_max = 48000,
+ },
.ops = &msm_fe_Multimedia_dai_ops,
.name = "MultiMedia4",
},
diff --git a/sound/soc/msm/msm-dai-q6.c b/sound/soc/msm/msm-dai-q6.c
index b3e5120..147316e 100644
--- a/sound/soc/msm/msm-dai-q6.c
+++ b/sound/soc/msm/msm-dai-q6.c
@@ -40,9 +40,14 @@
union afe_port_config port_config;
};
+struct msm_dai_q6_mi2s_dai_config {
+ u16 pdata_mi2s_lines;
+ struct msm_dai_q6_dai_data mi2s_dai_data;
+};
+
struct msm_dai_q6_mi2s_dai_data {
- struct msm_dai_q6_dai_data tx_dai;
- struct msm_dai_q6_dai_data rx_dai;
+ struct msm_dai_q6_mi2s_dai_config tx_dai;
+ struct msm_dai_q6_mi2s_dai_config rx_dai;
struct snd_pcm_hw_constraint_list rate_constraint;
struct snd_pcm_hw_constraint_list bitwidth_constraint;
};
@@ -86,8 +91,8 @@
static const char *mi2s_format[] = {
"LPCM",
"Compr",
- "60958-LPCM",
- "60958-Compr"};
+ "LPCM-60958",
+ "Compr-60958"};
static const struct soc_enum mi2s_config_enum[] = {
SOC_ENUM_SINGLE_EXT(4, mi2s_format),
@@ -143,21 +148,63 @@
{
struct msm_dai_q6_mi2s_dai_data *mi2s_dai_data =
dev_get_drvdata(dai->dev);
- struct msm_dai_q6_dai_data *dai_data =
+ struct msm_dai_q6_mi2s_dai_config *mi2s_dai_config =
(substream->stream == SNDRV_PCM_STREAM_PLAYBACK ?
&mi2s_dai_data->rx_dai : &mi2s_dai_data->tx_dai);
+ struct msm_dai_q6_dai_data *dai_data = &mi2s_dai_config->mi2s_dai_data;
dai_data->channels = params_channels(params);
switch (dai_data->channels) {
- case 2:
- dai_data->port_config.mi2s.channel = MSM_AFE_STEREO;
+ case 8:
+ case 7:
+ if (mi2s_dai_config->pdata_mi2s_lines < AFE_I2S_8CHS)
+ goto error_invalid_data;
+ dai_data->port_config.mi2s.line = AFE_I2S_8CHS;
break;
+ case 6:
+ case 5:
+ if (mi2s_dai_config->pdata_mi2s_lines < AFE_I2S_6CHS)
+ goto error_invalid_data;
+ dai_data->port_config.mi2s.line = AFE_I2S_6CHS;
+ break;
+ case 4:
+ case 3:
+ if (mi2s_dai_config->pdata_mi2s_lines < AFE_I2S_QUAD01)
+ goto error_invalid_data;
+ if (mi2s_dai_config->pdata_mi2s_lines == AFE_I2S_QUAD23)
+ dai_data->port_config.mi2s.line =
+ mi2s_dai_config->pdata_mi2s_lines;
+ else
+ dai_data->port_config.mi2s.line = AFE_I2S_QUAD01;
+ break;
+ case 2:
case 1:
- dai_data->port_config.mi2s.channel = MSM_AFE_MONO;
+ if (mi2s_dai_config->pdata_mi2s_lines < AFE_I2S_SD0)
+ goto error_invalid_data;
+ switch (mi2s_dai_config->pdata_mi2s_lines) {
+ case AFE_I2S_SD0:
+ case AFE_I2S_SD1:
+ case AFE_I2S_SD2:
+ case AFE_I2S_SD3:
+ dai_data->port_config.mi2s.line =
+ mi2s_dai_config->pdata_mi2s_lines;
+ break;
+ case AFE_I2S_QUAD01:
+ case AFE_I2S_6CHS:
+ case AFE_I2S_8CHS:
+ dai_data->port_config.mi2s.line = AFE_I2S_SD0;
+ break;
+ case AFE_I2S_QUAD23:
+ dai_data->port_config.mi2s.line = AFE_I2S_SD2;
+ break;
+ }
+ if (dai_data->channels == 2)
+ dai_data->port_config.mi2s.channel = MSM_AFE_STEREO;
+ else
+ dai_data->port_config.mi2s.channel = MSM_AFE_MONO;
break;
default:
- pr_warn("greater than stereo has not been validated");
- break;
+ goto error_invalid_data;
}
dai_data->rate = params_rate(params);
dai_data->port_config.mi2s.bitwidth = 16;
@@ -166,7 +213,14 @@
mi2s_dai_data->rate_constraint.list = &dai_data->rate;
mi2s_dai_data->bitwidth_constraint.list = &dai_data->bitwidth;
}
+
+ pr_debug("%s: dai_data->channels = %d, line = %d\n", __func__,
+ dai_data->channels, dai_data->port_config.mi2s.line);
return 0;
+error_invalid_data:
+ pr_err("%s: dai_data->channels = %d, line = %d\n", __func__,
+ dai_data->channels, dai_data->port_config.mi2s.line);
+ return -EINVAL;
}
static int msm_dai_q6_mi2s_get_lineconfig(u16 sd_lines, u16 *config_ptr,
@@ -276,7 +330,9 @@
}
if (ch_cnt) {
- dai_data->rx_dai.port_config.mi2s.line = sdline_config;
+ dai_data->rx_dai.mi2s_dai_data.port_config.mi2s.line =
+ sdline_config;
+ dai_data->rx_dai.pdata_mi2s_lines = sdline_config;
dai_driver->playback.channels_min = 1;
dai_driver->playback.channels_max = ch_cnt << 1;
} else {
@@ -292,7 +348,9 @@
}
if (ch_cnt) {
- dai_data->tx_dai.port_config.mi2s.line = sdline_config;
+ dai_data->tx_dai.mi2s_dai_data.port_config.mi2s.line =
+ sdline_config;
+ dai_data->tx_dai.pdata_mi2s_lines = sdline_config;
dai_driver->capture.channels_min = 1;
dai_driver->capture.channels_max = ch_cnt << 1;
} else {
@@ -301,8 +359,8 @@
}
dev_info(&pdev->dev, "%s: playback sdline %x capture sdline %x\n",
- __func__, dai_data->rx_dai.port_config.mi2s.line,
- dai_data->tx_dai.port_config.mi2s.line);
+ __func__, dai_data->rx_dai.pdata_mi2s_lines,
+ dai_data->tx_dai.pdata_mi2s_lines);
dev_info(&pdev->dev, "%s: playback ch_max %d capture ch_mx %d\n",
__func__, dai_driver->playback.channels_max,
dai_driver->capture.channels_max);
@@ -315,8 +373,10 @@
struct msm_dai_q6_mi2s_dai_data *mi2s_dai_data =
dev_get_drvdata(dai->dev);
- if (test_bit(STATUS_PORT_STARTED, mi2s_dai_data->rx_dai.status_mask) ||
- test_bit(STATUS_PORT_STARTED, mi2s_dai_data->rx_dai.status_mask)) {
+ if (test_bit(STATUS_PORT_STARTED,
+ mi2s_dai_data->rx_dai.mi2s_dai_data.status_mask) ||
+ test_bit(STATUS_PORT_STARTED,
+ mi2s_dai_data->tx_dai.mi2s_dai_data.status_mask)) {
dev_err(dai->dev, "%s: err chg i2s mode while dai running",
__func__);
return -EPERM;
@@ -324,12 +384,12 @@
switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
case SND_SOC_DAIFMT_CBS_CFS:
- mi2s_dai_data->rx_dai.port_config.mi2s.ws = 1;
- mi2s_dai_data->tx_dai.port_config.mi2s.ws = 1;
+ mi2s_dai_data->rx_dai.mi2s_dai_data.port_config.mi2s.ws = 1;
+ mi2s_dai_data->tx_dai.mi2s_dai_data.port_config.mi2s.ws = 1;
break;
case SND_SOC_DAIFMT_CBM_CFM:
- mi2s_dai_data->rx_dai.port_config.mi2s.ws = 0;
- mi2s_dai_data->tx_dai.port_config.mi2s.ws = 0;
+ mi2s_dai_data->rx_dai.mi2s_dai_data.port_config.mi2s.ws = 0;
+ mi2s_dai_data->tx_dai.mi2s_dai_data.port_config.mi2s.ws = 0;
break;
default:
return -EINVAL;
@@ -345,7 +405,8 @@
dev_get_drvdata(dai->dev);
struct msm_dai_q6_dai_data *dai_data =
(substream->stream == SNDRV_PCM_STREAM_PLAYBACK ?
- &mi2s_dai_data->rx_dai : &mi2s_dai_data->tx_dai);
+ &mi2s_dai_data->rx_dai.mi2s_dai_data :
+ &mi2s_dai_data->tx_dai.mi2s_dai_data);
int rc = 0;
if (!test_bit(STATUS_PORT_STARTED, dai_data->status_mask)) {
@@ -364,7 +425,8 @@
dev_get_drvdata(dai->dev);
struct msm_dai_q6_dai_data *dai_data =
(substream->stream == SNDRV_PCM_STREAM_PLAYBACK ?
- &mi2s_dai_data->rx_dai : &mi2s_dai_data->tx_dai);
+ &mi2s_dai_data->rx_dai.mi2s_dai_data :
+ &mi2s_dai_data->tx_dai.mi2s_dai_data);
u16 port_id = (substream->stream == SNDRV_PCM_STREAM_PLAYBACK ?
MI2S_RX : MI2S_TX);
int rc = 0;
@@ -406,7 +468,8 @@
dev_get_drvdata(dai->dev);
struct msm_dai_q6_dai_data *dai_data =
(substream->stream == SNDRV_PCM_STREAM_PLAYBACK ?
- &mi2s_dai_data->rx_dai : &mi2s_dai_data->tx_dai);
+ &mi2s_dai_data->rx_dai.mi2s_dai_data :
+ &mi2s_dai_data->tx_dai.mi2s_dai_data);
u16 port_id = (substream->stream == SNDRV_PCM_STREAM_PLAYBACK ?
MI2S_RX : MI2S_TX);
int rc = 0;
@@ -418,8 +481,10 @@
clear_bit(STATUS_PORT_STARTED, dai_data->status_mask);
}
- if (!test_bit(STATUS_PORT_STARTED, mi2s_dai_data->rx_dai.status_mask) &&
- !test_bit(STATUS_PORT_STARTED, mi2s_dai_data->rx_dai.status_mask)) {
+ if (!test_bit(STATUS_PORT_STARTED,
+ mi2s_dai_data->rx_dai.mi2s_dai_data.status_mask) &&
+ !test_bit(STATUS_PORT_STARTED,
+ mi2s_dai_data->rx_dai.mi2s_dai_data.status_mask)) {
mi2s_dai_data->rate_constraint.list = NULL;
mi2s_dai_data->bitwidth_constraint.list = NULL;
}
@@ -1268,9 +1333,9 @@
struct snd_kcontrol *kcontrol = NULL;
int rc = 0;
- if (mi2s_dai_data->rx_dai.port_config.mi2s.line) {
+ if (mi2s_dai_data->rx_dai.mi2s_dai_data.port_config.mi2s.line) {
kcontrol = snd_ctl_new1(&mi2s_config_controls[0],
- &mi2s_dai_data->rx_dai);
+ &mi2s_dai_data->rx_dai.mi2s_dai_data);
rc = snd_ctl_add(dai->card->snd_card, kcontrol);
if (IS_ERR_VALUE(rc)) {
@@ -1279,10 +1344,10 @@
}
}
- if (mi2s_dai_data->tx_dai.port_config.mi2s.line) {
+ if (mi2s_dai_data->tx_dai.mi2s_dai_data.port_config.mi2s.line) {
rc = snd_ctl_add(dai->card->snd_card,
- snd_ctl_new1(&mi2s_config_controls[2],
- &mi2s_dai_data->tx_dai));
+ snd_ctl_new1(&mi2s_config_controls[2],
+ &mi2s_dai_data->tx_dai.mi2s_dai_data));
if (IS_ERR_VALUE(rc)) {
if (kcontrol)
@@ -1302,19 +1367,21 @@
int rc;
/* If AFE port is still up, close it */
- if (test_bit(STATUS_PORT_STARTED, mi2s_dai_data->rx_dai.status_mask)) {
+ if (test_bit(STATUS_PORT_STARTED,
+ mi2s_dai_data->rx_dai.mi2s_dai_data.status_mask)) {
rc = afe_close(MI2S_RX); /* can block */
if (IS_ERR_VALUE(rc))
dev_err(dai->dev, "fail to close MI2S_RX port\n");
clear_bit(STATUS_PORT_STARTED,
- mi2s_dai_data->rx_dai.status_mask);
+ mi2s_dai_data->rx_dai.mi2s_dai_data.status_mask);
}
- if (test_bit(STATUS_PORT_STARTED, mi2s_dai_data->tx_dai.status_mask)) {
+ if (test_bit(STATUS_PORT_STARTED,
+ mi2s_dai_data->tx_dai.mi2s_dai_data.status_mask)) {
rc = afe_close(MI2S_TX); /* can block */
if (IS_ERR_VALUE(rc))
dev_err(dai->dev, "fail to close MI2S_TX port\n");
clear_bit(STATUS_PORT_STARTED,
- mi2s_dai_data->tx_dai.status_mask);
+ mi2s_dai_data->tx_dai.mi2s_dai_data.status_mask);
}
kfree(mi2s_dai_data);
snd_soc_unregister_dai(dai->dev);
@@ -1966,6 +2033,8 @@
return 0;
err_pdata:
+
+ dev_err(&pdev->dev, "fail to msm_dai_q6_mi2s_dev_probe\n");
kfree(dai_data);
rtn:
return rc;
diff --git a/sound/soc/msm/msm-pcm-q6.c b/sound/soc/msm/msm-pcm-q6.c
index 39ce436..168cf97 100644
--- a/sound/soc/msm/msm-pcm-q6.c
+++ b/sound/soc/msm/msm-pcm-q6.c
@@ -532,12 +532,15 @@
int dir = OUT;
pr_debug("%s\n", __func__);
- q6asm_cmd(prtd->audio_client, CMD_CLOSE);
- q6asm_audio_client_buf_free_contiguous(dir,
+ if (prtd->audio_client) {
+ q6asm_cmd(prtd->audio_client, CMD_CLOSE);
+ q6asm_audio_client_buf_free_contiguous(dir,
prtd->audio_client);
+ q6asm_audio_client_free(prtd->audio_client);
+ }
+
msm_pcm_routing_dereg_phy_stream(soc_prtd->dai_link->be_id,
- SNDRV_PCM_STREAM_CAPTURE);
- q6asm_audio_client_free(prtd->audio_client);
+ SNDRV_PCM_STREAM_CAPTURE);
kfree(prtd);
return 0;
@@ -638,7 +641,7 @@
if (ret < 0) {
pr_err("%s: q6asm_open_read failed\n", __func__);
q6asm_audio_client_free(prtd->audio_client);
- kfree(prtd);
+ prtd->audio_client = NULL;
return -ENOMEM;
}
}
diff --git a/sound/soc/msm/msm-pcm-routing.c b/sound/soc/msm/msm-pcm-routing.c
index 239c904..387fe44 100644
--- a/sound/soc/msm/msm-pcm-routing.c
+++ b/sound/soc/msm/msm-pcm-routing.c
@@ -1352,6 +1352,13 @@
msm_routing_put_audio_mixer),
};
+
+static const struct snd_kcontrol_new mmul4_mixer_controls[] = {
+ SOC_SINGLE_EXT("MI2S_TX", MSM_BACKEND_DAI_MI2S_TX,
+ MSM_FRONTEND_DAI_MULTIMEDIA4, 1, 0, msm_routing_get_audio_mixer,
+ msm_routing_put_audio_mixer),
+};
+
static const struct snd_kcontrol_new pri_rx_voice_mixer_controls[] = {
SOC_SINGLE_EXT("CSVoice", MSM_BACKEND_DAI_PRI_I2S_RX,
MSM_FRONTEND_DAI_CS_VOICE, 1, 0, msm_routing_get_voice_mixer,
@@ -1983,6 +1990,7 @@
SND_SOC_DAPM_AIF_IN("VOIP_DL", "VoIP Playback", 0, 0, 0, 0),
SND_SOC_DAPM_AIF_OUT("MM_UL1", "MultiMedia1 Capture", 0, 0, 0, 0),
SND_SOC_DAPM_AIF_OUT("MM_UL2", "MultiMedia2 Capture", 0, 0, 0, 0),
+ SND_SOC_DAPM_AIF_OUT("MM_UL4", "MultiMedia4 Capture", 0, 0, 0, 0),
SND_SOC_DAPM_AIF_IN("CS-VOICE_DL1", "CS-VOICE Playback", 0, 0, 0, 0),
SND_SOC_DAPM_AIF_OUT("CS-VOICE_UL1", "CS-VOICE Capture", 0, 0, 0, 0),
SND_SOC_DAPM_AIF_IN("VoLTE_DL", "VoLTE Playback", 0, 0, 0, 0),
@@ -2080,6 +2088,8 @@
mmul1_mixer_controls, ARRAY_SIZE(mmul1_mixer_controls)),
SND_SOC_DAPM_MIXER("MultiMedia2 Mixer", SND_SOC_NOPM, 0, 0,
mmul2_mixer_controls, ARRAY_SIZE(mmul2_mixer_controls)),
+ SND_SOC_DAPM_MIXER("MultiMedia4 Mixer", SND_SOC_NOPM, 0, 0,
+ mmul4_mixer_controls, ARRAY_SIZE(mmul4_mixer_controls)),
SND_SOC_DAPM_MIXER("AUX_PCM_RX Audio Mixer", SND_SOC_NOPM, 0, 0,
auxpcm_rx_mixer_controls, ARRAY_SIZE(auxpcm_rx_mixer_controls)),
SND_SOC_DAPM_MIXER("SEC_AUX_PCM_RX Audio Mixer", SND_SOC_NOPM, 0, 0,
@@ -2247,6 +2257,7 @@
{"MultiMedia1 Mixer", "PRI_TX", "PRI_I2S_TX"},
{"MultiMedia1 Mixer", "MI2S_TX", "MI2S_TX"},
{"MultiMedia2 Mixer", "MI2S_TX", "MI2S_TX"},
+ {"MultiMedia4 Mixer", "MI2S_TX", "MI2S_TX"},
{"MultiMedia1 Mixer", "SLIM_0_TX", "SLIMBUS_0_TX"},
{"MultiMedia1 Mixer", "AUX_PCM_UL_TX", "AUX_PCM_TX"},
{"MultiMedia1 Mixer", "SEC_AUX_PCM_UL_TX", "SEC_AUX_PCM_TX"},
@@ -2276,6 +2287,7 @@
{"MM_UL1", NULL, "MultiMedia1 Mixer"},
{"MultiMedia2 Mixer", "INTERNAL_FM_TX", "INT_FM_TX"},
{"MM_UL2", NULL, "MultiMedia2 Mixer"},
+ {"MM_UL4", NULL, "MultiMedia4 Mixer"},
{"AUX_PCM_RX Audio Mixer", "MultiMedia1", "MM_DL1"},
{"AUX_PCM_RX Audio Mixer", "MultiMedia2", "MM_DL2"},
diff --git a/sound/soc/msm/qdsp6/q6asm.c b/sound/soc/msm/qdsp6/q6asm.c
index 50011a1..f39a227 100644
--- a/sound/soc/msm/qdsp6/q6asm.c
+++ b/sound/soc/msm/qdsp6/q6asm.c
@@ -737,6 +737,9 @@
cnt++;
}
ac->port[dir].max_buf_cnt = cnt;
+
+ pr_debug("%s ac->port[%d].max_buf_cnt[%d]\n", __func__, dir,
+ ac->port[dir].max_buf_cnt);
mutex_unlock(&ac->cmd_lock);
rc = q6asm_memory_map(ac, buf[0].phys, dir, bufsz, cnt);
if (rc < 0) {
@@ -857,6 +860,7 @@
case ASM_DATA_CMD_MEDIA_FORMAT_UPDATE:
case ASM_STREAM_CMD_SET_ENCDEC_PARAM:
case ASM_STREAM_CMD_OPEN_WRITE_COMPRESSED:
+ case ASM_STREAM_CMD_OPEN_READ_COMPRESSED:
if (atomic_read(&ac->cmd_state)) {
atomic_set(&ac->cmd_state, 0);
wake_up(&ac->cmd_wait);
@@ -1260,6 +1264,42 @@
return -EINVAL;
}
+int q6asm_open_read_compressed(struct audio_client *ac, uint32_t format)
+{
+ int rc = 0x00;
+ struct asm_stream_cmd_open_read_compressed open;
+#ifdef CONFIG_DEBUG_FS
+ in_cont_index = 0;
+#endif
+ if ((ac == NULL) || (ac->apr == NULL)) {
+ pr_err("%s: APR handle NULL\n", __func__);
+ return -EINVAL;
+ }
+ pr_debug("%s:session[%d]", __func__, ac->session);
+
+ q6asm_add_hdr(ac, &open.hdr, sizeof(open), TRUE);
+ open.hdr.opcode = ASM_STREAM_CMD_OPEN_READ_COMPRESSED;
+ /* hardcoded as following*/
+ open.frame_per_buf = 1;
+ open.uMode = 0;
+
+ rc = apr_send_pkt(ac->apr, (uint32_t *) &open);
+ if (rc < 0) {
+ pr_err("open failed op[0x%x]rc[%d]\n", open.hdr.opcode, rc);
+ goto fail_cmd;
+ }
+ rc = wait_event_timeout(ac->cmd_wait,
+ (atomic_read(&ac->cmd_state) == 0), 5*HZ);
+ if (!rc) {
+ pr_err("%s: timeout. waited for OPEN_READ_COMPRESSED rc[%d]\n",
+ __func__, rc);
+ goto fail_cmd;
+ }
+ return 0;
+fail_cmd:
+ return -EINVAL;
+}
+
int q6asm_open_write_compressed(struct audio_client *ac, uint32_t format)
{
int rc = 0x00;
@@ -1289,6 +1329,9 @@
case FORMAT_DTS:
open.format = DTS;
break;
+ case FORMAT_DTS_LBR:
+ open.format = DTS_LBR;
+ break;
case FORMAT_AAC:
open.format = MPEG4_AAC;
break;
@@ -1372,6 +1415,12 @@
case FORMAT_MP3:
open.format = MP3;
break;
+ case FORMAT_DTS:
+ open.format = DTS;
+ break;
+ case FORMAT_DTS_LBR:
+ open.format = DTS_LBR;
+ break;
default:
pr_err("%s: Invalid format[%d]\n", __func__, format);
goto fail_cmd;
@@ -2263,6 +2312,12 @@
case FORMAT_MP3:
fmt.format = MP3;
break;
+ case FORMAT_DTS:
+ fmt.format = DTS;
+ break;
+ case FORMAT_DTS_LBR:
+ fmt.format = DTS_LBR;
+ break;
default:
pr_err("Invalid format[%d]\n", format);
goto fail_cmd;