diff --git a/arch/arm64/boot/dts/qcom/qcs9100-ride-r3.dts b/arch/arm64/boot/dts/qcom/qcs9100-ride-r3.dts index 6c7fc881615092b91a804553a0e4568fa9b7ee92..279f051e75b60baa0620b9599be5184b72b9b176 100644 --- a/arch/arm64/boot/dts/qcom/qcs9100-ride-r3.dts +++ b/arch/arm64/boot/dts/qcom/qcs9100-ride-r3.dts @@ -7,9 +7,102 @@ #include "sa8775p-ride-r3.dts" #include "qcs9100-thermal.dtsi" +/delete-node/ &pil_adsp_mem; +/delete-node/ &pil_gdsp0_mem; +/delete-node/ &pil_gdsp1_mem; +/delete-node/ &pil_cdsp0_mem; +/delete-node/ &pil_gpu_mem; +/delete-node/ &pil_cdsp1_mem; +/delete-node/ &pil_cvp_mem; +/delete-node/ &pil_video_mem; +/delete-node/ &audio_mdf_mem; +/delete-node/ &trusted_apps_mem; + + / { model = "Qualcomm QCS9100 Ride Rev3"; compatible = "qcom,qcs9100-ride-r3", "qcom,qcs9100", "qcom,sa8775p"; qcom,msm-id = <667 0x10000>, <667 0x20000>; qcom,board-id = <0x20025 1>; + + reserved-memory { + #address-cells = <2>; + #size-cells = <2>; + ranges; + + gunyah_md_mem: gunyah-md@91a80000 { + reg = <0x0 0x91a80000 0x0 0x80000>; + no-map; + }; + + pil_adsp_mem: pil-adsp@95900000 { + reg = <0x0 0x95900000 0x0 0x1e00000>; + no-map; + }; + + q6_adsp_dtb_mem: q6-adsp-dtb@97700000 { + reg = <0x0 0x97700000 0x0 0x80000>; + no-map; + }; + + q6_gdsp0_dtb_mem: q6-gdsp0-dtb@97780000 { + reg = <0x0 0x97780000 0x0 0x80000>; + no-map; + }; + + pil_gdsp0_mem: pil-gdsp0@97800000 { + reg = <0x0 0x97800000 0x0 0x1e00000>; + no-map; + }; + + pil_gdsp1_mem: pil-gdsp1@99600000 { + reg = <0x0 0x99600000 0x0 0x1e00000>; + no-map; + }; + + q6_gdsp1_dtb_mem: q6-gdsp1-dtb@9b400000 { + reg = <0x0 0x9b400000 0x0 0x80000>; + no-map; + }; + + q6_cdsp0_dtb_mem: q6-cdsp0-dtb@9b480000 { + reg = <0x0 0x9b480000 0x0 0x80000>; + no-map; + }; + + pil_cdsp0_mem: pil-cdsp0@9b500000 { + reg = <0x0 0x9b500000 0x0 0x1e00000>; + no-map; + }; + + pil_gpu_mem: pil-gpu@9d300000 { + reg = <0x0 0x9d300000 0x0 0x2000>; + no-map; + }; + + q6_cdsp1_dtb_mem: q6-cdsp1-dtb@9d380000 { + reg = <0x0 0x9d380000 0x0 0x80000>; + no-map; + }; + + pil_cdsp1_mem: pil-cdsp1@9d400000 { + reg = <0x0 0x9d400000 0x0 0x1e00000>; + no-map; + }; + + pil_cvp_mem: pil-cvp@9f200000 { + reg = <0x0 0x9f200000 0x0 0x700000>; + no-map; + }; + + pil_video_mem: pil-video@9f900000 { + reg = <0x0 0x9f900000 0x0 0x1000000>; + no-map; + }; + + trusted_apps_mem: trusted-apps@d1900000 { + reg = <0x0 0xd1900000 0x0 0x1c00000>; + no-map; + }; + }; }; diff --git a/arch/arm64/boot/dts/qcom/qcs9100-ride.dts b/arch/arm64/boot/dts/qcom/qcs9100-ride.dts index e5e47f28990310f7e708bb5e83a5ad110105704f..b76a51c8ad948449f738c632ad46051015892113 100644 --- a/arch/arm64/boot/dts/qcom/qcs9100-ride.dts +++ b/arch/arm64/boot/dts/qcom/qcs9100-ride.dts @@ -7,9 +7,102 @@ #include "sa8775p-ride.dts" #include "qcs9100-thermal.dtsi" +/delete-node/ &pil_adsp_mem; +/delete-node/ &pil_gdsp0_mem; +/delete-node/ &pil_gdsp1_mem; +/delete-node/ &pil_cdsp0_mem; +/delete-node/ &pil_gpu_mem; +/delete-node/ &pil_cdsp1_mem; +/delete-node/ &pil_cvp_mem; +/delete-node/ &pil_video_mem; +/delete-node/ &audio_mdf_mem; +/delete-node/ &trusted_apps_mem; + + / { model = "Qualcomm QCS9100 Ride"; compatible = "qcom,qcs9100-ride", "qcom,qcs9100", "qcom,sa8775p"; qcom,msm-id = <667 0x10000>, <667 0x20000>; qcom,board-id = <0x10019 0>, <0x10025 1>; + + reserved-memory { + #address-cells = <2>; + #size-cells = <2>; + ranges; + + gunyah_md_mem: gunyah-md@91a80000 { + reg = <0x0 0x91a80000 0x0 0x80000>; + no-map; + }; + + pil_adsp_mem: pil-adsp@95900000 { + reg = <0x0 0x95900000 0x0 0x1e00000>; + no-map; + }; + + q6_adsp_dtb_mem: q6-adsp-dtb@97700000 { + reg = <0x0 0x97700000 0x0 0x80000>; + no-map; + }; + + q6_gdsp0_dtb_mem: q6-gdsp0-dtb@97780000 { + reg = <0x0 0x97780000 0x0 0x80000>; + no-map; + }; + + pil_gdsp0_mem: pil-gdsp0@97800000 { + reg = <0x0 0x97800000 0x0 0x1e00000>; + no-map; + }; + + pil_gdsp1_mem: pil-gdsp1@99600000 { + reg = <0x0 0x99600000 0x0 0x1e00000>; + no-map; + }; + + q6_gdsp1_dtb_mem: q6-gdsp1-dtb@9b400000 { + reg = <0x0 0x9b400000 0x0 0x80000>; + no-map; + }; + + q6_cdsp0_dtb_mem: q6-cdsp0-dtb@9b480000 { + reg = <0x0 0x9b480000 0x0 0x80000>; + no-map; + }; + + pil_cdsp0_mem: pil-cdsp0@9b500000 { + reg = <0x0 0x9b500000 0x0 0x1e00000>; + no-map; + }; + + pil_gpu_mem: pil-gpu@9d300000 { + reg = <0x0 0x9d300000 0x0 0x2000>; + no-map; + }; + + q6_cdsp1_dtb_mem: q6-cdsp1-dtb@9d380000 { + reg = <0x0 0x9d380000 0x0 0x80000>; + no-map; + }; + + pil_cdsp1_mem: pil-cdsp1@9d400000 { + reg = <0x0 0x9d400000 0x0 0x1e00000>; + no-map; + }; + + pil_cvp_mem: pil-cvp@9f200000 { + reg = <0x0 0x9f200000 0x0 0x700000>; + no-map; + }; + + pil_video_mem: pil-video@9f900000 { + reg = <0x0 0x9f900000 0x0 0x1000000>; + no-map; + }; + + trusted_apps_mem: trusted-apps@d1900000 { + reg = <0x0 0xd1900000 0x0 0x1c00000>; + no-map; + }; + }; }; diff --git a/drivers/hwmon/emc2305.c b/drivers/hwmon/emc2305.c index 29f0e4945f1924eabd30b055da16e596bc25ebef..4a1c22cbb07c6bedc9ee82057d842fca23b0c03a 100644 --- a/drivers/hwmon/emc2305.c +++ b/drivers/hwmon/emc2305.c @@ -3,6 +3,7 @@ * Hardware monitoring driver for EMC2305 fan controller * * Copyright (C) 2022 Nvidia Technologies Ltd. + * Copyright (c) 2024 Qualcomm Innovation Center, Inc. All rights reserved. */ #include <linux/err.h> @@ -530,6 +531,18 @@ static int emc2305_identify(struct device *dev) return 0; } + +static int emc2305_detect(struct i2c_client *client, struct i2c_board_info *info) +{ + struct i2c_adapter *adapter = client->adapter; + + if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA)) + return -ENODEV; + + strscpy(info->type, "emc2303", I2C_NAME_SIZE); + return 0; +} + static int emc2305_probe(struct i2c_client *client) { struct i2c_adapter *adapter = client->adapter; @@ -618,10 +631,27 @@ static struct i2c_driver emc2305_driver = { .probe = emc2305_probe, .remove = emc2305_remove, .id_table = emc2305_ids, + .detect = emc2305_detect, .address_list = emc2305_normal_i2c, }; -module_i2c_driver(emc2305_driver); +static struct i2c_board_info emc2305_i2c_info = { + I2C_BOARD_INFO("emc2303", 0x2c), +}; + +static int __init emc2305_init(void) +{ + i2c_register_board_info(1, &emc2305_i2c_info, 1); + return i2c_add_driver(&emc2305_driver); +} + +static void __exit emc2305_exit(void) +{ + i2c_del_driver(&emc2305_driver); +} + +module_init(emc2305_init); +module_exit(emc2305_exit); MODULE_AUTHOR("Nvidia"); MODULE_DESCRIPTION("Microchip EMC2305 fan controller driver"); diff --git a/drivers/net/wireless/ath/ath11k/core.h b/drivers/net/wireless/ath/ath11k/core.h index bba9ed302f78b426650e41cdfcccf707cb8625b1..3db0aa2c98e5a57193aeb9a05264f8563e76f252 100644 --- a/drivers/net/wireless/ath/ath11k/core.h +++ b/drivers/net/wireless/ath/ath11k/core.h @@ -329,6 +329,7 @@ struct ath11k_vif { u16 tx_seq_no; struct wmi_wmm_params_all_arg wmm_params; + struct wmi_wmm_params_all_arg muedca_params; struct list_head list; union { struct { diff --git a/drivers/net/wireless/ath/ath11k/mac.c b/drivers/net/wireless/ath/ath11k/mac.c index ffb99502f23d95f98ed963f25467cdca1c97c976..1658a0f06cfafb2d5a21ceff20fa528e0b0d407e 100644 --- a/drivers/net/wireless/ath/ath11k/mac.c +++ b/drivers/net/wireless/ath/ath11k/mac.c @@ -5097,6 +5097,51 @@ static int ath11k_conf_tx_uapsd(struct ath11k *ar, struct ieee80211_vif *vif, return ret; } +static int ath11k_mac_op_conf_tx_mu_edca(struct ieee80211_hw *hw, + struct ieee80211_vif *vif, + unsigned int link_id, u16 ac, + const struct ieee80211_tx_queue_params *params) +{ + struct ath11k *ar = hw->priv; + struct ath11k_vif *arvif = ath11k_vif_to_arvif(vif); + struct wmi_wmm_params_arg *p = NULL; + int ret; + + switch (ac) { + case IEEE80211_AC_VO: + p = &arvif->muedca_params.ac_vo; + break; + case IEEE80211_AC_VI: + p = &arvif->muedca_params.ac_vi; + break; + case IEEE80211_AC_BE: + p = &arvif->muedca_params.ac_be; + break; + case IEEE80211_AC_BK: + p = &arvif->muedca_params.ac_bk; + break; + } + + if (WARN_ON(!p)) { + ret = -EINVAL; + goto exit; + } + + p->cwmin = params->mu_edca_param_rec.ecw_min_max & 0x0f; + p->cwmax = (params->mu_edca_param_rec.ecw_min_max & 0xf0) >> 4; + p->aifs = params->mu_edca_param_rec.aifsn & 0x0f; + p->txop = params->mu_edca_param_rec.mu_edca_timer; + + ret = ath11k_wmi_send_wmm_update_cmd_tlv(ar, arvif->vdev_id, + &arvif->muedca_params, + WMM_PARAM_TYPE_11AX_MU_EDCA); + if (ret) + ath11k_warn(ar->ab, "failed to set mu_edca params: %d\n", ret); + +exit: + return ret; +} + static int ath11k_mac_op_conf_tx(struct ieee80211_hw *hw, struct ieee80211_vif *vif, unsigned int link_id, u16 ac, @@ -5135,12 +5180,21 @@ static int ath11k_mac_op_conf_tx(struct ieee80211_hw *hw, p->txop = params->txop; ret = ath11k_wmi_send_wmm_update_cmd_tlv(ar, arvif->vdev_id, - &arvif->wmm_params); + &arvif->wmm_params, WMM_PARAM_TYPE_LEGACY); if (ret) { ath11k_warn(ar->ab, "failed to set wmm params: %d\n", ret); goto exit; } + if (params->mu_edca) { + ret = ath11k_mac_op_conf_tx_mu_edca(hw, vif, link_id, ac, + params); + if (ret) { + ath11k_warn(ar->ab, "failed to set mu_edca params: %d\n", ret); + goto exit; + } + } + ret = ath11k_conf_tx_uapsd(ar, vif, ac, params->uapsd); if (ret) diff --git a/drivers/net/wireless/ath/ath11k/wmi.c b/drivers/net/wireless/ath/ath11k/wmi.c index f99de4874df119475f9a59812a5d40b4625743f7..4955570bcc85e44070fb3b1c9ba5b7ca0f3ba49a 100644 --- a/drivers/net/wireless/ath/ath11k/wmi.c +++ b/drivers/net/wireless/ath/ath11k/wmi.c @@ -2554,7 +2554,7 @@ int ath11k_wmi_send_scan_chan_list_cmd(struct ath11k *ar, } int ath11k_wmi_send_wmm_update_cmd_tlv(struct ath11k *ar, u32 vdev_id, - struct wmi_wmm_params_all_arg *param) + struct wmi_wmm_params_all_arg *param, u32 wmm_param_type) { struct ath11k_pdev_wmi *wmi = ar->wmi; struct wmi_vdev_set_wmm_params_cmd *cmd; @@ -2573,7 +2573,7 @@ int ath11k_wmi_send_wmm_update_cmd_tlv(struct ath11k *ar, u32 vdev_id, FIELD_PREP(WMI_TLV_LEN, sizeof(*cmd) - TLV_HDR_SIZE); cmd->vdev_id = vdev_id; - cmd->wmm_param_type = 0; + cmd->wmm_param_type = wmm_param_type; for (ac = 0; ac < WME_NUM_AC; ac++) { switch (ac) { @@ -2606,8 +2606,8 @@ int ath11k_wmi_send_wmm_update_cmd_tlv(struct ath11k *ar, u32 vdev_id, wmm_param->no_ack = wmi_wmm_arg->no_ack; ath11k_dbg(ar->ab, ATH11K_DBG_WMI, - "wmm set ac %d aifs %d cwmin %d cwmax %d txop %d acm %d no_ack %d\n", - ac, wmm_param->aifs, wmm_param->cwmin, + "wmm set type %d ac %d aifs %d cwmin %d cwmax %d txop %d acm %d no_ack %d\n", + wmm_param_type, ac, wmm_param->aifs, wmm_param->cwmin, wmm_param->cwmax, wmm_param->txoplimit, wmm_param->acm, wmm_param->no_ack); } diff --git a/drivers/net/wireless/ath/ath11k/wmi.h b/drivers/net/wireless/ath/ath11k/wmi.h index 2b0eefe17ce3b89d414a0e0ff205b69ef53b9d77..363c8dac25d5ee69bab127f19fc4fe1557c79a73 100644 --- a/drivers/net/wireless/ath/ath11k/wmi.h +++ b/drivers/net/wireless/ath/ath11k/wmi.h @@ -6292,6 +6292,11 @@ enum wmi_sta_keepalive_method { #define WMI_STA_KEEPALIVE_INTERVAL_DEFAULT 30 #define WMI_STA_KEEPALIVE_INTERVAL_DISABLE 0 +enum wmm_edca_params_type { + WMM_PARAM_TYPE_LEGACY = 0, + WMM_PARAM_TYPE_11AX_MU_EDCA = 1, +}; + const void **ath11k_wmi_tlv_parse_alloc(struct ath11k_base *ab, const void *ptr, size_t len, gfp_t gfp); int ath11k_wmi_cmd_send(struct ath11k_pdev_wmi *wmi, struct sk_buff *skb, @@ -6346,7 +6351,7 @@ int ath11k_wmi_send_scan_start_cmd(struct ath11k *ar, int ath11k_wmi_send_scan_stop_cmd(struct ath11k *ar, struct scan_cancel_param *param); int ath11k_wmi_send_wmm_update_cmd_tlv(struct ath11k *ar, u32 vdev_id, - struct wmi_wmm_params_all_arg *param); + struct wmi_wmm_params_all_arg *param, u32 wmm_param_type); int ath11k_wmi_pdev_suspend(struct ath11k *ar, u32 suspend_opt, u32 pdev_id); int ath11k_wmi_pdev_resume(struct ath11k *ar, u32 pdev_id); diff --git a/drivers/usb/misc/Kconfig b/drivers/usb/misc/Kconfig index 99b15b77dfd576dace539b7166dd574fe134fcdf..6659e917ea261988c8ed7a5e7ab4fcdaac925e14 100644 --- a/drivers/usb/misc/Kconfig +++ b/drivers/usb/misc/Kconfig @@ -251,6 +251,15 @@ config USB_EZUSB_FX2 Say Y here if you need EZUSB device support. (Cypress FX/FX2/FX2LP microcontrollers) +config USB_HUB_USB5807 + tristate "USB5807 Hub Controller Configuration Driver" + depends on I2C + help + This option enables support for configuration via SMBus of the + Microchip USB5807 USB 3.1 Hub Controller. Configuration parameters may + be set in devicetree. + Say Y or M here if you need to configure such a device via SMBus. + config USB_HUB_USB251XB tristate "USB251XB Hub Controller Configuration Driver" depends on I2C diff --git a/drivers/usb/misc/Makefile b/drivers/usb/misc/Makefile index 1992cc284d8aba91f2229810d6b1d9e3b663ef2e..e827ed251fa53e6adef67aea7149e614fc3cb76f 100644 --- a/drivers/usb/misc/Makefile +++ b/drivers/usb/misc/Makefile @@ -25,6 +25,7 @@ obj-$(CONFIG_USB_USS720) += uss720.o obj-$(CONFIG_USB_SEVSEG) += usbsevseg.o obj-$(CONFIG_USB_YUREX) += yurex.o obj-$(CONFIG_USB_HUB_USB251XB) += usb251xb.o +obj-$(CONFIG_USB_HUB_USB5807) += usb5807.o obj-$(CONFIG_USB_HSIC_USB3503) += usb3503.o obj-$(CONFIG_USB_HSIC_USB4604) += usb4604.o obj-$(CONFIG_USB_CHAOSKEY) += chaoskey.o diff --git a/drivers/usb/misc/usb5807.c b/drivers/usb/misc/usb5807.c new file mode 100644 index 0000000000000000000000000000000000000000..d37d682c1a12aff5aa4e6c725a9affddae446e05 --- /dev/null +++ b/drivers/usb/misc/usb5807.c @@ -0,0 +1,175 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Driver for Microchip USB5807 USB 3.1 Hub + * Configuration via SMBus. + * + * Copyright (c) 2023 Topic Embedded Products + */ + +#include <linux/delay.h> +#include <linux/err.h> +#include <linux/gpio/consumer.h> +#include <linux/i2c.h> +#include <linux/kernel.h> +#include <linux/module.h> +#include <linux/of_device.h> + +#define USB5807_CMD_ATTACH 0xAA55 +#define USB5807_CMD_CONFIG 0x9937 + +#define USB5807_REG_LANE_SWAP 0x30FA + +#define USB5807_NUM_PORTS 7 + + +static int usb5807_write(struct i2c_client *i2c, void *buf, u8 len) +{ + int ret; + struct i2c_msg msg = { + .addr = i2c->addr, + .flags = 0x0, + .len = len, + .buf = buf, + }; + + ret = i2c_transfer(i2c->adapter, &msg, 1); + return ret < 0 ? ret : 0; +} + +/* + * Send a command sequence, which is an I2C write transaction, with the command + * word in big endian and a terminating "0" byte. + */ +static int usb5807_command(struct i2c_client *i2c, u16 cmd) +{ + u8 buf[3] = {cmd >> 8, cmd & 0xff, 0}; + + return usb5807_write(i2c, buf, sizeof(buf)); +} + +static int usb5807_prepare_reg_u8(struct i2c_client *i2c, u16 reg, u8 value) +{ + u8 buf[] = { + 0x00, + 0x00, /* Memory offset */ + 1 + 4, /* Transaction size */ + 0x00, /* 0 = Register write operation */ + 1, /* Size of register data */ + (reg >> 8) & 0xff, + reg & 0xff, /* Register offset */ + value, /* Register data */ + 0 /* Terminating zero */ + }; + + return usb5807_write(i2c, buf, sizeof(buf)); +} + +/* + * Write an 8-bit register. First we must write the "set register" operation to + * the chip's internal memory at offset 0, then issue a command to execute said + * operation. + */ +static int usb5807_write_reg_u8(struct i2c_client *i2c, u16 reg, u8 value) +{ + int ret; + + ret = usb5807_prepare_reg_u8(i2c, reg, value); + if (ret) + return ret; + + return usb5807_command(i2c, USB5807_CMD_CONFIG); +} + +/* Decode array of port numbers property into bit mask */ +static u8 usb5807_get_ports_field(struct device *dev, const char *prop_name) +{ + struct property *prop; + const __be32 *p; + u32 port; + u8 result = 0; + + of_property_for_each_u32(dev->of_node, prop_name, prop, p, port) { + if (port < USB5807_NUM_PORTS) + result |= BIT(port); + else + dev_warn(dev, "%s: port %u doesn't exist\n", prop_name, + port); + } + return result; +} + +static int usb5807_i2c_probe(struct i2c_client *i2c) +{ + struct device_node *np = i2c->dev.of_node; + struct gpio_desc *reset_gpio; + int ret; + u8 val; + + /* Reset the chip to bring it into configuration mode */ + reset_gpio = devm_gpiod_get_optional(&i2c->dev, "reset", + GPIOD_OUT_HIGH); + if (IS_ERR(reset_gpio)) { + dev_warn(&i2c->dev, "Failed to request reset GPIO\n"); + reset_gpio = NULL; + } + /* Reset timing: Assert for >= 5 us */ + usleep_range(5, 10); + + /* Lock the bus for >= 1ms while the hub reads the I2C strapping */ + i2c_lock_bus(i2c->adapter, I2C_LOCK_SEGMENT); + + if (reset_gpio) + gpiod_set_value_cansleep(reset_gpio, 0); + + usleep_range(1000, 2000); + + i2c_unlock_bus(i2c->adapter, I2C_LOCK_SEGMENT); + + /* The hub device needs additional time to boot up */ + msleep(20); + + val = usb5807_get_ports_field(&i2c->dev, "swap-dx-lanes"); + if (val) { + ret = usb5807_write_reg_u8(i2c, USB5807_REG_LANE_SWAP, val); + if (ret < 0) + dev_err(&i2c->dev, "Failed writing config: %d\n", ret); + } + + /* + * Send the "Attach" command which makes the device disappear from the + * I2C bus and starts USB enumeration. + */ + ret = usb5807_command(i2c, USB5807_CMD_ATTACH); + if (ret) { + dev_err(&i2c->dev, "Failed sending ATTACH command: %d\n", ret); + return ret; + } + + return 0; +} + +static const struct of_device_id usb5807_of_match[] = { + { .compatible = "microchip,usb5807" }, + { } /* sentinel */ +}; +MODULE_DEVICE_TABLE(of, usb5807_of_match); + +static const struct i2c_device_id usb5807_id[] = { + { "usb5807", }, + { /* sentinel */ } +}; +MODULE_DEVICE_TABLE(i2c, usb5807_id); + +static struct i2c_driver usb5807_i2c_driver = { + .driver = { + .name = "usb5807", + .of_match_table = of_match_ptr(usb5807_of_match), + }, + .probe = usb5807_i2c_probe, + .id_table = usb5807_id, +}; + +module_i2c_driver(usb5807_i2c_driver); + +MODULE_DESCRIPTION("USB5807 USB 3.1 Hub Controller Driver"); +MODULE_LICENSE("GPL");