Merge "defconfig: msm: Enable CONFIG_DM_BOW for SDM670/710"
diff --git a/Documentation/devicetree/bindings/usb/dwc3.txt b/Documentation/devicetree/bindings/usb/dwc3.txt
index 83ecdc7..20abd3d 100644
--- a/Documentation/devicetree/bindings/usb/dwc3.txt
+++ b/Documentation/devicetree/bindings/usb/dwc3.txt
@@ -63,6 +63,7 @@
during bus suspend.
- snps,usb3-u1u2-disable: If present, disable U1U2 low power modes in Superspeed mode
- snps,usb2-l1-disable: If present, disable L1 low power modes in Highspeed mode
+ - normal-eps-in-gsi-mode: If present, two normal EPS (1 In, 1 Out) can be used in GSI mode
This is usually a subnode to DWC3 glue to which it is connected.
diff --git a/arch/arm/boot/dts/qcom/sa415m-ttp.dtsi b/arch/arm/boot/dts/qcom/sa415m-ttp.dtsi
index e8fdc08..27d4437 100644
--- a/arch/arm/boot/dts/qcom/sa415m-ttp.dtsi
+++ b/arch/arm/boot/dts/qcom/sa415m-ttp.dtsi
@@ -44,6 +44,36 @@
enable-active-high;
gpio = <&tlmm 71 GPIO_ACTIVE_HIGH>;
};
+ cnss_pcie: qcom,cnss {
+ compatible = "qcom,cnss";
+ reg = <0x10000000 0x10000000>,
+ <0x20000000 0x10000>;
+ reg-names = "smmu_iova_base", "smmu_iova_ipa";
+
+ wlan-en-gpio = <&tlmm 52 0>;
+ vdd-wlan-supply = <&vreg_wlan>;
+ vdd-wlan-xtal-supply = <&pmxpoorwills_l6>;
+ vdd-wlan-io-supply = <&pmxpoorwills_l6>;
+ qcom,notify-modem-status;
+ pinctrl-names = "wlan_en_active", "wlan_en_sleep";
+ pinctrl-0 = <&cnss_wlan_en_active>;
+ pinctrl-1 = <&cnss_wlan_en_sleep>;
+ qcom,wlan-rc-num = <0>;
+ qcom,wlan-ramdump-dynamic = <0x200000>;
+ qcom,smmu-s1-enable;
+ qcom,msm-bus,name = "msm-cnss";
+ qcom,msm-bus,num-cases = <4>;
+ qcom,msm-bus,num-paths = <2>;
+ qcom,msm-bus,vectors-KBps =
+ <45 512 0 0>, <1 512 0 0>,
+ /* Upto 200 Mbps */
+ <45 512 41421 655360>, <1 512 41421 655360>,
+ /* Upto 400 Mbps */
+ <45 512 98572 655360>, <1 512 98572 1600000>,
+ /* Upto 800 Mbps */
+ <45 512 207108 1146880>, <1 512 207108 3124992>;
+
+ };
};
&i2c_3 {
diff --git a/arch/arm/configs/sdxpoorwills-auto-perf_defconfig b/arch/arm/configs/sdxpoorwills-auto-perf_defconfig
index 1af9a91..b04fd97 100644
--- a/arch/arm/configs/sdxpoorwills-auto-perf_defconfig
+++ b/arch/arm/configs/sdxpoorwills-auto-perf_defconfig
@@ -180,6 +180,7 @@
CONFIG_RFKILL=y
CONFIG_IPC_ROUTER=y
CONFIG_IPC_ROUTER_SECURITY=y
+CONFIG_IPC_ROUTER_NODE_ID=2
CONFIG_REGMAP_ALLOW_WRITE_DEBUGFS=y
CONFIG_DMA_CMA=y
CONFIG_CMA_SIZE_MBYTES=12
diff --git a/arch/arm/configs/sdxpoorwills-auto_defconfig b/arch/arm/configs/sdxpoorwills-auto_defconfig
index 572c46b..3d0cca3 100644
--- a/arch/arm/configs/sdxpoorwills-auto_defconfig
+++ b/arch/arm/configs/sdxpoorwills-auto_defconfig
@@ -181,6 +181,7 @@
CONFIG_RFKILL=y
CONFIG_IPC_ROUTER=y
CONFIG_IPC_ROUTER_SECURITY=y
+CONFIG_IPC_ROUTER_NODE_ID=2
CONFIG_REGMAP_ALLOW_WRITE_DEBUGFS=y
CONFIG_DMA_CMA=y
CONFIG_CMA_SIZE_MBYTES=12
diff --git a/arch/arm/mach-qcom/board-sdm429.c b/arch/arm/mach-qcom/board-sdm429.c
index 6bdf0f4..3638c37 100644
--- a/arch/arm/mach-qcom/board-sdm429.c
+++ b/arch/arm/mach-qcom/board-sdm429.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2018, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2018-2019, The Linux Foundation. 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
@@ -18,6 +18,7 @@
static const char *sdm429_dt_match[] __initconst = {
"qcom,sdm429",
"qcom,sda429",
+ "qcom,sdm429w",
NULL
};
diff --git a/arch/arm64/boot/dts/qcom/msm8937-smp2p.dtsi b/arch/arm64/boot/dts/qcom/msm8937-smp2p.dtsi
index d5537e9..7b6d4d1 100644
--- a/arch/arm64/boot/dts/qcom/msm8937-smp2p.dtsi
+++ b/arch/arm64/boot/dts/qcom/msm8937-smp2p.dtsi
@@ -158,6 +158,21 @@
gpios = <&smp2pgpio_smp2p_2_out 0 0>;
};
+ smp2pgpio_sleepstate_2_out: qcom,smp2pgpio-sleepstate-gpio-2-out {
+ compatible = "qcom,smp2pgpio";
+ qcom,entry-name = "sleepstate";
+ qcom,remote-pid = <2>;
+ gpio-controller;
+ #gpio-cells = <2>;
+ interrupt-controller;
+ #interrupt-cells = <2>;
+ };
+
+ qcom,smp2pgpio-sleepstate-2-out {
+ compatible = "qcom,smp2pgpio-sleepstate-out";
+ gpios = <&smp2pgpio_sleepstate_2_out 0 0>;
+ };
+
/* ssr - inbound entry from mss. */
smp2pgpio_ssr_smp2p_1_in: qcom,smp2pgpio-ssr-smp2p-1-in {
compatible = "qcom,smp2pgpio";
diff --git a/arch/arm64/boot/dts/qcom/sdm429w-regulator.dtsi b/arch/arm64/boot/dts/qcom/sdm429w-regulator.dtsi
index 0a06e2da..b4dd41e 100644
--- a/arch/arm64/boot/dts/qcom/sdm429w-regulator.dtsi
+++ b/arch/arm64/boot/dts/qcom/sdm429w-regulator.dtsi
@@ -111,7 +111,7 @@
status = "okay";
S5A: pm660_s5: regulator-s5 {
regulator-min-microvolt = <1040000>;
- regulator-max-microvolt = <1350000>;
+ regulator-max-microvolt = <1420000>;
qcom,init-voltage = <1040000>;
status = "okay";
};
diff --git a/arch/arm64/boot/dts/qcom/sdm845-camera-sensor-rb3.dtsi b/arch/arm64/boot/dts/qcom/sdm845-camera-sensor-rb3.dtsi
index 8aac76e..8f25cb0 100644
--- a/arch/arm64/boot/dts/qcom/sdm845-camera-sensor-rb3.dtsi
+++ b/arch/arm64/boot/dts/qcom/sdm845-camera-sensor-rb3.dtsi
@@ -139,30 +139,30 @@
cam_clk-supply = <&titan_top_gdsc>;
regulator-names = "cam_vio", "cam_clk";
rgltr-cntrl-support;
- rgltr-min-voltage = <1800000 0>;
- rgltr-max-voltage = <1800000 0>;
- rgltr-load-current = <80000 0>;
+ rgltr-min-voltage = <0 0>;
+ rgltr-max-voltage = <0 0>;
+ rgltr-load-current = <0 0>;
gpio-no-mux = <0>;
pinctrl-names = "cam_default", "cam_suspend";
- pinctrl-0 = <&cam_sensor_mclk0_active
+ pinctrl-0 = <&cam_sensor_mclk2_active
&cam_sensor_rear4_active>;
- pinctrl-1 = <&cam_sensor_mclk0_suspend
+ pinctrl-1 = <&cam_sensor_mclk2_suspend
&cam_sensor_rear4_suspend>;
- gpios = <&tlmm 13 0>,
+ gpios = <&tlmm 15 0>,
<&tlmm 12 0>,
<&tlmm 69 0>;
gpio-reset = <1>;
gpio-custom1 = <2>;
gpio-req-tbl-num = <0 1 2>;
gpio-req-tbl-flags = <1 0 0>;
- gpio-req-tbl-label = "CAMIF_MCLK0",
+ gpio-req-tbl-label = "CAMIF_MCLK4",
"CAM_RESET4",
"CAM_CUSTOM4";
sensor-position = <0>;
sensor-mode = <0>;
cci-master = <1>;
status = "ok";
- clocks = <&clock_camcc CAM_CC_MCLK0_CLK>;
+ clocks = <&clock_camcc CAM_CC_MCLK2_CLK>;
clock-names = "cam_clk";
clock-cntl-level = "turbo";
clock-rates = <24000000>;
@@ -261,9 +261,9 @@
cam_clk-supply = <&titan_top_gdsc>;
regulator-names = "cam_vio", "cam_clk";
rgltr-cntrl-support;
- rgltr-min-voltage = <1800000 0>;
- rgltr-max-voltage = <1800000 0>;
- rgltr-load-current = <100000 0>;
+ rgltr-min-voltage = <0 0>;
+ rgltr-max-voltage = <0 0>;
+ rgltr-load-current = <0 0>;
gpio-no-mux = <0>;
pinctrl-names = "cam_default", "cam_suspend";
pinctrl-0 = <&cam_sensor_mclk3_active
@@ -286,10 +286,10 @@
clock-rates = <24000000>;
};
- qcom,cam-sensor@4 {
- cell-index = <4>;
+ qcom,cam-sensor@6 {
+ cell-index = <6>;
compatible = "qcom,cam-sensor";
- reg = <0x4>;
+ reg = <0x6>;
csiphy-sd-index = <2>;
sensor-position-roll = <270>;
sensor-position-pitch = <0>;
@@ -303,29 +303,29 @@
cam_clk-supply = <&titan_top_gdsc>;
regulator-names = "cam_vio", "cam_clk";
rgltr-cntrl-support;
- rgltr-min-voltage = <1800000 0>;
- rgltr-max-voltage = <1800000 0>;
- rgltr-load-current = <80000 0>;
+ rgltr-min-voltage = <0 0>;
+ rgltr-max-voltage = <0 0>;
+ rgltr-load-current = <0 0>;
gpio-no-mux = <0>;
pinctrl-names = "cam_default", "cam_suspend";
- pinctrl-0 = <&cam_sensor_mclk0_active
+ pinctrl-0 = <&cam_sensor_mclk2_active
&cam_sensor_rear4_active>;
- pinctrl-1 = <&cam_sensor_mclk0_suspend
+ pinctrl-1 = <&cam_sensor_mclk2_suspend
&cam_sensor_rear4_suspend>;
- gpios = <&tlmm 13 0>,
+ gpios = <&tlmm 15 0>,
<&tlmm 12 0>,
<&tlmm 69 0>;
gpio-reset = <1>;
gpio-custom1 = <2>;
gpio-req-tbl-num = <0 1 2>;
gpio-req-tbl-flags = <1 0 0>;
- gpio-req-tbl-label = "CAMIF_MCLK0",
+ gpio-req-tbl-label = "CAMIF_MCLK4",
"CAM_RESET4",
"CAM_CUSTOM4";
sensor-mode = <0>;
cci-master = <1>;
status = "ok";
- clocks = <&clock_camcc CAM_CC_MCLK0_CLK>;
+ clocks = <&clock_camcc CAM_CC_MCLK2_CLK>;
clock-names = "cam_clk";
clock-cntl-level = "turbo";
clock-rates = <24000000>;
diff --git a/arch/arm64/boot/dts/qcom/sdm845-v2.1-rb3.dtsi b/arch/arm64/boot/dts/qcom/sdm845-v2.1-rb3.dtsi
index dd1188b..e1159d3 100644
--- a/arch/arm64/boot/dts/qcom/sdm845-v2.1-rb3.dtsi
+++ b/arch/arm64/boot/dts/qcom/sdm845-v2.1-rb3.dtsi
@@ -195,9 +195,8 @@
config {
pins = "gpio12","gpio69";
- bias-pull-down; /* PULL DOWN */
+ bias-disable; /* No PULL */
drive-strength = <2>; /* 2 MA */
- output-low;
};
};
};
diff --git a/arch/arm64/configs/sdm670-perf_defconfig b/arch/arm64/configs/sdm670-perf_defconfig
index d80e603..d75479e 100755
--- a/arch/arm64/configs/sdm670-perf_defconfig
+++ b/arch/arm64/configs/sdm670-perf_defconfig
@@ -37,7 +37,6 @@
# CONFIG_RD_LZ4 is not set
CONFIG_KALLSYMS_ALL=y
CONFIG_BPF_SYSCALL=y
-# CONFIG_MEMBARRIER is not set
CONFIG_EMBEDDED=y
# CONFIG_SLUB_DEBUG is not set
# CONFIG_COMPAT_BRK is not set
@@ -72,12 +71,12 @@
CONFIG_SWP_EMULATION=y
CONFIG_CP15_BARRIER_EMULATION=y
CONFIG_SETEND_EMULATION=y
+CONFIG_ARM64_SW_TTBR0_PAN=y
# CONFIG_ARM64_VHE is not set
CONFIG_RANDOMIZE_BASE=y
# CONFIG_EFI is not set
# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set
CONFIG_COMPAT=y
-CONFIG_PM_AUTOSLEEP=y
CONFIG_PM_WAKELOCKS=y
CONFIG_PM_WAKELOCKS_LIMIT=0
# CONFIG_PM_WAKELOCKS_GC is not set
@@ -94,6 +93,7 @@
CONFIG_PACKET=y
CONFIG_UNIX=y
CONFIG_XFRM_USER=y
+CONFIG_XFRM_INTERFACE=y
CONFIG_XFRM_STATISTICS=y
CONFIG_NET_KEY=y
CONFIG_INET=y
@@ -296,6 +296,7 @@
CONFIG_PPPOPNS=y
CONFIG_PPP_ASYNC=y
CONFIG_PPP_SYNC_TTY=y
+CONFIG_USB_RTL8152=y
CONFIG_USB_LAN78XX=y
CONFIG_USB_USBNET=y
CONFIG_WCNSS_MEM_PRE_ALLOC=y
diff --git a/arch/arm64/configs/sdm670_defconfig b/arch/arm64/configs/sdm670_defconfig
index 33deb51..1eea891 100755
--- a/arch/arm64/configs/sdm670_defconfig
+++ b/arch/arm64/configs/sdm670_defconfig
@@ -39,7 +39,6 @@
# CONFIG_RD_LZ4 is not set
CONFIG_KALLSYMS_ALL=y
CONFIG_BPF_SYSCALL=y
-# CONFIG_MEMBARRIER is not set
CONFIG_EMBEDDED=y
# CONFIG_COMPAT_BRK is not set
CONFIG_PROFILING=y
@@ -77,11 +76,11 @@
CONFIG_SWP_EMULATION=y
CONFIG_CP15_BARRIER_EMULATION=y
CONFIG_SETEND_EMULATION=y
+CONFIG_ARM64_SW_TTBR0_PAN=y
# CONFIG_ARM64_VHE is not set
CONFIG_RANDOMIZE_BASE=y
# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set
CONFIG_COMPAT=y
-CONFIG_PM_AUTOSLEEP=y
CONFIG_PM_WAKELOCKS=y
CONFIG_PM_WAKELOCKS_LIMIT=0
# CONFIG_PM_WAKELOCKS_GC is not set
@@ -99,6 +98,7 @@
CONFIG_PACKET=y
CONFIG_UNIX=y
CONFIG_XFRM_USER=y
+CONFIG_XFRM_INTERFACE=y
CONFIG_XFRM_STATISTICS=y
CONFIG_NET_KEY=y
CONFIG_INET=y
@@ -302,6 +302,7 @@
CONFIG_PPPOPNS=y
CONFIG_PPP_ASYNC=y
CONFIG_PPP_SYNC_TTY=y
+CONFIG_USB_RTL8152=y
CONFIG_USB_LAN78XX=y
CONFIG_USB_USBNET=y
CONFIG_WCNSS_MEM_PRE_ALLOC=y
diff --git a/arch/arm64/configs/sdm845-perf_defconfig b/arch/arm64/configs/sdm845-perf_defconfig
index 9e0c7a8..4529bfb 100755
--- a/arch/arm64/configs/sdm845-perf_defconfig
+++ b/arch/arm64/configs/sdm845-perf_defconfig
@@ -419,6 +419,7 @@
CONFIG_USB_EHCI_HCD_PLATFORM=y
CONFIG_USB_OHCI_HCD=y
CONFIG_USB_OHCI_HCD_PLATFORM=y
+CONFIG_USB_ACM=y
CONFIG_USB_STORAGE=y
CONFIG_USB_DWC3=y
CONFIG_USB_DWC3_MSM=y
diff --git a/arch/arm64/configs/sdm845_defconfig b/arch/arm64/configs/sdm845_defconfig
index 99b464a..c063564 100755
--- a/arch/arm64/configs/sdm845_defconfig
+++ b/arch/arm64/configs/sdm845_defconfig
@@ -423,6 +423,7 @@
CONFIG_USB_EHCI_HCD_PLATFORM=y
CONFIG_USB_OHCI_HCD=y
CONFIG_USB_OHCI_HCD_PLATFORM=y
+CONFIG_USB_ACM=y
CONFIG_USB_STORAGE=y
CONFIG_USB_DWC3=y
CONFIG_USB_DWC3_MSM=y
diff --git a/drivers/media/platform/msm/camera_v3/cam_icp/icp_hw/icp_hw_mgr/cam_icp_hw_mgr.c b/drivers/media/platform/msm/camera_v3/cam_icp/icp_hw/icp_hw_mgr/cam_icp_hw_mgr.c
index 2b764d1..cfc474a 100644
--- a/drivers/media/platform/msm/camera_v3/cam_icp/icp_hw/icp_hw_mgr/cam_icp_hw_mgr.c
+++ b/drivers/media/platform/msm/camera_v3/cam_icp/icp_hw/icp_hw_mgr/cam_icp_hw_mgr.c
@@ -4686,6 +4686,13 @@
return -EFAULT;
}
+ /* To make sure num_out_res is same as allocated */
+ if (ctx_data->icp_dev_acquire_info->num_out_res !=
+ icp_dev_acquire_info.num_out_res) {
+ CAM_ERR(CAM_ICP, "num_out_res got changed");
+ return -EFAULT;
+ }
+
CAM_DBG(CAM_ICP, "%x %x %x %x %x %x %x",
ctx_data->icp_dev_acquire_info->dev_type,
ctx_data->icp_dev_acquire_info->in_res.format,
diff --git a/drivers/media/platform/msm/camera_v3/cam_sensor_module/cam_eeprom/cam_eeprom_core.c b/drivers/media/platform/msm/camera_v3/cam_sensor_module/cam_eeprom/cam_eeprom_core.c
index 8f59ca3..06d6bd4 100644
--- a/drivers/media/platform/msm/camera_v3/cam_sensor_module/cam_eeprom/cam_eeprom_core.c
+++ b/drivers/media/platform/msm/camera_v3/cam_sensor_module/cam_eeprom/cam_eeprom_core.c
@@ -439,17 +439,32 @@
else if (cmm_hdr->cmd_type == CAMERA_SENSOR_CMD_TYPE_WAIT)
validate_size = sizeof(struct cam_cmd_unconditional_wait);
- if (remain_buf_len < validate_size) {
+ if (remain_buf_len < validate_size ||
+ *num_map >= (MSM_EEPROM_MAX_MEM_MAP_CNT *
+ MSM_EEPROM_MEMORY_MAP_MAX_SIZE)) {
CAM_ERR(CAM_EEPROM, "not enough buffer");
return -EINVAL;
}
switch (cmm_hdr->cmd_type) {
case CAMERA_SENSOR_CMD_TYPE_I2C_RNDM_WR:
i2c_random_wr = (struct cam_cmd_i2c_random_wr *)cmd_buf;
+
+ if (i2c_random_wr->header.count == 0 ||
+ i2c_random_wr->header.count >= MSM_EEPROM_MAX_MEM_MAP_CNT ||
+ (size_t)*num_map >= ((MSM_EEPROM_MAX_MEM_MAP_CNT *
+ MSM_EEPROM_MEMORY_MAP_MAX_SIZE) -
+ i2c_random_wr->header.count)) {
+ CAM_ERR(CAM_EEPROM, "OOB Error");
+ return -EINVAL;
+ }
cmd_length_in_bytes = sizeof(struct cam_cmd_i2c_random_wr) +
((i2c_random_wr->header.count - 1) *
sizeof(struct i2c_random_wr_payload));
+ if (cmd_length_in_bytes > remain_buf_len) {
+ CAM_ERR(CAM_EEPROM, "Not enough buffer remaining");
+ return -EINVAL;
+ }
for (cnt = 0; cnt < (i2c_random_wr->header.count);
cnt++) {
map[*num_map + cnt].page.addr =
@@ -472,6 +487,11 @@
i2c_cont_rd = (struct cam_cmd_i2c_continuous_rd *)cmd_buf;
cmd_length_in_bytes = sizeof(struct cam_cmd_i2c_continuous_rd);
+ if (i2c_cont_rd->header.count >= U32_MAX - data->num_data) {
+ CAM_ERR(CAM_EEPROM,
+ "int overflow on eeprom memory block");
+ return -EINVAL;
+ }
map[*num_map].mem.addr = i2c_cont_rd->reg_addr;
map[*num_map].mem.addr_type = i2c_cont_rd->header.addr_type;
map[*num_map].mem.data_type = i2c_cont_rd->header.data_type;
diff --git a/drivers/usb/dwc3/core.c b/drivers/usb/dwc3/core.c
index 02839e2..146fe3e 100755
--- a/drivers/usb/dwc3/core.c
+++ b/drivers/usb/dwc3/core.c
@@ -1284,6 +1284,8 @@
"snps,usb3-u1u2-disable");
dwc->usb2_l1_disable = device_property_read_bool(dev,
"snps,usb2-l1-disable");
+ dwc->normal_eps_in_gsi_mode = device_property_read_bool(dev,
+ "normal-eps-in-gsi-mode");
if (dwc->enable_bus_suspend) {
pm_runtime_set_autosuspend_delay(dev, 500);
pm_runtime_use_autosuspend(dev);
diff --git a/drivers/usb/dwc3/core.h b/drivers/usb/dwc3/core.h
index 89d7ee0..80386d2 100644
--- a/drivers/usb/dwc3/core.h
+++ b/drivers/usb/dwc3/core.h
@@ -620,6 +620,7 @@
* @dbg_ep_events_ts: timestamp for previous event counters
* @fifo_depth: allocated TXFIFO depth
* @ep_cfg_init_params: Used by GSI EP to save EP_CFG init_cmd params
+ * @gsi_db_reg_addr: Address of GSI DB register mapped to this EP
*/
struct dwc3_ep {
struct usb_ep endpoint;
@@ -676,6 +677,7 @@
struct timespec dbg_ep_events_ts;
int fifo_depth;
struct dwc3_gadget_ep_cmd_params ep_cfg_init_params;
+ void __iomem *gsi_db_reg_addr;
};
enum dwc3_phy {
@@ -989,6 +991,8 @@
* @create_reg_debugfs: create debugfs entry to allow dwc3 register dump
* @xhci_imod_value: imod value to use with xhci
* @core_id: usb core id to differentiate different controller
+ * @normal_eps_in_gsi_mode: if true, two normal EPS (1 In, 1 Out) can be used in
+ * GSI mode
*/
struct dwc3 {
struct usb_ctrlrequest *ctrl_req;
@@ -1191,6 +1195,7 @@
u32 xhci_imod_value;
int core_id;
int retries_on_error;
+ bool normal_eps_in_gsi_mode;
};
/* -------------------------------------------------------------------------- */
diff --git a/drivers/usb/dwc3/dwc3-msm.c b/drivers/usb/dwc3/dwc3-msm.c
index af704b7..37c4e7e 100644
--- a/drivers/usb/dwc3/dwc3-msm.c
+++ b/drivers/usb/dwc3/dwc3-msm.c
@@ -203,7 +203,7 @@
"ENABLE_GSI", "UPDATE_XFER", "RING_DB",
"END_XFER", "GET_CH_INFO", "GET_XFER_IDX", "PREPARE_TRBS",
"FREE_TRBS", "SET_CLR_BLOCK_DBL", "CHECK_FOR_SUSP",
- "EP_DISABLE" };
+ "EP_DISABLE", "EP_UPDATE_DB" };
/* Input bits to state machine (mdwc->inputs) */
@@ -312,6 +312,8 @@
u64 dummy_gsi_db;
dma_addr_t dummy_gsi_db_dma;
+ u64 dummy_gevntcnt;
+ dma_addr_t dummy_gevntcnt_dma;
};
#define USB_HSPHY_3P3_VOL_MIN 3050000 /* uV */
@@ -864,6 +866,7 @@
int last_trb_index = 0;
struct dwc3 *dwc = dep->dwc;
struct usb_gsi_request *request = ch_info->ch_req;
+ struct dwc3_msm *mdwc = dev_get_drvdata(dwc->dev->parent);
/* Provide physical USB addresses for DEPCMD and GEVENTCNT registers */
ch_info->depcmd_low_addr = (u32)(dwc->reg_phys +
@@ -898,14 +901,28 @@
/* Store last 16 bits of LINK TRB address as per GSI hw requirement */
ch_info->last_trb_addr = (dwc3_trb_dma_offset(dep,
&dep->trb_pool[last_trb_index - 1]) & 0x0000FFFF);
- ch_info->gevntcount_low_addr = (u32)(dwc->reg_phys +
- DWC3_GEVNTCOUNT(ep->ep_intr_num));
- ch_info->gevntcount_hi_addr = 0;
+ dev_dbg(dwc->dev, "depcmd_laddr=%x last_trb_addr=%x\n",
+ ch_info->depcmd_low_addr, ch_info->last_trb_addr);
- dev_dbg(dwc->dev,
- "depcmd_laddr=%x last_trb_addr=%x gevtcnt_laddr=%x gevtcnt_haddr=%x",
- ch_info->depcmd_low_addr, ch_info->last_trb_addr,
- ch_info->gevntcount_low_addr, ch_info->gevntcount_hi_addr);
+ /*
+ * Check if NORMAL EP is used with GSI. In that case USB driver
+ * processes events and GSI shouldn't access GEVNTCOUNT(0) register.
+ */
+ if (ep->ep_intr_num) {
+ ch_info->gevntcount_low_addr = (u32)(dwc->reg_phys +
+ DWC3_GEVNTCOUNT(ep->ep_intr_num));
+ ch_info->gevntcount_hi_addr = 0;
+ dev_dbg(dwc->dev, "gevtcnt_laddr=%x gevtcnt_haddr=%x\n",
+ ch_info->gevntcount_low_addr, ch_info->gevntcount_hi_addr);
+ } else {
+ ch_info->gevntcount_low_addr = (u32)mdwc->dummy_gevntcnt_dma;
+ ch_info->gevntcount_hi_addr =
+ (u32)((u64)mdwc->dummy_gevntcnt_dma >> 32);
+ dev_dbg(dwc->dev, "Dummy GEVNTCNT Addr %pK: %llx %x (LSB)\n",
+ &mdwc->dummy_gevntcnt,
+ (unsigned long long)mdwc->dummy_gevntcnt_dma,
+ (u32)mdwc->dummy_gevntcnt_dma);
+ }
}
/*
@@ -929,8 +946,15 @@
}
memset(¶ms, 0, sizeof(params));
- params.param0 = GSI_TRB_ADDR_BIT_53_MASK | GSI_TRB_ADDR_BIT_55_MASK;
- params.param0 |= (ep->ep_intr_num << 16);
+ /*
+ * Check if NORMAL EP is used with GSI. In that case USB driver
+ * updates GSI doorbell and USB GSI wrapper h/w isn't involved.
+ */
+ if (ep->ep_intr_num) {
+ params.param0 = GSI_TRB_ADDR_BIT_53_MASK |
+ GSI_TRB_ADDR_BIT_55_MASK;
+ params.param0 |= (ep->ep_intr_num << 16);
+ }
params.param1 = lower_32_bits(dwc3_trb_dma_offset(dep,
&dep->trb_pool[0]));
cmd = DWC3_DEPCMD_STARTTRANSFER;
@@ -957,7 +981,18 @@
struct dwc3_ep *dep = to_dwc3_ep(ep);
struct dwc3 *dwc = dep->dwc;
struct dwc3_msm *mdwc = dev_get_drvdata(dwc->dev->parent);
- int n = ep->ep_intr_num - 1;
+ int n;
+
+ /*
+ * Check if NORMAL EP is used with GSI. In that case USB driver
+ * updates GSI doorbell and USB GSI wrapper h/w isn't involved.
+ */
+ if (!ep->ep_intr_num) {
+ dev_dbg(mdwc->dev, "%s: is no-op for normal EP\n", __func__);
+ return;
+ }
+
+ n = ep->ep_intr_num - 1;
dwc3_msm_write_reg(mdwc->base, GSI_RING_BASE_ADDR_L(n),
dwc3_trb_dma_offset(dep, &dep->trb_pool[0]));
@@ -991,6 +1026,21 @@
dwc3_msm_read_reg(mdwc->base, GSI_DBL_ADDR_L(n)));
}
+static void dwc3_msm_gsi_db_update(struct dwc3_ep *dep, dma_addr_t offset)
+{
+ struct dwc3 *dwc = dep->dwc;
+ struct dwc3_msm *mdwc = dev_get_drvdata(dwc->dev->parent);
+
+ if (!dep->gsi_db_reg_addr) {
+ dev_err(mdwc->dev, "Failed to update GSI DBL\n");
+ return;
+ }
+
+ writel_relaxed(offset, dep->gsi_db_reg_addr);
+ dev_dbg(mdwc->dev, "Writing TRB addr: %pa to %pK\n",
+ &offset, dep->gsi_db_reg_addr);
+}
+
/*
* Rings Doorbell for GSI Channel
*
@@ -1016,6 +1066,8 @@
return;
}
+ dep->gsi_db_reg_addr = gsi_dbl_address_lsb;
+
gsi_dbl_address_msb = devm_ioremap_nocache(mdwc->dev,
request->db_reg_phs_addr_msb, sizeof(u32));
if (!gsi_dbl_address_msb) {
@@ -1399,6 +1451,15 @@
struct dwc3 *dwc = dep->dwc;
struct dwc3_msm *mdwc = dev_get_drvdata(dwc->dev->parent);
+ /*
+ * Check if NORMAL EP is used with GSI. In that case USB driver
+ * updates GSI doorbell and USB GSI wrapper h/w isn't involved.
+ */
+ if (!ep->ep_intr_num) {
+ dev_dbg(mdwc->dev, "%s: is no-op for normal EP\n", __func__);
+ return;
+ }
+
dwc3_msm_write_reg_field(mdwc->base,
GSI_GENERAL_CFG_REG, GSI_CLK_EN_MASK, 1);
dwc3_msm_write_reg_field(mdwc->base,
@@ -1435,6 +1496,12 @@
else
gsi_enable_ep_events(ep);
+ /* Nothing to be done if NORMAL EP is used with GSI */
+ if (!ep->ep_intr_num) {
+ dev_dbg(mdwc->dev, "%s: is no-op for normal EP\n", __func__);
+ return;
+ }
+
dwc3_msm_write_reg_field(mdwc->base,
GSI_GENERAL_CFG_REG, BLOCK_GSI_WR_GO_MASK, block_db);
}
@@ -1490,6 +1557,7 @@
struct gsi_channel_info *ch_info;
bool block_db;
unsigned long flags;
+ dma_addr_t offset;
dbg_log_string("%s(%d):%s", ep->name, ep->ep_num, gsi_op_to_string(op));
@@ -1555,6 +1623,10 @@
case GSI_EP_OP_DISABLE:
ret = ep->ops->disable(ep);
break;
+ case GSI_EP_OP_UPDATE_DB:
+ offset = *(dma_addr_t *)op_data;
+ dwc3_msm_gsi_db_update(dep, offset);
+ break;
default:
dev_err(mdwc->dev, "%s: Invalid opcode GSI EP\n", __func__);
}
@@ -2065,6 +2137,19 @@
dev_err(dwc->dev, "failed to map dummy doorbell buffer\n");
mdwc->dummy_gsi_db_dma = (dma_addr_t)NULL;
}
+
+ /*
+ * Set-up dummy GEVNTCOUNT address to be passed on to GSI for
+ * normal (non HW-accelerated) EPs.
+ */
+ mdwc->dummy_gevntcnt_dma = dma_map_single(dwc->sysdev,
+ &mdwc->dummy_gevntcnt,
+ sizeof(mdwc->dummy_gevntcnt),
+ DMA_FROM_DEVICE);
+ if (dma_mapping_error(dwc->sysdev, mdwc->dummy_gevntcnt_dma)) {
+ dev_err(dwc->dev, "failed to map dummy geventcount\n");
+ mdwc->dummy_gevntcnt_dma = (dma_addr_t)NULL;
+ }
break;
case DWC3_GSI_EVT_BUF_SETUP:
dev_dbg(mdwc->dev, "DWC3_GSI_EVT_BUF_SETUP\n");
@@ -2138,6 +2223,12 @@
dma_free_coherent(dwc->sysdev, evt->length,
evt->buf, evt->dma);
}
+ if (mdwc->dummy_gevntcnt_dma) {
+ dma_unmap_single(dwc->sysdev, mdwc->dummy_gevntcnt_dma,
+ sizeof(mdwc->dummy_gevntcnt),
+ DMA_FROM_DEVICE);
+ mdwc->dummy_gevntcnt_dma = (dma_addr_t)NULL;
+ }
if (mdwc->dummy_gsi_db_dma) {
dma_unmap_single(dwc->sysdev, mdwc->dummy_gsi_db_dma,
sizeof(mdwc->dummy_gsi_db),
diff --git a/drivers/usb/dwc3/gadget.c b/drivers/usb/dwc3/gadget.c
index e8d270d..d0391b4 100644
--- a/drivers/usb/dwc3/gadget.c
+++ b/drivers/usb/dwc3/gadget.c
@@ -2390,8 +2390,8 @@
/* -------------------------------------------------------------------------- */
-#define NUM_GSI_OUT_EPS 1
-#define NUM_GSI_IN_EPS 2
+#define NUM_GSI_OUT_EPS(dwc) (dwc->normal_eps_in_gsi_mode ? 2 : 1)
+#define NUM_GSI_IN_EPS(dwc) (dwc->normal_eps_in_gsi_mode ? 3 : 2)
static int dwc3_gadget_init_hw_endpoints(struct dwc3 *dwc,
u8 num, u32 direction)
@@ -2399,13 +2399,13 @@
struct dwc3_ep *dep;
u8 i, gsi_ep_count, gsi_ep_index = 0;
- gsi_ep_count = NUM_GSI_OUT_EPS + NUM_GSI_IN_EPS;
+ gsi_ep_count = NUM_GSI_OUT_EPS(dwc) + NUM_GSI_IN_EPS(dwc);
/* OUT GSI EPs based on direction field */
if (gsi_ep_count && !direction)
- gsi_ep_count = NUM_GSI_OUT_EPS;
+ gsi_ep_count = NUM_GSI_OUT_EPS(dwc);
/* IN GSI EPs */
else if (gsi_ep_count && direction)
- gsi_ep_count = NUM_GSI_IN_EPS;
+ gsi_ep_count = NUM_GSI_IN_EPS(dwc);
for (i = 0; i < num; i++) {
u8 epnum = (i << 1) | (direction ? 1 : 0);
@@ -2710,6 +2710,25 @@
return 1;
}
+static void dwc3_gsi_ep_transfer_complete(struct dwc3 *dwc, struct dwc3_ep *dep)
+{
+ struct usb_ep *ep = &dep->endpoint;
+ struct dwc3_trb *trb;
+ dma_addr_t offset;
+
+ trb = &dep->trb_pool[dep->trb_dequeue];
+ while (trb->ctrl & DWC3_TRBCTL_LINK_TRB) {
+ dwc3_ep_inc_trb(&dep->trb_dequeue);
+ trb = &dep->trb_pool[dep->trb_dequeue];
+ }
+
+ if (!(trb->ctrl & DWC3_TRB_CTRL_HWO)) {
+ offset = dwc3_trb_dma_offset(dep, trb);
+ usb_gsi_ep_op(ep, (void *)&offset, GSI_EP_OP_UPDATE_DB);
+ dwc3_ep_inc_trb(&dep->trb_dequeue);
+ }
+}
+
static void dwc3_endpoint_transfer_complete(struct dwc3 *dwc,
struct dwc3_ep *dep, const struct dwc3_event_depevt *event)
{
@@ -2721,6 +2740,15 @@
if (event->status & DEPEVT_STATUS_BUSERR)
status = -ECONNRESET;
+ /*
+ * Check if NORMAL EP is used with GSI.
+ * In that case dwc3 driver recevies EP events from hardware and
+ * updates GSI doorbell with completed TRB.
+ */
+ if (dep->endpoint.ep_type == EP_TYPE_GSI) {
+ dwc3_gsi_ep_transfer_complete(dwc, dep);
+ return;
+ }
clean_busy = dwc3_cleanup_done_reqs(dwc, dep, event, status);
if (clean_busy && (!dep->endpoint.desc || is_xfer_complete ||
diff --git a/drivers/usb/gadget/function/f_gsi.c b/drivers/usb/gadget/function/f_gsi.c
index ffd5952..d58b20a 100644
--- a/drivers/usb/gadget/function/f_gsi.c
+++ b/drivers/usb/gadget/function/f_gsi.c
@@ -572,9 +572,11 @@
GSI_EP_OP_GET_CH_INFO);
log_event_dbg("%s: USB GSI IN OPS Completed", __func__);
- in_params->client =
- (gsi->prot_id != USB_PROT_DIAG_IPA) ? IPA_CLIENT_USB_CONS :
- IPA_CLIENT_USB_DPL_CONS;
+ if (gsi->prot_id != USB_PROT_DIAG_IPA)
+ in_params->client = (gsi->prot_id != USB_PROT_RMNET_V2X_IPA) ?
+ IPA_CLIENT_USB_CONS : IPA_CLIENT_USB2_CONS;
+ else
+ in_params->client = IPA_CLIENT_USB_DPL_CONS;
in_params->ipa_ep_cfg.mode.mode = IPA_BASIC;
in_params->teth_prot = (enum ipa_usb_teth_prot)gsi->prot_id;
in_params->gevntcount_low_addr =
@@ -627,7 +629,8 @@
usb_gsi_ep_op(d_port->out_ep, (void *)&gsi_channel_info,
GSI_EP_OP_GET_CH_INFO);
log_event_dbg("%s: USB GSI OUT OPS Completed", __func__);
- out_params->client = IPA_CLIENT_USB_PROD;
+ out_params->client = (gsi->prot_id != USB_PROT_RMNET_V2X_IPA) ?
+ IPA_CLIENT_USB_PROD : IPA_CLIENT_USB2_PROD;
out_params->ipa_ep_cfg.mode.mode = IPA_BASIC;
out_params->teth_prot = (enum ipa_usb_teth_prot)gsi->prot_id;
out_params->gevntcount_low_addr =
@@ -1521,6 +1524,7 @@
case GSI_MBIM_GPS_USB_STATUS:
val = atomic_read(&gsi->connected);
if (gsi->prot_id == USB_PROT_RMNET_IPA ||
+ gsi->prot_id == USB_PROT_RMNET_V2X_IPA ||
gsi->prot_id == USB_PROT_RMNET_ETHER)
val = gsi->rmnet_dtr_status;
@@ -1701,6 +1705,9 @@
case USB_PROT_RMNET_IPA:
cdev_name = GSI_RMNET_CTRL_NAME;
break;
+ case USB_PROT_RMNET_V2X_IPA:
+ cdev_name = GSI_RMNET_V2X_CTRL_NAME;
+ break;
case USB_PROT_RMNET_ETHER:
cdev_name = ETHER_RMNET_CTRL_NAME;
break;
@@ -2190,6 +2197,7 @@
| USB_CDC_REQ_SET_CONTROL_LINE_STATE:
line_state = (w_value & GSI_CTRL_DTR ? true : false);
if (gsi->prot_id == USB_PROT_RMNET_IPA ||
+ gsi->prot_id == USB_PROT_RMNET_V2X_IPA ||
gsi->prot_id == USB_PROT_RMNET_ETHER)
gsi->rmnet_dtr_status = line_state;
log_event_dbg("%s: USB_CDC_REQ_SET_CONTROL_LINE_STATE DTR:%d\n",
@@ -2293,6 +2301,7 @@
/* RNDIS, RMNET and DPL only support alt 0*/
if (intf == gsi->ctrl_id || gsi->prot_id == USB_PROT_RNDIS_IPA ||
gsi->prot_id == USB_PROT_RMNET_IPA ||
+ gsi->prot_id == USB_PROT_RMNET_V2X_IPA ||
gsi->prot_id == USB_PROT_DIAG_IPA ||
is_ext_prot_ether(gsi->prot_id))
return 0;
@@ -2414,6 +2423,7 @@
/* Control interface has only altsetting 0 */
if (intf == gsi->ctrl_id || gsi->prot_id == USB_PROT_RMNET_IPA ||
+ gsi->prot_id == USB_PROT_RMNET_V2X_IPA ||
gsi->prot_id == USB_PROT_RMNET_ETHER) {
if (alt != 0)
goto fail;
@@ -2450,6 +2460,7 @@
/* for rndis and rmnet alt is always 0 update alt accordingly */
if (gsi->prot_id == USB_PROT_RNDIS_IPA ||
gsi->prot_id == USB_PROT_RMNET_IPA ||
+ gsi->prot_id == USB_PROT_RMNET_V2X_IPA ||
gsi->prot_id == USB_PROT_DIAG_IPA ||
is_ext_prot_ether(gsi->prot_id))
alt = 1;
@@ -2480,9 +2491,11 @@
/* Configure EPs for GSI */
if (gsi->d_port.in_ep &&
- gsi->prot_id <= USB_PROT_DIAG_IPA) {
+ gsi->prot_id <= USB_PROT_RMNET_V2X_IPA) {
if (gsi->prot_id == USB_PROT_DIAG_IPA)
gsi->d_port.in_ep->ep_intr_num = 3;
+ else if (gsi->prot_id == USB_PROT_RMNET_V2X_IPA)
+ gsi->d_port.in_ep->ep_intr_num = 0;
else
gsi->d_port.in_ep->ep_intr_num = 2;
usb_gsi_ep_op(gsi->d_port.in_ep,
@@ -2491,8 +2504,11 @@
}
if (gsi->d_port.out_ep &&
- gsi->prot_id <= USB_PROT_DIAG_IPA) {
- gsi->d_port.out_ep->ep_intr_num = 1;
+ gsi->prot_id <= USB_PROT_RMNET_V2X_IPA) {
+ if (gsi->prot_id == USB_PROT_RMNET_V2X_IPA)
+ gsi->d_port.out_ep->ep_intr_num = 0;
+ else
+ gsi->d_port.out_ep->ep_intr_num = 1;
usb_gsi_ep_op(gsi->d_port.out_ep,
&gsi->d_port.out_request,
GSI_EP_OP_CONFIG);
@@ -2587,6 +2603,7 @@
rndis_uninit(gsi->params);
if (gsi->prot_id == USB_PROT_RMNET_IPA ||
+ gsi->prot_id == USB_PROT_RMNET_V2X_IPA ||
gsi->prot_id == USB_PROT_RMNET_ETHER)
gsi->rmnet_dtr_status = false;
@@ -2817,7 +2834,7 @@
info->data_nop_desc->bInterfaceNumber = gsi->data_id;
/* allocate instance-specific endpoints */
- if (info->fs_in_desc && gsi->prot_id <= USB_PROT_DIAG_IPA) {
+ if (info->fs_in_desc && gsi->prot_id <= USB_PROT_RMNET_V2X_IPA) {
ep = usb_ep_autoconfig_by_name(cdev->gadget,
info->fs_in_desc, info->in_epname);
if (!ep)
@@ -2835,7 +2852,7 @@
}
}
- if (info->fs_out_desc && gsi->prot_id <= USB_PROT_DIAG_IPA) {
+ if (info->fs_out_desc && gsi->prot_id <= USB_PROT_RMNET_V2X_IPA) {
ep = usb_ep_autoconfig_by_name(cdev->gadget,
info->fs_out_desc, info->out_epname);
if (!ep)
@@ -3011,6 +3028,7 @@
if (gsi->prot_id == USB_PROT_RMNET_IPA ||
+ gsi->prot_id == USB_PROT_RMNET_V2X_IPA ||
gsi->prot_id == USB_PROT_DIAG_IPA ||
is_ext_prot_ether(gsi->prot_id))
gsi->ctrl_id = -ENODEV;
@@ -3222,6 +3240,7 @@
}
break;
case USB_PROT_RMNET_IPA:
+ case USB_PROT_RMNET_V2X_IPA:
case USB_PROT_RMNET_ETHER:
info.string_defs = rmnet_gsi_string_defs;
info.data_desc = &rmnet_gsi_interface_desc;
@@ -3487,6 +3506,7 @@
gsi->function.strings = ecm_gsi_strings;
break;
case USB_PROT_RMNET_IPA:
+ case USB_PROT_RMNET_V2X_IPA:
case USB_PROT_RMNET_ETHER:
gsi->function.name = "rmnet";
gsi->function.strings = rmnet_gsi_strings;
@@ -3885,6 +3905,7 @@
switch (gsi->prot_id) {
case USB_PROT_RMNET_IPA:
+ case USB_PROT_RMNET_V2X_IPA:
case USB_PROT_RMNET_ETHER:
str = gsi->rmnet_dtr_status ? "connected" : "disconnected";
break;
diff --git a/drivers/usb/gadget/function/f_gsi.h b/drivers/usb/gadget/function/f_gsi.h
index b7e8fe8..02be58d 100644
--- a/drivers/usb/gadget/function/f_gsi.h
+++ b/drivers/usb/gadget/function/f_gsi.h
@@ -32,6 +32,7 @@
#include "configfs.h"
#define GSI_RMNET_CTRL_NAME "rmnet_ctrl"
+#define GSI_RMNET_V2X_CTRL_NAME "rmnet_v2x_ctrl"
#define GSI_MBIM_CTRL_NAME "android_mbim"
#define GSI_DPL_CTRL_NAME "dpl_ctrl"
#define ETHER_RMNET_CTRL_NAME "rmnet_ctrl0"
@@ -125,6 +126,7 @@
USB_PROT_RMNET_IPA,
USB_PROT_MBIM_IPA,
USB_PROT_DIAG_IPA,
+ USB_PROT_RMNET_V2X_IPA,
/* non-accelerated */
USB_PROT_RMNET_ETHER,
@@ -339,6 +341,8 @@
return USB_PROT_MBIM_IPA;
if (!strncasecmp(name, "dpl", MAX_INST_NAME_LEN))
return USB_PROT_DIAG_IPA;
+ if (!strncasecmp(name, "rmnet.v2x", MAX_INST_NAME_LEN))
+ return USB_PROT_RMNET_V2X_IPA;
if (!strncasecmp(name, "rmnet.ether", MAX_INST_NAME_LEN))
return USB_PROT_RMNET_ETHER;
if (!strncasecmp(name, "dpl.ether", MAX_INST_NAME_LEN))
diff --git a/drivers/usb/host/Kconfig b/drivers/usb/host/Kconfig
index 0e7cc71..d44905b 100644
--- a/drivers/usb/host/Kconfig
+++ b/drivers/usb/host/Kconfig
@@ -804,3 +804,9 @@
This option is of interest only to developers who need to validate
their USB hardware designs. It is not needed for normal use. If
unsure, say N.
+
+config USB_UPD720X
+ tristate "Support for Renesas UPD720X XHCI USB controller"
+ ---help---
+ Enables support for the USB Host controller present on the
+ Renesas UPD720X chipsets.
diff --git a/drivers/usb/host/Makefile b/drivers/usb/host/Makefile
index 6ef785b..fc6981a 100644
--- a/drivers/usb/host/Makefile
+++ b/drivers/usb/host/Makefile
@@ -82,3 +82,4 @@
obj-$(CONFIG_USB_HCD_SSB) += ssb-hcd.o
obj-$(CONFIG_USB_FOTG210_HCD) += fotg210-hcd.o
obj-$(CONFIG_USB_MAX3421_HCD) += max3421-hcd.o
+obj-$(CONFIG_USB_UPD720X) += xhci-fwdload.o
diff --git a/drivers/usb/host/pci-quirks.h b/drivers/usb/host/pci-quirks.h
index 6463fdb..38a91d8 100644
--- a/drivers/usb/host/pci-quirks.h
+++ b/drivers/usb/host/pci-quirks.h
@@ -15,6 +15,11 @@
void usb_enable_intel_xhci_ports(struct pci_dev *xhci_pdev);
void usb_disable_xhci_ports(struct pci_dev *xhci_pdev);
void sb800_prefetch(struct device *dev, int on);
+#ifdef CONFIG_USB_UPD720X
+void upd720x_finish_download(struct pci_dev *pDev);
+#else
+#define upd720x_finish_download(pDev)
+#endif
#else
struct pci_dev;
static inline void usb_amd_quirk_pll_disable(void) {}
@@ -23,6 +28,7 @@
static inline void usb_amd_dev_put(void) {}
static inline void usb_disable_xhci_ports(struct pci_dev *xhci_pdev) {}
static inline void sb800_prefetch(struct device *dev, int on) {}
+#define upd720x_finish_download(pDev)
#endif /* CONFIG_PCI */
#endif /* __LINUX_USB_PCI_QUIRKS_H */
diff --git a/drivers/usb/host/xhci-fwdload.c b/drivers/usb/host/xhci-fwdload.c
new file mode 100644
index 0000000..f214e03
--- /dev/null
+++ b/drivers/usb/host/xhci-fwdload.c
@@ -0,0 +1,228 @@
+/*
+ * Copyright (c) 2019 The Linux Foundation. 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/errno.h>
+#include <linux/time.h>
+#include <linux/firmware.h>
+#include <linux/pci.h>
+#include <linux/platform_device.h>
+#include <asm/dma-iommu.h>
+#include <linux/msm_dma_iommu_mapping.h>
+
+#define upd720x_firmware "K2026090.mem"
+
+#define UPD_PCI_F4 0xF4
+
+#define UPD_PCI_F4_FWDOWNLOADENABLE (0x0001)
+#define UPD_PCI_F4_FWDOWNLOADLOCK (0x0002)
+#define UPD_PCI_F4_SETDATA0 (0x0100)
+#define UPD_PCI_F4_SETDATA1 (0x0200)
+#define UPD_PCI_F4_RESULT (0x0070)
+
+#define UPD_PCI_F8 0xF8
+
+#define UPD_PCI_FC 0xFC
+
+enum SET_DATA {
+ SET_DATA_PAGE0,
+ SET_DATA_PAGE1
+};
+
+#define SMMU_BASE 0x10000000
+#define SMMU_SIZE 0x40000000
+
+struct firmware *fw_pointer;
+static struct dma_iommu_mapping *upd720x_smmu_init(struct device *dev)
+{
+ int rc = 0;
+ int atomic_ctx = 1;
+ int bypass_enable = 1;
+ struct dma_iommu_mapping *mapping = NULL;
+
+ mapping = arm_iommu_create_mapping(&platform_bus_type,
+ SMMU_BASE, SMMU_SIZE);
+ if (IS_ERR(mapping)) {
+ rc = PTR_ERR(mapping);
+ dev_err(dev, "create mapping failed, err = %d\n", rc);
+ return NULL;
+ }
+
+ rc = iommu_domain_set_attr(mapping->domain,
+ DOMAIN_ATTR_ATOMIC, &atomic_ctx);
+ if (rc) {
+ dev_err(dev, "Set atomic attribute to SMMU failed (%d)\n", rc);
+ arm_iommu_release_mapping(mapping);
+ return NULL;
+ }
+
+ rc = iommu_domain_set_attr(mapping->domain,
+ DOMAIN_ATTR_S1_BYPASS, &bypass_enable);
+ if (rc) {
+ dev_err(dev, "Set bypass attribute to SMMU failed (%d)\n", rc);
+ arm_iommu_release_mapping(mapping);
+ return NULL;
+ }
+
+ rc = arm_iommu_attach_device(dev, mapping);
+ if (rc) {
+ dev_err(dev, "arm_iommu_attach_device failed (%d)\n", rc);
+ arm_iommu_release_mapping(mapping);
+ return NULL;
+ }
+
+ pr_info("attached to IOMMU\n");
+ return mapping;
+}
+
+static void upd720x_smmu_deinit(struct device *dev)
+{
+ arm_iommu_detach_device(dev);
+ arm_iommu_release_mapping(to_dma_iommu_mapping(dev));
+}
+
+
+static int upd720x_download_enable(struct pci_dev *pDev)
+{
+ unsigned int read_data;
+ int result;
+
+ result = pci_read_config_dword(pDev, UPD_PCI_F4, &read_data);
+ pr_info("Set FW Download enable\n");
+ result = pci_write_config_dword(pDev, UPD_PCI_F4, read_data |
+ UPD_PCI_F4_FWDOWNLOADENABLE);
+ return result;
+}
+
+static int upd720x_download_lock(struct pci_dev *pDev)
+{
+ unsigned int read_data;
+ int result;
+
+ result = pci_read_config_dword(pDev, UPD_PCI_F4, &read_data);
+ pr_info("Set FW Download lock\n");
+ result = pci_write_config_dword(pDev, UPD_PCI_F4, read_data |
+ UPD_PCI_F4_FWDOWNLOADLOCK);
+ return result;
+}
+
+static int upd720x_set_data0(struct pci_dev *pDev)
+{
+ unsigned int read_data;
+ int result;
+
+ result = pci_read_config_dword(pDev, UPD_PCI_F4, &read_data);
+ result = pci_write_config_dword(pDev, UPD_PCI_F4,
+ (read_data & ~UPD_PCI_F4_SETDATA1) |
+ UPD_PCI_F4_SETDATA0);
+
+ return result;
+}
+
+static int upd720x_set_data1(struct pci_dev *pDev)
+{
+ unsigned int read_data;
+ int result;
+
+ result = pci_read_config_dword(pDev, UPD_PCI_F4, &read_data);
+ result = pci_write_config_dword(pDev, UPD_PCI_F4,
+ (read_data & ~UPD_PCI_F4_SETDATA0) |
+ UPD_PCI_F4_SETDATA1);
+
+ return result;
+}
+
+static int upd720x_download_clearcontrol(struct pci_dev *pDev)
+{
+ int read_buf;
+ int rc;
+
+ rc = pci_read_config_dword(pDev, UPD_PCI_F4, &read_buf);
+ if (rc == 0) {
+ rc = pci_write_config_dword(pDev, UPD_PCI_F4, read_buf &
+ ~UPD_PCI_F4_FWDOWNLOADENABLE);
+ }
+ return rc;
+}
+int upd720x_firmware_download(struct pci_dev *pDev,
+ unsigned char *pFWImage, unsigned int firmware_size)
+{
+ enum SET_DATA page = SET_DATA_PAGE0;
+ int offset;
+ unsigned int *image = (unsigned int *)pFWImage;
+ unsigned int fw_dwordsize = firmware_size /
+ (sizeof(unsigned int) / sizeof(unsigned char));
+
+ if ((firmware_size %
+ (sizeof(unsigned int) / sizeof(unsigned char))) != 0)
+ fw_dwordsize++;
+
+ if (upd720x_download_enable(pDev) == -EFAULT) {
+ pr_info("Set FW Download Enable is timeout");
+ return -EFAULT;
+ }
+
+ for (offset = 0; offset < fw_dwordsize; offset++) {
+ switch (page) {
+ case SET_DATA_PAGE0:
+ pci_write_config_dword(pDev, UPD_PCI_F8, image[offset]);
+
+ if (upd720x_set_data0(pDev) == -EFAULT)
+ return -EFAULT;
+ page = SET_DATA_PAGE1;
+ break;
+
+ case SET_DATA_PAGE1:
+ pci_write_config_dword(pDev, UPD_PCI_FC, image[offset]);
+ if (upd720x_set_data1(pDev) == -EFAULT)
+ return -EFAULT;
+ page = SET_DATA_PAGE0;
+ break;
+ default:
+ break;
+ }
+ }
+
+ if (upd720x_download_clearcontrol(pDev) == -EFAULT)
+ return -EFAULT;
+
+ if (upd720x_download_lock(pDev) == -EFAULT)
+ return -EFAULT;
+
+ return 0;
+}
+
+int upd720x_finish_download(struct pci_dev *pDev)
+{
+ int result = -EFAULT;
+ char *firmwarename = upd720x_firmware;
+ int lc;
+ int ret;
+
+ if (!upd720x_smmu_init(&pDev->dev))
+ return -EFAULT;
+
+ for (lc = 0; (lc < 2) && (fw_pointer == NULL); lc++) {
+ ret = request_firmware((const struct firmware **)&fw_pointer,
+ firmwarename, &pDev->bus->dev);
+ if (ret == 0) {
+ result = upd720x_firmware_download(pDev,
+ (unsigned char *)fw_pointer->data,
+ fw_pointer->size);
+ break;
+ }
+ result = ret;
+ }
+ return result;
+}
+
+
+
diff --git a/drivers/usb/host/xhci-pci.c b/drivers/usb/host/xhci-pci.c
index b514055..3e6c437 100644
--- a/drivers/usb/host/xhci-pci.c
+++ b/drivers/usb/host/xhci-pci.c
@@ -192,8 +192,10 @@
xhci->quirks |= XHCI_BROKEN_STREAMS;
}
if (pdev->vendor == PCI_VENDOR_ID_RENESAS &&
- pdev->device == 0x0014)
+ pdev->device == 0x0014) {
xhci->quirks |= XHCI_TRUST_TX_LENGTH;
+ upd720x_finish_download(pdev);
+ }
if (pdev->vendor == PCI_VENDOR_ID_RENESAS &&
pdev->device == 0x0015)
xhci->quirks |= XHCI_RESET_ON_RESUME;
diff --git a/include/linux/usb/gadget.h b/include/linux/usb/gadget.h
index 0267bed..418978e 100644
--- a/include/linux/usb/gadget.h
+++ b/include/linux/usb/gadget.h
@@ -67,6 +67,7 @@
GSI_EP_OP_SET_CLR_BLOCK_DBL,
GSI_EP_OP_CHECK_FOR_SUSPEND,
GSI_EP_OP_DISABLE,
+ GSI_EP_OP_UPDATE_DB,
};
/*
diff --git a/kernel/sched/fair.c b/kernel/sched/fair.c
index 6f7d15a..87e674b 100644
--- a/kernel/sched/fair.c
+++ b/kernel/sched/fair.c
@@ -3914,6 +3914,7 @@
{
struct sched_entity *left = __pick_first_entity(cfs_rq);
struct sched_entity *se;
+ bool strict_skip = false;
/*
* If curr is set we have to see if its left of the leftmost entity
@@ -3933,13 +3934,15 @@
if (se == curr) {
second = __pick_first_entity(cfs_rq);
+ if (sched_feat(STRICT_SKIP_BUDDY))
+ strict_skip = true;
} else {
second = __pick_next_entity(se);
if (!second || (curr && entity_before(curr, second)))
second = curr;
}
- if (second && (sched_feat(STRICT_SKIP_BUDDY) ||
+ if (second && (strict_skip ||
wakeup_preempt_entity(second, left) < 1))
se = second;
}