MSM8953/SDM450 去PMI的USB3.0 TYPE-C Micro USB OTG功能适配
提前说明一下有哪些“坑”。
1、PM8953 GPIO_8的TZ权限
2、PM8953 GPIO_8寄存器的写入保护
3、去掉高通默认的ID检测
4、增加dwc3的ID检测
5、增加TYPE-C的ID PIN控制
设备树配置:
&tlmm {
usb_id_default: usb_id_default {
mux {
pins = "gpio1";
function = "gpio";
};
config {
pins = "gpio1";
drive-strength = <2>;
bias-pull-up;
};
};
};
&pm8953_typec {
qcom,ssmux-gpio = <&tlmm 139 GPIO_ACTIVE_LOW>;
qcom,id-gpio = <&pm8953_gpios 8 0x0>;
pinctrl-names = "default";
pinctrl-0 = <&typec_ssmux_config>;
status = "ok";
};
&usb3 {
vbus_dwc3-supply = <&usb_otg_switch>;
otg,id_det_pin = <&tlmm 1 0x0>;
extcon = <&usb_detect>;
pinctrl-names = "default";
pinctrl-0 = <&usb_id_default>;
};
&usb_otg_switch {
gpio = <&tlmm 3 0>;
};
&soc {
usb_detect: usb_detect {
compatible = "qcom,gpio-usbdetect";
interrupt-parent = <&spmi_bus>;
interrupts = <0x0 0xc6 0x0>;
interrupt-names = "vbus_det_irq";
qcom,vbus-det-gpio = <&pm8953_gpios 7 0x00>;
pinctrl-names = "default";
pinctrl-0 = <&pm8953_gpio7_default>;
};
};
修改PM8953 GPIO8 TZ权限
index e1d339e..dda5a23 100755
--- a/TZ.BF.4.0.5/trustzone_images/core/systemdrivers/pmic/config/msm8953_pm8950/src/pm_spmi_config.c
+++ b/TZ.BF.4.0.5/trustzone_images/core/systemdrivers/pmic/config/msm8953_pm8950/src/pm_spmi_config.c
@@ -167,7 +167,7 @@ SpmiCfg_ChannelCfg pm_spmi_pheriph_cfg [] = {0x0, 0xFE, 0, PM_RPM_OWNER, PM_RPM_OWNER}, /* TRIM */
- {0x0, 0xC7, 0, PM_WCONNECT_OWNER, SPMI_OPEN_OWNER}, /* GPIO8 */
+ {0x0, 0xC7, 0, PM_APPS_HLOS_OWNER, SPMI_OPEN_OWNER}, /* GPIO8 */
{0x0, 0xC6, 0, PM_APPS_HLOS_OWNER, SPMI_OPEN_OWNER}, /* GPIO7 */
{0x0, 0xC5, 0, PM_WCONNECT_OWNER, SPMI_OPEN_OWNER}, /* GPIO6 */
{0x0, 0xC4, 0, PM_WCONNECT_OWNER, SPMI_OPEN_OWNER}, /* GPIO5 */
去除PM8953 GPIO_8寄存器的写入保护
index 0f0b7ba..f7946e0 100644
--- a/drivers/spmi/spmi-pmic-arb.c
+++ b/drivers/spmi/spmi-pmic-arb.c
@@ -451,6 +451,7 @@ static int pmic_arb_write_cmd(struct spmi_controller *ctrl, u8 opc, u8 sid,
dev_err(&pa->spmic->dev,
"error: impermissible write to peripheral sid:%d addr:0x%x\n",
sid, addr);
+ if (!(0xc740 == (addr & 0xc740))) // skip PM8953 GPIO_8 Register protect check
return -ENODEV;
}
去掉高通默认的ID检测
diff --git a/drivers/platform/msm/gpio-usbdetect.c b/drivers/platform/msm/gpio-usbdetect.c
index 6730d4a..d2cbdea 100644
--- a/drivers/platform/msm/gpio-usbdetect.c
+++ b/drivers/platform/msm/gpio-usbdetect.c
@@ -22,6 +22,7 @@
#include <linux/gpio.h>
#include <linux/extcon.h>
#include <linux/regulator/consumer.h>
+#include <linux/delay.h> struct gpio_usbdetect {
struct platform_device *pdev;
@@ -45,66 +46,21 @@ static irqreturn_t gpio_usbdetect_vbus_irq(int irq, void *data)
struct gpio_usbdetect *usb = data;
union extcon_property_value val; - usb->vbus_state = gpio_get_value(usb->gpio);
+ usb->vbus_state = !!gpio_get_value(usb->gpio);
+
if (usb->vbus_state) {
- dev_dbg(&usb->pdev->dev, "setting vbus notification\n");
+ dev_err(&usb->pdev->dev, "xcz setting vbus notification\n");
val.intval = true;
- extcon_set_property(usb->extcon_dev, EXTCON_USB,
- EXTCON_PROP_USB_SS, val);
+
extcon_set_cable_state_(usb->extcon_dev, EXTCON_USB, 1);
} else {
- dev_dbg(&usb->pdev->dev, "setting vbus removed notification\n");
+ dev_err(&usb->pdev->dev, "xcz setting vbus removed notification\n");
extcon_set_cable_state_(usb->extcon_dev, EXTCON_USB, 0);
} return IRQ_HANDLED;
} -static irqreturn_t gpio_usbdetect_id_irq(int irq, void *data)
-{
- struct gpio_usbdetect *usb = data;
- int ret;
-
- ret = irq_get_irqchip_state(irq, IRQCHIP_STATE_LINE_LEVEL,
- &usb->id_state);
- if (ret < 0) {
- dev_err(&usb->pdev->dev, "unable to read ID IRQ LINE\n");
- return IRQ_HANDLED;
- }
-
- return IRQ_WAKE_THREAD;
-}
-
-static irqreturn_t gpio_usbdetect_id_irq_thread(int irq, void *data)
-{
- struct gpio_usbdetect *usb = data;
- bool curr_id_state;
- static int prev_id_state = -EINVAL;
- union extcon_property_value val;
-
- curr_id_state = usb->id_state;
- if (curr_id_state == prev_id_state) {
- dev_dbg(&usb->pdev->dev, "no change in ID state\n");
- return IRQ_HANDLED;
- }
-
- if (curr_id_state) {
- dev_dbg(&usb->pdev->dev, "stopping usb host\n");
- extcon_set_cable_state_(usb->extcon_dev, EXTCON_USB_HOST, 0);
- enable_irq(usb->vbus_det_irq);
- } else {
- dev_dbg(&usb->pdev->dev, "starting usb HOST\n");
- disable_irq(usb->vbus_det_irq);
- val.intval = true;
- extcon_set_property(usb->extcon_dev, EXTCON_USB_HOST,
- EXTCON_PROP_USB_SS, val);
- extcon_set_cable_state_(usb->extcon_dev, EXTCON_USB_HOST, 1);
- }
-
- prev_id_state = curr_id_state;
- return IRQ_HANDLED;
-}
-
static const u32 gpio_usb_extcon_exclusive[] = {0x3, 0}; static int gpio_usbdetect_probe(struct platform_device *pdev)
@@ -164,8 +120,6 @@ static int gpio_usbdetect_probe(struct platform_device *pdev)
"qcom,vbus-det-gpio", 0);
if (usb->gpio < 0) {
dev_err(&pdev->dev, "Failed to get gpio: %d\n", usb->gpio);
- rc = usb->gpio;
- goto error;
} rc = gpio_request(usb->gpio, "vbus-det-gpio");
@@ -174,7 +128,7 @@ static int gpio_usbdetect_probe(struct platform_device *pdev)
goto error;
} - usb->vbus_det_irq = gpio_to_irq(usb->gpio);
+ usb->vbus_det_irq = gpio_to_irq(usb->gpio);//0xc6;//= gpio_to_irq(usb->gpio);
if (usb->vbus_det_irq < 0) {
dev_err(&pdev->dev, "get vbus_det_irq failed\n");
rc = usb->vbus_det_irq;
@@ -191,35 +145,11 @@ static int gpio_usbdetect_probe(struct platform_device *pdev)
goto error;
} - usb->id_det_irq = platform_get_irq_byname(pdev, "pmic_id_irq");
- if (usb->id_det_irq < 0) {
- dev_err(&pdev->dev, "get id_det_irq failed\n");
- rc = usb->id_det_irq;
- goto error;
- }
-
- rc = devm_request_threaded_irq(&pdev->dev, usb->id_det_irq,
- gpio_usbdetect_id_irq,
- gpio_usbdetect_id_irq_thread,
- IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING |
- IRQF_ONESHOT, "id_det_irq", usb);
- if (rc) {
- dev_err(&pdev->dev, "request for id_det_irq failed: %d\n", rc);
- goto error;
- }
+ usb->id_det_irq = platform_get_irq_byname(pdev, "vbus_det_irq"); enable_irq_wake(usb->vbus_det_irq);
- enable_irq_wake(usb->id_det_irq);
dev_set_drvdata(&pdev->dev, usb); - if (usb->id_det_irq) {
- gpio_usbdetect_id_irq(usb->id_det_irq, usb);
- if (!usb->id_state) {
- gpio_usbdetect_id_irq_thread(usb->id_det_irq, usb);
- return 0;
- }
- }
-
/* Read and report initial VBUS state */
gpio_usbdetect_vbus_irq(usb->vbus_det_irq, usb);
增加dwc3的ID检测
diff --git a/drivers/usb/dwc3/dwc3-msm.c b/drivers/usb/dwc3/dwc3-msm.c
index f549047..cc54672 100644
--- a/drivers/usb/dwc3/dwc3-msm.c
+++ b/drivers/usb/dwc3/dwc3-msm.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2012-2019, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2012-2018, 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
@@ -55,6 +55,8 @@
#include "debug.h"
#include "xhci.h" +#define DEBUG
+
#define SDP_CONNETION_CHECK_TIME 10000 /* in ms */ /* time out to wait for USB cable status notification (in ms)*/
@@ -235,6 +237,8 @@ struct dwc3_msm {
bool use_pdc_interrupts;
enum dwc3_id_state id_state;
unsigned long lpm_flags;
+ int id_det_pin;
+ int id_det_irq;
#define MDWC3_SS_PHY_SUSPEND BIT(0)
#define MDWC3_ASYNC_IRQ_WAKE_CAPABILITY BIT(1)
#define MDWC3_POWER_COLLAPSE BIT(2)
@@ -290,7 +294,7 @@ struct dwc3_msm { #define DSTS_CONNECTSPD_SS 0x4 -
+static int dwc3_msm_id_notifier(struct notifier_block *nb, unsigned long event, void *ptr);
static void dwc3_pwr_event_handler(struct dwc3_msm *mdwc);
static int dwc3_msm_gadget_vbus_draw(struct dwc3_msm *mdwc, unsigned int mA);
static void dwc3_msm_notify_event(struct dwc3 *dwc, unsigned int event,
@@ -1860,13 +1864,8 @@ static void dwc3_msm_notify_event(struct dwc3 *dwc, unsigned int event,
reg |= DWC3_GCTL_CORESOFTRESET;
dwc3_msm_write_reg(mdwc->base, DWC3_GCTL, reg); - /*
- * If the core could not recover after MAX_ERROR_RECOVERY_TRIES,
- * skip the restart USB work and keep the core in softreset
- * state.
- */
- if (dwc->retries_on_error < MAX_ERROR_RECOVERY_TRIES)
- schedule_work(&mdwc->restart_usb_work);
+ /* restart USB which performs full reset and reconnect */
+ schedule_work(&mdwc->restart_usb_work);
break;
case DWC3_CONTROLLER_RESET_EVENT:
dev_dbg(mdwc->dev, "DWC3_CONTROLLER_RESET_EVENT received\n");
@@ -2828,6 +2827,17 @@ static irqreturn_t msm_dwc3_pwr_irq(int irq, void *data)
return IRQ_HANDLED;
} +// add 2020-02-24
+static irqreturn_t id_det_irq_handle(int irq, void *data)
+{
+ struct dwc3_msm *mdwc = data;
+
+ dwc3_msm_id_notifier(&mdwc->id_nb, gpio_get_value(mdwc->id_det_pin) ? 0 : 1, mdwc->extcon_id);
+
+ return IRQ_HANDLED;
+}
+// add 2020-02-24 end
+
static int dwc3_cpu_notifier_cb(struct notifier_block *nfb,
unsigned long action, void *hcpu)
{
@@ -2953,7 +2963,7 @@ static int dwc3_msm_get_clk_gdsc(struct dwc3_msm *mdwc)
return 0;
} -static int dwc3_msm_id_notifier(struct notifier_block *nb,
+static int dwc3_msm_id_notifier(struct notifier_block *nb, //xcz
unsigned long event, void *ptr)
{
struct dwc3_msm *mdwc = container_of(nb, struct dwc3_msm, id_nb);
@@ -3005,7 +3015,10 @@ static int dwc3_msm_vbus_notifier(struct notifier_block *nb,
struct dwc3_msm *mdwc = container_of(nb, struct dwc3_msm, vbus_nb);
struct dwc3 *dwc = platform_get_drvdata(mdwc->dwc3); - dev_dbg(mdwc->dev, "vbus:%ld event received\n", event);
+ dev_err(mdwc->dev, "vbus:%ld event received\n", event);
+
+ printk("xcz haha ===== vbus:%ld event received\n", event);
+ if (mdwc->vbus_active == event)
return NOTIFY_DONE;
@@ -3442,6 +3455,30 @@ static int dwc3_msm_probe(struct platform_device *pdev)
}
} + // add 2020-02-24
+ mdwc->id_det_pin = of_get_named_gpio(pdev->dev.of_node, "otg,id_det_pin", 0);
+ if (mdwc->id_det_pin > 0) {
+ ret = gpio_request(mdwc->id_det_pin, "id_det_pin");
+ if(0 != ret) {
+ dev_err(&pdev->dev, "xcz Otg id_det_pin request %d failed.\n", mdwc->id_det_pin);
+ }
+
+ mdwc->id_det_irq = gpio_to_irq(mdwc->id_det_pin);
+ dev_err(&pdev->dev, "xcz Otg id_det_pin: %d, irq: %d\n",
+ mdwc->id_det_pin, mdwc->id_det_irq);
+
+ ret = devm_request_irq(&pdev->dev,
+ mdwc->id_det_irq,
+ id_det_irq_handle,
+ IRQF_TRIGGER_RISING |
+ IRQF_TRIGGER_FALLING,
+ "id_det_irq",
+ mdwc);
+ } else {
+ dev_err(&pdev->dev, "xcz Otg id_det_pin NUll\n");
+ }
+ // add 2020-02-24 end
+
res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "tcsr_base");
if (!res) {
dev_dbg(&pdev->dev, "missing TCSR memory resource\n");
@@ -3701,7 +3738,8 @@ static int dwc3_msm_probe(struct platform_device *pdev)
if (pval.intval > 0)
dev_info(mdwc->dev, "charger detection in progress\n");
}
-
+ if(mdwc->id_det_pin > 0)
+ id_det_irq_handle(mdwc->id_det_irq, mdwc);
device_create_file(&pdev->dev, &dev_attr_mode);
device_create_file(&pdev->dev, &dev_attr_speed);
device_create_file(&pdev->dev, &dev_attr_usb_compliance_mode);
增加TYPE-C的ID PIN控制
diff --git a/drivers/power/supply/qcom/qpnp-typec.c b/drivers/power/supply/qcom/qpnp-typec.c
index 12aa16b..20f1a71 100644
--- a/drivers/power/supply/qcom/qpnp-typec.c
+++ b/drivers/power/supply/qcom/qpnp-typec.c
@@ -113,6 +113,7 @@ struct qpnp_typec_chip {
int ssmux_gpio;
enum of_gpio_flags gpio_flag;
int typec_state;
+ int id_gpio; /* Dual role support */
bool role_reversal_supported;
@@ -280,6 +281,15 @@ static int qpnp_typec_configure_ssmux(struct qpnp_typec_chip *chip,
return rc;
}
}
+
+ if (chip->id_gpio) {
+ rc = gpio_direction_input(chip->id_gpio);
+ if (rc) {
+ pr_err("failed to configure usb id gpio rc=%d\n",
+ rc);
+ return rc;
+ }
+ }
break;
case CC_1:
case CC_2:
@@ -526,6 +536,8 @@ static irqreturn_t dfp_detect_handler(int irq, void *_chip)
pr_debug("UFP status reg = 0x%x DFP status reg = 0x%x\n",
reg[0], reg[1]); + // pull down USB ID pin to start host
+ gpio_direction_output(chip->id_gpio, 0);
out:
mutex_unlock(&chip->typec_lock);
return IRQ_HANDLED;
@@ -545,6 +557,8 @@ static irqreturn_t dfp_detach_handler(int irq, void *_chip) mutex_unlock(&chip->typec_lock); + // pull up USB ID pin to start device
+ gpio_direction_output(chip->id_gpio, 1);
return IRQ_HANDLED;
} @@ -589,6 +603,27 @@ static int qpnp_typec_parse_dt(struct qpnp_typec_chip *chip)
}
} + /* USB ID configuration gpio */
+ if (of_find_property(node, "qcom,id-gpio", NULL)) {
+ chip->id_gpio = of_get_named_gpio(node,
+ "qcom,id-gpio", 0);
+ if (!gpio_is_valid(chip->id_gpio)) {
+ if (chip->id_gpio != -EPROBE_DEFER)
+ pr_err("failed to get usb id config gpio=%d\n",
+ chip->id_gpio);
+ return chip->id_gpio;
+ }
+
+ rc = devm_gpio_request(chip->dev, chip->id_gpio,
+ "typec_usb_id_gpio");
+ if (rc) {
+ pr_err("failed to request usb id gpio rc=%d\n", rc);
+ chip->id_gpio = 0;
+ } else {
+ gpio_direction_input(chip->id_gpio);
+ }
+ }
+
/* SS-Mux regulator */
if (of_find_property(node, "ss-mux-supply", NULL)) {
chip->ss_mux_vreg = devm_regulator_get(chip->dev, "ss-mux");
MSM8953/SDM450 去PMI的USB3.0 TYPE-C Micro USB OTG功能适配的更多相关文章
- USB3.0驱动与2.0有什么区别
安装好usb3.0驱动就可以驱动usb 3.0设备,能够适应于大部份主板,帮助用户解决usb3.0和电脑无法正常通讯的问题,并支持winxp,win7和win8系统,是目前网络上最好用的usb3.0万 ...
- 硕盟SM-T54(TYPE C转HDMI+VGA+USB3.0+PD3.0)
硕盟SM-T54是一款TYPE C转HDMI+VGA+USB3.0+PD3.0四口扩展坞,您可以将含有USB 3.1协议的电脑主机,通过此产品连接到具有HDMI或VGA的显示器.电视机或其他显示设备. ...
- 硕盟SM-T54| TYPE C转HDMI+VGA+USB3.0+PD3.0四合一多功能扩展坞
硕盟SM-T54是一款 TYPE C转HDMI+VGA+USB3.0+PD3.0四合一多功能扩展坞,支持四口同时使用,您可以将含有USB 3.1协议的电脑主机,通过此产品连接到具有HDMI或VGA的显 ...
- 硕盟 TYPE C转HDMI+VGA+USB3.0+PD3.0四口扩展坞
硕盟SM-T54是一款USB-C 四合一多功能扩展坞,支持四口同时使用,您可以将含有USB 3.1协议的电脑主机,通过此产品连接到具有HDMI或VGA的显示器.电视机或其他显示设备.产品可以接入硬盘. ...
- 硕盟SM-A44|USB3.0转RJ45千兆网口转换器(TYPE A USB3.0 TO RJ45)
硕盟SM-A44是一款USB3.0转RJ45千兆网口转换器.,转换USB端口到以太网端口.它让你投入低成本就可以轻松拥有千兆以太网.可将网络连接到台式机,笔记本电脑等等设备.硕盟 USB千兆网卡采用嵌 ...
- 硕盟USB3.0 转RJ45千兆网卡 TYPE A USB3.0 TO RJ45
硕盟SM-A44是一款USB3.0转RJ45千兆网口转换器.这是一种高性能和低开销的解决方案.转换USB端口到10 / 100/ 1000M以太网端口可以让您的笔记本,台式机电脑能够通过USB接口连接 ...
- AC6102开发板USB3.0测试和使用说明
AC6102开发板USB3.0测试和使用说明 概述 AC6102上集成了一颗Cypress 推出的高性能USB3.0传输芯片CYUSB3014,Cypress称之为EZ-USBFX3.该芯片性能强劲, ...
- 关于在win7内集成usb3.0驱动。
mac air 装了win7但是折腾良久还是无法升级,只能是重新安装. 很蛋疼.bootcamp 老是找不到驱动.只能是手动分区后U盘引导安装. 驱动的下载,直接在Os x 下用bootcamp 下载 ...
- VirtualBox虚拟机中启用usb3.0却无法显示u盘的解决方法
主机系统为win7 64位,由于工作需要,安装了Virtualbox 5.18虚拟机,virtaulbox中安装了win7 32系统.以为下启用usb 3.0的步骤: 1.宿主机要支持 usb 3.0 ...
- USB3.0及NVME SSD安装WIN7X64
USB3.0及NVME SSD安装WIN7X64https://tieba.baidu.com/p/4822034273?pn=1所有的人都是菜鸟过来的,不过有些人懂得自己动手找到答案:有些人则是懒得 ...
随机推荐
- vs程序员使用windbg实例
如果使用32位的windbg,windbg加载完dump文件后,窗口会显示wow64cpu,表示是64位进程,需要切换到64位环境: .load wow64exts !sw 设置符号表(crtl+s) ...
- Java高并发Lock接口讲解,精准通知线程间的执行顺序
题目:两个线程操作一个变量,实现两个线程对同一个资源一个进行加1操作,另外一个进行减1操作,且需要交替实现,变量的初始值为0.即两个线程对同一个资源进行加一减一交替操作. Lock接口与Conditi ...
- Python-提高-1
阅读目录 1.GIL(全局解释器锁) 2.深拷贝.浅拷贝 3.私有化 4.import导入模块 5.再议 封装.继承.多态 一.GIL(全局解释器锁) GIL面试题如下 描述Python GIL的概念 ...
- 关于Java后台处理前端用户传来数据过大,超过数据库字段设置长度导致的异常问题处理
在DTO bean对象上使用javax验证(如最小值,最大值等,请参阅here).
- python实现基于RPC协议的接口自动化测试
01什么是RPC RPC(Remote Procedure Call)远程过程调用协议是一个用于建立适当框架的协议.从本质上讲,它使一台机器上的程序能够调用另一台机器上的子程序,而不会意识到它是远程的 ...
- 在美国和以色列的技术支持下BP机可以爆炸,那么苹果手机是否也可以被远程引爆
要知道,这一切在技术上都是可以实现的. 由此可见,带电池的产品,最为稳妥的办法就是购买在中国组装的产品,否则其安全性是无法保证的.有人可能会说美国政府不会单独的通过这种方法去定向的杀害某个中国普通人, ...
- Java深度历险(九)——Java安全
安全性是Java应用程序的非功能性需求的重要组成部分,如同其它的非功能性需求一样,安全性很容易被开发人员所忽略.当然,对于Java EE的开发人员来说,安全性的话题可能没那么陌生,用户认证和授权可能是 ...
- vue中登录超时跳转到登录页面设置拦截器
axios中添加响应拦截器 Axios.interceptors.response.use(res = > { let resData = res.data; if (resData.code ...
- python之日志logging
转载:https://blog.csdn.net/weixin_43790276/article/details/101944628 logging 模块是 Python 内置的标准模块,用于输出代码 ...
- golang之循环导包
作为一个 Golang 开发,你可能在项目中遇到过包的循环依赖问题.Golang 不允许循环依赖,如果检测到代码中存在这种情况,在编译时就会抛出异常. 循环依赖 假设我们有两个包:p1和p2.当包p1 ...