Merge "msm: cam: reqmgr: Add list empty check for task list" into msm-4.9
diff --git a/arch/arm64/boot/dts/qcom/sdm845-cdp.dtsi b/arch/arm64/boot/dts/qcom/sdm845-cdp.dtsi
index 6f35bf7..68824d7 100644
--- a/arch/arm64/boot/dts/qcom/sdm845-cdp.dtsi
+++ b/arch/arm64/boot/dts/qcom/sdm845-cdp.dtsi
@@ -209,6 +209,30 @@
status = "ok";
};
+&labibb {
+ status = "ok";
+ qcom,qpnp-labibb-mode = "lcd";
+};
+
+&dsi_dual_nt35597_truly_video {
+ qcom,panel-supply-entries = <&dsi_panel_pwr_supply>;
+ qcom,mdss-dsi-bl-pmic-control-type = "bl_ctrl_wled";
+ qcom,mdss-dsi-bl-min-level = <1>;
+ qcom,mdss-dsi-bl-max-level = <4095>;
+ qcom,mdss-dsi-panel-mode-gpio-state = "dual_port";
+ qcom,panel-mode-gpio = <&tlmm 52 0>;
+ qcom,platform-reset-gpio = <&tlmm 6 0>;
+};
+
+&dsi_dual_nt35597_truly_video_display {
+ qcom,dsi-display-active;
+};
+
+&pmi8998_wled {
+ status = "okay";
+ qcom,led-strings-list = [01 02];
+};
+
&qupv3_se8_spi {
status = "ok";
};
diff --git a/arch/arm64/boot/dts/qcom/sdm845-mtp.dtsi b/arch/arm64/boot/dts/qcom/sdm845-mtp.dtsi
index faa0b5e..4391189 100644
--- a/arch/arm64/boot/dts/qcom/sdm845-mtp.dtsi
+++ b/arch/arm64/boot/dts/qcom/sdm845-mtp.dtsi
@@ -78,6 +78,30 @@
};
};
+&labibb {
+ status = "ok";
+ qcom,qpnp-labibb-mode = "lcd";
+};
+
+&dsi_dual_nt35597_truly_video {
+ qcom,panel-supply-entries = <&dsi_panel_pwr_supply>;
+ qcom,mdss-dsi-bl-pmic-control-type = "bl_ctrl_wled";
+ qcom,mdss-dsi-bl-min-level = <1>;
+ qcom,mdss-dsi-bl-max-level = <4095>;
+ qcom,mdss-dsi-panel-mode-gpio-state = "dual_port";
+ qcom,panel-mode-gpio = <&tlmm 52 0>;
+ qcom,platform-reset-gpio = <&tlmm 6 0>;
+};
+
+&dsi_dual_nt35597_truly_video_display {
+ qcom,dsi-display-active;
+};
+
+&pmi8998_wled {
+ status = "okay";
+ qcom,led-strings-list = [01 02];
+};
+
&ufsphy_mem {
compatible = "qcom,ufs-phy-qmp-v3";
diff --git a/arch/arm64/boot/dts/qcom/sdm845-sde-display.dtsi b/arch/arm64/boot/dts/qcom/sdm845-sde-display.dtsi
index 2ff9b2f..e56073c 100644
--- a/arch/arm64/boot/dts/qcom/sdm845-sde-display.dtsi
+++ b/arch/arm64/boot/dts/qcom/sdm845-sde-display.dtsi
@@ -23,6 +23,7 @@
#include "dsi-panel-sharp-1080p-cmd.dtsi"
#include "dsi-panel-sharp-dualmipi-1080p-120hz.dtsi"
#include "dsi-panel-s6e3ha3-amoled-dualmipi-wqhd-cmd.dtsi"
+#include <dt-bindings/clock/mdss-10nm-pll-clk.h>
&soc {
dsi_panel_pwr_supply: dsi_panel_pwr_supply {
@@ -198,15 +199,15 @@
qcom,dsi-ctrl = <&mdss_dsi0 &mdss_dsi1>;
qcom,dsi-phy = <&mdss_dsi_phy0 &mdss_dsi_phy1>;
- clocks = <&clock_dispcc DISP_CC_MDSS_BYTE0_CLK_SRC>,
- <&clock_dispcc DISP_CC_MDSS_PCLK0_CLK_SRC>;
+ clocks = <&mdss_dsi0_pll BYTECLK_MUX_0_CLK>,
+ <&mdss_dsi0_pll PCLK_MUX_0_CLK>;
clock-names = "src_byte_clk", "src_pixel_clk";
pinctrl-names = "panel_active", "panel_suspend";
pinctrl-0 = <&sde_dsi_active &sde_te_active>;
pinctrl-1 = <&sde_dsi_suspend &sde_te_suspend>;
- qcom,platform-te-gpio = <&tlmm 10 0>;
qcom,platform-reset-gpio = <&tlmm 6 0>;
+ qcom,panel-mode-gpio = <&tlmm 52 0>;
qcom,dsi-panel = <&dsi_dual_nt35597_truly_video>;
vddio-supply = <&pm8998_l14>;
@@ -291,7 +292,7 @@
};
&mdss_mdp {
- connectors = <&sde_wb>;
+ connectors = <&sde_wb &dsi_dual_nt35597_truly_video_display>;
};
&dsi_dual_nt35597_truly_video {
diff --git a/arch/arm64/configs/sdm845-perf_defconfig b/arch/arm64/configs/sdm845-perf_defconfig
index 9a2ab8c..fa6bae8 100644
--- a/arch/arm64/configs/sdm845-perf_defconfig
+++ b/arch/arm64/configs/sdm845-perf_defconfig
@@ -442,6 +442,7 @@
CONFIG_QCOM_LAZY_MAPPING=y
CONFIG_IOMMU_DEBUG=y
CONFIG_IOMMU_TESTS=y
+CONFIG_QCOM_RUN_QUEUE_STATS=y
CONFIG_QCOM_LLCC=y
CONFIG_QCOM_SDM845_LLCC=y
CONFIG_MSM_BOOT_STATS=y
diff --git a/arch/arm64/configs/sdm845_defconfig b/arch/arm64/configs/sdm845_defconfig
index 31f8703..a71aa64 100644
--- a/arch/arm64/configs/sdm845_defconfig
+++ b/arch/arm64/configs/sdm845_defconfig
@@ -459,6 +459,7 @@
CONFIG_IOMMU_DEBUG=y
CONFIG_IOMMU_TESTS=y
CONFIG_QCOM_CPUSS_DUMP=y
+CONFIG_QCOM_RUN_QUEUE_STATS=y
CONFIG_QCOM_LLCC=y
CONFIG_QCOM_SDM845_LLCC=y
CONFIG_MSM_BOOT_STATS=y
diff --git a/drivers/clk/qcom/gcc-sdm845.c b/drivers/clk/qcom/gcc-sdm845.c
index 4824546..678dd10 100644
--- a/drivers/clk/qcom/gcc-sdm845.c
+++ b/drivers/clk/qcom/gcc-sdm845.c
@@ -3295,6 +3295,8 @@
[GCC_USB3PHY_PHY_SEC_BCR] = { 0x50010 },
[GCC_USB3_DP_PHY_SEC_BCR] = { 0x50014 },
[GCC_USB_PHY_CFG_AHB2PHY_BCR] = { 0x6a000 },
+ [GCC_PCIE_0_PHY_BCR] = { 0x6c01c },
+ [GCC_PCIE_1_PHY_BCR] = { 0x8e01c },
};
static const struct regmap_config gcc_sdm845_regmap_config = {
diff --git a/drivers/devfreq/bimc-bwmon.c b/drivers/devfreq/bimc-bwmon.c
index 56036ea..d70104d 100644
--- a/drivers/devfreq/bimc-bwmon.c
+++ b/drivers/devfreq/bimc-bwmon.c
@@ -54,6 +54,11 @@
#define MON2_ZONE_CNT(m) ((m)->base + 0x2D8)
#define MON2_ZONE_MAX(m, zone) ((m)->base + 0x2E0 + 0x4 * zone)
+enum bwmon_type {
+ BWMON_1,
+ BWMON_2,
+};
+
struct bwmon_spec {
bool wrap_on_thres;
bool overflow;
@@ -76,7 +81,6 @@
};
#define to_bwmon(ptr) container_of(ptr, struct bwmon, hw)
-#define has_hw_sampling(m) (m->spec->hw_sampling)
#define ENABLE_MASK BIT(0)
#define THROTTLE_MASK 0x1F
@@ -86,20 +90,29 @@
#define INT_STATUS_MASK_HWS 0xF0
static DEFINE_SPINLOCK(glb_lock);
-static void mon_enable(struct bwmon *m)
+
+static __always_inline void mon_enable(struct bwmon *m, enum bwmon_type type)
{
- if (has_hw_sampling(m))
- writel_relaxed((ENABLE_MASK | m->throttle_adj), MON2_EN(m));
- else
- writel_relaxed((ENABLE_MASK | m->throttle_adj), MON_EN(m));
+ switch (type) {
+ case BWMON_1:
+ writel_relaxed(ENABLE_MASK | m->throttle_adj, MON_EN(m));
+ break;
+ case BWMON_2:
+ writel_relaxed(ENABLE_MASK | m->throttle_adj, MON2_EN(m));
+ break;
+ }
}
-static void mon_disable(struct bwmon *m)
+static __always_inline void mon_disable(struct bwmon *m, enum bwmon_type type)
{
- if (has_hw_sampling(m))
- writel_relaxed(m->throttle_adj, MON2_EN(m));
- else
+ switch (type) {
+ case BWMON_1:
writel_relaxed(m->throttle_adj, MON_EN(m));
+ break;
+ case BWMON_2:
+ writel_relaxed(m->throttle_adj, MON2_EN(m));
+ break;
+ }
/*
* mon_disable() and mon_irq_clear(),
* If latter goes first and count happen to trigger irq, we would
@@ -110,24 +123,25 @@
#define MON_CLEAR_BIT 0x1
#define MON_CLEAR_ALL_BIT 0x2
-static void mon_clear(struct bwmon *m, bool clear_all)
+static __always_inline
+void mon_clear(struct bwmon *m, bool clear_all, enum bwmon_type type)
{
- if (!has_hw_sampling(m)) {
+ switch (type) {
+ case BWMON_1:
writel_relaxed(MON_CLEAR_BIT, MON_CLEAR(m));
- goto out;
+ break;
+ case BWMON_2:
+ if (clear_all)
+ writel_relaxed(MON_CLEAR_ALL_BIT, MON2_CLEAR(m));
+ else
+ writel_relaxed(MON_CLEAR_BIT, MON2_CLEAR(m));
+ break;
}
-
- if (clear_all)
- writel_relaxed(MON_CLEAR_ALL_BIT, MON2_CLEAR(m));
- else
- writel_relaxed(MON_CLEAR_BIT, MON2_CLEAR(m));
-
/*
* The counter clear and IRQ clear bits are not in the same 4KB
* region. So, we need to make sure the counter clear is completed
* before we try to clear the IRQ or do any other counter operations.
*/
-out:
mb();
}
@@ -148,72 +162,141 @@
}
}
-static void mon_irq_enable(struct bwmon *m)
+static void mon_glb_irq_enable(struct bwmon *m)
{
u32 val;
- spin_lock(&glb_lock);
val = readl_relaxed(GLB_INT_EN(m));
val |= 1 << m->mport;
writel_relaxed(val, GLB_INT_EN(m));
-
- val = readl_relaxed(MON_INT_EN(m));
- val |= has_hw_sampling(m) ? INT_STATUS_MASK_HWS : INT_ENABLE_V1;
- writel_relaxed(val, MON_INT_EN(m));
- spin_unlock(&glb_lock);
- /*
- * make Sure irq enable complete for local and global
- * to avoid race with other monitor calls
- */
- mb();
}
-static void mon_irq_disable(struct bwmon *m)
+static __always_inline
+void mon_irq_enable(struct bwmon *m, enum bwmon_type type)
{
u32 val;
spin_lock(&glb_lock);
- val = readl_relaxed(GLB_INT_EN(m));
- val &= ~(1 << m->mport);
- writel_relaxed(val, GLB_INT_EN(m));
-
- val = readl_relaxed(MON_INT_EN(m));
- val &= has_hw_sampling(m) ? ~INT_STATUS_MASK_HWS : ~INT_ENABLE_V1;
- writel_relaxed(val, MON_INT_EN(m));
+ switch (type) {
+ case BWMON_1:
+ mon_glb_irq_enable(m);
+ val = readl_relaxed(MON_INT_EN(m));
+ val |= INT_ENABLE_V1;
+ writel_relaxed(val, MON_INT_EN(m));
+ break;
+ case BWMON_2:
+ mon_glb_irq_enable(m);
+ val = readl_relaxed(MON_INT_EN(m));
+ val |= INT_STATUS_MASK_HWS;
+ writel_relaxed(val, MON_INT_EN(m));
+ break;
+ }
spin_unlock(&glb_lock);
/*
- * make Sure irq disable complete for local and global
+ * make sure irq enable complete for local and global
* to avoid race with other monitor calls
*/
mb();
}
-static unsigned int mon_irq_status(struct bwmon *m)
+static void mon_glb_irq_disable(struct bwmon *m)
+{
+ u32 val;
+
+ val = readl_relaxed(GLB_INT_EN(m));
+ val &= ~(1 << m->mport);
+ writel_relaxed(val, GLB_INT_EN(m));
+}
+
+static __always_inline
+void mon_irq_disable(struct bwmon *m, enum bwmon_type type)
+{
+ u32 val;
+
+ spin_lock(&glb_lock);
+
+ switch (type) {
+ case BWMON_1:
+ mon_glb_irq_disable(m);
+ val = readl_relaxed(MON_INT_EN(m));
+ val &= ~INT_ENABLE_V1;
+ writel_relaxed(val, MON_INT_EN(m));
+ break;
+ case BWMON_2:
+ mon_glb_irq_disable(m);
+ val = readl_relaxed(MON_INT_EN(m));
+ val &= ~INT_STATUS_MASK_HWS;
+ writel_relaxed(val, MON_INT_EN(m));
+ break;
+ }
+ spin_unlock(&glb_lock);
+ /*
+ * make sure irq disable complete for local and global
+ * to avoid race with other monitor calls
+ */
+ mb();
+}
+
+static __always_inline
+unsigned int mon_irq_status(struct bwmon *m, enum bwmon_type type)
{
u32 mval;
- mval = readl_relaxed(MON_INT_STATUS(m));
-
- dev_dbg(m->dev, "IRQ status p:%x, g:%x\n", mval,
- readl_relaxed(GLB_INT_STATUS(m)));
-
- mval &= has_hw_sampling(m) ? INT_STATUS_MASK_HWS : INT_STATUS_MASK;
+ switch (type) {
+ case BWMON_1:
+ mval = readl_relaxed(MON_INT_STATUS(m));
+ dev_dbg(m->dev, "IRQ status p:%x, g:%x\n", mval,
+ readl_relaxed(GLB_INT_STATUS(m)));
+ mval &= INT_STATUS_MASK;
+ break;
+ case BWMON_2:
+ mval = readl_relaxed(MON_INT_STATUS(m));
+ dev_dbg(m->dev, "IRQ status p:%x, g:%x\n", mval,
+ readl_relaxed(GLB_INT_STATUS(m)));
+ mval &= INT_STATUS_MASK_HWS;
+ break;
+ }
return mval;
}
-static void mon_irq_clear(struct bwmon *m)
+
+static void mon_glb_irq_clear(struct bwmon *m)
{
- u32 intclr;
-
- intclr = has_hw_sampling(m) ? INT_STATUS_MASK_HWS : INT_STATUS_MASK;
-
- writel_relaxed(intclr, MON_INT_CLR(m));
+ /*
+ * Synchronize the local interrupt clear in mon_irq_clear()
+ * with the global interrupt clear here. Otherwise, the CPU
+ * may reorder the two writes and clear the global interrupt
+ * before the local interrupt, causing the global interrupt
+ * to be retriggered by the local interrupt still being high.
+ */
mb();
writel_relaxed(1 << m->mport, GLB_INT_CLR(m));
+ /*
+ * Similarly, because the global registers are in a different
+ * region than the local registers, we need to ensure any register
+ * writes to enable the monitor after this call are ordered with the
+ * clearing here so that local writes don't happen before the
+ * interrupt is cleared.
+ */
mb();
}
+static __always_inline
+void mon_irq_clear(struct bwmon *m, enum bwmon_type type)
+{
+ switch (type) {
+ case BWMON_1:
+ writel_relaxed(INT_STATUS_MASK, MON_INT_CLR(m));
+ mon_glb_irq_clear(m);
+ break;
+ case BWMON_2:
+ writel_relaxed(INT_STATUS_MASK_HWS, MON_INT_CLR(m));
+ mon_glb_irq_clear(m);
+ break;
+ }
+}
+
static int mon_set_throttle_adj(struct bw_hwmon *hw, uint adj)
{
struct bwmon *m = to_bwmon(hw);
@@ -331,12 +414,12 @@
#define THRES_HIT(status) (status & BIT(0))
#define OVERFLOW(status) (status & BIT(1))
-static unsigned long mon_get_count(struct bwmon *m)
+static unsigned long mon_get_count1(struct bwmon *m)
{
unsigned long count, status;
count = readl_relaxed(MON_CNT(m));
- status = mon_irq_status(m);
+ status = mon_irq_status(m, BWMON_1);
dev_dbg(m->dev, "Counter: %08lx\n", count);
@@ -385,6 +468,23 @@
return count;
}
+static __always_inline
+unsigned long mon_get_count(struct bwmon *m, enum bwmon_type type)
+{
+ unsigned long count;
+
+ switch (type) {
+ case BWMON_1:
+ count = mon_get_count1(m);
+ break;
+ case BWMON_2:
+ count = mon_get_zone_stats(m);
+ break;
+ }
+
+ return count;
+}
+
/* ********** CPUBW specific code ********** */
/* Returns MBps of read/writes for the sampling window. */
@@ -398,30 +498,41 @@
return mbps;
}
-static unsigned long get_bytes_and_clear(struct bw_hwmon *hw)
+static __always_inline
+unsigned long __get_bytes_and_clear(struct bw_hwmon *hw, enum bwmon_type type)
{
struct bwmon *m = to_bwmon(hw);
unsigned long count;
- mon_disable(m);
- count = has_hw_sampling(m) ? mon_get_zone_stats(m) : mon_get_count(m);
- mon_clear(m, false);
- mon_irq_clear(m);
- mon_enable(m);
+ mon_disable(m, type);
+ count = mon_get_count(m, type);
+ mon_clear(m, false, type);
+ mon_irq_clear(m, type);
+ mon_enable(m, type);
return count;
}
+static unsigned long get_bytes_and_clear(struct bw_hwmon *hw)
+{
+ return __get_bytes_and_clear(hw, BWMON_1);
+}
+
+static unsigned long get_bytes_and_clear2(struct bw_hwmon *hw)
+{
+ return __get_bytes_and_clear(hw, BWMON_2);
+}
+
static unsigned long set_thres(struct bw_hwmon *hw, unsigned long bytes)
{
unsigned long count;
u32 limit;
struct bwmon *m = to_bwmon(hw);
- mon_disable(m);
- count = mon_get_count(m);
- mon_clear(m, false);
- mon_irq_clear(m);
+ mon_disable(m, BWMON_1);
+ count = mon_get_count1(m);
+ mon_clear(m, false, BWMON_1);
+ mon_irq_clear(m, BWMON_1);
if (likely(!m->spec->wrap_on_thres))
limit = bytes;
@@ -429,7 +540,7 @@
limit = max(bytes, 500000UL);
mon_set_limit(m, limit);
- mon_enable(m);
+ mon_enable(m, BWMON_1);
return count;
}
@@ -438,21 +549,22 @@
{
struct bwmon *m = to_bwmon(hw);
- mon_disable(m);
- mon_clear(m, false);
- mon_irq_clear(m);
+ mon_disable(m, BWMON_2);
+ mon_clear(m, false, BWMON_2);
+ mon_irq_clear(m, BWMON_2);
mon_set_zones(m, sample_ms);
- mon_enable(m);
+ mon_enable(m, BWMON_2);
return 0;
}
-static irqreturn_t bwmon_intr_handler(int irq, void *dev)
+static irqreturn_t
+__bwmon_intr_handler(int irq, void *dev, enum bwmon_type type)
{
struct bwmon *m = dev;
- m->intr_status = mon_irq_status(m);
+ m->intr_status = mon_irq_status(m, type);
if (!m->intr_status)
return IRQ_NONE;
@@ -462,6 +574,16 @@
return IRQ_HANDLED;
}
+static irqreturn_t bwmon_intr_handler(int irq, void *dev)
+{
+ return __bwmon_intr_handler(irq, dev, BWMON_1);
+}
+
+static irqreturn_t bwmon_intr_handler2(int irq, void *dev)
+{
+ return __bwmon_intr_handler(irq, dev, BWMON_2);
+}
+
static irqreturn_t bwmon_intr_thread(int irq, void *dev)
{
struct bwmon *m = dev;
@@ -470,85 +592,151 @@
return IRQ_HANDLED;
}
-static int start_bw_hwmon(struct bw_hwmon *hw, unsigned long mbps)
+static __always_inline int
+__start_bw_hwmon(struct bw_hwmon *hw, unsigned long mbps, enum bwmon_type type)
{
struct bwmon *m = to_bwmon(hw);
- u32 limit;
- u32 zone_actions = calc_zone_actions();
+ u32 limit, zone_actions;
int ret;
+ irq_handler_t handler;
- ret = request_threaded_irq(m->irq, bwmon_intr_handler,
- bwmon_intr_thread,
+ switch (type) {
+ case BWMON_1:
+ handler = bwmon_intr_handler;
+ limit = mbps_to_bytes(mbps, hw->df->profile->polling_ms, 0);
+ break;
+ case BWMON_2:
+ zone_actions = calc_zone_actions();
+ handler = bwmon_intr_handler2;
+ break;
+ }
+
+ ret = request_threaded_irq(m->irq, handler, bwmon_intr_thread,
IRQF_ONESHOT | IRQF_SHARED,
dev_name(m->dev), m);
if (ret) {
dev_err(m->dev, "Unable to register interrupt handler! (%d)\n",
- ret);
+ ret);
return ret;
}
- mon_disable(m);
+ mon_disable(m, type);
- mon_clear(m, true);
- limit = mbps_to_bytes(mbps, hw->df->profile->polling_ms, 0);
- if (has_hw_sampling(m)) {
+ mon_clear(m, false, type);
+
+ switch (type) {
+ case BWMON_1:
+ handler = bwmon_intr_handler;
+ mon_set_limit(m, limit);
+ break;
+ case BWMON_2:
mon_set_zones(m, hw->df->profile->polling_ms);
/* Set the zone actions to increment appropriate counters */
writel_relaxed(zone_actions, MON2_ZONE_ACTIONS(m));
- } else {
- mon_set_limit(m, limit);
+ break;
}
- mon_irq_clear(m);
- mon_irq_enable(m);
- mon_enable(m);
+ mon_irq_clear(m, type);
+ mon_irq_enable(m, type);
+ mon_enable(m, type);
return 0;
}
-static void stop_bw_hwmon(struct bw_hwmon *hw)
+static int start_bw_hwmon(struct bw_hwmon *hw, unsigned long mbps)
+{
+ return __start_bw_hwmon(hw, mbps, BWMON_1);
+}
+
+static int start_bw_hwmon2(struct bw_hwmon *hw, unsigned long mbps)
+{
+ return __start_bw_hwmon(hw, mbps, BWMON_2);
+}
+
+static __always_inline
+void __stop_bw_hwmon(struct bw_hwmon *hw, enum bwmon_type type)
{
struct bwmon *m = to_bwmon(hw);
- mon_irq_disable(m);
+ mon_irq_disable(m, type);
free_irq(m->irq, m);
- mon_disable(m);
- mon_clear(m, true);
- mon_irq_clear(m);
+ mon_disable(m, type);
+ mon_clear(m, true, type);
+ mon_irq_clear(m, type);
+}
+
+static void stop_bw_hwmon(struct bw_hwmon *hw)
+{
+ return __stop_bw_hwmon(hw, BWMON_1);
+}
+
+static void stop_bw_hwmon2(struct bw_hwmon *hw)
+{
+ return __stop_bw_hwmon(hw, BWMON_2);
+}
+
+static __always_inline
+int __suspend_bw_hwmon(struct bw_hwmon *hw, enum bwmon_type type)
+{
+ struct bwmon *m = to_bwmon(hw);
+
+ mon_irq_disable(m, type);
+ free_irq(m->irq, m);
+ mon_disable(m, type);
+ mon_irq_clear(m, type);
+
+ return 0;
}
static int suspend_bw_hwmon(struct bw_hwmon *hw)
{
- struct bwmon *m = to_bwmon(hw);
+ return __suspend_bw_hwmon(hw, BWMON_1);
+}
- mon_irq_disable(m);
- free_irq(m->irq, m);
- mon_disable(m);
- mon_irq_clear(m);
+static int suspend_bw_hwmon2(struct bw_hwmon *hw)
+{
+ return __suspend_bw_hwmon(hw, BWMON_2);
+}
+
+static int __resume_bw_hwmon(struct bw_hwmon *hw, enum bwmon_type type)
+{
+ struct bwmon *m = to_bwmon(hw);
+ int ret;
+ irq_handler_t handler;
+
+ switch (type) {
+ case BWMON_1:
+ handler = bwmon_intr_handler;
+ break;
+ case BWMON_2:
+ handler = bwmon_intr_handler2;
+ break;
+ }
+
+ mon_clear(m, false, type);
+ ret = request_threaded_irq(m->irq, handler, bwmon_intr_thread,
+ IRQF_ONESHOT | IRQF_SHARED,
+ dev_name(m->dev), m);
+ if (ret) {
+ dev_err(m->dev, "Unable to register interrupt handler! (%d)\n",
+ ret);
+ return ret;
+ }
+
+ mon_irq_enable(m, type);
+ mon_enable(m, type);
return 0;
}
static int resume_bw_hwmon(struct bw_hwmon *hw)
{
- struct bwmon *m = to_bwmon(hw);
- int ret;
+ return __resume_bw_hwmon(hw, BWMON_1);
+}
- mon_clear(m, false);
- ret = request_threaded_irq(m->irq, bwmon_intr_handler,
- bwmon_intr_thread,
- IRQF_ONESHOT | IRQF_SHARED,
- dev_name(m->dev), m);
- if (ret) {
- dev_err(m->dev, "Unable to register interrupt handler! (%d)\n",
- ret);
- return ret;
- }
-
- mon_irq_enable(m);
- mon_enable(m);
-
- return 0;
+static int resume_bw_hwmon2(struct bw_hwmon *hw)
+{
+ return __resume_bw_hwmon(hw, BWMON_2);
}
/*************************************************************************/
@@ -614,16 +802,6 @@
return -ENODEV;
}
- if (has_hw_sampling(m)) {
- ret = of_property_read_u32(dev->of_node, "qcom,hw-timer-hz",
- &data);
- if (ret) {
- dev_err(dev, "HW sampling rate not specified!\n");
- return ret;
- }
- m->hw_timer_hz = data;
- }
-
res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "base");
if (!res) {
dev_err(dev, "base not found!\n");
@@ -656,15 +834,28 @@
if (!m->hw.of_node)
return -EINVAL;
- m->hw.start_hwmon = start_bw_hwmon;
- m->hw.stop_hwmon = stop_bw_hwmon;
- m->hw.suspend_hwmon = suspend_bw_hwmon;
- m->hw.resume_hwmon = resume_bw_hwmon;
- m->hw.get_bytes_and_clear = get_bytes_and_clear;
- m->hw.set_thres = set_thres;
+ if (m->spec->hw_sampling) {
+ ret = of_property_read_u32(dev->of_node, "qcom,hw-timer-hz",
+ &m->hw_timer_hz);
+ if (ret) {
+ dev_err(dev, "HW sampling rate not specified!\n");
+ return ret;
+ }
- if (has_hw_sampling(m))
+ m->hw.start_hwmon = start_bw_hwmon2;
+ m->hw.stop_hwmon = stop_bw_hwmon2;
+ m->hw.suspend_hwmon = suspend_bw_hwmon2;
+ m->hw.resume_hwmon = resume_bw_hwmon2;
+ m->hw.get_bytes_and_clear = get_bytes_and_clear2;
m->hw.set_hw_events = set_hw_events;
+ } else {
+ m->hw.start_hwmon = start_bw_hwmon;
+ m->hw.stop_hwmon = stop_bw_hwmon;
+ m->hw.suspend_hwmon = suspend_bw_hwmon;
+ m->hw.resume_hwmon = resume_bw_hwmon;
+ m->hw.get_bytes_and_clear = get_bytes_and_clear;
+ m->hw.set_thres = set_thres;
+ }
if (m->spec->throt_adj) {
m->hw.set_throttle_adj = mon_set_throttle_adj;
diff --git a/drivers/gpu/drm/msm/sde_power_handle.c b/drivers/gpu/drm/msm/sde_power_handle.c
index 9a68dbe..3618479 100644
--- a/drivers/gpu/drm/msm/sde_power_handle.c
+++ b/drivers/gpu/drm/msm/sde_power_handle.c
@@ -44,6 +44,7 @@
static int sde_power_rsc_update(struct sde_power_handle *phandle, bool enable)
{
u32 rsc_state;
+ int ret = 0;
/* creates the rsc client on the first enable */
if (!phandle->rsc_client_init) {
@@ -59,8 +60,11 @@
rsc_state = enable ? SDE_RSC_CLK_STATE : SDE_RSC_IDLE_STATE;
- return sde_rsc_client_state_update(phandle->rsc_client,
+ if (phandle->rsc_client)
+ ret = sde_rsc_client_state_update(phandle->rsc_client,
rsc_state, NULL, -1);
+
+ return ret;
}
struct sde_power_client *sde_power_client_create(
diff --git a/drivers/gpu/drm/msm/sde_rsc.c b/drivers/gpu/drm/msm/sde_rsc.c
index c1b812a..d762904 100644
--- a/drivers/gpu/drm/msm/sde_rsc.c
+++ b/drivers/gpu/drm/msm/sde_rsc.c
@@ -388,7 +388,7 @@
static int sde_rsc_switch_to_cmd(struct sde_rsc_priv *rsc,
struct sde_rsc_cmd_config *config,
- struct sde_rsc_client *caller_client, bool wait_req)
+ struct sde_rsc_client *caller_client)
{
struct sde_rsc_client *client;
int rc = STATE_UPDATE_NOT_ALLOWED;
@@ -416,8 +416,8 @@
if (rsc->hw_ops.state_update)
rc = rsc->hw_ops.state_update(rsc, SDE_RSC_CMD_STATE);
- /* wait for vsync */
- if (!rc && wait_req)
+ /* wait for vsync for vid to cmd state switch */
+ if (!rc && (rsc->current_state == SDE_RSC_VID_STATE))
drm_wait_one_vblank(rsc->master_drm,
rsc->primary_client->crtc_id);
end:
@@ -436,13 +436,19 @@
if (rsc->hw_ops.state_update)
rc = rsc->hw_ops.state_update(rsc, SDE_RSC_CLK_STATE);
+
+ /* wait for vsync for cmd to clk state switch */
+ if (!rc && rsc->primary_client &&
+ (rsc->current_state == SDE_RSC_CMD_STATE))
+ drm_wait_one_vblank(rsc->master_drm,
+ rsc->primary_client->crtc_id);
end:
return rc;
}
static bool sde_rsc_switch_to_vid(struct sde_rsc_priv *rsc,
struct sde_rsc_cmd_config *config,
- struct sde_rsc_client *caller_client, bool wait_req)
+ struct sde_rsc_client *caller_client)
{
int rc = 0;
@@ -454,8 +460,9 @@
if (rsc->hw_ops.state_update)
rc = rsc->hw_ops.state_update(rsc, SDE_RSC_VID_STATE);
- /* wait for vsync */
- if (!rc && rsc->primary_client && wait_req)
+ /* wait for vsync for cmd to vid state switch */
+ if (!rc && rsc->primary_client &&
+ (rsc->current_state == SDE_RSC_CMD_STATE))
drm_wait_one_vblank(rsc->master_drm,
rsc->primary_client->crtc_id);
return rc;
@@ -481,7 +488,6 @@
{
int rc = 0;
struct sde_rsc_priv *rsc;
- bool wait_requested = false;
if (!caller_client) {
pr_err("invalid client for rsc state update\n");
@@ -512,11 +518,7 @@
__builtin_return_address(0), rsc->current_state,
caller_client->name, state);
- /* only switch state needs vsync wait */
- wait_requested = (rsc->current_state == SDE_RSC_VID_STATE) ||
- (rsc->current_state == SDE_RSC_CMD_STATE);
-
- if (rsc->power_collapse)
+ if (rsc->current_state == SDE_RSC_IDLE_STATE)
sde_rsc_clk_enable(&rsc->phandle, rsc->pclient, true);
switch (state) {
@@ -526,7 +528,7 @@
/* video state client might be exiting; try cmd state switch */
if (rc == TRY_CMD_MODE_SWITCH) {
rc = sde_rsc_switch_to_cmd(rsc, NULL,
- rsc->primary_client, wait_requested);
+ rsc->primary_client);
if (!rc)
state = SDE_RSC_CMD_STATE;
@@ -539,13 +541,11 @@
break;
case SDE_RSC_CMD_STATE:
- rc = sde_rsc_switch_to_cmd(rsc, config, caller_client,
- wait_requested);
+ rc = sde_rsc_switch_to_cmd(rsc, config, caller_client);
break;
case SDE_RSC_VID_STATE:
- rc = sde_rsc_switch_to_vid(rsc, config, caller_client,
- wait_requested);
+ rc = sde_rsc_switch_to_vid(rsc, config, caller_client);
break;
case SDE_RSC_CLK_STATE:
@@ -561,7 +561,7 @@
rc = 0;
goto clk_disable;
} else if (rc) {
- pr_err("state update failed rc:%d\n", rc);
+ pr_debug("state:%d update failed rc:%d\n", state, rc);
goto clk_disable;
}
@@ -569,7 +569,7 @@
rsc->current_state = state;
clk_disable:
- if (rsc->power_collapse)
+ if (rsc->current_state == SDE_RSC_IDLE_STATE)
sde_rsc_clk_enable(&rsc->phandle, rsc->pclient, false);
end:
mutex_unlock(&rsc->client_lock);
@@ -615,14 +615,9 @@
caller_client->name, ab_vote, ib_vote);
mutex_lock(&rsc->client_lock);
- if ((caller_client->current_state == SDE_RSC_IDLE_STATE) ||
- (rsc->current_state == SDE_RSC_IDLE_STATE)) {
-
- pr_err("invalid state: client state:%d rsc state:%d\n",
- caller_client->current_state, rsc->current_state);
- rc = -EINVAL;
- goto end;
- }
+ rc = sde_rsc_clk_enable(&rsc->phandle, rsc->pclient, true);
+ if (rc)
+ goto clk_enable_fail;
if (rsc->hw_ops.is_amc_mode)
amc_mode = rsc->hw_ops.is_amc_mode(rsc);
@@ -644,14 +639,19 @@
}
}
+ rpmh_invalidate(rsc->disp_rsc);
sde_power_data_bus_set_quota(&rsc->phandle, rsc->pclient,
SDE_POWER_HANDLE_DATA_BUS_CLIENT_RT, ab_vote, ib_vote);
+ rpmh_flush(rsc->disp_rsc);
if (rsc->hw_ops.tcs_use_ok)
rsc->hw_ops.tcs_use_ok(rsc);
end:
+ sde_rsc_clk_enable(&rsc->phandle, rsc->pclient, false);
+clk_enable_fail:
mutex_unlock(&rsc->client_lock);
+
return rc;
}
EXPORT_SYMBOL(sde_rsc_client_vote);
@@ -668,6 +668,10 @@
rsc = s->private;
mutex_lock(&rsc->client_lock);
+ ret = sde_rsc_clk_enable(&rsc->phandle, rsc->pclient, true);
+ if (ret)
+ goto end;
+
seq_printf(s, "rsc current state:%d\n", rsc->current_state);
seq_printf(s, "wraper backoff time(ns):%d\n",
rsc->timer_config.static_wakeup_time_ns);
@@ -691,17 +695,15 @@
seq_printf(s, "\t client:%s state:%d\n",
client->name, client->current_state);
- sde_rsc_clk_enable(&rsc->phandle, rsc->pclient, true);
-
if (rsc->hw_ops.debug_show) {
ret = rsc->hw_ops.debug_show(s, rsc);
if (ret)
pr_err("sde rsc: hw debug failed ret:%d\n", ret);
}
-
sde_rsc_clk_enable(&rsc->phandle, rsc->pclient, false);
- mutex_unlock(&rsc->client_lock);
+end:
+ mutex_unlock(&rsc->client_lock);
return 0;
}
@@ -722,20 +724,23 @@
{
struct sde_rsc_priv *rsc = file->private_data;
char buffer[MAX_BUFFER_SIZE];
- int blen = 0;
+ int blen = 0, rc;
if (*ppos || !rsc || !rsc->hw_ops.mode_ctrl)
return 0;
mutex_lock(&rsc->client_lock);
- sde_rsc_clk_enable(&rsc->phandle, rsc->pclient, true);
+ rc = sde_rsc_clk_enable(&rsc->phandle, rsc->pclient, true);
+ if (rc)
+ goto end;
blen = rsc->hw_ops.mode_ctrl(rsc, MODE_READ, buffer,
MAX_BUFFER_SIZE, 0);
sde_rsc_clk_enable(&rsc->phandle, rsc->pclient, false);
- mutex_unlock(&rsc->client_lock);
+end:
+ mutex_unlock(&rsc->client_lock);
if (blen < 0)
return 0;
@@ -752,6 +757,7 @@
struct sde_rsc_priv *rsc = file->private_data;
char *input, *mode;
u32 mode0_state = 0, mode1_state = 0, mode2_state = 0;
+ int rc;
if (!rsc || !rsc->hw_ops.mode_ctrl)
return 0;
@@ -767,7 +773,9 @@
input[count - 1] = '\0';
mutex_lock(&rsc->client_lock);
- sde_rsc_clk_enable(&rsc->phandle, rsc->pclient, true);
+ rc = sde_rsc_clk_enable(&rsc->phandle, rsc->pclient, true);
+ if (rc)
+ goto clk_enable_fail;
mode = strnstr(input, "mode0=", strlen("mode0="));
if (mode) {
@@ -794,9 +802,10 @@
end:
sde_rsc_clk_enable(&rsc->phandle, rsc->pclient, false);
+clk_enable_fail:
mutex_unlock(&rsc->client_lock);
- pr_err("req: mode0:%d mode1:%d mode2:%d\n", mode0_state, mode1_state,
+ pr_info("req: mode0:%d mode1:%d mode2:%d\n", mode0_state, mode1_state,
mode2_state);
kfree(input);
return count;
@@ -814,20 +823,23 @@
{
struct sde_rsc_priv *rsc = file->private_data;
char buffer[MAX_BUFFER_SIZE];
- int blen = 0;
+ int blen = 0, rc;
if (*ppos || !rsc || !rsc->hw_ops.hw_vsync)
return 0;
mutex_lock(&rsc->client_lock);
- sde_rsc_clk_enable(&rsc->phandle, rsc->pclient, true);
+ rc = sde_rsc_clk_enable(&rsc->phandle, rsc->pclient, true);
+ if (rc)
+ goto end;
blen = rsc->hw_ops.hw_vsync(rsc, VSYNC_READ, buffer,
MAX_BUFFER_SIZE, 0);
sde_rsc_clk_enable(&rsc->phandle, rsc->pclient, false);
- mutex_unlock(&rsc->client_lock);
+end:
+ mutex_unlock(&rsc->client_lock);
if (blen < 0)
return 0;
@@ -844,6 +856,7 @@
struct sde_rsc_priv *rsc = file->private_data;
char *input, *vsync_mode;
u32 vsync_state = 0;
+ int rc;
if (!rsc || !rsc->hw_ops.hw_vsync)
return 0;
@@ -865,7 +878,9 @@
}
mutex_lock(&rsc->client_lock);
- sde_rsc_clk_enable(&rsc->phandle, rsc->pclient, true);
+ rc = sde_rsc_clk_enable(&rsc->phandle, rsc->pclient, true);
+ if (rc)
+ goto end;
if (vsync_state)
rsc->hw_ops.hw_vsync(rsc, VSYNC_ENABLE, NULL,
@@ -874,8 +889,9 @@
rsc->hw_ops.hw_vsync(rsc, VSYNC_DISABLE, NULL, 0, 0);
sde_rsc_clk_enable(&rsc->phandle, rsc->pclient, false);
- mutex_unlock(&rsc->client_lock);
+end:
+ mutex_unlock(&rsc->client_lock);
kfree(input);
return count;
}
@@ -930,6 +946,8 @@
msm_dss_iounmap(&rsc->wrapper_io);
if (rsc->drv_io.base)
msm_dss_iounmap(&rsc->drv_io);
+ if (rsc->disp_rsc)
+ rpmh_release(rsc->disp_rsc);
if (rsc->pclient)
sde_power_client_destroy(&rsc->phandle, rsc->pclient);
@@ -1038,6 +1056,17 @@
goto sde_rsc_fail;
}
+ rsc->disp_rsc = rpmh_get_byname(pdev, "disp_rsc");
+ if (IS_ERR_OR_NULL(rsc->disp_rsc)) {
+ ret = PTR_ERR(rsc->disp_rsc);
+ rsc->disp_rsc = NULL;
+ pr_err("sde rsc:get display rsc failed ret:%d\n", ret);
+ goto sde_rsc_fail;
+ }
+ rpmh_invalidate(rsc->disp_rsc);
+ /* call flush to disable the disp rsc interrupt */
+ rpmh_flush(rsc->disp_rsc);
+
ret = msm_dss_ioremap_byname(pdev, &rsc->wrapper_io, "wrapper");
if (ret) {
pr_err("sde rsc: wrapper io data mapping failed ret=%d\n", ret);
@@ -1084,7 +1113,6 @@
snprintf(name, MAX_RSC_CLIENT_NAME_LEN, "%s%d", "sde_rsc", counter);
_sde_rsc_init_debugfs(rsc, name);
counter++;
- rsc->power_collapse = true;
ret = component_add(&pdev->dev, &sde_rsc_comp_ops);
if (ret)
diff --git a/drivers/gpu/drm/msm/sde_rsc_hw.c b/drivers/gpu/drm/msm/sde_rsc_hw.c
index de579c1..b63fbc6 100644
--- a/drivers/gpu/drm/msm/sde_rsc_hw.c
+++ b/drivers/gpu/drm/msm/sde_rsc_hw.c
@@ -36,6 +36,7 @@
#define SDE_RSCC_AMC_TCS_MODE_IRQ_STATUS_DRV0 0x1c00
#define SDE_RSCC_SOFT_WAKEUP_TIME_LO_DRV0 0xc04
+#define SDE_RSCC_SOFT_WAKEUP_TIME_HI_DRV0 0xc08
#define SDE_RSCC_MAX_IDLE_DURATION_DRV0 0xc0c
#define SDE_RSC_SOLVER_TIME_SLOT_TABLE_0_DRV0 0x1000
#define SDE_RSC_SOLVER_TIME_SLOT_TABLE_1_DRV0 0x1004
@@ -224,7 +225,9 @@
pr_debug("rsc solver init\n");
dss_reg_w(&rsc->drv_io, SDE_RSCC_SOFT_WAKEUP_TIME_LO_DRV0,
- 0x7FFFFFFF, rsc->debug_mode);
+ 0xFFFFFFFF, rsc->debug_mode);
+ dss_reg_w(&rsc->drv_io, SDE_RSCC_SOFT_WAKEUP_TIME_HI_DRV0,
+ 0xFFFFFFFF, rsc->debug_mode);
dss_reg_w(&rsc->drv_io, SDE_RSCC_MAX_IDLE_DURATION_DRV0,
0xEFFFFFFF, rsc->debug_mode);
@@ -308,6 +311,15 @@
rsc_event_trigger(rsc, SDE_RSC_EVENT_PRE_CORE_PC);
+ /* update qtimers to high during clk & video mode state */
+ if ((rsc->current_state == SDE_RSC_VID_STATE) ||
+ (rsc->current_state == SDE_RSC_CLK_STATE)) {
+ dss_reg_w(&rsc->wrapper_io, SDE_RSCC_F0_QTMR_V1_CNTP_CVAL_HI,
+ 0xffffffff, rsc->debug_mode);
+ dss_reg_w(&rsc->wrapper_io, SDE_RSCC_F0_QTMR_V1_CNTP_CVAL_LO,
+ 0xffffffff, rsc->debug_mode);
+ }
+
wrapper_status = dss_reg_r(&rsc->wrapper_io, SDE_RSCC_WRAPPER_CTRL,
rsc->debug_mode);
wrapper_status |= BIT(3);
@@ -357,8 +369,6 @@
return 0;
end:
- regulator_set_mode(rsc->fs, REGULATOR_MODE_NORMAL);
-
rsc_event_trigger(rsc, SDE_RSC_EVENT_POST_CORE_RESTORE);
return rc;
@@ -378,8 +388,7 @@
if ((state == SDE_RSC_VID_STATE) || (state == SDE_RSC_CLK_STATE)) {
reg = dss_reg_r(&rsc->wrapper_io,
SDE_RSCC_WRAPPER_OVERRIDE_CTRL, rsc->debug_mode);
- reg |= BIT(8);
- reg &= ~(BIT(1) | BIT(0));
+ reg &= ~(BIT(8) | BIT(0));
dss_reg_w(&rsc->wrapper_io, SDE_RSCC_WRAPPER_OVERRIDE_CTRL,
reg, rsc->debug_mode);
}
@@ -411,7 +420,7 @@
rc = 0;
break;
}
- usleep_range(1, 2);
+ usleep_range(10, 100);
}
reg = dss_reg_r(&rsc->wrapper_io, SDE_RSCC_SPARE_PWR_EVENT,
@@ -419,14 +428,9 @@
reg &= ~BIT(13);
dss_reg_w(&rsc->wrapper_io, SDE_RSCC_SPARE_PWR_EVENT,
reg, rsc->debug_mode);
-
if (rc)
pr_err("vdd reg is not enabled yet\n");
- rc = regulator_set_mode(rsc->fs, REGULATOR_MODE_NORMAL);
- if (rc)
- pr_err("vdd reg normal mode set failed rc:%d\n", rc);
-
rsc_event_trigger(rsc, SDE_RSC_EVENT_POST_CORE_RESTORE);
return rc;
@@ -454,6 +458,9 @@
0x1, rsc->debug_mode);
dss_reg_w(&rsc->drv_io, SDE_RSCC_SOLVER_OVERRIDE_CTRL_DRV0,
0x0, rsc->debug_mode);
+ dss_reg_w(&rsc->drv_io,
+ SDE_RSC_SOLVER_SOLVER_MODES_ENABLED_DRV0, 0x7,
+ rsc->debug_mode);
reg = dss_reg_r(&rsc->wrapper_io,
SDE_RSCC_WRAPPER_OVERRIDE_CTRL, rsc->debug_mode);
reg |= (BIT(0) | BIT(8));
@@ -477,8 +484,9 @@
reg &= ~(BIT(1) | BIT(0));
dss_reg_w(&rsc->wrapper_io, SDE_RSCC_WRAPPER_OVERRIDE_CTRL,
reg, rsc->debug_mode);
- dss_reg_w(&rsc->drv_io, SDE_RSCC_SOLVER_OVERRIDE_CTRL_DRV0,
- 0x1, rsc->debug_mode);
+ dss_reg_w(&rsc->drv_io,
+ SDE_RSC_SOLVER_SOLVER_MODES_ENABLED_DRV0, 0x5,
+ rsc->debug_mode);
/* make sure that solver mode is override */
wmb();
@@ -487,6 +495,17 @@
case SDE_RSC_CLK_STATE:
pr_debug("clk state handling\n");
+
+ reg = dss_reg_r(&rsc->wrapper_io,
+ SDE_RSCC_WRAPPER_OVERRIDE_CTRL, rsc->debug_mode);
+ reg &= ~(BIT(8) | BIT(0));
+ dss_reg_w(&rsc->wrapper_io, SDE_RSCC_WRAPPER_OVERRIDE_CTRL,
+ reg, rsc->debug_mode);
+ dss_reg_w(&rsc->drv_io,
+ SDE_RSC_SOLVER_SOLVER_MODES_ENABLED_DRV0, 0x5,
+ rsc->debug_mode);
+ /* make sure that solver mode is disabled */
+ wmb();
break;
case SDE_RSC_IDLE_STATE:
diff --git a/drivers/gpu/drm/msm/sde_rsc_priv.h b/drivers/gpu/drm/msm/sde_rsc_priv.h
index 30810fe..b83a866 100644
--- a/drivers/gpu/drm/msm/sde_rsc_priv.h
+++ b/drivers/gpu/drm/msm/sde_rsc_priv.h
@@ -111,6 +111,7 @@
* @pclient: module power client of phandle
* @fs: "MDSS GDSC" handle
*
+ * @disp_rsc: display rsc handle
* @drv_io: sde drv io data mapping
* @wrapper_io: wrapper io data mapping
*
@@ -141,6 +142,7 @@
struct sde_power_client *pclient;
struct regulator *fs;
+ struct rpmh_client *disp_rsc;
struct dss_io_data drv_io;
struct dss_io_data wrapper_io;
diff --git a/drivers/gpu/msm/a6xx_reg.h b/drivers/gpu/msm/a6xx_reg.h
index 28d93a9..69b639a 100644
--- a/drivers/gpu/msm/a6xx_reg.h
+++ b/drivers/gpu/msm/a6xx_reg.h
@@ -678,6 +678,7 @@
#define A6XX_GMU_DCVS_RETURN 0x1CBFF
#define A6XX_GMU_CM3_SYSRESET 0x1F800
#define A6XX_GMU_CM3_BOOT_CONFIG 0x1F801
+#define A6XX_GMU_CM3_FW_BUSY 0x1F81A
#define A6XX_GMU_CM3_FW_INIT_RESULT 0x1F81C
#define A6XX_GMU_PWR_COL_INTER_FRAME_CTRL 0x1F8C0
#define A6XX_GMU_PWR_COL_INTER_FRAME_HYST 0x1F8C1
diff --git a/drivers/gpu/msm/adreno_a6xx.c b/drivers/gpu/msm/adreno_a6xx.c
index c721065..3c3f99f 100644
--- a/drivers/gpu/msm/adreno_a6xx.c
+++ b/drivers/gpu/msm/adreno_a6xx.c
@@ -1303,16 +1303,11 @@
struct kgsl_device *device = KGSL_DEVICE(adreno_dev);
struct gmu_device *gmu = &device->gmu;
- if (timed_poll_check(device, A6XX_GMU_RPMH_POWER_STATE,
- gmu->idle_level, GMU_START_TIMEOUT, 0xf)) {
- dev_err(&gmu->pdev->dev,
- "GMU is not going to powerstate %d\n",
- gmu->idle_level);
- return -ETIMEDOUT;
- }
+ /* TODO: Remove this register write when firmware is updated */
+ kgsl_gmu_regwrite(device, A6XX_GMU_CM3_FW_BUSY, 0);
if (timed_poll_check(device, A6XX_GPU_GMU_AO_GPU_CX_BUSY_STATUS,
- 0, GMU_START_TIMEOUT, CXGXCPUBUSYIGNAHB)) {
+ 0, GMU_START_TIMEOUT, CXGXCPUBUSYIGNAHB)) {
dev_err(&gmu->pdev->dev, "GMU is not idling\n");
return -ETIMEDOUT;
}
diff --git a/drivers/gpu/msm/kgsl_gmu.c b/drivers/gpu/msm/kgsl_gmu.c
index 416085f..0c821cd 100644
--- a/drivers/gpu/msm/kgsl_gmu.c
+++ b/drivers/gpu/msm/kgsl_gmu.c
@@ -1369,24 +1369,39 @@
return ret;
}
+#define GMU_IDLE_TIMEOUT 10 /* ms */
+
/* Caller shall ensure GPU is ready for SLUMBER */
void gmu_stop(struct kgsl_device *device)
{
struct gmu_device *gmu = &device->gmu;
struct adreno_device *adreno_dev = ADRENO_DEVICE(device);
struct adreno_gpudev *gpudev = ADRENO_GPU_DEVICE(adreno_dev);
+ unsigned long t;
+ bool idle = false;
if (!test_bit(GMU_CLK_ON, &gmu->flags))
return;
- if (gpudev->wait_for_gmu_idle &&
- !gpudev->wait_for_gmu_idle(adreno_dev)) {
- dev_err(&gmu->pdev->dev, "Failure to stop gmu");
- return;
+ if (gpudev->hw_isidle) {
+ t = jiffies + msecs_to_jiffies(GMU_IDLE_TIMEOUT);
+ while (!time_after(jiffies, t)) {
+ if (gpudev->hw_isidle(adreno_dev)) {
+ idle = true;
+ break;
+ }
+ cpu_relax();
+ }
}
gpudev->rpmh_gpu_pwrctrl(adreno_dev, GMU_NOTIFY_SLUMBER, 0, 0);
+ if (!idle || (gpudev->wait_for_gmu_idle &&
+ gpudev->wait_for_gmu_idle(adreno_dev))) {
+ dev_err(&gmu->pdev->dev, "Failure to stop GMU");
+ return;
+ }
+
/* Pending message in all queues are abandoned */
hfi_stop(gmu);
clear_bit(GMU_HFI_ON, &gmu->flags);
diff --git a/drivers/gpu/msm/kgsl_gmu.h b/drivers/gpu/msm/kgsl_gmu.h
index a2ca67c..7055eb7 100644
--- a/drivers/gpu/msm/kgsl_gmu.h
+++ b/drivers/gpu/msm/kgsl_gmu.h
@@ -146,7 +146,7 @@
GPU_HW_NAP = 0x4,
GPU_HW_MIN_VOLT = 0x5,
GPU_HW_MIN_DDR = 0x6,
- GPU_HW_SLUMBER = 0xF
+ GPU_HW_SLUMBER = 0x7
};
/**
diff --git a/drivers/mailbox/qti-tcs.c b/drivers/mailbox/qti-tcs.c
index b150bad..dfed3cd 100644
--- a/drivers/mailbox/qti-tcs.c
+++ b/drivers/mailbox/qti-tcs.c
@@ -85,7 +85,6 @@
#define TCS_HIDDEN_CMD_SHIFT 0x08
#define TCS_TYPE_NR 4
-#define TCS_MBOX_TOUT_MS 2000
#define MAX_POOL_SIZE (MAX_TCS_PER_TYPE * TCS_TYPE_NR)
#define TCS_M_INIT 0xFFFF
@@ -97,7 +96,6 @@
struct tcs_mbox_msg *msg;
u32 m; /* m-th TCS */
struct tasklet_struct tasklet;
- struct delayed_work dwork;
int err;
int idx;
bool in_use;
@@ -141,7 +139,6 @@
};
static void tcs_notify_tx_done(unsigned long data);
-static void tcs_notify_timeout(struct work_struct *work);
static int tcs_response_pool_init(struct tcs_drv *drv)
{
@@ -155,7 +152,6 @@
for (i = 0; i < MAX_POOL_SIZE; i++) {
tasklet_init(&pool->resp[i].tasklet, tcs_notify_tx_done,
(unsigned long) &pool->resp[i]);
- INIT_DELAYED_WORK(&pool->resp[i].dwork, tcs_notify_timeout);
pool->resp[i].drv = drv;
pool->resp[i].idx = i;
pool->resp[i].m = TCS_M_INIT;
@@ -337,11 +333,6 @@
tasklet_schedule(&resp->tasklet);
}
-static inline void schedule_tcs_err_response(struct tcs_response *resp)
-{
- schedule_delayed_work(&resp->dwork, msecs_to_jiffies(TCS_MBOX_TOUT_MS));
-}
-
/**
* tcs_irq_handler: TX Done / Recv data handler
*/
@@ -371,8 +362,6 @@
continue;
}
- cancel_delayed_work(&resp->dwork);
-
tcs = get_tcs_from_index(drv, m);
if (!tcs) {
pr_err("TCS-%d doesn't exist in DRV\n", m);
@@ -448,80 +437,6 @@
free_response(resp);
}
-/**
- * tcs_notify_timeout: TX Done for requests that do trigger TCS, but
- * we do not get a response IRQ back.
- */
-static void tcs_notify_timeout(struct work_struct *work)
-{
- struct delayed_work *dwork = to_delayed_work(work);
- struct tcs_response *resp = container_of(dwork,
- struct tcs_response, dwork);
- struct mbox_chan *chan = resp->chan;
- struct tcs_mbox_msg *msg = resp->msg;
- struct tcs_drv *drv = resp->drv;
- int m = resp->m;
- u32 irq_status;
- struct tcs_mbox *tcs = get_tcs_from_index(drv, m);
- bool pending = false;
- int sent_count, irq_count;
- int i;
-
- /* Read while holding a lock, to get a consistent state snapshot */
- spin_lock(&tcs->tcs_lock);
- irq_status = read_tcs_reg(drv->reg_base, TCS_DRV_IRQ_STATUS, 0, 0);
- sent_count = atomic_read(&drv->tcs_send_count[m]);
- irq_count = atomic_read(&drv->tcs_irq_count[m]);
-
- if (!tcs_is_free(drv, m)) {
- struct tcs_cmd *cmd;
- u32 addr;
-
- for (i = 0; i < msg->num_payload; i++) {
- cmd = &msg->payload[i];
- addr = read_tcs_reg(drv->reg_base, TCS_DRV_CMD_ADDR,
- m, i);
- pending |= (cmd->addr == addr);
- }
- }
- spin_unlock(&tcs->tcs_lock);
-
- if (pending) {
- pr_err("TCS-%d waiting for response. (sent=%d recvd=%d ctrlr-sts=0x%x)\n",
- m, sent_count, irq_count, irq_status & (u32)BIT(m));
- for (i = 0; i < msg->num_payload; i++)
- pr_err("Addr: 0x%x Data: 0x%x\n",
- msg->payload[i].addr,
- msg->payload[i].data);
- /*
- * In case the RPMH resource fails to respond to the
- * completion request, the TCS would be blocked forever
- * waiting on the response. There is no way to recover
- * from such a case. But WARN() to investigate any false
- * positives.
- */
- WARN_ON(irq_status & BIT(m));
-
- /* Clear the TCS status register so we could try again */
- write_tcs_reg(drv->reg_base, TCS_DRV_IRQ_CLEAR, 0, 0, BIT(m));
-
- /* Increment the response count, so it doesn't keep adding up */
- atomic_inc(&drv->tcs_irq_count[m]);
-
- /*
- * If the request was fire-n-forget then the controller,
- * then our controller is OK, but the accelerator may be
- * in a bad state.
- * Let the upper layers figure out what needs to be done
- * in such a case. Return error code and carry on.
- */
- atomic_set(&drv->tcs_in_use[m], 0);
- }
-
- mbox_notify_tx_done(chan, msg, -1, -ETIMEDOUT);
- free_response(resp);
-}
-
static void __tcs_buffer_write(struct tcs_drv *drv, int d, int m, int n,
struct tcs_mbox_msg *msg, bool trigger)
{
@@ -595,60 +510,45 @@
return true;
}
-static void wait_for_req_inflight(struct tcs_drv *drv, struct tcs_mbox *tcs,
+static int check_for_req_inflight(struct tcs_drv *drv, struct tcs_mbox *tcs,
struct tcs_mbox_msg *msg)
{
- u32 curr_enabled;
+ u32 curr_enabled, addr;
int i, j, k;
- bool is_free;
+ void __iomem *base = drv->reg_base;
+ int m = tcs->tcs_offset;
- do {
- is_free = true;
- for (i = 1; i > tcs->tcs_mask; i = i << 1) {
- if (!(tcs->tcs_mask & i))
+ for (i = 0; i < tcs->num_tcs; i++, m++) {
+ if (tcs_is_free(drv, m))
+ continue;
+
+ curr_enabled = read_tcs_reg(base, TCS_DRV_CMD_ENABLE, m, 0);
+ for (j = 0; j < curr_enabled; j++) {
+ if (!(curr_enabled & BIT(j)))
continue;
- if (tcs_is_free(drv, i))
- continue;
- curr_enabled = read_tcs_reg(drv->reg_base,
- TCS_DRV_CMD_ENABLE, i, 0);
- for (j = 0; j < msg->num_payload; j++) {
- for (k = 0; k < curr_enabled; k++) {
- if (!(curr_enabled & BIT(k)))
- continue;
- if (tcs->cmd_addr[k] ==
- msg->payload[j].addr) {
- is_free = false;
- goto retry;
- }
- }
+ addr = read_tcs_reg(base, TCS_DRV_CMD_ADDR, m, j);
+ for (k = 0; k < msg->num_payload; k++) {
+ if (addr == msg->payload[k].addr)
+ return -EBUSY;
}
}
-retry:
- if (!is_free)
- udelay(1);
- } while (!is_free);
+ }
+
+ return 0;
}
static int find_free_tcs(struct tcs_mbox *tcs)
{
- int slot, m = 0;
- u32 irq_status;
+ int slot = -EBUSY;
+ int m = 0;
/* Loop until we find a free AMC */
- do {
+ for (m = 0; m < tcs->num_tcs; m++) {
if (tcs_is_free(tcs->drv, tcs->tcs_offset + m)) {
slot = m * tcs->ncpt;
break;
}
- if (++m >= tcs->num_tcs) {
- m = 0;
- irq_status = read_tcs_reg(tcs->drv->reg_base,
- TCS_DRV_IRQ_STATUS, 0, 0);
- WARN((irq_status & tcs->tcs_mask && in_irq()),
- "TCS busy. Request should not be made from hard IRQ context.");
- udelay(10);
- }
- } while (1);
+ }
return slot;
}
@@ -711,8 +611,9 @@
struct tcs_drv *drv = container_of(chan->mbox, struct tcs_drv, mbox);
int d = drv->drv_id;
struct tcs_mbox *tcs;
- int i, slot, offset, m, n;
+ int i, slot, offset, m, n, ret;
struct tcs_response *resp = NULL;
+ unsigned long flags;
tcs = get_tcs_for_msg(drv, msg);
if (IS_ERR(tcs))
@@ -722,16 +623,24 @@
resp = setup_response(drv, msg, chan, TCS_M_INIT, 0);
/* Identify the sequential slots that we can write to */
- spin_lock(&tcs->tcs_lock);
+ spin_lock_irqsave(&tcs->tcs_lock, flags);
slot = find_slots(tcs, msg);
if (slot < 0) {
dev_err(dev, "No TCS slot found.\n");
- spin_unlock(&tcs->tcs_lock);
+ spin_unlock_irqrestore(&tcs->tcs_lock, flags);
if (resp)
free_response(resp);
return slot;
}
+ if (trigger) {
+ ret = check_for_req_inflight(drv, tcs, msg);
+ if (ret) {
+ spin_unlock_irqrestore(&tcs->tcs_lock, flags);
+ return ret;
+ }
+ }
+
/* Mark the slots as in-use, before we unlock */
if (tcs->type == SLEEP_TCS || tcs->type == WAKE_TCS)
bitmap_set(tcs->slots, slot, msg->num_payload);
@@ -750,17 +659,12 @@
/* Mark the TCS as busy */
atomic_set(&drv->tcs_in_use[m], 1);
atomic_inc(&drv->tcs_send_count[m]);
- wait_for_req_inflight(drv, tcs, msg);
}
/* Write to the TCS or AMC */
__tcs_buffer_write(drv, d, m, n, msg, trigger);
- /* Schedule a timeout response, incase there is no actual response */
- if (trigger)
- schedule_tcs_err_response(resp);
-
- spin_unlock(&tcs->tcs_lock);
+ spin_unlock_irqrestore(&tcs->tcs_lock, flags);
return 0;
}
@@ -777,22 +681,21 @@
int m, i;
int inv_types[] = { WAKE_TCS, SLEEP_TCS };
int type = 0;
+ unsigned long flags;
do {
tcs = get_tcs_of_type(drv, inv_types[type]);
if (IS_ERR(tcs))
return PTR_ERR(tcs);
- spin_lock(&tcs->tcs_lock);
+ spin_lock_irqsave(&tcs->tcs_lock, flags);
for (i = 0; i < tcs->num_tcs; i++) {
m = i + tcs->tcs_offset;
- while (!tcs_is_free(drv, m))
- udelay(1);
__tcs_buffer_invalidate(drv->reg_base, m);
}
/* Mark the TCS as free */
bitmap_zero(tcs->slots, MAX_TCS_SLOTS);
- spin_unlock(&tcs->tcs_lock);
+ spin_unlock_irqrestore(&tcs->tcs_lock, flags);
} while (++type < ARRAY_SIZE(inv_types));
return 0;
@@ -814,6 +717,7 @@
struct tcs_mbox_msg *msg = data;
const struct device *dev = chan->cl->dev;
int ret = -EINVAL;
+ int count = 0;
if (!msg) {
dev_err(dev, "Payload error.\n");
@@ -850,7 +754,14 @@
tcs_mbox_invalidate(chan);
/* Post the message to the TCS and trigger */
- ret = tcs_mbox_write(chan, msg, true);
+ do {
+ ret = tcs_mbox_write(chan, msg, true);
+ if (ret == -EBUSY) {
+ ret = -EIO;
+ udelay(10);
+ } else
+ break;
+ } while (++count < 10);
tx_fail:
if (ret) {
@@ -885,6 +796,7 @@
const struct device *dev = chan->cl->dev;
struct tcs_drv *drv = container_of(chan->mbox, struct tcs_drv, mbox);
struct tcs_mbox *tcs;
+ unsigned long flags;
tcs = get_tcs_of_type(drv, CONTROL_TCS);
if (IS_ERR(tcs))
@@ -895,9 +807,9 @@
return -EINVAL;
}
- spin_lock(&tcs->tcs_lock);
+ spin_lock_irqsave(&tcs->tcs_lock, flags);
__tcs_write_hidden(tcs->drv, drv->drv_id, msg);
- spin_unlock(&tcs->tcs_lock);
+ spin_unlock_irqrestore(&tcs->tcs_lock, flags);
return 0;
}
diff --git a/drivers/media/platform/msm/camera/cam_utils/cam_soc_util.c b/drivers/media/platform/msm/camera/cam_utils/cam_soc_util.c
index 683386c..b16e37e 100644
--- a/drivers/media/platform/msm/camera/cam_utils/cam_soc_util.c
+++ b/drivers/media/platform/msm/camera/cam_utils/cam_soc_util.c
@@ -412,6 +412,7 @@
goto put_regulator;
}
disable_irq(soc_info->irq_line->start);
+ soc_info->irq_data = irq_data;
}
/* Get Clock */
@@ -439,7 +440,8 @@
if (soc_info->irq_line) {
disable_irq(soc_info->irq_line->start);
- free_irq(soc_info->irq_line->start, soc_info);
+ devm_free_irq(&soc_info->pdev->dev,
+ soc_info->irq_line->start, irq_data);
}
put_regulator:
@@ -495,7 +497,8 @@
if (soc_info->irq_line) {
disable_irq(soc_info->irq_line->start);
- free_irq(soc_info->irq_line->start, soc_info);
+ devm_free_irq(&soc_info->pdev->dev,
+ soc_info->irq_line->start, soc_info->irq_data);
}
return 0;
diff --git a/drivers/media/platform/msm/camera/cam_utils/cam_soc_util.h b/drivers/media/platform/msm/camera/cam_utils/cam_soc_util.h
index 0baa9e6..3e8226f 100644
--- a/drivers/media/platform/msm/camera/cam_utils/cam_soc_util.h
+++ b/drivers/media/platform/msm/camera/cam_utils/cam_soc_util.h
@@ -58,6 +58,7 @@
* @index: Instance id for the camera device
* @irq_name: Name of the irq associated with the device
* @irq_line: Irq resource
+ * @irq_data: Private data that is passed when IRQ is requested
* @num_mem_block: Number of entry in the "reg-names"
* @mem_block_name: Array of the reg block name
* @mem_block_cam_base: Array of offset of this register space compared
@@ -85,6 +86,7 @@
const char *irq_name;
struct resource *irq_line;
+ void *irq_data;
uint32_t num_mem_block;
const char *mem_block_name[CAM_SOC_MAX_BLOCK];
diff --git a/drivers/media/platform/msm/sde/rotator/sde_rotator_dev.c b/drivers/media/platform/msm/sde/rotator/sde_rotator_dev.c
index 1c94632..15ecc10 100644
--- a/drivers/media/platform/msm/sde/rotator/sde_rotator_dev.c
+++ b/drivers/media/platform/msm/sde/rotator/sde_rotator_dev.c
@@ -2594,8 +2594,13 @@
static long sde_rotator_compat_ioctl32(struct file *file,
unsigned int cmd, unsigned long arg)
{
+ struct video_device *vdev = video_devdata(file);
+ struct sde_rotator_ctx *ctx =
+ sde_rotator_ctx_from_fh(file->private_data);
long ret;
+ mutex_lock(vdev->lock);
+
switch (cmd) {
case VIDIOC_S_SDE_ROTATOR_FENCE:
case VIDIOC_G_SDE_ROTATOR_FENCE:
@@ -2604,14 +2609,14 @@
if (copy_from_user(&fence, (void __user *)arg,
sizeof(struct msm_sde_rotator_fence)))
- return -EFAULT;
+ goto ioctl32_error;
ret = sde_rotator_private_ioctl(file, file->private_data,
0, cmd, (void *)&fence);
if (copy_to_user((void __user *)arg, &fence,
sizeof(struct msm_sde_rotator_fence)))
- return -EFAULT;
+ goto ioctl32_error;
break;
}
@@ -2622,24 +2627,31 @@
if (copy_from_user(&comp_ratio, (void __user *)arg,
sizeof(struct msm_sde_rotator_comp_ratio)))
- return -EFAULT;
+ goto ioctl32_error;
ret = sde_rotator_private_ioctl(file, file->private_data,
0, cmd, (void *)&comp_ratio);
if (copy_to_user((void __user *)arg, &comp_ratio,
sizeof(struct msm_sde_rotator_comp_ratio)))
- return -EFAULT;
+ goto ioctl32_error;
break;
}
default:
+ SDEDEV_ERR(ctx->rot_dev->dev, "invalid ioctl32 type:%x\n", cmd);
ret = -ENOIOCTLCMD;
break;
}
+ mutex_unlock(vdev->lock);
return ret;
+
+ioctl32_error:
+ mutex_unlock(vdev->lock);
+ SDEDEV_ERR(ctx->rot_dev->dev, "error handling ioctl32 cmd:%x\n", cmd);
+ return -EFAULT;
}
#endif
diff --git a/drivers/net/wireless/cnss_prealloc/cnss_prealloc.c b/drivers/net/wireless/cnss_prealloc/cnss_prealloc.c
index 61de231..3c89a73 100644
--- a/drivers/net/wireless/cnss_prealloc/cnss_prealloc.c
+++ b/drivers/net/wireless/cnss_prealloc/cnss_prealloc.c
@@ -210,6 +210,7 @@
#else
void wcnss_prealloc_check_memory_leak(void) {}
#endif
+EXPORT_SYMBOL(wcnss_prealloc_check_memory_leak);
int wcnss_pre_alloc_reset(void)
{
@@ -225,6 +226,7 @@
return n;
}
+EXPORT_SYMBOL(wcnss_pre_alloc_reset);
static int __init wcnss_pre_alloc_init(void)
{
diff --git a/drivers/soc/qcom/icnss.c b/drivers/soc/qcom/icnss.c
index 0b35caa..b759776 100644
--- a/drivers/soc/qcom/icnss.c
+++ b/drivers/soc/qcom/icnss.c
@@ -48,11 +48,6 @@
#include <soc/qcom/socinfo.h>
#include <soc/qcom/ramdump.h>
-#ifdef CONFIG_WCNSS_MEM_PRE_ALLOC
-#include <net/cnss_prealloc.h>
-#endif
-
-
#include "wlan_firmware_service_v01.h"
#ifdef CONFIG_ICNSS_DEBUG
@@ -1968,8 +1963,6 @@
if (ret < 0) {
icnss_pr_err("Driver probe failed: %d, state: 0x%lx\n",
ret, priv->state);
- wcnss_prealloc_check_memory_leak();
- wcnss_pre_alloc_reset();
goto out;
}
@@ -2099,8 +2092,6 @@
if (ret) {
icnss_pr_err("Driver probe failed: %d, state: 0x%lx\n",
ret, penv->state);
- wcnss_prealloc_check_memory_leak();
- wcnss_pre_alloc_reset();
goto power_off;
}
@@ -2126,8 +2117,6 @@
penv->ops->remove(&penv->pdev->dev);
clear_bit(ICNSS_DRIVER_PROBED, &penv->state);
- wcnss_prealloc_check_memory_leak();
- wcnss_pre_alloc_reset();
penv->ops = NULL;
@@ -2152,8 +2141,6 @@
penv->ops->remove(&priv->pdev->dev);
clear_bit(ICNSS_DRIVER_PROBED, &priv->state);
- wcnss_prealloc_check_memory_leak();
- wcnss_pre_alloc_reset();
icnss_hw_power_off(penv);
diff --git a/drivers/soc/qcom/msm-core.c b/drivers/soc/qcom/msm-core.c
index de2a1ce..4ec791c 100644
--- a/drivers/soc/qcom/msm-core.c
+++ b/drivers/soc/qcom/msm-core.c
@@ -35,6 +35,7 @@
#include <linux/uaccess.h>
#include <linux/uio_driver.h>
#include <asm/smp_plat.h>
+#include <asm/cputype.h>
#include <stdbool.h>
#define CREATE_TRACE_POINTS
#include <trace/events/trace_msm_core.h>
@@ -46,7 +47,6 @@
#define DEFAULT_TEMP 40
#define DEFAULT_LOW_HYST_TEMP 10
#define DEFAULT_HIGH_HYST_TEMP 5
-#define CLUSTER_OFFSET_FOR_MPIDR 8
#define MAX_CORES_PER_CLUSTER 4
#define MAX_NUM_OF_CLUSTERS 2
#define NUM_OF_CORNERS 10
@@ -291,12 +291,11 @@
int cpu = -1;
struct cpu_activity_info *node;
struct cpu_static_info *sp, *clear_sp;
- int cpumask, cluster, mpidr;
+ int cpumask, cluster;
bool pdata_valid[NR_CPUS] = {0};
get_user(cpumask, &argp->cpumask);
get_user(cluster, &argp->cluster);
- mpidr = cluster << 8;
pr_debug("%s: cpumask %d, cluster: %d\n", __func__, cpumask,
cluster);
@@ -304,10 +303,12 @@
if (!(cpumask & 0x01))
continue;
- mpidr |= i;
for_each_possible_cpu(cpu) {
- if (cpu_logical_map(cpu) == mpidr)
- break;
+ if ((cpu_topology[cpu].core_id != i) &&
+ (cpu_topology[cpu].cluster_id != cluster))
+ continue;
+
+ break;
}
}
@@ -348,10 +349,9 @@
for (i = 0; i < MAX_CORES_PER_CLUSTER; i++, cpumask >>= 1) {
if (!(cpumask & 0x01))
continue;
- mpidr = (cluster << CLUSTER_OFFSET_FOR_MPIDR);
- mpidr |= i;
for_each_possible_cpu(cpu) {
- if (!(cpu_logical_map(cpu) == mpidr))
+ if (((cpu_topology[cpu].core_id != i) ||
+ (cpu_topology[cpu].cluster_id != cluster)))
continue;
node = &activity[cpu];
@@ -395,14 +395,12 @@
struct cpu_activity_info *node = NULL;
struct sched_params __user *argp = (struct sched_params __user *)arg;
int i, cpu = num_possible_cpus();
- int mpidr, cluster, cpumask;
+ int cluster, cpumask;
if (!argp)
return -EINVAL;
get_user(cluster, &argp->cluster);
- mpidr = (cluster << (MAX_CORES_PER_CLUSTER *
- MAX_NUM_OF_CLUSTERS));
get_user(cpumask, &argp->cpumask);
switch (cmd) {
@@ -414,8 +412,11 @@
case EA_VOLT:
for (i = 0; cpumask > 0; i++, cpumask >>= 1) {
for_each_possible_cpu(cpu) {
- if (cpu_logical_map(cpu) == (mpidr | i))
- break;
+ if (((cpu_topology[cpu].core_id != i) ||
+ (cpu_topology[cpu].cluster_id != cluster)))
+ continue;
+
+ break;
}
}
if (cpu >= num_possible_cpus())
diff --git a/include/dt-bindings/clock/qcom,gcc-sdm845.h b/include/dt-bindings/clock/qcom,gcc-sdm845.h
index 6c62503..73a8c0b 100644
--- a/include/dt-bindings/clock/qcom,gcc-sdm845.h
+++ b/include/dt-bindings/clock/qcom,gcc-sdm845.h
@@ -214,6 +214,8 @@
#define GCC_USB3PHY_PHY_SEC_BCR 22
#define GCC_USB3_DP_PHY_SEC_BCR 23
#define GCC_USB_PHY_CFG_AHB2PHY_BCR 24
+#define GCC_PCIE_0_PHY_BCR 25
+#define GCC_PCIE_1_PHY_BCR 26
/* Dummy clocks for rate measurement */
#define MEASURE_ONLY_SNOC_CLK 0