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控制
设备树配置:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 | &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权限
1 2 3 4 5 6 7 8 9 10 11 12 | 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寄存器的写入保护
1 2 3 4 5 6 7 8 9 10 | 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检测
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 | 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检测
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 | 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控制
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 | 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" ); |
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· AI技术革命,工作效率10个最佳AI工具