summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--arch/arm/boot/compressed/head.S2
-rw-r--r--arch/arm/boot/dts/qcom/msmfalcon-pinctrl.dtsi64
-rw-r--r--arch/arm/boot/dts/qcom/msmfalcon-rumi.dts26
-rw-r--r--arch/arm/boot/dts/qcom/msmfalcon-sim.dts26
-rw-r--r--arch/arm/boot/dts/qcom/msmfalcon.dtsi21
-rw-r--r--arch/arm/boot/dts/qcom/msmtriton.dtsi29
-rw-r--r--drivers/clk/msm/clock-osm.c6
-rw-r--r--drivers/clk/qcom/clk-rcg2.c2
-rw-r--r--drivers/clk/qcom/gpucc-msmfalcon.c8
-rw-r--r--drivers/platform/msm/gsi/gsi.c4
-rw-r--r--drivers/power/power_supply_sysfs.c1
-rw-r--r--drivers/power/qcom-charger/qpnp-fg-gen3.c33
-rw-r--r--drivers/power/qcom-charger/qpnp-smb2.c31
-rw-r--r--drivers/power/qcom-charger/smb-lib.c70
-rw-r--r--drivers/power/qcom-charger/smb-lib.h4
-rw-r--r--drivers/usb/pd/policy_engine.c187
-rw-r--r--include/linux/power_supply.h1
-rw-r--r--kernel/sched/hmp.c2
-rw-r--r--sound/usb/usb_audio_qmi_svc.c2
19 files changed, 401 insertions, 118 deletions
diff --git a/arch/arm/boot/compressed/head.S b/arch/arm/boot/compressed/head.S
index ae85dcdcb7df..d2e43b053d9b 100644
--- a/arch/arm/boot/compressed/head.S
+++ b/arch/arm/boot/compressed/head.S
@@ -776,7 +776,7 @@ __armv7_mmu_cache_on:
orrne r0, r0, #1 @ MMU enabled
movne r1, #0xfffffffd @ domain 0 = client
bic r6, r6, #1 << 31 @ 32-bit translation system
- bic r6, r6, #3 << 0 @ use only ttbr0
+ bic r6, r6, #(7 << 0) | (1 << 4) @ use only ttbr0
mcrne p15, 0, r3, c2, c0, 0 @ load page table pointer
mcrne p15, 0, r0, c8, c7, 0 @ flush I,D TLBs
mcr p15, 0, r0, c7, c5, 4 @ ISB
diff --git a/arch/arm/boot/dts/qcom/msmfalcon-pinctrl.dtsi b/arch/arm/boot/dts/qcom/msmfalcon-pinctrl.dtsi
index d28d09c2a527..e8c66871425d 100644
--- a/arch/arm/boot/dts/qcom/msmfalcon-pinctrl.dtsi
+++ b/arch/arm/boot/dts/qcom/msmfalcon-pinctrl.dtsi
@@ -48,5 +48,69 @@
output-low;
};
};
+
+ /* SDC pin type */
+ sdc1_clk_on: sdc1_clk_on {
+ config {
+ pins = "sdc1_clk";
+ bias-disable; /* NO pull */
+ drive-strength = <16>; /* 16 MA */
+ };
+ };
+
+ sdc1_clk_off: sdc1_clk_off {
+ config {
+ pins = "sdc1_clk";
+ bias-disable; /* NO pull */
+ drive-strength = <2>; /* 2 MA */
+ };
+ };
+
+ sdc1_cmd_on: sdc1_cmd_on {
+ config {
+ pins = "sdc1_cmd";
+ bias-pull-up; /* pull up */
+ drive-strength = <10>; /* 10 MA */
+ };
+ };
+
+ sdc1_cmd_off: sdc1_cmd_off {
+ config {
+ pins = "sdc1_cmd";
+ num-grp-pins = <1>;
+ bias-pull-up; /* pull up */
+ drive-strength = <2>; /* 2 MA */
+ };
+ };
+
+ sdc1_data_on: sdc1_data_on {
+ config {
+ pins = "sdc1_data";
+ bias-pull-up; /* pull up */
+ drive-strength = <10>; /* 10 MA */
+ };
+ };
+
+ sdc1_data_off: sdc1_data_off {
+ config {
+ pins = "sdc1_data";
+ bias-pull-up; /* pull up */
+ drive-strength = <2>; /* 2 MA */
+ };
+ };
+
+ sdc1_rclk_on: sdc1_rclk_on {
+ config {
+ pins = "sdc1_rclk";
+ bias-pull-down; /* pull down */
+ };
+ };
+
+ sdc1_rclk_off: sdc1_rclk_off {
+ config {
+ pins = "sdc1_rclk";
+ bias-pull-down; /* pull down */
+ };
+ };
};
};
diff --git a/arch/arm/boot/dts/qcom/msmfalcon-rumi.dts b/arch/arm/boot/dts/qcom/msmfalcon-rumi.dts
index 0d694a6cd9fa..f0ba8b115120 100644
--- a/arch/arm/boot/dts/qcom/msmfalcon-rumi.dts
+++ b/arch/arm/boot/dts/qcom/msmfalcon-rumi.dts
@@ -27,3 +27,29 @@
pinctrl-names = "default";
pinctrl-0 = <&uart_console_active>;
};
+
+&sdhc_1 {
+ /* device core power supply */
+ vdd-supply = <&pmfalcon_l4b>;
+ qcom,vdd-voltage-level = <2950000 2950000>;
+ qcom,vdd-current-level = <200 570000>;
+
+ /* device communication power supply */
+ vdd-io-supply = <&pmfalcon_l8a>;
+ qcom,vdd-io-always-on;
+ qcom,vdd-io-lpm-sup;
+ qcom,vdd-io-voltage-level = <1800000 1800000>;
+ qcom,vdd-io-current-level = <200 325000>;
+
+ pinctrl-names = "active", "sleep";
+ pinctrl-0 = <&sdc1_clk_on &sdc1_cmd_on &sdc1_data_on &sdc1_rclk_on>;
+ pinctrl-1 = <&sdc1_clk_off &sdc1_cmd_off &sdc1_data_off &sdc1_rclk_off>;
+
+ qcom,clk-rates = <400000 20000000 25000000 50000000 192000000
+ 384000000>;
+
+ qcom,nonremovable;
+ qcom,bus-speed-mode = "HS400_1p8v", "HS200_1p8v", "DDR_1p8v";
+
+ status = "ok";
+};
diff --git a/arch/arm/boot/dts/qcom/msmfalcon-sim.dts b/arch/arm/boot/dts/qcom/msmfalcon-sim.dts
index eaaa1b407425..085419b7e108 100644
--- a/arch/arm/boot/dts/qcom/msmfalcon-sim.dts
+++ b/arch/arm/boot/dts/qcom/msmfalcon-sim.dts
@@ -27,3 +27,29 @@
pinctrl-names = "default";
pinctrl-0 = <&uart_console_active>;
};
+
+&sdhc_1 {
+ /* device core power supply */
+ vdd-supply = <&pmfalcon_l4b>;
+ qcom,vdd-voltage-level = <2950000 2950000>;
+ qcom,vdd-current-level = <200 570000>;
+
+ /* device communication power supply */
+ vdd-io-supply = <&pmfalcon_l8a>;
+ qcom,vdd-io-always-on;
+ qcom,vdd-io-lpm-sup;
+ qcom,vdd-io-voltage-level = <1800000 1800000>;
+ qcom,vdd-io-current-level = <200 325000>;
+
+ pinctrl-names = "active", "sleep";
+ pinctrl-0 = <&sdc1_clk_on &sdc1_cmd_on &sdc1_data_on &sdc1_rclk_on>;
+ pinctrl-1 = <&sdc1_clk_off &sdc1_cmd_off &sdc1_data_off &sdc1_rclk_off>;
+
+ qcom,clk-rates = <400000 20000000 25000000 50000000 192000000
+ 384000000>;
+
+ qcom,nonremovable;
+ qcom,bus-speed-mode = "HS400_1p8v", "HS200_1p8v", "DDR_1p8v";
+
+ status = "ok";
+};
diff --git a/arch/arm/boot/dts/qcom/msmfalcon.dtsi b/arch/arm/boot/dts/qcom/msmfalcon.dtsi
index 10d5bbcc01e5..8e8c407734eb 100644
--- a/arch/arm/boot/dts/qcom/msmfalcon.dtsi
+++ b/arch/arm/boot/dts/qcom/msmfalcon.dtsi
@@ -26,6 +26,7 @@
aliases {
serial0 = &uartblsp1dm1;
+ sdhc1 = &sdhc_1; /* SDC1 eMMC slot */
};
chosen {
@@ -403,6 +404,26 @@
#reset-cells = <1>;
};
+ sdhc_1: sdhci@c0c4000 {
+ compatible = "qcom,sdhci-msm-v5";
+ reg = <0xc0c4000 0x1000>, <0xc0c5000 0x1000>;
+ reg-names = "hc_mem", "cmdq_mem";
+
+ interrupts = <0 129 0>, <0 227 0>;
+ interrupt-names = "hc_irq", "pwr_irq";
+
+ qcom,bus-width = <8>;
+ qcom,large-address-bus;
+
+ qcom,devfreq,freq-table = <50000000 200000000>;
+
+ clocks = <&clock_gcc GCC_SDCC1_AHB_CLK>,
+ <&clock_gcc GCC_SDCC1_APPS_CLK>;
+ clock-names = "iface_clk", "core_clk";
+
+ status = "disabled";
+ };
+
qcom,ipc-spinlock@1f40000 {
compatible = "qcom,ipc-spinlock-sfpb";
reg = <0x1f40000 0x8000>;
diff --git a/arch/arm/boot/dts/qcom/msmtriton.dtsi b/arch/arm/boot/dts/qcom/msmtriton.dtsi
index 1dbefc555850..083c14af7839 100644
--- a/arch/arm/boot/dts/qcom/msmtriton.dtsi
+++ b/arch/arm/boot/dts/qcom/msmtriton.dtsi
@@ -580,6 +580,35 @@
qcom,gpio-force-stop = <&smp2pgpio_ssr_smp2p_2_out 0 0>;
status = "ok";
};
+
+ qcom,venus@cce0000 {
+ compatible = "qcom,pil-tz-generic";
+ reg = <0xcce0000 0x4000>;
+
+ vdd-supply = <&gdsc_venus>;
+ qcom,proxy-reg-names = "vdd";
+
+ clocks = <&clock_mmss MMSS_VIDEO_CORE_CLK>,
+ <&clock_mmss MMSS_VIDEO_AHB_CLK>,
+ <&clock_mmss MMSS_VIDEO_AXI_CLK>;
+ clock-names = "core_clk","iface_clk",
+ "bus_clk";
+ qcom,proxy-clock-names = "core_clk",
+ "iface_clk","bus_clk";
+
+ qcom,msm-bus,name = "pil-venus";
+ qcom,msm-bus,num-cases = <2>;
+ qcom,msm-bus,num-paths = <1>;
+ qcom,msm-bus,vectors-KBps =
+ <63 512 0 0>,
+ <63 512 0 304000>;
+
+ qcom,pas-id = <9>;
+ qcom,proxy-timeout-ms = <100>;
+ qcom,firmware-name = "venus";
+ memory-region = <&venus_fw_mem>;
+ status = "ok";
+ };
};
#include "msmtriton-ion.dtsi"
diff --git a/drivers/clk/msm/clock-osm.c b/drivers/clk/msm/clock-osm.c
index d29fd60719c9..a119c0b27321 100644
--- a/drivers/clk/msm/clock-osm.c
+++ b/drivers/clk/msm/clock-osm.c
@@ -1776,7 +1776,7 @@ static void clk_osm_setup_fsms(struct clk_osm *c)
val = clk_osm_read_reg(c,
DROOP_WAIT_TO_RELEASE_TIMER_CTRL0_REG);
- val |= BVAL(31, 16, clk_osm_count_ns(c, 500));
+ val |= BVAL(31, 16, clk_osm_count_ns(c, 250));
clk_osm_write_reg(c, val,
DROOP_WAIT_TO_RELEASE_TIMER_CTRL0_REG);
}
@@ -1793,7 +1793,7 @@ static void clk_osm_setup_fsms(struct clk_osm *c)
val = clk_osm_read_reg(c,
DROOP_WAIT_TO_RELEASE_TIMER_CTRL0_REG);
- val |= BVAL(15, 0, clk_osm_count_ns(c, 15000));
+ val |= BVAL(15, 0, clk_osm_count_ns(c, 250));
clk_osm_write_reg(c, val,
DROOP_WAIT_TO_RELEASE_TIMER_CTRL0_REG);
}
@@ -1807,7 +1807,7 @@ static void clk_osm_setup_fsms(struct clk_osm *c)
if (c->wfx_fsm_en || c->ps_fsm_en || c->droop_fsm_en) {
clk_osm_write_reg(c, 0x1, DROOP_PROG_SYNC_DELAY_REG);
- clk_osm_write_reg(c, clk_osm_count_ns(c, 500),
+ clk_osm_write_reg(c, clk_osm_count_ns(c, 5),
DROOP_RELEASE_TIMER_CTRL);
clk_osm_write_reg(c, clk_osm_count_ns(c, 500),
DCVS_DROOP_TIMER_CTRL);
diff --git a/drivers/clk/qcom/clk-rcg2.c b/drivers/clk/qcom/clk-rcg2.c
index 933a208392bd..6d12ddb3e245 100644
--- a/drivers/clk/qcom/clk-rcg2.c
+++ b/drivers/clk/qcom/clk-rcg2.c
@@ -935,6 +935,8 @@ static int clk_gfx3d_src_set_rate_and_parent(struct clk_hw *hw,
}
const struct clk_ops clk_gfx3d_src_ops = {
+ .enable = clk_rcg2_enable,
+ .disable = clk_rcg2_disable,
.is_enabled = clk_rcg2_is_enabled,
.get_parent = clk_rcg2_get_parent,
.set_parent = clk_rcg2_set_parent,
diff --git a/drivers/clk/qcom/gpucc-msmfalcon.c b/drivers/clk/qcom/gpucc-msmfalcon.c
index a2127e2629c7..f194abb471cd 100644
--- a/drivers/clk/qcom/gpucc-msmfalcon.c
+++ b/drivers/clk/qcom/gpucc-msmfalcon.c
@@ -84,12 +84,12 @@ static struct pll_vco gpu_vco[] = {
{ 250000000, 500000000, 3 },
};
-/* 640MHz configuration */
+/* 800MHz configuration */
static const struct pll_config gpu_pll0_config = {
- .l = 0x21,
+ .l = 0x29,
.config_ctl_val = 0x4001055b,
- .alpha = 0x55555600,
- .alpha_u = 0x55,
+ .alpha = 0xaaaaab00,
+ .alpha_u = 0xaa,
.alpha_en_mask = BIT(24),
.vco_val = 0x2 << 20,
.vco_mask = 0x3 << 20,
diff --git a/drivers/platform/msm/gsi/gsi.c b/drivers/platform/msm/gsi/gsi.c
index 352defe6204b..bd2132d77360 100644
--- a/drivers/platform/msm/gsi/gsi.c
+++ b/drivers/platform/msm/gsi/gsi.c
@@ -17,6 +17,7 @@
#include <linux/module.h>
#include <linux/msm_gsi.h>
#include <linux/platform_device.h>
+#include <linux/delay.h>
#include "gsi.h"
#include "gsi_reg.h"
@@ -26,6 +27,8 @@
#define GSI_MHI_ER_START 10
#define GSI_MHI_ER_END 16
+#define GSI_RESET_WA_MIN_SLEEP 1000
+#define GSI_RESET_WA_MAX_SLEEP 2000
static const struct of_device_id msm_gsi_match[] = {
{ .compatible = "qcom,msm_gsi", },
{ },
@@ -1982,6 +1985,7 @@ reset:
/* workaround: reset GSI producers again */
if (ctx->props.dir == GSI_CHAN_DIR_FROM_GSI && !reset_done) {
+ usleep_range(GSI_RESET_WA_MIN_SLEEP, GSI_RESET_WA_MAX_SLEEP);
reset_done = true;
goto reset;
}
diff --git a/drivers/power/power_supply_sysfs.c b/drivers/power/power_supply_sysfs.c
index ea2694c8c58d..2718ea93bd45 100644
--- a/drivers/power/power_supply_sysfs.c
+++ b/drivers/power/power_supply_sysfs.c
@@ -275,6 +275,7 @@ static struct device_attribute power_supply_attrs[] = {
POWER_SUPPLY_ATTR(charger_temp_max),
POWER_SUPPLY_ATTR(parallel_disable),
POWER_SUPPLY_ATTR(parallel_percent),
+ POWER_SUPPLY_ATTR(pe_start),
/* Local extensions of type int64_t */
POWER_SUPPLY_ATTR(charge_counter_ext),
/* Properties of type `const char *' */
diff --git a/drivers/power/qcom-charger/qpnp-fg-gen3.c b/drivers/power/qcom-charger/qpnp-fg-gen3.c
index 30408218b7e7..c0a19ae115d0 100644
--- a/drivers/power/qcom-charger/qpnp-fg-gen3.c
+++ b/drivers/power/qcom-charger/qpnp-fg-gen3.c
@@ -1644,6 +1644,37 @@ out:
return rc;
}
+static void fg_notify_charger(struct fg_chip *chip)
+{
+ union power_supply_propval prop = {0, };
+ int rc;
+
+ if (!is_charger_available(chip)) {
+ pr_warn("Charger not available yet?\n");
+ return;
+ }
+
+ prop.intval = chip->bp.float_volt_uv;
+ rc = power_supply_set_property(chip->batt_psy,
+ POWER_SUPPLY_PROP_VOLTAGE_MAX, &prop);
+ if (rc < 0) {
+ pr_err("Error in setting voltage_max property on batt_psy, rc=%d\n",
+ rc);
+ return;
+ }
+
+ prop.intval = chip->bp.fastchg_curr_ma;
+ rc = power_supply_set_property(chip->batt_psy,
+ POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT_MAX, &prop);
+ if (rc < 0) {
+ pr_err("Error in setting constant_charge_current_max property on batt_psy, rc=%d\n",
+ rc);
+ return;
+ }
+
+ fg_dbg(chip, FG_STATUS, "Notified charger on float voltage and FCC\n");
+}
+
static void profile_load_work(struct work_struct *work)
{
struct fg_chip *chip = container_of(work,
@@ -1709,6 +1740,7 @@ done:
rc);
}
+ fg_notify_charger(chip);
chip->profile_loaded = true;
fg_dbg(chip, FG_STATUS, "profile loaded successfully");
out:
@@ -1798,6 +1830,7 @@ static int fg_psy_get_property(struct power_supply *psy,
break;
case POWER_SUPPLY_PROP_VOLTAGE_MAX_DESIGN:
pval->intval = chip->bp.float_volt_uv;
+ break;
case POWER_SUPPLY_PROP_CYCLE_COUNT:
pval->intval = fg_get_cycle_count(chip);
break;
diff --git a/drivers/power/qcom-charger/qpnp-smb2.c b/drivers/power/qcom-charger/qpnp-smb2.c
index dee554b6e150..93965dbe99ae 100644
--- a/drivers/power/qcom-charger/qpnp-smb2.c
+++ b/drivers/power/qcom-charger/qpnp-smb2.c
@@ -351,6 +351,7 @@ static enum power_supply_property smb2_usb_props[] = {
POWER_SUPPLY_PROP_PD_ACTIVE,
POWER_SUPPLY_PROP_INPUT_CURRENT_SETTLED,
POWER_SUPPLY_PROP_INPUT_CURRENT_NOW,
+ POWER_SUPPLY_PROP_PE_START,
};
static int smb2_usb_get_prop(struct power_supply *psy,
@@ -422,6 +423,9 @@ static int smb2_usb_get_prop(struct power_supply *psy,
case POWER_SUPPLY_PROP_PD_USB_SUSPEND_SUPPORTED:
val->intval = chg->system_suspend_supported;
break;
+ case POWER_SUPPLY_PROP_PE_START:
+ rc = smblib_get_pe_start(chg, val);
+ break;
default:
pr_err("get prop %d is not supported\n", psp);
rc = -EINVAL;
@@ -633,13 +637,16 @@ static enum power_supply_property smb2_batt_props[] = {
POWER_SUPPLY_PROP_CHARGER_TEMP_MAX,
POWER_SUPPLY_PROP_INPUT_CURRENT_LIMITED,
POWER_SUPPLY_PROP_VOLTAGE_NOW,
+ POWER_SUPPLY_PROP_VOLTAGE_MAX,
POWER_SUPPLY_PROP_CURRENT_NOW,
+ POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT_MAX,
POWER_SUPPLY_PROP_TEMP,
POWER_SUPPLY_PROP_TECHNOLOGY,
POWER_SUPPLY_PROP_STEP_CHARGING_ENABLED,
POWER_SUPPLY_PROP_STEP_CHARGING_STEP,
POWER_SUPPLY_PROP_CHARGE_DONE,
POWER_SUPPLY_PROP_PARALLEL_DISABLE,
+ POWER_SUPPLY_PROP_PARALLEL_PERCENT,
};
static int smb2_batt_get_prop(struct power_supply *psy,
@@ -679,6 +686,7 @@ static int smb2_batt_get_prop(struct power_supply *psy,
break;
case POWER_SUPPLY_PROP_INPUT_CURRENT_LIMITED:
rc = smblib_get_prop_input_current_limited(chg, val);
+ break;
case POWER_SUPPLY_PROP_STEP_CHARGING_ENABLED:
val->intval = chg->step_chg_enabled;
break;
@@ -688,9 +696,16 @@ static int smb2_batt_get_prop(struct power_supply *psy,
case POWER_SUPPLY_PROP_VOLTAGE_NOW:
rc = smblib_get_prop_batt_voltage_now(chg, val);
break;
+ case POWER_SUPPLY_PROP_VOLTAGE_MAX:
+ val->intval = get_client_vote(chg->fv_votable, DEFAULT_VOTER);
+ break;
case POWER_SUPPLY_PROP_CURRENT_NOW:
rc = smblib_get_prop_batt_current_now(chg, val);
break;
+ case POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT_MAX:
+ val->intval = get_client_vote(chg->fcc_max_votable,
+ DEFAULT_VOTER);
+ break;
case POWER_SUPPLY_PROP_TEMP:
rc = smblib_get_prop_batt_temp(chg, val);
break;
@@ -704,6 +719,9 @@ static int smb2_batt_get_prop(struct power_supply *psy,
val->intval = get_client_vote(chg->pl_disable_votable,
USER_VOTER);
break;
+ case POWER_SUPPLY_PROP_PARALLEL_PERCENT:
+ val->intval = chg->pl.slave_pct;
+ break;
default:
pr_err("batt power supply prop %d not supported\n", psp);
return -EINVAL;
@@ -737,6 +755,18 @@ static int smb2_batt_set_prop(struct power_supply *psy,
case POWER_SUPPLY_PROP_PARALLEL_DISABLE:
vote(chg->pl_disable_votable, USER_VOTER, (bool)val->intval, 0);
break;
+ case POWER_SUPPLY_PROP_PARALLEL_PERCENT:
+ if (val->intval < 0 || val->intval > 100)
+ return -EINVAL;
+ chg->pl.slave_pct = val->intval;
+ rerun_election(chg->fcc_votable);
+ break;
+ case POWER_SUPPLY_PROP_VOLTAGE_MAX:
+ vote(chg->fv_votable, DEFAULT_VOTER, true, val->intval);
+ break;
+ case POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT_MAX:
+ vote(chg->fcc_max_votable, DEFAULT_VOTER, true, val->intval);
+ break;
default:
rc = -EINVAL;
}
@@ -752,6 +782,7 @@ static int smb2_batt_prop_is_writeable(struct power_supply *psy,
case POWER_SUPPLY_PROP_SYSTEM_TEMP_LEVEL:
case POWER_SUPPLY_PROP_CAPACITY:
case POWER_SUPPLY_PROP_PARALLEL_DISABLE:
+ case POWER_SUPPLY_PROP_PARALLEL_PERCENT:
return 1;
default:
break;
diff --git a/drivers/power/qcom-charger/smb-lib.c b/drivers/power/qcom-charger/smb-lib.c
index bcdfdd459b3d..5785e42e0140 100644
--- a/drivers/power/qcom-charger/smb-lib.c
+++ b/drivers/power/qcom-charger/smb-lib.c
@@ -38,8 +38,8 @@
static bool is_secure(struct smb_charger *chg, int addr)
{
- /* assume everything above 0xC0 is secure */
- return (bool)((addr & 0xFF) >= 0xC0);
+ /* assume everything above 0xA0 is secure */
+ return (bool)((addr & 0xFF) >= 0xA0);
}
int smblib_read(struct smb_charger *chg, u16 addr, u8 *val)
@@ -152,7 +152,7 @@ static void smblib_split_fcc(struct smb_charger *chg, int total_ua,
int *master_ua, int *slave_ua)
{
int rc, jeita_cc_delta_ua, step_cc_delta_ua, effective_total_ua,
- hw_cc_delta_ua = 0;
+ slave_limited_ua, hw_cc_delta_ua = 0;
rc = smblib_get_step_cc_delta(chg, &step_cc_delta_ua);
if (rc < 0) {
@@ -172,7 +172,8 @@ static void smblib_split_fcc(struct smb_charger *chg, int total_ua,
}
effective_total_ua = max(0, total_ua + hw_cc_delta_ua);
- *slave_ua = (effective_total_ua * chg->pl.slave_pct) / 100;
+ slave_limited_ua = min(effective_total_ua, chg->input_limited_fcc_ua);
+ *slave_ua = (slave_limited_ua * chg->pl.slave_pct) / 100;
*slave_ua = (*slave_ua * chg->pl.taper_pct) / 100;
*master_ua = max(0, total_ua - *slave_ua);
}
@@ -470,9 +471,8 @@ static int try_rerun_apsd_for_hvdcp(struct smb_charger *chg)
return 0;
}
-static int smblib_update_usb_type(struct smb_charger *chg)
+static const struct apsd_result *smblib_update_usb_type(struct smb_charger *chg)
{
- int rc = 0;
const struct apsd_result *apsd_result;
/* if PD is active, APSD is disabled so won't have a valid result */
@@ -483,7 +483,7 @@ static int smblib_update_usb_type(struct smb_charger *chg)
apsd_result = smblib_get_apsd_result(chg);
chg->usb_psy_desc.type = apsd_result->pst;
- return rc;
+ return apsd_result;
}
static int smblib_notifier_call(struct notifier_block *nb,
@@ -592,7 +592,7 @@ static int smblib_fcc_vote_callback(struct votable *votable, void *data,
{
struct smb_charger *chg = data;
union power_supply_propval pval = {0, };
- int rc, master_fcc_ua = total_fcc_ua, slave_fcc_ua;
+ int rc, master_fcc_ua = total_fcc_ua, slave_fcc_ua = 0;
if (total_fcc_ua < 0)
return 0;
@@ -624,6 +624,11 @@ static int smblib_fcc_vote_callback(struct votable *votable, void *data,
return rc;
}
+ smblib_dbg(chg, PR_PARALLEL, "master_fcc=%d slave_fcc=%d distribution=(%d/%d)\n",
+ master_fcc_ua, slave_fcc_ua,
+ (master_fcc_ua * 100) / total_fcc_ua,
+ (slave_fcc_ua * 100) / total_fcc_ua);
+
return 0;
}
@@ -833,6 +838,9 @@ static int smblib_pl_disable_vote_callback(struct votable *votable, void *data,
return rc;
}
+ smblib_dbg(chg, PR_PARALLEL, "parallel charging %s\n",
+ pl_disable ? "disabled" : "enabled");
+
return 0;
}
@@ -1758,7 +1766,7 @@ int smblib_get_prop_typec_power_role(struct smb_charger *chg,
int smblib_get_prop_pd_allowed(struct smb_charger *chg,
union power_supply_propval *val)
{
- val->intval = get_effective_result_locked(chg->pd_allowed_votable);
+ val->intval = get_effective_result(chg->pd_allowed_votable);
return 0;
}
@@ -1784,6 +1792,19 @@ int smblib_get_prop_pd_in_hard_reset(struct smb_charger *chg,
return 0;
}
+int smblib_get_pe_start(struct smb_charger *chg,
+ union power_supply_propval *val)
+{
+ /*
+ * hvdcp timeout voter is the last one to allow pd. Use its vote
+ * to indicate start of pe engine
+ */
+ val->intval
+ = !get_client_vote_locked(chg->pd_disallowed_votable_indirect,
+ HVDCP_TIMEOUT_VOTER);
+ return 0;
+}
+
/*******************
* USB PSY SETTERS *
* *****************/
@@ -1954,6 +1975,13 @@ int smblib_set_prop_pd_active(struct smb_charger *chg,
smblib_update_usb_type(chg);
power_supply_changed(chg->usb_psy);
+ rc = smblib_masked_write(chg, TYPE_C_CFG_3_REG, EN_TRYSINK_MODE_BIT,
+ chg->pd_active ? 0 : EN_TRYSINK_MODE_BIT);
+ if (rc < 0) {
+ dev_err(chg->dev, "Couldn't set TRYSINK_MODE rc=%d\n", rc);
+ return rc;
+ }
+
return rc;
}
@@ -2187,12 +2215,14 @@ skip_dpdm_float:
}
#define USB_WEAK_INPUT_UA 1400000
+#define EFFICIENCY_PCT 80
irqreturn_t smblib_handle_icl_change(int irq, void *data)
{
struct smb_irq_data *irq_data = data;
struct smb_charger *chg = irq_data->parent_data;
int rc, icl_ua;
+ smblib_dbg(chg, PR_INTERRUPT, "IRQ: %s\n", irq_data->name);
rc = smblib_get_charge_param(chg, &chg->param.icl_stat, &icl_ua);
if (rc < 0) {
@@ -2200,11 +2230,18 @@ irqreturn_t smblib_handle_icl_change(int irq, void *data)
return IRQ_HANDLED;
}
- if (chg->mode == PARALLEL_MASTER)
- vote(chg->pl_enable_votable_indirect, USBIN_I_VOTER,
- icl_ua >= USB_WEAK_INPUT_UA, 0);
+ if (chg->mode != PARALLEL_MASTER)
+ return IRQ_HANDLED;
- smblib_dbg(chg, PR_INTERRUPT, "IRQ: %s\n", irq_data->name);
+ chg->input_limited_fcc_ua = div64_s64(
+ (s64)icl_ua * MICRO_5V * EFFICIENCY_PCT,
+ (s64)get_effective_result(chg->fv_votable) * 100);
+
+ if (!get_effective_result(chg->pl_disable_votable))
+ rerun_election(chg->fcc_votable);
+
+ vote(chg->pl_enable_votable_indirect, USBIN_I_VOTER,
+ icl_ua >= USB_WEAK_INPUT_UA, 0);
return IRQ_HANDLED;
}
@@ -2280,13 +2317,12 @@ static void smblib_handle_hvdcp_detect_done(struct smb_charger *chg,
#define HVDCP_DET_MS 2500
static void smblib_handle_apsd_done(struct smb_charger *chg, bool rising)
{
- int rc;
const struct apsd_result *apsd_result;
if (!rising)
return;
- apsd_result = smblib_get_apsd_result(chg);
+ apsd_result = smblib_update_usb_type(chg);
switch (apsd_result->bit) {
case SDP_CHARGER_BIT:
case CDP_CHARGER_BIT:
@@ -2305,10 +2341,6 @@ static void smblib_handle_apsd_done(struct smb_charger *chg, bool rising)
break;
}
- rc = smblib_update_usb_type(chg);
- if (rc < 0)
- smblib_err(chg, "Couldn't update usb type rc=%d\n", rc);
-
smblib_dbg(chg, PR_INTERRUPT, "IRQ: apsd-done rising; %s detected\n",
apsd_result->name);
}
diff --git a/drivers/power/qcom-charger/smb-lib.h b/drivers/power/qcom-charger/smb-lib.h
index 9612b740d84f..4be06ffcfb25 100644
--- a/drivers/power/qcom-charger/smb-lib.h
+++ b/drivers/power/qcom-charger/smb-lib.h
@@ -22,6 +22,7 @@ enum print_reason {
PR_INTERRUPT = BIT(0),
PR_REGISTER = BIT(1),
PR_MISC = BIT(2),
+ PR_PARALLEL = BIT(3),
};
#define DEFAULT_VOTER "DEFAULT_VOTER"
@@ -190,6 +191,7 @@ struct smb_charger {
bool step_chg_enabled;
bool is_hdc;
bool chg_done;
+ int input_limited_fcc_ua;
/* workaround flag */
u32 wa_flags;
@@ -308,6 +310,8 @@ int smblib_get_prop_input_current_settled(struct smb_charger *chg,
union power_supply_propval *val);
int smblib_get_prop_pd_in_hard_reset(struct smb_charger *chg,
union power_supply_propval *val);
+int smblib_get_pe_start(struct smb_charger *chg,
+ union power_supply_propval *val);
int smblib_get_prop_charger_temp(struct smb_charger *chg,
union power_supply_propval *val);
int smblib_get_prop_charger_temp_max(struct smb_charger *chg,
diff --git a/drivers/usb/pd/policy_engine.c b/drivers/usb/pd/policy_engine.c
index 26c91e0ce163..a72c874f19a5 100644
--- a/drivers/usb/pd/policy_engine.c
+++ b/drivers/usb/pd/policy_engine.c
@@ -299,7 +299,6 @@ struct usbpd {
enum power_supply_typec_mode typec_mode;
enum power_supply_type psy_type;
bool vbus_present;
- bool pd_allowed;
enum data_role current_dr;
enum power_role current_pr;
@@ -498,6 +497,7 @@ static void pd_send_hard_reset(struct usbpd *pd)
ret = pd_phy_signal(HARD_RESET_SIG, 5); /* tHardResetComplete */
if (!ret)
pd->hard_reset = true;
+ pd->in_pr_swap = false;
}
static void kick_sm(struct usbpd *pd, int ms)
@@ -828,7 +828,15 @@ static void usbpd_set_state(struct usbpd *pd, enum usbpd_state next_state)
}
}
- if (!pd->pd_allowed)
+ ret = power_supply_get_property(pd->usb_psy,
+ POWER_SUPPLY_PROP_PD_ALLOWED, &val);
+ if (ret) {
+ usbpd_err(&pd->dev, "Unable to read USB PROP_PD_ALLOWED: %d\n",
+ ret);
+ break;
+ }
+
+ if (!val.intval)
break;
/* Reset protocol layer */
@@ -906,8 +914,6 @@ static void usbpd_set_state(struct usbpd *pd, enum usbpd_state next_state)
break;
case PE_SNK_TRANSITION_TO_DEFAULT:
- pd->hard_reset = false;
-
if (pd->current_dr != DR_UFP) {
extcon_set_cable_state_(pd->extcon, EXTCON_USB_HOST, 0);
@@ -1455,6 +1461,7 @@ static void usbpd_sm(struct work_struct *w)
power_supply_set_property(pd->usb_psy,
POWER_SUPPLY_PROP_PD_IN_HARD_RESET, &val);
+ pd->in_pr_swap = false;
reset_vdm_state(pd);
if (pd->current_pr == PR_SINK)
@@ -1822,6 +1829,12 @@ static void usbpd_sm(struct work_struct *w)
break;
case PE_SNK_TRANSITION_TO_DEFAULT:
+ pd->hard_reset = false;
+
+ val.intval = 0;
+ power_supply_set_property(pd->usb_psy,
+ POWER_SUPPLY_PROP_PD_IN_HARD_RESET, &val);
+
if (pd->vbus_present) {
usbpd_set_state(pd, PE_SNK_STARTUP);
} else {
@@ -2036,41 +2049,41 @@ static int psy_changed(struct notifier_block *nb, unsigned long evt, void *ptr)
struct usbpd *pd = container_of(nb, struct usbpd, psy_nb);
union power_supply_propval val;
enum power_supply_typec_mode typec_mode;
- bool do_work = false;
int ret;
if (ptr != pd->usb_psy || evt != PSY_EVENT_PROP_CHANGED)
return 0;
ret = power_supply_get_property(pd->usb_psy,
- POWER_SUPPLY_PROP_PD_ALLOWED, &val);
+ POWER_SUPPLY_PROP_TYPEC_MODE, &val);
if (ret) {
- usbpd_err(&pd->dev, "Unable to read USB PROP_PD_ALLOWED: %d\n",
- ret);
+ usbpd_err(&pd->dev, "Unable to read USB TYPEC_MODE: %d\n", ret);
return ret;
}
- if (pd->pd_allowed != val.intval)
- do_work = true;
- pd->pd_allowed = val.intval;
+ typec_mode = val.intval;
ret = power_supply_get_property(pd->usb_psy,
- POWER_SUPPLY_PROP_PRESENT, &val);
+ POWER_SUPPLY_PROP_PE_START, &val);
if (ret) {
- usbpd_err(&pd->dev, "Unable to read USB PRESENT: %d\n", ret);
+ usbpd_err(&pd->dev, "Unable to read USB PROP_PE_START: %d\n",
+ ret);
return ret;
}
- pd->vbus_present = val.intval;
+ /* Don't proceed if PE_START=0 as other props may still change */
+ if (!val.intval && !pd->pd_connected &&
+ typec_mode != POWER_SUPPLY_TYPEC_NONE)
+ return 0;
ret = power_supply_get_property(pd->usb_psy,
- POWER_SUPPLY_PROP_TYPEC_MODE, &val);
+ POWER_SUPPLY_PROP_PRESENT, &val);
if (ret) {
- usbpd_err(&pd->dev, "Unable to read USB TYPEC_MODE: %d\n", ret);
+ usbpd_err(&pd->dev, "Unable to read USB PRESENT: %d\n", ret);
return ret;
}
- typec_mode = val.intval;
+ pd->vbus_present = val.intval;
ret = power_supply_get_property(pd->usb_psy,
POWER_SUPPLY_PROP_TYPE, &val);
@@ -2079,91 +2092,87 @@ static int psy_changed(struct notifier_block *nb, unsigned long evt, void *ptr)
return ret;
}
- if (pd->psy_type != val.intval)
- do_work = true;
pd->psy_type = val.intval;
+ if (pd->typec_mode == typec_mode)
+ return 0;
+
+ pd->typec_mode = typec_mode;
+
usbpd_dbg(&pd->dev, "typec mode:%d present:%d type:%d orientation:%d\n",
typec_mode, pd->vbus_present, pd->psy_type,
usbpd_get_plug_orientation(pd));
- if (pd->typec_mode != typec_mode) {
- pd->typec_mode = typec_mode;
- do_work = true;
-
- switch (typec_mode) {
- /* Disconnect */
- case POWER_SUPPLY_TYPEC_NONE:
- if (pd->in_pr_swap) {
- usbpd_dbg(&pd->dev, "Ignoring disconnect due to PR swap\n");
- do_work = false;
- }
+ switch (typec_mode) {
+ /* Disconnect */
+ case POWER_SUPPLY_TYPEC_NONE:
+ if (pd->in_pr_swap) {
+ usbpd_dbg(&pd->dev, "Ignoring disconnect due to PR swap\n");
+ return 0;
+ }
- /*
- * Workaround for PMIC HW bug.
- *
- * During hard reset when VBUS goes to 0 the CC logic
- * will report this as a disconnection. In those cases
- * it can be ignored, however the downside is that
- * pd->hard_reset can be momentarily true even when a
- * non-PD capable source is attached, and can't be
- * distinguished from a physical disconnect. In that
- * case, allow for the common case of disconnecting
- * from an SDP.
- *
- * The less common case is a PD-capable SDP which will
- * result in a hard reset getting treated like a
- * disconnect. We can live with this until the HW bug
- * is fixed: in which disconnection won't be reported
- * on VBUS loss alone unless pullup is also removed
- * from CC.
- */
- if (pd->psy_type != POWER_SUPPLY_TYPE_USB &&
- pd->current_state ==
- PE_SNK_TRANSITION_TO_DEFAULT) {
- usbpd_dbg(&pd->dev, "Ignoring disconnect due to hard reset\n");
- do_work = false;
- }
+ /*
+ * Workaround for PMIC HW bug.
+ *
+ * During hard reset when VBUS goes to 0 the CC logic
+ * will report this as a disconnection. In those cases
+ * it can be ignored, however the downside is that
+ * pd->hard_reset can be momentarily true even when a
+ * non-PD capable source is attached, and can't be
+ * distinguished from a physical disconnect. In that
+ * case, allow for the common case of disconnecting
+ * from an SDP.
+ *
+ * The less common case is a PD-capable SDP which will
+ * result in a hard reset getting treated like a
+ * disconnect. We can live with this until the HW bug
+ * is fixed: in which disconnection won't be reported
+ * on VBUS loss alone unless pullup is also removed
+ * from CC.
+ */
+ if (pd->psy_type != POWER_SUPPLY_TYPE_USB &&
+ pd->current_state ==
+ PE_SNK_TRANSITION_TO_DEFAULT) {
+ usbpd_dbg(&pd->dev, "Ignoring disconnect due to hard reset\n");
+ return 0;
+ }
- break;
+ break;
- /* Sink states */
- case POWER_SUPPLY_TYPEC_SOURCE_DEFAULT:
- case POWER_SUPPLY_TYPEC_SOURCE_MEDIUM:
- case POWER_SUPPLY_TYPEC_SOURCE_HIGH:
- usbpd_info(&pd->dev, "Type-C Source (%s) connected\n",
- src_current(typec_mode));
- pd->current_pr = PR_SINK;
- pd->in_pr_swap = false;
- break;
+ /* Sink states */
+ case POWER_SUPPLY_TYPEC_SOURCE_DEFAULT:
+ case POWER_SUPPLY_TYPEC_SOURCE_MEDIUM:
+ case POWER_SUPPLY_TYPEC_SOURCE_HIGH:
+ usbpd_info(&pd->dev, "Type-C Source (%s) connected\n",
+ src_current(typec_mode));
+ pd->current_pr = PR_SINK;
+ pd->in_pr_swap = false;
+ break;
- /* Source states */
- case POWER_SUPPLY_TYPEC_SINK_POWERED_CABLE:
- case POWER_SUPPLY_TYPEC_SINK:
- usbpd_info(&pd->dev, "Type-C Sink%s connected\n",
- typec_mode == POWER_SUPPLY_TYPEC_SINK ?
- "" : " (powered)");
- pd->current_pr = PR_SRC;
- pd->in_pr_swap = false;
- break;
+ /* Source states */
+ case POWER_SUPPLY_TYPEC_SINK_POWERED_CABLE:
+ case POWER_SUPPLY_TYPEC_SINK:
+ usbpd_info(&pd->dev, "Type-C Sink%s connected\n",
+ typec_mode == POWER_SUPPLY_TYPEC_SINK ?
+ "" : " (powered)");
+ pd->current_pr = PR_SRC;
+ pd->in_pr_swap = false;
+ break;
- case POWER_SUPPLY_TYPEC_SINK_DEBUG_ACCESSORY:
- usbpd_info(&pd->dev, "Type-C Debug Accessory connected\n");
- break;
- case POWER_SUPPLY_TYPEC_SINK_AUDIO_ADAPTER:
- usbpd_info(&pd->dev, "Type-C Analog Audio Adapter connected\n");
- break;
- default:
- usbpd_warn(&pd->dev, "Unsupported typec mode:%d\n",
- typec_mode);
- break;
- }
+ case POWER_SUPPLY_TYPEC_SINK_DEBUG_ACCESSORY:
+ usbpd_info(&pd->dev, "Type-C Debug Accessory connected\n");
+ break;
+ case POWER_SUPPLY_TYPEC_SINK_AUDIO_ADAPTER:
+ usbpd_info(&pd->dev, "Type-C Analog Audio Adapter connected\n");
+ break;
+ default:
+ usbpd_warn(&pd->dev, "Unsupported typec mode:%d\n",
+ typec_mode);
+ break;
}
- /* only queue state machine if CC state or PD_ALLOWED changes */
- if (do_work)
- kick_sm(pd, 0);
-
+ /* queue state machine due to CC state change */
+ kick_sm(pd, 0);
return 0;
}
diff --git a/include/linux/power_supply.h b/include/linux/power_supply.h
index a8ccecf5799a..18e1a979db76 100644
--- a/include/linux/power_supply.h
+++ b/include/linux/power_supply.h
@@ -224,6 +224,7 @@ enum power_supply_property {
POWER_SUPPLY_PROP_CHARGER_TEMP_MAX,
POWER_SUPPLY_PROP_PARALLEL_DISABLE,
POWER_SUPPLY_PROP_PARALLEL_PERCENT,
+ POWER_SUPPLY_PROP_PE_START,
/* Local extensions of type int64_t */
POWER_SUPPLY_PROP_CHARGE_COUNTER_EXT,
/* Properties of type `const char *' */
diff --git a/kernel/sched/hmp.c b/kernel/sched/hmp.c
index b3dad1289ed4..7039eb8f1e63 100644
--- a/kernel/sched/hmp.c
+++ b/kernel/sched/hmp.c
@@ -201,7 +201,7 @@ int sched_update_freq_max_load(const cpumask_t *cpumask)
entry = &max_load->freqs[i];
freq = costs[i].freq;
hpct = get_freq_max_load(cpu, freq);
- if (hpct <= 0 && hpct > 100)
+ if (hpct <= 0 || hpct > 100)
hpct = 100;
hfreq = div64_u64((u64)freq * hpct, 100);
entry->hdemand =
diff --git a/sound/usb/usb_audio_qmi_svc.c b/sound/usb/usb_audio_qmi_svc.c
index 8337d11bad12..3a108eba3b01 100644
--- a/sound/usb/usb_audio_qmi_svc.c
+++ b/sound/usb/usb_audio_qmi_svc.c
@@ -50,7 +50,7 @@
#define IOVA_XFER_RING_MAX (IOVA_XFER_BUF_BASE - PAGE_SIZE)
#define IOVA_XFER_BUF_MAX (0xfffff000 - PAGE_SIZE)
-#define MAX_XFER_BUFF_LEN (2 * PAGE_SIZE)
+#define MAX_XFER_BUFF_LEN (24 * PAGE_SIZE)
struct iova_info {
struct list_head list;