提前说明一下有哪些“坑”。

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功能适配的更多相关文章

  1. USB3.0驱动与2.0有什么区别

    安装好usb3.0驱动就可以驱动usb 3.0设备,能够适应于大部份主板,帮助用户解决usb3.0和电脑无法正常通讯的问题,并支持winxp,win7和win8系统,是目前网络上最好用的usb3.0万 ...

  2. 硕盟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的显示器.电视机或其他显示设备. ...

  3. 硕盟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的显 ...

  4. 硕盟 TYPE C转HDMI+VGA+USB3.0+PD3.0四口扩展坞

    硕盟SM-T54是一款USB-C 四合一多功能扩展坞,支持四口同时使用,您可以将含有USB 3.1协议的电脑主机,通过此产品连接到具有HDMI或VGA的显示器.电视机或其他显示设备.产品可以接入硬盘. ...

  5. 硕盟SM-A44|USB3.0转RJ45千兆网口转换器(TYPE A USB3.0 TO RJ45)

    硕盟SM-A44是一款USB3.0转RJ45千兆网口转换器.,转换USB端口到以太网端口.它让你投入低成本就可以轻松拥有千兆以太网.可将网络连接到台式机,笔记本电脑等等设备.硕盟 USB千兆网卡采用嵌 ...

  6. 硕盟USB3.0 转RJ45千兆网卡 TYPE A USB3.0 TO RJ45

    硕盟SM-A44是一款USB3.0转RJ45千兆网口转换器.这是一种高性能和低开销的解决方案.转换USB端口到10 / 100/ 1000M以太网端口可以让您的笔记本,台式机电脑能够通过USB接口连接 ...

  7. AC6102开发板USB3.0测试和使用说明

    AC6102开发板USB3.0测试和使用说明 概述 AC6102上集成了一颗Cypress 推出的高性能USB3.0传输芯片CYUSB3014,Cypress称之为EZ-USBFX3.该芯片性能强劲, ...

  8. 关于在win7内集成usb3.0驱动。

    mac air 装了win7但是折腾良久还是无法升级,只能是重新安装. 很蛋疼.bootcamp 老是找不到驱动.只能是手动分区后U盘引导安装. 驱动的下载,直接在Os x 下用bootcamp 下载 ...

  9. VirtualBox虚拟机中启用usb3.0却无法显示u盘的解决方法

    主机系统为win7 64位,由于工作需要,安装了Virtualbox 5.18虚拟机,virtaulbox中安装了win7 32系统.以为下启用usb 3.0的步骤: 1.宿主机要支持 usb 3.0 ...

  10. USB3.0及NVME SSD安装WIN7X64

    USB3.0及NVME SSD安装WIN7X64https://tieba.baidu.com/p/4822034273?pn=1所有的人都是菜鸟过来的,不过有些人懂得自己动手找到答案:有些人则是懒得 ...

随机推荐

  1. HTTP常见状态码详细解析

    HTTP状态码(英语:HTTP Status Code)是用以表示网页服务器 超文本传输协议响应状态的3位数字代码. 它由 RFC 2616 规范定义的,并得到 RFC 2518.RFC 2817.R ...

  2. 挑战Java面试题复习第1天,坚持就是胜利

    面向对象和面向过程的区别面向过程: 步骤分析:将问题分解为一系列步骤.函数实现:用函数逐步实现这些步骤.调用执行:在需要时调用这些函数.高性能:适合对性能要求高的场合,如单片机和嵌入式开发.面向对象: ...

  3. C++之OpenCV入门到提高002:加载、修改、保存图像

    一.介绍 今天是这个系列<C++之 Opencv 入门到提高>得第二篇文章.今天这个篇文章很简单,只是简单介绍如何使用 Opencv 加载图像.显示图像.修改图像和保存图像,先给大家一个最 ...

  4. 登陆mysql,Can 't connect to local MySQL server through socket '/tmp/mysql.sock '(2) "

    今天ssh到slave机器上,登陆mysql,遇到下图的报错. 查了一圈,最终解决办法简洁的出乎意料. 首先,要查看mysql服务是否已经启动(真的太容易漏掉) 第2步,你可能会自然而然的以为密码也是 ...

  5. mysql隐蔽的索引规则导致数据全表扫描

    索引是为了加速数据的检索,但是不合理的表结构或适应不当则会起到反作用.我们在项目中就遇到过类似的问题,两个十万级别的数据表,在做连接查询的时候,查询时间达到了7000多秒还没有查出结果. 首先说明,关 ...

  6. 支持国产3A游戏大作 ——《黑神话:悟空》

  7. 低功耗4G模组:LCD应用示例

    ​ 今天我们学习合宙Air780E开发板LCD应用示例,文末[阅读原文]获取最新资料. 本文档适用于Air780E开发板 关联文档和使用工具 lcd-demo: https://gitee.com/o ...

  8. golang读取文件

    golang 按行读取文件 file, err := os.Open("app-2019-06-01.log") if err != nil { log.Fatal(err) } ...

  9. Spring源码学习 ------ IoC——AOP

    一直想抽空把Spring源码拿来读读,但真正去做这件事的时候发现不简单,Spring发展这么多年,它的规模已不是一个一般的开源框架所能比的,它的主要架构和流程不是非常清晰,很难抓到要害,但有一点可以肯 ...

  10. YOLOv8-PyQT5可视化界面

    使用PyQT5实现YOLOv8图形化界面 准备工作: 1.首先在YOLOv8环境中安装pyqt5 pip install pyqt5 pip install pyqt5-tools 然后再你的anac ...