diff options
author | jc_gargma <jc_gargma@iserlohn-fortress.net> | 2020-04-05 23:07:13 -0700 |
---|---|---|
committer | jc_gargma <jc_gargma@iserlohn-fortress.net> | 2020-04-05 23:07:13 -0700 |
commit | ffc47b07d1ab6437d4fc0bf69e3425a95f6622a7 (patch) | |
tree | 7dcc613471fb804bcf5e52c59d93cdfb8e0c91e6 /0008-board-rockpi4-dts-upper-port-host.patch | |
parent | Updated to 5.5 (diff) | |
download | linux-pinebookpro-ffc47b07d1ab6437d4fc0bf69e3425a95f6622a7.tar.xz |
Diffstat (limited to '0008-board-rockpi4-dts-upper-port-host.patch')
-rw-r--r-- | 0008-board-rockpi4-dts-upper-port-host.patch | 463 |
1 files changed, 463 insertions, 0 deletions
diff --git a/0008-board-rockpi4-dts-upper-port-host.patch b/0008-board-rockpi4-dts-upper-port-host.patch new file mode 100644 index 0000000..f6aa3e7 --- /dev/null +++ b/0008-board-rockpi4-dts-upper-port-host.patch @@ -0,0 +1,463 @@ +diff --git a/arch/arm64/boot/dts/rockchip/rk3399-rock-pi-4.dts b/arch/arm64/boot/dts/rockchip/rk3399-rock-pi-4.dts +index d02d053..ed2e44d 100644 +--- a/arch/arm64/boot/dts/rockchip/rk3399-rock-pi-4.dts ++++ b/arch/arm64/boot/dts/rockchip/rk3399-rock-pi-4.dts +@@ -93,7 +93,7 @@ + pinctrl-names = "default"; + pinctrl-0 = <&vcc5v0_typec_en>; + regulator-name = "vcc5v0_typec"; +- regulator-always-on; ++ // regulator-always-on; + vin-supply = <&vcc5v0_sys>; + }; + +@@ -631,6 +631,7 @@ + status = "okay"; + + u2phy0_otg: otg-port { ++ vbus-supply = <&vcc5v0_typec>; + status = "okay"; + }; + +@@ -696,6 +697,7 @@ + + &usbdrd_dwc3_0 { + status = "okay"; ++ extcon = <&u2phy0>; + dr_mode = "otg"; + }; + + +diff --git a/drivers/phy/rockchip/phy-rockchip-inno-usb2.c b/drivers/phy/rockchip/phy-rockchip-inno-usb2.c +index eae865f..20d79232 100644 +--- a/drivers/phy/rockchip/phy-rockchip-inno-usb2.c ++++ b/drivers/phy/rockchip/phy-rockchip-inno-usb2.c +@@ -69,6 +69,7 @@ enum usb_chg_state { + static const unsigned int rockchip_usb2phy_extcon_cable[] = { + EXTCON_USB, + EXTCON_USB_HOST, ++ EXTCON_USB_VBUS_EN, + EXTCON_CHG_USB_SDP, + EXTCON_CHG_USB_CDP, + EXTCON_CHG_USB_DCP, +@@ -129,13 +130,29 @@ struct rockchip_usb2phy_port_cfg { + struct usb2phy_reg bvalid_det_en; + struct usb2phy_reg bvalid_det_st; + struct usb2phy_reg bvalid_det_clr; ++ struct usb2phy_reg bypass_dm_en; ++ struct usb2phy_reg bypass_sel; ++ struct usb2phy_reg bypass_iomux; ++ struct usb2phy_reg bypass_bc; ++ struct usb2phy_reg bypass_otg; ++ struct usb2phy_reg bypass_host; + struct usb2phy_reg ls_det_en; + struct usb2phy_reg ls_det_st; + struct usb2phy_reg ls_det_clr; ++ struct usb2phy_reg iddig_output; ++ struct usb2phy_reg iddig_en; ++ struct usb2phy_reg idfall_det_en; ++ struct usb2phy_reg idfall_det_st; ++ struct usb2phy_reg idfall_det_clr; ++ struct usb2phy_reg idrise_det_en; ++ struct usb2phy_reg idrise_det_st; ++ struct usb2phy_reg idrise_det_clr; + struct usb2phy_reg utmi_avalid; + struct usb2phy_reg utmi_bvalid; ++ struct usb2phy_reg utmi_iddig; + struct usb2phy_reg utmi_ls; + struct usb2phy_reg utmi_hstdet; ++ struct usb2phy_reg vbus_det_en; + }; + + +@@ -178,13 +195,16 @@ struct rockchip_usb2phy_port { + unsigned int port_id; + bool suspended; + bool vbus_attached; ++ bool vbus_enabled; + int bvalid_irq; + int ls_irq; + int otg_mux_irq; ++ int id_irq; + struct mutex mutex; + struct delayed_work chg_work; + struct delayed_work otg_sm_work; + struct delayed_work sm_work; ++ struct regulator *vbus; + const struct rockchip_usb2phy_port_cfg *port_cfg; + struct notifier_block event_nb; + enum usb_otg_state state; +@@ -214,6 +234,7 @@ struct rockchip_usb2phy { + struct clk *clk; + struct clk *clk480m; + struct clk_hw clk480m_hw; ++ bool edev_self; + enum usb_chg_state chg_state; + enum power_supply_type chg_type; + u8 dcd_retries; +@@ -393,6 +414,8 @@ static int rockchip_usb2phy_extcon_register(struct rockchip_usb2phy *rphy) + dev_err(rphy->dev, "failed to register extcon device\n"); + return ret; + } ++ ++ rphy->edev_self = true; + } + + rphy->edev = edev; +@@ -400,6 +423,28 @@ static int rockchip_usb2phy_extcon_register(struct rockchip_usb2phy *rphy) + return 0; + } + ++static int rockchip_set_vbus_power(struct rockchip_usb2phy_port *rport,bool en) ++{ ++ int ret = 0; ++ ++ if (!rport->vbus) ++ return 0; ++ ++ if (en && !rport->vbus_enabled) { ++ ret = regulator_enable(rport->vbus); ++ if (ret) ++ dev_err(&rport->phy->dev, ++ "Failed to enable VBUS supply\n"); ++ } else if (!en && rport->vbus_enabled) { ++ ret = regulator_disable(rport->vbus); ++ } ++ ++ if (ret == 0) ++ rport->vbus_enabled = en; ++ ++ return ret; ++} ++ + static int rockchip_usb2phy_init(struct phy *phy) + { + struct rockchip_usb2phy_port *rport = phy_get_drvdata(phy); +@@ -407,10 +452,11 @@ static int rockchip_usb2phy_init(struct phy *phy) + int ret = 0; + + mutex_lock(&rport->mutex); +- ++printk("busb rport->port_id=%d\n",rport->port_id ); + if (rport->port_id == USB2PHY_PORT_OTG) { + if (rport->mode != USB_DR_MODE_HOST && + rport->mode != USB_DR_MODE_UNKNOWN) { ++ printk("busb enabled irq\n"); + /* clear bvalid status and enable bvalid detect irq */ + ret = property_enable(rphy->grf, + &rport->port_cfg->bvalid_det_clr, +@@ -423,9 +469,34 @@ static int rockchip_usb2phy_init(struct phy *phy) + true); + if (ret) + goto out; ++ ++ /* clear id status and enable id detect irq */ ++ ret = property_enable(rphy->grf, ++ &rport->port_cfg->idfall_det_clr, ++ true); ++ if (ret) ++ goto out; ++ ++ ret = property_enable(rphy->grf, ++ &rport->port_cfg->idfall_det_en, ++ true); ++ if (ret) ++ goto out; ++ ++ ret = property_enable(rphy->grf, ++ &rport->port_cfg->idrise_det_clr, ++ true); ++ if (ret) ++ goto out; ++ ++ ret = property_enable(rphy->grf, ++ &rport->port_cfg->idrise_det_en, ++ true); ++ if (ret) ++ goto out; + + schedule_delayed_work(&rport->otg_sm_work, + OTG_SCHEDULE_DELAY * 3); + } else { + /* If OTG works in host only mode, do nothing. */ + dev_dbg(&rport->phy->dev, "mode %d\n", rport->mode); +@@ -458,7 +529,7 @@ static int rockchip_usb2phy_power_on(struct phy *phy) + int ret; + + dev_dbg(&rport->phy->dev, "port power on\n"); +- ++printk("busb port power on\n"); + if (!rport->suspended) + return 0; + +@@ -502,7 +573,7 @@ static int rockchip_usb2phy_power_off(struct phy *phy) + static int rockchip_usb2phy_exit(struct phy *phy) + { + struct rockchip_usb2phy_port *rport = phy_get_drvdata(phy); +- ++printk("busb rockchip_usb2phy_exit \n"); + if (rport->port_id == USB2PHY_PORT_OTG && + rport->mode != USB_DR_MODE_HOST && + rport->mode != USB_DR_MODE_UNKNOWN) { +@@ -514,11 +585,61 @@ static int rockchip_usb2phy_exit(struct phy *phy) + return 0; + } + ++static int rockchip_usb2phy_set_mode(struct phy *phy, enum phy_mode mode , int submode) ++{ ++ struct rockchip_usb2phy_port *rport = phy_get_drvdata(phy); ++ struct rockchip_usb2phy *rphy = dev_get_drvdata(phy->dev.parent); ++ bool vbus_det_en; ++ int ret = 0; ++ if (rport->port_id != USB2PHY_PORT_OTG) ++ return ret; ++ ++printk("busb rockchip_usb2phy_set_mode mode = %d,submode=%d\n",mode,submode); ++ switch (mode) { ++ case PHY_MODE_USB_OTG: ++ /* ++ * In case of using vbus to detect connect state by u2phy, ++ * enable vbus detect on otg mode. ++ * ++ * fallthrough ++ */ ++ case PHY_MODE_USB_DEVICE: ++ /* Disable VBUS supply */ ++ rockchip_set_vbus_power(rport, false); ++ extcon_set_state_sync(rphy->edev, EXTCON_USB_VBUS_EN, false); ++ vbus_det_en = true; ++ break; ++ case PHY_MODE_USB_HOST: ++ /* Enable VBUS supply */ ++ ret = rockchip_set_vbus_power(rport, true); ++ if (ret) { ++ dev_err(&rport->phy->dev, ++ "Failed to set host mode\n"); ++ return ret; ++ } ++ ++ extcon_set_state_sync(rphy->edev, EXTCON_USB_VBUS_EN, true); ++ /* fallthrough */ ++ case PHY_MODE_INVALID: ++ vbus_det_en = false; ++ break; ++ default: ++ dev_info(&rport->phy->dev, "illegal mode\n"); ++ printk("busb illegal mode\n"); ++ return ret; ++ } ++ ++ ret = property_enable(rphy->grf, &rport->port_cfg->vbus_det_en, vbus_det_en); ++ ++ return ret; ++} ++ + static const struct phy_ops rockchip_usb2phy_ops = { + .init = rockchip_usb2phy_init, + .exit = rockchip_usb2phy_exit, + .power_on = rockchip_usb2phy_power_on, + .power_off = rockchip_usb2phy_power_off, ++// .set_mode = rockchip_usb2phy_set_mode, + .owner = THIS_MODULE, + }; + +@@ -540,7 +661,7 @@ static void rockchip_usb2phy_otg_sm_work(struct work_struct *work) + delay = OTG_SCHEDULE_DELAY; + dev_dbg(&rport->phy->dev, "%s otg sm work\n", + usb_otg_state_string(rport->state)); +- ++ printk("busb rockchip_usb2phy_otg_sm_work %s otg sm work %d\n",usb_otg_state_string(rport->state),rport->state); + switch (rport->state) { + case OTG_STATE_UNDEFINED: + rport->state = OTG_STATE_B_IDLE; +@@ -548,13 +669,16 @@ static void rockchip_usb2phy_otg_sm_work(struct work_struct *work) + rockchip_usb2phy_power_off(rport->phy); + /* fall through */ + case OTG_STATE_B_IDLE: ++ printk("busb HOST = %d,VBUS_EN=%d,vbus_attached=%d\n",extcon_get_state(rphy->edev, EXTCON_USB_HOST),extcon_get_state(rphy->edev,EXTCON_USB_VBUS_EN),rport->vbus_attached); + if (extcon_get_state(rphy->edev, EXTCON_USB_HOST) > 0) { + dev_dbg(&rport->phy->dev, "usb otg host connect\n"); ++ printk("busb usb otg host connect\n"); + rport->state = OTG_STATE_A_HOST; + rockchip_usb2phy_power_on(rport->phy); + return; + } else if (vbus_attach) { + dev_dbg(&rport->phy->dev, "vbus_attach\n"); ++ printk("busb vbus_attach rphy->chg_state = %d\n",rphy->chg_state); + switch (rphy->chg_state) { + case USB_CHG_STATE_UNDEFINED: + schedule_delayed_work(&rport->chg_work, 0); +@@ -689,7 +813,7 @@ static void rockchip_chg_detect_work(struct work_struct *work) + struct regmap *base = get_reg_base(rphy); + bool is_dcd, tmout, vout; + unsigned long delay; +- ++printk("busb chg detection work state = %d\n",rphy->chg_state); + dev_dbg(&rport->phy->dev, "chg detection work state = %d\n", + rphy->chg_state); + switch (rphy->chg_state) { +@@ -923,6 +1047,42 @@ static irqreturn_t rockchip_usb2phy_bvalid_irq(int irq, void *data) + return IRQ_HANDLED; + } + ++static irqreturn_t rockchip_usb2phy_id_irq(int irq, void *data) ++{ ++ struct rockchip_usb2phy_port *rport = data; ++ struct rockchip_usb2phy *rphy = dev_get_drvdata(rport->phy->dev.parent); ++ bool cable_vbus_state = false; ++printk("brian rockchip_usb2phy_id_irq \n"); ++ if (!property_enabled(rphy->grf, &rport->port_cfg->idfall_det_st) && ++ !property_enabled(rphy->grf, &rport->port_cfg->idrise_det_st)) ++ return IRQ_NONE; ++ ++ mutex_lock(&rport->mutex); ++ ++ /* clear id fall or rise detect irq pending status */ ++ if (property_enabled(rphy->grf, &rport->port_cfg->idfall_det_st)) { ++ property_enable(rphy->grf, &rport->port_cfg->idfall_det_clr, ++ true); ++ cable_vbus_state = true; ++ } else if (property_enabled(rphy->grf, &rport->port_cfg->idrise_det_st)) { ++ property_enable(rphy->grf, &rport->port_cfg->idrise_det_clr, ++ true); ++ cable_vbus_state = false; ++ } ++ ++ extcon_set_state(rphy->edev, EXTCON_USB_HOST, cable_vbus_state); ++ extcon_set_state(rphy->edev, EXTCON_USB_VBUS_EN, cable_vbus_state); ++ ++ extcon_sync(rphy->edev, EXTCON_USB_HOST); ++ extcon_sync(rphy->edev, EXTCON_USB_VBUS_EN); ++ ++ rockchip_set_vbus_power(rport, cable_vbus_state); ++ ++ mutex_unlock(&rport->mutex); ++ ++ return IRQ_HANDLED; ++} ++ + static irqreturn_t rockchip_usb2phy_otg_mux_irq(int irq, void *data) + { + struct rockchip_usb2phy_port *rport = data; +@@ -980,7 +1140,8 @@ static int rockchip_usb2phy_otg_port_init(struct rockchip_usb2phy *rphy, + struct rockchip_usb2phy_port *rport, + struct device_node *child_np) + { +- int ret; ++ int ret = 0; ++ int iddig; + + rport->port_id = USB2PHY_PORT_OTG; + rport->port_cfg = &rphy->phy_cfg->port_cfgs[USB2PHY_PORT_OTG]; +@@ -994,13 +1155,34 @@ static int rockchip_usb2phy_otg_port_init(struct rockchip_usb2phy *rphy, + */ + rport->suspended = true; + rport->vbus_attached = false; ++ rport->vbus_enabled = false; + ++ rport->vbus = devm_regulator_get_optional(&rport->phy->dev, "vbus"); ++ if (IS_ERR(rport->vbus)) { ++ ret = PTR_ERR(rport->vbus); ++ if (ret == -EPROBE_DEFER) ++ return ret; ++ printk("busb Failed to get VBUS supply regulator\n"); ++ dev_warn(&rport->phy->dev, "Failed to get VBUS supply regulator\n"); ++ rport->vbus = NULL; ++ } ++ if(rport->vbus != NULL) ++ printk("busb get rport->vbus ok\n"); + mutex_init(&rport->mutex); + + rport->mode = of_usb_get_dr_mode_by_phy(child_np, -1); + if (rport->mode == USB_DR_MODE_HOST || + rport->mode == USB_DR_MODE_UNKNOWN) { +- ret = 0; ++ if(rphy->edev_self) { ++ extcon_set_state(rphy->edev, EXTCON_USB, false); ++ extcon_set_state(rphy->edev, EXTCON_USB_HOST, true); ++ extcon_set_state(rphy->edev, EXTCON_USB_VBUS_EN, true); ++ ret = rockchip_set_vbus_power(rport, true); ++ printk("busb rockchip_set_vbus_power ret=%d\n",ret); ++ if(ret) ++ return ret; ++ } ++ //ret = 0; + goto out; + } + +@@ -1044,6 +1226,37 @@ static int rockchip_usb2phy_otg_port_init(struct rockchip_usb2phy *rphy, + "failed to request otg-bvalid irq handle\n"); + goto out; + } ++ ++ if (rphy->edev_self) { ++ ++ rport->id_irq = of_irq_get_byname(child_np, "otg-id"); ++ if (rport->id_irq < 0) { ++ dev_err(rphy->dev, "no otg id irq provided\n"); ++ ret = rport->id_irq; ++ goto out; ++ } ++ ++ ret = devm_request_threaded_irq(rphy->dev, rport->id_irq, NULL, ++ rockchip_usb2phy_id_irq, ++ IRQF_ONESHOT, ++ "rockchip_usb2phy_id", rport); ++ if (ret) { ++ dev_err(rphy->dev, "failed to request otg-id irq handle\n"); ++ return ret; ++ } ++ ++ iddig = property_enabled(rphy->grf, &rport->port_cfg->utmi_iddig); ++ if(!iddig) { ++ extcon_set_state(rphy->edev, EXTCON_USB, false); ++ extcon_set_state(rphy->edev, EXTCON_USB_HOST, true); ++ extcon_set_state(rphy->edev, EXTCON_USB_VBUS_EN, true); ++ ++ ret = rockchip_set_vbus_power(rport, true); ++ printk("busb rockchip_set_vbus_power ret=%d\n",ret); ++ if (ret) ++ return ret; ++ } ++ } + } + + if (!IS_ERR(rphy->edev)) { +@@ -1108,6 +1321,7 @@ static int rockchip_usb2phy_probe(struct platform_device *pdev) + phy_cfgs = match->data; + rphy->chg_state = USB_CHG_STATE_UNDEFINED; + rphy->chg_type = POWER_SUPPLY_TYPE_UNKNOWN; ++ rphy->edev_self = false; + platform_set_drvdata(pdev, rphy); + + ret = rockchip_usb2phy_extcon_register(rphy); +@@ -1329,6 +1543,17 @@ static const struct rockchip_usb2phy_cfg rk3399_phy_cfgs[] = { + .bvalid_det_en = { 0xe3c0, 3, 3, 0, 1 }, + .bvalid_det_st = { 0xe3e0, 3, 3, 0, 1 }, + .bvalid_det_clr = { 0xe3d0, 3, 3, 0, 1 }, ++ .bypass_dm_en = { 0xe450, 2, 2, 0, 1 }, ++ .bypass_sel = { 0xe450, 3, 3, 0, 1 }, ++ .idfall_det_en = { 0xe3c0, 5, 5, 0, 1 }, ++ .idfall_det_st = { 0xe3e0, 5, 5, 0, 1 }, ++ .idfall_det_clr = { 0xe3d0, 5, 5, 0, 1 }, ++ .idrise_det_en = { 0xe3c0, 4, 4, 0, 1 }, ++ .idrise_det_st = { 0xe3e0, 4, 4, 0, 1 }, ++ .idrise_det_clr = { 0xe3d0, 4, 4, 0, 1 }, ++ .ls_det_en = { 0xe3c0, 2, 2, 0, 1 }, ++ .ls_det_st = { 0xe3e0, 2, 2, 0, 1 }, ++ .ls_det_clr = { 0xe3d0, 2, 2, 0, 1 }, + .utmi_avalid = { 0xe2ac, 7, 7, 0, 1 }, + .utmi_bvalid = { 0xe2ac, 12, 12, 0, 1 }, + }, +diff --git a/include/linux/extcon.h b/include/linux/extcon.h +index 2bdf643..1c8e971 100644 +--- a/include/linux/extcon.h ++++ b/include/linux/extcon.h +@@ -37,6 +37,7 @@ + /* USB external connector */ + #define EXTCON_USB 1 + #define EXTCON_USB_HOST 2 ++#define EXTCON_USB_VBUS_EN 3 + + /* + * Charging external connector |